APIs
@haetae/core

@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 if filename exists. No effect when filename 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 as defaultConfigFiles.

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
}

HaetaeCommandEnvOptions

interface HaetaeCommandEnvOptions<S extends StoreConnector> {
  store: S
}

HaetaeCommandEnv

<E extends Rec, S extends StoreConnector> = (
  options: HaetaeCommandEnvOptions<S>,
) => void | PromiseOr<E>

HaetaePreCommandEnv

type HaetaePreCommandEnv<E extends Rec, S extends StoreConnector> =
  | HaetaeCommandEnv<E, S>
  | PromiseOr<E | void>

HaetaeCommandRun

interface HaetaeCommandRunOptions<
  E extends Rec,
  S extends StoreConnector,
> {
  env: E
  store: S
}

HaetaeCommandRun

type HaetaeCommandRun<
  D extends Rec,
  E extends Rec,
  S extends StoreConnector,
> = (options: HaetaeCommandRunOptions<E, S>) => void | PromiseOr<D | void>

HaetaePreCommand

interface HaetaePreCommand<
  D extends Rec,
  E extends Rec,
  S extends StoreConnector,
> {
  run: HaetaeCommandRun<D, E, S>
  env?: HaetaePreCommandEnv<E, S>
}

HaetaeCommand

interface HaetaeCommand<
  D extends Rec,
  E extends Rec,
  S extends StoreConnector,
> {
  run: HaetaeCommandRun<D, E, S>
  env: HaetaeCommandEnv<E, S>
}

RootEnv

type RootEnv<
  A extends Rec,
  S extends StoreConnector,
  R extends Rec = A,
> = (envFromCommand: A, options: HaetaeCommandEnvOptions<S>) => PromiseOr<R>

RootRecordData

type RootRecordData<
  A extends Rec,
  E extends Rec,
  S extends StoreConnector,
  R extends Rec = A,
> = (
  recordDataFromCommand: A,
  options: HaetaeCommandRunOptions<E, S>,
) => PromiseOr<R>

HaetaePreConfig

An interface of user-given config schema.
Also an argument interface of the function configure.

 interface HaetaePreConfig<S extends StoreConnector> {
  commands: Record<string, HaetaePreCommand<Rec, Rec, S>>
  env?: RootEnv<Rec, S>
  recordData?: RootRecordData<Rec, Rec, S>
  store?: S
}

HaetaeConfig

An interface of normalized config schema.
Also a return type of function configure.

interface HaetaeConfig<
  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]: HaetaeCommand<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 = LocalStoreConnector,
>(options: HaetaePreConfig<S>) => HaetaeConfig<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: localStore())

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.

haetae.config.js
export default { /* ... */ }

With configure, type-check is enabled. Your IDE is Happy! 😊

haetae.config.js
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 a user-given (argument) config. Omitted options from a user-given config HaetaePreConfig are to be set as their default values in HaetaeConfig.

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<HaetaeConfig<D, E, S>>

Options?

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? : If true, the arg recordData 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>
}

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 invoke env 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?: HaetaeConfig<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? : A env 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?: HaetaeConfig<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 invoke run of. (default: getCurrentCommand())
  • config? : A config object. (default: await getConfig()
  • env? : A env object to pass to run. (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?: HaetaeConfig<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 : A env object to pass to recordData. (default: await invokeRootEnv()
  • recordData : A Record Data object to pass to recordData. (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? : An env object*.

CreateRecordOptions

An argument interface of the function createRecord.

interface CreateRecordOptions<D extends Rec, E extends Rec> {
  config?: HaetaeConfig<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>>

LocalStore

An interface for the local store file.

interface LocalStore<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 of env 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
}

LocalStoreConnector

An interface of local Store Connector.

interface LocalStoreConnector extends StoreConnector {
  initNewStore<D extends Rec, E extends Rec>(): LocalStore<D, E>
  loadStore<D extends Rec, E extends Rec>
    (options?: LoadStoreOptions): Promise<LocalStore<D, E>>
  saveStore(store: LocalStore): Promise<void>
  localStore: {
    filename: string
    recordRemoval: {
      age: number
      count: number
    }
  }
}

LocalStoreOptions

An argument interface of a function localStore.

interface LocalStoreOptions {
  filename?: string
  recordRemoval?: {
    age?: number | string
    count?: number
    leaveOnlyLastestPerEnv?: boolean
  }
}

localStore

A function to create a Store Connector that reads and writes to a local file.

Type

(options?: LocalStoreOptions): LocalStoreConnector

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 calling addRecord. (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 calling addRecord. This task is executed after recordRemoval.age is used. (default: Number.POSITIVE_INFINITY)
  • recordRemoval.leaveOnlyLastestPerEnv? : If true, only the lastet records per env exist in the store file. This is useful if you only depend on the latest record per env. (default: true)

LocalStoreConnector.initNewStore

Initializes an empty store. It just returns an object. It does not save it as a file.

Type

LocalStoreConnector.initNewStore

LoadStoreOptions

An argument interface of the function LocalStoreConnector.loadStore.

interface LoadStoreOptions {
  initWhenNotFound?: boolean
}

LocalStoreConnector.loadStore


Memoized

A function to load a store object from the file.

Type

LocalStoreConnector.loadStore

Options?

  • initWhenNotFound? : Whether to throw an error or just initialize a new store object when filename does not exist in the filesystem. If true, LocalStoreConnector.initNewStore() is returned, and the filesystem is not affected. (default: true)

LocalStoreConnector.saveStore

A function to save a store object to a file.
Memoization cache of LocalStoreConnector.loadStore would be clear automatically.

Type

LocalStoreConnector.saveStore

Options?

  • store? : A store object to save. (default: await addRecord())