@memberjunction/core-actions 2.107.0 → 2.109.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/custom/ai/find-best-action.action.d.ts +53 -0
- package/dist/custom/ai/find-best-action.action.d.ts.map +1 -0
- package/dist/custom/ai/find-best-action.action.js +211 -0
- package/dist/custom/ai/find-best-action.action.js.map +1 -0
- package/dist/custom/ai/find-best-agent.action.d.ts +53 -0
- package/dist/custom/ai/find-best-agent.action.d.ts.map +1 -0
- package/dist/custom/ai/find-best-agent.action.js +194 -0
- package/dist/custom/ai/find-best-agent.action.js.map +1 -0
- package/dist/custom/ai/summarize-content.action.d.ts +3 -3
- package/dist/custom/ai/summarize-content.action.d.ts.map +1 -1
- package/dist/custom/ai/summarize-content.action.js +51 -143
- package/dist/custom/ai/summarize-content.action.js.map +1 -1
- package/dist/custom/code-execution/execute-code.action.d.ts +61 -0
- package/dist/custom/code-execution/execute-code.action.d.ts.map +1 -0
- package/dist/custom/code-execution/execute-code.action.js +172 -0
- package/dist/custom/code-execution/execute-code.action.js.map +1 -0
- package/dist/custom/data/csv-parser.action.js +1 -1
- package/dist/custom/data/csv-parser.action.js.map +1 -1
- package/dist/custom/data/execute-research-query.action.d.ts +36 -18
- package/dist/custom/data/execute-research-query.action.d.ts.map +1 -1
- package/dist/custom/data/execute-research-query.action.js +221 -114
- package/dist/custom/data/execute-research-query.action.js.map +1 -1
- package/dist/custom/data/explore-database-schema.action.d.ts +4 -0
- package/dist/custom/data/explore-database-schema.action.d.ts.map +1 -1
- package/dist/custom/data/explore-database-schema.action.js +101 -8
- package/dist/custom/data/explore-database-schema.action.js.map +1 -1
- package/dist/custom/data/get-entity-details.action.d.ts +63 -0
- package/dist/custom/data/get-entity-details.action.d.ts.map +1 -0
- package/dist/custom/data/get-entity-details.action.js +284 -0
- package/dist/custom/data/get-entity-details.action.js.map +1 -0
- package/dist/custom/data/get-entity-list.action.d.ts +57 -0
- package/dist/custom/data/get-entity-list.action.d.ts.map +1 -0
- package/dist/custom/data/get-entity-list.action.js +177 -0
- package/dist/custom/data/get-entity-list.action.js.map +1 -0
- package/dist/custom/visualization/create-svg-chart.action.d.ts +97 -0
- package/dist/custom/visualization/create-svg-chart.action.d.ts.map +1 -0
- package/dist/custom/visualization/create-svg-chart.action.js +326 -0
- package/dist/custom/visualization/create-svg-chart.action.js.map +1 -0
- package/dist/custom/visualization/create-svg-diagram.action.d.ts +151 -0
- package/dist/custom/visualization/create-svg-diagram.action.d.ts.map +1 -0
- package/dist/custom/visualization/create-svg-diagram.action.js +764 -0
- package/dist/custom/visualization/create-svg-diagram.action.js.map +1 -0
- package/dist/custom/visualization/create-svg-infographic.action.d.ts +72 -0
- package/dist/custom/visualization/create-svg-infographic.action.d.ts.map +1 -0
- package/dist/custom/visualization/create-svg-infographic.action.js +343 -0
- package/dist/custom/visualization/create-svg-infographic.action.js.map +1 -0
- package/dist/custom/visualization/create-svg-network.action.d.ts +106 -0
- package/dist/custom/visualization/create-svg-network.action.d.ts.map +1 -0
- package/dist/custom/visualization/create-svg-network.action.js +687 -0
- package/dist/custom/visualization/create-svg-network.action.js.map +1 -0
- package/dist/custom/visualization/create-svg-sketch-diagram.action.d.ts +97 -0
- package/dist/custom/visualization/create-svg-sketch-diagram.action.d.ts.map +1 -0
- package/dist/custom/visualization/create-svg-sketch-diagram.action.js +730 -0
- package/dist/custom/visualization/create-svg-sketch-diagram.action.js.map +1 -0
- package/dist/custom/visualization/create-svg-word-cloud.action.d.ts +94 -0
- package/dist/custom/visualization/create-svg-word-cloud.action.d.ts.map +1 -0
- package/dist/custom/visualization/create-svg-word-cloud.action.js +497 -0
- package/dist/custom/visualization/create-svg-word-cloud.action.js.map +1 -0
- package/dist/custom/visualization/shared/svg-theming.d.ts +91 -0
- package/dist/custom/visualization/shared/svg-theming.d.ts.map +1 -0
- package/dist/custom/visualization/shared/svg-theming.js +235 -0
- package/dist/custom/visualization/shared/svg-theming.js.map +1 -0
- package/dist/custom/visualization/shared/svg-types.d.ts +354 -0
- package/dist/custom/visualization/shared/svg-types.d.ts.map +1 -0
- package/dist/custom/visualization/shared/svg-types.js +11 -0
- package/dist/custom/visualization/shared/svg-types.js.map +1 -0
- package/dist/custom/visualization/shared/svg-utils.d.ts +166 -0
- package/dist/custom/visualization/shared/svg-utils.d.ts.map +1 -0
- package/dist/custom/visualization/shared/svg-utils.js +555 -0
- package/dist/custom/visualization/shared/svg-utils.js.map +1 -0
- package/dist/custom/web/google-custom-search.action.d.ts +6 -1
- package/dist/custom/web/google-custom-search.action.d.ts.map +1 -1
- package/dist/custom/web/google-custom-search.action.js +78 -10
- package/dist/custom/web/google-custom-search.action.js.map +1 -1
- package/dist/custom/web/web-page-content.action.d.ts +24 -0
- package/dist/custom/web/web-page-content.action.d.ts.map +1 -1
- package/dist/custom/web/web-page-content.action.js +90 -9
- package/dist/custom/web/web-page-content.action.js.map +1 -1
- package/dist/generated/action_subclasses.d.ts +4 -4
- package/dist/generated/action_subclasses.js +13 -13
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -1
- package/package.json +30 -12
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
25
|
+
if (mod && mod.__esModule) return mod;
|
|
26
|
+
var result = {};
|
|
27
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
28
|
+
__setModuleDefault(result, mod);
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.LoadCreateSVGDiagramAction = exports.CreateSVGDiagramAction = void 0;
|
|
33
|
+
const actions_1 = require("@memberjunction/actions");
|
|
34
|
+
const global_1 = require("@memberjunction/global");
|
|
35
|
+
const dagre = __importStar(require("@dagrejs/dagre"));
|
|
36
|
+
const d3Hierarchy = __importStar(require("d3-hierarchy"));
|
|
37
|
+
const svg_utils_1 = require("./shared/svg-utils");
|
|
38
|
+
const svg_theming_1 = require("./shared/svg-theming");
|
|
39
|
+
/**
|
|
40
|
+
* Action that generates SVG diagrams including flowcharts, org charts, and ER diagrams.
|
|
41
|
+
*
|
|
42
|
+
* This action provides server-side SVG generation for structured diagrams, designed for
|
|
43
|
+
* AI agents and workflows to create publication-quality visualizations from structured data.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // Flowchart example
|
|
48
|
+
* await runAction({
|
|
49
|
+
* ActionName: 'Create SVG Diagram',
|
|
50
|
+
* Params: [
|
|
51
|
+
* { Name: 'DiagramType', Value: 'flow' },
|
|
52
|
+
* { Name: 'Nodes', Value: JSON.stringify([
|
|
53
|
+
* { id: '1', kind: 'start', label: 'Start' },
|
|
54
|
+
* { id: '2', kind: 'process', label: 'Process Data' },
|
|
55
|
+
* { id: '3', kind: 'end', label: 'End' }
|
|
56
|
+
* ]) },
|
|
57
|
+
* { Name: 'Edges', Value: JSON.stringify([
|
|
58
|
+
* { from: '1', to: '2', label: 'Begin' },
|
|
59
|
+
* { from: '2', to: '3' }
|
|
60
|
+
* ]) },
|
|
61
|
+
* { Name: 'Direction', Value: 'TB' },
|
|
62
|
+
* { Name: 'Width', Value: '800' },
|
|
63
|
+
* { Name: 'Height', Value: '600' }
|
|
64
|
+
* ]
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* // Org chart example
|
|
68
|
+
* await runAction({
|
|
69
|
+
* ActionName: 'Create SVG Diagram',
|
|
70
|
+
* Params: [
|
|
71
|
+
* { Name: 'DiagramType', Value: 'org' },
|
|
72
|
+
* { Name: 'Nodes', Value: JSON.stringify({
|
|
73
|
+
* id: '1',
|
|
74
|
+
* label: 'CEO',
|
|
75
|
+
* role: 'Chief Executive Officer',
|
|
76
|
+
* children: [
|
|
77
|
+
* { id: '2', label: 'CTO', role: 'Technology' },
|
|
78
|
+
* { id: '3', label: 'CFO', role: 'Finance' }
|
|
79
|
+
* ]
|
|
80
|
+
* }) }
|
|
81
|
+
* ]
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
let CreateSVGDiagramAction = class CreateSVGDiagramAction extends actions_1.BaseAction {
|
|
86
|
+
/**
|
|
87
|
+
* Generates an SVG diagram from the provided data and configuration
|
|
88
|
+
*
|
|
89
|
+
* @param params - The action parameters containing:
|
|
90
|
+
* - DiagramType: Type of diagram ('flow' | 'org' | 'er')
|
|
91
|
+
* - Nodes: JSON array or object of nodes
|
|
92
|
+
* - Edges: JSON array of edges (for flow and ER diagrams)
|
|
93
|
+
* - Direction: Layout direction ('TB' | 'LR' | 'RL' | 'BT') for flow diagrams
|
|
94
|
+
* - Width: Diagram width in pixels (optional, default: 800)
|
|
95
|
+
* - Height: Diagram height in pixels (optional, default: 600)
|
|
96
|
+
* - Title: Diagram title (optional)
|
|
97
|
+
* - Palette: Color palette ('mjDefault' | 'gray' | 'pastel' | 'highContrast')
|
|
98
|
+
* - Seed: Random seed for deterministic layouts (optional)
|
|
99
|
+
*
|
|
100
|
+
* @returns A promise resolving to an SVGActionResult with:
|
|
101
|
+
* - Success: true if diagram was generated successfully
|
|
102
|
+
* - ResultCode: "SUCCESS" or error code
|
|
103
|
+
* - Message: The SVG string or error message
|
|
104
|
+
* - svg: The SVG XML string
|
|
105
|
+
* - width: Diagram width in pixels
|
|
106
|
+
* - height: Diagram height in pixels
|
|
107
|
+
*/
|
|
108
|
+
async InternalRunAction(params) {
|
|
109
|
+
try {
|
|
110
|
+
const diagramTypeParam = this.getParamValue(params, 'DiagramType');
|
|
111
|
+
if (!diagramTypeParam) {
|
|
112
|
+
return {
|
|
113
|
+
Success: false,
|
|
114
|
+
Message: 'DiagramType parameter is required (flow, org, or er)',
|
|
115
|
+
ResultCode: 'MISSING_PARAMETERS',
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const diagramType = this.ensureString(diagramTypeParam, 'DiagramType').toLowerCase();
|
|
119
|
+
// Parse common parameters
|
|
120
|
+
const width = parseInt(this.ensureString(this.getParamValue(params, 'Width') || '800', 'Width'));
|
|
121
|
+
const height = parseInt(this.ensureString(this.getParamValue(params, 'Height') || '600', 'Height'));
|
|
122
|
+
const title = this.ensureString(this.getParamValue(params, 'Title') || '', 'Title');
|
|
123
|
+
const paletteName = this.ensureString(this.getParamValue(params, 'Palette') || 'mjDefault', 'Palette');
|
|
124
|
+
const seed = parseInt(this.ensureString(this.getParamValue(params, 'Seed') || '0', 'Seed'));
|
|
125
|
+
// Create branding configuration
|
|
126
|
+
const branding = {
|
|
127
|
+
palette: { type: 'named', name: paletteName },
|
|
128
|
+
};
|
|
129
|
+
// Create viewBox configuration
|
|
130
|
+
const viewBox = {
|
|
131
|
+
width,
|
|
132
|
+
height,
|
|
133
|
+
padding: 40,
|
|
134
|
+
};
|
|
135
|
+
// Generate diagram based on type
|
|
136
|
+
let svg;
|
|
137
|
+
switch (diagramType) {
|
|
138
|
+
case 'flow':
|
|
139
|
+
svg = await this.renderFlowDiagram(params, viewBox, branding, title, seed);
|
|
140
|
+
break;
|
|
141
|
+
case 'org':
|
|
142
|
+
svg = await this.renderOrgChart(params, viewBox, branding, title);
|
|
143
|
+
break;
|
|
144
|
+
case 'er':
|
|
145
|
+
svg = await this.renderERDiagram(params, viewBox, branding, title, seed);
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
return {
|
|
149
|
+
Success: false,
|
|
150
|
+
Message: `Unsupported diagram type: ${diagramType}. Supported types: flow, org, er`,
|
|
151
|
+
ResultCode: 'INVALID_DIAGRAM_TYPE',
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
Success: true,
|
|
156
|
+
ResultCode: 'SUCCESS',
|
|
157
|
+
Message: svg,
|
|
158
|
+
svg,
|
|
159
|
+
width,
|
|
160
|
+
height,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
Success: false,
|
|
166
|
+
Message: `Failed to generate diagram: ${error instanceof Error ? error.message : String(error)}`,
|
|
167
|
+
ResultCode: 'DIAGRAM_GENERATION_FAILED',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Renders a flowchart using dagre layout
|
|
173
|
+
*/
|
|
174
|
+
async renderFlowDiagram(params, viewBox, branding, title, seed) {
|
|
175
|
+
// Parse nodes and edges
|
|
176
|
+
const nodesParam = this.getParamValue(params, 'Nodes');
|
|
177
|
+
const edgesParam = this.getParamValue(params, 'Edges');
|
|
178
|
+
if (!nodesParam) {
|
|
179
|
+
throw new Error('Nodes parameter is required for flow diagrams');
|
|
180
|
+
}
|
|
181
|
+
const nodes = this.parseJSON(nodesParam, 'Nodes');
|
|
182
|
+
const edges = edgesParam ? this.parseJSON(edgesParam, 'Edges') : [];
|
|
183
|
+
const directionParam = this.getParamValue(params, 'Direction');
|
|
184
|
+
const direction = (directionParam ? this.ensureString(directionParam, 'Direction') : 'TB');
|
|
185
|
+
// Create dagre graph
|
|
186
|
+
const g = new dagre.graphlib.Graph();
|
|
187
|
+
g.setGraph({
|
|
188
|
+
rankdir: direction,
|
|
189
|
+
nodesep: 50,
|
|
190
|
+
ranksep: 80,
|
|
191
|
+
marginx: 40,
|
|
192
|
+
marginy: 40,
|
|
193
|
+
});
|
|
194
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
195
|
+
// Add nodes to graph with dimensions based on kind
|
|
196
|
+
for (const node of nodes) {
|
|
197
|
+
const dims = this.getNodeDimensions(node);
|
|
198
|
+
g.setNode(node.id, {
|
|
199
|
+
...node,
|
|
200
|
+
width: node.width || dims.width,
|
|
201
|
+
height: node.height || dims.height,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Add edges to graph
|
|
205
|
+
for (const edge of edges) {
|
|
206
|
+
g.setEdge(edge.from, edge.to, edge);
|
|
207
|
+
}
|
|
208
|
+
// Run dagre layout
|
|
209
|
+
dagre.layout(g);
|
|
210
|
+
// Create SVG
|
|
211
|
+
const vb = svg_utils_1.SVGUtils.calculateViewBox(viewBox);
|
|
212
|
+
const doc = svg_utils_1.SVGUtils.createSVG(viewBox.width, viewBox.height, 'flow');
|
|
213
|
+
const svg = doc.querySelector('svg');
|
|
214
|
+
// Add accessibility
|
|
215
|
+
if (title) {
|
|
216
|
+
svg_utils_1.SVGUtils.addA11y(svg, {
|
|
217
|
+
title,
|
|
218
|
+
ariaRole: 'img',
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// Add styles
|
|
222
|
+
const css = (0, svg_theming_1.generateCSS)(branding);
|
|
223
|
+
svg_utils_1.SVGUtils.addStyles(svg, css);
|
|
224
|
+
// Get palette for colors
|
|
225
|
+
const palette = (0, svg_theming_1.getPalette)(branding.palette);
|
|
226
|
+
// Render nodes
|
|
227
|
+
for (const nodeId of g.nodes()) {
|
|
228
|
+
const node = g.node(nodeId);
|
|
229
|
+
this.renderFlowNode(doc, svg, node, palette);
|
|
230
|
+
}
|
|
231
|
+
// Render edges
|
|
232
|
+
for (const edgeObj of g.edges()) {
|
|
233
|
+
const edge = g.edge(edgeObj);
|
|
234
|
+
this.renderFlowEdge(doc, svg, edge, palette);
|
|
235
|
+
}
|
|
236
|
+
// Add title if present
|
|
237
|
+
if (title) {
|
|
238
|
+
this.addTitle(doc, svg, title, vb.width, (0, svg_theming_1.getFontSpec)(branding.font));
|
|
239
|
+
}
|
|
240
|
+
// Sanitize and return
|
|
241
|
+
return svg_utils_1.SVGUtils.sanitizeSVG(svg.outerHTML);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Gets dimensions for flow node based on kind
|
|
245
|
+
*/
|
|
246
|
+
getNodeDimensions(node) {
|
|
247
|
+
const labelWidth = svg_utils_1.SVGUtils.estimateTextWidth(node.label, 14);
|
|
248
|
+
switch (node.kind) {
|
|
249
|
+
case 'start':
|
|
250
|
+
case 'end':
|
|
251
|
+
return { width: 120, height: 60 };
|
|
252
|
+
case 'decision':
|
|
253
|
+
return { width: Math.max(160, labelWidth + 40), height: 100 };
|
|
254
|
+
case 'process':
|
|
255
|
+
case 'input':
|
|
256
|
+
case 'output':
|
|
257
|
+
case 'subprocess':
|
|
258
|
+
return { width: Math.max(140, labelWidth + 40), height: 70 };
|
|
259
|
+
default:
|
|
260
|
+
return { width: 140, height: 70 };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Renders a single flow node
|
|
265
|
+
*/
|
|
266
|
+
renderFlowNode(doc, svg, node, palette) {
|
|
267
|
+
const ns = svg.namespaceURI;
|
|
268
|
+
const g = doc.createElementNS(ns, 'g');
|
|
269
|
+
g.setAttribute('id', node.id);
|
|
270
|
+
g.setAttribute('transform', `translate(${node.x}, ${node.y})`);
|
|
271
|
+
const colorIndex = this.getNodeColorIndex(node.kind);
|
|
272
|
+
const fillColor = palette.categorical[colorIndex % palette.categorical.length];
|
|
273
|
+
// Render shape based on kind
|
|
274
|
+
switch (node.kind) {
|
|
275
|
+
case 'start':
|
|
276
|
+
case 'end':
|
|
277
|
+
this.renderEllipse(doc, g, node.width, node.height, fillColor);
|
|
278
|
+
break;
|
|
279
|
+
case 'decision':
|
|
280
|
+
this.renderDiamond(doc, g, node.width, node.height, fillColor);
|
|
281
|
+
break;
|
|
282
|
+
case 'subprocess':
|
|
283
|
+
this.renderRoundedRect(doc, g, node.width, node.height, fillColor, 10);
|
|
284
|
+
// Add double border for subprocess
|
|
285
|
+
const innerRect = doc.createElementNS(ns, 'path');
|
|
286
|
+
innerRect.setAttribute('d', svg_utils_1.SVGUtils.roundedRectPath(-node.width / 2 + 5, -node.height / 2 + 5, node.width - 10, node.height - 10, 8));
|
|
287
|
+
innerRect.setAttribute('fill', 'none');
|
|
288
|
+
innerRect.setAttribute('stroke', palette.foreground);
|
|
289
|
+
innerRect.setAttribute('stroke-width', '1.5');
|
|
290
|
+
g.appendChild(innerRect);
|
|
291
|
+
break;
|
|
292
|
+
default:
|
|
293
|
+
this.renderRoundedRect(doc, g, node.width, node.height, fillColor, 5);
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
// Add label
|
|
297
|
+
const text = doc.createElementNS(ns, 'text');
|
|
298
|
+
text.setAttribute('class', 'node-text');
|
|
299
|
+
text.setAttribute('y', '0');
|
|
300
|
+
text.textContent = node.label;
|
|
301
|
+
g.appendChild(text);
|
|
302
|
+
svg.appendChild(g);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Gets color index for node kind
|
|
306
|
+
*/
|
|
307
|
+
getNodeColorIndex(kind) {
|
|
308
|
+
const kindMap = {
|
|
309
|
+
start: 0,
|
|
310
|
+
end: 1,
|
|
311
|
+
process: 2,
|
|
312
|
+
decision: 3,
|
|
313
|
+
input: 4,
|
|
314
|
+
output: 5,
|
|
315
|
+
subprocess: 6,
|
|
316
|
+
};
|
|
317
|
+
return kindMap[kind] || 2;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Renders an ellipse shape
|
|
321
|
+
*/
|
|
322
|
+
renderEllipse(doc, g, width, height, fill) {
|
|
323
|
+
const ns = g.namespaceURI;
|
|
324
|
+
const ellipse = doc.createElementNS(ns, 'ellipse');
|
|
325
|
+
ellipse.setAttribute('cx', '0');
|
|
326
|
+
ellipse.setAttribute('cy', '0');
|
|
327
|
+
ellipse.setAttribute('rx', String(width / 2));
|
|
328
|
+
ellipse.setAttribute('ry', String(height / 2));
|
|
329
|
+
ellipse.setAttribute('fill', fill);
|
|
330
|
+
ellipse.setAttribute('stroke', '#333');
|
|
331
|
+
ellipse.setAttribute('stroke-width', '2');
|
|
332
|
+
g.appendChild(ellipse);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Renders a diamond shape
|
|
336
|
+
*/
|
|
337
|
+
renderDiamond(doc, g, width, height, fill) {
|
|
338
|
+
const ns = g.namespaceURI;
|
|
339
|
+
const path = doc.createElementNS(ns, 'path');
|
|
340
|
+
const w = width / 2;
|
|
341
|
+
const h = height / 2;
|
|
342
|
+
const d = `M 0,${-h} L ${w},0 L 0,${h} L ${-w},0 Z`;
|
|
343
|
+
path.setAttribute('d', d);
|
|
344
|
+
path.setAttribute('fill', fill);
|
|
345
|
+
path.setAttribute('stroke', '#333');
|
|
346
|
+
path.setAttribute('stroke-width', '2');
|
|
347
|
+
g.appendChild(path);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Renders a rounded rectangle
|
|
351
|
+
*/
|
|
352
|
+
renderRoundedRect(doc, g, width, height, fill, radius) {
|
|
353
|
+
const ns = g.namespaceURI;
|
|
354
|
+
const path = doc.createElementNS(ns, 'path');
|
|
355
|
+
path.setAttribute('d', svg_utils_1.SVGUtils.roundedRectPath(-width / 2, -height / 2, width, height, radius));
|
|
356
|
+
path.setAttribute('fill', fill);
|
|
357
|
+
path.setAttribute('stroke', '#333');
|
|
358
|
+
path.setAttribute('stroke-width', '2');
|
|
359
|
+
g.appendChild(path);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Renders a flow edge
|
|
363
|
+
*/
|
|
364
|
+
renderFlowEdge(doc, svg, edge, palette) {
|
|
365
|
+
const ns = svg.namespaceURI;
|
|
366
|
+
const g = doc.createElementNS(ns, 'g');
|
|
367
|
+
// Create path from points
|
|
368
|
+
const pathData = edge.points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x},${p.y}`).join(' ');
|
|
369
|
+
const path = doc.createElementNS(ns, 'path');
|
|
370
|
+
path.setAttribute('d', pathData);
|
|
371
|
+
path.setAttribute('class', 'edge-line');
|
|
372
|
+
if (edge.dashed) {
|
|
373
|
+
path.setAttribute('stroke-dasharray', '5,5');
|
|
374
|
+
}
|
|
375
|
+
// Add arrow marker
|
|
376
|
+
const markerId = svg_utils_1.SVGUtils.addArrowMarker(svg, 'arrow-end', palette.foreground);
|
|
377
|
+
path.setAttribute('marker-end', markerId);
|
|
378
|
+
g.appendChild(path);
|
|
379
|
+
// Add label if present
|
|
380
|
+
if (edge.label) {
|
|
381
|
+
const midPoint = edge.points[Math.floor(edge.points.length / 2)];
|
|
382
|
+
const text = doc.createElementNS(ns, 'text');
|
|
383
|
+
text.setAttribute('x', String(midPoint.x));
|
|
384
|
+
text.setAttribute('y', String(midPoint.y - 5));
|
|
385
|
+
text.setAttribute('class', 'edge-label');
|
|
386
|
+
text.textContent = edge.label;
|
|
387
|
+
g.appendChild(text);
|
|
388
|
+
}
|
|
389
|
+
svg.appendChild(g);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Renders an org chart using d3-hierarchy
|
|
393
|
+
*/
|
|
394
|
+
async renderOrgChart(params, viewBox, branding, title) {
|
|
395
|
+
// Parse org tree
|
|
396
|
+
const nodesParam = this.getParamValue(params, 'Nodes');
|
|
397
|
+
if (!nodesParam) {
|
|
398
|
+
throw new Error('Nodes parameter is required for org charts');
|
|
399
|
+
}
|
|
400
|
+
const rootNode = this.parseJSON(nodesParam, 'Nodes');
|
|
401
|
+
// Create hierarchy
|
|
402
|
+
const hierarchy = d3Hierarchy.hierarchy(rootNode);
|
|
403
|
+
// Create tree layout
|
|
404
|
+
const vb = svg_utils_1.SVGUtils.calculateViewBox(viewBox);
|
|
405
|
+
const treeLayout = d3Hierarchy.tree().size([vb.contentWidth, vb.contentHeight]);
|
|
406
|
+
// Calculate layout
|
|
407
|
+
const treeData = treeLayout(hierarchy);
|
|
408
|
+
// Create SVG
|
|
409
|
+
const doc = svg_utils_1.SVGUtils.createSVG(viewBox.width, viewBox.height, 'org');
|
|
410
|
+
const svg = doc.querySelector('svg');
|
|
411
|
+
// Add accessibility
|
|
412
|
+
if (title) {
|
|
413
|
+
svg_utils_1.SVGUtils.addA11y(svg, {
|
|
414
|
+
title,
|
|
415
|
+
ariaRole: 'img',
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
// Add styles
|
|
419
|
+
const css = (0, svg_theming_1.generateCSS)(branding);
|
|
420
|
+
svg_utils_1.SVGUtils.addStyles(svg, css);
|
|
421
|
+
// Get palette
|
|
422
|
+
const palette = (0, svg_theming_1.getPalette)(branding.palette);
|
|
423
|
+
// Create container group with offset for padding
|
|
424
|
+
const container = doc.createElementNS(svg.namespaceURI, 'g');
|
|
425
|
+
container.setAttribute('transform', `translate(${vb.x}, ${vb.y})`);
|
|
426
|
+
svg.appendChild(container);
|
|
427
|
+
// Render links first (so they appear behind nodes)
|
|
428
|
+
treeData.links().forEach((link) => {
|
|
429
|
+
this.renderOrgLink(doc, container, link, palette);
|
|
430
|
+
});
|
|
431
|
+
// Render nodes
|
|
432
|
+
treeData.descendants().forEach((node) => {
|
|
433
|
+
this.renderOrgNode(doc, container, node, palette);
|
|
434
|
+
});
|
|
435
|
+
// Add title if present
|
|
436
|
+
if (title) {
|
|
437
|
+
this.addTitle(doc, svg, title, vb.width, (0, svg_theming_1.getFontSpec)(branding.font));
|
|
438
|
+
}
|
|
439
|
+
// Sanitize and return
|
|
440
|
+
return svg_utils_1.SVGUtils.sanitizeSVG(svg.outerHTML);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Renders an org chart link
|
|
444
|
+
*/
|
|
445
|
+
renderOrgLink(doc, container, link, palette) {
|
|
446
|
+
const ns = container.namespaceURI;
|
|
447
|
+
const path = doc.createElementNS(ns, 'path');
|
|
448
|
+
// Create elbow connector
|
|
449
|
+
const d = `M ${link.source.x},${link.source.y + 35}
|
|
450
|
+
L ${link.source.x},${(link.source.y + link.target.y) / 2}
|
|
451
|
+
L ${link.target.x},${(link.source.y + link.target.y) / 2}
|
|
452
|
+
L ${link.target.x},${link.target.y - 35}`;
|
|
453
|
+
path.setAttribute('d', d);
|
|
454
|
+
path.setAttribute('fill', 'none');
|
|
455
|
+
path.setAttribute('stroke', palette.foreground);
|
|
456
|
+
path.setAttribute('stroke-width', '2');
|
|
457
|
+
path.setAttribute('opacity', '0.6');
|
|
458
|
+
container.appendChild(path);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Renders an org chart node
|
|
462
|
+
*/
|
|
463
|
+
renderOrgNode(doc, container, node, palette) {
|
|
464
|
+
const ns = container.namespaceURI;
|
|
465
|
+
const g = doc.createElementNS(ns, 'g');
|
|
466
|
+
g.setAttribute('transform', `translate(${node.x}, ${node.y})`);
|
|
467
|
+
const boxWidth = 180;
|
|
468
|
+
const boxHeight = 70;
|
|
469
|
+
// Determine color based on depth
|
|
470
|
+
const colorIndex = node.depth % palette.categorical.length;
|
|
471
|
+
const fillColor = palette.categorical[colorIndex];
|
|
472
|
+
// Render box
|
|
473
|
+
const rect = doc.createElementNS(ns, 'rect');
|
|
474
|
+
rect.setAttribute('x', String(-boxWidth / 2));
|
|
475
|
+
rect.setAttribute('y', String(-boxHeight / 2));
|
|
476
|
+
rect.setAttribute('width', String(boxWidth));
|
|
477
|
+
rect.setAttribute('height', String(boxHeight));
|
|
478
|
+
rect.setAttribute('fill', fillColor);
|
|
479
|
+
rect.setAttribute('stroke', '#333');
|
|
480
|
+
rect.setAttribute('stroke-width', '2');
|
|
481
|
+
rect.setAttribute('rx', '8');
|
|
482
|
+
if (node.data.highlight) {
|
|
483
|
+
rect.setAttribute('stroke', '#FFD700');
|
|
484
|
+
rect.setAttribute('stroke-width', '4');
|
|
485
|
+
}
|
|
486
|
+
g.appendChild(rect);
|
|
487
|
+
// Add avatar circle if avatarUrl present
|
|
488
|
+
if (node.data.avatarUrl) {
|
|
489
|
+
const avatar = doc.createElementNS(ns, 'circle');
|
|
490
|
+
avatar.setAttribute('cx', '0');
|
|
491
|
+
avatar.setAttribute('cy', String(-boxHeight / 2 + 20));
|
|
492
|
+
avatar.setAttribute('r', '15');
|
|
493
|
+
avatar.setAttribute('fill', '#FFF');
|
|
494
|
+
avatar.setAttribute('stroke', '#333');
|
|
495
|
+
g.appendChild(avatar);
|
|
496
|
+
}
|
|
497
|
+
// Add name
|
|
498
|
+
const nameText = doc.createElementNS(ns, 'text');
|
|
499
|
+
nameText.setAttribute('y', node.data.avatarUrl ? '5' : '-8');
|
|
500
|
+
nameText.setAttribute('text-anchor', 'middle');
|
|
501
|
+
nameText.setAttribute('font-weight', 'bold');
|
|
502
|
+
nameText.setAttribute('font-size', '14');
|
|
503
|
+
nameText.setAttribute('fill', '#FFF');
|
|
504
|
+
nameText.textContent = node.data.label;
|
|
505
|
+
g.appendChild(nameText);
|
|
506
|
+
// Add role if present
|
|
507
|
+
if (node.data.role) {
|
|
508
|
+
const roleText = doc.createElementNS(ns, 'text');
|
|
509
|
+
roleText.setAttribute('y', node.data.avatarUrl ? '20' : '8');
|
|
510
|
+
roleText.setAttribute('text-anchor', 'middle');
|
|
511
|
+
roleText.setAttribute('font-size', '12');
|
|
512
|
+
roleText.setAttribute('fill', '#FFF');
|
|
513
|
+
roleText.setAttribute('opacity', '0.9');
|
|
514
|
+
roleText.textContent = node.data.role;
|
|
515
|
+
g.appendChild(roleText);
|
|
516
|
+
}
|
|
517
|
+
container.appendChild(g);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Renders an ER diagram using dagre layout
|
|
521
|
+
*/
|
|
522
|
+
async renderERDiagram(params, viewBox, branding, title, seed) {
|
|
523
|
+
// Parse tables and relations
|
|
524
|
+
const nodesParam = this.getParamValue(params, 'Nodes');
|
|
525
|
+
const edgesParam = this.getParamValue(params, 'Edges');
|
|
526
|
+
if (!nodesParam) {
|
|
527
|
+
throw new Error('Nodes parameter is required for ER diagrams');
|
|
528
|
+
}
|
|
529
|
+
const tables = this.parseJSON(nodesParam, 'Nodes');
|
|
530
|
+
const relations = edgesParam ? this.parseJSON(edgesParam, 'Edges') : [];
|
|
531
|
+
// Create dagre graph
|
|
532
|
+
const g = new dagre.graphlib.Graph();
|
|
533
|
+
g.setGraph({
|
|
534
|
+
rankdir: 'TB',
|
|
535
|
+
nodesep: 60,
|
|
536
|
+
ranksep: 80,
|
|
537
|
+
marginx: 40,
|
|
538
|
+
marginy: 40,
|
|
539
|
+
});
|
|
540
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
541
|
+
// Add tables as nodes
|
|
542
|
+
for (const table of tables) {
|
|
543
|
+
const height = 40 + table.attrs.length * 25; // Header + rows
|
|
544
|
+
const maxAttrWidth = Math.max(...table.attrs.map((a) => svg_utils_1.SVGUtils.estimateTextWidth(`${a.name}: ${a.type || ''}`, 12)));
|
|
545
|
+
const width = Math.max(200, maxAttrWidth + 80);
|
|
546
|
+
g.setNode(table.id, {
|
|
547
|
+
...table,
|
|
548
|
+
width,
|
|
549
|
+
height,
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
// Add relations as edges
|
|
553
|
+
for (const rel of relations) {
|
|
554
|
+
g.setEdge(rel.from, rel.to, rel);
|
|
555
|
+
}
|
|
556
|
+
// Run dagre layout
|
|
557
|
+
dagre.layout(g);
|
|
558
|
+
// Create SVG
|
|
559
|
+
const vb = svg_utils_1.SVGUtils.calculateViewBox(viewBox);
|
|
560
|
+
const doc = svg_utils_1.SVGUtils.createSVG(viewBox.width, viewBox.height, 'er');
|
|
561
|
+
const svg = doc.querySelector('svg');
|
|
562
|
+
// Add accessibility
|
|
563
|
+
if (title) {
|
|
564
|
+
svg_utils_1.SVGUtils.addA11y(svg, {
|
|
565
|
+
title,
|
|
566
|
+
ariaRole: 'img',
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
// Add styles
|
|
570
|
+
const css = (0, svg_theming_1.generateCSS)(branding);
|
|
571
|
+
svg_utils_1.SVGUtils.addStyles(svg, css);
|
|
572
|
+
// Get palette
|
|
573
|
+
const palette = (0, svg_theming_1.getPalette)(branding.palette);
|
|
574
|
+
// Render tables
|
|
575
|
+
for (const tableId of g.nodes()) {
|
|
576
|
+
const table = g.node(tableId);
|
|
577
|
+
this.renderERTable(doc, svg, table, palette);
|
|
578
|
+
}
|
|
579
|
+
// Render relations
|
|
580
|
+
for (const edgeObj of g.edges()) {
|
|
581
|
+
const rel = g.edge(edgeObj);
|
|
582
|
+
this.renderERRelation(doc, svg, rel, palette);
|
|
583
|
+
}
|
|
584
|
+
// Add title if present
|
|
585
|
+
if (title) {
|
|
586
|
+
this.addTitle(doc, svg, title, vb.width, (0, svg_theming_1.getFontSpec)(branding.font));
|
|
587
|
+
}
|
|
588
|
+
// Sanitize and return
|
|
589
|
+
return svg_utils_1.SVGUtils.sanitizeSVG(svg.outerHTML);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Renders an ER table
|
|
593
|
+
*/
|
|
594
|
+
renderERTable(doc, svg, table, palette) {
|
|
595
|
+
const ns = svg.namespaceURI;
|
|
596
|
+
const g = doc.createElementNS(ns, 'g');
|
|
597
|
+
g.setAttribute('id', table.id);
|
|
598
|
+
g.setAttribute('transform', `translate(${table.x - table.width / 2}, ${table.y - table.height / 2})`);
|
|
599
|
+
// Render table box
|
|
600
|
+
const rect = doc.createElementNS(ns, 'rect');
|
|
601
|
+
rect.setAttribute('x', '0');
|
|
602
|
+
rect.setAttribute('y', '0');
|
|
603
|
+
rect.setAttribute('width', String(table.width));
|
|
604
|
+
rect.setAttribute('height', String(table.height));
|
|
605
|
+
rect.setAttribute('fill', palette.background);
|
|
606
|
+
rect.setAttribute('stroke', palette.foreground);
|
|
607
|
+
rect.setAttribute('stroke-width', '2');
|
|
608
|
+
g.appendChild(rect);
|
|
609
|
+
// Render header
|
|
610
|
+
const headerRect = doc.createElementNS(ns, 'rect');
|
|
611
|
+
headerRect.setAttribute('x', '0');
|
|
612
|
+
headerRect.setAttribute('y', '0');
|
|
613
|
+
headerRect.setAttribute('width', String(table.width));
|
|
614
|
+
headerRect.setAttribute('height', '40');
|
|
615
|
+
headerRect.setAttribute('fill', palette.categorical[0]);
|
|
616
|
+
g.appendChild(headerRect);
|
|
617
|
+
// Header text
|
|
618
|
+
const headerText = doc.createElementNS(ns, 'text');
|
|
619
|
+
headerText.setAttribute('x', String(table.width / 2));
|
|
620
|
+
headerText.setAttribute('y', '25');
|
|
621
|
+
headerText.setAttribute('text-anchor', 'middle');
|
|
622
|
+
headerText.setAttribute('font-weight', 'bold');
|
|
623
|
+
headerText.setAttribute('font-size', '14');
|
|
624
|
+
headerText.setAttribute('fill', '#FFF');
|
|
625
|
+
headerText.textContent = table.name;
|
|
626
|
+
g.appendChild(headerText);
|
|
627
|
+
// Render attributes
|
|
628
|
+
let yOffset = 40;
|
|
629
|
+
for (let i = 0; i < table.attrs.length; i++) {
|
|
630
|
+
const attr = table.attrs[i];
|
|
631
|
+
// Alternating row colors
|
|
632
|
+
if (i % 2 === 1) {
|
|
633
|
+
const rowRect = doc.createElementNS(ns, 'rect');
|
|
634
|
+
rowRect.setAttribute('x', '0');
|
|
635
|
+
rowRect.setAttribute('y', String(yOffset));
|
|
636
|
+
rowRect.setAttribute('width', String(table.width));
|
|
637
|
+
rowRect.setAttribute('height', '25');
|
|
638
|
+
rowRect.setAttribute('fill', '#F5F5F5');
|
|
639
|
+
g.appendChild(rowRect);
|
|
640
|
+
}
|
|
641
|
+
// Attribute text
|
|
642
|
+
const attrText = doc.createElementNS(ns, 'text');
|
|
643
|
+
attrText.setAttribute('x', '10');
|
|
644
|
+
attrText.setAttribute('y', String(yOffset + 17));
|
|
645
|
+
attrText.setAttribute('font-size', '12');
|
|
646
|
+
attrText.setAttribute('fill', palette.foreground);
|
|
647
|
+
let label = attr.name;
|
|
648
|
+
if (attr.pk)
|
|
649
|
+
label = '🔑 ' + label;
|
|
650
|
+
else if (attr.fk)
|
|
651
|
+
label = '🔗 ' + label;
|
|
652
|
+
if (attr.type)
|
|
653
|
+
label += `: ${attr.type}`;
|
|
654
|
+
attrText.textContent = label;
|
|
655
|
+
g.appendChild(attrText);
|
|
656
|
+
yOffset += 25;
|
|
657
|
+
}
|
|
658
|
+
svg.appendChild(g);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Renders an ER relation
|
|
662
|
+
*/
|
|
663
|
+
renderERRelation(doc, svg, rel, palette) {
|
|
664
|
+
const ns = svg.namespaceURI;
|
|
665
|
+
const g = doc.createElementNS(ns, 'g');
|
|
666
|
+
// Create path from points
|
|
667
|
+
const pathData = rel.points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x},${p.y}`).join(' ');
|
|
668
|
+
const path = doc.createElementNS(ns, 'path');
|
|
669
|
+
path.setAttribute('d', pathData);
|
|
670
|
+
path.setAttribute('class', 'edge-line');
|
|
671
|
+
path.setAttribute('stroke-dasharray', '5,5');
|
|
672
|
+
g.appendChild(path);
|
|
673
|
+
// Add cardinality label if present
|
|
674
|
+
if (rel.label) {
|
|
675
|
+
const midPoint = rel.points[Math.floor(rel.points.length / 2)];
|
|
676
|
+
const text = doc.createElementNS(ns, 'text');
|
|
677
|
+
text.setAttribute('x', String(midPoint.x));
|
|
678
|
+
text.setAttribute('y', String(midPoint.y - 5));
|
|
679
|
+
text.setAttribute('class', 'edge-label');
|
|
680
|
+
text.setAttribute('fill', palette.foreground);
|
|
681
|
+
text.setAttribute('font-size', '11');
|
|
682
|
+
text.textContent = rel.label;
|
|
683
|
+
g.appendChild(text);
|
|
684
|
+
}
|
|
685
|
+
svg.appendChild(g);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Adds a title to the SVG
|
|
689
|
+
*/
|
|
690
|
+
addTitle(doc, svg, title, width, font) {
|
|
691
|
+
const ns = svg.namespaceURI;
|
|
692
|
+
const text = doc.createElementNS(ns, 'text');
|
|
693
|
+
text.setAttribute('x', String(width / 2));
|
|
694
|
+
text.setAttribute('y', '25');
|
|
695
|
+
text.setAttribute('text-anchor', 'middle');
|
|
696
|
+
text.setAttribute('font-family', font.family);
|
|
697
|
+
text.setAttribute('font-size', String(font.size + 4));
|
|
698
|
+
text.setAttribute('font-weight', 'bold');
|
|
699
|
+
text.textContent = title;
|
|
700
|
+
svg.appendChild(text);
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Helper to safely parse JSON that might already be an object
|
|
704
|
+
*/
|
|
705
|
+
parseJSON(value, paramName) {
|
|
706
|
+
// If it's already an object/array, return it
|
|
707
|
+
if (typeof value === 'object' && value !== null) {
|
|
708
|
+
return value;
|
|
709
|
+
}
|
|
710
|
+
// If it's a string, parse it
|
|
711
|
+
if (typeof value === 'string') {
|
|
712
|
+
try {
|
|
713
|
+
return JSON.parse(value);
|
|
714
|
+
}
|
|
715
|
+
catch (error) {
|
|
716
|
+
throw new Error(`Parameter '${paramName}' contains invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
// For other types, error
|
|
720
|
+
throw new Error(`Parameter '${paramName}' must be a JSON string or object. Received ${typeof value}.`);
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Helper to ensure a parameter value is a string, with type conversion and validation
|
|
724
|
+
*/
|
|
725
|
+
ensureString(value, paramName) {
|
|
726
|
+
if (value == null) {
|
|
727
|
+
return '';
|
|
728
|
+
}
|
|
729
|
+
if (typeof value === 'string') {
|
|
730
|
+
return value;
|
|
731
|
+
}
|
|
732
|
+
// Convert numbers and booleans to strings
|
|
733
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
734
|
+
return String(value);
|
|
735
|
+
}
|
|
736
|
+
// For objects/arrays, reject with descriptive error
|
|
737
|
+
throw new Error(`Parameter '${paramName}' must be a string, number, or boolean. ` +
|
|
738
|
+
`Received ${typeof value}. If providing JSON data, ensure it's passed as a string.`);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Helper to get parameter value by name (case-insensitive)
|
|
742
|
+
*/
|
|
743
|
+
getParamValue(params, paramName) {
|
|
744
|
+
const param = params.Params.find((p) => p.Name.trim().toLowerCase() === paramName.toLowerCase());
|
|
745
|
+
if (param?.Value && typeof param.Value === 'string') {
|
|
746
|
+
return param?.Value?.trim() || null;
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
return param?.Value || null;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
exports.CreateSVGDiagramAction = CreateSVGDiagramAction;
|
|
754
|
+
exports.CreateSVGDiagramAction = CreateSVGDiagramAction = __decorate([
|
|
755
|
+
(0, global_1.RegisterClass)(actions_1.BaseAction, '__CreateSVGDiagram')
|
|
756
|
+
], CreateSVGDiagramAction);
|
|
757
|
+
/**
|
|
758
|
+
* Loader function to ensure the CreateSVGDiagramAction class is included in the bundle.
|
|
759
|
+
*/
|
|
760
|
+
function LoadCreateSVGDiagramAction() {
|
|
761
|
+
// this function is a stub that is used to force the bundler to include the above class in the final bundle and not tree shake them out
|
|
762
|
+
}
|
|
763
|
+
exports.LoadCreateSVGDiagramAction = LoadCreateSVGDiagramAction;
|
|
764
|
+
//# sourceMappingURL=create-svg-diagram.action.js.map
|