@edgerules/portable 0.0.0-alpha.202607041229

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.
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Portable JSON format for EdgeRules.
3
+ *
4
+ * This file ships with EdgeRules and is the TypeScript contract a host / GUI uses to:
5
+ * 1. read the model using:
6
+ * - `service.get(path, filter?): PortableNode | PortableError`
7
+ * - `service.get("*", filter?): PortableRootContext | PortableError`
8
+ * 2. set new entities to the model using:
9
+ * - `service.set(path, PortableNode): PortableNode | PortableError`
10
+ *
11
+ * Filters select which view of an entry is returned:
12
+ * - "CONTEXT" (default) — runtime/data view: contexts, values, expressions, and function *schemas*.
13
+ * - "TYPE_DEFINITIONS" — type definitions only.
14
+ * - "FUNCTION_DEFINITIONS" — function definitions (parameters + body) only.
15
+ * - "ALL" — every view combined (context, type, and function definitions).
16
+ *
17
+ * On success the returned node is enriched with linked type information; otherwise a PortableError is returned.
18
+ */
19
+ /**
20
+ * JSON-serializable scalars only. Temporal values (date/time/datetime/duration/period) are not
21
+ * native JSON, so they travel as a PortableExpressionString — e.g. "date('2024-01-15')" or
22
+ * "duration('P4D')" — consistent with the Output EBNF `TemporalValue` constructors.
23
+ */
24
+ export type PortableScalar = string | number | boolean;
25
+ /**
26
+ * Any concrete JSON value a Portable data field may hold: a scalar, an array, an object, or an
27
+ * EdgeRules expression carried as a string.
28
+ */
29
+ export type PortableValue = PortableScalar | PortableValue[] | PortableContext | PortableExpressionString;
30
+ export type PortableTypeReference = 'number' | 'string' | 'boolean' | 'date' | 'time' | 'datetime' | 'duration' | 'period' | 'array' | (string & {});
31
+ /**
32
+ * An EdgeRules expression carried as a string, e.g. "applicant.income >= 30000".
33
+ *
34
+ * The EdgeRules DSL parser reads the string and parses it by these rules:
35
+ * "'John'" -> parsed as a string literal
36
+ * "applicant.income >= 30000" -> parsed as an expression
37
+ * "[1,2,3]" -> parsed as an array via expression parsing, but prefer a
38
+ * real JSON array [1,2,3] (a PortableValue), which is treated
39
+ * as data instead of DSL.
40
+ */
41
+ export type PortableExpressionString = string;
42
+ export interface PortableObject {
43
+ '@kind': string;
44
+ '@description'?: string;
45
+ }
46
+ /**
47
+ * A type node (`@kind: 'type'`): used as a typed hole / input slot in a context, a field in a
48
+ * type definition, an array element type (`items`), or a parameter/return type. Carries the
49
+ * declared `type` plus optional input metadata (`required`, `default`, `enum`, `writeOnly`).
50
+ * The input-metadata fields are meaningful only where the node is an input or type-definition
51
+ * field; they are ignored when it appears as a `@return` / `@parameters` descriptor.
52
+ */
53
+ export interface PortableTypedValue extends PortableObject {
54
+ '@kind': 'type';
55
+ /**
56
+ * The value's type: a scalar type name, the literal `'array'` for list types
57
+ * (the element type lives in `items`), or a user-defined type name (e.g. "Customer").
58
+ */
59
+ type: PortableTypeReference;
60
+ /**
61
+ * Every input is expected: an absent input yields a `Missing` special value.
62
+ * `required: true` is an additional validation — a supplied value that fails the
63
+ * requirement yields an `Invalid` special value. Mirrors JSON Schema / OpenAPI `required`.
64
+ */
65
+ required?: boolean;
66
+ /**
67
+ * True for input fields the host supplies: typed holes (e.g. `<boolean>`,
68
+ * `<number, required: true>`). These are write-only slots — the host provides
69
+ * a value, the engine never computes one. Mirrors OpenAPI `writeOnly`.
70
+ */
71
+ writeOnly?: boolean;
72
+ /**
73
+ * True for computed (engine-derived) data-context fields: constants and
74
+ * expressions the host must not supply. Mirrors OpenAPI `readOnly`.
75
+ * `readOnly` and `writeOnly` are mutually exclusive — a data-context leaf
76
+ * carries exactly one. Absent on type-definition fields and on
77
+ * `@parameters` / `@return` / `items` type references.
78
+ */
79
+ readOnly?: boolean;
80
+ /** Default applied when an optional input is missing. */
81
+ default?: PortableScalar | PortableScalar[];
82
+ /** Allowed values; supports string and numeric enums (scalar types only). */
83
+ enum?: PortableScalar[];
84
+ /** Element type node; present (and meaningful) only when `type` is "array". */
85
+ items?: PortableTypedValue | PortableTypeReference;
86
+ }
87
+ /**
88
+ * The value of any field inside a context node. Reserved `@`-prefixed keys carry
89
+ * string|number metadata (see the index signature below); all other keys hold a PortableNode.
90
+ */
91
+ export type PortableNode = PortableValue | PortableContext | PortableContext[] | PortableExpression | PortableTypedValue | PortableFunctionDefinition | PortableTypeDefinition | PortableInvocationDefinition;
92
+ /**
93
+ * A context node — the model's record/object construct. In EdgeRules a record literal *is* a
94
+ * context, so data records and model contexts are one and the same node.
95
+ *
96
+ * a plain JSON object with no `@kind` defaults to a context
97
+ */
98
+ export interface PortableContext {
99
+ '@kind'?: 'context';
100
+ '@description'?: string;
101
+ /**
102
+ * The `string | number` arm admits the reserved `@`-prefixed metadata keys (`@kind`,
103
+ * `@description`, and `@version` / `@model-name` on `PortableRootContext`); every other key is
104
+ * a field whose value is a PortableNode.
105
+ */
106
+ [key: string]: PortableNode | string | number | undefined;
107
+ }
108
+ export interface PortableRootContext extends PortableContext {
109
+ '@version'?: string | number;
110
+ '@model-name'?: string;
111
+ }
112
+ /**
113
+ * An expression node (`@kind: 'expression'`): a host-authored computed field.
114
+ * On set, provide only `@kind` and `expression`. On get, the engine adds the linked result
115
+ * `type` (and `items` for array results) and marks the node `readOnly`.
116
+ */
117
+ export interface PortableExpression extends PortableObject {
118
+ '@kind': 'expression';
119
+ expression: PortableValue;
120
+ /** Engine-supplied on get; omit on set. */
121
+ readOnly?: true;
122
+ /** Inferred (linked) type; engine-supplied on get, omitted on set. */
123
+ type?: PortableTypeReference;
124
+ /** Inferred element type when the result type is 'array'; get-only. */
125
+ items?: PortableTypedValue | PortableTypeReference;
126
+ }
127
+ /**
128
+ * Used for type definitions.
129
+ * The fields are either type assignments (for primitive types and arrays) or nested type definitions (for objects).
130
+ *
131
+ * Example EdgeRules DSL: `type Customer: { name: <string>; birthdate: <date>; income: <number, 0> }`
132
+ * is represented as:
133
+ * { '@kind': 'type-definition',
134
+ * name: { '@kind': 'type', type: 'string' },
135
+ * birthdate: { '@kind': 'type', type: 'date' },
136
+ * income: { '@kind': 'type', type: 'number', default: 0 }
137
+ * }
138
+ */
139
+ export interface PortableTypeDefinition extends PortableObject {
140
+ '@kind': 'type-definition';
141
+ /** The `string` arm admits the reserved `@kind` discriminant; every other key is a field node. */
142
+ [field: string]: PortableTypedValue | PortableTypeDefinition | string | undefined;
143
+ }
144
+ /**
145
+ * Used for setting or getting function definitions.
146
+ * The `@parameters` field holds the parameter type information, and the `@body` field holds the function body,
147
+ * which can be either a context (for multi-line functions) or an expression (for single-line functions).
148
+ *
149
+ * - If function has no parameters, empty object must be set or will be returned
150
+ * - Function must have a body
151
+ * - In `@parameters`, a `null` value denotes an untyped (unannotated) parameter
152
+ *
153
+ * To get function definition, use:
154
+ * - `service.get("calculateLoanOffer.*")`
155
+ * - `service.get("calculateLoanOffer", "FUNCTION_DEFINITIONS")` -> returns `calculateLoanOffer` definition
156
+ * - `service.get("*", "FUNCTION_DEFINITIONS")` -> returns all function definitions in the root context
157
+ */
158
+ export interface PortableFunctionDefinition extends PortableObject {
159
+ '@kind': 'function';
160
+ '@parameters': Record<string, PortableTypeReference | PortableTypedValue | null>;
161
+ '@body': PortableContext | PortableExpression;
162
+ }
163
+ /**
164
+ * Use only for getting function schemas, usage:
165
+ * - `service.get("calculateLoanOffer")` -> returns `calculateLoanOffer` schema
166
+ * - `service.get("*")` -> returns all function schemas in the context, because default filter is "CONTEXT"
167
+ */
168
+ export interface PortableFunctionSchema extends PortableObject {
169
+ '@kind': 'function-schema';
170
+ '@parameters': Record<string, PortableTypeReference | PortableTypedValue | null>;
171
+ '@return': PortableTypeReference | PortableTypedValue;
172
+ }
173
+ /**
174
+ * Used for setting or getting function invocation definitions.
175
+ * - `@method` holds the function name, can also hold decision table hit-policy keywords (`firstMatch`, `uniqueMatch`, ...).
176
+ * - `@arguments` holds the argument values; if the call takes no arguments, an empty array must be set.
177
+ * `@arguments` can also hold a decision table definition (a `PortableContext` with `inputs`, `rules`, and optional `default`).
178
+ *
179
+ * `@type` is available only in return object, it is linked type information for the invocation result, inferred by the engine and provided
180
+ * for the host's convenience.
181
+ */
182
+ export interface PortableInvocationDefinition extends PortableObject {
183
+ '@kind': 'invocation';
184
+ '@type'?: PortableTypeReference;
185
+ '@method': string;
186
+ '@arguments': PortableValue[];
187
+ }
188
+ /** Machine-readable discriminant of a `PortableError`. */
189
+ export type PortableErrorType =
190
+ /** A path segment does not resolve to any entry. */
191
+ 'EntryNotFound'
192
+ /** Invalid/empty path, type mismatch (e.g. indexing a record), out-of-bounds, or negative index. */
193
+ | 'WrongFieldPath'
194
+ /** A rename/insert collides with a name already present in the same context. */
195
+ | 'DuplicateName'
196
+ /** A mutation produced an incompatible type or broke an existing reference. */
197
+ | 'Linking'
198
+ /** An expression string or Portable payload failed to parse. */
199
+ | 'Parse'
200
+ /** Evaluation failed while executing the model (e.g. a runtime/type error). */
201
+ | 'Execution';
202
+ /** Where an error occurred inside EdgeRules DSL source, when the engine can pinpoint it. */
203
+ export interface PortableSourceLocation {
204
+ /** 1-based line within the offending expression/source. */
205
+ line?: number;
206
+ /** 1-based column within the offending expression/source. */
207
+ column?: number;
208
+ /** The offending expression, echoed back for display. */
209
+ expression?: PortableExpressionString;
210
+ }
211
+ /**
212
+ * A structured error returned or thrown across the host boundary.
213
+ * Discriminated by `type`; safe to surface `message` directly to the user.
214
+ */
215
+ export interface PortableError {
216
+ '@kind': 'error';
217
+ /** The discriminant a GUI switches on. */
218
+ type: PortableErrorType;
219
+ /** Human-readable description of what went wrong. */
220
+ message: string;
221
+ /** Model path the operation targeted, when path-based (CRUD ops, `execute` method). */
222
+ path?: string;
223
+ /**
224
+ * Secondary path for relational errors:
225
+ * - `DuplicateName`: the path of the existing entry it collided with.
226
+ * - `WrongFieldPath` on rename: the rejected target path.
227
+ */
228
+ conflictPath?: string;
229
+ /** Source location for `Parse`, `Linking`, and `Execution` errors. */
230
+ location?: PortableSourceLocation;
231
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Portable JSON format for EdgeRules.
3
+ *
4
+ * This file ships with EdgeRules and is the TypeScript contract a host / GUI uses to:
5
+ * 1. read the model using:
6
+ * - `service.get(path, filter?): PortableNode | PortableError`
7
+ * - `service.get("*", filter?): PortableRootContext | PortableError`
8
+ * 2. set new entities to the model using:
9
+ * - `service.set(path, PortableNode): PortableNode | PortableError`
10
+ *
11
+ * Filters select which view of an entry is returned:
12
+ * - "CONTEXT" (default) — runtime/data view: contexts, values, expressions, and function *schemas*.
13
+ * - "TYPE_DEFINITIONS" — type definitions only.
14
+ * - "FUNCTION_DEFINITIONS" — function definitions (parameters + body) only.
15
+ * - "ALL" — every view combined (context, type, and function definitions).
16
+ *
17
+ * On success the returned node is enriched with linked type information; otherwise a PortableError is returned.
18
+ */
19
+ export {};
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@edgerules/portable",
3
+ "version": "0.0.0-alpha.202607041229",
4
+ "type": "module",
5
+ "description": "Portable JSON type definitions for EdgeRules.",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/portable.d.ts",
9
+ "import": "./dist/portable.js"
10
+ }
11
+ },
12
+ "files": [
13
+ "dist/"
14
+ ],
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "devDependencies": {
19
+ "typescript": "^5.7.3"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc"
23
+ }
24
+ }