@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.
@@ -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; 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 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.7.0-alpha.2",
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.7.0-alpha.2",
35
- "@cynodia/axiom-runtime": "0.7.0-alpha.2"
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",