process-graph 1.0.5 → 1.1.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 +85 -17
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +92 -0
- package/dist/cli.d.ts +512 -0
- package/dist/cli.js +3 -0
- package/dist/control-aDk9560d.js +294 -0
- package/dist/detail-panel-B1ZmMuJT.js +341 -0
- package/dist/dist-BpCBmnMl.js +582 -0
- package/dist/dist-HLlW8vgT.js +1388 -0
- package/dist/dist-IjrgWhHQ.js +3 -0
- package/dist/errors-BZe5WzCn.js +19 -0
- package/dist/exit-codes-0ultCqdS.js +23 -0
- package/dist/graphql-C1j5wQFz.d.ts +631 -0
- package/dist/index-CCfe0csl.d.ts +353 -0
- package/dist/index-CmZOswkx.d.ts +512 -0
- package/dist/index-CoA6vXqe.d.ts +404 -0
- package/dist/index-CptUHq6F.d.ts +58 -0
- package/dist/index-CrM5qWUA.d.ts +110 -0
- package/dist/index-DhbvDgK4.d.ts +1582 -0
- package/dist/index-DricKcyl.d.ts +421 -0
- package/dist/index.d.ts +111 -4
- package/dist/index.js +929 -5
- package/dist/layout-CCM-KBdp.js +307 -0
- package/dist/layout.d.ts +8 -0
- package/dist/layout.js +2 -0
- package/dist/node-AchI1T-K.js +40 -0
- package/dist/open-CyRXJ4bt.js +29 -0
- package/dist/parse-CuipC_2K.js +41 -0
- package/dist/queries-CCexJAE2.js +2202 -0
- package/dist/react-flow/style.css +658 -0
- package/dist/react-flow.d.ts +173 -0
- package/dist/react-flow.js +450 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +107 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/router-D4gtTlXm.js +188 -0
- package/dist/schema-CVnS6HiX.js +234 -0
- package/dist/selection-BW_xXWOy.js +314 -0
- package/dist/source/github/node.d.ts +16 -0
- package/dist/source/github/node.js +2 -0
- package/dist/source/github.d.ts +49 -0
- package/dist/source/github.js +201 -0
- package/dist/source-DRDpEA8Q.js +1316 -0
- package/dist/status-Bm1CGu9C.js +11 -0
- package/dist/store/node.d.ts +24 -0
- package/dist/store/node.js +2 -0
- package/dist/store/wasm/worker.d.ts +16 -0
- package/dist/store/wasm/worker.js +98 -0
- package/dist/store/wasm.d.ts +9 -0
- package/dist/store/wasm.js +11 -0
- package/dist/store-BcR70CaO.js +1287 -0
- package/dist/store.d.ts +1328 -0
- package/dist/store.js +238 -0
- package/dist/ui/style.css +351 -0
- package/dist/ui.d.ts +235 -0
- package/dist/ui.js +2 -0
- package/dist/validate-DF3mQZww.js +125 -0
- package/package.json +148 -13
package/dist/react.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { _ as toSwimlane, g as toStateMachine, m as toSequence, y as toFlowchart } from "./queries-CCexJAE2.js";
|
|
2
|
+
import { a as filterOptions, c as useElementFilter, d as useBlockers, f as useCriticalPath, g as useWhyStatus, h as useStatuses, i as filterElements, l as stepWeight, m as useReadySet, n as actorsOf, o as matchesFilter, p as useImpact, r as emptyFilter, s as sourceScope, t as useGraphSelection, u as useBlockedChain } from "./selection-BW_xXWOy.js";
|
|
3
|
+
import { a as TransitionItem, c as elementLabel, i as Lane, l as ruleDescriptions, n as FilterPanel, o as ElementCard, r as Legend, s as StatusBadge, t as DetailPanel, u as statusLabels } from "./detail-panel-B1ZmMuJT.js";
|
|
4
|
+
import { ORPCError } from "@orpc/client";
|
|
5
|
+
import { useEffect, useMemo, useState } from "react";
|
|
6
|
+
//#region ../../ui/graph/react/dist/run.js
|
|
7
|
+
/**
|
|
8
|
+
* The facts port of a run that has no facts source: every key is not found, so a condition that reads one is indeterminate and no input artefact counts as provided.
|
|
9
|
+
* @returns `{ found: false }` for every key.
|
|
10
|
+
*/
|
|
11
|
+
const noFacts = () => ({ found: false });
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region ../../ui/graph/react/dist/model.js
|
|
14
|
+
const loading = { status: "loading" };
|
|
15
|
+
const missing = { status: "missing" };
|
|
16
|
+
/** Revisions are positive, so every change to a model is newer than this: the revision a missing model is treated as having. */
|
|
17
|
+
const noRevision = 0;
|
|
18
|
+
/**
|
|
19
|
+
* Loads a model from a store and follows it: every change the store reports loads the model again, so the result always reflects the store's latest revision. It subscribes before the first load, so no change between the two is missed. A model the store does not have is `missing` and still followed, so a model that is created later, or deleted and saved again, is loaded when it is.
|
|
20
|
+
* @param client - A `GraphStore` client, over any transport. Keep it stable between renders.
|
|
21
|
+
* @param modelId - The model to follow.
|
|
22
|
+
* @returns `loading` until the first load; then `loaded` with the model, its overlay and revision, `missing` while the store has no such model (its load answers `NOT_FOUND`), or `failed` with any other error a load or the subscription ended with.
|
|
23
|
+
*/
|
|
24
|
+
const useModel = (client, modelId) => {
|
|
25
|
+
const [state, setState] = useState({
|
|
26
|
+
client,
|
|
27
|
+
modelId,
|
|
28
|
+
value: loading
|
|
29
|
+
});
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const { signal } = controller;
|
|
33
|
+
const settle = (value) => {
|
|
34
|
+
setState({
|
|
35
|
+
client,
|
|
36
|
+
modelId,
|
|
37
|
+
value
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const load = async () => {
|
|
41
|
+
try {
|
|
42
|
+
const stored = await client.v1.models.load({ modelId }, { signal });
|
|
43
|
+
settle({
|
|
44
|
+
status: "loaded",
|
|
45
|
+
stored
|
|
46
|
+
});
|
|
47
|
+
return stored.revision;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (error instanceof ORPCError && error.code === "NOT_FOUND") {
|
|
50
|
+
settle(missing);
|
|
51
|
+
return noRevision;
|
|
52
|
+
}
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const follow = async () => {
|
|
57
|
+
const changes = await client.v1.changes({ modelId }, { signal });
|
|
58
|
+
let loaded = await load();
|
|
59
|
+
for await (const change of changes) if (change.kind === "missed" || change.revision > loaded) loaded = await load();
|
|
60
|
+
};
|
|
61
|
+
follow().catch((error) => {
|
|
62
|
+
if (!signal.aborted) settle({
|
|
63
|
+
status: "failed",
|
|
64
|
+
error
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
return () => {
|
|
68
|
+
controller.abort();
|
|
69
|
+
};
|
|
70
|
+
}, [client, modelId]);
|
|
71
|
+
return state.client === client && state.modelId === modelId ? state.value : loading;
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region ../../ui/graph/react/dist/projection.js
|
|
75
|
+
/**
|
|
76
|
+
* Projects a model into the notation a projection names, with the input it records (a subject, a scenario).
|
|
77
|
+
* @param model - The model to project.
|
|
78
|
+
* @param projection - One of the model's declared projections, or one built the same way.
|
|
79
|
+
* @returns The notation and its view.
|
|
80
|
+
*/
|
|
81
|
+
const project = (model, projection) => {
|
|
82
|
+
if (projection.notation === "stateMachine") return {
|
|
83
|
+
notation: "stateMachine",
|
|
84
|
+
view: toStateMachine(model, projection.subject)
|
|
85
|
+
};
|
|
86
|
+
if (projection.notation === "sequence") return {
|
|
87
|
+
notation: "sequence",
|
|
88
|
+
view: toSequence(model, projection.scenario)
|
|
89
|
+
};
|
|
90
|
+
return projection.notation === "swimlane" ? {
|
|
91
|
+
notation: "swimlane",
|
|
92
|
+
view: toSwimlane(model)
|
|
93
|
+
} : {
|
|
94
|
+
notation: "flowchart",
|
|
95
|
+
view: toFlowchart(model)
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* A model's view in one notation, projected again only when the model or the projection changes.
|
|
100
|
+
* @param model - The model to project.
|
|
101
|
+
* @param projection - The projection to draw. Keep it stable between renders, for instance one of `model.projections`.
|
|
102
|
+
* @returns The notation and its view.
|
|
103
|
+
* @throws Error when a state machine's subject is not a declared entity.
|
|
104
|
+
*/
|
|
105
|
+
const useProjection = (model, projection) => useMemo(() => project(model, projection), [model, projection]);
|
|
106
|
+
//#endregion
|
|
107
|
+
export { DetailPanel, ElementCard, FilterPanel, Lane, Legend, StatusBadge, TransitionItem, actorsOf, elementLabel, emptyFilter, filterElements, filterOptions, matchesFilter, noFacts, project, ruleDescriptions, sourceScope, statusLabels, stepWeight, useBlockedChain, useBlockers, useCriticalPath, useElementFilter, useGraphSelection, useImpact, useModel, useProjection, useReadySet, useStatuses, useWhyStatus };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll as t };
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { r as overlaySchema, t as modelSchema } from "./schema-CVnS6HiX.js";
|
|
2
|
+
import { C as modelSummarySchema, D as revisionSchema, E as relationSchema, O as storeChangeSchema, S as modelIdSchema, _ as GraphStoreError, k as storedModelSchema, w as reachSchema, x as issueSchema, y as boundItemsSchema } from "./store-BcR70CaO.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { eventIterator, oc } from "@orpc/contract";
|
|
5
|
+
import { implement } from "@orpc/server";
|
|
6
|
+
//#region ../../core/graph/store-contract/dist/contract.js
|
|
7
|
+
/**
|
|
8
|
+
* The typed errors a procedure can end with, each carrying its detail as data. The codes are oRPC's common codes, so an HTTP transport answers with the matching status (404, 422) without any per-transport mapping.
|
|
9
|
+
*/
|
|
10
|
+
const graphStoreErrors = {
|
|
11
|
+
NOT_FOUND: {
|
|
12
|
+
message: "No such model, or no such element in it.",
|
|
13
|
+
data: z.strictObject({
|
|
14
|
+
modelId: z.string(),
|
|
15
|
+
element: z.string().exactOptional()
|
|
16
|
+
})
|
|
17
|
+
},
|
|
18
|
+
UNPROCESSABLE_CONTENT: {
|
|
19
|
+
message: "The change would leave the model or its overlay invalid.",
|
|
20
|
+
data: z.strictObject({ issues: z.array(issueSchema).readonly() })
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const modelRef = z.strictObject({ modelId: modelIdSchema }).readonly();
|
|
24
|
+
const elementRef = z.strictObject({
|
|
25
|
+
modelId: modelIdSchema,
|
|
26
|
+
element: z.string()
|
|
27
|
+
}).readonly();
|
|
28
|
+
const written = z.strictObject({ revision: revisionSchema }).readonly();
|
|
29
|
+
/** The `GraphStore` port: an oRPC router contract, keyed by version. */
|
|
30
|
+
const graphStoreContract = { v1: oc.errors(graphStoreErrors).router({
|
|
31
|
+
models: {
|
|
32
|
+
list: oc.output(z.array(modelSummarySchema).readonly()),
|
|
33
|
+
save: oc.input(z.strictObject({
|
|
34
|
+
modelId: modelIdSchema,
|
|
35
|
+
model: modelSchema
|
|
36
|
+
}).readonly()).output(written),
|
|
37
|
+
load: oc.input(modelRef).output(storedModelSchema),
|
|
38
|
+
delete: oc.input(modelRef).output(z.union([z.strictObject({
|
|
39
|
+
deleted: z.literal(true),
|
|
40
|
+
revision: revisionSchema
|
|
41
|
+
}).readonly(), z.strictObject({ deleted: z.literal(false) }).readonly()]))
|
|
42
|
+
},
|
|
43
|
+
overlay: { set: oc.input(z.strictObject({
|
|
44
|
+
modelId: modelIdSchema,
|
|
45
|
+
overlay: overlaySchema
|
|
46
|
+
}).readonly()).output(written) },
|
|
47
|
+
items: { upsert: oc.input(z.strictObject({
|
|
48
|
+
modelId: modelIdSchema,
|
|
49
|
+
items: boundItemsSchema
|
|
50
|
+
}).readonly()).output(written) },
|
|
51
|
+
relations: { list: oc.input(modelRef).output(z.strictObject({ relations: z.array(relationSchema).readonly() }).readonly()) },
|
|
52
|
+
query: {
|
|
53
|
+
ready: oc.input(modelRef).output(z.strictObject({ elements: z.array(z.string()).readonly() }).readonly()),
|
|
54
|
+
blockedChain: oc.input(elementRef).output(z.strictObject({ chain: z.array(reachSchema).readonly() }).readonly()),
|
|
55
|
+
impact: oc.input(elementRef).output(z.strictObject({ impacted: z.array(reachSchema).readonly() }).readonly()),
|
|
56
|
+
children: oc.input(elementRef).output(z.strictObject({ children: z.array(z.string()).readonly() }).readonly()),
|
|
57
|
+
descendants: oc.input(elementRef).output(z.strictObject({ descendants: z.array(reachSchema).readonly() }).readonly()),
|
|
58
|
+
ancestors: oc.input(elementRef).output(z.strictObject({ ancestors: z.array(reachSchema).readonly() }).readonly())
|
|
59
|
+
},
|
|
60
|
+
changes: oc.input(z.strictObject({
|
|
61
|
+
modelId: modelIdSchema,
|
|
62
|
+
since: revisionSchema.exactOptional()
|
|
63
|
+
}).readonly()).output(eventIterator(storeChangeSchema))
|
|
64
|
+
}) };
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region ../../core/graph/store-contract/dist/router.js
|
|
67
|
+
const os = implement(graphStoreContract);
|
|
68
|
+
/** Rethrows a store's `GraphStoreError` as the contract's typed oRPC error; anything else propagates unchanged. */
|
|
69
|
+
const toContractError = (error, errors) => {
|
|
70
|
+
if (!(error instanceof GraphStoreError)) return error;
|
|
71
|
+
const { failure } = error;
|
|
72
|
+
if (failure.kind === "not-found") return errors.NOT_FOUND({
|
|
73
|
+
message: error.message,
|
|
74
|
+
data: failure.element === void 0 ? { modelId: failure.modelId } : {
|
|
75
|
+
modelId: failure.modelId,
|
|
76
|
+
element: failure.element
|
|
77
|
+
},
|
|
78
|
+
cause: error
|
|
79
|
+
});
|
|
80
|
+
return errors.UNPROCESSABLE_CONTENT({
|
|
81
|
+
message: error.message,
|
|
82
|
+
data: { issues: failure.issues },
|
|
83
|
+
cause: error
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
/** Runs one store call: refuses an already-aborted signal before touching the store, and maps the store's failures to the contract's errors. */
|
|
87
|
+
const call = async (signal, errors, operation) => {
|
|
88
|
+
signal?.throwIfAborted();
|
|
89
|
+
try {
|
|
90
|
+
return await operation();
|
|
91
|
+
} catch (error) {
|
|
92
|
+
throw toContractError(error, errors);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Builds the `GraphStore` router over a store. Serve it over any oRPC transport, or call it in process with `createRouterClient`.
|
|
97
|
+
*
|
|
98
|
+
* `changes` subscribes to the store's feed before it reads the model's revision and before it returns, so no change is lost between the two, and a caller holding the iterator is already subscribed. When the caller names a revision `since` and the model is no longer at it, the first event is `missed`; every later change follows as it commits.
|
|
99
|
+
* @param store - The adapter.
|
|
100
|
+
* @returns The implemented router for `graphStoreContract`.
|
|
101
|
+
*/
|
|
102
|
+
const createGraphStoreRouter = (store) => os.router({ v1: {
|
|
103
|
+
models: {
|
|
104
|
+
list: os.v1.models.list.handler(async ({ signal, errors }) => call(signal, errors, async () => store.listModels({ signal }))),
|
|
105
|
+
save: os.v1.models.save.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ revision: await store.saveModel({
|
|
106
|
+
...input,
|
|
107
|
+
signal
|
|
108
|
+
}) }))),
|
|
109
|
+
load: os.v1.models.load.handler(async ({ input, signal, errors }) => call(signal, errors, async () => store.loadModel({
|
|
110
|
+
...input,
|
|
111
|
+
signal
|
|
112
|
+
}))),
|
|
113
|
+
delete: os.v1.models.delete.handler(async ({ input, signal, errors }) => call(signal, errors, async () => {
|
|
114
|
+
const revision = await store.deleteModel({
|
|
115
|
+
...input,
|
|
116
|
+
signal
|
|
117
|
+
});
|
|
118
|
+
return revision === void 0 ? { deleted: false } : {
|
|
119
|
+
deleted: true,
|
|
120
|
+
revision
|
|
121
|
+
};
|
|
122
|
+
}))
|
|
123
|
+
},
|
|
124
|
+
overlay: { set: os.v1.overlay.set.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ revision: await store.applyOverlay({
|
|
125
|
+
...input,
|
|
126
|
+
signal
|
|
127
|
+
}) }))) },
|
|
128
|
+
items: { upsert: os.v1.items.upsert.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ revision: await store.upsertItems({
|
|
129
|
+
...input,
|
|
130
|
+
signal
|
|
131
|
+
}) }))) },
|
|
132
|
+
relations: { list: os.v1.relations.list.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ relations: await store.relations({
|
|
133
|
+
...input,
|
|
134
|
+
signal
|
|
135
|
+
}) }))) },
|
|
136
|
+
query: {
|
|
137
|
+
ready: os.v1.query.ready.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ elements: await store.ready({
|
|
138
|
+
...input,
|
|
139
|
+
signal
|
|
140
|
+
}) }))),
|
|
141
|
+
blockedChain: os.v1.query.blockedChain.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ chain: await store.blockedChain({
|
|
142
|
+
...input,
|
|
143
|
+
signal
|
|
144
|
+
}) }))),
|
|
145
|
+
impact: os.v1.query.impact.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ impacted: await store.impact({
|
|
146
|
+
...input,
|
|
147
|
+
signal
|
|
148
|
+
}) }))),
|
|
149
|
+
children: os.v1.query.children.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ children: await store.children({
|
|
150
|
+
...input,
|
|
151
|
+
signal
|
|
152
|
+
}) }))),
|
|
153
|
+
descendants: os.v1.query.descendants.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ descendants: await store.descendants({
|
|
154
|
+
...input,
|
|
155
|
+
signal
|
|
156
|
+
}) }))),
|
|
157
|
+
ancestors: os.v1.query.ancestors.handler(async ({ input, signal, errors }) => call(signal, errors, async () => ({ ancestors: await store.ancestors({
|
|
158
|
+
...input,
|
|
159
|
+
signal
|
|
160
|
+
}) })))
|
|
161
|
+
},
|
|
162
|
+
changes: os.v1.changes.handler(async ({ input, signal, errors }) => {
|
|
163
|
+
const subscription = store.feed.subscribe(input.modelId, { signal });
|
|
164
|
+
let missed = false;
|
|
165
|
+
try {
|
|
166
|
+
if (input.since !== void 0) missed = await call(signal, errors, async () => store.revisionOf({
|
|
167
|
+
modelId: input.modelId,
|
|
168
|
+
signal
|
|
169
|
+
})) !== input.since;
|
|
170
|
+
} catch (error) {
|
|
171
|
+
subscription.close();
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
return (async function* () {
|
|
175
|
+
try {
|
|
176
|
+
if (missed) yield {
|
|
177
|
+
modelId: input.modelId,
|
|
178
|
+
kind: "missed"
|
|
179
|
+
};
|
|
180
|
+
yield* subscription;
|
|
181
|
+
} finally {
|
|
182
|
+
subscription.close();
|
|
183
|
+
}
|
|
184
|
+
})();
|
|
185
|
+
})
|
|
186
|
+
} });
|
|
187
|
+
//#endregion
|
|
188
|
+
export { graphStoreContract as n, createGraphStoreRouter as t };
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { JsonValueSchema, PredicateNodeSchema } from "trilean";
|
|
3
|
+
//#region ../../core/graph/schema/dist/vocabulary.js
|
|
4
|
+
/** What a participant is: a `role` or `system` can act, an `entity` has a lifecycle a state machine can track. */
|
|
5
|
+
const participantKinds = [
|
|
6
|
+
"role",
|
|
7
|
+
"system",
|
|
8
|
+
"entity"
|
|
9
|
+
];
|
|
10
|
+
const pseudoRoles = [
|
|
11
|
+
"initial",
|
|
12
|
+
"final",
|
|
13
|
+
"fork",
|
|
14
|
+
"join",
|
|
15
|
+
"history"
|
|
16
|
+
];
|
|
17
|
+
const messageModes = [
|
|
18
|
+
"sync",
|
|
19
|
+
"async",
|
|
20
|
+
"reply",
|
|
21
|
+
"create",
|
|
22
|
+
"destroy"
|
|
23
|
+
];
|
|
24
|
+
const fragmentOperators = [
|
|
25
|
+
"alt",
|
|
26
|
+
"opt",
|
|
27
|
+
"loop",
|
|
28
|
+
"par",
|
|
29
|
+
"break"
|
|
30
|
+
];
|
|
31
|
+
/** Where an element stands in a run: finished, still to do, or not known. Run state is supplied by sources and never stored in the model. */
|
|
32
|
+
const overlayStatuses = [
|
|
33
|
+
"done",
|
|
34
|
+
"open",
|
|
35
|
+
"unknown"
|
|
36
|
+
];
|
|
37
|
+
const notations = [
|
|
38
|
+
"flowchart",
|
|
39
|
+
"swimlane",
|
|
40
|
+
"stateMachine",
|
|
41
|
+
"sequence"
|
|
42
|
+
];
|
|
43
|
+
/** The kinds of element a model declares, one per variant of `Element`. */
|
|
44
|
+
const elementKinds = [
|
|
45
|
+
"activity",
|
|
46
|
+
"decision",
|
|
47
|
+
"state",
|
|
48
|
+
"pseudo",
|
|
49
|
+
"message"
|
|
50
|
+
];
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region ../../core/graph/schema/dist/pointer.js
|
|
53
|
+
/** Encodes a schema issue path as an RFC 6901 JSON pointer, escaping `~` and `/` inside a segment. The empty path is the document itself, `""`. */
|
|
54
|
+
const toPointer = (path) => path.map((segment) => `/${String(segment).replaceAll("~", "~0").replaceAll("/", "~1")}`).join("");
|
|
55
|
+
//#endregion
|
|
56
|
+
//#region ../../core/graph/schema/dist/overlay.js
|
|
57
|
+
/** The open overlay shape: element identifiers are plain strings. Its inferred type is exactly `Overlay<OpenIds>`. */
|
|
58
|
+
const overlaySchema = z.partialRecord(z.string(), z.enum(overlayStatuses)).readonly();
|
|
59
|
+
/** Thrown by `parseOverlay` when the input is not a valid overlay. */
|
|
60
|
+
var OverlayParseError = class extends Error {
|
|
61
|
+
/** Every problem found. Never empty. */
|
|
62
|
+
issues;
|
|
63
|
+
/**
|
|
64
|
+
* @param issues - The problems found. Must not be empty.
|
|
65
|
+
*/
|
|
66
|
+
constructor(issues) {
|
|
67
|
+
super(`Invalid overlay: ${issues.map((issue) => `${issue.pointer === "" ? "/" : issue.pointer}: ${issue.message}`).join("; ")}`);
|
|
68
|
+
this.name = "OverlayParseError";
|
|
69
|
+
this.issues = issues;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Checks an overlay against the model it is laid over. `parseOverlay` is model-independent, so this is where an element identifier that the model does not declare is found.
|
|
74
|
+
* @param model - The model the overlay is for.
|
|
75
|
+
* @param overlay - The overlay to check.
|
|
76
|
+
* @returns One `overlay-unknown-element` issue per entry whose key is not an element of the model, in the overlay's key order. Empty when every entry names a declared element.
|
|
77
|
+
*/
|
|
78
|
+
const validateOverlay = (model, overlay) => {
|
|
79
|
+
const elementIds = new Set(model.elements.map((e) => e.id));
|
|
80
|
+
return Object.keys(overlay).filter((id) => !elementIds.has(id)).map((id) => ({
|
|
81
|
+
code: "overlay-unknown-element",
|
|
82
|
+
message: `overlay refers to unknown element id "${id}"`
|
|
83
|
+
}));
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Loads an overlay from untrusted input, such as parsed JSON.
|
|
87
|
+
* @param input - The value to load.
|
|
88
|
+
* @returns The overlay, keyed by plain-string element identifiers.
|
|
89
|
+
* @throws OverlayParseError when the input is not an object of element identifier to `"done"`, `"open"` or `"unknown"`.
|
|
90
|
+
*/
|
|
91
|
+
const parseOverlay = (input) => {
|
|
92
|
+
const parsed = overlaySchema.safeParse(input);
|
|
93
|
+
if (!parsed.success) throw new OverlayParseError(parsed.error.issues.map((issue) => ({
|
|
94
|
+
pointer: toPointer(issue.path),
|
|
95
|
+
message: issue.message
|
|
96
|
+
})));
|
|
97
|
+
return parsed.data;
|
|
98
|
+
};
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region ../../core/graph/schema/dist/schema.js
|
|
101
|
+
/** An object schema that rejects unknown keys, so a misspelt field in a loaded document is an error and not silently dropped. */
|
|
102
|
+
const record = (shape) => z.strictObject(shape).readonly();
|
|
103
|
+
const id = z.string();
|
|
104
|
+
const elementRef = z.string();
|
|
105
|
+
const actorRef = z.string();
|
|
106
|
+
const eventRef = z.string();
|
|
107
|
+
const actionRef = z.string();
|
|
108
|
+
const transitionRef = z.string();
|
|
109
|
+
const entityRef = z.string();
|
|
110
|
+
const artefactRef = z.string();
|
|
111
|
+
const extensionsSchema = z.record(z.string(), JsonValueSchema).readonly();
|
|
112
|
+
const participantSchema = record({
|
|
113
|
+
id,
|
|
114
|
+
label: z.string(),
|
|
115
|
+
kind: z.enum(participantKinds)
|
|
116
|
+
});
|
|
117
|
+
const eventSchema = record({
|
|
118
|
+
id,
|
|
119
|
+
name: z.string(),
|
|
120
|
+
payload: z.record(z.string(), z.string()).readonly().exactOptional()
|
|
121
|
+
});
|
|
122
|
+
const actionSchema = record({
|
|
123
|
+
id,
|
|
124
|
+
name: z.string()
|
|
125
|
+
});
|
|
126
|
+
const artefactSchema = record({
|
|
127
|
+
id,
|
|
128
|
+
name: z.string(),
|
|
129
|
+
deliverable: z.boolean().exactOptional()
|
|
130
|
+
});
|
|
131
|
+
const elementSchema = z.discriminatedUnion("kind", [
|
|
132
|
+
record({
|
|
133
|
+
kind: z.literal("activity"),
|
|
134
|
+
id,
|
|
135
|
+
extensions: extensionsSchema.exactOptional(),
|
|
136
|
+
label: z.string(),
|
|
137
|
+
actor: actorRef.exactOptional(),
|
|
138
|
+
action: actionRef.exactOptional(),
|
|
139
|
+
source: z.string().exactOptional(),
|
|
140
|
+
affects: z.array(entityRef).readonly().exactOptional(),
|
|
141
|
+
consumes: z.array(artefactRef).readonly().exactOptional(),
|
|
142
|
+
produces: z.array(artefactRef).readonly().exactOptional()
|
|
143
|
+
}),
|
|
144
|
+
record({
|
|
145
|
+
kind: z.literal("decision"),
|
|
146
|
+
id,
|
|
147
|
+
extensions: extensionsSchema.exactOptional(),
|
|
148
|
+
label: z.string(),
|
|
149
|
+
actor: actorRef.exactOptional()
|
|
150
|
+
}),
|
|
151
|
+
record({
|
|
152
|
+
kind: z.literal("state"),
|
|
153
|
+
id,
|
|
154
|
+
extensions: extensionsSchema.exactOptional(),
|
|
155
|
+
label: z.string(),
|
|
156
|
+
parent: elementRef.exactOptional(),
|
|
157
|
+
entry: actionRef.exactOptional(),
|
|
158
|
+
exit: actionRef.exactOptional()
|
|
159
|
+
}),
|
|
160
|
+
record({
|
|
161
|
+
kind: z.literal("pseudo"),
|
|
162
|
+
id,
|
|
163
|
+
extensions: extensionsSchema.exactOptional(),
|
|
164
|
+
role: z.enum(pseudoRoles),
|
|
165
|
+
parent: elementRef.exactOptional()
|
|
166
|
+
}),
|
|
167
|
+
record({
|
|
168
|
+
kind: z.literal("message"),
|
|
169
|
+
id,
|
|
170
|
+
extensions: extensionsSchema.exactOptional(),
|
|
171
|
+
label: z.string(),
|
|
172
|
+
from: actorRef,
|
|
173
|
+
to: actorRef,
|
|
174
|
+
mode: z.enum(messageModes),
|
|
175
|
+
event: eventRef.exactOptional()
|
|
176
|
+
})
|
|
177
|
+
]);
|
|
178
|
+
const transitionSchema = record({
|
|
179
|
+
id,
|
|
180
|
+
source: elementRef,
|
|
181
|
+
target: elementRef,
|
|
182
|
+
trigger: eventRef.exactOptional(),
|
|
183
|
+
guard: z.string().exactOptional(),
|
|
184
|
+
condition: PredicateNodeSchema.exactOptional(),
|
|
185
|
+
effect: actionRef.exactOptional()
|
|
186
|
+
});
|
|
187
|
+
const fragmentOperandSchema = record({
|
|
188
|
+
guard: z.string().exactOptional(),
|
|
189
|
+
body: z.array(elementRef).readonly()
|
|
190
|
+
});
|
|
191
|
+
const fragmentSchema = record({
|
|
192
|
+
id,
|
|
193
|
+
operator: z.enum(fragmentOperators),
|
|
194
|
+
operands: z.array(fragmentOperandSchema).readonly()
|
|
195
|
+
});
|
|
196
|
+
const projectionSchema = z.union([
|
|
197
|
+
record({
|
|
198
|
+
id: z.string(),
|
|
199
|
+
notation: z.enum(["flowchart", "swimlane"])
|
|
200
|
+
}),
|
|
201
|
+
record({
|
|
202
|
+
id: z.string(),
|
|
203
|
+
notation: z.literal("stateMachine"),
|
|
204
|
+
subject: entityRef
|
|
205
|
+
}),
|
|
206
|
+
record({
|
|
207
|
+
id: z.string(),
|
|
208
|
+
notation: z.literal("sequence"),
|
|
209
|
+
scenario: z.array(transitionRef).readonly()
|
|
210
|
+
})
|
|
211
|
+
]);
|
|
212
|
+
const pointSchema = record({
|
|
213
|
+
x: z.number(),
|
|
214
|
+
y: z.number()
|
|
215
|
+
});
|
|
216
|
+
const viewsSchema = z.partialRecord(z.enum(notations), z.partialRecord(z.string(), pointSchema).readonly()).readonly();
|
|
217
|
+
/**
|
|
218
|
+
* The open (runtime) shape of a model: identifiers are plain strings, so references are not checked here. `validate` checks what the shape cannot, and `parseModel` runs both.
|
|
219
|
+
*
|
|
220
|
+
* Every object is strict. The inferred type is exactly `Model<OpenIds>`, which a type-level test pins in both directions.
|
|
221
|
+
*/
|
|
222
|
+
const modelSchema = record({
|
|
223
|
+
participants: z.array(participantSchema).readonly(),
|
|
224
|
+
events: z.array(eventSchema).readonly(),
|
|
225
|
+
actions: z.array(actionSchema).readonly(),
|
|
226
|
+
artefacts: z.array(artefactSchema).readonly(),
|
|
227
|
+
elements: z.array(elementSchema).readonly(),
|
|
228
|
+
transitions: z.array(transitionSchema).readonly(),
|
|
229
|
+
fragments: z.array(fragmentSchema).readonly(),
|
|
230
|
+
projections: z.array(projectionSchema).readonly(),
|
|
231
|
+
views: viewsSchema.exactOptional()
|
|
232
|
+
});
|
|
233
|
+
//#endregion
|
|
234
|
+
export { validateOverlay as a, fragmentOperators as c, overlayStatuses as d, participantKinds as f, parseOverlay as i, messageModes as l, OverlayParseError as n, toPointer as o, pseudoRoles as p, overlaySchema as r, elementKinds as s, modelSchema as t, notations as u };
|