@stocksharp/diagram 0.2.3 → 0.3.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/dist/esm/canvas-renderer.js +28 -22
- package/dist/esm/canvas-renderer.js.map +1 -1
- package/dist/esm/core/action-registry.js +24 -0
- package/dist/esm/core/action-registry.js.map +1 -1
- package/dist/esm/core/document.js +85 -28
- package/dist/esm/core/document.js.map +1 -1
- package/dist/esm/core/json.js +17 -0
- package/dist/esm/core/json.js.map +1 -0
- package/dist/esm/core/model.js +4 -0
- package/dist/esm/core/model.js.map +1 -1
- package/dist/esm/core/state.js +16 -2
- package/dist/esm/core/state.js.map +1 -1
- package/dist/esm/diagram/catalog.js +17 -5
- package/dist/esm/diagram/catalog.js.map +1 -1
- package/dist/esm/diagram/event-emitter.js +10 -0
- package/dist/esm/diagram/event-emitter.js.map +1 -1
- package/dist/esm/diagram/stocksharp-diagram.js +58 -56
- package/dist/esm/diagram/stocksharp-diagram.js.map +1 -1
- package/dist/esm/diagram/types.js +2 -1
- package/dist/esm/diagram/types.js.map +1 -1
- package/dist/esm/embed.js +121 -38
- package/dist/esm/embed.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/ssdiagram.js +297 -145
- package/dist/ssdiagram.js.map +4 -4
- package/dist/types/canvas-renderer.d.ts +3 -5
- package/dist/types/canvas-renderer.d.ts.map +1 -1
- package/dist/types/core/action-registry.d.ts +7 -0
- package/dist/types/core/action-registry.d.ts.map +1 -1
- package/dist/types/core/document.d.ts.map +1 -1
- package/dist/types/core/json.d.ts +11 -0
- package/dist/types/core/json.d.ts.map +1 -0
- package/dist/types/core/model.d.ts +10 -1
- package/dist/types/core/model.d.ts.map +1 -1
- package/dist/types/core/state.d.ts +24 -1
- package/dist/types/core/state.d.ts.map +1 -1
- package/dist/types/diagram/api.d.ts +6 -6
- package/dist/types/diagram/api.d.ts.map +1 -1
- package/dist/types/diagram/catalog.d.ts +2 -1
- package/dist/types/diagram/catalog.d.ts.map +1 -1
- package/dist/types/diagram/event-emitter.d.ts +6 -1
- package/dist/types/diagram/event-emitter.d.ts.map +1 -1
- package/dist/types/diagram/palette.d.ts +1 -1
- package/dist/types/diagram/palette.d.ts.map +1 -1
- package/dist/types/diagram/stocksharp-diagram.d.ts +29 -22
- package/dist/types/diagram/stocksharp-diagram.d.ts.map +1 -1
- package/dist/types/diagram/types.d.ts +4 -4
- package/dist/types/diagram/types.d.ts.map +1 -1
- package/dist/types/embed.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/canvas-renderer.ts +26 -24
- package/src/core/action-registry.ts +25 -0
- package/src/core/document.ts +91 -31
- package/src/core/json.ts +16 -0
- package/src/core/model.ts +14 -1
- package/src/core/state.ts +41 -3
- package/src/diagram/api.ts +6 -5
- package/src/diagram/catalog.ts +18 -6
- package/src/diagram/event-emitter.ts +12 -1
- package/src/diagram/palette.ts +1 -1
- package/src/diagram/stocksharp-diagram.ts +79 -76
- package/src/diagram/types.ts +6 -5
- package/src/embed.ts +140 -39
- package/src/index.ts +4 -0
package/dist/ssdiagram.js
CHANGED
|
@@ -37,6 +37,7 @@ var SSDiagram = (() => {
|
|
|
37
37
|
StockSharpDiagram: () => StockSharpDiagram,
|
|
38
38
|
StockSharpPalette: () => StockSharpPalette,
|
|
39
39
|
cloneDiagramDocument: () => cloneDiagramDocument,
|
|
40
|
+
cloneDiagramNodeErrors: () => cloneDiagramNodeErrors,
|
|
40
41
|
cloneDiagramRuntimeState: () => cloneDiagramRuntimeState,
|
|
41
42
|
createDiagramDocument: () => createDiagramDocument,
|
|
42
43
|
createDiagramNodeRuntimeState: () => createDiagramNodeRuntimeState,
|
|
@@ -58,7 +59,19 @@ var SSDiagram = (() => {
|
|
|
58
59
|
serializeDiagramViewState: () => serializeDiagramViewState
|
|
59
60
|
});
|
|
60
61
|
|
|
62
|
+
// src/core/json.ts
|
|
63
|
+
function setJsonKey(target, key, value) {
|
|
64
|
+
if (key === "__proto__") {
|
|
65
|
+
Object.defineProperty(target, key, { value, enumerable: true, writable: true, configurable: true });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
target[key] = value;
|
|
69
|
+
}
|
|
70
|
+
|
|
61
71
|
// src/core/model.ts
|
|
72
|
+
function toPortDynamicMode(value) {
|
|
73
|
+
return value === "manual" || value === "onConnect" ? value : "";
|
|
74
|
+
}
|
|
62
75
|
var DIAGRAM_DOCUMENT_VERSION = 1;
|
|
63
76
|
|
|
64
77
|
// src/core/document.ts
|
|
@@ -70,25 +83,29 @@ var SSDiagram = (() => {
|
|
|
70
83
|
}
|
|
71
84
|
};
|
|
72
85
|
function createDiagramDocument(input = {}) {
|
|
73
|
-
const
|
|
86
|
+
const rawNodes = mapElements(input.nodes, "$.nodes");
|
|
87
|
+
const rawLinks = mapElements(input.links, "$.links");
|
|
88
|
+
const nodes = rawNodes.map((node, index) => normalizeNode(node, `$.nodes[${index}]`));
|
|
74
89
|
const usedLinkIds = /* @__PURE__ */ new Set();
|
|
75
|
-
for (let index = 0; index <
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
78
|
-
requireIdentifier(
|
|
90
|
+
for (let index = 0; index < rawLinks.length; index++) {
|
|
91
|
+
const raw = rawLinks[index].id;
|
|
92
|
+
if (raw === void 0) continue;
|
|
93
|
+
const id = requireIdentifier(raw, `$.links[${index}].id`);
|
|
79
94
|
if (usedLinkIds.has(id)) {
|
|
80
95
|
throw new DiagramDocumentError(`duplicate link id "${id}"`, `$.links[${index}].id`);
|
|
81
96
|
}
|
|
82
97
|
usedLinkIds.add(id);
|
|
83
98
|
}
|
|
84
99
|
let sequence = 1;
|
|
85
|
-
const links =
|
|
100
|
+
const links = rawLinks.map((link, index) => {
|
|
86
101
|
let id = link.id;
|
|
87
102
|
if (id === void 0) {
|
|
103
|
+
let generated;
|
|
88
104
|
do
|
|
89
|
-
|
|
90
|
-
while (usedLinkIds.has(
|
|
91
|
-
usedLinkIds.add(
|
|
105
|
+
generated = `link_${sequence++}`;
|
|
106
|
+
while (usedLinkIds.has(generated));
|
|
107
|
+
usedLinkIds.add(generated);
|
|
108
|
+
id = generated;
|
|
92
109
|
}
|
|
93
110
|
return normalizeLink({ ...link, id }, `$.links[${index}]`);
|
|
94
111
|
});
|
|
@@ -117,7 +134,7 @@ var SSDiagram = (() => {
|
|
|
117
134
|
throw new DiagramDocumentError(reason);
|
|
118
135
|
}
|
|
119
136
|
}
|
|
120
|
-
const root =
|
|
137
|
+
const root = requireStructure(value, "$");
|
|
121
138
|
const version = requireNumber(root.version, "$.version");
|
|
122
139
|
if (version !== DIAGRAM_DOCUMENT_VERSION) {
|
|
123
140
|
throw new DiagramDocumentError(`unsupported document version ${version}`, "$.version");
|
|
@@ -131,7 +148,8 @@ var SSDiagram = (() => {
|
|
|
131
148
|
validateDocument(document2);
|
|
132
149
|
return document2;
|
|
133
150
|
}
|
|
134
|
-
function normalizeNode(
|
|
151
|
+
function normalizeNode(value, path) {
|
|
152
|
+
const input = requireStructure(value, path);
|
|
135
153
|
const id = requireIdentifier(input.id, `${path}.id`);
|
|
136
154
|
return {
|
|
137
155
|
id,
|
|
@@ -146,28 +164,30 @@ var SSDiagram = (() => {
|
|
|
146
164
|
icon: requireString(input.icon ?? "", `${path}.icon`),
|
|
147
165
|
message: requireString(input.message ?? "", `${path}.message`),
|
|
148
166
|
openAction: requireString(input.openAction ?? "", `${path}.openAction`),
|
|
149
|
-
inPorts: (input.inPorts
|
|
150
|
-
outPorts: (input.outPorts
|
|
151
|
-
parameters: (input.parameters
|
|
167
|
+
inPorts: mapElements(input.inPorts, `${path}.inPorts`).map((port, index) => normalizePort(port, `${path}.inPorts[${index}]`)),
|
|
168
|
+
outPorts: mapElements(input.outPorts, `${path}.outPorts`).map((port, index) => normalizePort(port, `${path}.outPorts[${index}]`)),
|
|
169
|
+
parameters: mapElements(input.parameters, `${path}.parameters`).map((parameter, index) => normalizeParameter(parameter, `${path}.parameters[${index}]`)),
|
|
152
170
|
paramValues: cloneStringRecord(input.paramValues ?? {}, `${path}.paramValues`),
|
|
153
171
|
metadata: cloneJsonObject(input.metadata ?? {}, `${path}.metadata`)
|
|
154
172
|
};
|
|
155
173
|
}
|
|
156
|
-
function normalizePort(
|
|
174
|
+
function normalizePort(value, path) {
|
|
175
|
+
const input = requireStructure(value, path);
|
|
157
176
|
return {
|
|
158
177
|
id: requireIdentifier(input.id, `${path}.id`),
|
|
159
178
|
name: requireString(input.name, `${path}.name`),
|
|
160
179
|
description: requireString(input.description ?? "", `${path}.description`),
|
|
161
180
|
type: requireString(input.type ?? "", `${path}.type`),
|
|
162
181
|
maxLinks: requireNonNegativeInteger(input.maxLinks ?? 0, `${path}.maxLinks`),
|
|
163
|
-
availableTypes: (input.availableTypes ?? []).map((type, index) => requireString(type, `${path}.availableTypes[${index}]`)),
|
|
182
|
+
availableTypes: requireArray(input.availableTypes ?? [], `${path}.availableTypes`).map((type, index) => requireString(type, `${path}.availableTypes[${index}]`)),
|
|
164
183
|
isDynamic: requireBoolean(input.isDynamic ?? false, `${path}.isDynamic`),
|
|
165
|
-
dynamicMode:
|
|
184
|
+
dynamicMode: requirePortDynamicMode(input.dynamicMode ?? "", `${path}.dynamicMode`),
|
|
166
185
|
isSibling: requireBoolean(input.isSibling ?? false, `${path}.isSibling`),
|
|
167
186
|
metadata: cloneJsonObject(input.metadata ?? {}, `${path}.metadata`)
|
|
168
187
|
};
|
|
169
188
|
}
|
|
170
|
-
function normalizeParameter(
|
|
189
|
+
function normalizeParameter(value, path) {
|
|
190
|
+
const input = requireStructure(value, path);
|
|
171
191
|
return {
|
|
172
192
|
name: requireIdentifier(input.name, `${path}.name`),
|
|
173
193
|
displayName: requireString(input.displayName, `${path}.displayName`),
|
|
@@ -183,7 +203,8 @@ var SSDiagram = (() => {
|
|
|
183
203
|
editorType: requireString(input.editorType, `${path}.editorType`)
|
|
184
204
|
};
|
|
185
205
|
}
|
|
186
|
-
function normalizeLink(
|
|
206
|
+
function normalizeLink(value, path) {
|
|
207
|
+
const input = requireStructure(value, path);
|
|
187
208
|
return {
|
|
188
209
|
id: requireIdentifier(input.id, `${path}.id`),
|
|
189
210
|
from: normalizeEndpoint(input.from, `${path}.from`),
|
|
@@ -191,14 +212,15 @@ var SSDiagram = (() => {
|
|
|
191
212
|
metadata: cloneJsonObject(input.metadata ?? {}, `${path}.metadata`)
|
|
192
213
|
};
|
|
193
214
|
}
|
|
194
|
-
function normalizeEndpoint(
|
|
215
|
+
function normalizeEndpoint(value, path) {
|
|
216
|
+
const input = requireStructure(value, path);
|
|
195
217
|
return {
|
|
196
218
|
nodeId: requireIdentifier(input.nodeId, `${path}.nodeId`),
|
|
197
219
|
portId: requireIdentifier(input.portId, `${path}.portId`)
|
|
198
220
|
};
|
|
199
221
|
}
|
|
200
222
|
function parseNode(value, path) {
|
|
201
|
-
const node =
|
|
223
|
+
const node = requireStructure(value, path);
|
|
202
224
|
return normalizeNode({
|
|
203
225
|
id: requireString(node.id, `${path}.id`),
|
|
204
226
|
typeId: requireString(node.typeId, `${path}.typeId`),
|
|
@@ -220,7 +242,7 @@ var SSDiagram = (() => {
|
|
|
220
242
|
}, path);
|
|
221
243
|
}
|
|
222
244
|
function parsePort(value, path) {
|
|
223
|
-
const port =
|
|
245
|
+
const port = requireStructure(value, path);
|
|
224
246
|
return normalizePort({
|
|
225
247
|
id: requireString(port.id, `${path}.id`),
|
|
226
248
|
name: requireString(port.name, `${path}.name`),
|
|
@@ -229,13 +251,13 @@ var SSDiagram = (() => {
|
|
|
229
251
|
maxLinks: requireNumber(port.maxLinks, `${path}.maxLinks`),
|
|
230
252
|
availableTypes: requireArray(port.availableTypes, `${path}.availableTypes`).map((type, index) => requireString(type, `${path}.availableTypes[${index}]`)),
|
|
231
253
|
isDynamic: requireBoolean(port.isDynamic, `${path}.isDynamic`),
|
|
232
|
-
dynamicMode:
|
|
254
|
+
dynamicMode: requirePortDynamicMode(port.dynamicMode, `${path}.dynamicMode`),
|
|
233
255
|
isSibling: requireBoolean(port.isSibling, `${path}.isSibling`),
|
|
234
256
|
metadata: cloneJsonObject(port.metadata, `${path}.metadata`)
|
|
235
257
|
}, path);
|
|
236
258
|
}
|
|
237
259
|
function parseParameter(value, path) {
|
|
238
|
-
const parameter =
|
|
260
|
+
const parameter = requireStructure(value, path);
|
|
239
261
|
return normalizeParameter({
|
|
240
262
|
name: requireString(parameter.name, `${path}.name`),
|
|
241
263
|
displayName: requireString(parameter.displayName, `${path}.displayName`),
|
|
@@ -252,7 +274,7 @@ var SSDiagram = (() => {
|
|
|
252
274
|
}, path);
|
|
253
275
|
}
|
|
254
276
|
function parseLink(value, path) {
|
|
255
|
-
const link =
|
|
277
|
+
const link = requireStructure(value, path);
|
|
256
278
|
return normalizeLink({
|
|
257
279
|
id: requireString(link.id, `${path}.id`),
|
|
258
280
|
from: parseEndpoint(link.from, `${path}.from`),
|
|
@@ -261,7 +283,7 @@ var SSDiagram = (() => {
|
|
|
261
283
|
}, path);
|
|
262
284
|
}
|
|
263
285
|
function parseEndpoint(value, path) {
|
|
264
|
-
const endpoint =
|
|
286
|
+
const endpoint = requireStructure(value, path);
|
|
265
287
|
return {
|
|
266
288
|
nodeId: requireIdentifier(endpoint.nodeId, `${path}.nodeId`),
|
|
267
289
|
portId: requireIdentifier(endpoint.portId, `${path}.portId`)
|
|
@@ -309,7 +331,7 @@ var SSDiagram = (() => {
|
|
|
309
331
|
function cloneStringRecord(value, path) {
|
|
310
332
|
const object = requireObject(value, path);
|
|
311
333
|
const result = {};
|
|
312
|
-
for (const [key, item] of Object.entries(object)) result
|
|
334
|
+
for (const [key, item] of Object.entries(object)) setJsonKey(result, key, requireString(item, `${path}.${key}`));
|
|
313
335
|
return result;
|
|
314
336
|
}
|
|
315
337
|
function cloneJsonObject(value, path, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
@@ -319,7 +341,7 @@ var SSDiagram = (() => {
|
|
|
319
341
|
const result = {};
|
|
320
342
|
try {
|
|
321
343
|
for (const [key, item] of Object.entries(object)) {
|
|
322
|
-
result
|
|
344
|
+
setJsonKey(result, key, cloneJsonValue(item, `${path}.${key}`, ancestors));
|
|
323
345
|
}
|
|
324
346
|
} finally {
|
|
325
347
|
ancestors.delete(object);
|
|
@@ -341,6 +363,12 @@ var SSDiagram = (() => {
|
|
|
341
363
|
if (isObject(value)) return cloneJsonObject(value, path, ancestors);
|
|
342
364
|
throw new DiagramDocumentError("expected a JSON value", path);
|
|
343
365
|
}
|
|
366
|
+
function requireStructure(value, path) {
|
|
367
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
368
|
+
throw new DiagramDocumentError("expected an object", path);
|
|
369
|
+
}
|
|
370
|
+
return value;
|
|
371
|
+
}
|
|
344
372
|
function requireObject(value, path) {
|
|
345
373
|
if (!isObject(value)) throw new DiagramDocumentError("expected an object", path);
|
|
346
374
|
return value;
|
|
@@ -350,6 +378,13 @@ var SSDiagram = (() => {
|
|
|
350
378
|
const prototype = Object.getPrototypeOf(value);
|
|
351
379
|
return prototype === Object.prototype || prototype === null;
|
|
352
380
|
}
|
|
381
|
+
function mapElements(value, path) {
|
|
382
|
+
if (value === void 0 || value === null) return [];
|
|
383
|
+
return Array.from(
|
|
384
|
+
requireArray(value, path),
|
|
385
|
+
(element, index) => requireStructure(element, `${path}[${index}]`)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
353
388
|
function requireArray(value, path) {
|
|
354
389
|
if (!Array.isArray(value)) throw new DiagramDocumentError("expected an array", path);
|
|
355
390
|
return value;
|
|
@@ -358,6 +393,10 @@ var SSDiagram = (() => {
|
|
|
358
393
|
if (typeof value !== "string") throw new DiagramDocumentError("expected a string", path);
|
|
359
394
|
return value;
|
|
360
395
|
}
|
|
396
|
+
function requirePortDynamicMode(value, path) {
|
|
397
|
+
const mode = requireString(value, path);
|
|
398
|
+
return toPortDynamicMode(mode);
|
|
399
|
+
}
|
|
361
400
|
function requireIdentifier(value, path) {
|
|
362
401
|
const id = requireString(value, path);
|
|
363
402
|
if (id.trim().length === 0) throw new DiagramDocumentError("identifier cannot be empty", path);
|
|
@@ -399,6 +438,24 @@ var SSDiagram = (() => {
|
|
|
399
438
|
if (this.actions.get(action.id) === action) this.actions.delete(action.id);
|
|
400
439
|
};
|
|
401
440
|
}
|
|
441
|
+
/**
|
|
442
|
+
* Registers one action per id from a table keyed by TId, in key order.
|
|
443
|
+
* Because the table is a total Record, adding a member to TId without adding
|
|
444
|
+
* its action stops compiling instead of producing a command that silently
|
|
445
|
+
* does nothing.
|
|
446
|
+
*/
|
|
447
|
+
registerAll(actions) {
|
|
448
|
+
const ids = Object.keys(actions);
|
|
449
|
+
const disposers = ids.map((id) => {
|
|
450
|
+
const action = actions[id];
|
|
451
|
+
return this.register({
|
|
452
|
+
id,
|
|
453
|
+
canExecute: (context) => action.canExecute(context),
|
|
454
|
+
execute: (context) => action.execute(context)
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
return () => disposers.forEach((dispose) => dispose());
|
|
458
|
+
}
|
|
402
459
|
get(id) {
|
|
403
460
|
return this.actions.get(id) ?? null;
|
|
404
461
|
}
|
|
@@ -554,7 +611,7 @@ var SSDiagram = (() => {
|
|
|
554
611
|
globalError: state.globalError === null ? null : { ...state.globalError },
|
|
555
612
|
nodes: Object.fromEntries(Object.entries(state.nodes).map(([nodeId, node]) => [nodeId, {
|
|
556
613
|
active: node.active,
|
|
557
|
-
|
|
614
|
+
errors: cloneDiagramNodeErrors(node.errors),
|
|
558
615
|
ports: {
|
|
559
616
|
in: Object.fromEntries(Object.entries(node.ports.in).map(([portId, port]) => [portId, { ...port }])),
|
|
560
617
|
out: Object.fromEntries(Object.entries(node.ports.out).map(([portId, port]) => [portId, { ...port }]))
|
|
@@ -611,10 +668,17 @@ var SSDiagram = (() => {
|
|
|
611
668
|
function createDiagramNodeRuntimeState() {
|
|
612
669
|
return {
|
|
613
670
|
active: false,
|
|
614
|
-
|
|
671
|
+
errors: {},
|
|
615
672
|
ports: { in: {}, out: {} }
|
|
616
673
|
};
|
|
617
674
|
}
|
|
675
|
+
function cloneDiagramNodeErrors(errors) {
|
|
676
|
+
const result = {};
|
|
677
|
+
if (errors === void 0 || errors === null) return result;
|
|
678
|
+
if (errors.runtime !== void 0) result.runtime = { ...errors.runtime };
|
|
679
|
+
if (errors.load !== void 0) result.load = { ...errors.load };
|
|
680
|
+
return result;
|
|
681
|
+
}
|
|
618
682
|
|
|
619
683
|
// src/core/view-state.ts
|
|
620
684
|
var DIAGRAM_VIEW_STATE_VERSION = 1;
|
|
@@ -699,7 +763,7 @@ var SSDiagram = (() => {
|
|
|
699
763
|
function copyJsonObject(value) {
|
|
700
764
|
if (value === void 0) return {};
|
|
701
765
|
const result = {};
|
|
702
|
-
for (const [key, item] of Object.entries(value)) result
|
|
766
|
+
for (const [key, item] of Object.entries(value)) setJsonKey(result, key, copyJsonValue(item));
|
|
703
767
|
return result;
|
|
704
768
|
}
|
|
705
769
|
function copyParameters(value) {
|
|
@@ -730,7 +794,7 @@ var SSDiagram = (() => {
|
|
|
730
794
|
this.maxLinks = typeof init.maxLinks === "number" ? init.maxLinks : 0;
|
|
731
795
|
this.availableTypes = [...init.availableTypes ?? []];
|
|
732
796
|
this.isDynamic = init.isDynamic ?? false;
|
|
733
|
-
this.dynamicMode = init.dynamicMode
|
|
797
|
+
this.dynamicMode = toPortDynamicMode(init.dynamicMode);
|
|
734
798
|
this.isSibling = init.isSibling ?? false;
|
|
735
799
|
this.metadata = copyJsonObject(init.metadata);
|
|
736
800
|
}
|
|
@@ -897,8 +961,6 @@ var SSDiagram = (() => {
|
|
|
897
961
|
this.dragStart = [];
|
|
898
962
|
// group-drag origin
|
|
899
963
|
this.dragAnchor = { wx: 0, wy: 0 };
|
|
900
|
-
this.dragDX = 0;
|
|
901
|
-
this.dragDY = 0;
|
|
902
964
|
this.panning = false;
|
|
903
965
|
this.panX = 0;
|
|
904
966
|
this.panY = 0;
|
|
@@ -1482,7 +1544,7 @@ var SSDiagram = (() => {
|
|
|
1482
1544
|
setNodeParamValue(nodeId, name, value) {
|
|
1483
1545
|
return this.updateNodeState(nodeId, "set node parameter", (node) => {
|
|
1484
1546
|
if (value === void 0) delete node.paramValues[name];
|
|
1485
|
-
else node.paramValues
|
|
1547
|
+
else setJsonKey(node.paramValues, name, value);
|
|
1486
1548
|
});
|
|
1487
1549
|
}
|
|
1488
1550
|
setShowNodeMessages(show) {
|
|
@@ -1565,7 +1627,7 @@ var SSDiagram = (() => {
|
|
|
1565
1627
|
for (const node of this.nodes) {
|
|
1566
1628
|
if (node.loadError.length === 0) continue;
|
|
1567
1629
|
const state = createDiagramNodeRuntimeState();
|
|
1568
|
-
state.
|
|
1630
|
+
state.errors.load = { kind: "load", message: node.loadError, pulse: ++this.runtimePulse };
|
|
1569
1631
|
this.runtimeState.nodes[node.id] = state;
|
|
1570
1632
|
}
|
|
1571
1633
|
if (Object.keys(this.runtimeState.nodes).length > 0) this.emitRuntimeStateChanged();
|
|
@@ -1765,15 +1827,16 @@ var SSDiagram = (() => {
|
|
|
1765
1827
|
this.runtimePulse = Math.max(
|
|
1766
1828
|
this.runtimePulse,
|
|
1767
1829
|
this.runtimeState.globalError?.pulse ?? 0,
|
|
1768
|
-
...Object.values(this.runtimeState.nodes).
|
|
1830
|
+
...Object.values(this.runtimeState.nodes).flatMap((node) => [node.errors.runtime?.pulse ?? 0, node.errors.load?.pulse ?? 0])
|
|
1769
1831
|
);
|
|
1770
1832
|
for (const node of this.nodes) {
|
|
1771
|
-
const
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
node.
|
|
1775
|
-
|
|
1776
|
-
|
|
1833
|
+
const errors = this.runtimeState.nodes[node.id]?.errors;
|
|
1834
|
+
const previousRuntime = previous.nodes[node.id]?.errors.runtime;
|
|
1835
|
+
const runtimeError = errors?.runtime;
|
|
1836
|
+
node.runtimeError = runtimeError?.message ?? "";
|
|
1837
|
+
node.loadError = errors?.load?.message ?? "";
|
|
1838
|
+
if (runtimeError !== void 0) {
|
|
1839
|
+
if (previousRuntime === void 0 || previousRuntime.pulse !== runtimeError.pulse) {
|
|
1777
1840
|
node.errorFlashStart = performance.now();
|
|
1778
1841
|
}
|
|
1779
1842
|
} else {
|
|
@@ -1822,7 +1885,9 @@ var SSDiagram = (() => {
|
|
|
1822
1885
|
const state = this.getRuntimeState();
|
|
1823
1886
|
const nodeState = state.nodes[id] ?? createDiagramNodeRuntimeState();
|
|
1824
1887
|
state.nodes[id] = nodeState;
|
|
1825
|
-
|
|
1888
|
+
if (message.length === 0) delete nodeState.errors[kind];
|
|
1889
|
+
else if (kind === "load") nodeState.errors.load = { kind, message, pulse: ++this.runtimePulse };
|
|
1890
|
+
else nodeState.errors.runtime = { kind, message, pulse: ++this.runtimePulse };
|
|
1826
1891
|
this.runtimeState = state;
|
|
1827
1892
|
this.emitRuntimeStateChanged();
|
|
1828
1893
|
return true;
|
|
@@ -1837,8 +1902,9 @@ var SSDiagram = (() => {
|
|
|
1837
1902
|
if (kind === void 0 || kind === "load") node.loadError = "";
|
|
1838
1903
|
const state = this.getRuntimeState();
|
|
1839
1904
|
const nodeState = state.nodes[id];
|
|
1840
|
-
if (nodeState !== void 0
|
|
1841
|
-
|
|
1905
|
+
if (nodeState !== void 0) {
|
|
1906
|
+
if (kind === void 0 || kind === "runtime") delete nodeState.errors.runtime;
|
|
1907
|
+
if (kind === void 0 || kind === "load") delete nodeState.errors.load;
|
|
1842
1908
|
}
|
|
1843
1909
|
this.runtimeState = state;
|
|
1844
1910
|
this.emitRuntimeStateChanged();
|
|
@@ -3634,6 +3700,13 @@ ${runtime.error}`;
|
|
|
3634
3700
|
}
|
|
3635
3701
|
}
|
|
3636
3702
|
}
|
|
3703
|
+
/**
|
|
3704
|
+
* Whether anyone is listening. Lets a subject skip building a payload that
|
|
3705
|
+
* is expensive to produce and that nothing would read.
|
|
3706
|
+
*/
|
|
3707
|
+
hasHandlers(event) {
|
|
3708
|
+
return (this.handlers.get(event)?.size ?? 0) > 0;
|
|
3709
|
+
}
|
|
3637
3710
|
clearEventHandlers() {
|
|
3638
3711
|
this.handlers.clear();
|
|
3639
3712
|
}
|
|
@@ -3655,7 +3728,7 @@ ${runtime.error}`;
|
|
|
3655
3728
|
this.maxLinks = typeof init.maxLinks === "number" ? init.maxLinks : 0;
|
|
3656
3729
|
this.availableTypes = init.availableTypes ?? [];
|
|
3657
3730
|
this.isDynamic = init.isDynamic ?? false;
|
|
3658
|
-
this.dynamicMode = init.dynamicMode
|
|
3731
|
+
this.dynamicMode = toPortDynamicMode(init.dynamicMode);
|
|
3659
3732
|
this.isSibling = init.isSibling ?? false;
|
|
3660
3733
|
}
|
|
3661
3734
|
clone() {
|
|
@@ -3757,7 +3830,6 @@ ${runtime.error}`;
|
|
|
3757
3830
|
this.fullscreen = false;
|
|
3758
3831
|
this.fullscreenButtonVisible = true;
|
|
3759
3832
|
this.fullscreenLabels = { enter: "Enter fullscreen", exit: "Exit fullscreen" };
|
|
3760
|
-
this.linkValidator = null;
|
|
3761
3833
|
this.contextActions = new DiagramActionRegistry();
|
|
3762
3834
|
this.div = options.div;
|
|
3763
3835
|
this.catalog = options.catalog;
|
|
@@ -3781,7 +3853,6 @@ ${runtime.error}`;
|
|
|
3781
3853
|
this.updateZoomLabel();
|
|
3782
3854
|
}
|
|
3783
3855
|
setLinkValidator(validator) {
|
|
3784
|
-
this.linkValidator = validator;
|
|
3785
3856
|
this.canvas.setLinkValidator(validator === null ? null : ({ fromNode, fromPort, toNode, toPort }) => validator({
|
|
3786
3857
|
fromNode: this.fromCanvasNode(fromNode),
|
|
3787
3858
|
fromPort: this.fromCanvasPort(fromPort),
|
|
@@ -3855,21 +3926,25 @@ ${runtime.error}`;
|
|
|
3855
3926
|
removeLink(link) {
|
|
3856
3927
|
this.canvas.removeLink(this.toCanvasLink(link));
|
|
3857
3928
|
}
|
|
3929
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3858
3930
|
addPort(nodeId, direction, port) {
|
|
3859
|
-
this.canvas.addPort(nodeId, direction, this.toCanvasPort(port));
|
|
3931
|
+
return this.canvas.addPort(nodeId, direction, this.toCanvasPort(port));
|
|
3860
3932
|
}
|
|
3933
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3861
3934
|
removePort(nodeId, direction, portId) {
|
|
3862
|
-
this.canvas.removePort(nodeId, direction, portId);
|
|
3935
|
+
return this.canvas.removePort(nodeId, direction, portId);
|
|
3863
3936
|
}
|
|
3937
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3864
3938
|
updatePortType(nodeId, direction, portId, type) {
|
|
3865
|
-
this.canvas.updatePortType(nodeId, direction, portId, type);
|
|
3939
|
+
return this.canvas.updatePortType(nodeId, direction, portId, type);
|
|
3866
3940
|
}
|
|
3867
3941
|
updatePort(nodeId, direction, portId, patch) {
|
|
3868
3942
|
return this.canvas.updatePort(nodeId, direction, portId, patch);
|
|
3869
3943
|
}
|
|
3944
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3870
3945
|
setNodePorts(nodeId, inPorts, outPorts) {
|
|
3871
3946
|
const current = this.canvas.findNode(nodeId);
|
|
3872
|
-
if (current === void 0) return;
|
|
3947
|
+
if (current === void 0) return false;
|
|
3873
3948
|
const convert = (port) => ({
|
|
3874
3949
|
id: port.key,
|
|
3875
3950
|
name: port.name,
|
|
@@ -3888,13 +3963,15 @@ ${runtime.error}`;
|
|
|
3888
3963
|
for (const sibling of current.outPorts.filter((port) => port.isSibling)) {
|
|
3889
3964
|
if (!nextOut.some((port) => port.id === sibling.id)) nextOut.push(sibling.toInit());
|
|
3890
3965
|
}
|
|
3891
|
-
this.canvas.setNodePorts(nodeId, nextIn, nextOut);
|
|
3966
|
+
return this.canvas.setNodePorts(nodeId, nextIn, nextOut);
|
|
3892
3967
|
}
|
|
3968
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3893
3969
|
updateNode(nodeId, patch) {
|
|
3894
|
-
this.canvas.updateNode(nodeId, patch);
|
|
3970
|
+
return this.canvas.updateNode(nodeId, patch);
|
|
3895
3971
|
}
|
|
3972
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3896
3973
|
setNodeMessage(nodeId, message) {
|
|
3897
|
-
this.canvas.updateNode(nodeId, { message });
|
|
3974
|
+
return this.canvas.updateNode(nodeId, { message });
|
|
3898
3975
|
}
|
|
3899
3976
|
setNodeError(nodeId, message, options = {}) {
|
|
3900
3977
|
return this.canvas.setNodeError(nodeId, message, options);
|
|
@@ -3920,11 +3997,13 @@ ${runtime.error}`;
|
|
|
3920
3997
|
setGlobalError(message, kind = "invalid") {
|
|
3921
3998
|
this.canvas.setGlobalError(message, kind);
|
|
3922
3999
|
}
|
|
4000
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3923
4001
|
setNodeParamValue(nodeId, paramName, value) {
|
|
3924
|
-
this.canvas.setNodeParamValue(nodeId, paramName, value);
|
|
4002
|
+
return this.canvas.setNodeParamValue(nodeId, paramName, value);
|
|
3925
4003
|
}
|
|
4004
|
+
/** False when nothing changed: no such node or port, or the edit was a no-op. */
|
|
3926
4005
|
setNodeName(nodeId, value) {
|
|
3927
|
-
this.canvas.updateNode(nodeId, { name: value });
|
|
4006
|
+
return this.canvas.updateNode(nodeId, { name: value });
|
|
3928
4007
|
}
|
|
3929
4008
|
/** Groups host-driven document edits into one undo/redo operation. */
|
|
3930
4009
|
transaction(label, action) {
|
|
@@ -4347,50 +4426,43 @@ ${runtime.error}`;
|
|
|
4347
4426
|
}
|
|
4348
4427
|
registerContextActions() {
|
|
4349
4428
|
const permissions = () => this.canvas.getInteractionPermissions();
|
|
4350
|
-
this.contextActions.
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
canExecute: ({ nodes }) => nodes.length > 0,
|
|
4388
|
-
execute: ({ nodes }) => this.emit("nodeProperties", { nodes })
|
|
4389
|
-
});
|
|
4390
|
-
this.contextActions.register({
|
|
4391
|
-
id: "help",
|
|
4392
|
-
canExecute: ({ nodes }) => this.helpEnabled && nodes.length > 0,
|
|
4393
|
-
execute: ({ nodes }) => this.emit("nodeHelp", { nodes })
|
|
4429
|
+
this.contextActions.registerAll({
|
|
4430
|
+
undo: {
|
|
4431
|
+
canExecute: () => this.canUndo(),
|
|
4432
|
+
execute: () => this.undo()
|
|
4433
|
+
},
|
|
4434
|
+
redo: {
|
|
4435
|
+
canExecute: () => this.canRedo(),
|
|
4436
|
+
execute: () => this.redo()
|
|
4437
|
+
},
|
|
4438
|
+
cut: {
|
|
4439
|
+
canExecute: ({ nodes }) => nodes.length > 0 && permissions().copy && permissions().deleteSelection,
|
|
4440
|
+
execute: () => this.cutSelection()
|
|
4441
|
+
},
|
|
4442
|
+
copy: {
|
|
4443
|
+
canExecute: ({ nodes }) => nodes.length > 0 && permissions().copy,
|
|
4444
|
+
execute: () => this.copySelection()
|
|
4445
|
+
},
|
|
4446
|
+
paste: {
|
|
4447
|
+
canExecute: () => this.canvas.hasClipboard() && permissions().paste,
|
|
4448
|
+
execute: () => this.pasteSelection()
|
|
4449
|
+
},
|
|
4450
|
+
open: {
|
|
4451
|
+
canExecute: ({ nodes }) => nodes.length === 1 && nodes[0].openAction.length > 0,
|
|
4452
|
+
execute: ({ nodes }) => this.emit("nodeOpen", { nodes })
|
|
4453
|
+
},
|
|
4454
|
+
delete: {
|
|
4455
|
+
canExecute: ({ selection }) => permissions().deleteSelection && (selection.nodeIds.length > 0 || selection.linkIds.length > 0),
|
|
4456
|
+
execute: () => this.canvas.deleteSelection()
|
|
4457
|
+
},
|
|
4458
|
+
properties: {
|
|
4459
|
+
canExecute: ({ nodes }) => nodes.length > 0,
|
|
4460
|
+
execute: ({ nodes }) => this.emit("nodeProperties", { nodes })
|
|
4461
|
+
},
|
|
4462
|
+
help: {
|
|
4463
|
+
canExecute: ({ nodes }) => this.helpEnabled && nodes.length > 0,
|
|
4464
|
+
execute: ({ nodes }) => this.emit("nodeHelp", { nodes })
|
|
4465
|
+
}
|
|
4394
4466
|
});
|
|
4395
4467
|
}
|
|
4396
4468
|
contextActionContext() {
|
|
@@ -4558,19 +4630,26 @@ ${runtime.error}`;
|
|
|
4558
4630
|
// imported node ("Element type is missing from the palette"). Node.id
|
|
4559
4631
|
// keeps its original casing so save/load round-trips unchanged.
|
|
4560
4632
|
addNodeType(node) {
|
|
4561
|
-
const n = node instanceof Node ? node : new Node(node);
|
|
4633
|
+
const n = (node instanceof Node ? node : new Node(node)).clone();
|
|
4562
4634
|
this.nodeTypes.set(n.id.toLowerCase(), n);
|
|
4563
|
-
this.
|
|
4635
|
+
this.emitNodeTypesChanged();
|
|
4564
4636
|
}
|
|
4565
4637
|
removeNodeType(id) {
|
|
4566
4638
|
this.nodeTypes.delete(id.toLowerCase());
|
|
4567
|
-
this.
|
|
4639
|
+
this.emitNodeTypesChanged();
|
|
4568
4640
|
}
|
|
4569
4641
|
getNodeType(id) {
|
|
4570
|
-
return this.nodeTypes.get(id.toLowerCase()) ?? null;
|
|
4642
|
+
return this.nodeTypes.get(id.toLowerCase())?.clone() ?? null;
|
|
4571
4643
|
}
|
|
4572
4644
|
getNodeTypes() {
|
|
4573
|
-
return Array.from(this.nodeTypes.values());
|
|
4645
|
+
return Array.from(this.nodeTypes.values(), (node) => node.clone());
|
|
4646
|
+
}
|
|
4647
|
+
// Node definitions are mutable, so the payload has to be a copy of each one.
|
|
4648
|
+
// Building a catalog is a loop of addNodeType calls, which would make that
|
|
4649
|
+
// quadratic; skipping it while nobody listens keeps catalog construction --
|
|
4650
|
+
// where no subscriber exists yet -- as cheap as it was.
|
|
4651
|
+
emitNodeTypesChanged() {
|
|
4652
|
+
if (this.hasHandlers("nodeTypesChanged")) this.emit("nodeTypesChanged", this.getNodeTypes());
|
|
4574
4653
|
}
|
|
4575
4654
|
};
|
|
4576
4655
|
|
|
@@ -4883,60 +4962,127 @@ ${runtime.error}`;
|
|
|
4883
4962
|
});
|
|
4884
4963
|
return { nodes, nodeErrors };
|
|
4885
4964
|
}
|
|
4965
|
+
function isRecord(value) {
|
|
4966
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4967
|
+
}
|
|
4968
|
+
function asRecord(value) {
|
|
4969
|
+
return isRecord(value) ? value : void 0;
|
|
4970
|
+
}
|
|
4971
|
+
function asArray(value) {
|
|
4972
|
+
return Array.isArray(value) ? value : [];
|
|
4973
|
+
}
|
|
4974
|
+
function asString(value) {
|
|
4975
|
+
return typeof value === "string" ? value : "";
|
|
4976
|
+
}
|
|
4977
|
+
function asFiniteNumber(value) {
|
|
4978
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
4979
|
+
}
|
|
4886
4980
|
function nodeName(node) {
|
|
4887
|
-
const
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
const
|
|
4891
|
-
|
|
4892
|
-
return nameVal;
|
|
4893
|
-
if (typeof node?.Figure === "string" && node.Figure.length > 0)
|
|
4894
|
-
return node.Figure;
|
|
4895
|
-
return typeof node?.Key === "string" ? node.Key : "";
|
|
4981
|
+
const named = asRecord(asRecord(asRecord(node.Settings)?.Parameters)?.Name)?.Value;
|
|
4982
|
+
if (typeof named === "string" && named.length > 0)
|
|
4983
|
+
return named;
|
|
4984
|
+
const figure = asString(node.Figure);
|
|
4985
|
+
return figure.length > 0 ? figure : asString(node.Key);
|
|
4896
4986
|
}
|
|
4897
4987
|
function parseRawScheme(raw) {
|
|
4898
4988
|
const nodes = [];
|
|
4899
4989
|
const links = [];
|
|
4900
|
-
const
|
|
4901
|
-
const
|
|
4902
|
-
|
|
4903
|
-
const scheme = value?.Scheme;
|
|
4904
|
-
const model = scheme?.Model;
|
|
4905
|
-
if (!model)
|
|
4990
|
+
const model = asRecord(asRecord(asRecord(asRecord(raw)?.Content)?.Value)?.Scheme)?.Model;
|
|
4991
|
+
const fields = asRecord(model);
|
|
4992
|
+
if (fields === void 0)
|
|
4906
4993
|
return { nodes, links };
|
|
4907
|
-
for (const
|
|
4908
|
-
const
|
|
4994
|
+
for (const entry of asArray(fields.Nodes)) {
|
|
4995
|
+
const node = asRecord(entry);
|
|
4996
|
+
if (node === void 0)
|
|
4997
|
+
continue;
|
|
4998
|
+
const key = node.Key;
|
|
4909
4999
|
if (typeof key !== "string" || key.length === 0)
|
|
4910
5000
|
continue;
|
|
4911
5001
|
nodes.push({
|
|
4912
5002
|
id: key,
|
|
4913
|
-
typeId:
|
|
4914
|
-
name: nodeName(
|
|
4915
|
-
x:
|
|
4916
|
-
y:
|
|
5003
|
+
typeId: asString(node.TypeId),
|
|
5004
|
+
name: nodeName(node),
|
|
5005
|
+
x: asFiniteNumber(node.X),
|
|
5006
|
+
y: asFiniteNumber(node.Y)
|
|
4917
5007
|
});
|
|
4918
5008
|
}
|
|
4919
|
-
for (const
|
|
4920
|
-
const
|
|
4921
|
-
|
|
5009
|
+
for (const entry of asArray(fields.Links)) {
|
|
5010
|
+
const link = asRecord(entry);
|
|
5011
|
+
if (link === void 0)
|
|
5012
|
+
continue;
|
|
5013
|
+
const from = link.From;
|
|
5014
|
+
const to = link.To;
|
|
4922
5015
|
if (typeof from !== "string" || typeof to !== "string")
|
|
4923
5016
|
continue;
|
|
4924
5017
|
links.push({
|
|
4925
5018
|
from,
|
|
4926
|
-
fromPort:
|
|
5019
|
+
fromPort: asString(link.FromPort),
|
|
4927
5020
|
to,
|
|
4928
|
-
toPort:
|
|
5021
|
+
toPort: asString(link.ToPort)
|
|
4929
5022
|
});
|
|
4930
5023
|
}
|
|
4931
5024
|
return { nodes, links };
|
|
4932
5025
|
}
|
|
5026
|
+
function parsePalettePorts(value) {
|
|
5027
|
+
const ports = [];
|
|
5028
|
+
for (const entry of asArray(value)) {
|
|
5029
|
+
const port = asRecord(entry);
|
|
5030
|
+
if (port === void 0)
|
|
5031
|
+
continue;
|
|
5032
|
+
const key = asString(port.key);
|
|
5033
|
+
if (key.length === 0)
|
|
5034
|
+
continue;
|
|
5035
|
+
ports.push({
|
|
5036
|
+
key,
|
|
5037
|
+
name: asString(port.name),
|
|
5038
|
+
type: asString(port.type),
|
|
5039
|
+
maxLinks: asFiniteNumber(port.maxLinks),
|
|
5040
|
+
availableTypes: asArray(port.availableTypes).filter((item) => typeof item === "string"),
|
|
5041
|
+
isDynamic: port.isDynamic === true,
|
|
5042
|
+
dynamicMode: toPortDynamicMode(port.dynamicMode)
|
|
5043
|
+
});
|
|
5044
|
+
}
|
|
5045
|
+
return ports;
|
|
5046
|
+
}
|
|
5047
|
+
function parsePalette(value) {
|
|
5048
|
+
const socketTypes = [];
|
|
5049
|
+
const elements = [];
|
|
5050
|
+
const root = asRecord(value);
|
|
5051
|
+
if (root === void 0)
|
|
5052
|
+
return { socketTypes, elements };
|
|
5053
|
+
for (const entry of asArray(root.socketTypes)) {
|
|
5054
|
+
const socket = asRecord(entry);
|
|
5055
|
+
const name = asString(socket?.name);
|
|
5056
|
+
if (name.length === 0)
|
|
5057
|
+
continue;
|
|
5058
|
+
socketTypes.push({ name, color: asString(socket?.color) });
|
|
5059
|
+
}
|
|
5060
|
+
for (const entry of asArray(root.elements)) {
|
|
5061
|
+
const element = asRecord(entry);
|
|
5062
|
+
const typeId = asString(element?.typeId);
|
|
5063
|
+
if (element === void 0 || typeId.length === 0)
|
|
5064
|
+
continue;
|
|
5065
|
+
elements.push({
|
|
5066
|
+
typeId,
|
|
5067
|
+
name: asString(element.name),
|
|
5068
|
+
groupName: asString(element.groupName),
|
|
5069
|
+
icon: asString(element.icon),
|
|
5070
|
+
inPorts: parsePalettePorts(element.inPorts),
|
|
5071
|
+
outPorts: parsePalettePorts(element.outPorts)
|
|
5072
|
+
});
|
|
5073
|
+
}
|
|
5074
|
+
return { socketTypes, elements };
|
|
5075
|
+
}
|
|
4933
5076
|
async function renderScheme(div, paletteUrl, scheme, options = {}) {
|
|
4934
5077
|
return renderSchemeAtRevision(div, paletteUrl, scheme, beginRender(div), options);
|
|
4935
5078
|
}
|
|
4936
5079
|
async function renderSchemeAtRevision(div, paletteUrl, scheme, revision, options) {
|
|
4937
5080
|
if (renderRevisions.get(div) !== revision)
|
|
4938
5081
|
return null;
|
|
4939
|
-
const
|
|
5082
|
+
const response = await fetch(paletteUrl);
|
|
5083
|
+
if (!response.ok)
|
|
5084
|
+
throw new Error(`Palette request to ${paletteUrl} failed with status ${response.status}.`);
|
|
5085
|
+
const palette = parsePalette(await response.json());
|
|
4940
5086
|
if (renderRevisions.get(div) !== revision)
|
|
4941
5087
|
return null;
|
|
4942
5088
|
const catalog = buildCatalog(palette);
|
|
@@ -5100,6 +5246,14 @@ ${runtime.error}`;
|
|
|
5100
5246
|
disconnectedHostObserver.disconnect();
|
|
5101
5247
|
disconnectedHostObserver = null;
|
|
5102
5248
|
}
|
|
5249
|
+
function errorTexts(div) {
|
|
5250
|
+
const parts = (div.dataset.diagramErrors ?? "").split("|");
|
|
5251
|
+
return {
|
|
5252
|
+
load: parts[0] || "Diagram source could not be loaded.",
|
|
5253
|
+
empty: parts[1] || "Diagram is empty or malformed.",
|
|
5254
|
+
draw: parts[2] || "Diagram could not be rendered."
|
|
5255
|
+
};
|
|
5256
|
+
}
|
|
5103
5257
|
function note(div, message, revision) {
|
|
5104
5258
|
if (renderRevisions.get(div) !== revision) return;
|
|
5105
5259
|
disposeActiveRender(div);
|
|
@@ -5108,53 +5262,51 @@ ${runtime.error}`;
|
|
|
5108
5262
|
}
|
|
5109
5263
|
async function renderFromSource(div, paletteUrl, srcUrl, options = {}) {
|
|
5110
5264
|
const revision = beginRender(div);
|
|
5111
|
-
const errors = (div
|
|
5112
|
-
const [errLoad = "Diagram source could not be loaded.", errEmpty = "Diagram is empty or malformed.", errDraw = "Diagram could not be rendered."] = errors;
|
|
5265
|
+
const errors = errorTexts(div);
|
|
5113
5266
|
let raw;
|
|
5114
5267
|
try {
|
|
5115
5268
|
const resp = await fetch(srcUrl);
|
|
5116
5269
|
if (!resp.ok) {
|
|
5117
|
-
note(div,
|
|
5270
|
+
note(div, errors.load, revision);
|
|
5118
5271
|
return null;
|
|
5119
5272
|
}
|
|
5120
5273
|
const text = (await resp.text()).replace(/^/, "");
|
|
5121
5274
|
raw = JSON.parse(text);
|
|
5122
5275
|
} catch {
|
|
5123
|
-
note(div,
|
|
5276
|
+
note(div, errors.load, revision);
|
|
5124
5277
|
return null;
|
|
5125
5278
|
}
|
|
5126
5279
|
const scheme = parseRawScheme(raw);
|
|
5127
5280
|
if (scheme.nodes.length === 0) {
|
|
5128
|
-
note(div,
|
|
5281
|
+
note(div, errors.empty, revision);
|
|
5129
5282
|
return null;
|
|
5130
5283
|
}
|
|
5131
5284
|
try {
|
|
5132
5285
|
return await renderSchemeAtRevision(div, paletteUrl, scheme, revision, options);
|
|
5133
5286
|
} catch {
|
|
5134
|
-
note(div,
|
|
5287
|
+
note(div, errors.draw, revision);
|
|
5135
5288
|
return null;
|
|
5136
5289
|
}
|
|
5137
5290
|
}
|
|
5138
5291
|
async function renderFromInline(div, paletteUrl, json, options = {}) {
|
|
5139
5292
|
const revision = beginRender(div);
|
|
5140
|
-
const errors = (div
|
|
5141
|
-
const [, errEmpty = "Diagram is empty or malformed.", errDraw = "Diagram could not be rendered."] = errors;
|
|
5293
|
+
const errors = errorTexts(div);
|
|
5142
5294
|
let raw;
|
|
5143
5295
|
try {
|
|
5144
5296
|
raw = JSON.parse(json);
|
|
5145
5297
|
} catch {
|
|
5146
|
-
note(div,
|
|
5298
|
+
note(div, errors.empty, revision);
|
|
5147
5299
|
return null;
|
|
5148
5300
|
}
|
|
5149
5301
|
const scheme = parseRawScheme(raw);
|
|
5150
5302
|
if (scheme.nodes.length === 0) {
|
|
5151
|
-
note(div,
|
|
5303
|
+
note(div, errors.empty, revision);
|
|
5152
5304
|
return null;
|
|
5153
5305
|
}
|
|
5154
5306
|
try {
|
|
5155
5307
|
return await renderSchemeAtRevision(div, paletteUrl, scheme, revision, options);
|
|
5156
5308
|
} catch {
|
|
5157
|
-
note(div,
|
|
5309
|
+
note(div, errors.draw, revision);
|
|
5158
5310
|
return null;
|
|
5159
5311
|
}
|
|
5160
5312
|
}
|