@graph-knowledge/api 0.3.2 → 0.9.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/package.json +1 -1
- package/src/index.d.ts +3 -2
- package/src/lib/clients/firebase-auth-client.d.ts +7 -0
- package/src/lib/clients/firebase-auth-client.js +20 -2
- package/src/lib/clients/firebase-firestore-client.js +83 -29
- package/src/lib/constants/element-defaults.js +1 -0
- package/src/lib/graph-knowledge-api.d.ts +21 -2
- package/src/lib/graph-knowledge-api.js +35 -5
- package/src/lib/interfaces/auth-client.interface.d.ts +10 -0
- package/src/lib/interfaces/custom-shape-operations.interface.d.ts +82 -0
- package/src/lib/interfaces/custom-shape-operations.interface.js +2 -0
- package/src/lib/interfaces/node-operations.interface.d.ts +29 -1
- package/src/lib/interfaces/template-operations.interface.d.ts +22 -1
- package/src/lib/operations/batch-operations.d.ts +3 -15
- package/src/lib/operations/batch-operations.js +8 -80
- package/src/lib/operations/custom-shape-operations.d.ts +27 -0
- package/src/lib/operations/custom-shape-operations.js +175 -0
- package/src/lib/operations/document-operations.js +9 -2
- package/src/lib/operations/element-operations.d.ts +3 -22
- package/src/lib/operations/element-operations.js +6 -119
- package/src/lib/operations/node-operations.d.ts +9 -3
- package/src/lib/operations/node-operations.js +18 -5
- package/src/lib/operations/template-operations.d.ts +3 -1
- package/src/lib/operations/template-operations.js +50 -7
- package/src/lib/testing/mock-auth-client.d.ts +2 -0
- package/src/lib/testing/mock-auth-client.js +7 -0
- package/src/lib/types/api-types.d.ts +113 -2
- package/src/lib/types/element-input-types.d.ts +67 -11
- package/src/lib/utils/element-builder.d.ts +63 -0
- package/src/lib/utils/element-builder.js +258 -0
- package/src/lib/utils/rotation.d.ts +4 -0
- package/src/lib/utils/rotation.js +13 -0
- package/src/lib/validators/custom-shape-definition-validator.d.ts +17 -0
- package/src/lib/validators/custom-shape-definition-validator.js +135 -0
- package/src/lib/validators/element-type-validators/base-element-validator.d.ts +4 -0
- package/src/lib/validators/element-type-validators/base-element-validator.js +30 -0
- package/src/lib/validators/element-type-validators/basic-shape-validators.js +2 -0
- package/src/lib/validators/element-type-validators/bezier-curve-validator.d.ts +12 -0
- package/src/lib/validators/element-type-validators/bezier-curve-validator.js +47 -0
- package/src/lib/validators/element-type-validators/block-arrow-validator.js +2 -0
- package/src/lib/validators/element-type-validators/line-validator.d.ts +1 -0
- package/src/lib/validators/element-type-validators/line-validator.js +12 -5
- package/src/lib/validators/element-type-validators/rectangle-validator.js +2 -0
- package/src/lib/validators/element-validator-registry.js +2 -0
- package/src/lib/validators/template-validator.d.ts +7 -1
- package/src/lib/validators/template-validator.js +21 -0
|
@@ -111,6 +111,40 @@ class TemplateOperations {
|
|
|
111
111
|
nodes
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
|
+
async update(templateId, input) {
|
|
115
|
+
this.auth.requireAuth();
|
|
116
|
+
await this.auth.requireAdmin();
|
|
117
|
+
this.validator.validateUpdate(input);
|
|
118
|
+
const docData = await this.firestore.getDocument(`documents/${templateId}`);
|
|
119
|
+
if (!docData) {
|
|
120
|
+
throw new api_errors_1.NotFoundError(`Template ${templateId} not found`);
|
|
121
|
+
}
|
|
122
|
+
if (!docData.isTemplate) {
|
|
123
|
+
throw new api_errors_1.NotFoundError(`Document ${templateId} is not a template`);
|
|
124
|
+
}
|
|
125
|
+
const updates = {};
|
|
126
|
+
if (input.title !== undefined)
|
|
127
|
+
updates.title = input.title;
|
|
128
|
+
if (input.content !== undefined)
|
|
129
|
+
updates.content = input.content;
|
|
130
|
+
if (Object.keys(updates).length > 0) {
|
|
131
|
+
await this.firestore.updateDocument(`documents/${templateId}`, updates);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async delete(templateId) {
|
|
135
|
+
this.auth.requireAuth();
|
|
136
|
+
await this.auth.requireAdmin();
|
|
137
|
+
const docData = await this.firestore.getDocument(`documents/${templateId}`);
|
|
138
|
+
if (!docData) {
|
|
139
|
+
throw new api_errors_1.NotFoundError(`Template ${templateId} not found`);
|
|
140
|
+
}
|
|
141
|
+
if (!docData.isTemplate) {
|
|
142
|
+
throw new api_errors_1.NotFoundError(`Document ${templateId} is not a template`);
|
|
143
|
+
}
|
|
144
|
+
await this.firestore.deleteDocument(`documents/${templateId}`);
|
|
145
|
+
// Note: Sub-collection nodes are not automatically deleted
|
|
146
|
+
// A Cloud Function should handle cascading deletion
|
|
147
|
+
}
|
|
114
148
|
async clone(templateId, title) {
|
|
115
149
|
const userId = this.auth.requireAuth();
|
|
116
150
|
// Require premium access for cloning
|
|
@@ -213,9 +247,13 @@ class TemplateOperations {
|
|
|
213
247
|
level: node.level,
|
|
214
248
|
owner: userId
|
|
215
249
|
};
|
|
216
|
-
//
|
|
250
|
+
// Remap parentNodeId. Drop if the parent doesn't exist in the mapping
|
|
251
|
+
// (orphaned reference) rather than keeping stale IDs.
|
|
217
252
|
if (node.parentNodeId) {
|
|
218
|
-
|
|
253
|
+
const mappedParentId = idMapping.get(node.parentNodeId);
|
|
254
|
+
if (mappedParentId) {
|
|
255
|
+
clonedNode.parentNodeId = mappedParentId;
|
|
256
|
+
}
|
|
219
257
|
}
|
|
220
258
|
return clonedNode;
|
|
221
259
|
}
|
|
@@ -248,12 +286,17 @@ class TemplateOperations {
|
|
|
248
286
|
rotation: element.rotation,
|
|
249
287
|
properties: clonedProperties
|
|
250
288
|
};
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
clonedElement.isLink = element.isLink;
|
|
254
|
-
}
|
|
289
|
+
// Remap link target to new node ID. If the target doesn't exist in the
|
|
290
|
+
// mapping (e.g. orphaned link), drop the link rather than keeping stale IDs.
|
|
255
291
|
if (element.linkTarget) {
|
|
256
|
-
|
|
292
|
+
const mappedTarget = idMapping.get(element.linkTarget);
|
|
293
|
+
if (mappedTarget) {
|
|
294
|
+
clonedElement.isLink = element.isLink ?? true;
|
|
295
|
+
clonedElement.linkTarget = mappedTarget;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else if (element.isLink !== undefined) {
|
|
299
|
+
clonedElement.isLink = element.isLink;
|
|
257
300
|
}
|
|
258
301
|
return clonedElement;
|
|
259
302
|
}
|
|
@@ -12,6 +12,7 @@ export declare class MockAuthClient implements IAuthClient {
|
|
|
12
12
|
isAdmin?: boolean;
|
|
13
13
|
});
|
|
14
14
|
signIn(email: string, _password: string): Promise<void>;
|
|
15
|
+
signInWithCustomToken(_token: string): Promise<void>;
|
|
15
16
|
signOut(): Promise<void>;
|
|
16
17
|
get currentUserId(): string | null;
|
|
17
18
|
requireAuth(): string;
|
|
@@ -31,4 +32,5 @@ export declare class MockAuthClient implements IAuthClient {
|
|
|
31
32
|
* Sets the admin status for testing.
|
|
32
33
|
*/
|
|
33
34
|
setAdmin(isAdmin: boolean): void;
|
|
35
|
+
destroy(): void;
|
|
34
36
|
}
|
|
@@ -18,6 +18,10 @@ class MockAuthClient {
|
|
|
18
18
|
// Simulate successful sign-in
|
|
19
19
|
this._currentUserId = `mock-user-${email.split("@")[0]}`;
|
|
20
20
|
}
|
|
21
|
+
async signInWithCustomToken(_token) {
|
|
22
|
+
// Simulate successful custom token sign-in
|
|
23
|
+
this._currentUserId = this._currentUserId ?? "mock-custom-token-user";
|
|
24
|
+
}
|
|
21
25
|
async signOut() {
|
|
22
26
|
this._currentUserId = null;
|
|
23
27
|
}
|
|
@@ -66,5 +70,8 @@ class MockAuthClient {
|
|
|
66
70
|
setAdmin(isAdmin) {
|
|
67
71
|
this._isAdmin = isAdmin;
|
|
68
72
|
}
|
|
73
|
+
destroy() {
|
|
74
|
+
// No-op for mock
|
|
75
|
+
}
|
|
69
76
|
}
|
|
70
77
|
exports.MockAuthClient = MockAuthClient;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Document, GraphNode } from "../models";
|
|
1
|
+
import { Document, GraphElement, GraphNode } from "../models";
|
|
2
|
+
import { AnyElementInput } from "./element-input-types";
|
|
2
3
|
/**
|
|
3
4
|
* Input for creating a new document.
|
|
4
5
|
*/
|
|
@@ -22,10 +23,13 @@ export interface UpdateDocumentInput {
|
|
|
22
23
|
content?: string;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
|
-
* Result of document operations
|
|
26
|
+
* Result of document operations.
|
|
27
|
+
* Always includes `id` and `rootNodeId` — every document has a root node created at document creation time.
|
|
28
|
+
* Use `rootNodeId` to add elements directly to the document's root canvas.
|
|
26
29
|
*/
|
|
27
30
|
export type DocumentResult = Document & {
|
|
28
31
|
id: string;
|
|
32
|
+
rootNodeId: string;
|
|
29
33
|
};
|
|
30
34
|
/**
|
|
31
35
|
* Input for creating a new node.
|
|
@@ -59,6 +63,22 @@ export interface UpdateNodeInput {
|
|
|
59
63
|
export type NodeResult = GraphNode & {
|
|
60
64
|
id: string;
|
|
61
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Input for creating a node with all its elements in a single atomic operation.
|
|
68
|
+
*/
|
|
69
|
+
export interface CreateNodeWithElementsInput extends CreateNodeInput {
|
|
70
|
+
/** Elements to create within the node */
|
|
71
|
+
elements: AnyElementInput[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Result of creating a node with elements.
|
|
75
|
+
*/
|
|
76
|
+
export interface CreateNodeWithElementsResult {
|
|
77
|
+
/** The created node (includes elements in its elements array) */
|
|
78
|
+
node: GraphNode;
|
|
79
|
+
/** The created elements with their generated IDs */
|
|
80
|
+
elements: GraphElement[];
|
|
81
|
+
}
|
|
62
82
|
/**
|
|
63
83
|
* Input for creating a new template (admin only).
|
|
64
84
|
*/
|
|
@@ -74,3 +94,94 @@ export interface CreateTemplateInput {
|
|
|
74
94
|
/** Whether to publish immediately (defaults to false - draft) */
|
|
75
95
|
isPublished?: boolean;
|
|
76
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Input for updating an existing template (admin only).
|
|
99
|
+
*/
|
|
100
|
+
export interface UpdateTemplateInput {
|
|
101
|
+
title?: string;
|
|
102
|
+
content?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* ViewBox configuration for SVG scaling.
|
|
106
|
+
*/
|
|
107
|
+
export interface ViewBoxInput {
|
|
108
|
+
minX: number;
|
|
109
|
+
minY: number;
|
|
110
|
+
width: number;
|
|
111
|
+
height: number;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Input for creating a new custom shape.
|
|
115
|
+
*/
|
|
116
|
+
export interface CreateCustomShapeInput {
|
|
117
|
+
/** Shape display name (required) */
|
|
118
|
+
name: string;
|
|
119
|
+
/** Optional description for the store listing */
|
|
120
|
+
description?: string;
|
|
121
|
+
/** Material icon name for the toolbar button (defaults to "category") */
|
|
122
|
+
icon?: string;
|
|
123
|
+
/** Category for toolbar grouping (defaults to "Custom") */
|
|
124
|
+
category?: string;
|
|
125
|
+
/** The SVG path "d" attribute (required) */
|
|
126
|
+
svgPathData: string;
|
|
127
|
+
/** ViewBox for proper SVG scaling (required) */
|
|
128
|
+
viewBox: ViewBoxInput;
|
|
129
|
+
/** Default width when element is created (defaults to 120) */
|
|
130
|
+
defaultWidth?: number;
|
|
131
|
+
/** Default height when element is created (defaults to 120) */
|
|
132
|
+
defaultHeight?: number;
|
|
133
|
+
/** If true, aspect ratio is preserved on resize */
|
|
134
|
+
aspectRatioLocked?: boolean;
|
|
135
|
+
/** Default property values for new elements */
|
|
136
|
+
defaultProperties?: {
|
|
137
|
+
fillColor?: string;
|
|
138
|
+
strokeColor?: string;
|
|
139
|
+
strokeWidth?: number;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Input for updating an existing custom shape.
|
|
144
|
+
*/
|
|
145
|
+
export interface UpdateCustomShapeInput {
|
|
146
|
+
name?: string;
|
|
147
|
+
description?: string;
|
|
148
|
+
icon?: string;
|
|
149
|
+
category?: string;
|
|
150
|
+
svgPathData?: string;
|
|
151
|
+
viewBox?: ViewBoxInput;
|
|
152
|
+
defaultWidth?: number;
|
|
153
|
+
defaultHeight?: number;
|
|
154
|
+
aspectRatioLocked?: boolean;
|
|
155
|
+
defaultProperties?: {
|
|
156
|
+
fillColor?: string;
|
|
157
|
+
strokeColor?: string;
|
|
158
|
+
strokeWidth?: number;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Result of custom shape operations.
|
|
163
|
+
*/
|
|
164
|
+
export interface CustomShapeResult {
|
|
165
|
+
id: string;
|
|
166
|
+
name: string;
|
|
167
|
+
description?: string;
|
|
168
|
+
icon: string;
|
|
169
|
+
category: string;
|
|
170
|
+
authorId: string;
|
|
171
|
+
authorDisplayName?: string;
|
|
172
|
+
status: "draft" | "published";
|
|
173
|
+
createdAt: Date;
|
|
174
|
+
updatedAt?: Date;
|
|
175
|
+
publishedAt?: Date;
|
|
176
|
+
svgPathData: string;
|
|
177
|
+
viewBox: ViewBoxInput;
|
|
178
|
+
defaultWidth: number;
|
|
179
|
+
defaultHeight: number;
|
|
180
|
+
aspectRatioLocked?: boolean;
|
|
181
|
+
defaultProperties: {
|
|
182
|
+
fillColor: string;
|
|
183
|
+
strokeColor: string;
|
|
184
|
+
strokeWidth: number;
|
|
185
|
+
};
|
|
186
|
+
schemaVersion: number;
|
|
187
|
+
}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Common properties for all element inputs.
|
|
3
|
+
*
|
|
4
|
+
* Position can be specified as either x/y (top-left) or centerX/centerY (center point).
|
|
5
|
+
* When centerX/centerY are used, x/y are computed as `centerX - width/2` and `centerY - height/2`.
|
|
6
|
+
* You cannot specify both x and centerX, or both y and centerY.
|
|
3
7
|
*/
|
|
4
8
|
export interface BaseElementInput {
|
|
5
|
-
/** X position on canvas */
|
|
6
|
-
x
|
|
7
|
-
/** Y position on canvas */
|
|
8
|
-
y
|
|
9
|
+
/** X position on canvas (top-left corner). Cannot be used with centerX. */
|
|
10
|
+
x?: number;
|
|
11
|
+
/** Y position on canvas (top-left corner). Cannot be used with centerY. */
|
|
12
|
+
y?: number;
|
|
13
|
+
/** Center X position. Computes x as centerX - width/2. Cannot be used with x. */
|
|
14
|
+
centerX?: number;
|
|
15
|
+
/** Center Y position. Computes y as centerY - height/2. Cannot be used with y. */
|
|
16
|
+
centerY?: number;
|
|
9
17
|
/** Element width (uses default if not specified) */
|
|
10
18
|
width?: number;
|
|
11
19
|
/** Element height (uses default if not specified) */
|
|
@@ -17,10 +25,26 @@ export interface BaseElementInput {
|
|
|
17
25
|
/** Target node ID when isLink is true */
|
|
18
26
|
linkTarget?: string;
|
|
19
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Optional text label properties for basic shapes.
|
|
30
|
+
* Supported by: rectangle, triangle, diamond, hexagon, ellipse, block-arrow.
|
|
31
|
+
*/
|
|
32
|
+
export interface ShapeTextLabelProperties {
|
|
33
|
+
/** Text label displayed inside the shape */
|
|
34
|
+
text?: string;
|
|
35
|
+
/** Font size in pixels (default: 14) */
|
|
36
|
+
fontSize?: number;
|
|
37
|
+
/** Text color (hex, e.g., "#000000") */
|
|
38
|
+
textColor?: string;
|
|
39
|
+
/** Horizontal text alignment */
|
|
40
|
+
textAlign?: "left" | "center" | "right";
|
|
41
|
+
/** Vertical text alignment */
|
|
42
|
+
verticalAlign?: "top" | "middle" | "bottom";
|
|
43
|
+
}
|
|
20
44
|
/**
|
|
21
45
|
* Input for creating a rectangle element.
|
|
22
46
|
*/
|
|
23
|
-
export interface RectangleInput extends BaseElementInput {
|
|
47
|
+
export interface RectangleInput extends BaseElementInput, ShapeTextLabelProperties {
|
|
24
48
|
type: "rectangle";
|
|
25
49
|
/** Fill color (hex, e.g., "#FF5733") */
|
|
26
50
|
fillColor?: string;
|
|
@@ -206,7 +230,7 @@ export interface UmlNoteInput extends BaseElementInput {
|
|
|
206
230
|
/**
|
|
207
231
|
* Input for creating a triangle element.
|
|
208
232
|
*/
|
|
209
|
-
export interface TriangleInput extends BaseElementInput {
|
|
233
|
+
export interface TriangleInput extends BaseElementInput, ShapeTextLabelProperties {
|
|
210
234
|
type: "triangle";
|
|
211
235
|
/** Fill color (hex, e.g., "#FF5733") */
|
|
212
236
|
fillColor?: string;
|
|
@@ -218,7 +242,7 @@ export interface TriangleInput extends BaseElementInput {
|
|
|
218
242
|
/**
|
|
219
243
|
* Input for creating a diamond element.
|
|
220
244
|
*/
|
|
221
|
-
export interface DiamondInput extends BaseElementInput {
|
|
245
|
+
export interface DiamondInput extends BaseElementInput, ShapeTextLabelProperties {
|
|
222
246
|
type: "diamond";
|
|
223
247
|
/** Fill color (hex, e.g., "#FF5733") */
|
|
224
248
|
fillColor?: string;
|
|
@@ -230,7 +254,7 @@ export interface DiamondInput extends BaseElementInput {
|
|
|
230
254
|
/**
|
|
231
255
|
* Input for creating a hexagon element.
|
|
232
256
|
*/
|
|
233
|
-
export interface HexagonInput extends BaseElementInput {
|
|
257
|
+
export interface HexagonInput extends BaseElementInput, ShapeTextLabelProperties {
|
|
234
258
|
type: "hexagon";
|
|
235
259
|
/** Fill color (hex, e.g., "#FF5733") */
|
|
236
260
|
fillColor?: string;
|
|
@@ -242,7 +266,7 @@ export interface HexagonInput extends BaseElementInput {
|
|
|
242
266
|
/**
|
|
243
267
|
* Input for creating an ellipse element.
|
|
244
268
|
*/
|
|
245
|
-
export interface EllipseInput extends BaseElementInput {
|
|
269
|
+
export interface EllipseInput extends BaseElementInput, ShapeTextLabelProperties {
|
|
246
270
|
type: "ellipse";
|
|
247
271
|
/** Fill color (hex, e.g., "#FF5733") */
|
|
248
272
|
fillColor?: string;
|
|
@@ -262,6 +286,38 @@ export interface LineInput extends BaseElementInput {
|
|
|
262
286
|
strokeWidth?: number;
|
|
263
287
|
/** Line style (reuses LineStyle from connectors) */
|
|
264
288
|
lineStyle?: LineStyle;
|
|
289
|
+
/** Marker at start of line */
|
|
290
|
+
startMarker?: MarkerType;
|
|
291
|
+
/** Marker at end of line */
|
|
292
|
+
endMarker?: MarkerType;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Input for creating a cubic bezier curve element.
|
|
296
|
+
*
|
|
297
|
+
* The curve is defined by two endpoints and two control points:
|
|
298
|
+
* - Start point: (x, y)
|
|
299
|
+
* - End point: (x + width, y + height)
|
|
300
|
+
* - Control point 1: offset from start (controlPoint1X, controlPoint1Y)
|
|
301
|
+
* - Control point 2: offset from end (controlPoint2X, controlPoint2Y)
|
|
302
|
+
*
|
|
303
|
+
* If control points are omitted, a default S-curve is computed.
|
|
304
|
+
*/
|
|
305
|
+
export interface BezierCurveInput extends BaseElementInput {
|
|
306
|
+
type: "bezier-curve";
|
|
307
|
+
/** Stroke color (hex) */
|
|
308
|
+
strokeColor?: string;
|
|
309
|
+
/** Stroke width in pixels */
|
|
310
|
+
strokeWidth?: number;
|
|
311
|
+
/** Line style */
|
|
312
|
+
lineStyle?: LineStyle;
|
|
313
|
+
/** Control point 1 X offset from start */
|
|
314
|
+
controlPoint1X?: number;
|
|
315
|
+
/** Control point 1 Y offset from start */
|
|
316
|
+
controlPoint1Y?: number;
|
|
317
|
+
/** Control point 2 X offset from end */
|
|
318
|
+
controlPoint2X?: number;
|
|
319
|
+
/** Control point 2 Y offset from end */
|
|
320
|
+
controlPoint2Y?: number;
|
|
265
321
|
}
|
|
266
322
|
/**
|
|
267
323
|
* Direction for block arrow elements.
|
|
@@ -270,7 +326,7 @@ export type BlockArrowDirection = "right" | "left" | "up" | "down";
|
|
|
270
326
|
/**
|
|
271
327
|
* Input for creating a block arrow element.
|
|
272
328
|
*/
|
|
273
|
-
export interface BlockArrowInput extends BaseElementInput {
|
|
329
|
+
export interface BlockArrowInput extends BaseElementInput, ShapeTextLabelProperties {
|
|
274
330
|
type: "block-arrow";
|
|
275
331
|
/** Fill color (hex, e.g., "#FF5733") */
|
|
276
332
|
fillColor?: string;
|
|
@@ -300,7 +356,7 @@ export interface CustomShapeInput extends BaseElementInput {
|
|
|
300
356
|
/**
|
|
301
357
|
* Union of all element input types.
|
|
302
358
|
*/
|
|
303
|
-
export type AnyElementInput = RectangleInput | TextInput | ConnectorInput | UmlClassInput | UmlInterfaceInput | UmlComponentInput | UmlPackageInput | UmlArtifactInput | UmlNoteInput | TriangleInput | DiamondInput | HexagonInput | EllipseInput | LineInput | BlockArrowInput | CustomShapeInput;
|
|
359
|
+
export type AnyElementInput = RectangleInput | TextInput | ConnectorInput | UmlClassInput | UmlInterfaceInput | UmlComponentInput | UmlPackageInput | UmlArtifactInput | UmlNoteInput | TriangleInput | DiamondInput | HexagonInput | EllipseInput | LineInput | BezierCurveInput | BlockArrowInput | CustomShapeInput;
|
|
304
360
|
/**
|
|
305
361
|
* Input for updating an existing element.
|
|
306
362
|
*/
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { GraphElement } from "../models";
|
|
2
|
+
import { IElementValidatorRegistry } from "../interfaces/element-validator.interface";
|
|
3
|
+
import { IFirestoreClient } from "../interfaces/firestore-client.interface";
|
|
4
|
+
import { IAuthClient } from "../interfaces/auth-client.interface";
|
|
5
|
+
import { AnyElementInput } from "../types/element-input-types";
|
|
6
|
+
import { CustomShapeResult } from "../types/api-types";
|
|
7
|
+
/**
|
|
8
|
+
* Builds GraphElement objects from AnyElementInput without persisting to Firestore.
|
|
9
|
+
*
|
|
10
|
+
* Handles: validation, default dimensions, centerX/centerY resolution,
|
|
11
|
+
* text auto-measurement, property building, custom shape enrichment.
|
|
12
|
+
*
|
|
13
|
+
* Shared by ElementOperations (single create) and NodeOperations (createWithElements).
|
|
14
|
+
*/
|
|
15
|
+
export declare class ElementBuilder {
|
|
16
|
+
private readonly validatorRegistry;
|
|
17
|
+
private readonly firestore;
|
|
18
|
+
private readonly auth;
|
|
19
|
+
private static _textMeasurementService;
|
|
20
|
+
constructor(validatorRegistry: IElementValidatorRegistry, firestore: IFirestoreClient, auth: IAuthClient);
|
|
21
|
+
/**
|
|
22
|
+
* Builds multiple GraphElements from inputs.
|
|
23
|
+
* Pre-fetches custom shape definitions with deduplication for efficiency.
|
|
24
|
+
*/
|
|
25
|
+
buildMany(inputs: AnyElementInput[]): Promise<GraphElement[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Builds a GraphElement from input.
|
|
28
|
+
* Validates, resolves defaults and center positioning, builds properties,
|
|
29
|
+
* enriches custom shapes. Does NOT write to Firestore.
|
|
30
|
+
*/
|
|
31
|
+
build(input: AnyElementInput, shapeCache?: Map<string, CustomShapeResult>): Promise<GraphElement>;
|
|
32
|
+
/**
|
|
33
|
+
* Validates that centerX/centerY are not used together with x/y.
|
|
34
|
+
*/
|
|
35
|
+
private validateCenterPosition;
|
|
36
|
+
/**
|
|
37
|
+
* Resolves x/y position, handling centerX/centerY conversion.
|
|
38
|
+
*/
|
|
39
|
+
private resolvePosition;
|
|
40
|
+
/**
|
|
41
|
+
* Gets default dimensions for an element type.
|
|
42
|
+
*/
|
|
43
|
+
private getDefaultDimensions;
|
|
44
|
+
/**
|
|
45
|
+
* Auto-measures text width for text elements created without explicit width/maxWidth.
|
|
46
|
+
*/
|
|
47
|
+
private measureTextWidth;
|
|
48
|
+
/**
|
|
49
|
+
* Pre-fetches custom shape definitions from the shape store.
|
|
50
|
+
* Each unique shape is fetched only once for efficiency.
|
|
51
|
+
*/
|
|
52
|
+
private _prefetchCustomShapes;
|
|
53
|
+
/**
|
|
54
|
+
* Enriches custom shape element properties with shape definition data
|
|
55
|
+
* from the published shape store or a pre-fetched cache.
|
|
56
|
+
*/
|
|
57
|
+
private _enrichCustomShapeProperties;
|
|
58
|
+
/**
|
|
59
|
+
* Builds properties object from element input.
|
|
60
|
+
* Extracts type-specific properties, excluding common/positional fields.
|
|
61
|
+
*/
|
|
62
|
+
private buildProperties;
|
|
63
|
+
}
|