@xylabs/creatable 5.0.65 → 5.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/neutral/AbstractCreatable.d.ts +3 -1
- package/dist/neutral/AbstractCreatable.d.ts.map +1 -1
- package/dist/neutral/AbstractCreatableV2.d.ts +62 -0
- package/dist/neutral/AbstractCreatableV2.d.ts.map +1 -0
- package/dist/neutral/Creatable.d.ts +5 -0
- package/dist/neutral/Creatable.d.ts.map +1 -1
- package/dist/neutral/CreatableV2.d.ts +31 -0
- package/dist/neutral/CreatableV2.d.ts.map +1 -0
- package/dist/neutral/FactoryV2.d.ts +11 -0
- package/dist/neutral/FactoryV2.d.ts.map +1 -0
- package/dist/neutral/index.d.ts +1 -0
- package/dist/neutral/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +67 -0
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/neutral/model/CreatableInstance.d.ts +2 -1
- package/dist/neutral/model/CreatableInstance.d.ts.map +1 -1
- package/dist/neutral/model/CreatableInstanceV2.d.ts +14 -0
- package/dist/neutral/model/CreatableInstanceV2.d.ts.map +1 -0
- package/dist/neutral/model/CreatableName.d.ts +5 -0
- package/dist/neutral/model/CreatableName.d.ts.map +1 -0
- package/dist/neutral/model/CreatableParams.d.ts +1 -2
- package/dist/neutral/model/CreatableParams.d.ts.map +1 -1
- package/dist/neutral/model/CreatableParamsV2.d.ts +68 -0
- package/dist/neutral/model/CreatableParamsV2.d.ts.map +1 -0
- package/dist/neutral/model/CreatableStatusReporter.d.ts +7 -4
- package/dist/neutral/model/CreatableStatusReporter.d.ts.map +1 -1
- package/dist/neutral/model/CreatableStatusReporter.zod.d.ts +44 -0
- package/dist/neutral/model/CreatableStatusReporter.zod.d.ts.map +1 -0
- package/dist/neutral/model/CreatableStatusReporterV2.d.ts +7 -0
- package/dist/neutral/model/CreatableStatusReporterV2.d.ts.map +1 -0
- package/dist/neutral/model/index.d.ts +5 -0
- package/dist/neutral/model/index.d.ts.map +1 -1
- package/package.json +15 -9
- package/src/AbstractCreatable.ts +3 -1
- package/src/AbstractCreatableV2.ts +270 -0
- package/src/Creatable.ts +5 -0
- package/src/CreatableV2.ts +67 -0
- package/src/FactoryV2.ts +38 -0
- package/src/index.ts +1 -0
- package/src/model/CreatableInstance.ts +2 -1
- package/src/model/CreatableInstanceV2.ts +16 -0
- package/src/model/CreatableName.ts +3 -0
- package/src/model/CreatableParams.ts +1 -3
- package/src/model/CreatableParamsV2.ts +11 -0
- package/src/model/CreatableStatusReporter.ts +8 -4
- package/src/model/CreatableStatusReporter.zod.ts +31 -0
- package/src/model/CreatableStatusReporterV2.ts +11 -0
- package/src/model/index.ts +5 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const CreatableStatusSuccessZod: z.ZodEnum<{
|
|
3
|
+
creating: "creating";
|
|
4
|
+
created: "created";
|
|
5
|
+
starting: "starting";
|
|
6
|
+
started: "started";
|
|
7
|
+
stopping: "stopping";
|
|
8
|
+
stopped: "stopped";
|
|
9
|
+
}>;
|
|
10
|
+
export declare const CreatableStatusErrorZod: z.ZodEnum<{
|
|
11
|
+
error: "error";
|
|
12
|
+
}>;
|
|
13
|
+
export declare const CreatableStatusZod: z.ZodUnion<readonly [z.ZodEnum<{
|
|
14
|
+
creating: "creating";
|
|
15
|
+
created: "created";
|
|
16
|
+
starting: "starting";
|
|
17
|
+
started: "started";
|
|
18
|
+
stopping: "stopping";
|
|
19
|
+
stopped: "stopped";
|
|
20
|
+
}>, z.ZodEnum<{
|
|
21
|
+
error: "error";
|
|
22
|
+
}>]>;
|
|
23
|
+
export declare const CreatableStatusReporterV2Zod: z.ZodObject<{
|
|
24
|
+
report: z.ZodUnion<readonly [z.ZodFunction<z.ZodUnion<readonly [z.ZodTuple<[z.ZodString, z.ZodEnum<{
|
|
25
|
+
creating: "creating";
|
|
26
|
+
created: "created";
|
|
27
|
+
starting: "starting";
|
|
28
|
+
started: "started";
|
|
29
|
+
stopping: "stopping";
|
|
30
|
+
stopped: "stopped";
|
|
31
|
+
}>, z.ZodOptional<z.ZodNumber>], null>, z.ZodTuple<[z.ZodString, z.ZodEnum<{
|
|
32
|
+
error: "error";
|
|
33
|
+
}>, z.ZodCustom<Error, Error>], null>, z.ZodTuple<[z.ZodString, z.ZodUnion<readonly [z.ZodEnum<{
|
|
34
|
+
creating: "creating";
|
|
35
|
+
created: "created";
|
|
36
|
+
starting: "starting";
|
|
37
|
+
started: "started";
|
|
38
|
+
stopping: "stopping";
|
|
39
|
+
stopped: "stopped";
|
|
40
|
+
}>, z.ZodEnum<{
|
|
41
|
+
error: "error";
|
|
42
|
+
}>]>], null>]>, z.ZodVoid>]>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
//# sourceMappingURL=CreatableStatusReporter.zod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreatableStatusReporter.zod.d.ts","sourceRoot":"","sources":["../../../src/model/CreatableStatusReporter.zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,yBAAyB;;;;;;;EAAgF,CAAA;AAEtH,eAAO,MAAM,uBAAuB;;EAAoB,CAAA;AAExD,eAAO,MAAM,kBAAkB;;;;;;;;;IAAgE,CAAA;AAE/F,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;iBAsBvC,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type z from 'zod';
|
|
2
|
+
import type { CreatableStatusReporterV2Zod, CreatableStatusSuccessZod, CreatableStatusZod } from './CreatableStatusReporter.zod.ts';
|
|
3
|
+
export type CreatableStatusSuccessV2 = z.infer<typeof CreatableStatusSuccessZod>;
|
|
4
|
+
export type CreatableStatusErrorV2 = Extract<CreatableStatusV2, 'error'>;
|
|
5
|
+
export type CreatableStatusV2 = z.infer<typeof CreatableStatusZod>;
|
|
6
|
+
export type CreatableStatusReporterV2 = z.infer<typeof CreatableStatusReporterV2Zod>;
|
|
7
|
+
//# sourceMappingURL=CreatableStatusReporterV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreatableStatusReporterV2.d.ts","sourceRoot":"","sources":["../../../src/model/CreatableStatusReporterV2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,KAAK,EACV,4BAA4B,EAAE,yBAAyB,EAAE,kBAAkB,EAC5E,MAAM,kCAAkC,CAAA;AAEzC,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAChF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;AACxE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAElE,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export * from './CreatableInstance.ts';
|
|
2
|
+
export * from './CreatableInstanceV2.ts';
|
|
3
|
+
export * from './CreatableName.ts';
|
|
2
4
|
export * from './CreatableParams.ts';
|
|
5
|
+
export * from './CreatableParamsV2.ts';
|
|
3
6
|
export * from './CreatableStatusReporter.ts';
|
|
7
|
+
export * from './CreatableStatusReporter.zod.ts';
|
|
8
|
+
export * from './CreatableStatusReporterV2.ts';
|
|
4
9
|
export * from './Labels.ts';
|
|
5
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/model/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/model/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,kCAAkC,CAAA;AAChD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,aAAa,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xylabs/creatable",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.66",
|
|
4
4
|
"description": "Base functionality used throughout XY Labs TypeScript/JavaScript libraries",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -38,21 +38,27 @@
|
|
|
38
38
|
"!**/*.test.*"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@xylabs/assert": "~5.0.
|
|
42
|
-
"@xylabs/base": "~5.0.
|
|
43
|
-
"@xylabs/events": "~5.0.
|
|
44
|
-
"@xylabs/logger": "~5.0.
|
|
45
|
-
"@xylabs/promise": "~5.0.
|
|
46
|
-
"@xylabs/telemetry": "~5.0.
|
|
47
|
-
"@xylabs/typeof": "~5.0.
|
|
41
|
+
"@xylabs/assert": "~5.0.66",
|
|
42
|
+
"@xylabs/base": "~5.0.66",
|
|
43
|
+
"@xylabs/events": "~5.0.66",
|
|
44
|
+
"@xylabs/logger": "~5.0.66",
|
|
45
|
+
"@xylabs/promise": "~5.0.66",
|
|
46
|
+
"@xylabs/telemetry": "~5.0.66",
|
|
47
|
+
"@xylabs/typeof": "~5.0.66",
|
|
48
48
|
"async-mutex": "~0.5.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
+
"@opentelemetry/api": "^1.9.0",
|
|
51
52
|
"@xylabs/ts-scripts-yarn3": "~7.3.2",
|
|
52
53
|
"@xylabs/tsconfig": "~7.3.2",
|
|
53
54
|
"tslib": "~2.8.1",
|
|
54
55
|
"typescript": "~5.9.3",
|
|
55
|
-
"vitest": "~4.0.18"
|
|
56
|
+
"vitest": "~4.0.18",
|
|
57
|
+
"zod": "^4.3.6"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@opentelemetry/api": "^1",
|
|
61
|
+
"zod": "^4"
|
|
56
62
|
},
|
|
57
63
|
"publishConfig": {
|
|
58
64
|
"access": "public"
|
package/src/AbstractCreatable.ts
CHANGED
|
@@ -17,8 +17,9 @@ import {
|
|
|
17
17
|
} from './Creatable.ts'
|
|
18
18
|
import { Factory } from './Factory.ts'
|
|
19
19
|
import { getFunctionName, getRootFunction } from './lib/index.ts'
|
|
20
|
+
import { CreatableName } from './model/CreatableName.ts'
|
|
20
21
|
import type {
|
|
21
|
-
CreatableInstance,
|
|
22
|
+
CreatableInstance, CreatableParams,
|
|
22
23
|
CreatableStatus,
|
|
23
24
|
Labels,
|
|
24
25
|
RequiredCreatableParams,
|
|
@@ -27,6 +28,7 @@ import type {
|
|
|
27
28
|
const AbstractCreatableConstructorKey = Symbol.for('AbstractCreatableConstructor')
|
|
28
29
|
const CREATABLE_NOT_STARTED = 'Creatable not Started' as const
|
|
29
30
|
|
|
31
|
+
/** @deprecated use AbstractCreatableV2 instead */
|
|
30
32
|
@creatable()
|
|
31
33
|
export class AbstractCreatable<TParams extends CreatableParams = CreatableParams,
|
|
32
34
|
TEventData extends EventData = EventData> extends BaseEmitter<Partial<TParams & RequiredCreatableParams>, TEventData> {
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import type { BaseEmitterParamsV2, EventData } from '@xylabs/events'
|
|
3
|
+
import { BaseEmitterV2 } from '@xylabs/events'
|
|
4
|
+
import { type Logger } from '@xylabs/logger'
|
|
5
|
+
import type { Promisable } from '@xylabs/promise'
|
|
6
|
+
import type { SpanConfig } from '@xylabs/telemetry'
|
|
7
|
+
import { spanRoot, spanRootAsync } from '@xylabs/telemetry'
|
|
8
|
+
import {
|
|
9
|
+
isError, isNumber, isString,
|
|
10
|
+
isUndefined,
|
|
11
|
+
} from '@xylabs/typeof'
|
|
12
|
+
import { Mutex } from 'async-mutex'
|
|
13
|
+
|
|
14
|
+
import type { CreatableFactoryV2, CreatableV2 } from './CreatableV2.ts'
|
|
15
|
+
import { FactoryV2 } from './FactoryV2.ts'
|
|
16
|
+
import { getFunctionName, getRootFunction } from './lib/index.ts'
|
|
17
|
+
import type {
|
|
18
|
+
CreatableInstanceV2,
|
|
19
|
+
CreatableName, CreatableParamsV2,
|
|
20
|
+
CreatableStatusV2,
|
|
21
|
+
Labels,
|
|
22
|
+
} from './model/index.ts'
|
|
23
|
+
|
|
24
|
+
const AbstractCreatableConstructorKey = Symbol.for('AbstractCreatableConstructor')
|
|
25
|
+
const CREATABLE_NOT_STARTED = 'Creatable not Started' as const
|
|
26
|
+
|
|
27
|
+
export abstract class AbstractCreatableV2<TParams extends CreatableParamsV2 = CreatableParamsV2,
|
|
28
|
+
TEventData extends EventData = EventData> extends BaseEmitterV2<TParams, TEventData> {
|
|
29
|
+
defaultLogger?: Logger
|
|
30
|
+
|
|
31
|
+
protected _startPromise: Promisable<boolean> | undefined
|
|
32
|
+
private _status: CreatableStatusV2 | null = null
|
|
33
|
+
private _statusMutex = new Mutex()
|
|
34
|
+
private _validatedParams?: TParams & BaseEmitterParamsV2
|
|
35
|
+
|
|
36
|
+
constructor(key: unknown, params: TParams) {
|
|
37
|
+
assertEx(key === AbstractCreatableConstructorKey, () => 'AbstractCreatable should not be instantiated directly, use the static create method instead')
|
|
38
|
+
super(params)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override get context(): TParams['context'] & BaseEmitterParamsV2['context'] {
|
|
42
|
+
return this.params.context
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get name(): CreatableName {
|
|
46
|
+
return this.params.name as CreatableName
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override get params(): TParams & BaseEmitterParamsV2 {
|
|
50
|
+
this._validatedParams = this._validatedParams ?? this.paramsValidator(super.params)
|
|
51
|
+
return assertEx(this._validatedParams)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get startable() {
|
|
55
|
+
return this.status === 'created' || this.status === 'stopped'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get status(): CreatableStatusV2 | null {
|
|
59
|
+
return this._status
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get statusReporter() {
|
|
63
|
+
return this.context.statusReporter
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
abstract override get className(): CreatableName
|
|
67
|
+
|
|
68
|
+
static async create<T extends CreatableInstanceV2>(
|
|
69
|
+
this: CreatableV2<T>,
|
|
70
|
+
inParams: Partial<T['params']> = {},
|
|
71
|
+
): Promise<T> {
|
|
72
|
+
const params = await this.paramsHandler(inParams)
|
|
73
|
+
const name = (params.name ?? this.name) as CreatableName
|
|
74
|
+
try {
|
|
75
|
+
const instance = new this(AbstractCreatableConstructorKey, params)
|
|
76
|
+
instance.setStatus('creating')
|
|
77
|
+
const initializedInstance = await this.createHandler(instance)
|
|
78
|
+
await instance.createHandler()
|
|
79
|
+
instance.setStatus('created')
|
|
80
|
+
return initializedInstance
|
|
81
|
+
} catch (ex) {
|
|
82
|
+
params.context.statusReporter?.report(name, 'error', isError(ex) ? ex : new Error(`Error creating: ${name}`))
|
|
83
|
+
params.context.logger?.error(`Error creating creatable [${name}]: ${(isError(ex) ? `${ex.message} ${ex.stack}` : ex)}`)
|
|
84
|
+
throw isError(ex) ? ex : new Error(`Error creating: ${name}`)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static createHandler<T extends CreatableInstanceV2>(
|
|
89
|
+
this: CreatableV2<T>,
|
|
90
|
+
instance: T,
|
|
91
|
+
): Promisable<T> {
|
|
92
|
+
return instance
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static paramsHandler<T extends CreatableInstanceV2>(
|
|
96
|
+
this: CreatableV2<T>,
|
|
97
|
+
params: Partial<T['params']> = {},
|
|
98
|
+
): Promisable<T['params']> {
|
|
99
|
+
return { ...params } as T['params']
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
createHandler(): Promisable<void> {
|
|
103
|
+
assertEx(this._status === 'creating', () => `createHandler can not be called [status = ${this.status}]`)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
paramsValidator(params: Partial<TParams>): TParams {
|
|
107
|
+
return { ...params, name: params.name } as TParams
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
span<T>(name: string, fn: () => T): T {
|
|
111
|
+
return spanRoot(name, fn, this.tracer)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async spanAsync<T>(name: string, fn: () => Promise<T>, config: SpanConfig = {}): Promise<T> {
|
|
115
|
+
return await spanRootAsync(name, fn, {
|
|
116
|
+
...config, tracer: config.tracer ?? this.tracer, logger: config.logger ?? this.defaultLogger,
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async start(): Promise<boolean> {
|
|
121
|
+
this._noOverride('start')
|
|
122
|
+
if (this.status === 'started') {
|
|
123
|
+
return true
|
|
124
|
+
}
|
|
125
|
+
return await this._statusMutex.runExclusive(async () => {
|
|
126
|
+
try {
|
|
127
|
+
// check again in case it changed
|
|
128
|
+
if (this.status === 'started') {
|
|
129
|
+
return true
|
|
130
|
+
}
|
|
131
|
+
assertEx(this.startable, () => `Creatable [${this.name}] is not startable in status [${this.status}]`)
|
|
132
|
+
this.setStatus('starting')
|
|
133
|
+
await this.startHandler()
|
|
134
|
+
this.setStatus('started')
|
|
135
|
+
return true
|
|
136
|
+
} catch (ex) {
|
|
137
|
+
this.setStatus('error', isError(ex) ? ex : new Error(`Error starting: ${ex}`))
|
|
138
|
+
this.logger?.error(`Error starting creatable [${this.name}]: ${(isError(ex) ? `${ex.message} ${ex.stack}` : ex)}`)
|
|
139
|
+
return false
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
started(notStartedAction: 'error' | 'throw' | 'warn' | 'log' | 'none' = 'log'): boolean {
|
|
145
|
+
if (isString(this.status) && this.status === 'started') {
|
|
146
|
+
return true
|
|
147
|
+
} else {
|
|
148
|
+
const message = () => `${CREATABLE_NOT_STARTED} [${this.name}] current state: ${this.status}`
|
|
149
|
+
switch (notStartedAction) {
|
|
150
|
+
case 'error': {
|
|
151
|
+
throw new Error(message())
|
|
152
|
+
}
|
|
153
|
+
case 'throw': {
|
|
154
|
+
throw new Error(message())
|
|
155
|
+
}
|
|
156
|
+
case 'warn': {
|
|
157
|
+
this.logger?.warn(message())
|
|
158
|
+
break
|
|
159
|
+
}
|
|
160
|
+
case 'log': {
|
|
161
|
+
this.logger?.log(message())
|
|
162
|
+
break
|
|
163
|
+
}
|
|
164
|
+
case 'none': {
|
|
165
|
+
break
|
|
166
|
+
}
|
|
167
|
+
default: {
|
|
168
|
+
throw new Error(`Unknown notStartedAction: ${notStartedAction}`)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return false
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async startedAsync(notStartedAction: 'error' | 'throw' | 'warn' | 'log' | 'none' = 'log', tryStart = true): Promise<boolean> {
|
|
176
|
+
if (isString(this.status) && this.status === 'started') {
|
|
177
|
+
return true
|
|
178
|
+
} else if (this.status === 'created' || this.status === 'stopped' || this.status === 'starting') {
|
|
179
|
+
// using promise as mutex
|
|
180
|
+
this._startPromise = this._startPromise ?? (async () => {
|
|
181
|
+
if (tryStart) {
|
|
182
|
+
try {
|
|
183
|
+
return await this.start()
|
|
184
|
+
} finally {
|
|
185
|
+
this._startPromise = undefined
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return this.started(notStartedAction)
|
|
189
|
+
})()
|
|
190
|
+
} else {
|
|
191
|
+
const message = `${CREATABLE_NOT_STARTED} [${this.name}] current state: ${this.status}`
|
|
192
|
+
throw new Error(message)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (isUndefined(this._startPromise)) {
|
|
196
|
+
throw new Error(`Failed to create start promise: ${this.status}`)
|
|
197
|
+
}
|
|
198
|
+
return await this._startPromise
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async stop(): Promise<boolean> {
|
|
202
|
+
this._noOverride('stop')
|
|
203
|
+
if (this.status === 'stopped') {
|
|
204
|
+
return true
|
|
205
|
+
}
|
|
206
|
+
return await this._statusMutex.runExclusive(async () => {
|
|
207
|
+
try {
|
|
208
|
+
// check again in case it changed
|
|
209
|
+
if (this.status === 'stopped') {
|
|
210
|
+
return true
|
|
211
|
+
}
|
|
212
|
+
assertEx(this.status === 'started', () => `Creatable [${this.name}] is not stoppable in status [${this.status}]`)
|
|
213
|
+
this.setStatus('stopping')
|
|
214
|
+
await this.stopHandler()
|
|
215
|
+
this.setStatus('stopped')
|
|
216
|
+
return true
|
|
217
|
+
} catch (ex) {
|
|
218
|
+
this.setStatus('error', isError(ex) ? ex : new Error(`Error stopping: ${ex}`))
|
|
219
|
+
return false
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
protected _noOverride(functionName = getFunctionName(3)) {
|
|
225
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
226
|
+
const thisFunc = (this as any)[functionName]
|
|
227
|
+
|
|
228
|
+
const rootFunc = getRootFunction(this, functionName)
|
|
229
|
+
assertEx(thisFunc === rootFunc, () => `Override not allowed for [${functionName}] - override ${functionName}Handler instead`)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
protected setStatus(value: Exclude<CreatableStatusV2, 'error'>, progress?: number): void
|
|
233
|
+
protected setStatus(value: Extract<CreatableStatusV2, 'error'>, error?: Error): void
|
|
234
|
+
protected setStatus(value: CreatableStatusV2, progressOrError?: number | Error): void {
|
|
235
|
+
this._status = value
|
|
236
|
+
if (value !== null) {
|
|
237
|
+
if (value === 'error') {
|
|
238
|
+
if (isError(progressOrError)) {
|
|
239
|
+
this.statusReporter?.report(this.name, value, progressOrError)
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
if (isNumber(progressOrError)) {
|
|
244
|
+
this.statusReporter?.report(this.name, value, progressOrError)
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
this.statusReporter?.report(this.name, value)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
protected startHandler(): Promisable<void> {
|
|
253
|
+
// when overriding this, throw an error on failure
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
protected stopHandler(): Promisable<void> {
|
|
257
|
+
// when overriding this, throw an error on failure
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export abstract class AbstractCreatableWithFactoryV2<TParams extends CreatableParamsV2 = CreatableParamsV2,
|
|
262
|
+
TEventData extends EventData = EventData> extends AbstractCreatableV2<TParams, TEventData> {
|
|
263
|
+
static factory<T extends CreatableInstanceV2>(
|
|
264
|
+
this: CreatableV2<T>,
|
|
265
|
+
params?: Partial<T['params']>,
|
|
266
|
+
labels?: Labels,
|
|
267
|
+
): CreatableFactoryV2<T> {
|
|
268
|
+
return FactoryV2.withParams<T>(this, params, labels)
|
|
269
|
+
}
|
|
270
|
+
}
|
package/src/Creatable.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
RequiredCreatableParams,
|
|
8
8
|
} from './model/index.ts'
|
|
9
9
|
|
|
10
|
+
/** @deprecated use CreatableFactoryV2 instead */
|
|
10
11
|
export interface CreatableFactory<T extends CreatableInstance = CreatableInstance>
|
|
11
12
|
extends Omit<Creatable<T>, 'create' | 'createHandler' | 'paramsHandler' | 'defaultLogger' | 'factory'> {
|
|
12
13
|
|
|
@@ -15,6 +16,7 @@ export interface CreatableFactory<T extends CreatableInstance = CreatableInstanc
|
|
|
15
16
|
params?: Partial<T['params']>): Promise<T>
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
/** @deprecated use CreatableV2 instead */
|
|
18
20
|
export interface Creatable<T extends CreatableInstance = CreatableInstance> {
|
|
19
21
|
|
|
20
22
|
defaultLogger?: Logger
|
|
@@ -34,6 +36,7 @@ export interface Creatable<T extends CreatableInstance = CreatableInstance> {
|
|
|
34
36
|
this: Creatable<T>, params?: Partial<T['params']>): Promisable<T['params'] & RequiredCreatableParams>
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
/** @deprecated use CreatableWithFactoryV2 instead */
|
|
37
40
|
export interface CreatableWithFactory<T extends CreatableInstance = CreatableInstance> extends Creatable<T> {
|
|
38
41
|
factory<T extends CreatableInstance>(
|
|
39
42
|
this: Creatable<T>,
|
|
@@ -47,6 +50,7 @@ export interface CreatableWithFactory<T extends CreatableInstance = CreatableIns
|
|
|
47
50
|
* @returns The decorated Module requiring it implement the members
|
|
48
51
|
* of the CreatableModule as statics properties/methods
|
|
49
52
|
*/
|
|
53
|
+
/** @deprecated use creatableV2 instead */
|
|
50
54
|
export function creatable<T extends CreatableInstance>() {
|
|
51
55
|
return <U extends Creatable<T>>(constructor: U) => {
|
|
52
56
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
@@ -61,6 +65,7 @@ export function creatable<T extends CreatableInstance>() {
|
|
|
61
65
|
* of the CreatableModule as statics properties/methods
|
|
62
66
|
*/
|
|
63
67
|
|
|
68
|
+
/** @deprecated use creatableFactoryV2 instead */
|
|
64
69
|
export function creatableFactory() {
|
|
65
70
|
return <U extends CreatableFactory>(constructor: U) => {
|
|
66
71
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Logger } from '@xylabs/logger'
|
|
2
|
+
import type { Promisable } from '@xylabs/promise'
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
CreatableInstanceV2, CreatableParamsV2, Labels,
|
|
6
|
+
} from './model/index.ts'
|
|
7
|
+
|
|
8
|
+
export interface CreatableFactoryV2<T extends CreatableInstanceV2 = CreatableInstanceV2>
|
|
9
|
+
extends Omit<CreatableV2<T>, 'create' | 'createHandler' | 'paramsHandler' | 'defaultLogger' | 'factory'> {
|
|
10
|
+
|
|
11
|
+
create(
|
|
12
|
+
this: CreatableFactoryV2<T>,
|
|
13
|
+
params?: Partial<T['params']>): Promise<T>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CreatableV2<T extends CreatableInstanceV2 = CreatableInstanceV2> {
|
|
17
|
+
|
|
18
|
+
defaultLogger?: Logger
|
|
19
|
+
|
|
20
|
+
new(key: unknown, params: Partial<CreatableParamsV2>): T
|
|
21
|
+
|
|
22
|
+
create<T extends CreatableInstanceV2>(
|
|
23
|
+
this: CreatableV2<T>,
|
|
24
|
+
params?: Partial<T['params']>): Promise<T>
|
|
25
|
+
|
|
26
|
+
createHandler<T extends CreatableInstanceV2>(
|
|
27
|
+
this: CreatableV2<T>,
|
|
28
|
+
instance: T
|
|
29
|
+
): Promisable<T>
|
|
30
|
+
|
|
31
|
+
paramsHandler<T extends CreatableInstanceV2>(
|
|
32
|
+
this: CreatableV2<T>, params?: Partial<T['params']>): Promisable<T['params']>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface CreatableWithFactoryV2<T extends CreatableInstanceV2 = CreatableInstanceV2> extends CreatableV2<T> {
|
|
36
|
+
factory<T extends CreatableInstanceV2>(
|
|
37
|
+
this: CreatableV2<T>,
|
|
38
|
+
params?: Partial<T['params']>,
|
|
39
|
+
labels?: Labels): CreatableFactoryV2<T>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Class annotation to be used to decorate Modules which support
|
|
44
|
+
* an asynchronous creation pattern
|
|
45
|
+
* @returns The decorated Module requiring it implement the members
|
|
46
|
+
* of the CreatableModule as statics properties/methods
|
|
47
|
+
*/
|
|
48
|
+
export function creatableV2<T extends CreatableInstanceV2>() {
|
|
49
|
+
return <U extends CreatableV2<T>>(constructor: U) => {
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
51
|
+
constructor
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Class annotation to be used to decorate Modules which support
|
|
57
|
+
* an asynchronous creation factory pattern
|
|
58
|
+
* @returns The decorated Module requiring it implement the members
|
|
59
|
+
* of the CreatableModule as statics properties/methods
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
export function creatableFactoryV2() {
|
|
63
|
+
return <U extends CreatableFactoryV2>(constructor: U) => {
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
65
|
+
constructor
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/FactoryV2.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CreatableFactoryV2, CreatableV2 } from './CreatableV2.ts'
|
|
2
|
+
import type {
|
|
3
|
+
CreatableInstanceV2, Labels, WithOptionalLabels,
|
|
4
|
+
} from './model/index.ts'
|
|
5
|
+
|
|
6
|
+
export class FactoryV2<T extends CreatableInstanceV2 = CreatableInstanceV2> implements CreatableFactoryV2<T> {
|
|
7
|
+
creatable: CreatableV2<T>
|
|
8
|
+
|
|
9
|
+
defaultParams?: Partial<T['params']>
|
|
10
|
+
|
|
11
|
+
labels?: Labels
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
creatable: CreatableV2<T>,
|
|
15
|
+
params?: Partial<T['params']>,
|
|
16
|
+
labels: Labels = {},
|
|
17
|
+
) {
|
|
18
|
+
this.creatable = creatable
|
|
19
|
+
this.defaultParams = params
|
|
20
|
+
this.labels = Object.assign({}, (creatable as WithOptionalLabels).labels ?? {}, labels ?? {})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static withParams<T extends CreatableInstanceV2>(
|
|
24
|
+
creatableModule: CreatableV2<T>,
|
|
25
|
+
params?: Partial<T['params']>,
|
|
26
|
+
labels: Labels = {},
|
|
27
|
+
) {
|
|
28
|
+
return new FactoryV2<T>(creatableModule, params, labels)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
create(params?: Partial<T['params']>): Promise<T> {
|
|
32
|
+
const mergedParams: T['params'] = {
|
|
33
|
+
...this.defaultParams,
|
|
34
|
+
...params,
|
|
35
|
+
} as T['params']
|
|
36
|
+
return this.creatable.create<T>(mergedParams)
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EventData, EventEmitter } from '@xylabs/events'
|
|
2
2
|
|
|
3
|
-
import type { CreatableName
|
|
3
|
+
import type { CreatableName } from './CreatableName.ts'
|
|
4
|
+
import type { CreatableParams } from './CreatableParams.ts'
|
|
4
5
|
|
|
5
6
|
export interface CreatableInstance<TParams extends CreatableParams = CreatableParams,
|
|
6
7
|
TEventData extends EventData = EventData> extends EventEmitter<TEventData> {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { EventData, EventEmitter } from '@xylabs/events'
|
|
2
|
+
import type { Promisable } from '@xylabs/promise'
|
|
3
|
+
|
|
4
|
+
import type { CreatableName } from './CreatableName.ts'
|
|
5
|
+
import type { CreatableParamsV2 } from './CreatableParamsV2.ts'
|
|
6
|
+
|
|
7
|
+
export interface CreatableInstanceV2<TParams extends CreatableParamsV2 = CreatableParamsV2,
|
|
8
|
+
TEventData extends EventData = EventData> extends EventEmitter<TEventData> {
|
|
9
|
+
createHandler: () => Promisable<void>
|
|
10
|
+
eventData: TEventData
|
|
11
|
+
name: CreatableName
|
|
12
|
+
params: TParams
|
|
13
|
+
setStatus: (status: string) => void
|
|
14
|
+
start: () => Promise<boolean>
|
|
15
|
+
stop: () => Promise<boolean>
|
|
16
|
+
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import type { BaseClassName } from '@xylabs/base'
|
|
2
1
|
import type { BaseEmitterParams } from '@xylabs/events'
|
|
3
2
|
|
|
3
|
+
import type { CreatableName } from './CreatableName.ts'
|
|
4
4
|
import type { CreatableStatus, CreatableStatusReporter } from './CreatableStatusReporter.ts'
|
|
5
5
|
|
|
6
|
-
export type CreatableName = Exclude<string, 'creatable-name-reserved-32546239486'> & BaseClassName
|
|
7
|
-
|
|
8
6
|
export interface RequiredCreatableParams<TAdditionalStatus extends CreatableStatus | void = void> extends BaseEmitterParams {
|
|
9
7
|
name?: CreatableName
|
|
10
8
|
statusReporter?: CreatableStatusReporter<TAdditionalStatus>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseContextZod } from '@xylabs/base'
|
|
2
|
+
import { BaseEmitterParamsV2Zod } from '@xylabs/events'
|
|
3
|
+
import z from 'zod'
|
|
4
|
+
|
|
5
|
+
import { CreatableStatusReporterV2Zod } from './CreatableStatusReporter.zod.ts'
|
|
6
|
+
|
|
7
|
+
export const CreatableContext = z.intersection(BaseContextZod, z.object({ name: z.string(), statusReporter: CreatableStatusReporterV2Zod.optional() }))
|
|
8
|
+
|
|
9
|
+
export const CreatableParamsV2Zod = BaseEmitterParamsV2Zod.extend(z.object({ context: CreatableContext, name: z.string() }).shape)
|
|
10
|
+
|
|
11
|
+
export type CreatableParamsV2 = z.infer<typeof CreatableParamsV2Zod>
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CreatableName } from './CreatableName.ts'
|
|
2
2
|
|
|
3
|
+
/** @deprecated use CreatableStatusReporterV2 instead */
|
|
3
4
|
export type StandardCreatableStatus = 'creating' | 'created' | 'starting' | 'started' | 'stopping' | 'stopped' | 'error'
|
|
5
|
+
|
|
6
|
+
/** @deprecated use CreatableStatusReporterV2 instead */
|
|
4
7
|
export type CreatableStatus<TAdditionalStatus extends void | string = void>
|
|
5
8
|
= StandardCreatableStatus | (TAdditionalStatus extends void ? StandardCreatableStatus : TAdditionalStatus)
|
|
6
9
|
|
|
10
|
+
/** @deprecated use CreatableStatusReporterV2 instead */
|
|
7
11
|
export interface CreatableStatusReporter<TAdditionalStatus extends void | string = void> {
|
|
8
|
-
report(name:
|
|
9
|
-
report(name:
|
|
10
|
-
report(name:
|
|
12
|
+
report(name: CreatableName, status: Exclude<CreatableStatus<TAdditionalStatus>, 'error'>, progress: number): void
|
|
13
|
+
report(name: CreatableName, status: Extract<CreatableStatus<TAdditionalStatus>, 'error'>, error: Error): void
|
|
14
|
+
report(name: CreatableName, status: CreatableStatus<TAdditionalStatus>): void
|
|
11
15
|
}
|