@cynodia/axiom-compiler 0.7.0-alpha.2 → 0.8.0-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.js +26 -0
- package/dist/server.js +33 -6
- package/package.json +3 -3
package/dist/normalize.js
CHANGED
|
@@ -71,6 +71,7 @@ export function compileToIR(graph, options = {}) {
|
|
|
71
71
|
const transitionConstraints = [];
|
|
72
72
|
const expressionDefs = {};
|
|
73
73
|
const routes = [];
|
|
74
|
+
const triggers = [];
|
|
74
75
|
// Authoring metadata is stripped on the way in, so no later stage has to remember to.
|
|
75
76
|
const forIR = (node) => options.includeAuthoringMetadata ? node : stripAuthoringMetadata(node);
|
|
76
77
|
for (const raw of graph.listNodes()) {
|
|
@@ -155,6 +156,30 @@ export function compileToIR(graph, options = {}) {
|
|
|
155
156
|
}
|
|
156
157
|
expressionDefs[node.id] = node;
|
|
157
158
|
break;
|
|
159
|
+
case 'integration':
|
|
160
|
+
case 'integration-operation':
|
|
161
|
+
case 'event':
|
|
162
|
+
// Server-only vocabulary: no client concern ever needs to know an integration,
|
|
163
|
+
// its operations or the events it can raise exist (spec §80).
|
|
164
|
+
delete nodes[node.id];
|
|
165
|
+
break;
|
|
166
|
+
case 'trigger': {
|
|
167
|
+
// Only client-authority, non-event triggers belong in the client IR. An `event`
|
|
168
|
+
// trigger only ever fires from a server-dispatched event, and a trigger whose
|
|
169
|
+
// target action is server-authority executes there, not here.
|
|
170
|
+
const target = authorityOf.actions.get(node.actionId);
|
|
171
|
+
const triggerAuthority = target ? actionAuthority(target, authorityOf) : 'client';
|
|
172
|
+
const triggerExpressions = [
|
|
173
|
+
...Object.values(node.arguments ?? {}),
|
|
174
|
+
...(node.enabledWhen ? [node.enabledWhen] : []),
|
|
175
|
+
];
|
|
176
|
+
if (node.when.kind === 'event' || triggerAuthority === 'server' || readsHiddenState(triggerExpressions)) {
|
|
177
|
+
delete nodes[node.id];
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
triggers.push(node);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
158
183
|
default:
|
|
159
184
|
}
|
|
160
185
|
}
|
|
@@ -231,6 +256,7 @@ export function compileToIR(graph, options = {}) {
|
|
|
231
256
|
remoteActionIds,
|
|
232
257
|
theme,
|
|
233
258
|
presentation,
|
|
259
|
+
triggers,
|
|
234
260
|
};
|
|
235
261
|
}
|
|
236
262
|
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, 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,11 @@ 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 contract = carriesDefinitions
|
|
106
|
-
? 'axiom.server.v2'
|
|
107
|
-
: requiredServerContract(serverIRExpressions(document));
|
|
134
|
+
const contract = maxContract(carriesDefinitions ? 'axiom.server.v2' : requiredServerContract(serverIRExpressions(document)), usesIntegrationVocabulary(document) ? 'axiom.server.v3' : 'axiom.server.v1');
|
|
108
135
|
return { contract, ...document };
|
|
109
136
|
}
|
|
110
137
|
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.0-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.0-alpha.1",
|
|
35
|
+
"@cynodia/axiom-runtime": "0.8.0-alpha.1"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "tsc -b tsconfig.json tsconfig.test.json",
|