@cynodia/axiom-compiler 0.9.0-alpha.2 → 0.11.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 +9 -4
- package/dist/server.js +49 -1
- package/package.json +3 -3
package/dist/normalize.js
CHANGED
|
@@ -162,11 +162,16 @@ export function compileToIR(graph, options = {}) {
|
|
|
162
162
|
case 'event':
|
|
163
163
|
case 'subscription':
|
|
164
164
|
case 'storage':
|
|
165
|
+
case 'query':
|
|
166
|
+
case 'relationship':
|
|
167
|
+
case 'read-policy':
|
|
168
|
+
case 'migration':
|
|
165
169
|
// Server-only vocabulary: no client concern ever needs to know an integration, its
|
|
166
|
-
// operations, the events it can raise (spec §80), the live sources it subscribes to
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
//
|
|
170
|
+
// operations, the events it can raise (spec §80), the live sources it subscribes to,
|
|
171
|
+
// the object stores it reaches, or — new in 0.10 — the registered queries,
|
|
172
|
+
// entity relationships and row-level read policies the authority executes. A client
|
|
173
|
+
// invokes a query by id and receives a typed page; it never sees a clause or a
|
|
174
|
+
// policy predicate (spec 0.10 §6, §46-49).
|
|
170
175
|
delete nodes[node.id];
|
|
171
176
|
break;
|
|
172
177
|
case 'trigger': {
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { actionAuthority, actionGuards, authorityContext, expressionDefsIn, isObservable, maxContract, requiredServerContract, serverIRExpressions, serverStateClosure, stateAuthority, usesExternalIOVocabulary, usesIntegrationVocabulary, usesInvocationVocabulary, usesV4Semantics, validateGraph, } from '@cynodia/axiom-core';
|
|
1
|
+
import { actionAuthority, actionGuards, authorityContext, expressionDefsIn, isObservable, maxContract, requiredServerContract, schemaFingerprint, stripAuthoringMetadata, serverIRExpressions, serverStateClosure, stateAuthority, usesExternalIOVocabulary, usesIntegrationVocabulary, usesInvocationVocabulary, usesMigrationVocabulary, usesQueryVocabulary, usesV4Semantics, validateGraph, } from '@cynodia/axiom-core';
|
|
2
2
|
import { GraphValidationError } from './normalize.js';
|
|
3
3
|
/**
|
|
4
4
|
* Compiles the authoritative half of a graph.
|
|
@@ -30,6 +30,10 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
30
30
|
const events = [];
|
|
31
31
|
const subscriptions = [];
|
|
32
32
|
const storages = [];
|
|
33
|
+
const queries = [];
|
|
34
|
+
const relationships = [];
|
|
35
|
+
const readPolicies = [];
|
|
36
|
+
const migrations = [];
|
|
33
37
|
for (const node of nodes) {
|
|
34
38
|
if (node.kind === 'entity') {
|
|
35
39
|
entities.push(node);
|
|
@@ -61,6 +65,30 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
61
65
|
else if (node.kind === 'storage') {
|
|
62
66
|
storages.push(node);
|
|
63
67
|
}
|
|
68
|
+
else if (node.kind === 'query') {
|
|
69
|
+
// A query reads authoritative data, so it is executed on the authority and nowhere
|
|
70
|
+
// else. The client invokes it by id (spec 0.10 §6); it never receives the clauses.
|
|
71
|
+
queries.push(node);
|
|
72
|
+
}
|
|
73
|
+
else if (node.kind === 'relationship') {
|
|
74
|
+
relationships.push(node);
|
|
75
|
+
}
|
|
76
|
+
else if (node.kind === 'read-policy') {
|
|
77
|
+
readPolicies.push(node);
|
|
78
|
+
}
|
|
79
|
+
else if (node.kind === 'migration') {
|
|
80
|
+
// A migration is authority-side by construction: only the authoritative runtime
|
|
81
|
+
// executes a schema evolution, and only against persisted canonical data (spec11
|
|
82
|
+
// §73). It never reaches a client. Authoring markers on the migration or its
|
|
83
|
+
// operations are stripped like any other trust-boundary payload.
|
|
84
|
+
migrations.push({
|
|
85
|
+
...stripAuthoringMetadata(node),
|
|
86
|
+
operations: node.operations.map((operation) => stripAuthoringMetadata(operation)),
|
|
87
|
+
...(node.reverseOperations
|
|
88
|
+
? { reverseOperations: node.reverseOperations.map((operation) => stripAuthoringMetadata(operation)) }
|
|
89
|
+
: {}),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
64
92
|
}
|
|
65
93
|
const states = [];
|
|
66
94
|
const observableStateIds = [];
|
|
@@ -104,10 +132,25 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
104
132
|
for (const entry of graph.listFields()) {
|
|
105
133
|
fields[entry.field.id] = entry;
|
|
106
134
|
}
|
|
135
|
+
// Schema-evolution vocabulary is emitted only when the document actually uses it — a
|
|
136
|
+
// migration node, or a schemaVersion past the default 1. A plain graph compiles to the
|
|
137
|
+
// byte-identical pre-v7 document it always did, so the frozen v1–v6 contracts and their
|
|
138
|
+
// conformance fixtures are untouched (spec11 §87).
|
|
139
|
+
const emitSchemaEvolution = usesMigrationVocabulary({
|
|
140
|
+
migrations,
|
|
141
|
+
schemaVersion: graph.schemaVersion,
|
|
142
|
+
});
|
|
107
143
|
const rules = {
|
|
108
144
|
id: graph.id,
|
|
109
145
|
name: graph.name,
|
|
110
146
|
version: graph.version,
|
|
147
|
+
...(emitSchemaEvolution
|
|
148
|
+
? {
|
|
149
|
+
schemaVersion: graph.schemaVersion,
|
|
150
|
+
schemaFingerprint: schemaFingerprint(graph),
|
|
151
|
+
...(migrations.length > 0 ? { migrations } : {}),
|
|
152
|
+
}
|
|
153
|
+
: {}),
|
|
111
154
|
entities,
|
|
112
155
|
fields,
|
|
113
156
|
states,
|
|
@@ -122,6 +165,9 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
122
165
|
...(triggers.length > 0 ? { triggers } : {}),
|
|
123
166
|
...(subscriptions.length > 0 ? { subscriptions } : {}),
|
|
124
167
|
...(storages.length > 0 ? { storages } : {}),
|
|
168
|
+
...(queries.length > 0 ? { queries } : {}),
|
|
169
|
+
...(relationships.length > 0 ? { relationships } : {}),
|
|
170
|
+
...(readPolicies.length > 0 ? { readPolicies } : {}),
|
|
125
171
|
};
|
|
126
172
|
// Only the definitions the authority's own rules reach. A calculation used by the client
|
|
127
173
|
// alone decides nothing here, and the Server IR carries nothing that decides nothing.
|
|
@@ -151,6 +197,8 @@ export function compileToServerIR(graph, options = {}) {
|
|
|
151
197
|
usesIntegrationVocabulary(document) ? 'axiom.server.v3' : 'axiom.server.v1',
|
|
152
198
|
usesV4Semantics(document) ? 'axiom.server.v4' : 'axiom.server.v1',
|
|
153
199
|
usesExternalIOVocabulary(document) ? 'axiom.server.v5' : 'axiom.server.v1',
|
|
200
|
+
usesQueryVocabulary(document) ? 'axiom.server.v6' : 'axiom.server.v1',
|
|
201
|
+
usesMigrationVocabulary(document) ? 'axiom.server.v7' : 'axiom.server.v1',
|
|
154
202
|
];
|
|
155
203
|
const contract = contractCandidates.reduce(maxContract);
|
|
156
204
|
return { contract, ...document };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cynodia/axiom-compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.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.11.0-alpha.1",
|
|
35
|
+
"@cynodia/axiom-runtime": "0.11.0-alpha.1"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "tsc -b tsconfig.json tsconfig.test.json",
|