@feasibleone/blong 1.12.0 → 1.12.1

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +1 -1
  3. package/types.ts +711 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.12.1](https://github.com/feasibleone/blong/compare/blong-v1.12.0...blong-v1.12.1) (2026-03-15)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * missing types.ts ([9903425](https://github.com/feasibleone/blong/commit/9903425a4f54e8f9c935b00b2e30e26ddcb11483))
9
+
3
10
  ## [1.12.0](https://github.com/feasibleone/blong/compare/blong-v1.11.0...blong-v1.12.0) (2026-03-15)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feasibleone/blong",
3
- "version": "1.12.0",
3
+ "version": "1.12.1",
4
4
  "description": "API and DRY focused RAD framework https://feasibleone.github.io/blong-docs",
5
5
  "keywords": [
6
6
  "blong",
package/types.ts ADDED
@@ -0,0 +1,711 @@
1
+ // import type {S3Client} from '@aws-sdk/client-s3';
2
+ import type KeycloakAdminClient from '@keycloak/keycloak-admin-client';
3
+ // import {
4
+ // AppsV1Api,
5
+ // CoreV1Api,
6
+ // NetworkingV1Api,
7
+ // RbacAuthorizationV1Api,
8
+ // Watch,
9
+ // } from '@kubernetes/client-node';
10
+ import type {IncomingWebhook} from '@slack/webhook';
11
+ import type {MongoClient} from 'mongodb';
12
+ import type Assert from 'node:assert';
13
+ import {
14
+ Type,
15
+ type Static,
16
+ type TArray,
17
+ type TBoolean,
18
+ type TFunction,
19
+ type TNever,
20
+ type TNumber,
21
+ type TObject,
22
+ type TSchema,
23
+ type TString,
24
+ type TUnknown,
25
+ } from 'typebox';
26
+ // import type {client} from 'node-vault';
27
+ import type {Dirent} from 'node:fs';
28
+ import type {Duplex} from 'node:stream';
29
+ import type {OpenAPI, OpenAPIV2, OpenAPIV3_1} from 'openapi-types';
30
+ import type {Level, LogFn, Logger as PinoLogger} from 'pino';
31
+ import merge from 'ut-function.merge';
32
+ import type {Knex} from './knex.js';
33
+
34
+ // export {
35
+ // AppsV1Api,
36
+ // CoreV1Api,
37
+ // NetworkingV1Api,
38
+ // RbacAuthorizationV1Api,
39
+ // Watch,
40
+ // } from '@kubernetes/client-node';
41
+ export type * from '@slack/webhook';
42
+ export type * from 'bson';
43
+ export type * from 'mongodb';
44
+ // export type {client} from 'node-vault';
45
+ export type {IJsonSchema, OpenAPI, OpenAPIV2, OpenAPIV3, OpenAPIV3_1} from 'openapi-types';
46
+ // export type {Level, LogFn, Logger as PinoLogger} from 'pino';
47
+ export type {Knex} from './knex.js';
48
+
49
+ export type ServerContext = {
50
+ queryBuilder?: Knex;
51
+ // coreV1Api?: CoreV1Api;
52
+ // appsV1Api?: AppsV1Api;
53
+ // networkingV1Api?: NetworkingV1Api;
54
+ // rbacV1Api?: RbacAuthorizationV1Api;
55
+ // watcher?: Watch;
56
+ kcAdminClient?: KeycloakAdminClient;
57
+ kafkaStream?: Duplex;
58
+ mongodb?: MongoClient;
59
+ // s3?: S3Client;
60
+ slack?: IncomingWebhook;
61
+ // vault?: client;
62
+ };
63
+
64
+ export type BrowserContext = {};
65
+
66
+ export type AdapterContext = ServerContext & BrowserContext;
67
+
68
+ export interface ILog {
69
+ logger: (level: Level, bindings: object) => ILogger;
70
+ child: PinoLogger['child'];
71
+ }
72
+
73
+ export interface IErrorFactory {
74
+ get(type?: string): unknown;
75
+ fetch(type: string): object;
76
+ define(
77
+ id: string,
78
+ superType: string | {type: string},
79
+ message: string,
80
+ ): (params?: unknown, $meta?: IMeta) => ITypedError;
81
+ register<T>(errorsMap: T): Record<keyof T, (params?: unknown, $meta?: IMeta) => ITypedError>;
82
+ }
83
+
84
+ export interface IError {
85
+ getError: IErrorFactory['get'];
86
+ fetchErrors: IErrorFactory['fetch'];
87
+ defineError: IErrorFactory['define'];
88
+ register: IErrorFactory['register'];
89
+ }
90
+
91
+ export type Config<T, C> = {
92
+ id: string;
93
+ type: string;
94
+ pkg: {
95
+ name: string;
96
+ version: string;
97
+ };
98
+ format?: {
99
+ sizeAdjust?: number;
100
+ };
101
+ context: C;
102
+ debug: boolean;
103
+ test: boolean;
104
+ disconnectOnError: boolean;
105
+ concurrency: number;
106
+ log: object;
107
+ maxReceiveBuffer: number;
108
+ logLevel: Parameters<ILog['logger']>[0];
109
+ namespace: string | string[];
110
+ imports: string | RegExp | (string | RegExp)[];
111
+ } & T;
112
+
113
+ export type RemoteMethod = (...params: unknown[]) => Promise<unknown>;
114
+ export interface IRemote {
115
+ remote: (methodName: string, options?: object) => RemoteMethod;
116
+ dispatch: (...params: unknown[]) => boolean | Promise<unknown>;
117
+ start: () => Promise<IRemote>;
118
+ stop: () => Promise<IRemote>;
119
+ }
120
+
121
+ export interface IRpcServer {
122
+ register: (methods: object, namespace: string, reply: boolean, pkg: {version: string}) => void;
123
+ unregister: (methods: string[], namespace: string, reply: boolean) => void;
124
+ start: () => Promise<IRpcServer>;
125
+ stop: () => Promise<IRpcServer>;
126
+ }
127
+
128
+ export interface ILocal {
129
+ register: (methods: object, namespace: string, reply: boolean, pkg: {version: string}) => void;
130
+ unregister: (methods: string[], namespace: string) => void;
131
+ get: (name: string) => {method: (...params: unknown[]) => Promise<unknown[]>};
132
+ }
133
+
134
+ export interface IApiSchema {
135
+ schema(
136
+ def: {namespace?: Record<string, string | string[]> | string[]; url?: string},
137
+ source: string,
138
+ ): Promise<Record<string, GatewaySchema>>;
139
+ generateFile(file: string): Promise<boolean>;
140
+ generateDir(dir: string, files: Dirent[]): Promise<boolean>;
141
+ }
142
+
143
+ export interface IGateway {
144
+ route: (
145
+ validations: Record<string, GatewaySchema>,
146
+ pkg: {name: string; version: string},
147
+ ) => void;
148
+ start: () => Promise<IGateway>;
149
+ stop: () => Promise<IGateway>;
150
+ }
151
+
152
+ export type Handlers = ((params: {
153
+ remote: unknown;
154
+ lib: object;
155
+ port: object;
156
+ local: object;
157
+ literals: object[];
158
+ gateway: IGateway;
159
+ }) => void)[];
160
+
161
+ export interface IRegistry {
162
+ start: (configOverride?: object) => Promise<IRegistry>;
163
+ test: (tester?: unknown) => Promise<void>;
164
+ stop: () => Promise<IRegistry>;
165
+ ports: Map<string, IAdapterFactory>;
166
+ methods: Map<string, Handlers>;
167
+ modules: Map<string | symbol, IRegistry[]>;
168
+ createPort: (id: string) => Promise<ReturnType<IAdapterFactory>>;
169
+ replaceHandlers: (id: string, handlers: object) => Promise<void>;
170
+ loadApi: (
171
+ id: string,
172
+ def: {
173
+ namespace: Record<string, string | string[]>;
174
+ },
175
+ source?: string,
176
+ ) => Promise<void>;
177
+ connected: () => Promise<boolean>;
178
+ }
179
+
180
+ export interface IApi {
181
+ id?: string;
182
+ type: typeof Type;
183
+ adapter: (
184
+ id: string,
185
+ ) => (api: {
186
+ utError: IError;
187
+ remote: IRemote;
188
+ rpc: IRpcServer;
189
+ local: ILocal;
190
+ registry: IRegistry;
191
+ }) => object;
192
+ utError: IError;
193
+ errors: IErrorFactory;
194
+ gateway: unknown;
195
+ remote: IRemote;
196
+ rpc: IRpcServer;
197
+ local: ILocal;
198
+ registry: IRegistry;
199
+ utBus: {
200
+ config: object;
201
+ register: (methods: object, namespace: string, id: string, pkg: {version: string}) => void;
202
+ unregister: (methods: string[], namespace: string) => void;
203
+ subscribe: (methods: object, namespace: string, id: string, pkg: {version: string}) => void;
204
+ unsubscribe: (methods: string[], namespace: string) => void;
205
+ dispatch: (...params: unknown[]) => boolean | Promise<unknown>;
206
+ methodId: (name: string) => string;
207
+ getPath: (name: string) => string;
208
+ importMethod: (
209
+ methodName: string,
210
+ options?: object,
211
+ ) => (...params: unknown[]) => Promise<unknown>;
212
+ attachHandlers: (target: object, patterns: unknown, adapter?: boolean) => unknown;
213
+ };
214
+ utLog: {
215
+ createLog: ILog['logger'];
216
+ };
217
+ handlers?: (api: {utError: IError; remote: IRemote; type: typeof Type}) => {
218
+ extends?:
219
+ | string
220
+ | ((api: {
221
+ utError: IError;
222
+ remote: IRemote;
223
+ rpc: IRpcServer;
224
+ local: ILocal;
225
+ registry: IRegistry;
226
+ }) => object);
227
+ };
228
+ }
229
+
230
+ export interface IErrorMap {
231
+ [name: string]:
232
+ | string
233
+ | {
234
+ message: string;
235
+ print?: string;
236
+ statusCode?: number;
237
+ };
238
+ }
239
+
240
+ export interface IAdapter<T, C> {
241
+ validation?: TSchema;
242
+ config?: Config<T, C>;
243
+ activation?: IActivationConfig<Partial<Config<T, C>>>;
244
+ configBase?: string;
245
+ log?: ILogger;
246
+ errors?: Errors<IErrorMap>;
247
+ imported?: ReturnType<IAdapterFactory<T, C>>;
248
+ extends?: object | `adapter.${string}` | `orchestrator.${string}`;
249
+ activeConfig?: (this: ReturnType<IAdapterFactory<T, C>>) => Partial<Config<T, C>>;
250
+ init?: (
251
+ this: ReturnType<IAdapterFactory<T, C>>,
252
+ ...config: Partial<Config<T, C>>[]
253
+ ) => Promise<void>;
254
+ start?: (this: ReturnType<IAdapterFactory<T, C>>, configOverride: object) => Promise<object>;
255
+ ready?: (this: ReturnType<IAdapterFactory<T, C>>) => Promise<object>;
256
+ stop?: (this: ReturnType<IAdapterFactory<T, C>>) => Promise<object>;
257
+ connected?: (this: ReturnType<IAdapterFactory<T, C>>) => Promise<boolean>;
258
+ error?: (error: Error, $meta: IMeta) => void;
259
+ pack?: (
260
+ this: ReturnType<IAdapterFactory<T, C>>,
261
+ packet: {size: number; data: Buffer},
262
+ ) => Buffer;
263
+ unpackSize?: (
264
+ this: ReturnType<IAdapterFactory<T, C>>,
265
+ buffer: Buffer,
266
+ ) => {size: number; data: Buffer};
267
+ unpack?: (
268
+ this: ReturnType<IAdapterFactory<T, C>>,
269
+ buffer: Buffer,
270
+ options?: {size: number},
271
+ ) => Buffer;
272
+ encode?: (data: unknown, $meta: IMeta, context: object, log: ILogger) => string | Buffer;
273
+ decode?: (buff: string | Buffer, $meta: IMeta, context: object, log: ILogger) => object[];
274
+ request?: () => Promise<unknown>;
275
+ publish?: () => Promise<unknown>;
276
+ drain?: () => void;
277
+ findValidation?: (this: ReturnType<IAdapterFactory<T, C>>, $meta: IMeta) => () => object;
278
+ getConversion?: (
279
+ this: ReturnType<IAdapterFactory<T, C>>,
280
+ $meta: IMeta,
281
+ type: 'send' | 'receive',
282
+ ) => {name: string; fn: () => object};
283
+ findHandler?: (this: ReturnType<IAdapterFactory<T, C>>, name: string) => () => unknown;
284
+ handles?: (this: ReturnType<IAdapterFactory<T, C>>, name: string) => boolean;
285
+ forNamespaces?: <T>(reducer: (prev: T, current: unknown) => T, initial: T) => T;
286
+ methodPath?: (name: string) => string;
287
+ dispatch?: (...params: unknown[]) => Promise<unknown>;
288
+ exec?: (this: ReturnType<IAdapterFactory<T, C>>, ...params: unknown[]) => Promise<unknown>;
289
+ bytesSent?: (count: number) => void;
290
+ bytesReceived?: (count: number) => void;
291
+ msgSent?: (count: number) => void;
292
+ msgReceived?: (count: number) => void;
293
+ isConnected?: Promise<boolean>;
294
+ event?: (name: string, params?: unknown) => Promise<object>;
295
+ handle?: (...params: unknown[]) => Promise<unknown>;
296
+ connect?: (
297
+ what: unknown,
298
+ context: {requests: unknown; waiting: unknown; buffer: unknown},
299
+ ) => void;
300
+ }
301
+
302
+ export interface IAdapterFactory<T = Record<string, unknown>, C = Record<string, unknown>> {
303
+ config?: Config<T, C> | false;
304
+ (api: IApi): IAdapter<T, C>;
305
+ }
306
+
307
+ export interface IMeta {
308
+ mtid?: 'request' | 'response' | 'error' | 'notification' | 'discard' | 'event';
309
+ request?: IMeta;
310
+ stream?: unknown;
311
+ headers?: object;
312
+ trace?: string;
313
+ retry?: number;
314
+ method?: string;
315
+ expect?: string[] | string;
316
+ opcode?: string;
317
+ source?: string;
318
+ forward?: object;
319
+ httpResponse?: {
320
+ type?: string;
321
+ redirect?: string;
322
+ code?: number;
323
+ state?: unknown[];
324
+ header?: string[] | [string, unknown][];
325
+ };
326
+ httpRequest?: {
327
+ url: URL | string;
328
+ state?: object;
329
+ headers: Record<string, string | string[]>;
330
+ };
331
+ auth?: {
332
+ mlek?: object | 'header';
333
+ mlsk?: object | 'header';
334
+ permissionMap?: Buffer;
335
+ actorId?: string | number;
336
+ sessionId?: string;
337
+ };
338
+ language?: {
339
+ languageId?: string | number;
340
+ };
341
+ cache?: {
342
+ port: string;
343
+ optional: boolean;
344
+ instead: boolean;
345
+ before: boolean;
346
+ key: unknown;
347
+ ttl: number;
348
+ after: boolean;
349
+ };
350
+ errorCode?: string;
351
+ errorMessage?: string;
352
+ hostName?: string | string[];
353
+ ipAddress?: string;
354
+ machineName?: string;
355
+ os?: string;
356
+ version?: string;
357
+ serviceName?: string;
358
+ frontEnd?: string;
359
+ localAddress?: string;
360
+ localPort?: number;
361
+ deviceId?: string | string[];
362
+ latitude?: string | string[];
363
+ longitude?: string | string[];
364
+ conId?: number;
365
+ dispatch?: (
366
+ msg?: object,
367
+ $meta?: IMeta,
368
+ ) => [msg: object, $meta: IMeta] | boolean | void | Promise<boolean>;
369
+ reply?: unknown;
370
+ timeout?: number;
371
+ timer?: (
372
+ name?: string,
373
+ newTime?: HRTime | false,
374
+ ) => {
375
+ [name: string]: number;
376
+ };
377
+ gateway?: object;
378
+ validation?: unknown;
379
+ }
380
+
381
+ export type HRTime = [number, number];
382
+
383
+ export interface IContext {
384
+ trace: number;
385
+ session?: {
386
+ [name: string]: unknown;
387
+ };
388
+ conId?: string;
389
+ requests: Map<
390
+ string,
391
+ {$meta: IMeta; end: (error: Error) => {local: object; literals: object[]}}
392
+ >;
393
+ waiting: Set<(error: Error) => void>;
394
+ }
395
+
396
+ export interface ITypedError extends Error {
397
+ type: string;
398
+ cause?: Error;
399
+ print?: string;
400
+ method?: string | string[];
401
+ params?: object;
402
+ code?: string;
403
+ req?: {
404
+ httpVersion: string;
405
+ url: URL;
406
+ method: string;
407
+ };
408
+ res?: {
409
+ httpVersion: string;
410
+ statusCode: number;
411
+ };
412
+ }
413
+
414
+ export type Errors<T> = {
415
+ [name in keyof T]: (params?: unknown, $meta?: IMeta) => ITypedError;
416
+ };
417
+
418
+ export interface IBaseConfig extends TObject<{
419
+ watch: TObject<{
420
+ test: TArray<TString>;
421
+ }>;
422
+ remote: TObject<{
423
+ canSkipSocket: TBoolean;
424
+ }>;
425
+ adapter: TBoolean;
426
+ orchestrator: TBoolean;
427
+ test: TBoolean;
428
+ error: TBoolean;
429
+ gateway: TBoolean | TObject;
430
+ sim: TBoolean;
431
+ resolution: TBoolean;
432
+ }> {
433
+ additionalProperties: false;
434
+ }
435
+ export interface IActivationConfig<T> {
436
+ default: T;
437
+ integration?: T;
438
+ deployment?: T;
439
+ microservice?: T;
440
+ dev?: T;
441
+ }
442
+
443
+ export interface IModuleConfig<T extends TSchema = TNever> {
444
+ pkg?: {
445
+ name: string;
446
+ version: string;
447
+ };
448
+ url: string;
449
+ config?: IActivationConfig<Partial<Static<T>> & Partial<Static<IBaseConfig>>>;
450
+ validation?: T;
451
+ children?: (string | (() => Promise<object>))[] | ((layer: ModuleApi) => unknown)[];
452
+ }
453
+
454
+ export interface ILogger {
455
+ trace?: LogFn;
456
+ debug?: LogFn;
457
+ info?: LogFn;
458
+ warn?: LogFn;
459
+ error?: LogFn;
460
+ fatal?: LogFn;
461
+ }
462
+
463
+ export interface IStep {
464
+ name: string;
465
+ method?: string;
466
+ }
467
+ export type Sequence = (boolean | string | IStep)[];
468
+
469
+ export type ApiSchema = TObject | TArray | TBoolean | TString | TNumber | TUnknown;
470
+
471
+ export type GatewaySchema = (
472
+ | {
473
+ params: ApiSchema;
474
+ result: ApiSchema;
475
+ }
476
+ | {
477
+ body: {
478
+ schema: ApiSchema;
479
+ };
480
+ response: ApiSchema;
481
+ }
482
+ | {
483
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
484
+ path?: string;
485
+ response?: ApiSchema;
486
+ }
487
+ | {
488
+ auth: false | 'basic' | 'login';
489
+ }
490
+ | {
491
+ namespace: Record<string, string | string[]>;
492
+ }
493
+ ) & {
494
+ auth?: false | 'basic' | 'login';
495
+ rpc?: boolean;
496
+ description?: string;
497
+ summary?: string;
498
+ security?: true;
499
+ basePath?: string;
500
+ subject?: string;
501
+ destination?: string;
502
+ operation?: OpenAPIV3_1.OperationObject | OpenAPIV2.OperationObject;
503
+ };
504
+
505
+ export type SchemaObject = OpenAPIV3_1.SchemaObject | OpenAPIV2.SchemaObject;
506
+ export type PathItemObject = OpenAPIV3_1.PathItemObject | OpenAPIV2.PathItemObject;
507
+ export type ThenableProxy = Promise<unknown> & {[key: string]: ThenableProxy};
508
+ export type ChainStep =
509
+ | ((
510
+ assert: typeof Assert,
511
+ context: {
512
+ $meta: IMeta;
513
+ } & Record<string, Promise<unknown[]> & ThenableProxy>,
514
+ ) => Promise<object>)
515
+ | object;
516
+
517
+ export interface ILib {
518
+ type: typeof Type;
519
+ error: <T>(errors: T) => Record<keyof T, (params?: unknown, $meta?: IMeta) => ITypedError>;
520
+ rename: <T extends object>(object: T, name: string) => T & {name: string};
521
+ group: (name: string) => (handlers: ChainStep[]) => ChainStep[] & {name: string};
522
+ ulid: () => string;
523
+ uuid4: () => string;
524
+ uuid7: () => string;
525
+ merge<T, S1>(target: T, source: S1): T & S1;
526
+ merge<T, S1, S2>(target: T, source1: S1, source2: S2): T & S1 & S2;
527
+ merge<T, S1, S2, S3>(target: T, source1: S1, source2: S2, source3: S3): T & S1 & S2 & S3;
528
+ merge<T>(...args: unknown[]): T;
529
+ }
530
+
531
+ export type ValidationFn = () => GatewaySchema;
532
+ export interface IValidationProxy {
533
+ type: typeof Type;
534
+ handler: {
535
+ [name: string]: ValidationFn;
536
+ };
537
+ lib: ILib & {
538
+ [name: string]: TSchema;
539
+ };
540
+ error: {
541
+ [name: string]: (...params: unknown[]) => ITypedError;
542
+ };
543
+ }
544
+ export type ValidationDefinition = (
545
+ blong: IValidationProxy,
546
+ ) => Record<string, ValidationFn | TSchema> | ValidationFn | ValidationFn[];
547
+
548
+ export type ApiDefinition = (blong: IValidationProxy) =>
549
+ | {
550
+ namespace: Record<
551
+ string,
552
+ string | (string | Partial<OpenAPI.Document & {'x-blong-namespace': string}>)[]
553
+ >;
554
+ }
555
+ | {
556
+ url: string;
557
+ };
558
+
559
+ export type PortHandler<T, C> = <R>(
560
+ this: ReturnType<IAdapterFactory<T, C>>,
561
+ params: {},
562
+ $meta: IMeta,
563
+ context?: IContext,
564
+ ) => Promise<R> | R;
565
+ export type PortHandlerBound = <T>(params: {}, $meta: IMeta, context?: IContext) => Promise<T> | T;
566
+ export type LibFn = <T>(...params: unknown[]) => T;
567
+ export interface IRemoteHandler {
568
+ [name: string]: PortHandlerBound;
569
+ }
570
+ export interface IHandlerProxy<T> {
571
+ config: T;
572
+ handler: {
573
+ [name: `error${string}`]: (
574
+ message?: string | {params?: object; cause?: Error},
575
+ ) => ITypedError;
576
+ } & IRemoteHandler;
577
+ lib: ILib & {
578
+ [name: string]: LibFn;
579
+ };
580
+ errors: {
581
+ [name: string]: (...params: unknown[]) => ITypedError;
582
+ };
583
+ utBus: {
584
+ info: () => {encrypt: object; sign: object};
585
+ };
586
+ gateway: {
587
+ config: () => {public: {sign: object; encrypt: object}};
588
+ };
589
+ }
590
+
591
+ export type ImportProxyCallback<T, C> = (
592
+ blong: IHandlerProxy<T>,
593
+ ) => PortHandler<T, C> | IAdapterFactory<T, C> | Record<string, PortHandler<T, C>>;
594
+ export type Definition<T, C> = object | ImportProxyCallback<T, C> | ImportProxyCallback<T, C>[];
595
+
596
+ export type LibProxyCallback<T> = (blong: IHandlerProxy<T>) => Record<string, LibFn> | LibFn;
597
+ export type Lib<T> = object | LibProxyCallback<T> | LibProxyCallback<T>[];
598
+
599
+ export type ModuleApi = {
600
+ config: Record<string, unknown>;
601
+ parent: IAdapterFactory;
602
+ error: (errors: object) => ModuleApi;
603
+ validation: (
604
+ method: ValidationDefinition | ValidationDefinition[],
605
+ namespace?: string,
606
+ ) => ModuleApi;
607
+ sequence: (fn: () => Sequence) => ModuleApi;
608
+ feature: (paths: string | string[]) => ModuleApi;
609
+ step: (step: Record<string, () => IStep>) => ModuleApi;
610
+ } & {
611
+ [name: string]: (
612
+ blong: Definition<Record<string, unknown>, Record<string, unknown>>,
613
+ ) => ModuleApi;
614
+ };
615
+
616
+ export interface SolutionFactory<T extends TSchema = TNever> {
617
+ (definition: {type: typeof Type}): IModuleConfig<T> | Promise<IModuleConfig<T>>;
618
+ }
619
+
620
+ const Kind: symbol = Symbol.for('blong:kind');
621
+ export type Kind = typeof Kind;
622
+
623
+ export abstract class Internal {
624
+ #log?: ILog;
625
+ protected log?: ReturnType<ILog['logger']>;
626
+ public constructor(api?: {log: ILog}) {
627
+ this.#log = api?.log;
628
+ }
629
+ protected merge: ILib['merge'] = (...args: Parameters<ILib['merge']>) => {
630
+ const result = merge<{logLevel?: Level}>(...args);
631
+ if (result.logLevel && this.#log)
632
+ this.log = this.#log.logger(result.logLevel, {name: this.constructor.name});
633
+ return result;
634
+ };
635
+ public async stop(): Promise<unknown> {
636
+ return this;
637
+ }
638
+ public async start(...params: unknown[]): Promise<unknown> {
639
+ return this;
640
+ }
641
+ }
642
+
643
+ export const handler = <T = Record<string, unknown>, C = AdapterContext>(
644
+ definition: Definition<T, C>,
645
+ ): Definition<T, C> => Object.defineProperty(definition, Kind, {value: 'handler'});
646
+ export const library = <T = Record<string, unknown>>(definition: Lib<T>): Lib<T> =>
647
+ Object.defineProperty(definition, Kind, {value: 'lib'});
648
+ export const validation = (validation: ValidationDefinition): ValidationDefinition =>
649
+ Object.defineProperty(validation, Kind, {value: 'validation'});
650
+ export const api = (api: ApiDefinition): ApiDefinition =>
651
+ Object.defineProperty(api, Kind, {value: 'api'});
652
+
653
+ export const validationHandlers: (
654
+ handlers: Record<string, TFunction<[TObject<{}>]>>,
655
+ ) => ValidationDefinition = handlers =>
656
+ validation(() =>
657
+ Object.fromEntries(
658
+ Object.entries(handlers).map(([name, handler]) => [
659
+ name,
660
+ Object.defineProperty(
661
+ () => ({
662
+ params: Type.Parameters(handler).items[0],
663
+ result: Type.Awaited(Type.ReturnType(handler)),
664
+ description: 'description' in handler ? handler.description : undefined,
665
+ }),
666
+ 'name',
667
+ {value: name},
668
+ ),
669
+ ]),
670
+ ),
671
+ );
672
+
673
+ export const realm = <T extends TObject>(definition: SolutionFactory<T>): SolutionFactory<T> =>
674
+ Object.defineProperty(definition, Kind, {value: 'solution'});
675
+ export const server = <T extends TObject>(definition: SolutionFactory<T>): SolutionFactory<T> =>
676
+ Object.defineProperty(definition, Kind, {value: 'server'});
677
+ export const browser = <T extends TObject>(definition: SolutionFactory<T>): SolutionFactory<T> =>
678
+ Object.defineProperty(definition, Kind, {value: 'browser'});
679
+ export const layer = (
680
+ activation: Record<string, boolean | object>,
681
+ ): Record<string, boolean | object> => Object.defineProperty(activation, Kind, {value: 'layer'});
682
+ export const adapter = <T, C = AdapterContext>(
683
+ definition: IAdapterFactory<T, C>,
684
+ ): IAdapterFactory<T, C> => Object.defineProperty(definition, Kind, {value: 'adapter'});
685
+ export const orchestrator = <T, C = AdapterContext>(
686
+ definition: IAdapterFactory<T, C>,
687
+ ): IAdapterFactory<T, C> => Object.defineProperty(definition, Kind, {value: 'orchestrator'});
688
+ export type Kinds =
689
+ | 'lib'
690
+ | 'validation'
691
+ | 'api'
692
+ | 'solution'
693
+ | 'server'
694
+ | 'browser'
695
+ | 'adapter'
696
+ | 'orchestrator'
697
+ | 'handler';
698
+ export const kind = (what: {[Kind]: Kinds | undefined}): Kinds | undefined => what[Kind];
699
+
700
+ export default {
701
+ handler,
702
+ library,
703
+ validation,
704
+ api,
705
+ realm,
706
+ server,
707
+ browser,
708
+ adapter,
709
+ orchestrator,
710
+ kind,
711
+ };