@haetae/core
@haetae/core
provides every core feature for Haetae.
For instance, it handles config file, store file, and your command's env
and run
.
If you want to use Haetae by programatic 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 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 command to run for current execution.
getCurrentCommand
A getter for current command name, which is a module-level state.
Type
() => string
defaultConfigFiles
An array of string constant for default config file name.
This is used when 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 config file name, which is a module-level state.
Set it before calling other APIs that requires a config file.
Type
(options?: SetConfigFilenameOptions) => void
Options?
filename?
: A config file path.cwd?
: A directory to join or start 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 same, priority order is same asdefaultConfigFiles
.
- A file closer to
getConfigFilename
Path Principles
A getter for config file name, which is a module-level state.
Type
() => string
getConfigDirname
Path Principles
A getter for 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
defaultStoreFile
A string constant for default store file name.
This is used when store file is not given, or given as a directory.
Type
'.haetae/store.json'
SetStoreFilenameOptions
An argument interface of the function setStoreFilename
.
interface SetStoreFilenameOptions {
filename: string
rootDir?: string
}
setStoreFilename
A setter for store file name, which is a module-level state.
Set the store filename by this setter function, before calling other APIs that require store filename.
Type
(options: SetStoreFilenameOptions) => void
Options
filename
: A store file path. If it does not end with'.json'
,'store.json'
is appended internally. (e.g.'/path/to'
becomes'/path/to/store.json'
)rootDir?
: A directory to join withfilename
whenfilename
is a relative path. (default:getConfigDirname()
)
getStoreFilename
A getter for store file name, which is a module-level state.
Type
() => string
HaetaeRecord
interface HaetaeRecord<D extends Rec = Rec, E extends Rec = Rec> {
data: D
env: E
time: number
}
HaetaeStore
interface HaetaeStore<D extends Rec = Rec, E extends Rec = Rec> {
version: string
commands: {
[command: string]: HaetaeRecord<D, E>[]
}
}
HaetaeCommandEnv
<E extends Rec>() => void | PromiseOr<E>
HaetaePreCommandEnv
type HaetaePreCommandEnv<E extends Rec> =
| HaetaeCommandEnv<E>
| PromiseOr<E | void>
HaetaeCommandRun
<D extends Rec>() => void | PromiseOr<D | void>
HaetaePreCommand
interface HaetaePreCommand<D extends Rec, E extends Rec> {
run: HaetaeCommandRun<D>
env?: HaetaePreCommandEnv<E>
}
HaetaeCommand
interface HaetaeCommand<D extends Rec, E extends Rec> {
run: HaetaeCommandRun<D>
env: HaetaeCommandEnv<E>
}
RootEnv
<E extends Rec>(envFromCommand: E) => PromiseOr<E>
RootRecordData
<A extends Rec, R extends Rec = A>(recordDataFromCommand: A) => PromiseOr<R>
HaetaePreConfig
An interface of user-given config schema.
Also an argument interface of the function configure
.
export interface HaetaePreConfig {
commands: {
[command: string]: HaetaePreCommand<Rec, Rec>
}
env?: RootEnv<Rec>
recordData?: RootRecordData<Rec>
recordRemoval?: {
age?: string | number
count?: number
}
storeFile?: string
}
HaetaeConfig
An interface of normalized config schema.
Also a return type of function configure
.
interface HaetaeConfig<D extends Rec, E extends Rec> {
commands: {
[command: string]: HaetaeCommand<D, E>
}
env: RootEnv<E>
recordData: RootRecordData<D>
recordRemoval: {
age: number
count: number
}
storeFile: string
}
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))
.
(The only exception is when setStoreFilename
is called with different arguments
between each call of configure
, which is unlikey to happen in real world scenario.)
Type
<D extends Rec, E extends Rec>(options: HaetaePreConfig) => HaetaeConfig<D, E>
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
)recordRemoval.age?
: Age threshold by milliseconds. Records whose age are 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 after that ofrecordRemoval.age
. (default:Number.POSITIVE_INFINITY
)storeFile?
: A store file path. Internally, it is used tosetStoreFilename({ filename: storeFile })
only ifsetStoreFilename
is never called before. IfsetStoreFilename
is called before callingconfigure
, the optionstoreFile
does not have any effect, even to the resultHaetaeConfig
object. (default:defaultStoreFile
)
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 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 HaetaeConfig
(return type) is roughly similar to that of HaetaePreConfig
(argument type).
The return value is a normalized result of user-given (argument) config.
Omitted options from user-given config(HaetaePreConfig
) are to be set as their default values in HaetaeConfig
.
Given value of storeFile
is replaced by a return value of getStoreFilename()
.
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>(options?: GetConfigOptions)
=> Promise<HaetaeConfig<D, E>>
Options?
filename?
: A path to 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()
)
initNewStore
Initializes an empty store. It just returns an object. It does not save it as a file.
Type
<D extends Rec, E extends Rec>() => HaetaeStore<D, E>
GetStoreOptions
An argument interface of the function getStore
.
interface GetStoreOptions {
filename?: string
initWhenNotFound?: boolean
}
getStore
Memoized
Type
<D extends Rec, E extends Rec>(options?: GetStoreOptions<D, E>)
=> Promise<HaetaeStore<D, E>>
A function to get store object.
Options?
filename?
: A path to store file (e.g.'/path/to/.haetae/store.json'
). (default:getStoreFilename()
)initWhenNotFound?
: Whether to throw an error or just initialize new store object whenfilename
does not exist in filesystem. Iftrue
,initNewStore()
is returned, and filesystem is not affected. (default:true
)
GetRecordsOptions
An argument interface of the function getRecords
.
There're GetRecordsOptions
(plural) and GetRecordOptions
(singular). Don't confuse!
interface GetRecordsOptions<D extends Rec, E extends Rec> {
command?: string
store?: HaetaeStore<D, E>
}
getRecords
A function to get records of a given command from given store.
undefined
is returned when there is no record.
There're getRecords
(plural) and getRecord
(singular). Don't confuse!
Type
<D extends Rec = Rec, E extends Rec = Rec>(options?: GetRecordsOptions<D, E>)
=> Promise<HaetaeRecord<D, E>[] | undefined>
Options?
command?
: A command name to get records of. (default:getCurrentCommand()
)store?
: A store object. (default:getStore()
)
ReserveRecordDataOptions
An option interface of the function reserveRecordData
.
interface ReserveRecordDataOptions {
dryRun?: boolean
}
reserveRecordData
A function to reserve Record Data.
This changes module-level state, the Reserved Record Data.
It returns a result of the Reserved Record Data.
Type
<D extends Rec>(recordData: Rec, options?: ReserveRecordDataOptions) => D
Options?
dryRun?
: Iftrue
, the argrecordData
is not reserved, but a return value is given as if it's applied. (default:false
)
InvokeEnvOptions
An argument interface of the function invokeEnv
.
interface InvokeEnvOptions<E extends Rec> {
command?: string
config?: HaetaeConfig<Rec, E>
applyRootEnv?: boolean
}
invokeEnv
Memoized
A function to invoke(execute) user-defined env
of the given command
.
Type
<E extends Rec>(options?: CommandFromConfig<Rec, E>) => Promise<E>
Options?
command?
: A command name to invokeenv
of. (default:getCurrentCommand()
)config?
: A config object. (default:getConfig()
)applyRootEnv?
: Whether to apply root env. (default:true
)
InvokeRunOptions
An argument interface of the function invokeRun
.
interface InvokeRunOptions<D extends Rec> {
command?: string
config?: HaetaeConfig<D, Rec>
applyReservedRecordData?: boolean
applyRootRecordData?: 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 invokeenv
of. (default:getCurrentCommand()
)config?
: A config object. (default:getConfig()
)applyReservedRecordData?
: Whether to apply reserved record data. (default:true
)applyRootRecordData?
: Whether to apply root record data. (default:true
)
compareEnvs
A function to compare two resolved env object.
Returns true
if they're equal, false
otherwise.
Type
(one: Rec, theOther: Rec) => boolean
Arguments
one
: A resolved env object to compare withtheOther
.theOther
: A resolved env object to compare withone
.
GetRecordOptions
An argument interface of a function getRecord
.
There're GetRecordsOptions
(plural) and GetRecordOptions
(singular). Don't confuse!
interface GetRecordOptions<D extends Rec, E extends Rec>
extends GetRecordsOptions<D, E> {
env?: PromiseOr<E>
}
getRecord
A function to get a record of a given command from given store, corresponding to the given env.
undefined
is returned when there is no record.
There're getRecords
(plural) and getRecord
(singular). Don't confuse!
Type
<D extends Rec = Rec, E extends Rec = Rec>(options?: GetRecordOptions<D, E>)
=> Promise<HaetaeRecord<D, E> | undefined>
Options?
command?
: A command name to get records of. (default:getCurrentCommand()
)store?
: A store object. (default:getStore()
)env?
: A resolved env object. (default:invokeEnv({ command })
)
FormRecordOptions
An argument interface of the function formRecord
.
interface FormRecordOptions<D extends Rec, E extends Rec> {
data?: D
env?: E
time?: number
}
formRecord
A function to create a new record object.
This only returns an object, not save it.
Type
<D extends Rec, E extends Rec>(options?: FormRecordOptions<D, E>)
=> Promise<HaetaeRecord<D, E>>
Options?
data?
: A record data. (default:invokeRun()
)env?
: A resolved env object. (default:invokeEnv()
time?
: Unix timestamp (opens in a new tab) by milliseconds. (default:Date.now()
(opens in a new tab))
AddRecordOptions
An argument interface of the function addRecord
.
interface AddRecordOptions<D extends Rec, E extends Rec> {
config?: HaetaeConfig<D, E>
command?: string
store?: HaetaeStore<D, E>
record?: HaetaeRecord<D, E>
}
addRecord
A function to add a new record under the given command to store.
Type
<D extends Rec, E extends Rec>(options?: AddRecordOptions<D, E>)
=> Promise<HaetaeStore<D, E>>
Options?
config?
: A config object. (default:getConfig()
)config.recordRemoval.age
: Age threshold by milliseconds. Records whose age are older than this value are removed.config.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. This task is executed after that ofconfig.recordRemoval.age
.
command?
: A command name to add record under. (default:getCurrentCommand()
)store?
: A store object. (default:getStore()
)record?
: A new record object to add. (default:)formRecord({ data: invokeRun({ command }), env: invokeEnv({ command }) })
SaveStoreOptions
An argument interface of the function saveStore
.
interface SaveStoreOptions {
filename?: string
store?: HaetaeStore
}
saveStore
A function to save store object to file.
Memoization cache of getStore
would be clear automatically.
File IO and Memoization cache clear is done sequentially in synchronous manner, as a transaction.
Type
(options?: SaveStoreOptions) => Promise<void>
Options?
filename?
: A file path to write store on. (default:getStoreFilename()
)store?
: A store object to save. (default:addRecord()
)
DeleteStoreOptions
An argument interface of the function deleteStore
.
interface DeleteStoreOptions {
filename?: string
}
deleteStore
A function to delete the entire store by removing the store file.
Memoization cache of getStore
would be clear automatically.
File IO and Memoization cache clear is done sequentially in synchronous manner, as a transaction.
Type
(options?: DeleteStoreOptions) => Promise<void>
Options?
filename?
: A store file path to delete. (default:getStoreFilename()
)