graphenix-format 1.2.1 → 1.4.0
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/README.md +322 -274
- package/dist/examples/validate-minimal.js +37 -0
- package/dist/examples/validate-minimal.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +70 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validateWorox.d.ts +22 -0
- package/dist/validateWorox.d.ts.map +1 -0
- package/dist/validateWorox.js +90 -0
- package/dist/validateWorox.js.map +1 -0
- package/docs/interop-worox-graph.md +32 -0
- package/package.json +3 -2
- package/schema/graphenix-format-1.0.0.schema.json +529 -438
package/README.md
CHANGED
|
@@ -1,274 +1,322 @@
|
|
|
1
|
-
## `@graphenix/format`
|
|
2
|
-
|
|
3
|
-
TypeScript/JavaScript utilities for working with the **Graphenix Format 1.0.0**:
|
|
4
|
-
|
|
5
|
-
- **JSON Schema** for validation (`schema/graphenix-format-1.0.0.schema.json`)
|
|
6
|
-
- **Runtime validator** built on [`ajv`](https://ajv.js.org)
|
|
7
|
-
- Lightweight **CRUD helpers** for nodes, edges, types and subgraphs
|
|
8
|
-
- First-class **TypeScript types** for graph documents
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
### Install
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
npm install @graphenix/format
|
|
16
|
-
# or
|
|
17
|
-
yarn add @graphenix/format
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
### Usage
|
|
23
|
-
|
|
24
|
-
#### Validate a graph document
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
import { validateGraph, type GraphDocument } from "@graphenix/format";
|
|
28
|
-
|
|
29
|
-
const doc: GraphDocument = {
|
|
30
|
-
formatVersion: "1.0.0",
|
|
31
|
-
id: "graph:auth/user-signup",
|
|
32
|
-
graph: {
|
|
33
|
-
nodes: [],
|
|
34
|
-
edges: [],
|
|
35
|
-
inputs: [],
|
|
36
|
-
outputs: []
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const result = validateGraph(doc);
|
|
41
|
-
|
|
42
|
-
if (!result.valid) {
|
|
43
|
-
console.error(result.errors);
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Each error has:
|
|
48
|
-
|
|
49
|
-
- **`message`**: human readable message
|
|
50
|
-
- **`path`**: JSON Pointer to the failing instance
|
|
51
|
-
- **`keyword`** and **`params`** from `ajv` for tooling.
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
#### Quick start: minimal Graphenix document
|
|
56
|
-
|
|
57
|
-
This is a minimal but complete **Graphenix Format 1.0.0** document that you can load, validate, and then modify:
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
import {
|
|
61
|
-
validateGraph,
|
|
62
|
-
type GraphDocument,
|
|
63
|
-
addNode,
|
|
64
|
-
addEdge
|
|
65
|
-
} from "@graphenix/format";
|
|
66
|
-
|
|
67
|
-
const doc: GraphDocument = {
|
|
68
|
-
formatVersion: "1.0.0",
|
|
69
|
-
id: "graph:auth/user-signup",
|
|
70
|
-
name: "User Signup",
|
|
71
|
-
graph: {
|
|
72
|
-
nodes: [
|
|
73
|
-
{
|
|
74
|
-
id: "node:validate-input",
|
|
75
|
-
kind: "builtin:validate",
|
|
76
|
-
inputs: [
|
|
77
|
-
{
|
|
78
|
-
id: "in:payload",
|
|
79
|
-
direction: "input",
|
|
80
|
-
type: "builtin:object",
|
|
81
|
-
required: true
|
|
82
|
-
}
|
|
83
|
-
],
|
|
84
|
-
outputs: [
|
|
85
|
-
{
|
|
86
|
-
id: "out:validated",
|
|
87
|
-
direction: "output",
|
|
88
|
-
type: "builtin:object"
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
|
-
parameters: {
|
|
92
|
-
schemaType: "type:User"
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
],
|
|
96
|
-
edges: [],
|
|
97
|
-
inputs: [
|
|
98
|
-
{
|
|
99
|
-
id: "graph-input:request",
|
|
100
|
-
name: "Request Body",
|
|
101
|
-
type: "builtin:object",
|
|
102
|
-
target: {
|
|
103
|
-
nodeId: "node:validate-input",
|
|
104
|
-
portId: "in:payload"
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
],
|
|
108
|
-
outputs: [],
|
|
109
|
-
metadata: {}
|
|
110
|
-
},
|
|
111
|
-
types: [
|
|
112
|
-
{
|
|
113
|
-
id: "type:User",
|
|
114
|
-
kind: "object",
|
|
115
|
-
fields: [
|
|
116
|
-
{ name: "id", type: "builtin:string", required: true },
|
|
117
|
-
{ name: "email", type: "builtin:string", required: true }
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
|
-
]
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
// Validate against the Graphenix JSON Schema
|
|
124
|
-
const res = validateGraph(doc);
|
|
125
|
-
if (!res.valid) {
|
|
126
|
-
throw new Error(JSON.stringify(res.errors, null, 2));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Programmatically add a new node + edge
|
|
130
|
-
const withCreateNode = addNode(doc, {
|
|
131
|
-
id: "node:create-user",
|
|
132
|
-
kind: "task:http-request",
|
|
133
|
-
inputs: [
|
|
134
|
-
{
|
|
135
|
-
id: "in:validated",
|
|
136
|
-
direction: "input",
|
|
137
|
-
type: "type:User",
|
|
138
|
-
required: true
|
|
139
|
-
}
|
|
140
|
-
],
|
|
141
|
-
outputs: [
|
|
142
|
-
{
|
|
143
|
-
id: "out:user",
|
|
144
|
-
direction: "output",
|
|
145
|
-
type: "type:User"
|
|
146
|
-
}
|
|
147
|
-
],
|
|
148
|
-
parameters: {
|
|
149
|
-
method: "POST",
|
|
150
|
-
url: "https://example.com/users"
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const finalDoc = addEdge(withCreateNode, {
|
|
155
|
-
id: "edge:validate-to-create",
|
|
156
|
-
from: { nodeId: "node:validate-input", portId: "out:validated" },
|
|
157
|
-
to: { nodeId: "node:create-user", portId: "in:validated" }
|
|
158
|
-
});
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
This matches the structure described in `GRAPHENIX-FORMAT.md` and can be fed directly to your executor.
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
#### CRUD helpers
|
|
166
|
-
|
|
167
|
-
CRUD helpers operate on an in-memory `GraphDocument` and return a new document by default (immutable), or mutate in-place when `mutate: true` is passed.
|
|
168
|
-
|
|
169
|
-
```ts
|
|
170
|
-
import {
|
|
171
|
-
addNode,
|
|
172
|
-
updateNode,
|
|
173
|
-
removeNode,
|
|
174
|
-
addEdge,
|
|
175
|
-
removeEdge,
|
|
176
|
-
addType
|
|
177
|
-
} from "@graphenix/format";
|
|
178
|
-
|
|
179
|
-
import type { GraphDocument } from "@graphenix/format";
|
|
180
|
-
|
|
181
|
-
let doc: GraphDocument = /* ... */;
|
|
182
|
-
|
|
183
|
-
// Add a node (immutable)
|
|
184
|
-
doc = addNode(doc, {
|
|
185
|
-
id: "node:validate-input",
|
|
186
|
-
kind: "builtin:validate",
|
|
187
|
-
inputs: [],
|
|
188
|
-
outputs: []
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// Update a node
|
|
192
|
-
doc = updateNode(doc, "node:validate-input", {
|
|
193
|
-
name: "Validate Input"
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
// Remove a node (also removes attached edges and graph IO)
|
|
197
|
-
doc = removeNode(doc, "node:validate-input");
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
All CRUD helpers accept an optional `{ mutate?: boolean }`:
|
|
201
|
-
|
|
202
|
-
```ts
|
|
203
|
-
addNode(doc, newNode, { mutate: true }); // modifies `doc` in place
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
Available helpers:
|
|
207
|
-
|
|
208
|
-
- **Nodes**: `getNode`, `addNode`, `updateNode`, `removeNode`
|
|
209
|
-
- **Edges**: `getEdge`, `addEdge`, `updateEdge`, `removeEdge`
|
|
210
|
-
- **Types**: `getType`, `addType`, `updateType`, `removeType`
|
|
211
|
-
- **Subgraphs**: `getSubgraph`, `addSubgraph`, `updateSubgraph`, `removeSubgraph`
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
### Working with subgraphs and types
|
|
216
|
-
|
|
217
|
-
Subgraphs are just nested `graph` structures that can be referenced via node `kind`:
|
|
218
|
-
|
|
219
|
-
```ts
|
|
220
|
-
import {
|
|
221
|
-
type GraphDocument,
|
|
222
|
-
addSubgraph,
|
|
223
|
-
addNode
|
|
224
|
-
} from "@graphenix/format";
|
|
225
|
-
|
|
226
|
-
let doc: GraphDocument = /* existing document */;
|
|
227
|
-
|
|
228
|
-
// Add a reusable subgraph
|
|
229
|
-
doc = addSubgraph(doc, {
|
|
230
|
-
id: "graph:user-validation",
|
|
231
|
-
name: "User Validation",
|
|
232
|
-
graph: {
|
|
233
|
-
nodes: [],
|
|
234
|
-
edges: [],
|
|
235
|
-
inputs: [],
|
|
236
|
-
outputs: []
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
// Use it as a node in the main graph
|
|
241
|
-
doc = addNode(doc, {
|
|
242
|
-
id: "node:user-validation",
|
|
243
|
-
kind: "subgraph:graph:user-validation",
|
|
244
|
-
inputs: [],
|
|
245
|
-
outputs: []
|
|
246
|
-
});
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
For a full description of all fields and constraints, see `GRAPHENIX-FORMAT.md` in this repo.
|
|
250
|
-
|
|
251
|
-
---
|
|
252
|
-
|
|
253
|
-
### Build & test locally
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
# install dev dependencies
|
|
257
|
-
npm install
|
|
258
|
-
|
|
259
|
-
# build ESM + CJS
|
|
260
|
-
npm run build
|
|
261
|
-
|
|
262
|
-
# run a tiny smoke test that validates the minimal example graph
|
|
263
|
-
npm test
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
The minimal example graph lives in `src/examples/minimal-graph.ts` and mirrors the example from `GRAPHENIX-FORMAT.md`.
|
|
267
|
-
|
|
268
|
-
---
|
|
269
|
-
|
|
270
|
-
###
|
|
271
|
-
|
|
272
|
-
-
|
|
273
|
-
|
|
274
|
-
|
|
1
|
+
## `@graphenix/format`
|
|
2
|
+
|
|
3
|
+
TypeScript/JavaScript utilities for working with the **Graphenix Format 1.0.0**:
|
|
4
|
+
|
|
5
|
+
- **JSON Schema** for validation (`schema/graphenix-format-1.0.0.schema.json`)
|
|
6
|
+
- **Runtime validator** built on [`ajv`](https://ajv.js.org)
|
|
7
|
+
- Lightweight **CRUD helpers** for nodes, edges, types and subgraphs
|
|
8
|
+
- First-class **TypeScript types** for graph documents
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
### Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @graphenix/format
|
|
16
|
+
# or
|
|
17
|
+
yarn add @graphenix/format
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
### Usage
|
|
23
|
+
|
|
24
|
+
#### Validate a graph document
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { validateGraph, type GraphDocument } from "@graphenix/format";
|
|
28
|
+
|
|
29
|
+
const doc: GraphDocument = {
|
|
30
|
+
formatVersion: "1.0.0",
|
|
31
|
+
id: "graph:auth/user-signup",
|
|
32
|
+
graph: {
|
|
33
|
+
nodes: [],
|
|
34
|
+
edges: [],
|
|
35
|
+
inputs: [],
|
|
36
|
+
outputs: []
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const result = validateGraph(doc);
|
|
41
|
+
|
|
42
|
+
if (!result.valid) {
|
|
43
|
+
console.error(result.errors);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Each error has:
|
|
48
|
+
|
|
49
|
+
- **`message`**: human readable message
|
|
50
|
+
- **`path`**: JSON Pointer to the failing instance
|
|
51
|
+
- **`keyword`** and **`params`** from `ajv` for tooling.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
#### Quick start: minimal Graphenix document
|
|
56
|
+
|
|
57
|
+
This is a minimal but complete **Graphenix Format 1.0.0** document that you can load, validate, and then modify:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import {
|
|
61
|
+
validateGraph,
|
|
62
|
+
type GraphDocument,
|
|
63
|
+
addNode,
|
|
64
|
+
addEdge
|
|
65
|
+
} from "@graphenix/format";
|
|
66
|
+
|
|
67
|
+
const doc: GraphDocument = {
|
|
68
|
+
formatVersion: "1.0.0",
|
|
69
|
+
id: "graph:auth/user-signup",
|
|
70
|
+
name: "User Signup",
|
|
71
|
+
graph: {
|
|
72
|
+
nodes: [
|
|
73
|
+
{
|
|
74
|
+
id: "node:validate-input",
|
|
75
|
+
kind: "builtin:validate",
|
|
76
|
+
inputs: [
|
|
77
|
+
{
|
|
78
|
+
id: "in:payload",
|
|
79
|
+
direction: "input",
|
|
80
|
+
type: "builtin:object",
|
|
81
|
+
required: true
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
outputs: [
|
|
85
|
+
{
|
|
86
|
+
id: "out:validated",
|
|
87
|
+
direction: "output",
|
|
88
|
+
type: "builtin:object"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
parameters: {
|
|
92
|
+
schemaType: "type:User"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
edges: [],
|
|
97
|
+
inputs: [
|
|
98
|
+
{
|
|
99
|
+
id: "graph-input:request",
|
|
100
|
+
name: "Request Body",
|
|
101
|
+
type: "builtin:object",
|
|
102
|
+
target: {
|
|
103
|
+
nodeId: "node:validate-input",
|
|
104
|
+
portId: "in:payload"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
outputs: [],
|
|
109
|
+
metadata: {}
|
|
110
|
+
},
|
|
111
|
+
types: [
|
|
112
|
+
{
|
|
113
|
+
id: "type:User",
|
|
114
|
+
kind: "object",
|
|
115
|
+
fields: [
|
|
116
|
+
{ name: "id", type: "builtin:string", required: true },
|
|
117
|
+
{ name: "email", type: "builtin:string", required: true }
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Validate against the Graphenix JSON Schema
|
|
124
|
+
const res = validateGraph(doc);
|
|
125
|
+
if (!res.valid) {
|
|
126
|
+
throw new Error(JSON.stringify(res.errors, null, 2));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Programmatically add a new node + edge
|
|
130
|
+
const withCreateNode = addNode(doc, {
|
|
131
|
+
id: "node:create-user",
|
|
132
|
+
kind: "task:http-request",
|
|
133
|
+
inputs: [
|
|
134
|
+
{
|
|
135
|
+
id: "in:validated",
|
|
136
|
+
direction: "input",
|
|
137
|
+
type: "type:User",
|
|
138
|
+
required: true
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
outputs: [
|
|
142
|
+
{
|
|
143
|
+
id: "out:user",
|
|
144
|
+
direction: "output",
|
|
145
|
+
type: "type:User"
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
parameters: {
|
|
149
|
+
method: "POST",
|
|
150
|
+
url: "https://example.com/users"
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const finalDoc = addEdge(withCreateNode, {
|
|
155
|
+
id: "edge:validate-to-create",
|
|
156
|
+
from: { nodeId: "node:validate-input", portId: "out:validated" },
|
|
157
|
+
to: { nodeId: "node:create-user", portId: "in:validated" }
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
This matches the structure described in `GRAPHENIX-FORMAT.md` and can be fed directly to your executor.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
#### CRUD helpers
|
|
166
|
+
|
|
167
|
+
CRUD helpers operate on an in-memory `GraphDocument` and return a new document by default (immutable), or mutate in-place when `mutate: true` is passed.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import {
|
|
171
|
+
addNode,
|
|
172
|
+
updateNode,
|
|
173
|
+
removeNode,
|
|
174
|
+
addEdge,
|
|
175
|
+
removeEdge,
|
|
176
|
+
addType
|
|
177
|
+
} from "@graphenix/format";
|
|
178
|
+
|
|
179
|
+
import type { GraphDocument } from "@graphenix/format";
|
|
180
|
+
|
|
181
|
+
let doc: GraphDocument = /* ... */;
|
|
182
|
+
|
|
183
|
+
// Add a node (immutable)
|
|
184
|
+
doc = addNode(doc, {
|
|
185
|
+
id: "node:validate-input",
|
|
186
|
+
kind: "builtin:validate",
|
|
187
|
+
inputs: [],
|
|
188
|
+
outputs: []
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Update a node
|
|
192
|
+
doc = updateNode(doc, "node:validate-input", {
|
|
193
|
+
name: "Validate Input"
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Remove a node (also removes attached edges and graph IO)
|
|
197
|
+
doc = removeNode(doc, "node:validate-input");
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
All CRUD helpers accept an optional `{ mutate?: boolean }`:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
addNode(doc, newNode, { mutate: true }); // modifies `doc` in place
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Available helpers:
|
|
207
|
+
|
|
208
|
+
- **Nodes**: `getNode`, `addNode`, `updateNode`, `removeNode`
|
|
209
|
+
- **Edges**: `getEdge`, `addEdge`, `updateEdge`, `removeEdge`
|
|
210
|
+
- **Types**: `getType`, `addType`, `updateType`, `removeType`
|
|
211
|
+
- **Subgraphs**: `getSubgraph`, `addSubgraph`, `updateSubgraph`, `removeSubgraph`
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### Working with subgraphs and types
|
|
216
|
+
|
|
217
|
+
Subgraphs are just nested `graph` structures that can be referenced via node `kind`:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import {
|
|
221
|
+
type GraphDocument,
|
|
222
|
+
addSubgraph,
|
|
223
|
+
addNode
|
|
224
|
+
} from "@graphenix/format";
|
|
225
|
+
|
|
226
|
+
let doc: GraphDocument = /* existing document */;
|
|
227
|
+
|
|
228
|
+
// Add a reusable subgraph
|
|
229
|
+
doc = addSubgraph(doc, {
|
|
230
|
+
id: "graph:user-validation",
|
|
231
|
+
name: "User Validation",
|
|
232
|
+
graph: {
|
|
233
|
+
nodes: [],
|
|
234
|
+
edges: [],
|
|
235
|
+
inputs: [],
|
|
236
|
+
outputs: []
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Use it as a node in the main graph
|
|
241
|
+
doc = addNode(doc, {
|
|
242
|
+
id: "node:user-validation",
|
|
243
|
+
kind: "subgraph:graph:user-validation",
|
|
244
|
+
inputs: [],
|
|
245
|
+
outputs: []
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
For a full description of all fields and constraints, see `GRAPHENIX-FORMAT.md` in this repo.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### Build & test locally
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# install dev dependencies
|
|
257
|
+
npm install
|
|
258
|
+
|
|
259
|
+
# build ESM + CJS
|
|
260
|
+
npm run build
|
|
261
|
+
|
|
262
|
+
# run a tiny smoke test that validates the minimal example graph
|
|
263
|
+
npm test
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The minimal example graph lives in `src/examples/minimal-graph.ts` and mirrors the example from `GRAPHENIX-FORMAT.md`.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### Worox-graph alignment (`metadata.graphEntry` / `metadata.graphResponse`)
|
|
271
|
+
|
|
272
|
+
Worox-graph attaches **entry** and **response** contracts to graph JSON; graphenix-format exposes the same shapes as **optional fields on the graph document**:
|
|
273
|
+
|
|
274
|
+
| Field | Type | Role |
|
|
275
|
+
|-------|------|------|
|
|
276
|
+
| `metadata.graphEntry` | `GraphEntryContract` | Entry / execution expectations |
|
|
277
|
+
| `metadata.graphResponse` | `GraphResponseContract` | Final output shape |
|
|
278
|
+
|
|
279
|
+
**`GraphEntryContract`** may include:
|
|
280
|
+
|
|
281
|
+
- `summary` — short description of what the graph expects at entry.
|
|
282
|
+
- `requiredExecutionPaths` / `notableExecutionPaths` — path descriptors (engine-specific item shapes).
|
|
283
|
+
- `executionSchema` — JSON Schema for the merged **execution** object after entry (optional tooling validation only).
|
|
284
|
+
|
|
285
|
+
**`GraphResponseContract`** may include:
|
|
286
|
+
|
|
287
|
+
- `summary` — description of the response.
|
|
288
|
+
- `finalOutputSchema` — JSON Schema for the **final output** value (optional tooling validation only).
|
|
289
|
+
|
|
290
|
+
**I/O visibility layers (single narrative for authors):**
|
|
291
|
+
|
|
292
|
+
- **Layer 01** — **Entry**: what must be satisfied when the graph is invoked; described by `graphEntry` (`summary`, paths, `executionSchema`).
|
|
293
|
+
- **Layer 08** — **Response**: what leaves the graph as the final result; described by `graphResponse` (`summary`, `finalOutputSchema`).
|
|
294
|
+
|
|
295
|
+
Optional **AJV** checks (not required for graphenix planning):
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
import {
|
|
299
|
+
validateGraph,
|
|
300
|
+
validateExecutionAgainstContract,
|
|
301
|
+
validateFinalOutputAgainstContract,
|
|
302
|
+
type GraphDocument
|
|
303
|
+
} from "@graphenix/format";
|
|
304
|
+
|
|
305
|
+
const doc: GraphDocument = /* ... with metadata.graphEntry / metadata.graphResponse ... */;
|
|
306
|
+
|
|
307
|
+
validateGraph(doc);
|
|
308
|
+
validateExecutionAgainstContract(doc, mergedExecution);
|
|
309
|
+
validateFinalOutputAgainstContract(doc, finalOutput);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
For how worox-graph’s task/DAG JSON differs from port-based `Graph`, see [`docs/interop-worox-graph.md`](docs/interop-worox-graph.md).
|
|
313
|
+
|
|
314
|
+
**Planning-only catalog fields (worox-graph):** optional `metadata.catalogRequests` on the document, and optional `metadata.catalogRequest` / `metadata.catalogBinding` on nodes, align with `@woroces/worox-graph` (`refs.ts`). JSON Schema `$defs` `WoroxCatalogRequest`, `WoroxCatalogBinding`, `WoroxCatalogRequests` describe the same keys for optional cross-validation; execution is unchanged.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### Notes
|
|
319
|
+
|
|
320
|
+
- The package is **execution-agnostic**: it only knows about the static Graphenix format.
|
|
321
|
+
- Runtime concerns (scheduling, retries, parallelism, logging, etc.) are intentionally left to your executor/runtime.
|
|
322
|
+
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const validate_1 = require("../validate");
|
|
4
|
+
const validateWorox_1 = require("../validateWorox");
|
|
4
5
|
const minimal_graph_1 = require("./minimal-graph");
|
|
5
6
|
const result = (0, validate_1.validateGraph)(minimal_graph_1.minimalGraph);
|
|
6
7
|
if (!result.valid) {
|
|
@@ -10,4 +11,40 @@ if (!result.valid) {
|
|
|
10
11
|
else {
|
|
11
12
|
console.log("Minimal graph is valid according to Graphenix format 1.0.0");
|
|
12
13
|
}
|
|
14
|
+
const withWoroxMetadata = {
|
|
15
|
+
...minimal_graph_1.minimalGraph,
|
|
16
|
+
metadata: {
|
|
17
|
+
graphEntry: {
|
|
18
|
+
summary: "Smoke-test entry contract",
|
|
19
|
+
requiredExecutionPaths: [["node:validate-input"]],
|
|
20
|
+
executionSchema: {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: { ok: { type: "boolean" } },
|
|
23
|
+
required: ["ok"]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
graphResponse: {
|
|
27
|
+
summary: "Smoke-test response contract",
|
|
28
|
+
finalOutputSchema: { type: "string", minLength: 1 }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const woroxDoc = (0, validate_1.validateGraph)(withWoroxMetadata);
|
|
33
|
+
if (!woroxDoc.valid) {
|
|
34
|
+
console.error("Worox metadata document is INVALID", woroxDoc.errors);
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
}
|
|
37
|
+
const execOk = (0, validateWorox_1.validateExecutionAgainstContract)(withWoroxMetadata, { ok: true });
|
|
38
|
+
const execBad = (0, validateWorox_1.validateExecutionAgainstContract)(withWoroxMetadata, {});
|
|
39
|
+
const outOk = (0, validateWorox_1.validateFinalOutputAgainstContract)(withWoroxMetadata, "done");
|
|
40
|
+
const outBad = (0, validateWorox_1.validateFinalOutputAgainstContract)(withWoroxMetadata, "");
|
|
41
|
+
if (!execOk.valid || execBad.valid || !outOk.valid || outBad.valid) {
|
|
42
|
+
console.error("Worox runtime validation smoke test failed", {
|
|
43
|
+
execOk,
|
|
44
|
+
execBad,
|
|
45
|
+
outOk,
|
|
46
|
+
outBad
|
|
47
|
+
});
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
}
|
|
13
50
|
//# sourceMappingURL=validate-minimal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-minimal.js","sourceRoot":"","sources":["../../src/examples/validate-minimal.ts"],"names":[],"mappings":";;AAAA,0CAA4C;AAC5C,mDAA+C;AAE/C,MAAM,MAAM,GAAG,IAAA,wBAAa,EAAC,4BAAY,CAAC,CAAC;AAE3C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;AAC5E,CAAC"}
|
|
1
|
+
{"version":3,"file":"validate-minimal.js","sourceRoot":"","sources":["../../src/examples/validate-minimal.ts"],"names":[],"mappings":";;AAAA,0CAA4C;AAC5C,oDAG0B;AAE1B,mDAA+C;AAE/C,MAAM,MAAM,GAAG,IAAA,wBAAa,EAAC,4BAAY,CAAC,CAAC;AAE3C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,iBAAiB,GAAkB;IACvC,GAAG,4BAAY;IACf,QAAQ,EAAE;QACR,UAAU,EAAE;YACV,OAAO,EAAE,2BAA2B;YACpC,sBAAsB,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC;YACjD,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;gBACvC,QAAQ,EAAE,CAAC,IAAI,CAAC;aACjB;SACF;QACD,aAAa,EAAE;YACb,OAAO,EAAE,8BAA8B;YACvC,iBAAiB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;SACpD;KACF;CACF,CAAC;AAEF,MAAM,QAAQ,GAAG,IAAA,wBAAa,EAAC,iBAAiB,CAAC,CAAC;AAClD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACpB,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,MAAM,GAAG,IAAA,gDAAgC,EAAC,iBAAiB,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AACjF,MAAM,OAAO,GAAG,IAAA,gDAAgC,EAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AACxE,MAAM,KAAK,GAAG,IAAA,kDAAkC,EAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;AAC5E,MAAM,MAAM,GAAG,IAAA,kDAAkC,EAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAEzE,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;IACnE,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE;QAC1D,MAAM;QACN,OAAO;QACP,KAAK;QACL,MAAM;KACP,CAAC,CAAC;IACH,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,QAAQ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -16,5 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./types"), exports);
|
|
18
18
|
__exportStar(require("./validate"), exports);
|
|
19
|
+
__exportStar(require("./validateWorox"), exports);
|
|
19
20
|
__exportStar(require("./crud"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,6CAA2B;AAC3B,yCAAuB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,6CAA2B;AAC3B,kDAAgC;AAChC,yCAAuB"}
|