@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 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; one
103
- * that groups or names an expression says so, because a v1 runtime could not execute it.
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.7.0-alpha.2",
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.7.0-alpha.2",
35
- "@cynodia/axiom-runtime": "0.7.0-alpha.2"
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",