@feasibleone/blong 1.22.0 → 1.23.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.23.0](https://github.com/feasibleone/blong/compare/blong-v1.22.0...blong-v1.23.0) (2026-07-14)
4
+
5
+
6
+ ### Features
7
+
8
+ * blong-mock, blong-server ([756caca](https://github.com/feasibleone/blong/commit/756cacab712db6792bf1b93830fc1d833b396f8d))
9
+ * check access credentials ([e6af405](https://github.com/feasibleone/blong/commit/e6af405c43921cb9c553db9c4986b7fe56154724))
10
+ * core.resource merging ([371d3e2](https://github.com/feasibleone/blong/commit/371d3e2b3f519dfd59ca4fd480bc33317992afcd))
11
+ * implement subjectObjectSchema ([8ca3282](https://github.com/feasibleone/blong/commit/8ca32829277b9816eb5e43ce708d2f1d0cc3ef28))
12
+ * manifest concept ([ed3c038](https://github.com/feasibleone/blong/commit/ed3c038352644d2d8f828b3cb69cbea718e7084b))
13
+ * object schema ([688d5d2](https://github.com/feasibleone/blong/commit/688d5d2a4a895c8feba7b898da03c46b3a3f3292))
14
+ * schema helpers and constraints ([8409257](https://github.com/feasibleone/blong/commit/84092571f6b327c1166ef142f70cb7d91b013eaf))
15
+ * seed ([5c76603](https://github.com/feasibleone/blong/commit/5c7660392bc1197638810e864bfd47ce1218b2e5))
16
+ * support expressions in the configuration ([843bb58](https://github.com/feasibleone/blong/commit/843bb58c97456d85eac573874c90755bdb68bc95))
17
+ * useBlong ([affdd67](https://github.com/feasibleone/blong/commit/affdd676db3338266d60155604e3bc9024078b5e))
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * build ([de22713](https://github.com/feasibleone/blong/commit/de2271393350945b8d793ca0ec89670465bba085))
23
+ * core.resource merging ([f191055](https://github.com/feasibleone/blong/commit/f1910558ce0f369f556911c4c0f6397b8003fd33))
24
+ * full stack alignment for CRUD ([8795e08](https://github.com/feasibleone/blong/commit/8795e087182402ac28c3ea03c6bee27319069625))
25
+ * Playwright, Storybook and realm DRY ([4302512](https://github.com/feasibleone/blong/commit/43025123e613ef43e0ac5b83ab00fbc0cabfccf2))
26
+
3
27
  ## [1.22.0](https://github.com/feasibleone/blong/compare/blong-v1.21.0...blong-v1.22.0) (2026-05-25)
4
28
 
5
29
 
package/dist/types.d.ts CHANGED
@@ -12,7 +12,7 @@ import { Level, LogFn, Logger as PinoLogger } from 'pino';
12
12
  import React$1 from 'react';
13
13
  import { Readable, Writable } from 'stream';
14
14
  import { ConnectionOptions as ConnectionOptions_2, TLSSocket, TLSSocketOptions } from 'tls';
15
- import { Static, TArray, TBoolean, TFunction, TIntersect, TNever, TNumber, TObject, TSchema, TString, TUnknown, Type } from 'typebox';
15
+ import { Static, TArray, TBoolean, TFunction, TIntersect, TNever, TNumber, TNumberOptions, TObject, TSchema, TSchemaOptions, TString, TStringOptions, TUnknown, Type } from 'typebox';
16
16
 
17
17
  export type Method = "GET" | "POST" | "PUT" | "DELETE";
18
18
  export interface RequestArgs {
@@ -18762,7 +18762,7 @@ export interface IWidgetConfig {
18762
18762
  type: WidgetType;
18763
18763
  /** For dropdown/multiSelect — action name to fetch options */
18764
18764
  fetch?: string;
18765
- /** Named dropdown key — loads options via portal.dropdown.list */
18765
+ /** Named dropdown key — loads options via portalDropdownList */
18766
18766
  dropdown?: string;
18767
18767
  /** Options list for static select/multiSelect/select/tree widgets.
18768
18768
  * Flat options use `{value, label}`. TreeNode-style options use `{key, label, children}`. */
@@ -18984,8 +18984,10 @@ export interface IEnrichedFieldSchema {
18984
18984
  maximum?: number;
18985
18985
  pattern?: string;
18986
18986
  enum?: unknown[];
18987
+ anyOf?: IEnrichedFieldSchema[];
18987
18988
  readOnly?: boolean;
18988
- required?: boolean;
18989
+ fieldRequired?: boolean;
18990
+ required?: string[];
18989
18991
  /** Normalized widget config */
18990
18992
  widget?: IWidgetConfig;
18991
18993
  /** Nested object properties — for composite/grouped fields accessed via dot-notation paths */
@@ -19391,10 +19393,46 @@ export type HRTime = [
19391
19393
  number,
19392
19394
  number
19393
19395
  ];
19396
+ export type BaseConfig = {
19397
+ name: string;
19398
+ pkg: {
19399
+ name: string;
19400
+ version: string;
19401
+ };
19402
+ children: unknown[];
19403
+ url: string;
19404
+ base: string;
19405
+ server: {
19406
+ load: {
19407
+ logLevel: Parameters<ILog["logger"]>[0];
19408
+ };
19409
+ realm: {
19410
+ logLevel: Parameters<ILog["logger"]>[0];
19411
+ };
19412
+ };
19413
+ browser: {
19414
+ load: {
19415
+ logLevel: Parameters<ILog["logger"]>[0];
19416
+ };
19417
+ realm: {
19418
+ logLevel: Parameters<ILog["logger"]>[0];
19419
+ };
19420
+ };
19421
+ kopi?: {
19422
+ realm?: unknown;
19423
+ };
19424
+ watch?: {
19425
+ configs?: object;
19426
+ };
19427
+ configs?: object;
19428
+ configNames: string[];
19429
+ };
19394
19430
  export interface IPlatformApi {
19395
19431
  platform: "server" | "browser";
19396
- loadConfig: (config: string | object) => Promise<{
19397
- loadedConfig?: object;
19432
+ loadConfig: (baseConfig: BaseConfig, parentConfig: string | object, loadedConfigs: object[]) => Promise<{
19433
+ loadedConfig: BaseConfig & {
19434
+ [key: string]: unknown;
19435
+ };
19398
19436
  configRuntime?: IConfigRuntime;
19399
19437
  }>;
19400
19438
  readdir: (path: string) => Promise<Dirent[]>;
@@ -19423,6 +19461,7 @@ export interface IPlatformApi {
19423
19461
  spare: (time: HRTime, latency?: number) => number;
19424
19462
  };
19425
19463
  configs: string[];
19464
+ context: Record<string, unknown>;
19426
19465
  }
19427
19466
  export interface IErrorFactory {
19428
19467
  get(type?: string): Record<string | symbol, {
@@ -19514,6 +19553,11 @@ export interface IApiSchema {
19514
19553
  assets: object;
19515
19554
  }, source: string): unknown;
19516
19555
  }
19556
+ export interface IObjectSchema {
19557
+ [subject: string]: {
19558
+ [object: string]: TObject;
19559
+ };
19560
+ }
19517
19561
  export interface IGateway {
19518
19562
  route: (validations: Record<string, GatewaySchema>, pkg: {
19519
19563
  name: string;
@@ -19540,6 +19584,7 @@ export interface IRegistry {
19540
19584
  ports: Map<string, IAdapterRegistry>;
19541
19585
  methods: Map<string, Handlers>;
19542
19586
  modules: Map<string | symbol, IRegistry[]>;
19587
+ objectSchema: IObjectSchema;
19543
19588
  createPort: (id: string) => Promise<Adapter | undefined>;
19544
19589
  getPort: (id: string) => Adapter | undefined;
19545
19590
  replaceHandlers: (id: string, handlers: Handlers) => Promise<void>;
@@ -19548,9 +19593,30 @@ export interface IRegistry {
19548
19593
  }, source: string) => Promise<void>;
19549
19594
  connected: () => Promise<boolean>;
19550
19595
  }
19596
+ export type BlongType = typeof Type & {
19597
+ increment: () => TSchema;
19598
+ integerNull: (options?: TNumberOptions) => TSchema;
19599
+ integerNotNull: (options?: TNumberOptions) => TSchema;
19600
+ bigIntNull: (options?: TNumberOptions) => TSchema;
19601
+ bigIntNotNull: (options?: TNumberOptions) => TSchema;
19602
+ stringNull: (options?: TStringOptions) => TSchema;
19603
+ stringNotNull: (options?: TStringOptions) => TSchema;
19604
+ numberNull: (options?: TNumberOptions) => TSchema;
19605
+ numberNotNull: (options?: TNumberOptions) => TSchema;
19606
+ booleanNull: (options?: TSchemaOptions) => TSchema;
19607
+ booleanNotNull: (options?: TSchemaOptions) => TSchema;
19608
+ dateNull: () => TSchema;
19609
+ dateNotNull: () => TSchema;
19610
+ dateTimeNull: () => TSchema;
19611
+ dateTimeNotNull: () => TSchema;
19612
+ ulid: () => TSchema;
19613
+ uuid: () => TSchema;
19614
+ uidNull: () => TSchema;
19615
+ uidNotNull: () => TSchema;
19616
+ };
19551
19617
  export interface IApi {
19552
19618
  id?: string;
19553
- type: typeof Type;
19619
+ type: BlongType;
19554
19620
  adapter: (id: string) => IAdapterRegistry | undefined;
19555
19621
  utError: IError;
19556
19622
  errors: IErrorFactory;
@@ -19559,6 +19625,7 @@ export interface IApi {
19559
19625
  rpc: IRpcServer;
19560
19626
  local: ILocal;
19561
19627
  registry: IRegistry;
19628
+ schema: IObjectSchema;
19562
19629
  register: (methods: Record<string, (...params: unknown[]) => Promise<unknown>> | Array<(...params: unknown[]) => Promise<unknown>>, namespace: string, id: string, pkg: {
19563
19630
  version: string;
19564
19631
  }) => void;
@@ -19578,12 +19645,15 @@ export interface IApi {
19578
19645
  namespace?: string | string[];
19579
19646
  };
19580
19647
  }, patterns: (string | RegExp)[] | string | RegExp, adapter?: boolean) => unknown;
19648
+ attach: (target: object, patterns: (string | RegExp)[] | string | RegExp) => Promise<object>;
19581
19649
  createLog: ILog["logger"];
19582
19650
  attachCheckpoint?: (meta: IMeta) => void;
19583
19651
  handlers?: (api: {
19584
19652
  utError: IError;
19585
19653
  remote: IRemote;
19586
- type: typeof Type;
19654
+ type: BlongType;
19655
+ schema: IObjectSchema;
19656
+ manifest?: IManifest;
19587
19657
  }) => {
19588
19658
  extends?: string | ((api: {
19589
19659
  utError: IError;
@@ -19591,8 +19661,13 @@ export interface IApi {
19591
19661
  rpc: IRpcServer;
19592
19662
  local: ILocal;
19593
19663
  registry: IRegistry;
19664
+ schema: IObjectSchema;
19665
+ manifest?: IManifest;
19594
19666
  }) => object);
19595
19667
  };
19668
+ render: (what: object[] | object) => object;
19669
+ platform: IPlatformApi;
19670
+ manifest?: IManifest;
19596
19671
  }
19597
19672
  export interface IErrorMap {
19598
19673
  [name: string]: string | {
@@ -19601,7 +19676,7 @@ export interface IErrorMap {
19601
19676
  statusCode?: number;
19602
19677
  };
19603
19678
  }
19604
- export type Adapter<T = Record<string, unknown>, C = Record<string, unknown>> = IAdapter<T, C> & Pick<Required<IAdapter<T, C>>, "init" | "start" | "stop" | "ready" | "config" | "imported" | "errors" | "error" | "findValidation" | "getConversion" | "dispatch">;
19679
+ export type Adapter<T = Record<string, unknown>, C = Record<string, unknown>> = IAdapter<T, C> & Pick<Required<IAdapter<T, C>>, "init" | "start" | "stop" | "ready" | "config" | "imported" | "errors" | "error" | "findValidation" | "getConversion" | "dispatch" | "platform">;
19605
19680
  export interface IAdapter<T, C> {
19606
19681
  validation?: TSchema;
19607
19682
  config?: Config<T, C>;
@@ -19612,18 +19687,13 @@ export interface IAdapter<T, C> {
19612
19687
  imported?: Record<string, PortHandlerBound>;
19613
19688
  importedMap?: Map<string, IRemoteHandler>;
19614
19689
  extends?: object | `adapter.${string}` | `orchestrator.${string}`;
19690
+ platform?: IPlatformApi;
19615
19691
  activeConfig?(this: Adapter<T, C>): Partial<Config<T, C>>;
19616
19692
  init?(this: Adapter<T, C>, ...config: unknown[]): Promise<unknown>;
19617
19693
  start?(this: Adapter<T, C>, ...params: unknown[]): Promise<unknown>;
19618
19694
  ready?(this: Adapter<T, C>): Promise<unknown>;
19619
19695
  stop?(this: Adapter<T, C>, ...params: unknown[]): Promise<unknown>;
19620
- link?(this: Adapter<T, C>, patterns: (string | RegExp)[] | string | RegExp, target: object): Promise<{
19621
- importedMap?: Map<string, object>;
19622
- imported?: object;
19623
- config?: {
19624
- namespace?: string | string[];
19625
- };
19626
- }>;
19696
+ attach?<R extends object>(this: Adapter<T, C>, patterns: (string | RegExp)[] | string | RegExp, target?: R): Promise<R>;
19627
19697
  connected?(this: Adapter<T, C>): Promise<boolean>;
19628
19698
  error?(error: unknown, $meta: unknown): void;
19629
19699
  pack?(this: Adapter<T, C>, ...params: unknown[]): unknown;
@@ -19680,6 +19750,8 @@ export interface IAdapterRegistry {
19680
19750
  rpc: IRpcServer;
19681
19751
  local: ILocal;
19682
19752
  registry: IRegistry;
19753
+ schema: IObjectSchema;
19754
+ manifest?: IManifest;
19683
19755
  }): Promise<Adapter>;
19684
19756
  }
19685
19757
  export interface IMeta {
@@ -19799,18 +19871,27 @@ export type Errors<T> = {
19799
19871
  };
19800
19872
  export interface IBaseConfig extends TObject<{
19801
19873
  watch: TObject<{
19802
- test: TArray<TString>;
19874
+ test?: TArray<TString>;
19803
19875
  }>;
19804
19876
  remote: TObject<{
19805
- canSkipSocket: TBoolean;
19877
+ canSkipSocket?: TBoolean;
19806
19878
  }>;
19807
- adapter: TBoolean;
19808
- orchestrator: TBoolean;
19809
- test: TBoolean;
19810
- error: TBoolean;
19879
+ adapter: TBoolean | TObject;
19880
+ orchestrator: TBoolean | TObject;
19881
+ test: TBoolean | TObject;
19882
+ error: TBoolean | TObject;
19811
19883
  gateway: TBoolean | TObject;
19812
- sim: TBoolean;
19813
- resolution: TBoolean;
19884
+ sim: TBoolean | TObject;
19885
+ resolution: TBoolean | TObject;
19886
+ log: TBoolean | TObject;
19887
+ apiSchema: TBoolean | TObject;
19888
+ registry: TBoolean | TObject;
19889
+ port: TBoolean | TObject;
19890
+ codec: TBoolean | TObject;
19891
+ local: TBoolean | TObject;
19892
+ rpcServer: TBoolean | TObject;
19893
+ restFs: TBoolean | TObject;
19894
+ systemDebug: TBoolean | TObject;
19814
19895
  }> {
19815
19896
  additionalProperties: false;
19816
19897
  }
@@ -19899,8 +19980,24 @@ export type ChainStep = ((assert: IAssert, context: {
19899
19980
  $meta: IMeta;
19900
19981
  } & Record<string, Promise<unknown[]> & ThenableProxy>) => Promise<object>) | object;
19901
19982
  export type CheckpointFn = (this: IMeta, name: string, data?: unknown) => void;
19983
+ /**
19984
+ * Manifest — a shared mutable object passed to the `load` function that allows
19985
+ * platforms to share information such as effective ports, URLs, or other
19986
+ * runtime-resolved values across components.
19987
+ *
19988
+ * Properties are typically Promises (created via `Promise.withResolvers()`) that
19989
+ * are resolved when one platform finishes a startup step (e.g. listening on a
19990
+ * random port), and awaited by another platform or adapter during its own
19991
+ * initialisation (e.g. constructing a backend URL from the effective port).
19992
+ *
19993
+ * Manifest properties can also be provided via CLI args using the
19994
+ * `--manifest.<key>=<value>` syntax.
19995
+ */
19996
+ export interface IManifest {
19997
+ [key: string]: unknown;
19998
+ }
19902
19999
  export interface ILib {
19903
- type: typeof Type;
20000
+ type: BlongType;
19904
20001
  error: <T>(errors: T) => Record<keyof T, (params?: unknown, $meta?: IMeta) => ITypedError>;
19905
20002
  rename: <T extends object>(object: T, name: string) => T & {
19906
20003
  name: string;
@@ -19953,22 +20050,29 @@ export interface ILib {
19953
20050
  merge<T, S1, S2>(target: T, source1: S1, source2: S2): T & S1 & S2;
19954
20051
  merge<T, S1, S2, S3>(target: T, source1: S1, source2: S2, source3: S3): T & S1 & S2 & S3;
19955
20052
  merge<T>(...args: unknown[]): T;
20053
+ mergeWithSymbols<T, S1>(target: T, source: S1): T & S1;
20054
+ render: (what: object[] | object) => object;
20055
+ crockfordEncode: (data: Uint8Array) => string;
20056
+ crockfordDecode: (data: string) => Uint8Array;
19956
20057
  }
19957
20058
  export type ValidationFn = () => GatewaySchema;
19958
- export interface IValidationProxy {
20059
+ export interface IValidationProxy<T> {
19959
20060
  type: typeof Type;
19960
20061
  handler: {
19961
20062
  [name: string]: ValidationFn;
19962
- };
20063
+ } & IRemoteHandler;
19963
20064
  lib: ILib & {
19964
20065
  [name: string]: TSchema;
19965
20066
  };
19966
20067
  error: {
19967
20068
  [name: string]: (...params: unknown[]) => ITypedError;
19968
20069
  };
20070
+ /** Collected object schemas accumulated so far; later `schema()` exports can reference earlier ones. */
20071
+ schema: IObjectSchema;
20072
+ config: T;
19969
20073
  }
19970
- export type ValidationDefinition = (blong: IValidationProxy) => Record<string, ValidationFn | TSchema> | ValidationFn | ValidationFn[];
19971
- export type ApiDefinition = (blong: IValidationProxy) => {
20074
+ export type ValidationDefinition<T> = (blong: IValidationProxy<T>) => Promise<Record<string, ValidationFn | TSchema> | ValidationFn | ValidationFn[]>;
20075
+ export type ApiDefinition<T> = (blong: IValidationProxy<T>) => {
19972
20076
  namespace: string[] | Record<string, string | (string | Partial<OpenAPI.Document & {
19973
20077
  "x-blong-namespace": string;
19974
20078
  }>)[]>;
@@ -19999,6 +20103,8 @@ export interface IHandlerProxy<T> {
19999
20103
  errors: {
20000
20104
  [name: string]: (...params: unknown[]) => ITypedError;
20001
20105
  };
20106
+ /** Collected object schemas from all registered `schema()` exports. */
20107
+ schema: IObjectSchema;
20002
20108
  utBus: {
20003
20109
  info: () => {
20004
20110
  encrypt: object;
@@ -20023,7 +20129,7 @@ export type ModuleApi = {
20023
20129
  config: Record<string, unknown>;
20024
20130
  parent: IAdapterFactory;
20025
20131
  error: (errors: object) => ModuleApi;
20026
- validation: (method: ValidationDefinition | ValidationDefinition[], namespace?: string) => ModuleApi;
20132
+ validation: <T>(method: ValidationDefinition<T> | ValidationDefinition<T>[], namespace?: string) => ModuleApi;
20027
20133
  sequence: (fn: () => Sequence) => ModuleApi;
20028
20134
  feature: (paths: string | string[]) => ModuleApi;
20029
20135
  step: (step: Record<string, () => IStep>) => ModuleApi;
@@ -20033,6 +20139,7 @@ export type ModuleApi = {
20033
20139
  export interface SolutionFactory<T extends TSchema = TNever> {
20034
20140
  (definition: {
20035
20141
  type: typeof Type;
20142
+ manifest?: IManifest;
20036
20143
  }): IModuleConfig<T> | Promise<IModuleConfig<T>>;
20037
20144
  }
20038
20145
  declare const Kind: symbol;
@@ -20064,26 +20171,27 @@ export interface IComponent {
20064
20171
  component: (params?: Record<string, unknown>) => Promise<unknown>;
20065
20172
  }
20066
20173
  export declare const library: <T = Record<string, unknown>>(definition: Lib<T>) => Lib<T>;
20067
- export declare const validation: (validation: ValidationDefinition) => ValidationDefinition;
20068
- export declare const api: (api: ApiDefinition) => ApiDefinition;
20174
+ export declare const validation: <T = Record<string, unknown>>(validation: ValidationDefinition<T>) => ValidationDefinition<T>;
20175
+ export declare const schema: <T = Record<string, unknown>>(schema: ValidationDefinition<T>) => ValidationDefinition<T>;
20176
+ export declare const api: <T = Record<string, unknown>>(api: ApiDefinition<T>) => ApiDefinition<T>;
20069
20177
  export declare const model: <T extends IModelSpec>(definition: () => () => Promise<T>) => (() => () => Promise<T>);
20070
20178
  export declare const fixture: <T extends IMock>(definition: () => T) => (() => T);
20071
- export declare const validationHandlers: (handlers: Record<string, TFunction<[
20179
+ export declare const validationHandlers: <T>(handlers: Record<string, TFunction<[
20072
20180
  ApiSchema
20073
- ]>>) => ValidationDefinition;
20181
+ ]>>) => ValidationDefinition<T>;
20074
20182
  export declare const realm: <T extends TObject>(definition: SolutionFactory<T>) => SolutionFactory<T> & {};
20075
20183
  export declare const server: <T extends TObject>(definition: SolutionFactory<T>) => SolutionFactory<T> & {};
20076
20184
  export declare const browser: <T extends TObject>(definition: SolutionFactory<T>) => SolutionFactory<T> & {};
20077
20185
  export declare const layer: (activation: Record<string, boolean | object>) => Record<string, boolean | object> & {};
20078
20186
  export declare const adapter: <T, C = AdapterContext>(definition: IAdapterFactory<T, C>) => IAdapterFactory<T, C> & {};
20079
20187
  export declare const orchestrator: <T, C = AdapterContext>(definition: IAdapterFactory<T, C>) => IAdapterFactory<T, C> & {};
20080
- export type Kinds = "lib" | "validation" | "api" | "solution" | "server" | "browser" | "adapter" | "orchestrator" | "handler" | "model" | "fixture" | "";
20188
+ export type Kinds = "lib" | "validation" | "schema" | "api" | "solution" | "server" | "browser" | "adapter" | "orchestrator" | "handler" | "model" | "fixture" | "";
20081
20189
  export declare const kind: (what: {}) => Kinds;
20082
20190
  declare const _default: {
20083
20191
  handler: <T = Record<string, unknown>, C = AdapterContext>(definition: Definition<T, C>) => Definition<T, C>;
20084
20192
  library: <T = Record<string, unknown>>(definition: Lib<T>) => Lib<T>;
20085
- validation: (validation: ValidationDefinition) => ValidationDefinition;
20086
- api: (api: ApiDefinition) => ApiDefinition;
20193
+ validation: <T = Record<string, unknown>>(validation: ValidationDefinition<T>) => ValidationDefinition<T>;
20194
+ api: <T = Record<string, unknown>>(api: ApiDefinition<T>) => ApiDefinition<T>;
20087
20195
  realm: <T extends TObject>(definition: SolutionFactory<T>) => SolutionFactory<T> & {};
20088
20196
  server: <T extends TObject>(definition: SolutionFactory<T>) => SolutionFactory<T> & {};
20089
20197
  browser: <T extends TObject>(definition: SolutionFactory<T>) => SolutionFactory<T> & {};
package/dist/types.js CHANGED
@@ -23,10 +23,11 @@ export class Internal {
23
23
  export const handler = (definition) => Object.defineProperty(definition, Kind, { value: 'handler' });
24
24
  export const library = (definition) => Object.defineProperty(definition, Kind, { value: 'lib' });
25
25
  export const validation = (validation) => Object.defineProperty(validation, Kind, { value: 'validation' });
26
+ export const schema = (schema) => Object.defineProperty(schema, Kind, { value: 'schema' });
26
27
  export const api = (api) => Object.defineProperty(api, Kind, { value: 'api' });
27
28
  export const model = (definition) => Object.defineProperty(definition, Kind, { value: 'model' });
28
29
  export const fixture = (definition) => Object.defineProperty(definition, Kind, { value: 'fixture' });
29
- export const validationHandlers = handlers => validation(() => Object.fromEntries(Object.entries(handlers).map(([name, handler]) => [
30
+ export const validationHandlers = handlers => validation(async () => Object.fromEntries(Object.entries(handlers).map(([name, handler]) => [
30
31
  name,
31
32
  Object.defineProperty(() => ({
32
33
  params: Type.Parameters(handler).items[0],
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feasibleone/blong",
3
- "version": "1.22.0",
3
+ "version": "1.23.0",
4
4
  "description": "API and DRY focused RAD framework https://feasibleone.github.io/blong-docs",
5
5
  "keywords": [
6
6
  "blong",
@@ -40,14 +40,14 @@
40
40
  "bson": "^7.2.0",
41
41
  "chokidar": "^5.0.0",
42
42
  "dts-bundle-generator": "^9.5.1",
43
- "knex": "^3.1.0",
43
+ "knex": "^3.2.10",
44
44
  "mongodb": "^7.1.0",
45
45
  "node-vault": "^0.10.10",
46
46
  "openapi-types": "^12.1.3",
47
47
  "react": "^19.1.0",
48
48
  "tarn": "^3.0.2",
49
49
  "typescript": "^6.0.3",
50
- "@feasibleone/blong-dev": "1.0.2"
50
+ "@feasibleone/blong-dev": "1.1.0"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "heft build --clean;dts-bundle-generator --config dts-gen.config.json",
package/types.ts CHANGED
@@ -19,9 +19,12 @@ import {
19
19
  type TIntersect,
20
20
  type TNever,
21
21
  type TNumber,
22
+ type TNumberOptions,
22
23
  type TObject,
23
24
  type TSchema,
25
+ type TSchemaOptions,
24
26
  type TString,
27
+ type TStringOptions,
25
28
  type TUnknown,
26
29
  } from 'typebox';
27
30
  // import type {client} from 'node-vault';
@@ -132,11 +135,38 @@ export interface IWatcher extends EventEmitter<FSWatcherEventMap> {
132
135
 
133
136
  export type HRTime = [number, number];
134
137
 
138
+ type BaseConfig = {
139
+ name: string;
140
+ pkg: {name: string; version: string};
141
+ children: unknown[];
142
+ url: string;
143
+ base: string;
144
+ server: {
145
+ load: {logLevel: Parameters<ILog['logger']>[0]};
146
+ realm: {logLevel: Parameters<ILog['logger']>[0]};
147
+ };
148
+ browser: {
149
+ load: {logLevel: Parameters<ILog['logger']>[0]};
150
+ realm: {logLevel: Parameters<ILog['logger']>[0]};
151
+ };
152
+ kopi?: {realm?: unknown};
153
+ watch?: {configs?: object};
154
+ configs?: object;
155
+ configNames: string[];
156
+ };
157
+
135
158
  export interface IPlatformApi {
136
159
  platform: 'server' | 'browser';
137
160
  loadConfig: (
138
- config: string | object,
139
- ) => Promise<{loadedConfig?: object; configRuntime?: IConfigRuntime}>;
161
+ baseConfig: BaseConfig,
162
+ parentConfig: string | object,
163
+ loadedConfigs: object[],
164
+ ) => Promise<{
165
+ loadedConfig: BaseConfig & {
166
+ [key: string]: unknown;
167
+ };
168
+ configRuntime?: IConfigRuntime;
169
+ }>;
140
170
  readdir: (path: string) => Promise<Dirent[]>;
141
171
  scan: (...path: string[]) => Promise<Dirent[]>;
142
172
  existsSync: (path: string) => boolean;
@@ -163,6 +193,7 @@ export interface IPlatformApi {
163
193
  spare: (time: HRTime, latency?: number) => number;
164
194
  };
165
195
  configs: string[];
196
+ context: Record<string, unknown>;
166
197
  }
167
198
 
168
199
  export interface IErrorFactory {
@@ -263,6 +294,12 @@ export interface IApiSchema {
263
294
  ): unknown;
264
295
  }
265
296
 
297
+ export interface IObjectSchema {
298
+ [subject: string]: {
299
+ [object: string]: TObject;
300
+ };
301
+ }
302
+
266
303
  export interface IGateway {
267
304
  route: (
268
305
  validations: Record<string, GatewaySchema>,
@@ -291,6 +328,7 @@ export interface IRegistry {
291
328
  ports: Map<string, IAdapterRegistry>;
292
329
  methods: Map<string, Handlers>;
293
330
  modules: Map<string | symbol, IRegistry[]>;
331
+ objectSchema: IObjectSchema;
294
332
  createPort: (id: string) => Promise<Adapter | undefined>;
295
333
  getPort: (id: string) => Adapter | undefined;
296
334
  replaceHandlers: (id: string, handlers: Handlers) => Promise<void>;
@@ -304,9 +342,31 @@ export interface IRegistry {
304
342
  connected: () => Promise<boolean>;
305
343
  }
306
344
 
345
+ type BlongType = typeof Type & {
346
+ increment: () => TSchema;
347
+ integerNull: (options?: TNumberOptions) => TSchema;
348
+ integerNotNull: (options?: TNumberOptions) => TSchema;
349
+ bigIntNull: (options?: TNumberOptions) => TSchema;
350
+ bigIntNotNull: (options?: TNumberOptions) => TSchema;
351
+ stringNull: (options?: TStringOptions) => TSchema;
352
+ stringNotNull: (options?: TStringOptions) => TSchema;
353
+ numberNull: (options?: TNumberOptions) => TSchema;
354
+ numberNotNull: (options?: TNumberOptions) => TSchema;
355
+ booleanNull: (options?: TSchemaOptions) => TSchema;
356
+ booleanNotNull: (options?: TSchemaOptions) => TSchema;
357
+ dateNull: () => TSchema;
358
+ dateNotNull: () => TSchema;
359
+ dateTimeNull: () => TSchema;
360
+ dateTimeNotNull: () => TSchema;
361
+ ulid: () => TSchema;
362
+ uuid: () => TSchema;
363
+ uidNull: () => TSchema;
364
+ uidNotNull: () => TSchema;
365
+ };
366
+
307
367
  export interface IApi {
308
368
  id?: string;
309
- type: typeof Type;
369
+ type: BlongType;
310
370
  adapter: (id: string) => IAdapterRegistry | undefined;
311
371
  utError: IError;
312
372
  errors: IErrorFactory;
@@ -315,6 +375,7 @@ export interface IApi {
315
375
  rpc: IRpcServer;
316
376
  local: ILocal;
317
377
  registry: IRegistry;
378
+ schema: IObjectSchema;
318
379
  register: (
319
380
  methods:
320
381
  | Record<string, (...params: unknown[]) => Promise<unknown>>
@@ -349,9 +410,16 @@ export interface IApi {
349
410
  patterns: (string | RegExp)[] | string | RegExp,
350
411
  adapter?: boolean,
351
412
  ) => unknown;
413
+ attach: (target: object, patterns: (string | RegExp)[] | string | RegExp) => Promise<object>;
352
414
  createLog: ILog['logger'];
353
415
  attachCheckpoint?: (meta: IMeta) => void;
354
- handlers?: (api: {utError: IError; remote: IRemote; type: typeof Type}) => {
416
+ handlers?: (api: {
417
+ utError: IError;
418
+ remote: IRemote;
419
+ type: BlongType;
420
+ schema: IObjectSchema;
421
+ manifest?: IManifest;
422
+ }) => {
355
423
  extends?:
356
424
  | string
357
425
  | ((api: {
@@ -360,8 +428,13 @@ export interface IApi {
360
428
  rpc: IRpcServer;
361
429
  local: ILocal;
362
430
  registry: IRegistry;
431
+ schema: IObjectSchema;
432
+ manifest?: IManifest;
363
433
  }) => object);
364
434
  };
435
+ render: (what: object[] | object) => object;
436
+ platform: IPlatformApi;
437
+ manifest?: IManifest;
365
438
  }
366
439
 
367
440
  export interface IErrorMap {
@@ -388,6 +461,7 @@ export type Adapter<T = Record<string, unknown>, C = Record<string, unknown>> =
388
461
  | 'findValidation'
389
462
  | 'getConversion'
390
463
  | 'dispatch'
464
+ | 'platform'
391
465
  >;
392
466
  export interface IAdapter<T, C> {
393
467
  validation?: TSchema;
@@ -399,20 +473,17 @@ export interface IAdapter<T, C> {
399
473
  imported?: Record<string, PortHandlerBound>;
400
474
  importedMap?: Map<string, IRemoteHandler>;
401
475
  extends?: object | `adapter.${string}` | `orchestrator.${string}`;
476
+ platform?: IPlatformApi;
402
477
  activeConfig?(this: Adapter<T, C>): Partial<Config<T, C>>;
403
478
  init?(this: Adapter<T, C>, ...config: unknown[]): Promise<unknown>;
404
479
  start?(this: Adapter<T, C>, ...params: unknown[]): Promise<unknown>;
405
480
  ready?(this: Adapter<T, C>): Promise<unknown>;
406
481
  stop?(this: Adapter<T, C>, ...params: unknown[]): Promise<unknown>;
407
- link?(
482
+ attach?<R extends object>(
408
483
  this: Adapter<T, C>,
409
484
  patterns: (string | RegExp)[] | string | RegExp,
410
- target: object,
411
- ): Promise<{
412
- importedMap?: Map<string, object>;
413
- imported?: object;
414
- config?: {namespace?: string | string[]};
415
- }>;
485
+ target?: R,
486
+ ): Promise<R>;
416
487
  connected?(this: Adapter<T, C>): Promise<boolean>;
417
488
  error?(error: unknown, $meta: unknown): void;
418
489
  pack?(this: Adapter<T, C>, ...params: unknown[]): unknown;
@@ -487,6 +558,8 @@ export interface IAdapterRegistry {
487
558
  rpc: IRpcServer;
488
559
  local: ILocal;
489
560
  registry: IRegistry;
561
+ schema: IObjectSchema;
562
+ manifest?: IManifest;
490
563
  }): Promise<Adapter>;
491
564
  }
492
565
 
@@ -605,18 +678,27 @@ export type Errors<T> = {
605
678
 
606
679
  export interface IBaseConfig extends TObject<{
607
680
  watch: TObject<{
608
- test: TArray<TString>;
681
+ test?: TArray<TString>;
609
682
  }>;
610
683
  remote: TObject<{
611
- canSkipSocket: TBoolean;
684
+ canSkipSocket?: TBoolean;
612
685
  }>;
613
- adapter: TBoolean;
614
- orchestrator: TBoolean;
615
- test: TBoolean;
616
- error: TBoolean;
686
+ adapter: TBoolean | TObject;
687
+ orchestrator: TBoolean | TObject;
688
+ test: TBoolean | TObject;
689
+ error: TBoolean | TObject;
617
690
  gateway: TBoolean | TObject;
618
- sim: TBoolean;
619
- resolution: TBoolean;
691
+ sim: TBoolean | TObject;
692
+ resolution: TBoolean | TObject;
693
+ log: TBoolean | TObject;
694
+ apiSchema: TBoolean | TObject;
695
+ registry: TBoolean | TObject;
696
+ port: TBoolean | TObject;
697
+ codec: TBoolean | TObject;
698
+ local: TBoolean | TObject;
699
+ rpcServer: TBoolean | TObject;
700
+ restFs: TBoolean | TObject;
701
+ systemDebug: TBoolean | TObject;
620
702
  }> {
621
703
  additionalProperties: false;
622
704
  }
@@ -725,8 +807,25 @@ export type ChainStep =
725
807
 
726
808
  export type CheckpointFn = (this: IMeta, name: string, data?: unknown) => void;
727
809
 
810
+ /**
811
+ * Manifest — a shared mutable object passed to the `load` function that allows
812
+ * platforms to share information such as effective ports, URLs, or other
813
+ * runtime-resolved values across components.
814
+ *
815
+ * Properties are typically Promises (created via `Promise.withResolvers()`) that
816
+ * are resolved when one platform finishes a startup step (e.g. listening on a
817
+ * random port), and awaited by another platform or adapter during its own
818
+ * initialisation (e.g. constructing a backend URL from the effective port).
819
+ *
820
+ * Manifest properties can also be provided via CLI args using the
821
+ * `--manifest.<key>=<value>` syntax.
822
+ */
823
+ export interface IManifest {
824
+ [key: string]: unknown;
825
+ }
826
+
728
827
  export interface ILib {
729
- type: typeof Type;
828
+ type: BlongType;
730
829
  error: <T>(errors: T) => Record<keyof T, (params?: unknown, $meta?: IMeta) => ITypedError>;
731
830
  rename: <T extends object>(object: T, name: string) => T & {name: string};
732
831
  /**
@@ -773,26 +872,33 @@ export interface ILib {
773
872
  merge<T, S1, S2>(target: T, source1: S1, source2: S2): T & S1 & S2;
774
873
  merge<T, S1, S2, S3>(target: T, source1: S1, source2: S2, source3: S3): T & S1 & S2 & S3;
775
874
  merge<T>(...args: unknown[]): T;
875
+ mergeWithSymbols<T, S1>(target: T, source: S1): T & S1;
876
+ render: (what: object[] | object) => object;
877
+ crockfordEncode: (data: Uint8Array) => string;
878
+ crockfordDecode: (data: string) => Uint8Array;
776
879
  }
777
880
 
778
881
  export type ValidationFn = () => GatewaySchema;
779
- export interface IValidationProxy {
882
+ export interface IValidationProxy<T> {
780
883
  type: typeof Type;
781
884
  handler: {
782
885
  [name: string]: ValidationFn;
783
- };
886
+ } & IRemoteHandler;
784
887
  lib: ILib & {
785
888
  [name: string]: TSchema;
786
889
  };
787
890
  error: {
788
891
  [name: string]: (...params: unknown[]) => ITypedError;
789
892
  };
893
+ /** Collected object schemas accumulated so far; later `schema()` exports can reference earlier ones. */
894
+ schema: IObjectSchema;
895
+ config: T;
790
896
  }
791
- export type ValidationDefinition = (
792
- blong: IValidationProxy,
793
- ) => Record<string, ValidationFn | TSchema> | ValidationFn | ValidationFn[];
897
+ export type ValidationDefinition<T> = (
898
+ blong: IValidationProxy<T>,
899
+ ) => Promise<Record<string, ValidationFn | TSchema> | ValidationFn | ValidationFn[]>;
794
900
 
795
- export type ApiDefinition = (blong: IValidationProxy) =>
901
+ export type ApiDefinition<T> = (blong: IValidationProxy<T>) =>
796
902
  | {
797
903
  namespace:
798
904
  | string[]
@@ -838,6 +944,8 @@ export interface IHandlerProxy<T> {
838
944
  errors: {
839
945
  [name: string]: (...params: unknown[]) => ITypedError;
840
946
  };
947
+ /** Collected object schemas from all registered `schema()` exports. */
948
+ schema: IObjectSchema;
841
949
  utBus: {
842
950
  info: () => {encrypt: object; sign: object};
843
951
  };
@@ -859,8 +967,8 @@ export type ModuleApi = {
859
967
  config: Record<string, unknown>;
860
968
  parent: IAdapterFactory;
861
969
  error: (errors: object) => ModuleApi;
862
- validation: (
863
- method: ValidationDefinition | ValidationDefinition[],
970
+ validation: <T>(
971
+ method: ValidationDefinition<T> | ValidationDefinition<T>[],
864
972
  namespace?: string,
865
973
  ) => ModuleApi;
866
974
  sequence: (fn: () => Sequence) => ModuleApi;
@@ -873,7 +981,10 @@ export type ModuleApi = {
873
981
  };
874
982
 
875
983
  export interface SolutionFactory<T extends TSchema = TNever> {
876
- (definition: {type: typeof Type}): IModuleConfig<T> | Promise<IModuleConfig<T>>;
984
+ (definition: {
985
+ type: typeof Type;
986
+ manifest?: IManifest;
987
+ }): IModuleConfig<T> | Promise<IModuleConfig<T>>;
877
988
  }
878
989
 
879
990
  const Kind: symbol = Symbol.for('blong:kind');
@@ -921,9 +1032,13 @@ export interface IComponent {
921
1032
 
922
1033
  export const library = <T = Record<string, unknown>>(definition: Lib<T>): Lib<T> =>
923
1034
  Object.defineProperty(definition, Kind, {value: 'lib'});
924
- export const validation = (validation: ValidationDefinition): ValidationDefinition =>
925
- Object.defineProperty(validation, Kind, {value: 'validation'});
926
- export const api = (api: ApiDefinition): ApiDefinition =>
1035
+ export const validation = <T = Record<string, unknown>>(
1036
+ validation: ValidationDefinition<T>,
1037
+ ): ValidationDefinition<T> => Object.defineProperty(validation, Kind, {value: 'validation'});
1038
+ export const schema = <T = Record<string, unknown>>(
1039
+ schema: ValidationDefinition<T>,
1040
+ ): ValidationDefinition<T> => Object.defineProperty(schema, Kind, {value: 'schema'});
1041
+ export const api = <T = Record<string, unknown>>(api: ApiDefinition<T>): ApiDefinition<T> =>
927
1042
  Object.defineProperty(api, Kind, {value: 'api'});
928
1043
  export const model = <T extends IModelSpec>(
929
1044
  definition: () => () => Promise<T>,
@@ -931,10 +1046,10 @@ export const model = <T extends IModelSpec>(
931
1046
  export const fixture = <T extends IMock>(definition: () => T): (() => T) =>
932
1047
  Object.defineProperty(definition, Kind, {value: 'fixture'});
933
1048
 
934
- export const validationHandlers: (
1049
+ export const validationHandlers: <T>(
935
1050
  handlers: Record<string, TFunction<[ApiSchema]>>,
936
- ) => ValidationDefinition = handlers =>
937
- validation(() =>
1051
+ ) => ValidationDefinition<T> = handlers =>
1052
+ validation(async () =>
938
1053
  Object.fromEntries(
939
1054
  Object.entries(handlers).map(([name, handler]) => [
940
1055
  name,
@@ -989,6 +1104,7 @@ export const orchestrator = <T, C = AdapterContext>(
989
1104
  export type Kinds =
990
1105
  | 'lib'
991
1106
  | 'validation'
1107
+ | 'schema'
992
1108
  | 'api'
993
1109
  | 'solution'
994
1110
  | 'server'