@cynodia/axiom-compiler 0.7.0-alpha.2 → 0.8.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/normalize.d.ts +7 -1
- package/dist/normalize.js +28 -1
- package/dist/server.js +40 -6
- package/package.json +3 -3
package/dist/normalize.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ApplicationGraph, ApplicationIR, ValidationIssue, ValidationResult } from '@cynodia/axiom-core';
|
|
2
|
-
import type { RendererCapabilities } from '@cynodia/axiom-core';
|
|
2
|
+
import type { RendererCapabilities, TriggerRuntimeCapabilities } from '@cynodia/axiom-core';
|
|
3
3
|
export declare class GraphValidationError extends Error {
|
|
4
4
|
readonly problems: ValidationIssue[];
|
|
5
5
|
constructor(result: ValidationResult);
|
|
@@ -21,6 +21,12 @@ export interface CompileOptions {
|
|
|
21
21
|
* rejected at compile time rather than discovered on screen.
|
|
22
22
|
*/
|
|
23
23
|
renderer?: RendererCapabilities;
|
|
24
|
+
/**
|
|
25
|
+
* The trigger runtime the IR is being compiled for. Defaults to the browser's real (empty)
|
|
26
|
+
* capability set, because the browser runtime implements no trigger kind — so a
|
|
27
|
+
* client-authority trigger is rejected at compile time rather than compiled inert.
|
|
28
|
+
*/
|
|
29
|
+
triggerRuntime?: TriggerRuntimeCapabilities;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* Validates a graph and normalizes it into the runtime-ready IR: references resolved,
|
package/dist/normalize.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { actionAuthority, actionGuards, authorityContext, inferExpressionType, inferLocationType, itemTypeOf, locationFieldIds, locationRootStateId, referencedIds, resolvePresentationMap, semanticContextFromGraph, stateAuthority, validateGraph, } from '@cynodia/axiom-core';
|
|
2
2
|
import { isUINode, stripAuthoringMetadata } from '@cynodia/axiom-core';
|
|
3
|
-
import { BROWSER_RENDERER_CAPABILITIES } from '@cynodia/axiom-runtime';
|
|
3
|
+
import { BROWSER_RENDERER_CAPABILITIES, BROWSER_TRIGGER_CAPABILITIES } from '@cynodia/axiom-runtime';
|
|
4
4
|
export class GraphValidationError extends Error {
|
|
5
5
|
problems;
|
|
6
6
|
constructor(result) {
|
|
@@ -41,6 +41,7 @@ export function compileToIR(graph, options = {}) {
|
|
|
41
41
|
if (options.validate !== false) {
|
|
42
42
|
const result = validateGraph(graph, {
|
|
43
43
|
renderer: options.renderer ?? BROWSER_RENDERER_CAPABILITIES,
|
|
44
|
+
triggerRuntime: options.triggerRuntime ?? BROWSER_TRIGGER_CAPABILITIES,
|
|
44
45
|
});
|
|
45
46
|
if (!result.valid) {
|
|
46
47
|
throw new GraphValidationError(result);
|
|
@@ -71,6 +72,7 @@ export function compileToIR(graph, options = {}) {
|
|
|
71
72
|
const transitionConstraints = [];
|
|
72
73
|
const expressionDefs = {};
|
|
73
74
|
const routes = [];
|
|
75
|
+
const triggers = [];
|
|
74
76
|
// Authoring metadata is stripped on the way in, so no later stage has to remember to.
|
|
75
77
|
const forIR = (node) => options.includeAuthoringMetadata ? node : stripAuthoringMetadata(node);
|
|
76
78
|
for (const raw of graph.listNodes()) {
|
|
@@ -155,6 +157,30 @@ export function compileToIR(graph, options = {}) {
|
|
|
155
157
|
}
|
|
156
158
|
expressionDefs[node.id] = node;
|
|
157
159
|
break;
|
|
160
|
+
case 'integration':
|
|
161
|
+
case 'integration-operation':
|
|
162
|
+
case 'event':
|
|
163
|
+
// Server-only vocabulary: no client concern ever needs to know an integration,
|
|
164
|
+
// its operations or the events it can raise exist (spec §80).
|
|
165
|
+
delete nodes[node.id];
|
|
166
|
+
break;
|
|
167
|
+
case 'trigger': {
|
|
168
|
+
// Only client-authority, non-event triggers belong in the client IR. An `event`
|
|
169
|
+
// trigger only ever fires from a server-dispatched event, and a trigger whose
|
|
170
|
+
// target action is server-authority executes there, not here.
|
|
171
|
+
const target = authorityOf.actions.get(node.actionId);
|
|
172
|
+
const triggerAuthority = target ? actionAuthority(target, authorityOf) : 'client';
|
|
173
|
+
const triggerExpressions = [
|
|
174
|
+
...Object.values(node.arguments ?? {}),
|
|
175
|
+
...(node.enabledWhen ? [node.enabledWhen] : []),
|
|
176
|
+
];
|
|
177
|
+
if (node.when.kind === 'event' || triggerAuthority === 'server' || readsHiddenState(triggerExpressions)) {
|
|
178
|
+
delete nodes[node.id];
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
triggers.push(node);
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
158
184
|
default:
|
|
159
185
|
}
|
|
160
186
|
}
|
|
@@ -231,6 +257,7 @@ export function compileToIR(graph, options = {}) {
|
|
|
231
257
|
remoteActionIds,
|
|
232
258
|
theme,
|
|
233
259
|
presentation,
|
|
260
|
+
triggers,
|
|
234
261
|
};
|
|
235
262
|
}
|
|
236
263
|
export function serializeIR(ir) {
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { actionAuthority, actionGuards, authorityContext, expressionDefsIn, isObservable, requiredServerContract, serverIRExpressions, serverStateClosure, stateAuthority, validateGraph, } from '@cynodia/axiom-core';
|
|
1
|
+
import { actionAuthority, actionGuards, authorityContext, expressionDefsIn, isObservable, maxContract, requiredServerContract, serverIRExpressions, serverStateClosure, stateAuthority, usesIntegrationVocabulary, usesInvocationVocabulary, usesV4Semantics, validateGraph, } from '@cynodia/axiom-core';
|
|
2
2
|
import { GraphValidationError } from './normalize.js';
|
|
3
3
|
/**
|
|
4
4
|
* Compiles the authoritative half of a graph.
|
|
@@ -25,6 +25,9 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
25
25
|
const constraints = [];
|
|
26
26
|
const transitionConstraints = [];
|
|
27
27
|
const expressionDefs = {};
|
|
28
|
+
const integrations = [];
|
|
29
|
+
const integrationOperations = {};
|
|
30
|
+
const events = [];
|
|
28
31
|
for (const node of nodes) {
|
|
29
32
|
if (node.kind === 'entity') {
|
|
30
33
|
entities.push(node);
|
|
@@ -38,6 +41,15 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
38
41
|
else if (node.kind === 'expression') {
|
|
39
42
|
expressionDefs[node.id] = node;
|
|
40
43
|
}
|
|
44
|
+
else if (node.kind === 'integration') {
|
|
45
|
+
integrations.push(node);
|
|
46
|
+
}
|
|
47
|
+
else if (node.kind === 'integration-operation') {
|
|
48
|
+
integrationOperations[node.id] = node;
|
|
49
|
+
}
|
|
50
|
+
else if (node.kind === 'event') {
|
|
51
|
+
events.push(node);
|
|
52
|
+
}
|
|
41
53
|
}
|
|
42
54
|
const states = [];
|
|
43
55
|
const observableStateIds = [];
|
|
@@ -65,6 +77,18 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
65
77
|
failureModes: guards.map((guard) => guard.failureMode ?? { code: 'precondition-failed' }),
|
|
66
78
|
};
|
|
67
79
|
}
|
|
80
|
+
// Only the triggers whose target action executes here. A `route-enter`/`route-leave`
|
|
81
|
+
// trigger's target is always client-authority (validated), so it is naturally excluded.
|
|
82
|
+
const triggers = [];
|
|
83
|
+
for (const node of nodes) {
|
|
84
|
+
if (node.kind !== 'trigger') {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const target = context.actions.get(node.actionId);
|
|
88
|
+
if (target && actionAuthority(target, context) === 'server') {
|
|
89
|
+
triggers.push(node);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
68
92
|
const fields = {};
|
|
69
93
|
for (const entry of graph.listFields()) {
|
|
70
94
|
fields[entry.field.id] = entry;
|
|
@@ -81,6 +105,10 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
81
105
|
transitionConstraints,
|
|
82
106
|
...(graph.principalEntityId ? { principalEntityId: graph.principalEntityId } : {}),
|
|
83
107
|
observableStateIds,
|
|
108
|
+
...(integrations.length > 0 ? { integrations } : {}),
|
|
109
|
+
...(Object.keys(integrationOperations).length > 0 ? { integrationOperations } : {}),
|
|
110
|
+
...(events.length > 0 ? { events } : {}),
|
|
111
|
+
...(triggers.length > 0 ? { triggers } : {}),
|
|
84
112
|
};
|
|
85
113
|
// Only the definitions the authority's own rules reach. A calculation used by the client
|
|
86
114
|
// alone decides nothing here, and the Server IR carries nothing that decides nothing.
|
|
@@ -99,12 +127,18 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
99
127
|
const document = { ...rules, ...(carriesDefinitions ? { expressionDefs: used } : {}) };
|
|
100
128
|
/**
|
|
101
129
|
* The label follows the vocabulary the document actually uses. An application that uses
|
|
102
|
-
* nothing from 0.7 compiles to the same `axiom.server.v1` document it always did;
|
|
103
|
-
* that groups or names an expression
|
|
130
|
+
* nothing from 0.7 or 0.8 compiles to the same `axiom.server.v1` document it always did;
|
|
131
|
+
* one that groups or names an expression, or uses any integration/trigger/event
|
|
132
|
+
* vocabulary, says so, because an older runtime could not execute it.
|
|
104
133
|
*/
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
134
|
+
const contractCandidates = [
|
|
135
|
+
carriesDefinitions || usesInvocationVocabulary(document)
|
|
136
|
+
? 'axiom.server.v2'
|
|
137
|
+
: requiredServerContract(serverIRExpressions(document)),
|
|
138
|
+
usesIntegrationVocabulary(document) ? 'axiom.server.v3' : 'axiom.server.v1',
|
|
139
|
+
usesV4Semantics(document) ? 'axiom.server.v4' : 'axiom.server.v1',
|
|
140
|
+
];
|
|
141
|
+
const contract = contractCandidates.reduce(maxContract);
|
|
108
142
|
return { contract, ...document };
|
|
109
143
|
}
|
|
110
144
|
export function serializeServerIR(ir) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cynodia/axiom-compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1-alpha.1",
|
|
4
4
|
"description": "Normalizes an Axiom application graph and emits a self-contained page.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "AskTech AS",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@cynodia/axiom-core": "0.
|
|
35
|
-
"@cynodia/axiom-runtime": "0.
|
|
34
|
+
"@cynodia/axiom-core": "0.8.1-alpha.1",
|
|
35
|
+
"@cynodia/axiom-runtime": "0.8.1-alpha.1"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "tsc -b tsconfig.json tsconfig.test.json",
|