@ankhorage/contracts 1.11.0 → 1.12.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,11 @@
1
1
  # @ankhorage/contracts
2
2
 
3
+ ## 1.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 440f28e: Replace node-local prop bindings with app-level component data-binding contracts that reference data-source operations.
8
+
3
9
  ## 1.11.0
4
10
 
5
11
  ### Minor Changes
@@ -1,38 +1,93 @@
1
- import type { DbFilter, DbPage, DbSort } from './db';
1
+ import type { DataSourceId, EndpointId, OperationId } from './data';
2
+ export type ComponentInstanceId = string;
3
+ export type ComponentTypeId = string;
2
4
  export type BindingValue = string | number | boolean | null | readonly BindingValue[] | {
3
5
  readonly [key: string]: BindingValue;
4
6
  };
5
- export type BindingRefreshMode = 'focus' | 'live' | 'poll' | 'static';
6
- export interface DbCollectionQueryBinding {
7
- readonly collection: string;
8
- readonly schema?: string;
9
- readonly columns?: readonly string[];
10
- readonly filters?: readonly DbFilter[];
11
- readonly sort?: readonly DbSort[];
12
- readonly page?: DbPage;
13
- readonly refresh?: BindingRefreshMode;
14
- readonly pollIntervalMs?: number;
7
+ export type BindingDataPath = string;
8
+ export type BindingValueTransform = 'lowercase' | 'trim' | 'uppercase';
9
+ export interface BindingOperationRef {
10
+ readonly dataSourceId: DataSourceId;
11
+ readonly operationId: OperationId;
12
+ readonly endpointId?: EndpointId;
15
13
  }
16
14
  export type BindingValueSource = {
17
- readonly source: 'context';
18
- readonly path: string;
15
+ readonly kind: 'context';
16
+ readonly path: BindingDataPath;
17
+ } | {
18
+ readonly kind: 'event';
19
+ readonly path: BindingDataPath;
19
20
  } | {
20
- readonly source: 'db.collection';
21
- readonly query: DbCollectionQueryBinding;
21
+ readonly kind: 'literal';
22
+ readonly value: BindingValue;
22
23
  } | {
23
- readonly source: 'event';
24
- readonly path: string;
24
+ readonly kind: 'operation';
25
+ readonly operation: BindingOperationRef;
26
+ readonly path?: BindingDataPath;
25
27
  } | {
26
- readonly source: 'literal';
28
+ readonly kind: 'state';
29
+ readonly path: BindingDataPath;
30
+ };
31
+ export interface BindingValueExpression {
32
+ readonly source: BindingValueSource;
33
+ readonly transforms?: readonly BindingValueTransform[];
34
+ }
35
+ export interface BindingFallback {
36
+ readonly value?: BindingValue;
37
+ readonly source?: BindingValueSource;
38
+ }
39
+ export type BindingLifecycleState = 'empty' | 'error' | 'loading';
40
+ export interface BindingLifecycleBehavior {
41
+ readonly state: BindingLifecycleState;
42
+ readonly fallback?: BindingFallback;
43
+ readonly message?: string;
44
+ }
45
+ export interface PropBinding {
46
+ readonly source: BindingValueSource;
47
+ readonly fallback?: BindingFallback;
48
+ readonly loading?: BindingLifecycleBehavior;
49
+ readonly error?: BindingLifecycleBehavior;
50
+ readonly empty?: BindingLifecycleBehavior;
51
+ readonly transforms?: readonly BindingValueTransform[];
52
+ }
53
+ export type BindingInputValue = {
54
+ readonly kind: 'array';
55
+ readonly items: readonly BindingInputValue[];
56
+ } | {
57
+ readonly kind: 'literal';
27
58
  readonly value: BindingValue;
28
59
  } | {
29
- readonly source: 'state';
30
- readonly path: string;
60
+ readonly kind: 'object';
61
+ readonly fields: Readonly<Record<string, BindingInputValue>>;
62
+ } | {
63
+ readonly kind: 'source';
64
+ readonly source: BindingValueSource;
65
+ readonly transforms?: readonly BindingValueTransform[];
31
66
  };
32
- export type BindingValueTransform = 'lowercase' | 'trim' | 'uppercase';
33
- export interface NodePropBinding {
34
- readonly prop: string;
35
- readonly valueFrom: BindingValueSource;
36
- readonly transform?: BindingValueTransform | readonly BindingValueTransform[];
67
+ export type BindingInputMap = Readonly<Record<string, BindingInputValue>>;
68
+ export type BindingConditionOperator = 'eq' | 'exists' | 'neq' | 'notExists';
69
+ export interface BindingCondition {
70
+ readonly source: BindingValueSource;
71
+ readonly operator: BindingConditionOperator;
72
+ readonly value?: BindingValue;
73
+ }
74
+ export type EventBindingTarget = {
75
+ readonly kind: 'action';
76
+ readonly type: string;
77
+ } | {
78
+ readonly kind: 'operation';
79
+ readonly operation: BindingOperationRef;
80
+ };
81
+ export interface EventBinding {
82
+ readonly target: EventBindingTarget;
83
+ readonly input?: BindingInputMap;
84
+ readonly when?: BindingCondition;
85
+ }
86
+ export interface ComponentDataBinding {
87
+ readonly componentId: ComponentInstanceId;
88
+ readonly componentType?: ComponentTypeId;
89
+ readonly props?: Readonly<Record<string, PropBinding>>;
90
+ readonly events?: Readonly<Record<string, readonly EventBinding[]>>;
37
91
  }
92
+ export type ComponentDataBindingRegistry = Readonly<Record<ComponentInstanceId, ComponentDataBinding>>;
38
93
  //# sourceMappingURL=bindings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAErD,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,YAAY,EAAE,GACvB;IACE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC;CACtC,CAAC;AAEN,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEtE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,MAAM,kBAAkB,GAC1B;IACE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;CAC1C,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEN,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,GAAG,SAAS,qBAAqB,EAAE,CAAC;CAC/E"}
1
+ {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.js","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"","sourcesContent":["import type { DbFilter, DbPage, DbSort } from './db';\n\nexport type BindingValue =\n | string\n | number\n | boolean\n | null\n | readonly BindingValue[]\n | {\n readonly [key: string]: BindingValue;\n };\n\nexport type BindingRefreshMode = 'focus' | 'live' | 'poll' | 'static';\n\nexport interface DbCollectionQueryBinding {\n readonly collection: string;\n readonly schema?: string;\n readonly columns?: readonly string[];\n readonly filters?: readonly DbFilter[];\n readonly sort?: readonly DbSort[];\n readonly page?: DbPage;\n readonly refresh?: BindingRefreshMode;\n readonly pollIntervalMs?: number;\n}\n\nexport type BindingValueSource =\n | {\n readonly source: 'context';\n readonly path: string;\n }\n | {\n readonly source: 'db.collection';\n readonly query: DbCollectionQueryBinding;\n }\n | {\n readonly source: 'event';\n readonly path: string;\n }\n | {\n readonly source: 'literal';\n readonly value: BindingValue;\n }\n | {\n readonly source: 'state';\n readonly path: string;\n };\n\nexport type BindingValueTransform = 'lowercase' | 'trim' | 'uppercase';\n\nexport interface NodePropBinding {\n readonly prop: string;\n readonly valueFrom: BindingValueSource;\n readonly transform?: BindingValueTransform | readonly BindingValueTransform[];\n}\n"]}
1
+ {"version":3,"file":"bindings.js","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"","sourcesContent":["import type { DataSourceId, EndpointId, OperationId } from './data';\n\nexport type ComponentInstanceId = string;\nexport type ComponentTypeId = string;\n\nexport type BindingValue =\n | string\n | number\n | boolean\n | null\n | readonly BindingValue[]\n | {\n readonly [key: string]: BindingValue;\n };\n\nexport type BindingDataPath = string;\n\nexport type BindingValueTransform = 'lowercase' | 'trim' | 'uppercase';\n\nexport interface BindingOperationRef {\n readonly dataSourceId: DataSourceId;\n readonly operationId: OperationId;\n readonly endpointId?: EndpointId;\n}\n\nexport type BindingValueSource =\n | {\n readonly kind: 'context';\n readonly path: BindingDataPath;\n }\n | {\n readonly kind: 'event';\n readonly path: BindingDataPath;\n }\n | {\n readonly kind: 'literal';\n readonly value: BindingValue;\n }\n | {\n readonly kind: 'operation';\n readonly operation: BindingOperationRef;\n readonly path?: BindingDataPath;\n }\n | {\n readonly kind: 'state';\n readonly path: BindingDataPath;\n };\n\nexport interface BindingValueExpression {\n readonly source: BindingValueSource;\n readonly transforms?: readonly BindingValueTransform[];\n}\n\nexport interface BindingFallback {\n readonly value?: BindingValue;\n readonly source?: BindingValueSource;\n}\n\nexport type BindingLifecycleState = 'empty' | 'error' | 'loading';\n\nexport interface BindingLifecycleBehavior {\n readonly state: BindingLifecycleState;\n readonly fallback?: BindingFallback;\n readonly message?: string;\n}\n\nexport interface PropBinding {\n readonly source: BindingValueSource;\n readonly fallback?: BindingFallback;\n readonly loading?: BindingLifecycleBehavior;\n readonly error?: BindingLifecycleBehavior;\n readonly empty?: BindingLifecycleBehavior;\n readonly transforms?: readonly BindingValueTransform[];\n}\n\nexport type BindingInputValue =\n | {\n readonly kind: 'array';\n readonly items: readonly BindingInputValue[];\n }\n | {\n readonly kind: 'literal';\n readonly value: BindingValue;\n }\n | {\n readonly kind: 'object';\n readonly fields: Readonly<Record<string, BindingInputValue>>;\n }\n | {\n readonly kind: 'source';\n readonly source: BindingValueSource;\n readonly transforms?: readonly BindingValueTransform[];\n };\n\nexport type BindingInputMap = Readonly<Record<string, BindingInputValue>>;\n\nexport type BindingConditionOperator = 'eq' | 'exists' | 'neq' | 'notExists';\n\nexport interface BindingCondition {\n readonly source: BindingValueSource;\n readonly operator: BindingConditionOperator;\n readonly value?: BindingValue;\n}\n\nexport type EventBindingTarget =\n | {\n readonly kind: 'action';\n readonly type: string;\n }\n | {\n readonly kind: 'operation';\n readonly operation: BindingOperationRef;\n };\n\nexport interface EventBinding {\n readonly target: EventBindingTarget;\n readonly input?: BindingInputMap;\n readonly when?: BindingCondition;\n}\n\nexport interface ComponentDataBinding {\n readonly componentId: ComponentInstanceId;\n readonly componentType?: ComponentTypeId;\n readonly props?: Readonly<Record<string, PropBinding>>;\n readonly events?: Readonly<Record<string, readonly EventBinding[]>>;\n}\n\nexport type ComponentDataBindingRegistry = Readonly<\n Record<ComponentInstanceId, ComponentDataBinding>\n>;\n"]}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { ColorHarmony } from '@ankhorage/color-theory';
2
2
  import type { AuthFlowConfig, AuthIdentifierKind, AuthSignUpField } from './auth';
3
- import type { NodePropBinding } from './bindings';
3
+ import type { ComponentDataBindingRegistry } from './bindings';
4
+ import type { DataSourceRegistry } from './data';
4
5
  export interface ThemeModeConfig {
5
6
  primaryColor: string;
6
7
  harmony: ColorHarmony;
@@ -57,82 +58,6 @@ export type Action = AlertAction | ConsoleAction | FilterAction | NavigateAction
57
58
  export type ManifestValue = string | number | boolean | null | readonly ManifestValue[] | {
58
59
  readonly [key: string]: ManifestValue;
59
60
  };
60
- export type ActionValue = ManifestValue;
61
- export type ActionBindingPayload = Record<string, ActionValue>;
62
- export type ActionConditionSource = 'context' | 'event' | 'state';
63
- export type ActionConditionOperator = 'eq' | 'exists' | 'neq' | 'notExists';
64
- export interface ActionCondition {
65
- readonly source: ActionConditionSource;
66
- readonly path: string;
67
- readonly operator: ActionConditionOperator;
68
- readonly value?: ActionValue;
69
- }
70
- export type ActionValueSource = {
71
- readonly source: 'context';
72
- readonly path: string;
73
- } | {
74
- readonly source: 'event';
75
- readonly path: string;
76
- } | {
77
- readonly source: 'literal';
78
- readonly value: ActionValue;
79
- } | {
80
- readonly source: 'state';
81
- readonly path: string;
82
- };
83
- export type ActionValueTransform = 'lowercase' | 'trim' | 'uppercase';
84
- export interface ActionValueBinding {
85
- readonly valueFrom: ActionValueSource;
86
- readonly transform?: ActionValueTransform | readonly ActionValueTransform[];
87
- }
88
- export interface ActionBinding<TType extends string = string, TPayload extends object = ActionBindingPayload> {
89
- readonly type: TType;
90
- readonly payload?: TPayload;
91
- readonly when?: ActionCondition;
92
- }
93
- export type DbPersistMode = 'columns' | 'json';
94
- export interface DbPersistFieldBinding {
95
- readonly field: string;
96
- readonly valueFrom: ActionValueSource;
97
- readonly transform?: ActionValueTransform | readonly ActionValueTransform[];
98
- }
99
- export interface DbPersistActionPayload {
100
- readonly collection: string;
101
- readonly kind?: string;
102
- readonly mode?: DbPersistMode;
103
- readonly jsonField?: string;
104
- readonly values: readonly DbPersistFieldBinding[];
105
- }
106
- export interface DbPersistActionBinding extends ActionBinding<'db.persist', DbPersistActionPayload> {
107
- readonly payload: DbPersistActionPayload;
108
- }
109
- export interface EmailSendActionPayload {
110
- readonly to: string;
111
- readonly subject?: string;
112
- readonly body?: string;
113
- readonly bodyFrom?: ActionValueSource;
114
- }
115
- export interface EmailSendActionBinding extends ActionBinding<'email.send', EmailSendActionPayload> {
116
- readonly payload: EmailSendActionPayload;
117
- }
118
- export type KnownActionBinding = DbPersistActionBinding | EmailSendActionBinding;
119
- export type UiNodeEventBindings = Record<string, readonly ActionBinding<string, object>[]>;
120
- export interface CommandDto<TType extends string = string, TPayload extends object = Record<string, ActionValue>> {
121
- readonly type: TType;
122
- readonly payload: TPayload;
123
- }
124
- export type DbPersistOperation = 'insert';
125
- export type DbPersistCommandValues = Record<string, ActionValue>;
126
- export interface DbPersistCommandPayload {
127
- readonly operation: DbPersistOperation;
128
- readonly collection: string;
129
- readonly kind?: string;
130
- readonly mode?: DbPersistMode;
131
- readonly jsonField?: string;
132
- readonly values: DbPersistCommandValues;
133
- }
134
- export type DbPersistCommand = CommandDto<'db.persist.command', DbPersistCommandPayload>;
135
- export type KnownCommandDto = DbPersistCommand;
136
61
  export type ComponentEventPayloadValue = ManifestValue;
137
62
  export interface ComponentEventDto<TType extends string = string, TPayload extends object = Record<string, ComponentEventPayloadValue>> {
138
63
  readonly type: TType;
@@ -192,10 +117,8 @@ export interface UiNode {
192
117
  type: string;
193
118
  alias?: string;
194
119
  props?: Record<string, unknown>;
195
- bindings?: readonly NodePropBinding[];
196
120
  children?: UiNode[];
197
121
  style?: Record<string, number | string>;
198
- events?: UiNodeEventBindings;
199
122
  }
200
123
  export interface ScreenSpec {
201
124
  id: string;
@@ -284,6 +207,8 @@ export interface AppManifest {
284
207
  infra: InfraManifest;
285
208
  navigator: NavigatorSpec;
286
209
  screens: Record<string, ScreenSpec>;
210
+ dataSources?: DataSourceRegistry;
211
+ dataBindings?: ComponentDataBindingRegistry;
287
212
  settings: {
288
213
  apiBaseUrl?: string;
289
214
  localization: {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwPA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAGpE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe;IACf,uBAAuB;IACvB,iBAAiB;IACjB,oBAAoB;IACpB,qBAAqB;IACrB,eAAe;IACf,YAAY;IACZ,OAAO;IACP,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,SAAS;IACT,aAAa;IACb,mBAAmB;IACnB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,mBAAmB;IACnB,kBAAkB;IAClB,QAAQ;IACR,iBAAiB;IACjB,SAAS;CACD,CAAC;AAGX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,CAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAG/D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAU,CAAC;AAGrD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAG3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAU,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,CAAU,CAAC;AAIpD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAGhF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,qBAAqB,CAAU,CAAC;AAGpF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,wBAAwB;IAC3B,WAAW;IACX,UAAU;IACV,aAAa;IACb,WAAW;CACH,CAAC","sourcesContent":["import type { ColorHarmony } from '@ankhorage/color-theory';\n\nimport type { AuthFlowConfig, AuthIdentifierKind, AuthSignUpField } from './auth';\nimport type { NodePropBinding } from './bindings';\n\nexport interface ThemeModeConfig {\n primaryColor: string;\n harmony: ColorHarmony;\n}\n\nexport interface ThemeConfig {\n id: string;\n name: string;\n light: ThemeModeConfig;\n dark: ThemeModeConfig;\n}\n\nexport type ActionType =\n | 'navigate'\n | 'alert'\n | 'console'\n | 'toggleDarkMode'\n | 'setLanguage'\n | 'search'\n | 'filter';\n\nexport interface NavigateAction {\n type: 'navigate';\n payload: {\n route: string;\n params?: Record<string, number | string>;\n };\n}\n\nexport interface AlertAction {\n type: 'alert';\n payload?: {\n message?: string;\n };\n}\n\nexport interface ConsoleAction {\n type: 'console';\n payload?: Record<string, unknown>;\n}\n\nexport interface ToggleDarkModeAction {\n type: 'toggleDarkMode';\n payload?: never;\n}\n\nexport interface SetLanguageAction {\n type: 'setLanguage';\n payload: {\n locale: string;\n };\n}\n\nexport interface SearchAction {\n type: 'search';\n payload: {\n query: string;\n scope?: string;\n };\n}\n\nexport interface FilterAction {\n type: 'filter';\n payload: {\n filterKey: string;\n filterValue: string;\n };\n}\n\nexport type Action =\n | AlertAction\n | ConsoleAction\n | FilterAction\n | NavigateAction\n | SearchAction\n | SetLanguageAction\n | ToggleDarkModeAction;\n\nexport type ManifestValue =\n | string\n | number\n | boolean\n | null\n | readonly ManifestValue[]\n | { readonly [key: string]: ManifestValue };\n\nexport type ActionValue = ManifestValue;\n\nexport type ActionBindingPayload = Record<string, ActionValue>;\n\nexport type ActionConditionSource = 'context' | 'event' | 'state';\n\nexport type ActionConditionOperator = 'eq' | 'exists' | 'neq' | 'notExists';\n\nexport interface ActionCondition {\n readonly source: ActionConditionSource;\n readonly path: string;\n readonly operator: ActionConditionOperator;\n readonly value?: ActionValue;\n}\n\nexport type ActionValueSource =\n | {\n readonly source: 'context';\n readonly path: string;\n }\n | {\n readonly source: 'event';\n readonly path: string;\n }\n | {\n readonly source: 'literal';\n readonly value: ActionValue;\n }\n | {\n readonly source: 'state';\n readonly path: string;\n };\n\nexport type ActionValueTransform = 'lowercase' | 'trim' | 'uppercase';\n\nexport interface ActionValueBinding {\n readonly valueFrom: ActionValueSource;\n readonly transform?: ActionValueTransform | readonly ActionValueTransform[];\n}\n\nexport interface ActionBinding<\n TType extends string = string,\n TPayload extends object = ActionBindingPayload,\n> {\n readonly type: TType;\n readonly payload?: TPayload;\n readonly when?: ActionCondition;\n}\n\nexport type DbPersistMode = 'columns' | 'json';\n\nexport interface DbPersistFieldBinding {\n readonly field: string;\n readonly valueFrom: ActionValueSource;\n readonly transform?: ActionValueTransform | readonly ActionValueTransform[];\n}\n\nexport interface DbPersistActionPayload {\n readonly collection: string;\n readonly kind?: string;\n readonly mode?: DbPersistMode;\n readonly jsonField?: string;\n readonly values: readonly DbPersistFieldBinding[];\n}\n\nexport interface DbPersistActionBinding extends ActionBinding<\n 'db.persist',\n DbPersistActionPayload\n> {\n readonly payload: DbPersistActionPayload;\n}\n\nexport interface EmailSendActionPayload {\n readonly to: string;\n readonly subject?: string;\n readonly body?: string;\n readonly bodyFrom?: ActionValueSource;\n}\n\nexport interface EmailSendActionBinding extends ActionBinding<\n 'email.send',\n EmailSendActionPayload\n> {\n readonly payload: EmailSendActionPayload;\n}\n\nexport type KnownActionBinding = DbPersistActionBinding | EmailSendActionBinding;\n\nexport type UiNodeEventBindings = Record<string, readonly ActionBinding<string, object>[]>;\n\nexport interface CommandDto<\n TType extends string = string,\n TPayload extends object = Record<string, ActionValue>,\n> {\n readonly type: TType;\n readonly payload: TPayload;\n}\n\nexport type DbPersistOperation = 'insert';\n\nexport type DbPersistCommandValues = Record<string, ActionValue>;\n\nexport interface DbPersistCommandPayload {\n readonly operation: DbPersistOperation;\n readonly collection: string;\n readonly kind?: string;\n readonly mode?: DbPersistMode;\n readonly jsonField?: string;\n readonly values: DbPersistCommandValues;\n}\n\nexport type DbPersistCommand = CommandDto<'db.persist.command', DbPersistCommandPayload>;\n\nexport type KnownCommandDto = DbPersistCommand;\n\nexport type ComponentEventPayloadValue = ManifestValue;\n\nexport interface ComponentEventDto<\n TType extends string = string,\n TPayload extends object = Record<string, ComponentEventPayloadValue>,\n> {\n readonly type: TType;\n readonly sourceNodeId: string;\n readonly payload: TPayload;\n}\n\nexport type FormSubmitValues = Record<string, ComponentEventPayloadValue>;\n\nexport type FormSubmitEventDto = ComponentEventDto<\n 'form.submit',\n {\n readonly values: FormSubmitValues;\n }\n>;\n\nexport type ButtonPressEventDto = ComponentEventDto<'button.press', Record<string, never>>;\n\nexport interface CollectionItemPressPayload {\n readonly itemId: string | number;\n readonly item: Record<string, ComponentEventPayloadValue>;\n}\n\nexport type CollectionItemPressEventDto = ComponentEventDto<\n 'collection.itemPress',\n CollectionItemPressPayload\n>;\n\nexport type ComponentEventDtoKind =\n | ButtonPressEventDto['type']\n | CollectionItemPressEventDto['type']\n | FormSubmitEventDto['type'];\n\nexport type KnownComponentEventDto =\n | ButtonPressEventDto\n | CollectionItemPressEventDto\n | FormSubmitEventDto;\n\nexport const NAVIGATOR_TYPES = ['stack', 'tabs', 'drawer'] as const;\nexport type NavigatorType = (typeof NAVIGATOR_TYPES)[number];\n\nexport const APP_CATEGORIES = [\n 'books_reading',\n 'business_productivity',\n 'developer_tools',\n 'education_learning',\n 'entertainment_media',\n 'finance_money',\n 'food_drink',\n 'games',\n 'graphics_design',\n 'health_fitness',\n 'kids_family',\n 'lifestyle',\n 'medical',\n 'music_audio',\n 'navigation_travel',\n 'news_magazines',\n 'photo_video',\n 'reference',\n 'shopping_commerce',\n 'social_community',\n 'sports',\n 'utilities_tools',\n 'weather',\n] as const;\nexport type AppCategory = (typeof APP_CATEGORIES)[number];\n\nexport const DEPLOYMENT_TARGETS = ['minikube'] as const;\nexport type KnownDeploymentTarget = (typeof DEPLOYMENT_TARGETS)[number];\nexport type DeploymentTarget = KnownDeploymentTarget | (string & {});\n\nexport const DATABASE_PROVIDERS = ['supabase'] as const;\nexport type KnownDatabaseProvider = (typeof DATABASE_PROVIDERS)[number];\nexport type DatabaseProvider = KnownDatabaseProvider | (string & {});\n\nexport const DATABASE_TIERS = ['dev', 'prod'] as const;\nexport type DatabaseTier = (typeof DATABASE_TIERS)[number];\n\nexport const STORAGE_PROVIDERS = ['auto', 's3', 'r2'] as const;\nexport type StorageProvider = (typeof STORAGE_PROVIDERS)[number];\n\nexport const AUTHZ_KINDS = ['RBAC', 'ABAC'] as const;\nexport type AuthzKind = (typeof AUTHZ_KINDS)[number];\n\nexport const AUTHZ_ENGINES = ['cerbos', 'native'] as const;\nexport type AuthzEngine = (typeof AUTHZ_ENGINES)[number];\n\nexport const AUTH_SCOPES = ['global', 'none', 'integrated'] as const;\nexport type AuthScope = (typeof AUTH_SCOPES)[number];\n\nexport const AUTH_PROVIDERS = ['supabase'] as const;\nexport type KnownAuthProvider = (typeof AUTH_PROVIDERS)[number];\nexport type AuthProvider = KnownAuthProvider | (string & {});\n\nexport const AUTH_SIGN_IN_IDENTIFIERS = ['email', 'username', 'phone'] as const;\nexport type AuthSignInIdentifier = AuthIdentifierKind;\n\nexport const AUTH_SIGN_UP_POLICIES = ['autoSignIn', 'requireVerification'] as const;\nexport type AuthSignUpPolicy = (typeof AUTH_SIGN_UP_POLICIES)[number];\n\nexport const AUTH_PROFILE_FIELDS = [\n ...AUTH_SIGN_IN_IDENTIFIERS,\n 'firstName',\n 'lastName',\n 'displayName',\n 'avatarUrl',\n] as const;\nexport type KnownAuthProfileField = (typeof AUTH_PROFILE_FIELDS)[number];\nexport type AuthProfileField = KnownAuthProfileField | (string & {});\n\nexport interface IconSpec {\n name: string;\n provider?: string;\n size?: number | string;\n color?: string;\n}\n\nexport interface UiNode {\n id: string;\n type: string;\n alias?: string;\n props?: Record<string, unknown>;\n bindings?: readonly NodePropBinding[];\n children?: UiNode[];\n style?: Record<string, number | string>;\n events?: UiNodeEventBindings;\n}\n\nexport interface ScreenSpec {\n id: string;\n name: string;\n title?: string;\n description?: string;\n root: UiNode;\n}\n\nexport interface NavigatorSpec {\n type: NavigatorType;\n initialRouteName?: string;\n routes: RouteDefinition[];\n options?: Record<string, unknown>;\n}\n\nexport interface RouteDefinition {\n name: string;\n path?: string;\n label?: string;\n icon?: IconSpec;\n hideInTabBar?: boolean;\n guards?: string[];\n screenId?: string;\n navigator?: NavigatorSpec;\n}\n\nexport interface DeploymentSpec {\n target: DeploymentTarget;\n monitoring: boolean;\n}\n\nexport interface DatabaseSpec {\n provider: DatabaseProvider;\n tier: DatabaseTier;\n}\n\nexport interface StorageSpec {\n provider: StorageProvider;\n buckets: string[];\n}\n\nexport interface AuthzSpec {\n kind: AuthzKind;\n engine: AuthzEngine;\n}\n\nexport interface AuthSignInSpec {\n identifiers: AuthSignInIdentifier[];\n}\n\nexport interface AuthSignUpSpec {\n requiredFields: AuthSignUpField[];\n optionalFields?: AuthSignUpField[];\n signUpPolicy?: AuthSignUpPolicy;\n}\n\nexport interface AuthProfileSpec {\n fields: AuthProfileField[];\n}\n\nexport interface AuthSpec {\n scope: AuthScope;\n provider: AuthProvider;\n authorization: AuthzSpec;\n flow?: AuthFlowConfig;\n signIn?: AuthSignInSpec;\n signUp?: AuthSignUpSpec;\n profile?: AuthProfileSpec;\n}\n\nexport interface NetworkingSpec {\n domain?: string;\n cdn: boolean;\n}\n\nexport interface InfraManifest {\n deployment?: DeploymentSpec;\n auth?: AuthSpec;\n database?: DatabaseSpec;\n storage?: StorageSpec;\n networking?: NetworkingSpec;\n plugins: string[];\n pluginsConfig?: Record<string, unknown>;\n}\n\nexport interface AppManifest {\n metadata: {\n name: string;\n slug: string;\n version: string;\n themeId: string;\n created?: string;\n updated?: string;\n };\n themes: ThemeConfig[];\n activeThemeId: string;\n activeThemeMode?: 'dark' | 'light';\n infra: InfraManifest;\n navigator: NavigatorSpec;\n screens: Record<string, ScreenSpec>;\n settings: {\n apiBaseUrl?: string;\n localization: {\n defaultLocale: string;\n locales: string[];\n };\n authFlow: AuthFlowConfig;\n };\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsIA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAGpE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe;IACf,uBAAuB;IACvB,iBAAiB;IACjB,oBAAoB;IACpB,qBAAqB;IACrB,eAAe;IACf,YAAY;IACZ,OAAO;IACP,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,SAAS;IACT,aAAa;IACb,mBAAmB;IACnB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,mBAAmB;IACnB,kBAAkB;IAClB,QAAQ;IACR,iBAAiB;IACjB,SAAS;CACD,CAAC;AAGX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,CAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAG/D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAU,CAAC;AAGrD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAG3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAU,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,CAAU,CAAC;AAIpD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAGhF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,qBAAqB,CAAU,CAAC;AAGpF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,wBAAwB;IAC3B,WAAW;IACX,UAAU;IACV,aAAa;IACb,WAAW;CACH,CAAC","sourcesContent":["import type { ColorHarmony } from '@ankhorage/color-theory';\n\nimport type { AuthFlowConfig, AuthIdentifierKind, AuthSignUpField } from './auth';\nimport type { ComponentDataBindingRegistry } from './bindings';\nimport type { DataSourceRegistry } from './data';\n\nexport interface ThemeModeConfig {\n primaryColor: string;\n harmony: ColorHarmony;\n}\n\nexport interface ThemeConfig {\n id: string;\n name: string;\n light: ThemeModeConfig;\n dark: ThemeModeConfig;\n}\n\nexport type ActionType =\n | 'navigate'\n | 'alert'\n | 'console'\n | 'toggleDarkMode'\n | 'setLanguage'\n | 'search'\n | 'filter';\n\nexport interface NavigateAction {\n type: 'navigate';\n payload: {\n route: string;\n params?: Record<string, number | string>;\n };\n}\n\nexport interface AlertAction {\n type: 'alert';\n payload?: {\n message?: string;\n };\n}\n\nexport interface ConsoleAction {\n type: 'console';\n payload?: Record<string, unknown>;\n}\n\nexport interface ToggleDarkModeAction {\n type: 'toggleDarkMode';\n payload?: never;\n}\n\nexport interface SetLanguageAction {\n type: 'setLanguage';\n payload: {\n locale: string;\n };\n}\n\nexport interface SearchAction {\n type: 'search';\n payload: {\n query: string;\n scope?: string;\n };\n}\n\nexport interface FilterAction {\n type: 'filter';\n payload: {\n filterKey: string;\n filterValue: string;\n };\n}\n\nexport type Action =\n | AlertAction\n | ConsoleAction\n | FilterAction\n | NavigateAction\n | SearchAction\n | SetLanguageAction\n | ToggleDarkModeAction;\n\nexport type ManifestValue =\n | string\n | number\n | boolean\n | null\n | readonly ManifestValue[]\n | { readonly [key: string]: ManifestValue };\n\nexport type ComponentEventPayloadValue = ManifestValue;\n\nexport interface ComponentEventDto<\n TType extends string = string,\n TPayload extends object = Record<string, ComponentEventPayloadValue>,\n> {\n readonly type: TType;\n readonly sourceNodeId: string;\n readonly payload: TPayload;\n}\n\nexport type FormSubmitValues = Record<string, ComponentEventPayloadValue>;\n\nexport type FormSubmitEventDto = ComponentEventDto<\n 'form.submit',\n {\n readonly values: FormSubmitValues;\n }\n>;\n\nexport type ButtonPressEventDto = ComponentEventDto<'button.press', Record<string, never>>;\n\nexport interface CollectionItemPressPayload {\n readonly itemId: string | number;\n readonly item: Record<string, ComponentEventPayloadValue>;\n}\n\nexport type CollectionItemPressEventDto = ComponentEventDto<\n 'collection.itemPress',\n CollectionItemPressPayload\n>;\n\nexport type ComponentEventDtoKind =\n | ButtonPressEventDto['type']\n | CollectionItemPressEventDto['type']\n | FormSubmitEventDto['type'];\n\nexport type KnownComponentEventDto =\n | ButtonPressEventDto\n | CollectionItemPressEventDto\n | FormSubmitEventDto;\n\nexport const NAVIGATOR_TYPES = ['stack', 'tabs', 'drawer'] as const;\nexport type NavigatorType = (typeof NAVIGATOR_TYPES)[number];\n\nexport const APP_CATEGORIES = [\n 'books_reading',\n 'business_productivity',\n 'developer_tools',\n 'education_learning',\n 'entertainment_media',\n 'finance_money',\n 'food_drink',\n 'games',\n 'graphics_design',\n 'health_fitness',\n 'kids_family',\n 'lifestyle',\n 'medical',\n 'music_audio',\n 'navigation_travel',\n 'news_magazines',\n 'photo_video',\n 'reference',\n 'shopping_commerce',\n 'social_community',\n 'sports',\n 'utilities_tools',\n 'weather',\n] as const;\nexport type AppCategory = (typeof APP_CATEGORIES)[number];\n\nexport const DEPLOYMENT_TARGETS = ['minikube'] as const;\nexport type KnownDeploymentTarget = (typeof DEPLOYMENT_TARGETS)[number];\nexport type DeploymentTarget = KnownDeploymentTarget | (string & {});\n\nexport const DATABASE_PROVIDERS = ['supabase'] as const;\nexport type KnownDatabaseProvider = (typeof DATABASE_PROVIDERS)[number];\nexport type DatabaseProvider = KnownDatabaseProvider | (string & {});\n\nexport const DATABASE_TIERS = ['dev', 'prod'] as const;\nexport type DatabaseTier = (typeof DATABASE_TIERS)[number];\n\nexport const STORAGE_PROVIDERS = ['auto', 's3', 'r2'] as const;\nexport type StorageProvider = (typeof STORAGE_PROVIDERS)[number];\n\nexport const AUTHZ_KINDS = ['RBAC', 'ABAC'] as const;\nexport type AuthzKind = (typeof AUTHZ_KINDS)[number];\n\nexport const AUTHZ_ENGINES = ['cerbos', 'native'] as const;\nexport type AuthzEngine = (typeof AUTHZ_ENGINES)[number];\n\nexport const AUTH_SCOPES = ['global', 'none', 'integrated'] as const;\nexport type AuthScope = (typeof AUTH_SCOPES)[number];\n\nexport const AUTH_PROVIDERS = ['supabase'] as const;\nexport type KnownAuthProvider = (typeof AUTH_PROVIDERS)[number];\nexport type AuthProvider = KnownAuthProvider | (string & {});\n\nexport const AUTH_SIGN_IN_IDENTIFIERS = ['email', 'username', 'phone'] as const;\nexport type AuthSignInIdentifier = AuthIdentifierKind;\n\nexport const AUTH_SIGN_UP_POLICIES = ['autoSignIn', 'requireVerification'] as const;\nexport type AuthSignUpPolicy = (typeof AUTH_SIGN_UP_POLICIES)[number];\n\nexport const AUTH_PROFILE_FIELDS = [\n ...AUTH_SIGN_IN_IDENTIFIERS,\n 'firstName',\n 'lastName',\n 'displayName',\n 'avatarUrl',\n] as const;\nexport type KnownAuthProfileField = (typeof AUTH_PROFILE_FIELDS)[number];\nexport type AuthProfileField = KnownAuthProfileField | (string & {});\n\nexport interface IconSpec {\n name: string;\n provider?: string;\n size?: number | string;\n color?: string;\n}\n\nexport interface UiNode {\n id: string;\n type: string;\n alias?: string;\n props?: Record<string, unknown>;\n children?: UiNode[];\n style?: Record<string, number | string>;\n}\n\nexport interface ScreenSpec {\n id: string;\n name: string;\n title?: string;\n description?: string;\n root: UiNode;\n}\n\nexport interface NavigatorSpec {\n type: NavigatorType;\n initialRouteName?: string;\n routes: RouteDefinition[];\n options?: Record<string, unknown>;\n}\n\nexport interface RouteDefinition {\n name: string;\n path?: string;\n label?: string;\n icon?: IconSpec;\n hideInTabBar?: boolean;\n guards?: string[];\n screenId?: string;\n navigator?: NavigatorSpec;\n}\n\nexport interface DeploymentSpec {\n target: DeploymentTarget;\n monitoring: boolean;\n}\n\nexport interface DatabaseSpec {\n provider: DatabaseProvider;\n tier: DatabaseTier;\n}\n\nexport interface StorageSpec {\n provider: StorageProvider;\n buckets: string[];\n}\n\nexport interface AuthzSpec {\n kind: AuthzKind;\n engine: AuthzEngine;\n}\n\nexport interface AuthSignInSpec {\n identifiers: AuthSignInIdentifier[];\n}\n\nexport interface AuthSignUpSpec {\n requiredFields: AuthSignUpField[];\n optionalFields?: AuthSignUpField[];\n signUpPolicy?: AuthSignUpPolicy;\n}\n\nexport interface AuthProfileSpec {\n fields: AuthProfileField[];\n}\n\nexport interface AuthSpec {\n scope: AuthScope;\n provider: AuthProvider;\n authorization: AuthzSpec;\n flow?: AuthFlowConfig;\n signIn?: AuthSignInSpec;\n signUp?: AuthSignUpSpec;\n profile?: AuthProfileSpec;\n}\n\nexport interface NetworkingSpec {\n domain?: string;\n cdn: boolean;\n}\n\nexport interface InfraManifest {\n deployment?: DeploymentSpec;\n auth?: AuthSpec;\n database?: DatabaseSpec;\n storage?: StorageSpec;\n networking?: NetworkingSpec;\n plugins: string[];\n pluginsConfig?: Record<string, unknown>;\n}\n\nexport interface AppManifest {\n metadata: {\n name: string;\n slug: string;\n version: string;\n themeId: string;\n created?: string;\n updated?: string;\n };\n themes: ThemeConfig[];\n activeThemeId: string;\n activeThemeMode?: 'dark' | 'light';\n infra: InfraManifest;\n navigator: NavigatorSpec;\n screens: Record<string, ScreenSpec>;\n dataSources?: DataSourceRegistry;\n dataBindings?: ComponentDataBindingRegistry;\n settings: {\n apiBaseUrl?: string;\n localization: {\n defaultLocale: string;\n locales: string[];\n };\n authFlow: AuthFlowConfig;\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/contracts",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "main": "./dist/index.js",
5
5
  "dependencies": {
6
6
  "@ankhorage/color-theory": "^0.0.7"
@@ -1,96 +1,316 @@
1
1
  import { describe, expect, it } from 'bun:test';
2
2
 
3
3
  import type {
4
+ AppManifest,
5
+ BindingInputMap,
4
6
  BindingValueSource,
5
- DbCollectionQueryBinding,
6
- NodePropBinding,
7
- UiNode,
7
+ ComponentDataBinding,
8
+ ComponentDataBindingRegistry,
9
+ EventBinding,
10
+ PropBinding,
8
11
  } from './index';
9
12
 
10
- describe('binding contracts', () => {
11
- it('serializes a node prop bound to state', () => {
12
- const binding: NodePropBinding = {
13
- prop: 'value',
14
- valueFrom: {
15
- source: 'state',
16
- path: 'forms.contact.values.firstname',
17
- },
18
- transform: 'trim',
19
- };
20
- const node: UiNode = {
21
- id: 'firstname-input',
22
- type: 'Input',
13
+ function assertSerializable<TValue>(value: TValue): void {
14
+ expect(JSON.parse(JSON.stringify(value))).toEqual(value);
15
+ }
16
+
17
+ describe('component data-binding contracts', () => {
18
+ it('serializes a component prop bound to an operation response path', () => {
19
+ const binding: ComponentDataBinding = {
20
+ componentId: 'hero-title',
21
+ componentType: 'Text',
23
22
  props: {
24
- label: 'Firstname',
23
+ children: {
24
+ source: {
25
+ kind: 'operation',
26
+ operation: {
27
+ dataSourceId: 'cms',
28
+ endpointId: 'pages',
29
+ operationId: 'pages.getHome',
30
+ },
31
+ path: '$.data.title',
32
+ },
33
+ fallback: {
34
+ value: 'Untitled',
35
+ },
36
+ loading: {
37
+ state: 'loading',
38
+ fallback: {
39
+ value: 'Loading…',
40
+ },
41
+ },
42
+ error: {
43
+ state: 'error',
44
+ message: 'Could not load title.',
45
+ fallback: {
46
+ value: 'Untitled',
47
+ },
48
+ },
49
+ transforms: ['trim'],
50
+ },
25
51
  },
26
- bindings: [binding],
27
52
  };
28
53
 
29
- expect(JSON.parse(JSON.stringify(node))).toEqual(node);
30
- expect(node.bindings?.[0]?.valueFrom.source).toBe('state');
54
+ assertSerializable(binding);
55
+ expect(binding.props?.children?.source.kind).toBe('operation');
31
56
  });
32
57
 
33
- it('serializes a node prop bound to a DB collection query', () => {
34
- const query: DbCollectionQueryBinding = {
35
- collection: 'posts',
36
- schema: 'public',
37
- columns: ['id', 'title', 'published'],
38
- filters: [{ field: 'published', operator: 'eq', value: true }],
39
- sort: [{ field: 'created_at', direction: 'desc' }],
40
- page: { limit: 10, offset: 0 },
41
- refresh: 'live',
42
- };
43
- const node: UiNode = {
44
- id: 'posts-list',
45
- type: 'CollectionList',
46
- bindings: [
47
- {
48
- prop: 'items',
49
- valueFrom: {
50
- source: 'db.collection',
51
- query,
58
+ it('serializes literal, context, event, state, and operation value sources', () => {
59
+ const sources: readonly BindingValueSource[] = [
60
+ { kind: 'literal', value: { fallback: 'Untitled' } },
61
+ { kind: 'context', path: 'auth.user.displayName' },
62
+ { kind: 'event', path: 'payload.values.search' },
63
+ { kind: 'state', path: 'forms.search.query' },
64
+ {
65
+ kind: 'operation',
66
+ operation: {
67
+ dataSourceId: 'search-api',
68
+ operationId: 'search.query',
69
+ },
70
+ path: '$.results',
71
+ },
72
+ ];
73
+
74
+ assertSerializable(sources);
75
+ expect(sources.map((source) => source.kind)).toEqual([
76
+ 'literal',
77
+ 'context',
78
+ 'event',
79
+ 'state',
80
+ 'operation',
81
+ ]);
82
+ });
83
+
84
+ it('serializes an event binding that executes a data-source operation', () => {
85
+ const input: BindingInputMap = {
86
+ email: {
87
+ kind: 'source',
88
+ source: {
89
+ kind: 'event',
90
+ path: 'payload.values.email',
91
+ },
92
+ transforms: ['trim', 'lowercase'],
93
+ },
94
+ message: {
95
+ kind: 'source',
96
+ source: {
97
+ kind: 'event',
98
+ path: 'payload.values.message',
99
+ },
100
+ },
101
+ source: {
102
+ kind: 'literal',
103
+ value: 'contact-form',
104
+ },
105
+ metadata: {
106
+ kind: 'object',
107
+ fields: {
108
+ userId: {
109
+ kind: 'source',
110
+ source: {
111
+ kind: 'context',
112
+ path: 'auth.user.id',
113
+ },
52
114
  },
53
115
  },
54
- ],
116
+ },
117
+ };
118
+
119
+ const binding: EventBinding = {
120
+ target: {
121
+ kind: 'operation',
122
+ operation: {
123
+ dataSourceId: 'contact-api',
124
+ endpointId: 'messages',
125
+ operationId: 'messages.create',
126
+ },
127
+ },
128
+ input,
129
+ when: {
130
+ source: {
131
+ kind: 'event',
132
+ path: 'payload.values.email',
133
+ },
134
+ operator: 'exists',
135
+ },
55
136
  };
56
137
 
57
- expect(JSON.parse(JSON.stringify(node))).toEqual(node);
58
- expect(node.bindings?.[0]?.valueFrom.source).toBe('db.collection');
138
+ assertSerializable(binding);
139
+ expect(binding.target.kind).toBe('operation');
140
+ expect(binding.input?.email?.kind).toBe('source');
59
141
  });
60
142
 
61
- it('supports literal, context, and event value sources', () => {
62
- const sources: readonly BindingValueSource[] = [
63
- { source: 'literal', value: { fallback: 'Untitled' } },
64
- { source: 'context', path: 'auth.user.displayName' },
65
- { source: 'event', path: 'payload.values.search' },
66
- ];
143
+ it('serializes an event binding that targets a named action', () => {
144
+ const binding: EventBinding = {
145
+ target: {
146
+ kind: 'action',
147
+ type: 'toast.show',
148
+ },
149
+ input: {
150
+ message: {
151
+ kind: 'literal',
152
+ value: 'Saved successfully.',
153
+ },
154
+ },
155
+ };
67
156
 
68
- expect(JSON.parse(JSON.stringify(sources))).toEqual(sources);
69
- expect(sources.map((source) => source.source)).toEqual(['literal', 'context', 'event']);
157
+ assertSerializable(binding);
158
+ expect(binding.target.kind).toBe('action');
70
159
  });
71
160
 
72
- it('supports static, focus, poll, and live refresh intent', () => {
73
- const refreshModes = ['static', 'focus', 'poll', 'live'] as const;
74
- const bindings = refreshModes.map(
75
- (refresh): NodePropBinding => ({
76
- prop: `items.${refresh}`,
77
- valueFrom: {
78
- source: 'db.collection',
79
- query: {
80
- collection: 'posts',
81
- refresh,
82
- pollIntervalMs: refresh === 'poll' ? 30_000 : undefined,
161
+ it('serializes component data-binding registries', () => {
162
+ const bindings: ComponentDataBindingRegistry = {
163
+ 'submit-button': {
164
+ componentId: 'submit-button',
165
+ componentType: 'Button',
166
+ props: {
167
+ children: {
168
+ source: {
169
+ kind: 'literal',
170
+ value: 'Send',
171
+ },
172
+ },
173
+ disabled: {
174
+ source: {
175
+ kind: 'state',
176
+ path: 'forms.contact.isSubmitting',
177
+ },
83
178
  },
84
179
  },
85
- }),
86
- );
180
+ events: {
181
+ press: [
182
+ {
183
+ target: {
184
+ kind: 'operation',
185
+ operation: {
186
+ dataSourceId: 'contact-api',
187
+ operationId: 'messages.create',
188
+ },
189
+ },
190
+ },
191
+ ],
192
+ },
193
+ },
194
+ };
87
195
 
88
- expect(JSON.parse(JSON.stringify(bindings))).toEqual(bindings);
89
- expect(bindings.map((binding) => binding.valueFrom.source)).toEqual([
90
- 'db.collection',
91
- 'db.collection',
92
- 'db.collection',
93
- 'db.collection',
94
- ]);
196
+ assertSerializable(bindings);
197
+ expect(bindings['submit-button']?.events?.press?.[0]?.target.kind).toBe('operation');
198
+ });
199
+
200
+ it('serializes app-level dataSources and dataBindings on the manifest', () => {
201
+ const propBinding: PropBinding = {
202
+ source: {
203
+ kind: 'operation',
204
+ operation: {
205
+ dataSourceId: 'cms',
206
+ endpointId: 'pages',
207
+ operationId: 'pages.getHome',
208
+ },
209
+ path: '$.data.heroTitle',
210
+ },
211
+ };
212
+
213
+ const manifest: AppManifest = {
214
+ metadata: {
215
+ name: 'Demo',
216
+ slug: 'demo',
217
+ version: '1.0.0',
218
+ themeId: 'default',
219
+ },
220
+ themes: [
221
+ {
222
+ id: 'default',
223
+ name: 'Default',
224
+ light: {
225
+ primaryColor: '#3366ff',
226
+ harmony: 'analogous',
227
+ },
228
+ dark: {
229
+ primaryColor: '#3366ff',
230
+ harmony: 'analogous',
231
+ },
232
+ },
233
+ ],
234
+ activeThemeId: 'default',
235
+ infra: {
236
+ plugins: [],
237
+ },
238
+ navigator: {
239
+ type: 'stack',
240
+ routes: [
241
+ {
242
+ name: 'home',
243
+ screenId: 'home',
244
+ },
245
+ ],
246
+ },
247
+ screens: {
248
+ home: {
249
+ id: 'home',
250
+ name: 'Home',
251
+ root: {
252
+ id: 'screen-root',
253
+ type: 'Screen',
254
+ children: [
255
+ {
256
+ id: 'hero-title',
257
+ type: 'Text',
258
+ },
259
+ ],
260
+ },
261
+ },
262
+ },
263
+ dataSources: {
264
+ cms: {
265
+ id: 'cms',
266
+ kind: 'rest',
267
+ baseUrl: 'https://cms.example.com',
268
+ endpoints: {
269
+ pages: {
270
+ id: 'pages',
271
+ kind: 'http',
272
+ path: '/pages/home',
273
+ operations: {
274
+ 'pages.getHome': {
275
+ id: 'pages.getHome',
276
+ endpointId: 'pages',
277
+ protocol: 'http',
278
+ intent: 'read',
279
+ method: 'GET',
280
+ path: '/pages/home',
281
+ },
282
+ },
283
+ },
284
+ },
285
+ },
286
+ },
287
+ dataBindings: {
288
+ 'hero-title': {
289
+ componentId: 'hero-title',
290
+ componentType: 'Text',
291
+ props: {
292
+ children: propBinding,
293
+ },
294
+ },
295
+ },
296
+ settings: {
297
+ localization: {
298
+ defaultLocale: 'en',
299
+ locales: ['en'],
300
+ },
301
+ authFlow: {
302
+ signInRoute: '/sign-in',
303
+ signUpRoute: '/sign-up',
304
+ signOutRoute: '/sign-out',
305
+ forgotPasswordRoute: '/forgot-password',
306
+ postSignInRoute: '/',
307
+ unauthorizedRoute: '/sign-in',
308
+ },
309
+ },
310
+ };
311
+
312
+ assertSerializable(manifest);
313
+ expect(manifest.dataBindings?.['hero-title']?.props?.children?.source.kind).toBe('operation');
314
+ expect(manifest.dataSources?.cms?.kind).toBe('rest');
95
315
  });
96
316
  });
package/src/bindings.ts CHANGED
@@ -1,4 +1,7 @@
1
- import type { DbFilter, DbPage, DbSort } from './db';
1
+ import type { DataSourceId, EndpointId, OperationId } from './data';
2
+
3
+ export type ComponentInstanceId = string;
4
+ export type ComponentTypeId = string;
2
5
 
3
6
  export type BindingValue =
4
7
  | string
@@ -10,45 +13,118 @@ export type BindingValue =
10
13
  readonly [key: string]: BindingValue;
11
14
  };
12
15
 
13
- export type BindingRefreshMode = 'focus' | 'live' | 'poll' | 'static';
16
+ export type BindingDataPath = string;
17
+
18
+ export type BindingValueTransform = 'lowercase' | 'trim' | 'uppercase';
14
19
 
15
- export interface DbCollectionQueryBinding {
16
- readonly collection: string;
17
- readonly schema?: string;
18
- readonly columns?: readonly string[];
19
- readonly filters?: readonly DbFilter[];
20
- readonly sort?: readonly DbSort[];
21
- readonly page?: DbPage;
22
- readonly refresh?: BindingRefreshMode;
23
- readonly pollIntervalMs?: number;
20
+ export interface BindingOperationRef {
21
+ readonly dataSourceId: DataSourceId;
22
+ readonly operationId: OperationId;
23
+ readonly endpointId?: EndpointId;
24
24
  }
25
25
 
26
26
  export type BindingValueSource =
27
27
  | {
28
- readonly source: 'context';
29
- readonly path: string;
28
+ readonly kind: 'context';
29
+ readonly path: BindingDataPath;
30
30
  }
31
31
  | {
32
- readonly source: 'db.collection';
33
- readonly query: DbCollectionQueryBinding;
32
+ readonly kind: 'event';
33
+ readonly path: BindingDataPath;
34
34
  }
35
35
  | {
36
- readonly source: 'event';
37
- readonly path: string;
36
+ readonly kind: 'literal';
37
+ readonly value: BindingValue;
38
+ }
39
+ | {
40
+ readonly kind: 'operation';
41
+ readonly operation: BindingOperationRef;
42
+ readonly path?: BindingDataPath;
43
+ }
44
+ | {
45
+ readonly kind: 'state';
46
+ readonly path: BindingDataPath;
47
+ };
48
+
49
+ export interface BindingValueExpression {
50
+ readonly source: BindingValueSource;
51
+ readonly transforms?: readonly BindingValueTransform[];
52
+ }
53
+
54
+ export interface BindingFallback {
55
+ readonly value?: BindingValue;
56
+ readonly source?: BindingValueSource;
57
+ }
58
+
59
+ export type BindingLifecycleState = 'empty' | 'error' | 'loading';
60
+
61
+ export interface BindingLifecycleBehavior {
62
+ readonly state: BindingLifecycleState;
63
+ readonly fallback?: BindingFallback;
64
+ readonly message?: string;
65
+ }
66
+
67
+ export interface PropBinding {
68
+ readonly source: BindingValueSource;
69
+ readonly fallback?: BindingFallback;
70
+ readonly loading?: BindingLifecycleBehavior;
71
+ readonly error?: BindingLifecycleBehavior;
72
+ readonly empty?: BindingLifecycleBehavior;
73
+ readonly transforms?: readonly BindingValueTransform[];
74
+ }
75
+
76
+ export type BindingInputValue =
77
+ | {
78
+ readonly kind: 'array';
79
+ readonly items: readonly BindingInputValue[];
38
80
  }
39
81
  | {
40
- readonly source: 'literal';
82
+ readonly kind: 'literal';
41
83
  readonly value: BindingValue;
42
84
  }
43
85
  | {
44
- readonly source: 'state';
45
- readonly path: string;
86
+ readonly kind: 'object';
87
+ readonly fields: Readonly<Record<string, BindingInputValue>>;
88
+ }
89
+ | {
90
+ readonly kind: 'source';
91
+ readonly source: BindingValueSource;
92
+ readonly transforms?: readonly BindingValueTransform[];
46
93
  };
47
94
 
48
- export type BindingValueTransform = 'lowercase' | 'trim' | 'uppercase';
95
+ export type BindingInputMap = Readonly<Record<string, BindingInputValue>>;
96
+
97
+ export type BindingConditionOperator = 'eq' | 'exists' | 'neq' | 'notExists';
49
98
 
50
- export interface NodePropBinding {
51
- readonly prop: string;
52
- readonly valueFrom: BindingValueSource;
53
- readonly transform?: BindingValueTransform | readonly BindingValueTransform[];
99
+ export interface BindingCondition {
100
+ readonly source: BindingValueSource;
101
+ readonly operator: BindingConditionOperator;
102
+ readonly value?: BindingValue;
54
103
  }
104
+
105
+ export type EventBindingTarget =
106
+ | {
107
+ readonly kind: 'action';
108
+ readonly type: string;
109
+ }
110
+ | {
111
+ readonly kind: 'operation';
112
+ readonly operation: BindingOperationRef;
113
+ };
114
+
115
+ export interface EventBinding {
116
+ readonly target: EventBindingTarget;
117
+ readonly input?: BindingInputMap;
118
+ readonly when?: BindingCondition;
119
+ }
120
+
121
+ export interface ComponentDataBinding {
122
+ readonly componentId: ComponentInstanceId;
123
+ readonly componentType?: ComponentTypeId;
124
+ readonly props?: Readonly<Record<string, PropBinding>>;
125
+ readonly events?: Readonly<Record<string, readonly EventBinding[]>>;
126
+ }
127
+
128
+ export type ComponentDataBindingRegistry = Readonly<
129
+ Record<ComponentInstanceId, ComponentDataBinding>
130
+ >;
@@ -5,8 +5,6 @@ import { COLOR_HARMONIES } from '@ankhorage/color-theory';
5
5
  import { describe, expect, it } from 'bun:test';
6
6
 
7
7
  import {
8
- type ActionBinding,
9
- type ActionValueSource,
10
8
  APP_CATEGORIES,
11
9
  type AppCategory,
12
10
  AUTH_PROVIDERS,
@@ -21,22 +19,16 @@ import {
21
19
  type DbAdapter,
22
20
  type DbAdminAdapter,
23
21
  type DbChangeEvent,
24
- type DbPersistActionBinding,
25
- type DbPersistCommand,
26
22
  type DbRealtimeAdapter,
27
23
  DEPLOYMENT_TARGETS,
28
- type EmailSendActionBinding,
29
24
  type FormSubmitEventDto,
30
25
  type ImageAssetSource,
31
- type KnownActionBinding,
32
- type KnownCommandDto,
33
26
  NAVIGATOR_TYPES,
34
27
  type StoragePublicUrlResult,
35
28
  type StorageResult,
36
29
  type StorageUploadResult,
37
30
  type ThemeConfig,
38
31
  type ThemeModeConfig,
39
- type UiNode,
40
32
  } from './index';
41
33
 
42
34
  async function collectTypeScriptFiles(directory: string): Promise<string[]> {
@@ -236,55 +228,6 @@ describe('contracts', () => {
236
228
  expect(JSON.parse(JSON.stringify(source))).toEqual(source);
237
229
  });
238
230
 
239
- it('serializes node event bindings for submit actions', () => {
240
- const node: UiNode = {
241
- id: 'contact-form',
242
- type: 'Form',
243
- props: {
244
- title: 'Contact us',
245
- },
246
- events: {
247
- submit: [
248
- {
249
- type: 'email.send',
250
- payload: {
251
- to: 'info@example.com',
252
- subject: 'New contact message',
253
- bodyFrom: 'payload.values.message',
254
- },
255
- },
256
- {
257
- type: 'db.persist',
258
- payload: {
259
- collection: 'contact_messages',
260
- mode: 'columns',
261
- },
262
- },
263
- ],
264
- },
265
- };
266
-
267
- expect(JSON.parse(JSON.stringify(node))).toEqual(node);
268
- expect(node.events?.submit?.map((action) => action.type)).toEqual(['email.send', 'db.persist']);
269
- });
270
-
271
- it('accepts conditional node event bindings', () => {
272
- const binding: ActionBinding = {
273
- type: 'db.persist',
274
- payload: {
275
- collection: 'contact_messages',
276
- },
277
- when: {
278
- source: 'event',
279
- path: 'payload.values.email',
280
- operator: 'exists',
281
- },
282
- };
283
-
284
- expect(binding.when?.operator).toBe('exists');
285
- expect(binding.payload?.collection).toBe('contact_messages');
286
- });
287
-
288
231
  it('serializes normalized form submit event DTOs', () => {
289
232
  const event: FormSubmitEventDto = {
290
233
  type: 'form.submit',
@@ -344,121 +287,6 @@ describe('contracts', () => {
344
287
  expect(knownEventType).toBe('form.submit');
345
288
  });
346
289
 
347
- it('serializes provider-neutral value sources for action payloads', () => {
348
- const sources: readonly ActionValueSource[] = [
349
- { source: 'event', path: 'payload.values.email' },
350
- { source: 'literal', value: 'website-contact-form' },
351
- { source: 'context', path: 'auth.user.id' },
352
- { source: 'state', path: 'forms.contact.isSubmitting' },
353
- ];
354
-
355
- expect(JSON.parse(JSON.stringify(sources))).toEqual(sources);
356
- expect(sources.map((source) => source.source)).toEqual([
357
- 'event',
358
- 'literal',
359
- 'context',
360
- 'state',
361
- ]);
362
- });
363
-
364
- it('serializes a typed db.persist action binding', () => {
365
- const binding: DbPersistActionBinding = {
366
- type: 'db.persist',
367
- payload: {
368
- collection: 'contact_messages',
369
- mode: 'columns',
370
- values: [
371
- {
372
- field: 'firstname',
373
- valueFrom: { source: 'event', path: 'payload.values.firstname' },
374
- transform: 'trim',
375
- },
376
- {
377
- field: 'message',
378
- valueFrom: { source: 'event', path: 'payload.values.message' },
379
- },
380
- {
381
- field: 'source',
382
- valueFrom: { source: 'literal', value: 'website-contact-form' },
383
- },
384
- ],
385
- },
386
- };
387
-
388
- expect(JSON.parse(JSON.stringify(binding))).toEqual(binding);
389
- expect(binding.payload.values.map((value) => value.field)).toEqual([
390
- 'firstname',
391
- 'message',
392
- 'source',
393
- ]);
394
- });
395
-
396
- it('serializes a typed email.send action binding', () => {
397
- const binding: EmailSendActionBinding = {
398
- type: 'email.send',
399
- payload: {
400
- to: 'info@example.com',
401
- subject: 'New contact message',
402
- bodyFrom: { source: 'event', path: 'payload.values.message' },
403
- },
404
- };
405
-
406
- expect(JSON.parse(JSON.stringify(binding))).toEqual(binding);
407
- expect(binding.payload.bodyFrom?.source).toBe('event');
408
- });
409
-
410
- it('accepts typed action bindings in node event bindings', () => {
411
- const persist: DbPersistActionBinding = {
412
- type: 'db.persist',
413
- payload: {
414
- collection: 'contact_messages',
415
- values: [
416
- {
417
- field: 'message',
418
- valueFrom: { source: 'event', path: 'payload.values.message' },
419
- },
420
- ],
421
- },
422
- };
423
- const email: EmailSendActionBinding = {
424
- type: 'email.send',
425
- payload: {
426
- to: 'info@example.com',
427
- bodyFrom: { source: 'event', path: 'payload.values.message' },
428
- },
429
- };
430
- const node: UiNode = {
431
- id: 'contact-form',
432
- type: 'Form',
433
- events: {
434
- submit: [persist, email],
435
- },
436
- };
437
- const known: KnownActionBinding = persist;
438
-
439
- expect(node.events?.submit?.map((action) => action.type)).toEqual(['db.persist', 'email.send']);
440
- expect(known.type).toBe('db.persist');
441
- });
442
-
443
- it('serializes a normalized db.persist command DTO', () => {
444
- const command: DbPersistCommand = {
445
- type: 'db.persist.command',
446
- payload: {
447
- operation: 'insert',
448
- collection: 'contact_messages',
449
- mode: 'columns',
450
- values: {
451
- firstname: 'Fabio',
452
- message: 'This is my contact message',
453
- },
454
- },
455
- };
456
- const knownCommand: KnownCommandDto = command;
457
-
458
- expect(JSON.parse(JSON.stringify(command))).toEqual(command);
459
- expect(knownCommand.type).toBe('db.persist.command');
460
- });
461
-
462
290
  it('accepts a provider-neutral CRUD database adapter', async () => {
463
291
  const adapter: DbAdapter = {
464
292
  capabilities: {
package/src/types.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { ColorHarmony } from '@ankhorage/color-theory';
2
2
 
3
3
  import type { AuthFlowConfig, AuthIdentifierKind, AuthSignUpField } from './auth';
4
- import type { NodePropBinding } from './bindings';
4
+ import type { ComponentDataBindingRegistry } from './bindings';
5
+ import type { DataSourceRegistry } from './data';
5
6
 
6
7
  export interface ThemeModeConfig {
7
8
  primaryColor: string;
@@ -89,121 +90,6 @@ export type ManifestValue =
89
90
  | readonly ManifestValue[]
90
91
  | { readonly [key: string]: ManifestValue };
91
92
 
92
- export type ActionValue = ManifestValue;
93
-
94
- export type ActionBindingPayload = Record<string, ActionValue>;
95
-
96
- export type ActionConditionSource = 'context' | 'event' | 'state';
97
-
98
- export type ActionConditionOperator = 'eq' | 'exists' | 'neq' | 'notExists';
99
-
100
- export interface ActionCondition {
101
- readonly source: ActionConditionSource;
102
- readonly path: string;
103
- readonly operator: ActionConditionOperator;
104
- readonly value?: ActionValue;
105
- }
106
-
107
- export type ActionValueSource =
108
- | {
109
- readonly source: 'context';
110
- readonly path: string;
111
- }
112
- | {
113
- readonly source: 'event';
114
- readonly path: string;
115
- }
116
- | {
117
- readonly source: 'literal';
118
- readonly value: ActionValue;
119
- }
120
- | {
121
- readonly source: 'state';
122
- readonly path: string;
123
- };
124
-
125
- export type ActionValueTransform = 'lowercase' | 'trim' | 'uppercase';
126
-
127
- export interface ActionValueBinding {
128
- readonly valueFrom: ActionValueSource;
129
- readonly transform?: ActionValueTransform | readonly ActionValueTransform[];
130
- }
131
-
132
- export interface ActionBinding<
133
- TType extends string = string,
134
- TPayload extends object = ActionBindingPayload,
135
- > {
136
- readonly type: TType;
137
- readonly payload?: TPayload;
138
- readonly when?: ActionCondition;
139
- }
140
-
141
- export type DbPersistMode = 'columns' | 'json';
142
-
143
- export interface DbPersistFieldBinding {
144
- readonly field: string;
145
- readonly valueFrom: ActionValueSource;
146
- readonly transform?: ActionValueTransform | readonly ActionValueTransform[];
147
- }
148
-
149
- export interface DbPersistActionPayload {
150
- readonly collection: string;
151
- readonly kind?: string;
152
- readonly mode?: DbPersistMode;
153
- readonly jsonField?: string;
154
- readonly values: readonly DbPersistFieldBinding[];
155
- }
156
-
157
- export interface DbPersistActionBinding extends ActionBinding<
158
- 'db.persist',
159
- DbPersistActionPayload
160
- > {
161
- readonly payload: DbPersistActionPayload;
162
- }
163
-
164
- export interface EmailSendActionPayload {
165
- readonly to: string;
166
- readonly subject?: string;
167
- readonly body?: string;
168
- readonly bodyFrom?: ActionValueSource;
169
- }
170
-
171
- export interface EmailSendActionBinding extends ActionBinding<
172
- 'email.send',
173
- EmailSendActionPayload
174
- > {
175
- readonly payload: EmailSendActionPayload;
176
- }
177
-
178
- export type KnownActionBinding = DbPersistActionBinding | EmailSendActionBinding;
179
-
180
- export type UiNodeEventBindings = Record<string, readonly ActionBinding<string, object>[]>;
181
-
182
- export interface CommandDto<
183
- TType extends string = string,
184
- TPayload extends object = Record<string, ActionValue>,
185
- > {
186
- readonly type: TType;
187
- readonly payload: TPayload;
188
- }
189
-
190
- export type DbPersistOperation = 'insert';
191
-
192
- export type DbPersistCommandValues = Record<string, ActionValue>;
193
-
194
- export interface DbPersistCommandPayload {
195
- readonly operation: DbPersistOperation;
196
- readonly collection: string;
197
- readonly kind?: string;
198
- readonly mode?: DbPersistMode;
199
- readonly jsonField?: string;
200
- readonly values: DbPersistCommandValues;
201
- }
202
-
203
- export type DbPersistCommand = CommandDto<'db.persist.command', DbPersistCommandPayload>;
204
-
205
- export type KnownCommandDto = DbPersistCommand;
206
-
207
93
  export type ComponentEventPayloadValue = ManifestValue;
208
94
 
209
95
  export interface ComponentEventDto<
@@ -331,10 +217,8 @@ export interface UiNode {
331
217
  type: string;
332
218
  alias?: string;
333
219
  props?: Record<string, unknown>;
334
- bindings?: readonly NodePropBinding[];
335
220
  children?: UiNode[];
336
221
  style?: Record<string, number | string>;
337
- events?: UiNodeEventBindings;
338
222
  }
339
223
 
340
224
  export interface ScreenSpec {
@@ -437,6 +321,8 @@ export interface AppManifest {
437
321
  infra: InfraManifest;
438
322
  navigator: NavigatorSpec;
439
323
  screens: Record<string, ScreenSpec>;
324
+ dataSources?: DataSourceRegistry;
325
+ dataBindings?: ComponentDataBindingRegistry;
440
326
  settings: {
441
327
  apiBaseUrl?: string;
442
328
  localization: {