@haetae/core
@haetae/core
provides every core feature for Haetae.
For instance, it handles the config file, your command's env
and run
, etc.
If you want to use Haetae by programmatic API, you probably need this package.
Dependents
Installation
Unlike other @haetae/*
packages, @haetae/core
doesn't have peerDependencies
.
Just purely installing @haetae/core
itself is enough.
Are you developing a library(e.g. plugin) for Haetae?
It might be more suitable to specify @haetae/core
as peerDependencies
than dependencies
.
# As dependencies
npm install @haetae/core
# As devDependencies
npm install --save-dev @haetae/core
API
pkg
Refer to introduction#pkg.
SetCurrentCommandOptions
An argument interface of the function setCurrentCommand
.
interface SetCurrentCommandOptions {
command: string
}
setCurrentCommand
A setter for the current command name, which is a module-level state.
Set it before calling other APIs that require it (as a default parameter).
Type
(options: SetCurrentCommandOptions) => void
Options?
command
: A name of the command to run for current execution.
getCurrentCommand
A getter for the current command name, which is a module-level state.
Type
() => string
defaultConfigFiles
An array of string constants for default config file name.
This is used when the config file path is not given or given as a directory.
Type
[
'haetae.config.js',
'haetae.config.mjs',
'haetae.config.ts',
'haetae.config.mts',
]
SetConfigFilenameOptions
An argument interface of the function setConfigFilename
.
interface SetConfigFilenameOptions {
filename?: string
cwd?: string
checkExistence?: boolean
}
setConfigFilename
A setter for the config file name, which is a module-level state.
Set it before calling other APIs that require a config file.
Type
(options?: SetConfigFilenameOptions) => Promise<void>
Options?
filename?
: A config file path.cwd?
: A directory to join or start the search from. (default:process.cwd()
(opens in a new tab))checkExistence?
: Whether to check iffilename
exists. No effect whenfilename
is not given. (default:true
)
When filename
is given
filename
can be either an absolute or relative path.
If relative, filename
will be joined with cwd
.
If filename
does not exist on the filesystem, it throws an error when checkExistence
is true
.
When filename
is not given
It will try finding the config file (one of defaultConfigFiles
)
by walking up parent directories recursively, starting from cwd
.
- If not found, it throws an error.
- If multiple files (of
defaultConfigFiles
) exist,- A file closer to
cwd
is chosen. - If distances from
cwd
are equal, the priority order is the same asdefaultConfigFiles
.
- A file closer to
getConfigFilename
Path Principles
A getter for the config file name, which is a module-level state.
Type
() => string
getConfigDirname
Path Principles
A getter for the config file's directory name, which is a derived module-level state.
Throws an error if the config file is not yet set.
Type
() => string
HaetaeRecord
interface HaetaeRecord<D extends Rec = Rec, E extends Rec = Rec> {
data: D
env: E
envHash: string
time: number
}
CommandEnvOptions
interface CommandEnvOptions<S extends StoreConnector> {
store: S
}
CommandEnv
<E extends Rec, S extends StoreConnector> = (
options: CommandEnvOptions<S>,
) => void | PromiseOr<E>
PreCommandEnv
type PreCommandEnv<E extends Rec, S extends StoreConnector> =
| CommandEnv<E, S>
| PromiseOr<E | void>
CommandRun
interface CommandRunOptions<
E extends Rec,
S extends StoreConnector,
> {
env: E
store: S
}
CommandRun
type CommandRun<
D extends Rec,
E extends Rec,
S extends StoreConnector,
> = (options: CommandRunOptions<E, S>) => void | PromiseOr<D | void>
PreCommand
interface PreCommand<
D extends Rec,
E extends Rec,
S extends StoreConnector,
> {
run: CommandRun<D, E, S>
env?: PreCommandEnv<E, S>
}
Command
interface Command<
D extends Rec,
E extends Rec,
S extends StoreConnector,
> {
run: CommandRun<D, E, S>
env: CommandEnv<E, S>
}
RootEnv
type RootEnv<
A extends Rec,
S extends StoreConnector,
R extends Rec = A,
> = (envFromCommand: A, options: CommandEnvOptions<S>) => PromiseOr<R>
RootRecordData
type RootRecordData<
A extends Rec,
E extends Rec,
S extends StoreConnector,
R extends Rec = A,
> = (
recordDataFromCommand: A,
options: CommandRunOptions<E, S>,
) => PromiseOr<R>
PreConfig
An interface of user-given config schema.
Also an argument interface of the function configure
.
interface PreConfig<S extends StoreConnector> {
commands: Record<string, PreCommand<Rec, Rec, S>>
env?: RootEnv<Rec, S>
recordData?: RootRecordData<Rec, Rec, S>
store?: S
}
Config
An interface of normalized config schema.
Also a return type of function configure
.
interface Config<
D extends Rec, // Record Data
E extends Rec, // Env
S extends StoreConnector = StoreConnector,
RD extends Rec = D, // Root Record Data
RE extends Rec = E, // Root Env
> {
commands: {
[key: string]: Command<D, E, S>
}
env: RootEnv<E, S, RE>
recordData: RootRecordData<D, RE, S, RD>
store: S
}
configure
Path Principles
configure
validates and transform the user-provided config(e.g. haetae.config.js
) into normalized config.
Idempotent function
configure(obj)
is eqaul to configure(configure(obj))
.
Type
< D extends Rec,
E extends Rec,
S extends StoreConnector = LocalFileStoreConnector,
>(options: PreConfig<S>) => Config<D, E, S>
Options
commands
: Your commands as an object.env?
: An env-to-env transformer. (default:(arg) => arg
)recordData?
: A recordData-to-recordData transformer. (default:(arg) => arg
)store?
: A store connector. (default:localFileStore()
)
Type-check for your config
The below example is 100% valid.
The exported raw json will be processed by configure
internally.
But you'd not get a type-check from the IDE.
export default { /* ... */ }
With configure
, type-check is enabled. Your IDE is Happy! 😊
import { core } from 'haetae'
export default core.configure({ /* ... */ })
Normalization
Schema of Config
(return type) is roughly similar to
that of PreConfig
(argument type).
The return value is a normalized result of a user-given (argument) config.
Omitted options from a user-given config PreConfig
are to be set
as their default values in Config
.
GetConfigOptions
An argument interface of the function getConfig
.
interface GetConfigOptions {
filename?: string
}
getConfig
Memoized
A function to get config object by config file path.
Type
< D extends Rec,
E extends Rec,
S extends StoreConnector = StoreConnector,
>(options: GetConfigOptions) => Promise<Config<D, E, S>>
Options?
filename?
: A path to the config file. If given as a relative path,process.cwd()
(opens in a new tab) is joined in front of it. If given as an absolute path, it's used as-is. (default:getConfigFilename()
)
reservedRecordDataList
A list of Reserved Record Data.
The latter is added more recently, as when reserveRecordData
is called,
it pushes to reservedRecordDataList
.
Type
Rec[]
reserveRecordData
A function to reserve Record Data.
This pushes the Record Data into reservedRecordDataList
.
Type
<D extends Rec>(recordData: Rec) => void
InvokeEnvOptions
An argument interface of the function invokeEnv
.
interface InvokeEnvOptions<E extends Rec> {
command?: string
config?: Config<Rec, E>
}
invokeEnv
A function to invoke(execute) user-defined env
of the given command
.
Type
<E extends Rec>(options?: InvokeEnvOptions<Rec, E>) => Promise<E>
Options?
command?
: A command name to invokeenv
of. (default:getCurrentCommand()
)config?
: A config object. (default:await getConfig()
InvokeRootEnvOptions
An argument interface of the function invokeRootEnv
.
interface InvokeRootEnvOptions<A extends Rec, R extends Rec> {
env?: A
config?: Config<Rec, R>
}
invokeRootEnv
A function to invoke(execute) user-defined env
of the given command
.
Type
<A extends Rec, R extends Rec>(options?: InvokeRootEnvOptions<A, R>): Promise<R>
Options?
env?
: Aenv
object returned from a command. It receives the object and returns a transformed object. (default:getCurrentCommand()
)config?
: A config object. (default:await getConfig()
InvokeRunOptions
An argument interface of the function invokeRun
.
interface InvokeRunOptions<D extends Rec> {
command?: string
env?: Rec // env before RootEnv
config?: Config<D, Rec>
reservedRecordData?: boolean
}
invokeRun
A function to invoke (execute) user-defined run
of the given command
.
Type
<D extends Rec>(options?: CommandFromConfig<D, Rec>) => Promise<D>
Options?
command?
: A command name to invokerun
of. (default:getCurrentCommand()
)config?
: A config object. (default:await getConfig()
env?
: Aenv
object to pass torun
. (default:await invokeEnv()
reservedRecordData?
: Whether to apply reserved Record Data. (default:true
)
InvokeRootRecordDataOptions
An argument interface of the function invokeRootRecordData
.
interface InvokeRunOptions<A extends Rec, R extends Rec> {
env: Rec
recordData: A
config?: Config<R, Rec>
}
invokeRootRecordData
A function to invoke (execute) user-defined Root Record Data recordData
.
Type
<A extends Rec, R extends Rec>(options: InvokeRootRecordDataOptions<A, R>): Promise<R>
Options?
env
: Aenv
object to pass torecordData
. (default:await invokeRootEnv()
recordData
: A Record Data object to pass torecordData
. (default:await invokeEnv()
config?
: A config object. (default:await getConfig()
hashEnv
A function to calculate a deterministic cryptographic hash of an env
object.
Type
(env: Rec) => string
Argument
env?
: Anenv
object*.
CreateRecordOptions
An argument interface of the function createRecord
.
interface CreateRecordOptions<D extends Rec, E extends Rec> {
config?: Config<D, E>
}
createRecord
A function to create a new record object.
This only returns an object, not saves it.
Type
<D extends Rec, E extends Rec>(options?: CreateRecordOptions<D, E>) => Promise<HaetaeRecord<D, E>>
LocalFileStore
An interface for the local store file.
interface LocalFileStore<D extends Rec = Rec, E extends Rec = Rec> {
version: string
commands: {
[command: string]: HaetaeRecord<D, E>[]
}
}
StoreConnector
An interface of Store Connector.
interface StoreConnector {
addRecord: AddRecord
getRecord: GetRecord
}
AddRecordOptions
An argument interface of the function StoreConnector.addRecord
.
interface AddRecordOptions<D extends Rec, E extends Rec> {
command?: string
record: HaetaeRecord
}
AddRecord
A type of function StoreConnector.addRecord
.
(options: AddRecordOptions) => PromiseOr<void>
StoreConnector.addRecord
A function to add a new record to the store.
The record is to be persisted to the store.
Type
AddRecord
Options
record
: A new record object to add.command?
: A command name to add a new record. (default:getCurrentCommand()
)
GetRecordOptions
An argument interface of a function StoreConnector.getRecord
.
interface GetRecordOptions {
command?: string
envHash?: string
}
GetRecord
A type of function getRecord
.
<D extends Rec = Rec, E extends Rec = Rec>(
options?: GetRecordOptions,
) => PromiseOr<HaetaeRecord<D, E> | undefined>
StoreConnector.getRecord
A function to get a record of a given command, corresponding to the given env.
undefined
is returned when there's no record.
Type
GetRecord
Options?
command?
: A command name to get records of. (default:getCurrentCommand()
)envHash?
: A hash ofenv
object. Used to compare with previous Records and to get the matching result. (default:hashEnv(await invokeEnv({ command }))
)
LoadStoreOptions
An interface of function StoreConnector.loadStore
.
interface LoadStoreOptions {
initWhenNotFound?: boolean
}
LocalFileStoreConnector
An interface of local Store Connector.
interface LocalFileStoreConnector extends StoreConnector {
initNewStore<D extends Rec, E extends Rec>(): LocalFileStore<D, E>
loadStore<D extends Rec, E extends Rec>
(options?: LoadStoreOptions): Promise<LocalFileStore<D, E>>
saveStore(store: LocalFileStore): Promise<void>
localFileStore: {
filename: string
recordRemoval: {
age: number
count: number
}
}
}
LocalFileStoreOptions
An argument interface of a function localFileStore
.
interface LocalFileStoreOptions {
filename?: string
recordRemoval?: {
age?: number | string
count?: number
leaveOnlyLastestPerEnv?: boolean
}
}
localFileStore
A function to create a Store Connector that reads and writes to a local file.
Type
(options?: LocalFileStoreOptions): LocalFileStoreConnector
Options?
filename?
: The store file. (default:core.getConfigDirname() + '/.haetae/store.json'
recordRemoval.age?
: Age threshold by milliseconds (e.g.90 * 24 * 60 * 60 * 1000
=> 90 days). vercel/ms (opens in a new tab)-compatible string is allowed (e.g.'90 days'
=> 90 days). Records whose age is older than this value are to be removed when callingaddRecord
. (default:Number.POSITIVE_INFINITY
)recordRemoval.count?
: The number of total records to keep. When the number of records becomes larger than this value, old records are removed to satisfy the threshold when callingaddRecord
. This task is executed afterrecordRemoval.age
is used. (default:Number.POSITIVE_INFINITY
)recordRemoval.leaveOnlyLastestPerEnv?
: Iftrue
, only the lastet records perenv
exist in the store file. This is useful if you only depend on the latest record perenv
. (default:true
)
LocalFileStoreConnector.initNewStore
Initializes an empty store. It just returns an object. It does not save it as a file.
Type
LocalFileStoreConnector.initNewStore
LoadStoreOptions
An argument interface of the function LocalFileStoreConnector.loadStore
.
interface LoadStoreOptions {
initWhenNotFound?: boolean
}
LocalFileStoreConnector.loadStore
Memoized
A function to load a store object from the file.
Type
LocalFileStoreConnector.loadStore
Options?
initWhenNotFound?
: Whether to throw an error or just initialize a new store object whenfilename
does not exist in the filesystem. Iftrue
,LocalFileStoreConnector.initNewStore()
is returned, and the filesystem is not affected. (default:true
)
LocalFileStoreConnector.saveStore
A function to save a store object to a file.
Memoization cache of LocalFileStoreConnector.loadStore
would be clear automatically.
Type
LocalFileStoreConnector.saveStore
Options?
store?
: A store object to save. (default:await addRecord()
)