@bpmn-ld/bpmn-ld 0.0.0-stage → 0.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/LICENSE +201 -0
- package/README.md +125 -2
- package/contexts/combined.jsonld +3 -0
- package/contexts/core.jsonld +170 -0
- package/contexts/di.jsonld +37 -0
- package/dist/analyze/analyze.d.ts +3 -0
- package/dist/analyze/analyze.js +11 -0
- package/dist/analyze/findings.d.ts +8 -0
- package/dist/analyze/findings.js +1 -0
- package/dist/analyze/report.d.ts +3 -0
- package/dist/analyze/report.js +9 -0
- package/dist/analyze/rules/ad-hoc-completion-condition.d.ts +2 -0
- package/dist/analyze/rules/ad-hoc-completion-condition.js +7 -0
- package/dist/analyze/rules/cannot-reach-end.d.ts +2 -0
- package/dist/analyze/rules/cannot-reach-end.js +28 -0
- package/dist/analyze/rules/compensation-association.d.ts +2 -0
- package/dist/analyze/rules/compensation-association.js +13 -0
- package/dist/analyze/rules/dead-end.d.ts +2 -0
- package/dist/analyze/rules/dead-end.js +13 -0
- package/dist/analyze/rules/end-event.d.ts +2 -0
- package/dist/analyze/rules/end-event.js +8 -0
- package/dist/analyze/rules/error-catch.d.ts +2 -0
- package/dist/analyze/rules/error-catch.js +14 -0
- package/dist/analyze/rules/escalation-catch.d.ts +2 -0
- package/dist/analyze/rules/escalation-catch.js +14 -0
- package/dist/analyze/rules/gateway-cardinality.d.ts +3 -0
- package/dist/analyze/rules/gateway-cardinality.js +17 -0
- package/dist/analyze/rules/index.d.ts +4 -0
- package/dist/analyze/rules/index.js +21 -0
- package/dist/analyze/rules/instantiating-gateway.d.ts +2 -0
- package/dist/analyze/rules/instantiating-gateway.js +14 -0
- package/dist/analyze/rules/non-interrupting-start.d.ts +2 -0
- package/dist/analyze/rules/non-interrupting-start.js +14 -0
- package/dist/analyze/rules/reachability.d.ts +2 -0
- package/dist/analyze/rules/reachability.js +25 -0
- package/dist/analyze/rules/rule.d.ts +7 -0
- package/dist/analyze/rules/rule.js +1 -0
- package/dist/analyze/rules/signal-catch.d.ts +2 -0
- package/dist/analyze/rules/signal-catch.js +12 -0
- package/dist/analyze/rules/split-join-pairing.d.ts +3 -0
- package/dist/analyze/rules/split-join-pairing.js +50 -0
- package/dist/analyze/rules/start-event.d.ts +2 -0
- package/dist/analyze/rules/start-event.js +8 -0
- package/dist/analyze/rules/task-message-flow.d.ts +2 -0
- package/dist/analyze/rules/task-message-flow.js +19 -0
- package/dist/analyze/scope-graph.d.ts +56 -0
- package/dist/analyze/scope-graph.js +89 -0
- package/dist/analyze-cli.d.ts +1 -0
- package/dist/analyze-cli.js +5 -0
- package/dist/analyze-run.d.ts +12 -0
- package/dist/analyze-run.js +85 -0
- package/dist/bpmn-ld-cli.d.ts +1 -0
- package/dist/bpmn-ld-cli.js +90 -0
- package/dist/build-cli.d.ts +1 -0
- package/dist/build-cli.js +2 -0
- package/dist/build.d.ts +3 -0
- package/dist/build.js +38 -0
- package/dist/check-xml/check.d.ts +3 -0
- package/dist/check-xml/check.js +11 -0
- package/dist/check-xml/lint.d.ts +2 -0
- package/dist/check-xml/lint.js +47 -0
- package/dist/check-xml/moddle.d.ts +6 -0
- package/dist/check-xml/moddle.js +23 -0
- package/dist/check-xml/types.d.ts +20 -0
- package/dist/check-xml/types.js +1 -0
- package/dist/check-xml/xsd.d.ts +2 -0
- package/dist/check-xml/xsd.js +25 -0
- package/dist/check-xml-cli.d.ts +1 -0
- package/dist/check-xml-cli.js +5 -0
- package/dist/check-xml-run.d.ts +10 -0
- package/dist/check-xml-run.js +77 -0
- package/dist/convert/analyze-output.d.ts +3 -0
- package/dist/convert/analyze-output.js +8 -0
- package/dist/convert/convert.d.ts +19 -0
- package/dist/convert/convert.js +96 -0
- package/dist/convert/errors.d.ts +5 -0
- package/dist/convert/errors.js +8 -0
- package/dist/convert/extensions.d.ts +23 -0
- package/dist/convert/extensions.js +103 -0
- package/dist/convert/mapping-check.d.ts +15 -0
- package/dist/convert/mapping-check.js +66 -0
- package/dist/convert/mapping.d.ts +52 -0
- package/dist/convert/mapping.js +273 -0
- package/dist/convert/namespaces.d.ts +2 -0
- package/dist/convert/namespaces.js +19 -0
- package/dist/convert/validate-output.d.ts +2 -0
- package/dist/convert/validate-output.js +28 -0
- package/dist/convert/warnings.d.ts +9 -0
- package/dist/convert/warnings.js +67 -0
- package/dist/convert/xml-reader.d.ts +11 -0
- package/dist/convert/xml-reader.js +84 -0
- package/dist/convert-cli.d.ts +1 -0
- package/dist/convert-cli.js +5 -0
- package/dist/convert-run.d.ts +10 -0
- package/dist/convert-run.js +125 -0
- package/dist/coverage-cli.d.ts +1 -0
- package/dist/coverage-cli.js +8 -0
- package/dist/coverage-mappings.d.ts +3 -0
- package/dist/coverage-mappings.js +34 -0
- package/dist/coverage-scope.d.ts +11 -0
- package/dist/coverage-scope.js +187 -0
- package/dist/coverage-xsd.d.ts +15 -0
- package/dist/coverage-xsd.js +55 -0
- package/dist/coverage.d.ts +35 -0
- package/dist/coverage.js +152 -0
- package/dist/docs-cli.d.ts +1 -0
- package/dist/docs-cli.js +18 -0
- package/dist/docs.d.ts +8 -0
- package/dist/docs.js +136 -0
- package/dist/eval/checks.d.ts +19 -0
- package/dist/eval/checks.js +252 -0
- package/dist/eval/regenerate.d.ts +10 -0
- package/dist/eval/regenerate.js +48 -0
- package/dist/eval-regenerate-cli.d.ts +1 -0
- package/dist/eval-regenerate-cli.js +16 -0
- package/dist/export/data.d.ts +10 -0
- package/dist/export/data.js +127 -0
- package/dist/export/diagram.d.ts +8 -0
- package/dist/export/diagram.js +112 -0
- package/dist/export/element.d.ts +27 -0
- package/dist/export/element.js +175 -0
- package/dist/export/export.d.ts +22 -0
- package/dist/export/export.js +124 -0
- package/dist/export/extensions.d.ts +18 -0
- package/dist/export/extensions.js +122 -0
- package/dist/export/layout-export.d.ts +4 -0
- package/dist/export/layout-export.js +25 -0
- package/dist/export/mapping-check.d.ts +39 -0
- package/dist/export/mapping-check.js +175 -0
- package/dist/export/normalize.d.ts +3 -0
- package/dist/export/normalize.js +67 -0
- package/dist/export-cli.d.ts +1 -0
- package/dist/export-cli.js +5 -0
- package/dist/export-run.d.ts +10 -0
- package/dist/export-run.js +157 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/install-skill-run.d.ts +8 -0
- package/dist/install-skill-run.js +30 -0
- package/dist/install-skill.d.ts +23 -0
- package/dist/install-skill.js +76 -0
- package/dist/layout/collaboration.d.ts +36 -0
- package/dist/layout/collaboration.js +152 -0
- package/dist/layout/di.d.ts +15 -0
- package/dist/layout/di.js +52 -0
- package/dist/layout/extract.d.ts +2 -0
- package/dist/layout/extract.js +99 -0
- package/dist/layout/lanes.d.ts +30 -0
- package/dist/layout/lanes.js +112 -0
- package/dist/layout/layering.d.ts +7 -0
- package/dist/layout/layering.js +53 -0
- package/dist/layout/layout.d.ts +12 -0
- package/dist/layout/layout.js +299 -0
- package/dist/layout/model.d.ts +52 -0
- package/dist/layout/model.js +10 -0
- package/dist/layout/placement.d.ts +25 -0
- package/dist/layout/placement.js +256 -0
- package/dist/layout/standalone.d.ts +8 -0
- package/dist/layout/standalone.js +50 -0
- package/dist/layout-cli.d.ts +1 -0
- package/dist/layout-cli.js +5 -0
- package/dist/layout-run.d.ts +9 -0
- package/dist/layout-run.js +105 -0
- package/dist/loader.d.ts +5 -0
- package/dist/loader.js +7 -0
- package/dist/namespace.d.ts +5 -0
- package/dist/namespace.js +5 -0
- package/dist/ontology.d.ts +19 -0
- package/dist/ontology.js +94 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.js +2 -0
- package/dist/render/geometry.d.ts +40 -0
- package/dist/render/geometry.js +81 -0
- package/dist/render/renderer.d.ts +31 -0
- package/dist/render/renderer.js +369 -0
- package/dist/render/symbols.d.ts +10 -0
- package/dist/render/symbols.js +26 -0
- package/dist/render/text.d.ts +20 -0
- package/dist/render/text.js +28 -0
- package/dist/render-cli.d.ts +1 -0
- package/dist/render-cli.js +7 -0
- package/dist/render-run.d.ts +9 -0
- package/dist/render-run.js +161 -0
- package/dist/render.d.ts +4 -0
- package/dist/render.js +4 -0
- package/dist/schema-overrides.d.ts +14 -0
- package/dist/schema-overrides.js +36 -0
- package/dist/schema-validate.d.ts +5 -0
- package/dist/schema-validate.js +8 -0
- package/dist/schema.d.ts +6 -0
- package/dist/schema.js +114 -0
- package/dist/shacl.d.ts +15 -0
- package/dist/shacl.js +37 -0
- package/dist/validate-cli.d.ts +1 -0
- package/dist/validate-cli.js +5 -0
- package/dist/validate-run.d.ts +8 -0
- package/dist/validate-run.js +58 -0
- package/dist/validate.d.ts +11 -0
- package/dist/validate.js +94 -0
- package/dist/versioning-cli.d.ts +1 -0
- package/dist/versioning-cli.js +18 -0
- package/dist/versioning.d.ts +17 -0
- package/dist/versioning.js +45 -0
- package/ontology/core.ttl +993 -0
- package/ontology/di.ttl +167 -0
- package/package.json +76 -4
- package/schema/bpmn-ld.schema.json +15230 -0
- package/shapes/core.shapes.ttl +398 -0
- package/skills/bpmn-ld/SKILL.md +154 -0
- package/skills/bpmn-ld/evals/models/order-approval-di.jsonld +296 -0
- package/skills/bpmn-ld/evals/models/refund-di.bpmn +82 -0
- package/skills/bpmn-ld/evals/models/refund.bpmn +18 -0
- package/skills/bpmn-ld/evals/outputs/explain-collaboration.md +22 -0
- package/skills/bpmn-ld/evals/outputs/explain-order-approval.md +24 -0
- package/skills/bpmn-ld/evals/outputs/explain-refund.md +17 -0
- package/skills/bpmn-ld/evals/outputs/generate-activity-compensation.jsonld +39 -0
- package/skills/bpmn-ld/evals/outputs/generate-ad-hoc-sub-process.jsonld +52 -0
- package/skills/bpmn-ld/evals/outputs/generate-boundary-event.jsonld +27 -0
- package/skills/bpmn-ld/evals/outputs/generate-collaboration.jsonld +49 -0
- package/skills/bpmn-ld/evals/outputs/generate-conditions.jsonld +93 -0
- package/skills/bpmn-ld/evals/outputs/generate-diagram-properties.jsonld +340 -0
- package/skills/bpmn-ld/evals/outputs/generate-error.jsonld +217 -0
- package/skills/bpmn-ld/evals/outputs/generate-escalation.jsonld +231 -0
- package/skills/bpmn-ld/evals/outputs/generate-event-definition-ref.jsonld +67 -0
- package/skills/bpmn-ld/evals/outputs/generate-event-sub-process.jsonld +54 -0
- package/skills/bpmn-ld/evals/outputs/generate-exclusive-choice.jsonld +32 -0
- package/skills/bpmn-ld/evals/outputs/generate-instantiating-gateway.jsonld +24 -0
- package/skills/bpmn-ld/evals/outputs/generate-lane-partition.jsonld +46 -0
- package/skills/bpmn-ld/evals/outputs/generate-link-event.expect.json +11 -0
- package/skills/bpmn-ld/evals/outputs/generate-link-event.jsonld +57 -0
- package/skills/bpmn-ld/evals/outputs/generate-loop.jsonld +30 -0
- package/skills/bpmn-ld/evals/outputs/generate-message.jsonld +61 -0
- package/skills/bpmn-ld/evals/outputs/generate-parallel-branches.jsonld +25 -0
- package/skills/bpmn-ld/evals/outputs/generate-process-attributes.jsonld +49 -0
- package/skills/bpmn-ld/evals/outputs/generate-script-task.jsonld +18 -0
- package/skills/bpmn-ld/evals/outputs/generate-signal.jsonld +178 -0
- package/skills/bpmn-ld/evals/outputs/generate-sub-process.jsonld +31 -0
- package/skills/bpmn-ld/evals/outputs/generate-targeted-compensation.jsonld +40 -0
- package/skills/bpmn-ld/evals/outputs/generate-task-implementation.jsonld +18 -0
- package/skills/bpmn-ld/evals/outputs/generate-task-message-references.jsonld +49 -0
- package/skills/bpmn-ld/evals/outputs/generate-transaction.jsonld +48 -0
- package/skills/bpmn-ld/evals/outputs/modify-order-approval.jsonld +376 -0
- package/skills/bpmn-ld/evals/outputs/modify-refund.jsonld +373 -0
- package/skills/bpmn-ld/evals/outputs/order-approval.jsonld +29 -0
- package/skills/bpmn-ld/evals/outputs/refine-order-approval.jsonld +377 -0
- package/skills/bpmn-ld/evals/prompts/explain-collaboration.md +3 -0
- package/skills/bpmn-ld/evals/prompts/explain-order-approval.md +3 -0
- package/skills/bpmn-ld/evals/prompts/explain-refund.md +3 -0
- package/skills/bpmn-ld/evals/prompts/generate-activity-compensation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-ad-hoc-sub-process.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-boundary-event.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-collaboration.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-conditions.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-diagram-properties.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-error.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-escalation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-event-definition-ref.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-event-sub-process.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-exclusive-choice.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-instantiating-gateway.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-lane-partition.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-link-event.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-loop.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-message.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-parallel-branches.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-process-attributes.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-script-task.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-signal.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-sub-process.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-targeted-compensation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-task-implementation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-task-message-references.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-transaction.md +1 -0
- package/skills/bpmn-ld/evals/prompts/modify-order-approval.md +4 -0
- package/skills/bpmn-ld/evals/prompts/modify-refund.md +4 -0
- package/skills/bpmn-ld/evals/prompts/order-approval.md +1 -0
- package/skills/bpmn-ld/evals/prompts/refine-order-approval.md +8 -0
- package/skills/bpmn-ld/examples/positive/activity-compensation.jsonld +39 -0
- package/skills/bpmn-ld/examples/positive/ad-hoc-sub-process.jsonld +52 -0
- package/skills/bpmn-ld/examples/positive/boundary-event.jsonld +27 -0
- package/skills/bpmn-ld/examples/positive/collaboration.jsonld +49 -0
- package/skills/bpmn-ld/examples/positive/conditions.jsonld +93 -0
- package/skills/bpmn-ld/examples/positive/diagram-properties.jsonld +340 -0
- package/skills/bpmn-ld/examples/positive/error.jsonld +208 -0
- package/skills/bpmn-ld/examples/positive/escalation.jsonld +231 -0
- package/skills/bpmn-ld/examples/positive/event-definition-ref.jsonld +142 -0
- package/skills/bpmn-ld/examples/positive/event-sub-process.jsonld +54 -0
- package/skills/bpmn-ld/examples/positive/exclusive-choice.jsonld +32 -0
- package/skills/bpmn-ld/examples/positive/instantiating-gateway.jsonld +24 -0
- package/skills/bpmn-ld/examples/positive/lane-partition.jsonld +46 -0
- package/skills/bpmn-ld/examples/positive/link-event.expect.json +10 -0
- package/skills/bpmn-ld/examples/positive/link-event.jsonld +138 -0
- package/skills/bpmn-ld/examples/positive/loop.jsonld +30 -0
- package/skills/bpmn-ld/examples/positive/message.jsonld +60 -0
- package/skills/bpmn-ld/examples/positive/order-approval.jsonld +29 -0
- package/skills/bpmn-ld/examples/positive/parallel-branches.jsonld +25 -0
- package/skills/bpmn-ld/examples/positive/process-attributes.jsonld +49 -0
- package/skills/bpmn-ld/examples/positive/script-task.jsonld +18 -0
- package/skills/bpmn-ld/examples/positive/signal.jsonld +150 -0
- package/skills/bpmn-ld/examples/positive/sub-process.jsonld +31 -0
- package/skills/bpmn-ld/examples/positive/targeted-compensation.jsonld +40 -0
- package/skills/bpmn-ld/examples/positive/task-implementation.jsonld +18 -0
- package/skills/bpmn-ld/examples/positive/task-message-references.jsonld +151 -0
- package/skills/bpmn-ld/examples/positive/transaction.jsonld +48 -0
- package/skills/bpmn-ld/references/clarification-and-refinement.md +60 -0
- package/skills/bpmn-ld/references/common-mistakes.md +110 -0
- package/skills/bpmn-ld/references/explain-and-document.md +36 -0
- package/skills/bpmn-ld/references/modify-existing-model.md +49 -0
- package/skills/bpmn-ld/references/patterns.md +292 -0
- package/skills/bpmn-ld/references/render-output.md +1 -0
- package/skills/bpmn-ld/references/rule-catalogue.md +183 -0
- package/skills/bpmn-ld/references/vocabulary-summary.md +65 -0
- package/skills/bpmn-ld/template.jsonld +14 -0
- package/templates/combined.jsonld +3 -0
- package/templates/core.jsonld +170 -0
- package/templates/core.shapes.ttl +398 -0
- package/templates/core.ttl +993 -0
- package/templates/di.jsonld +37 -0
- package/templates/di.ttl +167 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ElementMapping } from "../convert/mapping.ts";
|
|
2
|
+
export declare const DATA_MAPPINGS: Record<string, ElementMapping>;
|
|
3
|
+
export declare const EXPRESSION_ELEMENTS: string[];
|
|
4
|
+
export declare const MAPPINGS: Record<string, ElementMapping>;
|
|
5
|
+
export declare const THROW_EVENTS: string[];
|
|
6
|
+
export declare const CATCH_EVENTS: string[];
|
|
7
|
+
export declare const CONTAINS: Record<string, Record<string, string>>;
|
|
8
|
+
export declare const EVENT_DEFINITION_ROOTS: Record<string, string>;
|
|
9
|
+
export declare const DATA_ROOT_ELEMENTS: Record<string, string>;
|
|
10
|
+
export declare const childRank: (key: string) => number;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { CONTAINMENT, ELEMENT_MAPPINGS } from "../convert/mapping.js";
|
|
2
|
+
const named = { id: "id", name: "name" };
|
|
3
|
+
const flowDataElements = ["dataObject", "dataObjectReference", "dataStoreReference"];
|
|
4
|
+
export const DATA_MAPPINGS = {
|
|
5
|
+
dataObject: { type: "DataObject", attributes: { ...named, isCollection: "isCollection" } },
|
|
6
|
+
dataObjectReference: { type: "DataObjectReference", attributes: { ...named, dataObjectRef: "dataObjectRef" } },
|
|
7
|
+
dataStore: {
|
|
8
|
+
type: "DataStore",
|
|
9
|
+
attributes: { ...named, capacity: "capacity", isUnlimited: "isUnlimited" },
|
|
10
|
+
},
|
|
11
|
+
dataStoreReference: { type: "DataStoreReference", attributes: { ...named, dataStoreRef: "dataStoreRef" } },
|
|
12
|
+
};
|
|
13
|
+
const CONTAINER_ACTIVITIES = ["subProcess", "adHocSubProcess", "transaction"];
|
|
14
|
+
const ACTIVITIES = ["task", "businessRuleTask", "manualTask", "receiveTask", "sendTask", "scriptTask", "serviceTask", "userTask", ...CONTAINER_ACTIVITIES];
|
|
15
|
+
const withIoSpecification = Object.fromEntries(ACTIVITIES.map((name) => [
|
|
16
|
+
name,
|
|
17
|
+
{ ...ELEMENT_MAPPINGS[name], singles: { ...ELEMENT_MAPPINGS[name].singles, ioSpecification: "ioSpecification" } },
|
|
18
|
+
]));
|
|
19
|
+
const dataItem = { ...named, isCollection: "isCollection" };
|
|
20
|
+
const SET_MAPPINGS = {
|
|
21
|
+
ioSpecification: { type: "InputOutputSpecification", attributes: { id: "id" } },
|
|
22
|
+
dataInput: { type: "DataInput", attributes: dataItem },
|
|
23
|
+
dataOutput: { type: "DataOutput", attributes: dataItem },
|
|
24
|
+
inputSet: {
|
|
25
|
+
type: "InputSet",
|
|
26
|
+
attributes: { id: "id" },
|
|
27
|
+
textLists: {
|
|
28
|
+
dataInputRefs: "dataInputRefs",
|
|
29
|
+
optionalInputRefs: "optionalInputRefs",
|
|
30
|
+
whileExecutingInputRefs: "whileExecutingInputRefs",
|
|
31
|
+
outputSetRefs: "outputSetRefs",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
outputSet: {
|
|
35
|
+
type: "OutputSet",
|
|
36
|
+
attributes: { id: "id" },
|
|
37
|
+
textLists: {
|
|
38
|
+
dataOutputRefs: "dataOutputRefs",
|
|
39
|
+
optionalOutputRefs: "optionalOutputRefs",
|
|
40
|
+
whileExecutingOutputRefs: "whileExecutingOutputRefs",
|
|
41
|
+
inputSetRefs: "inputSetRefs",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const expression = () => ({
|
|
46
|
+
type: "FormalExpression",
|
|
47
|
+
attributes: { language: "language", evaluatesToTypeRef: "evaluatesToTypeRef" },
|
|
48
|
+
bodyTerm: "body",
|
|
49
|
+
anonymous: true,
|
|
50
|
+
});
|
|
51
|
+
const association = (type) => ({
|
|
52
|
+
type,
|
|
53
|
+
attributes: { id: "id" },
|
|
54
|
+
textLists: { sourceRef: "sourceRef" },
|
|
55
|
+
textChildren: { targetRef: "targetRef" },
|
|
56
|
+
singles: { transformation: "transformation" },
|
|
57
|
+
});
|
|
58
|
+
const ASSOCIATION_MAPPINGS = {
|
|
59
|
+
dataInputAssociation: association("DataInputAssociation"),
|
|
60
|
+
dataOutputAssociation: association("DataOutputAssociation"),
|
|
61
|
+
assignment: { type: "Assignment", attributes: { id: "id" }, singles: { from: "from", to: "to" } },
|
|
62
|
+
transformation: expression(),
|
|
63
|
+
from: expression(),
|
|
64
|
+
to: expression(),
|
|
65
|
+
};
|
|
66
|
+
const CONDITION_ELEMENTS = ["completionCondition", "condition", "activationCondition"];
|
|
67
|
+
export const EXPRESSION_ELEMENTS = ["conditionExpression", ...CONDITION_ELEMENTS, "transformation", "from", "to"];
|
|
68
|
+
export const MAPPINGS = {
|
|
69
|
+
...ELEMENT_MAPPINGS,
|
|
70
|
+
...withIoSpecification,
|
|
71
|
+
...DATA_MAPPINGS,
|
|
72
|
+
...SET_MAPPINGS,
|
|
73
|
+
...ASSOCIATION_MAPPINGS,
|
|
74
|
+
};
|
|
75
|
+
const flowData = Object.fromEntries(flowDataElements.map((name) => [name, "flowElements"]));
|
|
76
|
+
const associations = { dataInputAssociation: "dataInputAssociations", dataOutputAssociation: "dataOutputAssociations" };
|
|
77
|
+
const throwData = { dataInput: "dataInputs", dataInputAssociation: "dataInputAssociations", inputSet: "inputSets" };
|
|
78
|
+
const catchData = { dataOutput: "dataOutputs", dataOutputAssociation: "dataOutputAssociations", outputSet: "outputSets" };
|
|
79
|
+
export const THROW_EVENTS = ["intermediateThrowEvent", "implicitThrowEvent", "endEvent"];
|
|
80
|
+
export const CATCH_EVENTS = ["startEvent", "intermediateCatchEvent", "boundaryEvent"];
|
|
81
|
+
const dataContainment = {
|
|
82
|
+
process: flowData,
|
|
83
|
+
...Object.fromEntries(CONTAINER_ACTIVITIES.map((name) => [name, { ...flowData, ...associations }])),
|
|
84
|
+
...Object.fromEntries(ACTIVITIES.filter((name) => !CONTAINER_ACTIVITIES.includes(name)).map((name) => [name, associations])),
|
|
85
|
+
...Object.fromEntries(THROW_EVENTS.map((name) => [name, throwData])),
|
|
86
|
+
...Object.fromEntries(CATCH_EVENTS.map((name) => [name, catchData])),
|
|
87
|
+
assignment: {},
|
|
88
|
+
dataInputAssociation: { assignment: "assignments" },
|
|
89
|
+
dataOutputAssociation: { assignment: "assignments" },
|
|
90
|
+
ioSpecification: { dataInput: "dataInputs", dataOutput: "dataOutputs", inputSet: "inputSets", outputSet: "outputSets" },
|
|
91
|
+
};
|
|
92
|
+
export const CONTAINS = Object.fromEntries([...new Set([...Object.keys(CONTAINMENT), ...Object.keys(dataContainment)])].map((name) => [
|
|
93
|
+
name,
|
|
94
|
+
{ ...CONTAINMENT[name], ...dataContainment[name] },
|
|
95
|
+
]));
|
|
96
|
+
export const EVENT_DEFINITION_ROOTS = Object.fromEntries(Object.keys(CONTAINMENT.startEvent).map((name) => [ELEMENT_MAPPINGS[name].type, name]));
|
|
97
|
+
export const DATA_ROOT_ELEMENTS = { DataStore: "dataStore" };
|
|
98
|
+
const DATA_CHILD_ORDER = [
|
|
99
|
+
"incoming",
|
|
100
|
+
"outgoing",
|
|
101
|
+
"ioSpecification",
|
|
102
|
+
"dataInput",
|
|
103
|
+
"dataOutput",
|
|
104
|
+
"dataInputAssociation",
|
|
105
|
+
"dataOutputAssociation",
|
|
106
|
+
"inputSet",
|
|
107
|
+
"outputSet",
|
|
108
|
+
"partitionElement",
|
|
109
|
+
"source",
|
|
110
|
+
"target",
|
|
111
|
+
"sourceRef",
|
|
112
|
+
"targetRef",
|
|
113
|
+
"transformation",
|
|
114
|
+
"assignment",
|
|
115
|
+
];
|
|
116
|
+
export const childRank = (key) => {
|
|
117
|
+
if (key.startsWith("@_"))
|
|
118
|
+
return -1;
|
|
119
|
+
if (key === "extensionElements")
|
|
120
|
+
return -0.5;
|
|
121
|
+
if (key === "eventDefinitionRef")
|
|
122
|
+
return DATA_CHILD_ORDER.length + 0.5;
|
|
123
|
+
if (CONDITION_ELEMENTS.includes(key))
|
|
124
|
+
return DATA_CHILD_ORDER.length + 1;
|
|
125
|
+
const index = DATA_CHILD_ORDER.indexOf(key);
|
|
126
|
+
return index === -1 ? DATA_CHILD_ORDER.length : index;
|
|
127
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Extensions } from "./extensions.ts";
|
|
2
|
+
import { type ExportWarning, type Json, type XmlNode } from "./element.ts";
|
|
3
|
+
export declare const DIAGRAM_NAMESPACES: Record<string, string>;
|
|
4
|
+
export declare const DIAGRAM_EXPORT: Record<string, {
|
|
5
|
+
attributes: string[];
|
|
6
|
+
children: string[];
|
|
7
|
+
}>;
|
|
8
|
+
export declare const exportDiagram: (node: Json, location: string, warnings: ExportWarning[], extensions: Extensions) => XmlNode;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { DC_NAMESPACE, DD_NAMESPACE, DI_NAMESPACE } from "../convert/mapping.js";
|
|
2
|
+
import { isObject, unsupported } from "./element.js";
|
|
3
|
+
export const DIAGRAM_NAMESPACES = {
|
|
4
|
+
"@_xmlns:bpmndi": DI_NAMESPACE,
|
|
5
|
+
"@_xmlns:dc": DC_NAMESPACE,
|
|
6
|
+
"@_xmlns:di": DD_NAMESPACE,
|
|
7
|
+
};
|
|
8
|
+
export const DIAGRAM_EXPORT = {
|
|
9
|
+
BPMNDiagram: { attributes: ["id", "name", "resolution"], children: ["plane"] },
|
|
10
|
+
BPMNPlane: { attributes: ["id", "bpmnElement"], children: ["planeElements"] },
|
|
11
|
+
BPMNShape: {
|
|
12
|
+
attributes: ["id", "bpmnElement", "isExpanded", "isHorizontal", "isMarkerVisible", "isMessageVisible"],
|
|
13
|
+
children: ["bounds", "label"],
|
|
14
|
+
},
|
|
15
|
+
BPMNEdge: { attributes: ["id", "bpmnElement", "sourceElement", "targetElement", "messageVisibleKind"], children: ["waypoints", "label"] },
|
|
16
|
+
BPMNLabel: { attributes: [], children: ["bounds"] },
|
|
17
|
+
Bounds: { attributes: ["x", "y", "width", "height"], children: [] },
|
|
18
|
+
waypoint: { attributes: ["x", "y"], children: [] },
|
|
19
|
+
};
|
|
20
|
+
const text = (value) => String(value);
|
|
21
|
+
const attributes = (node, names, handled) => {
|
|
22
|
+
const result = {};
|
|
23
|
+
for (const name of names) {
|
|
24
|
+
handled.add(name);
|
|
25
|
+
if (node[name] !== undefined)
|
|
26
|
+
result[`@_${name}`] = text(node[name]);
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
const report = (node, handled, element, location, warnings, extensions, foreign = true) => {
|
|
31
|
+
for (const key of Object.keys(node).sort()) {
|
|
32
|
+
if (!handled.has(key) && !(foreign && extensions.attribute(key, node[key], element)))
|
|
33
|
+
warnings.push(unsupported("unsupported-property", key, `${location}/${key}`, node));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const base = () => new Set(["type"]);
|
|
37
|
+
const exportBounds = (node, location, warnings, extensions) => {
|
|
38
|
+
const handled = base();
|
|
39
|
+
const element = attributes(node, DIAGRAM_EXPORT.Bounds.attributes, handled);
|
|
40
|
+
report(node, handled, element, location, warnings, extensions, false);
|
|
41
|
+
return element;
|
|
42
|
+
};
|
|
43
|
+
const exportLabel = (node, location, warnings, extensions) => {
|
|
44
|
+
const handled = base();
|
|
45
|
+
const element = {};
|
|
46
|
+
handled.add("bounds");
|
|
47
|
+
if (isObject(node.bounds))
|
|
48
|
+
element["dc:Bounds"] = exportBounds(node.bounds, `${location}/bounds`, warnings, extensions);
|
|
49
|
+
report(node, handled, element, location, warnings, extensions);
|
|
50
|
+
return element;
|
|
51
|
+
};
|
|
52
|
+
const exportPoint = (node, location, warnings, extensions) => {
|
|
53
|
+
const handled = base();
|
|
54
|
+
const element = attributes(node, DIAGRAM_EXPORT.waypoint.attributes, handled);
|
|
55
|
+
report(node, handled, element, location, warnings, extensions, false);
|
|
56
|
+
return element;
|
|
57
|
+
};
|
|
58
|
+
const exportShape = (node, location, warnings, extensions) => {
|
|
59
|
+
const handled = base();
|
|
60
|
+
handled.add("id");
|
|
61
|
+
const element = attributes(node, DIAGRAM_EXPORT.BPMNShape.attributes, handled);
|
|
62
|
+
handled.add("bounds");
|
|
63
|
+
handled.add("label");
|
|
64
|
+
if (isObject(node.bounds))
|
|
65
|
+
element["dc:Bounds"] = exportBounds(node.bounds, `${location}/bounds`, warnings, extensions);
|
|
66
|
+
if (isObject(node.label))
|
|
67
|
+
element["bpmndi:BPMNLabel"] = exportLabel(node.label, `${location}/label`, warnings, extensions);
|
|
68
|
+
report(node, handled, element, location, warnings, extensions);
|
|
69
|
+
return element;
|
|
70
|
+
};
|
|
71
|
+
const exportEdge = (node, location, warnings, extensions) => {
|
|
72
|
+
const handled = base();
|
|
73
|
+
const element = attributes(node, DIAGRAM_EXPORT.BPMNEdge.attributes, handled);
|
|
74
|
+
handled.add("waypoints");
|
|
75
|
+
handled.add("label");
|
|
76
|
+
if (Array.isArray(node.waypoints)) {
|
|
77
|
+
element["di:waypoint"] = node.waypoints.map((waypoint, index) => exportPoint(waypoint, `${location}/waypoints/${index}`, warnings, extensions));
|
|
78
|
+
}
|
|
79
|
+
if (isObject(node.label))
|
|
80
|
+
element["bpmndi:BPMNLabel"] = exportLabel(node.label, `${location}/label`, warnings, extensions);
|
|
81
|
+
report(node, handled, element, location, warnings, extensions);
|
|
82
|
+
return element;
|
|
83
|
+
};
|
|
84
|
+
const exportPlane = (node, location, warnings, extensions) => {
|
|
85
|
+
const handled = base();
|
|
86
|
+
const element = attributes(node, DIAGRAM_EXPORT.BPMNPlane.attributes, handled);
|
|
87
|
+
handled.add("planeElements");
|
|
88
|
+
const members = Array.isArray(node.planeElements) ? node.planeElements : [];
|
|
89
|
+
const children = [];
|
|
90
|
+
members.forEach((member, index) => {
|
|
91
|
+
const memberLocation = `${location}/planeElements/${index}`;
|
|
92
|
+
if (member.type === "BPMNShape")
|
|
93
|
+
children.push({ "bpmndi:BPMNShape": exportShape(member, memberLocation, warnings, extensions) });
|
|
94
|
+
else if (member.type === "BPMNEdge")
|
|
95
|
+
children.push({ "bpmndi:BPMNEdge": exportEdge(member, memberLocation, warnings, extensions) });
|
|
96
|
+
else
|
|
97
|
+
warnings.push(unsupported("unsupported-element", String(member.type), memberLocation, member));
|
|
98
|
+
});
|
|
99
|
+
if (children.length > 0)
|
|
100
|
+
element["#children"] = children;
|
|
101
|
+
report(node, handled, element, location, warnings, extensions);
|
|
102
|
+
return element;
|
|
103
|
+
};
|
|
104
|
+
export const exportDiagram = (node, location, warnings, extensions) => {
|
|
105
|
+
const handled = base();
|
|
106
|
+
const element = attributes(node, DIAGRAM_EXPORT.BPMNDiagram.attributes, handled);
|
|
107
|
+
handled.add("plane");
|
|
108
|
+
if (isObject(node.plane))
|
|
109
|
+
element["bpmndi:BPMNPlane"] = exportPlane(node.plane, `${location}/plane`, warnings, extensions);
|
|
110
|
+
report(node, handled, element, location, warnings, extensions, false);
|
|
111
|
+
return element;
|
|
112
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Extensions } from "./extensions.ts";
|
|
2
|
+
export interface ExportWarning {
|
|
3
|
+
kind: "unsupported";
|
|
4
|
+
code: WarningCode;
|
|
5
|
+
construct: string;
|
|
6
|
+
location: string;
|
|
7
|
+
node?: string;
|
|
8
|
+
message?: string;
|
|
9
|
+
}
|
|
10
|
+
export type WarningCode = "unsupported-root" | "unsupported-element" | "unsupported-property";
|
|
11
|
+
export type Json = Record<string, any>;
|
|
12
|
+
export type XmlNode = Record<string, any>;
|
|
13
|
+
export declare const isObject: (value: unknown) => value is Json;
|
|
14
|
+
export declare const unsupported: (code: WarningCode, construct: string, location: string, owner?: Json) => ExportWarning;
|
|
15
|
+
export declare const SUPPORTED_ELEMENTS: Record<string, string[]>;
|
|
16
|
+
export declare const elementName: (type: unknown) => string | undefined;
|
|
17
|
+
export declare class ExportContext {
|
|
18
|
+
readonly warnings: ExportWarning[];
|
|
19
|
+
readonly roots: Record<string, XmlNode[]>;
|
|
20
|
+
private readonly usedIds;
|
|
21
|
+
private readonly references;
|
|
22
|
+
readonly extensions: Extensions;
|
|
23
|
+
constructor(usedIds: Set<string>, extensions: Extensions);
|
|
24
|
+
reference(root: string, attribute: string, value: string): string;
|
|
25
|
+
}
|
|
26
|
+
export declare const collectIds: (value: unknown, ids?: Set<string>) => Set<string>;
|
|
27
|
+
export declare const exportElement: (name: string, node: Json, location: string, context: ExportContext) => XmlNode;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { CONTAINMENT } from "../convert/mapping.js";
|
|
2
|
+
import { CATCH_EVENTS, childRank, CONTAINS, EXPRESSION_ELEMENTS, MAPPINGS, THROW_EVENTS } from "./data.js";
|
|
3
|
+
export const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
export const unsupported = (code, construct, location, owner) => ({
|
|
5
|
+
kind: "unsupported",
|
|
6
|
+
code,
|
|
7
|
+
construct,
|
|
8
|
+
location,
|
|
9
|
+
...(typeof owner?.id === "string" ? { node: owner.id } : {}),
|
|
10
|
+
});
|
|
11
|
+
const SUB_PROCESSES = ["subProcess", "adHocSubProcess", "transaction"];
|
|
12
|
+
const EXCLUDED_FLOW_ELEMENTS = [...SUB_PROCESSES, "laneSet"];
|
|
13
|
+
const PROPERTY_ORDER = ["laneSets"];
|
|
14
|
+
const FLOW_ELEMENTS = Object.keys(CONTAINS.process).filter((name) => !EXCLUDED_FLOW_ELEMENTS.includes(name));
|
|
15
|
+
const EVENT_DEFINITIONS = Object.keys(CONTAINMENT.startEvent);
|
|
16
|
+
const EVENTS = ["startEvent", "endEvent", "intermediateCatchEvent", "intermediateThrowEvent", "boundaryEvent"];
|
|
17
|
+
const ASSOCIATIONS = ["dataInputAssociation", "dataOutputAssociation"];
|
|
18
|
+
const NON_FLOW_NODES = ["sequenceFlow", "association", "laneSet", "dataObject", "dataObjectReference", "dataStoreReference"];
|
|
19
|
+
const FLOW_NODES = [...FLOW_ELEMENTS, ...SUB_PROCESSES].filter((name) => !NON_FLOW_NODES.includes(name));
|
|
20
|
+
const CONTAINER_ELEMENTS = [...FLOW_ELEMENTS, ...SUB_PROCESSES, "laneSet"];
|
|
21
|
+
const ACTIVITY_ELEMENTS = ["task", "businessRuleTask", "manualTask", "receiveTask", "sendTask", "scriptTask", "serviceTask", "userTask"];
|
|
22
|
+
export const SUPPORTED_ELEMENTS = {
|
|
23
|
+
process: CONTAINER_ELEMENTS,
|
|
24
|
+
...Object.fromEntries(SUB_PROCESSES.map((name) => [name, [...CONTAINER_ELEMENTS, ...ASSOCIATIONS]])),
|
|
25
|
+
...Object.fromEntries(ACTIVITY_ELEMENTS.map((name) => [name, ASSOCIATIONS])),
|
|
26
|
+
dataInputAssociation: ["assignment"],
|
|
27
|
+
dataOutputAssociation: ["assignment"],
|
|
28
|
+
ioSpecification: ["dataInput", "dataOutput", "inputSet", "outputSet"],
|
|
29
|
+
laneSet: ["lane"],
|
|
30
|
+
childLaneSet: ["lane"],
|
|
31
|
+
collaboration: ["participant", "messageFlow"],
|
|
32
|
+
...Object.fromEntries(EVENTS.map((name) => [name, EVENT_DEFINITIONS])),
|
|
33
|
+
...Object.fromEntries(THROW_EVENTS.map((name) => [name, [...EVENT_DEFINITIONS, "dataInput", "dataInputAssociation", "inputSet"]])),
|
|
34
|
+
...Object.fromEntries(CATCH_EVENTS.map((name) => [name, [...EVENT_DEFINITIONS, "dataOutput", "dataOutputAssociation", "outputSet"]])),
|
|
35
|
+
};
|
|
36
|
+
export const elementName = (type) => {
|
|
37
|
+
if (typeof type !== "string" || type === "")
|
|
38
|
+
return undefined;
|
|
39
|
+
const name = type[0].toLowerCase() + type.slice(1);
|
|
40
|
+
return MAPPINGS[name]?.type === type ? name : undefined;
|
|
41
|
+
};
|
|
42
|
+
export class ExportContext {
|
|
43
|
+
warnings = [];
|
|
44
|
+
roots = {};
|
|
45
|
+
usedIds;
|
|
46
|
+
references = new Map();
|
|
47
|
+
extensions;
|
|
48
|
+
constructor(usedIds, extensions) {
|
|
49
|
+
this.usedIds = usedIds;
|
|
50
|
+
this.extensions = extensions;
|
|
51
|
+
}
|
|
52
|
+
reference(root, attribute, value) {
|
|
53
|
+
const key = `${root}\u0000${value}`;
|
|
54
|
+
const known = this.references.get(key);
|
|
55
|
+
if (known !== undefined)
|
|
56
|
+
return known;
|
|
57
|
+
let index = this.references.size + 1;
|
|
58
|
+
let id = `${root[0].toUpperCase()}${root.slice(1)}_${index}`;
|
|
59
|
+
while (this.usedIds.has(id))
|
|
60
|
+
id = `${root[0].toUpperCase()}${root.slice(1)}_${++index}`;
|
|
61
|
+
this.usedIds.add(id);
|
|
62
|
+
this.references.set(key, id);
|
|
63
|
+
(this.roots[root] ??= []).push({ "@_id": id, [`@_${attribute}`]: value });
|
|
64
|
+
return id;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export const collectIds = (value, ids = new Set()) => {
|
|
68
|
+
if (Array.isArray(value))
|
|
69
|
+
value.forEach((item) => collectIds(item, ids));
|
|
70
|
+
else if (isObject(value)) {
|
|
71
|
+
if (typeof value.id === "string")
|
|
72
|
+
ids.add(value.id);
|
|
73
|
+
Object.values(value).forEach((item) => collectIds(item, ids));
|
|
74
|
+
}
|
|
75
|
+
return ids;
|
|
76
|
+
};
|
|
77
|
+
const connectionsOf = (members) => {
|
|
78
|
+
const connections = new Map();
|
|
79
|
+
const entry = (id) => connections.get(id) ?? connections.set(id, { incoming: [], outgoing: [] }).get(id);
|
|
80
|
+
for (const member of Array.isArray(members) ? members : []) {
|
|
81
|
+
if (!isObject(member) || member.type !== "SequenceFlow" || typeof member.id !== "string")
|
|
82
|
+
continue;
|
|
83
|
+
if (typeof member.sourceRef === "string")
|
|
84
|
+
entry(member.sourceRef).outgoing.push(member.id);
|
|
85
|
+
if (typeof member.targetRef === "string")
|
|
86
|
+
entry(member.targetRef).incoming.push(member.id);
|
|
87
|
+
}
|
|
88
|
+
return connections;
|
|
89
|
+
};
|
|
90
|
+
const ordered = (element) => Object.fromEntries(Object.entries(element).sort(([a], [b]) => childRank(a) - childRank(b)));
|
|
91
|
+
const toText = (value) => String(value);
|
|
92
|
+
const exportPartitionElement = (node, location, parent, context) => {
|
|
93
|
+
const name = elementName(node.type);
|
|
94
|
+
if (name === undefined) {
|
|
95
|
+
context.warnings.push(unsupported("unsupported-element", String(node.type), location, node));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
parent.partitionElement = { ...exportElement(name, node, location, context), "@_xsi:type": `t${node.type}` };
|
|
99
|
+
};
|
|
100
|
+
export const exportElement = (name, node, location, context) => {
|
|
101
|
+
const mapping = MAPPINGS[name];
|
|
102
|
+
const element = {};
|
|
103
|
+
const handled = new Set(["id", "type", "@context"]);
|
|
104
|
+
for (const [attribute, term] of Object.entries(mapping.attributes)) {
|
|
105
|
+
handled.add(term);
|
|
106
|
+
if (node[term] !== undefined)
|
|
107
|
+
element[`@_${attribute}`] = (mapping.hashPrefixed?.includes(term) ? "##" : "") + toText(node[term]);
|
|
108
|
+
}
|
|
109
|
+
for (const lookup of mapping.lookups ?? []) {
|
|
110
|
+
handled.add(lookup.term);
|
|
111
|
+
if (node[lookup.term] !== undefined && element[`@_${lookup.attribute}`] === undefined) {
|
|
112
|
+
element[`@_${lookup.attribute}`] = context.reference(lookup.root, lookup.from, toText(node[lookup.term]));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
for (const [child, term] of Object.entries(mapping.textChildren ?? {})) {
|
|
116
|
+
handled.add(term);
|
|
117
|
+
if (node[term] !== undefined)
|
|
118
|
+
element[child] = toText(node[term]);
|
|
119
|
+
}
|
|
120
|
+
for (const [child, term] of Object.entries(mapping.textLists ?? {})) {
|
|
121
|
+
handled.add(term);
|
|
122
|
+
if (Array.isArray(node[term]))
|
|
123
|
+
element[child] = node[term].map(toText);
|
|
124
|
+
else if (node[term] !== undefined)
|
|
125
|
+
element[child] = [toText(node[term])];
|
|
126
|
+
}
|
|
127
|
+
if (mapping.bodyTerm !== undefined) {
|
|
128
|
+
handled.add(mapping.bodyTerm);
|
|
129
|
+
if (node[mapping.bodyTerm] !== undefined)
|
|
130
|
+
element["#text"] = toText(node[mapping.bodyTerm]);
|
|
131
|
+
}
|
|
132
|
+
if (EXPRESSION_ELEMENTS.includes(name)) {
|
|
133
|
+
element["@_xsi:type"] = "tFormalExpression";
|
|
134
|
+
}
|
|
135
|
+
if (name === "conditionalEventDefinition" && !isObject(node.condition))
|
|
136
|
+
element.condition = { "@_xsi:type": "tFormalExpression" };
|
|
137
|
+
for (const [child, term] of Object.entries(mapping.singles ?? {})) {
|
|
138
|
+
handled.add(term);
|
|
139
|
+
if (!isObject(node[term]))
|
|
140
|
+
continue;
|
|
141
|
+
if (child === "partitionElement")
|
|
142
|
+
exportPartitionElement(node[term], `${location}/${term}`, element, context);
|
|
143
|
+
else
|
|
144
|
+
element[child] = exportElement(child, node[term], `${location}/${term}`, context);
|
|
145
|
+
}
|
|
146
|
+
const connections = name === "process" || SUB_PROCESSES.includes(name) ? connectionsOf(node.flowElements) : new Map();
|
|
147
|
+
const allowed = SUPPORTED_ELEMENTS[name] ?? [];
|
|
148
|
+
const properties = [...new Set(Object.values(CONTAINS[name] ?? {}))].sort((a, b) => Number(!PROPERTY_ORDER.includes(a)) - Number(!PROPERTY_ORDER.includes(b)));
|
|
149
|
+
for (const property of properties) {
|
|
150
|
+
handled.add(property);
|
|
151
|
+
const members = Array.isArray(node[property]) ? node[property] : [];
|
|
152
|
+
members.forEach((member, index) => {
|
|
153
|
+
const memberLocation = `${location}/${property}/${index}`;
|
|
154
|
+
const memberName = elementName(member.type);
|
|
155
|
+
if (memberName === undefined || !allowed.includes(memberName) || CONTAINS[name][memberName] !== property) {
|
|
156
|
+
context.warnings.push(unsupported("unsupported-element", String(member.type), memberLocation, member));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
let exported = exportElement(memberName, member, memberLocation, context);
|
|
160
|
+
const linked = FLOW_NODES.includes(memberName) && typeof member.id === "string" ? connections.get(member.id) : undefined;
|
|
161
|
+
if (linked?.incoming.length)
|
|
162
|
+
exported.incoming = linked.incoming;
|
|
163
|
+
if (linked?.outgoing.length)
|
|
164
|
+
exported.outgoing = linked.outgoing;
|
|
165
|
+
if (linked)
|
|
166
|
+
exported = ordered(exported);
|
|
167
|
+
(element[memberName] ??= []).push(exported);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
for (const key of Object.keys(node).sort()) {
|
|
171
|
+
if (!handled.has(key) && !context.extensions.apply(key, node[key], element))
|
|
172
|
+
context.warnings.push(unsupported("unsupported-property", key, `${location}/${key}`, node));
|
|
173
|
+
}
|
|
174
|
+
return ordered(element);
|
|
175
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ExportWarning } from "./element.ts";
|
|
2
|
+
export type { ExportWarning };
|
|
3
|
+
export interface ExportResult {
|
|
4
|
+
xml: string;
|
|
5
|
+
warnings: ExportWarning[];
|
|
6
|
+
}
|
|
7
|
+
export interface ExportOptions {
|
|
8
|
+
documentUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ExportError {
|
|
11
|
+
code: "not-an-object" | "invalid-context" | "invalid-document" | "unreadable-input" | "invalid-json" | "cannot-write" | "strict-mode";
|
|
12
|
+
location: string;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class ExportInputError extends Error {
|
|
16
|
+
readonly findings: ExportError[];
|
|
17
|
+
readonly errors: string[];
|
|
18
|
+
constructor(findings: ExportError[]);
|
|
19
|
+
}
|
|
20
|
+
export declare const schemaFinding: (message: string) => ExportError;
|
|
21
|
+
export declare const ROOT_ELEMENTS: Record<string, string>;
|
|
22
|
+
export declare const exportDocument: (input: unknown, options?: ExportOptions) => Promise<ExportResult>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { XMLBuilder } from "fast-xml-parser";
|
|
2
|
+
import { compileSchema, validateWithSchema } from "../schema-validate.js";
|
|
3
|
+
import { defaultBase } from "../convert/convert.js";
|
|
4
|
+
import { MODEL_NAMESPACE, XSI_NAMESPACE } from "../convert/mapping.js";
|
|
5
|
+
import { DATA_ROOT_ELEMENTS, EVENT_DEFINITION_ROOTS } from "./data.js";
|
|
6
|
+
import { Extensions } from "./extensions.js";
|
|
7
|
+
import { normalize } from "./normalize.js";
|
|
8
|
+
import { DIAGRAM_NAMESPACES, exportDiagram } from "./diagram.js";
|
|
9
|
+
import { collectIds, exportElement, ExportContext, isObject, unsupported } from "./element.js";
|
|
10
|
+
const describe = (error) => `${error.location} ${error.message}`;
|
|
11
|
+
export class ExportInputError extends Error {
|
|
12
|
+
findings;
|
|
13
|
+
errors;
|
|
14
|
+
constructor(findings) {
|
|
15
|
+
const errors = findings.map(describe);
|
|
16
|
+
super(`invalid BPMN-LD document: ${errors[0]}`);
|
|
17
|
+
this.name = "ExportInputError";
|
|
18
|
+
this.findings = findings;
|
|
19
|
+
this.errors = errors;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export const schemaFinding = (message) => {
|
|
23
|
+
const split = message.indexOf(" ");
|
|
24
|
+
return { code: "invalid-document", location: message.slice(0, split), message: message.slice(split + 1) };
|
|
25
|
+
};
|
|
26
|
+
const absolute = (id, base) => {
|
|
27
|
+
try {
|
|
28
|
+
return new URL(id, base).href;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export const ROOT_ELEMENTS = { Process: "process", Collaboration: "collaboration", Message: "message", Signal: "signal", Error: "error", Escalation: "escalation", ...EVENT_DEFINITION_ROOTS, ...DATA_ROOT_ELEMENTS };
|
|
35
|
+
const ESCAPES = [
|
|
36
|
+
[/\r/g, "\uE00D", " "],
|
|
37
|
+
[/\n/g, "\uE00A", " "],
|
|
38
|
+
[/\t/g, "\uE009", "	"],
|
|
39
|
+
];
|
|
40
|
+
const protect = (value, attribute) => ESCAPES.slice(0, attribute ? 3 : 1).reduce((text, [pattern, sentinel]) => text.replace(pattern, sentinel), value);
|
|
41
|
+
const restore = (xml) => ESCAPES.reduce((text, [, sentinel, entity]) => text.replaceAll(sentinel, entity), xml);
|
|
42
|
+
const toOrdered = (tag, value) => {
|
|
43
|
+
if (!isObject(value))
|
|
44
|
+
return [{ [tag]: [{ "#text": protect(String(value), false) }] }];
|
|
45
|
+
const attributes = {};
|
|
46
|
+
const children = [];
|
|
47
|
+
for (const [key, member] of Object.entries(value)) {
|
|
48
|
+
if (key.startsWith("@_"))
|
|
49
|
+
attributes[key] = protect(String(member), true);
|
|
50
|
+
else if (key === "#text")
|
|
51
|
+
children.push({ "#text": protect(String(member), false) });
|
|
52
|
+
else if (key === "#children") {
|
|
53
|
+
for (const child of member) {
|
|
54
|
+
const [[childTag, childValue]] = Object.entries(child);
|
|
55
|
+
children.push(...toOrdered(childTag, childValue));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (Array.isArray(member))
|
|
59
|
+
member.forEach((item) => children.push(...toOrdered(key, item)));
|
|
60
|
+
else
|
|
61
|
+
children.push(...toOrdered(key, member));
|
|
62
|
+
}
|
|
63
|
+
return [Object.keys(attributes).length > 0 ? { [tag]: children, ":@": attributes } : { [tag]: children }];
|
|
64
|
+
};
|
|
65
|
+
let compiled;
|
|
66
|
+
const schema = () => (compiled ??= compileSchema());
|
|
67
|
+
const unique = (errors) => [...new Set(errors)];
|
|
68
|
+
const targetNamespace = (document) => {
|
|
69
|
+
const context = Array.isArray(document["@context"]) ? document["@context"] : [document["@context"]];
|
|
70
|
+
const base = context.find((entry) => isObject(entry) && typeof entry["@base"] === "string");
|
|
71
|
+
return base?.["@base"] ?? defaultBase();
|
|
72
|
+
};
|
|
73
|
+
export const exportDocument = async (input, options = {}) => {
|
|
74
|
+
if (!isObject(input))
|
|
75
|
+
throw new ExportInputError([{ code: "not-an-object", location: "/", message: "document must be a JSON object" }]);
|
|
76
|
+
let document;
|
|
77
|
+
try {
|
|
78
|
+
document = await normalize(input, options.documentUrl);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw new ExportInputError([{ code: "invalid-context", location: "/@context", message: error.message }]);
|
|
82
|
+
}
|
|
83
|
+
const errors = unique(validateWithSchema(document, schema()));
|
|
84
|
+
if (errors.length > 0)
|
|
85
|
+
throw new ExportInputError(errors.map(schemaFinding));
|
|
86
|
+
const context = new ExportContext(collectIds(document), new Extensions(document["@context"], targetNamespace(document)));
|
|
87
|
+
const { warnings } = context;
|
|
88
|
+
const graph = Array.isArray(document["@graph"]) ? document["@graph"] : [document];
|
|
89
|
+
const prefix = Array.isArray(document["@graph"]) ? "/@graph" : "";
|
|
90
|
+
const definitions = {
|
|
91
|
+
"@_xmlns": MODEL_NAMESPACE,
|
|
92
|
+
"@_xmlns:xsi": XSI_NAMESPACE,
|
|
93
|
+
"@_id": "Definitions_1",
|
|
94
|
+
"@_targetNamespace": targetNamespace(document),
|
|
95
|
+
};
|
|
96
|
+
graph.forEach((root, index) => {
|
|
97
|
+
const location = prefix === "" ? "" : `${prefix}/${index}`;
|
|
98
|
+
if (root.type === "BPMNDiagram") {
|
|
99
|
+
(definitions["bpmndi:BPMNDiagram"] ??= []).push(exportDiagram(root, location, warnings, context.extensions));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const name = ROOT_ELEMENTS[root.type];
|
|
103
|
+
if (name === undefined) {
|
|
104
|
+
warnings.push(unsupported("unsupported-root", root.type, location || "/", root));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
(definitions[name] ??= []).push(exportElement(name, root, location, context));
|
|
108
|
+
});
|
|
109
|
+
const { process: processes, collaboration: collaborations, "bpmndi:BPMNDiagram": diagrams, ...attributes } = definitions;
|
|
110
|
+
const generated = Object.fromEntries(Object.entries(context.roots).map(([name, nodes]) => [name, [...(attributes[name] ?? []), ...nodes]]));
|
|
111
|
+
const ordered = {
|
|
112
|
+
...attributes,
|
|
113
|
+
...Object.fromEntries([...context.extensions.namespaces].map(([prefix, namespace]) => [`@_xmlns:${prefix}`, namespace])),
|
|
114
|
+
...(diagrams ? DIAGRAM_NAMESPACES : {}),
|
|
115
|
+
...generated,
|
|
116
|
+
...(collaborations ? { collaboration: collaborations } : {}),
|
|
117
|
+
...(processes ? { process: processes } : {}),
|
|
118
|
+
...(diagrams ? { "bpmndi:BPMNDiagram": diagrams } : {}),
|
|
119
|
+
};
|
|
120
|
+
const builder = new XMLBuilder({ preserveOrder: true, ignoreAttributes: false, attributeNamePrefix: "@_", attributesGroupName: ":@", format: true, suppressEmptyNode: true, suppressBooleanAttributes: false });
|
|
121
|
+
const base = targetNamespace(document);
|
|
122
|
+
const located = warnings.map((warning) => (warning.node === undefined ? warning : { ...warning, node: absolute(warning.node, base) }));
|
|
123
|
+
return { xml: `<?xml version="1.0" encoding="UTF-8"?>\n${restore(String(builder.build(toOrdered("definitions", ordered)))).trimStart()}`, warnings: located };
|
|
124
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type XmlNode } from "./element.ts";
|
|
2
|
+
export declare class Extensions {
|
|
3
|
+
readonly namespaces: Map<string, string>;
|
|
4
|
+
private readonly terms;
|
|
5
|
+
private readonly references;
|
|
6
|
+
private readonly base;
|
|
7
|
+
private readonly byNamespace;
|
|
8
|
+
private generated;
|
|
9
|
+
constructor(context: unknown, base: string);
|
|
10
|
+
private expand;
|
|
11
|
+
private prefixFor;
|
|
12
|
+
qualify(key: string): string | undefined;
|
|
13
|
+
private content;
|
|
14
|
+
private resolve;
|
|
15
|
+
private scalar;
|
|
16
|
+
attribute(key: string, value: unknown, element: XmlNode): boolean;
|
|
17
|
+
apply(key: string, value: unknown, element: XmlNode): boolean;
|
|
18
|
+
}
|