@xylabs/creatable
Advanced tools
@@ -390,2 +390,2 @@ var __defProp = Object.defineProperty; | ||
| }; | ||
| //# sourceMappingURL=index.mjs.map | ||
| //# sourceMappingURL=index.mjs.map |
@@ -1,1 +0,7 @@ | ||
| {"version":3,"sources":["../../src/AbstractCreatable.ts","../../src/Creatable.ts","../../src/Factory.ts","../../src/lib/getFunctionName.ts","../../src/lib/getRootFunction.ts","../../src/model/Labels.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport type { EventData } from '@xylabs/events'\nimport { BaseEmitter } from '@xylabs/events'\nimport { type Logger } from '@xylabs/logger'\nimport type { Promisable } from '@xylabs/promise'\nimport {\n SpanConfig, spanRoot, spanRootAsync,\n} from '@xylabs/telemetry'\nimport {\n isError, isNumber, isString,\n isUndefined,\n} from '@xylabs/typeof'\nimport { Mutex } from 'async-mutex'\n\nimport {\n type Creatable, creatable, CreatableFactory,\n} from './Creatable.ts'\nimport { Factory } from './Factory.ts'\nimport { getFunctionName, getRootFunction } from './lib/index.ts'\nimport type {\n CreatableInstance, CreatableName, CreatableParams,\n CreatableStatus,\n Labels,\n RequiredCreatableParams,\n} from './model/index.ts'\n\nconst AbstractCreatableConstructorKey = Symbol.for('AbstractCreatableConstructor')\nconst CREATABLE_NOT_STARTED = 'Creatable not Started' as const\n\n/**\n * Base class for objects that follow an asynchronous creation and lifecycle pattern.\n * Instances must be created via the static `create` method rather than direct construction.\n * Provides start/stop lifecycle management with status tracking and telemetry support.\n */\n@creatable()\nexport class AbstractCreatable<TParams extends CreatableParams = CreatableParams,\n TEventData extends EventData = EventData> extends BaseEmitter<Partial<TParams & RequiredCreatableParams>, TEventData> {\n /** Optional default logger for this instance. */\n defaultLogger?: Logger\n\n protected _startPromise: Promisable<boolean> | undefined\n private _status: CreatableStatus | null = null\n private _statusMutex = new Mutex()\n private _validatedParams?: TParams & RequiredCreatableParams\n\n constructor(key: unknown, params: Partial<TParams & RequiredCreatableParams>) {\n assertEx(key === AbstractCreatableConstructorKey, () => 'AbstractCreatable should not be instantiated directly, use the static create method instead')\n super(params)\n }\n\n /** The name identifier for this creatable instance. */\n get name(): CreatableName {\n return this.params.name as CreatableName\n }\n\n /** The validated and merged parameters for this instance. */\n override get params(): TParams & RequiredCreatableParams {\n this._validatedParams = this._validatedParams ?? this.paramsValidator(super.params)\n return this._validatedParams\n }\n\n /** Whether this instance can be started (must be in 'created' or 'stopped' status). */\n get startable() {\n return this.status === 'created' || this.status === 'stopped'\n }\n\n /** The current lifecycle status of this instance, or null if not yet initialized. */\n get status(): CreatableStatus | null {\n return this._status\n }\n\n /** The status reporter used to broadcast lifecycle changes. */\n get statusReporter() {\n return this.params.statusReporter\n }\n\n /**\n * Asynchronously creates a new instance by processing params, constructing,\n * and running both static and instance createHandlers.\n * @param inParams - Optional partial parameters to configure the instance\n * @returns The fully initialized instance\n */\n static async create<T extends CreatableInstance>(\n this: Creatable<T>,\n inParams: Partial<T['params']> = {},\n ): Promise<T> {\n const params = await this.paramsHandler(inParams)\n const name: CreatableName = params.name ?? this.name as CreatableName\n try {\n const instance = new this(AbstractCreatableConstructorKey, params)\n instance.setStatus('creating')\n const initializedInstance = await this.createHandler(instance)\n await instance.createHandler()\n instance.setStatus('created')\n return initializedInstance\n } catch (ex) {\n params.statusReporter?.report(name, 'error', isError(ex) ? ex : new Error(`Error creating: ${name}`))\n params.logger?.error(`Error creating creatable [${name}]: ${(isError(ex) ? `${ex.message} ${ex.stack}` : ex)}`)\n throw isError(ex) ? ex : new Error(`Error creating: ${name}`)\n }\n }\n\n /**\n * Static hook called during creation to perform additional initialization.\n * Override in subclasses to customize post-construction setup.\n * @param instance - The newly constructed instance\n * @returns The instance, potentially modified\n */\n static createHandler<T extends CreatableInstance>(\n this: Creatable<T>,\n instance: T,\n ): Promisable<T> {\n return instance\n }\n\n /**\n * Static hook called during creation to validate and transform params.\n * Override in subclasses to add default values or validation.\n * @param params - The raw partial params provided to `create`\n * @returns The processed params ready for construction\n */\n static paramsHandler<T extends CreatableInstance>(\n this: Creatable<T>,\n params: Partial<T['params']> = {},\n ): Promisable<T['params']> {\n return { ...params }\n }\n\n /** Instance-level creation hook. Override in subclasses to perform setup after construction. */\n createHandler(): Promisable<void> {\n assertEx(this._status === 'creating', () => `createHandler can not be called [status = ${this.status}]`)\n }\n\n /**\n * Validates and returns the merged params, ensuring required fields are present.\n * Override in subclasses to add custom validation logic.\n * @param params - The raw partial params to validate\n * @returns The validated params\n */\n paramsValidator(params: Partial<TParams & RequiredCreatableParams>): TParams & RequiredCreatableParams {\n return { ...params, name: params.name } as TParams & RequiredCreatableParams\n }\n\n /**\n * Executes a function within a telemetry span.\n * @param name - The span name\n * @param fn - The function to execute within the span\n */\n span<T>(name: string, fn: () => T): T {\n return spanRoot(name, fn, this.tracer)\n }\n\n /**\n * Executes an async function within a telemetry span.\n * @param name - The span name\n * @param fn - The async function to execute within the span\n * @param config - Optional span configuration\n */\n async spanAsync<T>(name: string, fn: () => Promise<T>, config: SpanConfig = {}): Promise<T> {\n return await spanRootAsync(name, fn, {\n ...config, tracer: config.tracer ?? this.tracer, logger: config.logger ?? this.defaultLogger,\n })\n }\n\n /**\n * Starts the instance, transitioning through 'starting' to 'started' status.\n * Thread-safe via mutex. Returns true if already started or started successfully.\n */\n async start(): Promise<boolean> {\n this._noOverride('start')\n if (this.status === 'started') {\n return true\n }\n return await this._statusMutex.runExclusive(async () => {\n try {\n // check again in case it changed\n if (this.status === 'started') {\n return true\n }\n assertEx(this.startable, () => `Creatable [${this.name}] is not startable in status [${this.status}]`)\n this.setStatus('starting')\n await this.startHandler()\n this.setStatus('started')\n return true\n } catch (ex) {\n this.setStatus('error', isError(ex) ? ex : new Error(`Error starting: ${ex}`))\n this.logger?.error(`Error starting creatable [${this.name}]: ${(isError(ex) ? `${ex.message} ${ex.stack}` : ex)}`)\n return false\n }\n })\n }\n\n /**\n * Checks whether this instance is currently started.\n * Takes an action if not started, based on the notStartedAction parameter.\n * @param notStartedAction - What to do if not started: 'error'/'throw' throws, 'warn'/'log' logs, 'none' is silent\n * @returns True if started, false otherwise\n */\n started(notStartedAction: 'error' | 'throw' | 'warn' | 'log' | 'none' = 'log'): boolean {\n if (isString(this.status) && this.status === 'started') {\n return true\n } else {\n const message = () => `${CREATABLE_NOT_STARTED} [${this.name}] current state: ${this.status}`\n switch (notStartedAction) {\n case 'error': {\n throw new Error(message())\n }\n case 'throw': {\n throw new Error(message())\n }\n case 'warn': {\n this.logger?.warn(message())\n break\n }\n case 'log': {\n this.logger?.log(message())\n break\n }\n case 'none': {\n break\n }\n default: {\n throw new Error(`Unknown notStartedAction: ${notStartedAction}`)\n }\n }\n return false\n }\n }\n\n /**\n * Async version of `started` that can optionally auto-start the instance.\n * @param notStartedAction - What to do if not started and auto-start is disabled\n * @param tryStart - If true, attempts to start the instance automatically\n * @returns True if the instance is or becomes started\n */\n async startedAsync(notStartedAction: 'error' | 'throw' | 'warn' | 'log' | 'none' = 'log', tryStart = true): Promise<boolean> {\n if (isString(this.status) && this.status === 'started') {\n return true\n } else if (this.status === 'created' || this.status === 'stopped' || this.status === 'starting') {\n // using promise as mutex\n this._startPromise = this._startPromise ?? (async () => {\n if (tryStart) {\n try {\n return await this.start()\n } finally {\n this._startPromise = undefined\n }\n }\n return this.started(notStartedAction)\n })()\n } else {\n const message = `${CREATABLE_NOT_STARTED} [${this.name}] current state: ${this.status}`\n throw new Error(message)\n }\n\n if (isUndefined(this._startPromise)) {\n throw new Error(`Failed to create start promise: ${this.status}`)\n }\n return await this._startPromise\n }\n\n /**\n * Stops the instance, transitioning through 'stopping' to 'stopped' status.\n * Thread-safe via mutex. Returns true if already stopped or stopped successfully.\n */\n async stop(): Promise<boolean> {\n this._noOverride('stop')\n if (this.status === 'stopped') {\n return true\n }\n return await this._statusMutex.runExclusive(async () => {\n try {\n // check again in case it changed\n if (this.status === 'stopped') {\n return true\n }\n assertEx(this.status === 'started', () => `Creatable [${this.name}] is not stoppable in status [${this.status}]`)\n this.setStatus('stopping')\n await this.stopHandler()\n this.setStatus('stopped')\n return true\n } catch (ex) {\n this.setStatus('error', isError(ex) ? ex : new Error(`Error stopping: ${ex}`))\n return false\n }\n })\n }\n\n /**\n * Asserts that the given function has not been overridden in a subclass.\n * Used to enforce the handler pattern (override `startHandler` not `start`).\n */\n protected _noOverride(functionName = getFunctionName(3)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const thisFunc = (this as any)[functionName]\n\n const rootFunc = getRootFunction(this, functionName)\n assertEx(thisFunc === rootFunc, () => `Override not allowed for [${functionName}] - override ${functionName}Handler instead`)\n }\n\n /** Sets the lifecycle status and reports it via the status reporter. */\n protected setStatus(value: Exclude<CreatableStatus, 'error'>, progress?: number): void\n protected setStatus(value: Extract<CreatableStatus, 'error'>, error?: Error): void\n protected setStatus(value: CreatableStatus, progressOrError?: number | Error): void {\n this._status = value\n if (value !== null) {\n if (value === 'error') {\n if (isError(progressOrError)) {\n this.statusReporter?.report(this.name, value, progressOrError)\n return\n }\n } else {\n if (isNumber(progressOrError)) {\n this.statusReporter?.report(this.name, value, progressOrError)\n return\n }\n }\n this.statusReporter?.report(this.name, value)\n }\n }\n\n /** Override in subclasses to define start behavior. Throw an error on failure. */\n protected startHandler(): Promisable<void> {\n // when overriding this, throw an error on failure\n }\n\n /** Override in subclasses to define stop behavior. Throw an error on failure. */\n protected stopHandler(): Promisable<void> {\n // when overriding this, throw an error on failure\n }\n}\n\n/**\n * Extends AbstractCreatable with a static `factory` method for creating\n * pre-configured CreatableFactory instances.\n */\n@creatable()\nexport class AbstractCreatableWithFactory<TParams extends CreatableParams = CreatableParams,\n TEventData extends EventData = EventData> extends AbstractCreatable<TParams, TEventData> {\n /**\n * Creates a factory that produces instances of this class with pre-configured params and labels.\n * @param params - Default parameters for instances created by the factory\n * @param labels - Labels to assign to created instances\n */\n static factory<T extends CreatableInstance>(\n this: Creatable<T>,\n params?: Partial<T['params']>,\n labels?: Labels,\n ): CreatableFactory<T> {\n return Factory.withParams<T>(this, params, labels)\n }\n}\n","import type { Logger } from '@xylabs/logger'\nimport type { Promisable } from '@xylabs/promise'\n\nimport type { AbstractCreatable } from './AbstractCreatable.ts'\nimport type {\n CreatableInstance, CreatableParams, Labels,\n RequiredCreatableParams,\n} from './model/index.ts'\n\n/**\n * A factory interface for creating instances of a Creatable with pre-configured parameters.\n * Unlike the full Creatable, this only exposes the `create` method.\n */\nexport interface CreatableFactory<T extends CreatableInstance = CreatableInstance>\n extends Omit<Creatable<T>, 'create' | 'createHandler' | 'paramsHandler' | 'defaultLogger' | 'factory'> {\n\n /** Creates a new instance, merging the provided params with the factory's defaults. */\n create(\n this: CreatableFactory<T>,\n params?: Partial<T['params']>): Promise<T>\n}\n\n/**\n * Static interface for classes that support asynchronous creation.\n * Provides the `create`, `createHandler`, and `paramsHandler` static methods\n * used to construct instances through the creatable lifecycle.\n */\nexport interface Creatable<T extends CreatableInstance = CreatableInstance> {\n\n /** Optional default logger shared across instances created by this class. */\n defaultLogger?: Logger\n\n /** Constructs a new raw instance. Should not be called directly; use `create` instead. */\n new(key: unknown, params: Partial<CreatableParams>): T & AbstractCreatable<T['params']>\n\n /** Asynchronously creates and initializes a new instance with the given params. */\n create<T extends CreatableInstance>(\n this: Creatable<T>,\n params?: Partial<T['params']>): Promise<T>\n\n /** Hook called after construction to perform additional initialization on the instance. */\n createHandler<T extends CreatableInstance>(\n this: Creatable<T>,\n instance: T\n ): Promisable<T>\n\n /** Hook called to validate and transform params before instance construction. */\n paramsHandler<T extends CreatableInstance>(\n this: Creatable<T>, params?: Partial<T['params']>): Promisable<T['params'] & RequiredCreatableParams>\n}\n\n/** Extends Creatable with a `factory` method that produces pre-configured CreatableFactory instances. */\nexport interface CreatableWithFactory<T extends CreatableInstance = CreatableInstance> extends Creatable<T> {\n /** Creates a factory with the given default params and labels. */\n factory<T extends CreatableInstance>(\n this: Creatable<T>,\n params?: Partial<T['params']>,\n labels?: Labels): CreatableFactory<T>\n}\n\n/**\n * Class annotation to be used to decorate Modules which support\n * an asynchronous creation pattern\n * @returns The decorated Module requiring it implement the members\n * of the CreatableModule as statics properties/methods\n */\nexport function creatable<T extends CreatableInstance>() {\n return <U extends Creatable<T>>(constructor: U) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n constructor\n }\n}\n\n/**\n * Class annotation to be used to decorate Modules which support\n * an asynchronous creation factory pattern\n * @returns The decorated Module requiring it implement the members\n * of the CreatableModule as statics properties/methods\n */\n\nexport function creatableFactory() {\n return <U extends CreatableFactory>(constructor: U) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n constructor\n }\n}\n","import { type Creatable, type CreatableFactory } from './Creatable.ts'\nimport type {\n CreatableInstance, Labels, WithOptionalLabels,\n} from './model/index.ts'\n\n/**\n * A concrete factory that wraps a Creatable class with default parameters and labels.\n * Instances are created by merging caller-provided params over the factory defaults.\n */\nexport class Factory<T extends CreatableInstance = CreatableInstance> implements CreatableFactory<T> {\n /** The Creatable class this factory delegates creation to. */\n creatable: Creatable<T>\n\n /** Default parameters merged into every `create` call. */\n defaultParams?: Partial<T['params']>\n\n /** Labels identifying resources created by this factory. */\n labels?: Labels\n\n constructor(\n creatable: Creatable<T>,\n params?: Partial<T['params']>,\n labels: Labels = {},\n ) {\n this.creatable = creatable\n this.defaultParams = params\n this.labels = Object.assign({}, (creatable as WithOptionalLabels).labels ?? {}, labels ?? {})\n }\n\n /**\n * Creates a new Factory instance with the given default params and labels.\n * @param creatableModule - The Creatable class to wrap\n * @param params - Default parameters for new instances\n * @param labels - Labels to assign to created instances\n */\n static withParams<T extends CreatableInstance>(\n creatableModule: Creatable<T>,\n params?: Partial<T['params']>,\n labels: Labels = {},\n ) {\n return new Factory<T>(creatableModule, params, labels)\n }\n\n /**\n * Creates a new instance, merging the provided params over the factory defaults.\n * @param params - Optional parameters to override the factory defaults\n */\n create(params?: Partial<T['params']>): Promise<T> {\n const mergedParams: T['params'] = {\n ...this.defaultParams,\n ...params,\n } as T['params']\n return this.creatable.create<T>(mergedParams)\n }\n}\n","import { isNumber } from '@xylabs/typeof'\n\n/**\n * Extracts the function name from the call stack at the given depth.\n * @param depth - The stack frame depth to inspect (default: 2)\n * @returns The function name, or '\\<unknown\\>' if it cannot be determined\n */\nexport function getFunctionName(depth = 2) {\n const error = new Error('Stack')\n let newIndex: number | undefined\n const stackParts = error.stack?.split('\\n')[depth]?.split(' ')\n const funcName\n = stackParts?.find((item, index) => {\n if (item.length > 0 && item !== 'at') {\n // check if constructor\n if (item === 'new') {\n newIndex = index\n }\n return true\n }\n }) ?? '<unknown>'\n return isNumber(newIndex) ? `${funcName} ${stackParts?.[newIndex + 1]}` : funcName\n}\n","/**\n * Walks the prototype chain to find the root (base-most) definition of a named function.\n * @param obj - The object to start searching from\n * @param funcName - The name of the function to locate\n * @returns The function from the highest prototype in the chain that defines it\n */\nexport function getRootFunction(obj: unknown, funcName: string) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let anyObj = obj as any\n while (anyObj.__proto__?.[funcName]) {\n anyObj = anyObj.__proto__\n }\n return anyObj[funcName]\n}\n","/**\n * Object used to represent labels identifying a resource.\n */\nexport type Labels = Record<string, string | undefined>\n\n/**\n * Interface for objects that have labels.\n */\nexport interface WithLabels<T extends Labels = Labels> {\n labels: T\n}\n\n/**\n * Interface for objects that have labels.\n */\nexport interface WithOptionalLabels<T extends Labels = Labels> {\n labels?: T\n}\n\n/**\n * Returns true if the source object has all the labels from the required set\n * @param source Source object to check against\n * @param required Set of labels to check for in source\n * @returns True of the source object has all the labels from the required set\n */\nexport const hasAllLabels = (source?: Labels, required?: Labels): boolean => {\n if (!required) return true\n return Object.entries(required).every(([key, value]) => {\n return source?.hasOwnProperty(key as keyof typeof source) && source?.[key as keyof typeof source] === value\n })\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,gBAAgB;AAEzB,SAAS,mBAAmB;AAG5B;AAAA,EACc;AAAA,EAAU;AAAA,OACjB;AACP;AAAA,EACE;AAAA,EAAS,YAAAA;AAAA,EAAU;AAAA,EACnB;AAAA,OACK;AACP,SAAS,aAAa;;;ACsDf,SAAS,YAAyC;AACvD,SAAO,CAAyB,gBAAmB;AAEjD;AAAA,EACF;AACF;AASO,SAAS,mBAAmB;AACjC,SAAO,CAA6B,gBAAmB;AAErD;AAAA,EACF;AACF;;;AC5EO,IAAM,UAAN,MAAM,SAAwF;AAAA;AAAA,EAEnG;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EAEA,YACEC,YACA,QACA,SAAiB,CAAC,GAClB;AACA,SAAK,YAAYA;AACjB,SAAK,gBAAgB;AACrB,SAAK,SAAS,OAAO,OAAO,CAAC,GAAIA,WAAiC,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,WACL,iBACA,QACA,SAAiB,CAAC,GAClB;AACA,WAAO,IAAI,SAAW,iBAAiB,QAAQ,MAAM;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,QAA2C;AAChD,UAAM,eAA4B;AAAA,MAChC,GAAG,KAAK;AAAA,MACR,GAAG;AAAA,IACL;AACA,WAAO,KAAK,UAAU,OAAU,YAAY;AAAA,EAC9C;AACF;;;ACtDA,SAAS,gBAAgB;AAOlB,SAAS,gBAAgB,QAAQ,GAAG;AACzC,QAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,MAAI;AACJ,QAAM,aAAa,MAAM,OAAO,MAAM,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG;AAC7D,QAAM,WACF,YAAY,KAAK,CAAC,MAAM,UAAU;AAClC,QAAI,KAAK,SAAS,KAAK,SAAS,MAAM;AAEpC,UAAI,SAAS,OAAO;AAClB,mBAAW;AAAA,MACb;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC,KAAK;AACR,SAAO,SAAS,QAAQ,IAAI,GAAG,QAAQ,IAAI,aAAa,WAAW,CAAC,CAAC,KAAK;AAC5E;;;AChBO,SAAS,gBAAgB,KAAc,UAAkB;AAE9D,MAAI,SAAS;AACb,SAAO,OAAO,YAAY,QAAQ,GAAG;AACnC,aAAS,OAAO;AAAA,EAClB;AACA,SAAO,OAAO,QAAQ;AACxB;;;AJaA,IAAM,kCAAkC,uBAAO,IAAI,8BAA8B;AACjF,IAAM,wBAAwB;AAQvB,IAAM,oBAAN,cAC6C,YAAoE;AAAA;AAAA,EAEtH;AAAA,EAEU;AAAA,EACF,UAAkC;AAAA,EAClC,eAAe,IAAI,MAAM;AAAA,EACzB;AAAA,EAER,YAAY,KAAc,QAAoD;AAC5E,aAAS,QAAQ,iCAAiC,MAAM,6FAA6F;AACrJ,UAAM,MAAM;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,OAAsB;AACxB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA,EAGA,IAAa,SAA4C;AACvD,SAAK,mBAAmB,KAAK,oBAAoB,KAAK,gBAAgB,MAAM,MAAM;AAClF,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,YAAY;AACd,WAAO,KAAK,WAAW,aAAa,KAAK,WAAW;AAAA,EACtD;AAAA;AAAA,EAGA,IAAI,SAAiC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,iBAAiB;AACnB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,OAEX,WAAiC,CAAC,GACtB;AACZ,UAAM,SAAS,MAAM,KAAK,cAAc,QAAQ;AAChD,UAAM,OAAsB,OAAO,QAAQ,KAAK;AAChD,QAAI;AACF,YAAM,WAAW,IAAI,KAAK,iCAAiC,MAAM;AACjE,eAAS,UAAU,UAAU;AAC7B,YAAM,sBAAsB,MAAM,KAAK,cAAc,QAAQ;AAC7D,YAAM,SAAS,cAAc;AAC7B,eAAS,UAAU,SAAS;AAC5B,aAAO;AAAA,IACT,SAAS,IAAI;AACX,aAAO,gBAAgB,OAAO,MAAM,SAAS,QAAQ,EAAE,IAAI,KAAK,IAAI,MAAM,mBAAmB,IAAI,EAAE,CAAC;AACpG,aAAO,QAAQ,MAAM,6BAA6B,IAAI,MAAO,QAAQ,EAAE,IAAI,GAAG,GAAG,OAAO,IAAI,GAAG,KAAK,KAAK,EAAG,EAAE;AAC9G,YAAM,QAAQ,EAAE,IAAI,KAAK,IAAI,MAAM,mBAAmB,IAAI,EAAE;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,cAEL,UACe;AACf,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,cAEL,SAA+B,CAAC,GACP;AACzB,WAAO,EAAE,GAAG,OAAO;AAAA,EACrB;AAAA;AAAA,EAGA,gBAAkC;AAChC,aAAS,KAAK,YAAY,YAAY,MAAM,6CAA6C,KAAK,MAAM,GAAG;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,QAAuF;AACrG,WAAO,EAAE,GAAG,QAAQ,MAAM,OAAO,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAQ,MAAc,IAAgB;AACpC,WAAO,SAAS,MAAM,IAAI,KAAK,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAa,MAAc,IAAsB,SAAqB,CAAC,GAAe;AAC1F,WAAO,MAAM,cAAc,MAAM,IAAI;AAAA,MACnC,GAAG;AAAA,MAAQ,QAAQ,OAAO,UAAU,KAAK;AAAA,MAAQ,QAAQ,OAAO,UAAU,KAAK;AAAA,IACjF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAA0B;AAC9B,SAAK,YAAY,OAAO;AACxB,QAAI,KAAK,WAAW,WAAW;AAC7B,aAAO;AAAA,IACT;AACA,WAAO,MAAM,KAAK,aAAa,aAAa,YAAY;AACtD,UAAI;AAEF,YAAI,KAAK,WAAW,WAAW;AAC7B,iBAAO;AAAA,QACT;AACA,iBAAS,KAAK,WAAW,MAAM,cAAc,KAAK,IAAI,iCAAiC,KAAK,MAAM,GAAG;AACrG,aAAK,UAAU,UAAU;AACzB,cAAM,KAAK,aAAa;AACxB,aAAK,UAAU,SAAS;AACxB,eAAO;AAAA,MACT,SAAS,IAAI;AACX,aAAK,UAAU,SAAS,QAAQ,EAAE,IAAI,KAAK,IAAI,MAAM,mBAAmB,EAAE,EAAE,CAAC;AAC7E,aAAK,QAAQ,MAAM,6BAA6B,KAAK,IAAI,MAAO,QAAQ,EAAE,IAAI,GAAG,GAAG,OAAO,IAAI,GAAG,KAAK,KAAK,EAAG,EAAE;AACjH,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAQ,mBAAgE,OAAgB;AACtF,QAAI,SAAS,KAAK,MAAM,KAAK,KAAK,WAAW,WAAW;AACtD,aAAO;AAAA,IACT,OAAO;AACL,YAAM,UAAU,MAAM,GAAG,qBAAqB,KAAK,KAAK,IAAI,oBAAoB,KAAK,MAAM;AAC3F,cAAQ,kBAAkB;AAAA,QACxB,KAAK,SAAS;AACZ,gBAAM,IAAI,MAAM,QAAQ,CAAC;AAAA,QAC3B;AAAA,QACA,KAAK,SAAS;AACZ,gBAAM,IAAI,MAAM,QAAQ,CAAC;AAAA,QAC3B;AAAA,QACA,KAAK,QAAQ;AACX,eAAK,QAAQ,KAAK,QAAQ,CAAC;AAC3B;AAAA,QACF;AAAA,QACA,KAAK,OAAO;AACV,eAAK,QAAQ,IAAI,QAAQ,CAAC;AAC1B;AAAA,QACF;AAAA,QACA,KAAK,QAAQ;AACX;AAAA,QACF;AAAA,QACA,SAAS;AACP,gBAAM,IAAI,MAAM,6BAA6B,gBAAgB,EAAE;AAAA,QACjE;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,mBAAgE,OAAO,WAAW,MAAwB;AAC3H,QAAI,SAAS,KAAK,MAAM,KAAK,KAAK,WAAW,WAAW;AACtD,aAAO;AAAA,IACT,WAAW,KAAK,WAAW,aAAa,KAAK,WAAW,aAAa,KAAK,WAAW,YAAY;AAE/F,WAAK,gBAAgB,KAAK,kBAAkB,YAAY;AACtD,YAAI,UAAU;AACZ,cAAI;AACF,mBAAO,MAAM,KAAK,MAAM;AAAA,UAC1B,UAAE;AACA,iBAAK,gBAAgB;AAAA,UACvB;AAAA,QACF;AACA,eAAO,KAAK,QAAQ,gBAAgB;AAAA,MACtC,GAAG;AAAA,IACL,OAAO;AACL,YAAM,UAAU,GAAG,qBAAqB,KAAK,KAAK,IAAI,oBAAoB,KAAK,MAAM;AACrF,YAAM,IAAI,MAAM,OAAO;AAAA,IACzB;AAEA,QAAI,YAAY,KAAK,aAAa,GAAG;AACnC,YAAM,IAAI,MAAM,mCAAmC,KAAK,MAAM,EAAE;AAAA,IAClE;AACA,WAAO,MAAM,KAAK;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAyB;AAC7B,SAAK,YAAY,MAAM;AACvB,QAAI,KAAK,WAAW,WAAW;AAC7B,aAAO;AAAA,IACT;AACA,WAAO,MAAM,KAAK,aAAa,aAAa,YAAY;AACtD,UAAI;AAEF,YAAI,KAAK,WAAW,WAAW;AAC7B,iBAAO;AAAA,QACT;AACA,iBAAS,KAAK,WAAW,WAAW,MAAM,cAAc,KAAK,IAAI,iCAAiC,KAAK,MAAM,GAAG;AAChH,aAAK,UAAU,UAAU;AACzB,cAAM,KAAK,YAAY;AACvB,aAAK,UAAU,SAAS;AACxB,eAAO;AAAA,MACT,SAAS,IAAI;AACX,aAAK,UAAU,SAAS,QAAQ,EAAE,IAAI,KAAK,IAAI,MAAM,mBAAmB,EAAE,EAAE,CAAC;AAC7E,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,YAAY,eAAe,gBAAgB,CAAC,GAAG;AAEvD,UAAM,WAAY,KAAa,YAAY;AAE3C,UAAM,WAAW,gBAAgB,MAAM,YAAY;AACnD,aAAS,aAAa,UAAU,MAAM,6BAA6B,YAAY,gBAAgB,YAAY,iBAAiB;AAAA,EAC9H;AAAA,EAKU,UAAU,OAAwB,iBAAwC;AAClF,SAAK,UAAU;AACf,QAAI,UAAU,MAAM;AAClB,UAAI,UAAU,SAAS;AACrB,YAAI,QAAQ,eAAe,GAAG;AAC5B,eAAK,gBAAgB,OAAO,KAAK,MAAM,OAAO,eAAe;AAC7D;AAAA,QACF;AAAA,MACF,OAAO;AACL,YAAIC,UAAS,eAAe,GAAG;AAC7B,eAAK,gBAAgB,OAAO,KAAK,MAAM,OAAO,eAAe;AAC7D;AAAA,QACF;AAAA,MACF;AACA,WAAK,gBAAgB,OAAO,KAAK,MAAM,KAAK;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA,EAGU,eAAiC;AAAA,EAE3C;AAAA;AAAA,EAGU,cAAgC;AAAA,EAE1C;AACF;AAvSa,oBAAN;AAAA,EADN,UAAU;AAAA,GACE;AA8SN,IAAM,+BAAN,cAC6C,kBAAuC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzF,OAAO,QAEL,QACA,QACqB;AACrB,WAAO,QAAQ,WAAc,MAAM,QAAQ,MAAM;AAAA,EACnD;AACF;AAda,+BAAN;AAAA,EADN,UAAU;AAAA,GACE;;;AKxTN,IAAM,eAAe,CAAC,QAAiB,aAA+B;AAC3E,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,OAAO,QAAQ,QAAQ,EAAE,MAAM,CAAC,CAAC,KAAK,KAAK,MAAM;AACtD,WAAO,QAAQ,eAAe,GAA0B,KAAK,SAAS,GAA0B,MAAM;AAAA,EACxG,CAAC;AACH;","names":["isNumber","creatable","isNumber"]} | ||
| { | ||
| "version": 3, | ||
| "sources": ["../../src/AbstractCreatable.ts", "../../src/Creatable.ts", "../../src/Factory.ts", "../../src/lib/getFunctionName.ts", "../../src/lib/getRootFunction.ts", "../../src/model/Labels.ts"], | ||
| "sourcesContent": ["import { assertEx } from '@xylabs/assert'\nimport type { EventData } from '@xylabs/events'\nimport { BaseEmitter } from '@xylabs/events'\nimport { type Logger } from '@xylabs/logger'\nimport type { Promisable } from '@xylabs/promise'\nimport {\n SpanConfig, spanRoot, spanRootAsync,\n} from '@xylabs/telemetry'\nimport {\n isError, isNumber, isString,\n isUndefined,\n} from '@xylabs/typeof'\nimport { Mutex } from 'async-mutex'\n\nimport {\n type Creatable, creatable, CreatableFactory,\n} from './Creatable.ts'\nimport { Factory } from './Factory.ts'\nimport { getFunctionName, getRootFunction } from './lib/index.ts'\nimport type {\n CreatableInstance, CreatableName, CreatableParams,\n CreatableStatus,\n Labels,\n RequiredCreatableParams,\n} from './model/index.ts'\n\nconst AbstractCreatableConstructorKey = Symbol.for('AbstractCreatableConstructor')\nconst CREATABLE_NOT_STARTED = 'Creatable not Started' as const\n\n/**\n * Base class for objects that follow an asynchronous creation and lifecycle pattern.\n * Instances must be created via the static `create` method rather than direct construction.\n * Provides start/stop lifecycle management with status tracking and telemetry support.\n */\n@creatable()\nexport class AbstractCreatable<TParams extends CreatableParams = CreatableParams,\n TEventData extends EventData = EventData> extends BaseEmitter<Partial<TParams & RequiredCreatableParams>, TEventData> {\n /** Optional default logger for this instance. */\n defaultLogger?: Logger\n\n protected _startPromise: Promisable<boolean> | undefined\n private _status: CreatableStatus | null = null\n private _statusMutex = new Mutex()\n private _validatedParams?: TParams & RequiredCreatableParams\n\n constructor(key: unknown, params: Partial<TParams & RequiredCreatableParams>) {\n assertEx(key === AbstractCreatableConstructorKey, () => 'AbstractCreatable should not be instantiated directly, use the static create method instead')\n super(params)\n }\n\n /** The name identifier for this creatable instance. */\n get name(): CreatableName {\n return this.params.name as CreatableName\n }\n\n /** The validated and merged parameters for this instance. */\n override get params(): TParams & RequiredCreatableParams {\n this._validatedParams = this._validatedParams ?? this.paramsValidator(super.params)\n return this._validatedParams\n }\n\n /** Whether this instance can be started (must be in 'created' or 'stopped' status). */\n get startable() {\n return this.status === 'created' || this.status === 'stopped'\n }\n\n /** The current lifecycle status of this instance, or null if not yet initialized. */\n get status(): CreatableStatus | null {\n return this._status\n }\n\n /** The status reporter used to broadcast lifecycle changes. */\n get statusReporter() {\n return this.params.statusReporter\n }\n\n /**\n * Asynchronously creates a new instance by processing params, constructing,\n * and running both static and instance createHandlers.\n * @param inParams - Optional partial parameters to configure the instance\n * @returns The fully initialized instance\n */\n static async create<T extends CreatableInstance>(\n this: Creatable<T>,\n inParams: Partial<T['params']> = {},\n ): Promise<T> {\n const params = await this.paramsHandler(inParams)\n const name: CreatableName = params.name ?? this.name as CreatableName\n try {\n const instance = new this(AbstractCreatableConstructorKey, params)\n instance.setStatus('creating')\n const initializedInstance = await this.createHandler(instance)\n await instance.createHandler()\n instance.setStatus('created')\n return initializedInstance\n } catch (ex) {\n params.statusReporter?.report(name, 'error', isError(ex) ? ex : new Error(`Error creating: ${name}`))\n params.logger?.error(`Error creating creatable [${name}]: ${(isError(ex) ? `${ex.message} ${ex.stack}` : ex)}`)\n throw isError(ex) ? ex : new Error(`Error creating: ${name}`)\n }\n }\n\n /**\n * Static hook called during creation to perform additional initialization.\n * Override in subclasses to customize post-construction setup.\n * @param instance - The newly constructed instance\n * @returns The instance, potentially modified\n */\n static createHandler<T extends CreatableInstance>(\n this: Creatable<T>,\n instance: T,\n ): Promisable<T> {\n return instance\n }\n\n /**\n * Static hook called during creation to validate and transform params.\n * Override in subclasses to add default values or validation.\n * @param params - The raw partial params provided to `create`\n * @returns The processed params ready for construction\n */\n static paramsHandler<T extends CreatableInstance>(\n this: Creatable<T>,\n params: Partial<T['params']> = {},\n ): Promisable<T['params']> {\n return { ...params }\n }\n\n /** Instance-level creation hook. Override in subclasses to perform setup after construction. */\n createHandler(): Promisable<void> {\n assertEx(this._status === 'creating', () => `createHandler can not be called [status = ${this.status}]`)\n }\n\n /**\n * Validates and returns the merged params, ensuring required fields are present.\n * Override in subclasses to add custom validation logic.\n * @param params - The raw partial params to validate\n * @returns The validated params\n */\n paramsValidator(params: Partial<TParams & RequiredCreatableParams>): TParams & RequiredCreatableParams {\n return { ...params, name: params.name } as TParams & RequiredCreatableParams\n }\n\n /**\n * Executes a function within a telemetry span.\n * @param name - The span name\n * @param fn - The function to execute within the span\n */\n span<T>(name: string, fn: () => T): T {\n return spanRoot(name, fn, this.tracer)\n }\n\n /**\n * Executes an async function within a telemetry span.\n * @param name - The span name\n * @param fn - The async function to execute within the span\n * @param config - Optional span configuration\n */\n async spanAsync<T>(name: string, fn: () => Promise<T>, config: SpanConfig = {}): Promise<T> {\n return await spanRootAsync(name, fn, {\n ...config, tracer: config.tracer ?? this.tracer, logger: config.logger ?? this.defaultLogger,\n })\n }\n\n /**\n * Starts the instance, transitioning through 'starting' to 'started' status.\n * Thread-safe via mutex. Returns true if already started or started successfully.\n */\n async start(): Promise<boolean> {\n this._noOverride('start')\n if (this.status === 'started') {\n return true\n }\n return await this._statusMutex.runExclusive(async () => {\n try {\n // check again in case it changed\n if (this.status === 'started') {\n return true\n }\n assertEx(this.startable, () => `Creatable [${this.name}] is not startable in status [${this.status}]`)\n this.setStatus('starting')\n await this.startHandler()\n this.setStatus('started')\n return true\n } catch (ex) {\n this.setStatus('error', isError(ex) ? ex : new Error(`Error starting: ${ex}`))\n this.logger?.error(`Error starting creatable [${this.name}]: ${(isError(ex) ? `${ex.message} ${ex.stack}` : ex)}`)\n return false\n }\n })\n }\n\n /**\n * Checks whether this instance is currently started.\n * Takes an action if not started, based on the notStartedAction parameter.\n * @param notStartedAction - What to do if not started: 'error'/'throw' throws, 'warn'/'log' logs, 'none' is silent\n * @returns True if started, false otherwise\n */\n started(notStartedAction: 'error' | 'throw' | 'warn' | 'log' | 'none' = 'log'): boolean {\n if (isString(this.status) && this.status === 'started') {\n return true\n } else {\n const message = () => `${CREATABLE_NOT_STARTED} [${this.name}] current state: ${this.status}`\n switch (notStartedAction) {\n case 'error': {\n throw new Error(message())\n }\n case 'throw': {\n throw new Error(message())\n }\n case 'warn': {\n this.logger?.warn(message())\n break\n }\n case 'log': {\n this.logger?.log(message())\n break\n }\n case 'none': {\n break\n }\n default: {\n throw new Error(`Unknown notStartedAction: ${notStartedAction}`)\n }\n }\n return false\n }\n }\n\n /**\n * Async version of `started` that can optionally auto-start the instance.\n * @param notStartedAction - What to do if not started and auto-start is disabled\n * @param tryStart - If true, attempts to start the instance automatically\n * @returns True if the instance is or becomes started\n */\n async startedAsync(notStartedAction: 'error' | 'throw' | 'warn' | 'log' | 'none' = 'log', tryStart = true): Promise<boolean> {\n if (isString(this.status) && this.status === 'started') {\n return true\n } else if (this.status === 'created' || this.status === 'stopped' || this.status === 'starting') {\n // using promise as mutex\n this._startPromise = this._startPromise ?? (async () => {\n if (tryStart) {\n try {\n return await this.start()\n } finally {\n this._startPromise = undefined\n }\n }\n return this.started(notStartedAction)\n })()\n } else {\n const message = `${CREATABLE_NOT_STARTED} [${this.name}] current state: ${this.status}`\n throw new Error(message)\n }\n\n if (isUndefined(this._startPromise)) {\n throw new Error(`Failed to create start promise: ${this.status}`)\n }\n return await this._startPromise\n }\n\n /**\n * Stops the instance, transitioning through 'stopping' to 'stopped' status.\n * Thread-safe via mutex. Returns true if already stopped or stopped successfully.\n */\n async stop(): Promise<boolean> {\n this._noOverride('stop')\n if (this.status === 'stopped') {\n return true\n }\n return await this._statusMutex.runExclusive(async () => {\n try {\n // check again in case it changed\n if (this.status === 'stopped') {\n return true\n }\n assertEx(this.status === 'started', () => `Creatable [${this.name}] is not stoppable in status [${this.status}]`)\n this.setStatus('stopping')\n await this.stopHandler()\n this.setStatus('stopped')\n return true\n } catch (ex) {\n this.setStatus('error', isError(ex) ? ex : new Error(`Error stopping: ${ex}`))\n return false\n }\n })\n }\n\n /**\n * Asserts that the given function has not been overridden in a subclass.\n * Used to enforce the handler pattern (override `startHandler` not `start`).\n */\n protected _noOverride(functionName = getFunctionName(3)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const thisFunc = (this as any)[functionName]\n\n const rootFunc = getRootFunction(this, functionName)\n assertEx(thisFunc === rootFunc, () => `Override not allowed for [${functionName}] - override ${functionName}Handler instead`)\n }\n\n /** Sets the lifecycle status and reports it via the status reporter. */\n protected setStatus(value: Exclude<CreatableStatus, 'error'>, progress?: number): void\n protected setStatus(value: Extract<CreatableStatus, 'error'>, error?: Error): void\n protected setStatus(value: CreatableStatus, progressOrError?: number | Error): void {\n this._status = value\n if (value !== null) {\n if (value === 'error') {\n if (isError(progressOrError)) {\n this.statusReporter?.report(this.name, value, progressOrError)\n return\n }\n } else {\n if (isNumber(progressOrError)) {\n this.statusReporter?.report(this.name, value, progressOrError)\n return\n }\n }\n this.statusReporter?.report(this.name, value)\n }\n }\n\n /** Override in subclasses to define start behavior. Throw an error on failure. */\n protected startHandler(): Promisable<void> {\n // when overriding this, throw an error on failure\n }\n\n /** Override in subclasses to define stop behavior. Throw an error on failure. */\n protected stopHandler(): Promisable<void> {\n // when overriding this, throw an error on failure\n }\n}\n\n/**\n * Extends AbstractCreatable with a static `factory` method for creating\n * pre-configured CreatableFactory instances.\n */\n@creatable()\nexport class AbstractCreatableWithFactory<TParams extends CreatableParams = CreatableParams,\n TEventData extends EventData = EventData> extends AbstractCreatable<TParams, TEventData> {\n /**\n * Creates a factory that produces instances of this class with pre-configured params and labels.\n * @param params - Default parameters for instances created by the factory\n * @param labels - Labels to assign to created instances\n */\n static factory<T extends CreatableInstance>(\n this: Creatable<T>,\n params?: Partial<T['params']>,\n labels?: Labels,\n ): CreatableFactory<T> {\n return Factory.withParams<T>(this, params, labels)\n }\n}\n", "import type { Logger } from '@xylabs/logger'\nimport type { Promisable } from '@xylabs/promise'\n\nimport type { AbstractCreatable } from './AbstractCreatable.ts'\nimport type {\n CreatableInstance, CreatableParams, Labels,\n RequiredCreatableParams,\n} from './model/index.ts'\n\n/**\n * A factory interface for creating instances of a Creatable with pre-configured parameters.\n * Unlike the full Creatable, this only exposes the `create` method.\n */\nexport interface CreatableFactory<T extends CreatableInstance = CreatableInstance>\n extends Omit<Creatable<T>, 'create' | 'createHandler' | 'paramsHandler' | 'defaultLogger' | 'factory'> {\n\n /** Creates a new instance, merging the provided params with the factory's defaults. */\n create(\n this: CreatableFactory<T>,\n params?: Partial<T['params']>): Promise<T>\n}\n\n/**\n * Static interface for classes that support asynchronous creation.\n * Provides the `create`, `createHandler`, and `paramsHandler` static methods\n * used to construct instances through the creatable lifecycle.\n */\nexport interface Creatable<T extends CreatableInstance = CreatableInstance> {\n\n /** Optional default logger shared across instances created by this class. */\n defaultLogger?: Logger\n\n /** Constructs a new raw instance. Should not be called directly; use `create` instead. */\n new(key: unknown, params: Partial<CreatableParams>): T & AbstractCreatable<T['params']>\n\n /** Asynchronously creates and initializes a new instance with the given params. */\n create<T extends CreatableInstance>(\n this: Creatable<T>,\n params?: Partial<T['params']>): Promise<T>\n\n /** Hook called after construction to perform additional initialization on the instance. */\n createHandler<T extends CreatableInstance>(\n this: Creatable<T>,\n instance: T\n ): Promisable<T>\n\n /** Hook called to validate and transform params before instance construction. */\n paramsHandler<T extends CreatableInstance>(\n this: Creatable<T>, params?: Partial<T['params']>): Promisable<T['params'] & RequiredCreatableParams>\n}\n\n/** Extends Creatable with a `factory` method that produces pre-configured CreatableFactory instances. */\nexport interface CreatableWithFactory<T extends CreatableInstance = CreatableInstance> extends Creatable<T> {\n /** Creates a factory with the given default params and labels. */\n factory<T extends CreatableInstance>(\n this: Creatable<T>,\n params?: Partial<T['params']>,\n labels?: Labels): CreatableFactory<T>\n}\n\n/**\n * Class annotation to be used to decorate Modules which support\n * an asynchronous creation pattern\n * @returns The decorated Module requiring it implement the members\n * of the CreatableModule as statics properties/methods\n */\nexport function creatable<T extends CreatableInstance>() {\n return <U extends Creatable<T>>(constructor: U) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n constructor\n }\n}\n\n/**\n * Class annotation to be used to decorate Modules which support\n * an asynchronous creation factory pattern\n * @returns The decorated Module requiring it implement the members\n * of the CreatableModule as statics properties/methods\n */\n\nexport function creatableFactory() {\n return <U extends CreatableFactory>(constructor: U) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n constructor\n }\n}\n", "import { type Creatable, type CreatableFactory } from './Creatable.ts'\nimport type {\n CreatableInstance, Labels, WithOptionalLabels,\n} from './model/index.ts'\n\n/**\n * A concrete factory that wraps a Creatable class with default parameters and labels.\n * Instances are created by merging caller-provided params over the factory defaults.\n */\nexport class Factory<T extends CreatableInstance = CreatableInstance> implements CreatableFactory<T> {\n /** The Creatable class this factory delegates creation to. */\n creatable: Creatable<T>\n\n /** Default parameters merged into every `create` call. */\n defaultParams?: Partial<T['params']>\n\n /** Labels identifying resources created by this factory. */\n labels?: Labels\n\n constructor(\n creatable: Creatable<T>,\n params?: Partial<T['params']>,\n labels: Labels = {},\n ) {\n this.creatable = creatable\n this.defaultParams = params\n this.labels = Object.assign({}, (creatable as WithOptionalLabels).labels ?? {}, labels ?? {})\n }\n\n /**\n * Creates a new Factory instance with the given default params and labels.\n * @param creatableModule - The Creatable class to wrap\n * @param params - Default parameters for new instances\n * @param labels - Labels to assign to created instances\n */\n static withParams<T extends CreatableInstance>(\n creatableModule: Creatable<T>,\n params?: Partial<T['params']>,\n labels: Labels = {},\n ) {\n return new Factory<T>(creatableModule, params, labels)\n }\n\n /**\n * Creates a new instance, merging the provided params over the factory defaults.\n * @param params - Optional parameters to override the factory defaults\n */\n create(params?: Partial<T['params']>): Promise<T> {\n const mergedParams: T['params'] = {\n ...this.defaultParams,\n ...params,\n } as T['params']\n return this.creatable.create<T>(mergedParams)\n }\n}\n", "import { isNumber } from '@xylabs/typeof'\n\n/**\n * Extracts the function name from the call stack at the given depth.\n * @param depth - The stack frame depth to inspect (default: 2)\n * @returns The function name, or '\\<unknown\\>' if it cannot be determined\n */\nexport function getFunctionName(depth = 2) {\n const error = new Error('Stack')\n let newIndex: number | undefined\n const stackParts = error.stack?.split('\\n')[depth]?.split(' ')\n const funcName\n = stackParts?.find((item, index) => {\n if (item.length > 0 && item !== 'at') {\n // check if constructor\n if (item === 'new') {\n newIndex = index\n }\n return true\n }\n }) ?? '<unknown>'\n return isNumber(newIndex) ? `${funcName} ${stackParts?.[newIndex + 1]}` : funcName\n}\n", "/**\n * Walks the prototype chain to find the root (base-most) definition of a named function.\n * @param obj - The object to start searching from\n * @param funcName - The name of the function to locate\n * @returns The function from the highest prototype in the chain that defines it\n */\nexport function getRootFunction(obj: unknown, funcName: string) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let anyObj = obj as any\n while (anyObj.__proto__?.[funcName]) {\n anyObj = anyObj.__proto__\n }\n return anyObj[funcName]\n}\n", "/**\n * Object used to represent labels identifying a resource.\n */\nexport type Labels = Record<string, string | undefined>\n\n/**\n * Interface for objects that have labels.\n */\nexport interface WithLabels<T extends Labels = Labels> {\n labels: T\n}\n\n/**\n * Interface for objects that have labels.\n */\nexport interface WithOptionalLabels<T extends Labels = Labels> {\n labels?: T\n}\n\n/**\n * Returns true if the source object has all the labels from the required set\n * @param source Source object to check against\n * @param required Set of labels to check for in source\n * @returns True of the source object has all the labels from the required set\n */\nexport const hasAllLabels = (source?: Labels, required?: Labels): boolean => {\n if (!required) return true\n return Object.entries(required).every(([key, value]) => {\n return source?.hasOwnProperty(key as keyof typeof source) && source?.[key as keyof typeof source] === value\n })\n}\n"], | ||
| "mappings": "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", | ||
| "names": ["isNumber", "creatable", "isNumber"] | ||
| } |
+14
-14
| { | ||
| "name": "@xylabs/creatable", | ||
| "version": "5.1.2", | ||
| "version": "5.1.3", | ||
| "description": "Base functionality used throughout XY Labs TypeScript/JavaScript libraries", | ||
@@ -37,21 +37,21 @@ "homepage": "https://xyo.network", | ||
| "dependencies": { | ||
| "@xylabs/base": "~5.1.2", | ||
| "@xylabs/assert": "~5.1.2", | ||
| "@xylabs/events": "~5.1.2", | ||
| "@xylabs/promise": "~5.1.2", | ||
| "@xylabs/logger": "~5.1.2", | ||
| "@xylabs/typeof": "~5.1.2", | ||
| "@xylabs/telemetry": "~5.1.2" | ||
| "@xylabs/base": "~5.1.3", | ||
| "@xylabs/assert": "~5.1.3", | ||
| "@xylabs/events": "~5.1.3", | ||
| "@xylabs/logger": "~5.1.3", | ||
| "@xylabs/promise": "~5.1.3", | ||
| "@xylabs/telemetry": "~5.1.3", | ||
| "@xylabs/typeof": "~5.1.3" | ||
| }, | ||
| "devDependencies": { | ||
| "@opentelemetry/api": "^1.9.1", | ||
| "@types/node": "^25.6.0", | ||
| "@xylabs/toolchain": "~7.13.15", | ||
| "@xylabs/tsconfig": "~7.13.15", | ||
| "@types/node": "^25.8.0", | ||
| "@xylabs/toolchain": "~8.0.4", | ||
| "@xylabs/tsconfig": "~8.0.4", | ||
| "async-mutex": "~0.5.0", | ||
| "eslint": "^10.3.0", | ||
| "tslib": "^2.8.1", | ||
| "typescript": "^5.9.3", | ||
| "vite": "^8.0.10", | ||
| "vitest": "^4.1.5", | ||
| "typescript": "^6.0.3", | ||
| "vite": "^8.0.13", | ||
| "vitest": "^4.1.6", | ||
| "zod": "^4.4.3" | ||
@@ -58,0 +58,0 @@ }, |
170044
0.02%670
0.15%Updated
Updated
Updated
Updated
Updated
Updated
Updated