@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.
Files changed (46) hide show
  1. package/package.json +1 -1
  2. package/src/index.d.ts +3 -2
  3. package/src/lib/clients/firebase-auth-client.d.ts +7 -0
  4. package/src/lib/clients/firebase-auth-client.js +20 -2
  5. package/src/lib/clients/firebase-firestore-client.js +83 -29
  6. package/src/lib/constants/element-defaults.js +1 -0
  7. package/src/lib/graph-knowledge-api.d.ts +21 -2
  8. package/src/lib/graph-knowledge-api.js +35 -5
  9. package/src/lib/interfaces/auth-client.interface.d.ts +10 -0
  10. package/src/lib/interfaces/custom-shape-operations.interface.d.ts +82 -0
  11. package/src/lib/interfaces/custom-shape-operations.interface.js +2 -0
  12. package/src/lib/interfaces/node-operations.interface.d.ts +29 -1
  13. package/src/lib/interfaces/template-operations.interface.d.ts +22 -1
  14. package/src/lib/operations/batch-operations.d.ts +3 -15
  15. package/src/lib/operations/batch-operations.js +8 -80
  16. package/src/lib/operations/custom-shape-operations.d.ts +27 -0
  17. package/src/lib/operations/custom-shape-operations.js +175 -0
  18. package/src/lib/operations/document-operations.js +9 -2
  19. package/src/lib/operations/element-operations.d.ts +3 -22
  20. package/src/lib/operations/element-operations.js +6 -119
  21. package/src/lib/operations/node-operations.d.ts +9 -3
  22. package/src/lib/operations/node-operations.js +18 -5
  23. package/src/lib/operations/template-operations.d.ts +3 -1
  24. package/src/lib/operations/template-operations.js +50 -7
  25. package/src/lib/testing/mock-auth-client.d.ts +2 -0
  26. package/src/lib/testing/mock-auth-client.js +7 -0
  27. package/src/lib/types/api-types.d.ts +113 -2
  28. package/src/lib/types/element-input-types.d.ts +67 -11
  29. package/src/lib/utils/element-builder.d.ts +63 -0
  30. package/src/lib/utils/element-builder.js +258 -0
  31. package/src/lib/utils/rotation.d.ts +4 -0
  32. package/src/lib/utils/rotation.js +13 -0
  33. package/src/lib/validators/custom-shape-definition-validator.d.ts +17 -0
  34. package/src/lib/validators/custom-shape-definition-validator.js +135 -0
  35. package/src/lib/validators/element-type-validators/base-element-validator.d.ts +4 -0
  36. package/src/lib/validators/element-type-validators/base-element-validator.js +30 -0
  37. package/src/lib/validators/element-type-validators/basic-shape-validators.js +2 -0
  38. package/src/lib/validators/element-type-validators/bezier-curve-validator.d.ts +12 -0
  39. package/src/lib/validators/element-type-validators/bezier-curve-validator.js +47 -0
  40. package/src/lib/validators/element-type-validators/block-arrow-validator.js +2 -0
  41. package/src/lib/validators/element-type-validators/line-validator.d.ts +1 -0
  42. package/src/lib/validators/element-type-validators/line-validator.js +12 -5
  43. package/src/lib/validators/element-type-validators/rectangle-validator.js +2 -0
  44. package/src/lib/validators/element-validator-registry.js +2 -0
  45. package/src/lib/validators/template-validator.d.ts +7 -1
  46. package/src/lib/validators/template-validator.js +21 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graph-knowledge/api",
3
- "version": "0.3.2",
3
+ "version": "0.9.0",
4
4
  "description": "Headless Document API for Graph Knowledge - programmatic access to documents, nodes, and elements",
5
5
  "license": "MIT",
6
6
  "author": "Graph Knowledge Team",
package/src/index.d.ts CHANGED
@@ -7,9 +7,10 @@ export type { INodeOperations } from "./lib/interfaces/node-operations.interface
7
7
  export type { IElementOperations } from "./lib/interfaces/element-operations.interface";
8
8
  export type { IBatchOperations, BatchUpdateElementInput } from "./lib/interfaces/batch-operations.interface";
9
9
  export type { ITemplateOperations } from "./lib/interfaces/template-operations.interface";
10
+ export type { ICustomShapeOperations } from "./lib/interfaces/custom-shape-operations.interface";
10
11
  export type { IElementTypeValidator, IElementValidatorRegistry } from "./lib/interfaces/element-validator.interface";
11
- export type { CreateDocumentInput, UpdateDocumentInput, DocumentResult, CreateNodeInput, UpdateNodeInput, NodeResult, CreateTemplateInput } from "./lib/types/api-types";
12
- export type { BaseElementInput, RectangleInput, TextInput, ConnectorInput, ConnectorAnchor, LineStyle, MarkerType, UmlClassInput, UmlInterfaceInput, UmlComponentInput, UmlPackageInput, UmlArtifactInput, UmlNoteInput, TriangleInput, DiamondInput, HexagonInput, EllipseInput, LineInput, BlockArrowInput, BlockArrowDirection, CustomShapeInput, AnyElementInput, UpdateElementInput } from "./lib/types/element-input-types";
12
+ export type { CreateDocumentInput, UpdateDocumentInput, DocumentResult, CreateNodeInput, UpdateNodeInput, NodeResult, CreateNodeWithElementsInput, CreateNodeWithElementsResult, CreateTemplateInput, UpdateTemplateInput, CreateCustomShapeInput, UpdateCustomShapeInput, CustomShapeResult, ViewBoxInput } from "./lib/types/api-types";
13
+ export type { BaseElementInput, RectangleInput, TextInput, ConnectorInput, ConnectorAnchor, LineStyle, MarkerType, UmlClassInput, UmlInterfaceInput, UmlComponentInput, UmlPackageInput, UmlArtifactInput, UmlNoteInput, TriangleInput, DiamondInput, HexagonInput, EllipseInput, LineInput, BezierCurveInput, BlockArrowInput, BlockArrowDirection, CustomShapeInput, AnyElementInput, UpdateElementInput } from "./lib/types/element-input-types";
13
14
  export { GraphKnowledgeAPIError, AuthenticationError, NotFoundError, ValidationError, PermissionError } from "./lib/errors/api-errors";
14
15
  export type { Document, GraphNode, GraphElement } from "./lib/models";
15
16
  export { CURRENT_DOCUMENT_SCHEMA_VERSION } from "./lib/models";
@@ -10,12 +10,19 @@ export declare class FirebaseAuthClient implements IAuthClient {
10
10
  private _currentUser;
11
11
  private _initialized;
12
12
  private _initPromise;
13
+ private _unsubscribe;
13
14
  constructor(auth: Auth, firestore: Firestore);
15
+ /**
16
+ * Cleans up the auth state listener.
17
+ * Call this when the API instance is no longer needed.
18
+ */
19
+ destroy(): void;
14
20
  /**
15
21
  * Waits for auth state to be initialized.
16
22
  */
17
23
  waitForInit(): Promise<void>;
18
24
  signIn(email: string, password: string): Promise<void>;
25
+ signInWithCustomToken(token: string): Promise<void>;
19
26
  signOut(): Promise<void>;
20
27
  get currentUserId(): string | null;
21
28
  requireAuth(): string;
@@ -13,20 +13,28 @@ class FirebaseAuthClient {
13
13
  _currentUser = null;
14
14
  _initialized = false;
15
15
  _initPromise;
16
+ _unsubscribe = null;
16
17
  constructor(auth, firestore) {
17
18
  this.auth = auth;
18
19
  this.firestore = firestore;
19
20
  this._initPromise = new Promise((resolve) => {
20
- const unsubscribe = (0, auth_1.onAuthStateChanged)(this.auth, (user) => {
21
+ this._unsubscribe = (0, auth_1.onAuthStateChanged)(this.auth, (user) => {
21
22
  this._currentUser = user;
22
23
  if (!this._initialized) {
23
24
  this._initialized = true;
24
- unsubscribe();
25
25
  resolve();
26
26
  }
27
27
  });
28
28
  });
29
29
  }
30
+ /**
31
+ * Cleans up the auth state listener.
32
+ * Call this when the API instance is no longer needed.
33
+ */
34
+ destroy() {
35
+ this._unsubscribe?.();
36
+ this._unsubscribe = null;
37
+ }
30
38
  /**
31
39
  * Waits for auth state to be initialized.
32
40
  */
@@ -43,6 +51,16 @@ class FirebaseAuthClient {
43
51
  throw new api_errors_1.AuthenticationError(message);
44
52
  }
45
53
  }
54
+ async signInWithCustomToken(token) {
55
+ try {
56
+ const credential = await (0, auth_1.signInWithCustomToken)(this.auth, token);
57
+ this._currentUser = credential.user;
58
+ }
59
+ catch (error) {
60
+ const message = error instanceof Error ? error.message : "Custom token sign in failed";
61
+ throw new api_errors_1.AuthenticationError(message);
62
+ }
63
+ }
46
64
  async signOut() {
47
65
  await (0, auth_1.signOut)(this.auth);
48
66
  this._currentUser = null;
@@ -2,6 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FirebaseFirestoreClient = void 0;
4
4
  const firestore_1 = require("firebase/firestore");
5
+ const api_errors_1 = require("../errors/api-errors");
6
+ /**
7
+ * Maps Firebase error codes to typed API errors.
8
+ * @throws PermissionError for permission-denied
9
+ * @throws AuthenticationError for unauthenticated
10
+ * @throws the original error for all other cases
11
+ */
12
+ function handleFirestoreError(error) {
13
+ if (error instanceof Error && "code" in error) {
14
+ const code = error.code;
15
+ if (code === "permission-denied") {
16
+ throw new api_errors_1.PermissionError("Firestore access denied: " + error.message);
17
+ }
18
+ if (code === "unauthenticated") {
19
+ throw new api_errors_1.AuthenticationError("Firestore authentication failed: " + error.message);
20
+ }
21
+ }
22
+ throw error;
23
+ }
5
24
  /**
6
25
  * Firebase Firestore batch writer implementation.
7
26
  */
@@ -25,7 +44,12 @@ class FirestoreBatchWriter {
25
44
  this.batch.delete(docRef);
26
45
  }
27
46
  async commit() {
28
- await this.batch.commit();
47
+ try {
48
+ await this.batch.commit();
49
+ }
50
+ catch (error) {
51
+ handleFirestoreError(error);
52
+ }
29
53
  }
30
54
  }
31
55
  /**
@@ -37,44 +61,74 @@ class FirebaseFirestoreClient {
37
61
  this.db = db;
38
62
  }
39
63
  async getDocument(path) {
40
- const docRef = (0, firestore_1.doc)(this.db, path);
41
- const snapshot = await (0, firestore_1.getDoc)(docRef);
42
- if (!snapshot.exists()) {
43
- return null;
44
- }
45
- return {
46
- id: snapshot.id,
47
- ...snapshot.data()
48
- };
64
+ try {
65
+ const docRef = (0, firestore_1.doc)(this.db, path);
66
+ const snapshot = await (0, firestore_1.getDoc)(docRef);
67
+ if (!snapshot.exists()) {
68
+ return null;
69
+ }
70
+ return {
71
+ id: snapshot.id,
72
+ ...snapshot.data()
73
+ };
74
+ }
75
+ catch (error) {
76
+ handleFirestoreError(error);
77
+ }
49
78
  }
50
79
  async setDocument(path, data) {
51
- const docRef = (0, firestore_1.doc)(this.db, path);
52
- await (0, firestore_1.setDoc)(docRef, data);
80
+ try {
81
+ const docRef = (0, firestore_1.doc)(this.db, path);
82
+ await (0, firestore_1.setDoc)(docRef, data);
83
+ }
84
+ catch (error) {
85
+ handleFirestoreError(error);
86
+ }
53
87
  }
54
88
  async updateDocument(path, data) {
55
- const docRef = (0, firestore_1.doc)(this.db, path);
56
- await (0, firestore_1.updateDoc)(docRef, data);
89
+ try {
90
+ const docRef = (0, firestore_1.doc)(this.db, path);
91
+ await (0, firestore_1.updateDoc)(docRef, data);
92
+ }
93
+ catch (error) {
94
+ handleFirestoreError(error);
95
+ }
57
96
  }
58
97
  async deleteDocument(path) {
59
- const docRef = (0, firestore_1.doc)(this.db, path);
60
- await (0, firestore_1.deleteDoc)(docRef);
98
+ try {
99
+ const docRef = (0, firestore_1.doc)(this.db, path);
100
+ await (0, firestore_1.deleteDoc)(docRef);
101
+ }
102
+ catch (error) {
103
+ handleFirestoreError(error);
104
+ }
61
105
  }
62
106
  async getCollection(path) {
63
- const collectionRef = (0, firestore_1.collection)(this.db, path);
64
- const snapshot = await (0, firestore_1.getDocs)(collectionRef);
65
- return snapshot.docs.map((doc) => ({
66
- id: doc.id,
67
- ...doc.data()
68
- }));
107
+ try {
108
+ const collectionRef = (0, firestore_1.collection)(this.db, path);
109
+ const snapshot = await (0, firestore_1.getDocs)(collectionRef);
110
+ return snapshot.docs.map((doc) => ({
111
+ id: doc.id,
112
+ ...doc.data()
113
+ }));
114
+ }
115
+ catch (error) {
116
+ handleFirestoreError(error);
117
+ }
69
118
  }
70
119
  async queryCollection(path, field, value) {
71
- const collectionRef = (0, firestore_1.collection)(this.db, path);
72
- const q = (0, firestore_1.query)(collectionRef, (0, firestore_1.where)(field, "==", value));
73
- const snapshot = await (0, firestore_1.getDocs)(q);
74
- return snapshot.docs.map((doc) => ({
75
- id: doc.id,
76
- ...doc.data()
77
- }));
120
+ try {
121
+ const collectionRef = (0, firestore_1.collection)(this.db, path);
122
+ const q = (0, firestore_1.query)(collectionRef, (0, firestore_1.where)(field, "==", value));
123
+ const snapshot = await (0, firestore_1.getDocs)(q);
124
+ return snapshot.docs.map((doc) => ({
125
+ id: doc.id,
126
+ ...doc.data()
127
+ }));
128
+ }
129
+ catch (error) {
130
+ handleFirestoreError(error);
131
+ }
78
132
  }
79
133
  batch() {
80
134
  return new FirestoreBatchWriter(this.db, (0, firestore_1.writeBatch)(this.db));
@@ -20,6 +20,7 @@ exports.DEFAULT_ELEMENT_DIMENSIONS = {
20
20
  hexagon: { width: 120, height: 104 },
21
21
  ellipse: { width: 150, height: 100 },
22
22
  line: { width: 150, height: 0 },
23
+ "bezier-curve": { width: 150, height: 0 },
23
24
  "block-arrow": { width: 150, height: 80 }
24
25
  };
25
26
  /**
@@ -5,6 +5,7 @@ import { INodeOperations } from "./interfaces/node-operations.interface";
5
5
  import { IElementOperations } from "./interfaces/element-operations.interface";
6
6
  import { IBatchOperations } from "./interfaces/batch-operations.interface";
7
7
  import { ITemplateOperations } from "./interfaces/template-operations.interface";
8
+ import { ICustomShapeOperations } from "./interfaces/custom-shape-operations.interface";
8
9
  import { MeasureTextOptions, TextMetrics } from "./types/text-measurement-types";
9
10
  import { FitTextOptions, FitTextResult, ShapeBounds } from "./types/layout-types";
10
11
  /**
@@ -52,6 +53,7 @@ export declare class GraphKnowledgeAPI {
52
53
  private readonly _elements;
53
54
  private readonly _batch;
54
55
  private readonly _templates;
56
+ private readonly _customShapes;
55
57
  /**
56
58
  * Shared text measurement service for static and instance methods.
57
59
  */
@@ -86,17 +88,29 @@ export declare class GraphKnowledgeAPI {
86
88
  */
87
89
  get batch(): IBatchOperations;
88
90
  /**
89
- * Template operations (list, get, clone, publish, unpublish).
91
+ * Template operations (create, list, get, update, delete, clone, publish, unpublish).
90
92
  * Templates are documents that can be cloned by premium users.
91
- * Admins can publish/unpublish templates to control visibility.
93
+ * Admins can create/update/delete and publish/unpublish templates.
92
94
  */
93
95
  get templates(): ITemplateOperations;
96
+ /**
97
+ * Custom shape operations (create, list, get, update, delete, publish, unpublish, listPublished, getPublished).
98
+ * Custom shapes are user-created SVG path-based shapes.
99
+ * Premium users can create and publish shapes to the public store.
100
+ */
101
+ get customShapes(): ICustomShapeOperations;
94
102
  /**
95
103
  * Signs in with email and password.
96
104
  * @param email User email
97
105
  * @param password User password
98
106
  */
99
107
  signIn(email: string, password: string): Promise<void>;
108
+ /**
109
+ * Signs in with a Firebase custom token (for server-to-server auth).
110
+ * Used by remote MCP server to authenticate per-user sessions.
111
+ * @param token Custom token generated by Firebase Admin SDK
112
+ */
113
+ signInWithCustomToken(token: string): Promise<void>;
100
114
  /**
101
115
  * Signs out the current user.
102
116
  */
@@ -110,6 +124,11 @@ export declare class GraphKnowledgeAPI {
110
124
  * Call this before checking auth state if the API was just created.
111
125
  */
112
126
  waitForAuthInit(): Promise<void>;
127
+ /**
128
+ * Cleans up resources (auth state listeners).
129
+ * Call this when the API instance is no longer needed.
130
+ */
131
+ destroy(): void;
113
132
  /**
114
133
  * Checks if the current user has premium status.
115
134
  * @returns Promise resolving to true if user is premium
@@ -11,12 +11,15 @@ const node_operations_1 = require("./operations/node-operations");
11
11
  const element_operations_1 = require("./operations/element-operations");
12
12
  const batch_operations_1 = require("./operations/batch-operations");
13
13
  const template_operations_1 = require("./operations/template-operations");
14
+ const custom_shape_operations_1 = require("./operations/custom-shape-operations");
14
15
  const document_validator_1 = require("./validators/document-validator");
15
16
  const node_validator_1 = require("./validators/node-validator");
16
17
  const element_validator_registry_1 = require("./validators/element-validator-registry");
17
18
  const template_validator_1 = require("./validators/template-validator");
19
+ const custom_shape_definition_validator_1 = require("./validators/custom-shape-definition-validator");
18
20
  const text_measurement_service_1 = require("./utils/text-measurement/text-measurement-service");
19
21
  const layout_helper_1 = require("./utils/layout/layout-helper");
22
+ const element_builder_1 = require("./utils/element-builder");
20
23
  /**
21
24
  * Main entry point for the Graph Knowledge Headless API.
22
25
  *
@@ -62,6 +65,7 @@ class GraphKnowledgeAPI {
62
65
  _elements;
63
66
  _batch;
64
67
  _templates;
68
+ _customShapes;
65
69
  /**
66
70
  * Shared text measurement service for static and instance methods.
67
71
  */
@@ -86,12 +90,15 @@ class GraphKnowledgeAPI {
86
90
  const documentValidator = new document_validator_1.DocumentValidator();
87
91
  const nodeValidator = new node_validator_1.NodeValidator();
88
92
  const elementValidatorRegistry = new element_validator_registry_1.ElementValidatorRegistry();
93
+ // Create shared element builder (used by ElementOperations and NodeOperations)
94
+ const elementBuilder = new element_builder_1.ElementBuilder(elementValidatorRegistry, firestoreClient, this._authClient);
89
95
  // Create operations (dependency injection)
90
96
  this._documents = new document_operations_1.DocumentOperations(firestoreClient, this._authClient, documentValidator);
91
- this._nodes = new node_operations_1.NodeOperations(firestoreClient, this._authClient, nodeValidator);
92
- this._elements = new element_operations_1.ElementOperations(firestoreClient, this._authClient, elementValidatorRegistry);
93
- this._batch = new batch_operations_1.BatchOperations(firestoreClient, this._authClient, elementValidatorRegistry);
97
+ this._nodes = new node_operations_1.NodeOperations(firestoreClient, this._authClient, nodeValidator, elementBuilder);
98
+ this._elements = new element_operations_1.ElementOperations(firestoreClient, this._authClient, elementBuilder);
99
+ this._batch = new batch_operations_1.BatchOperations(firestoreClient, this._authClient, elementBuilder);
94
100
  this._templates = new template_operations_1.TemplateOperations(firestoreClient, this._authClient, new template_validator_1.TemplateValidator());
101
+ this._customShapes = new custom_shape_operations_1.CustomShapeOperations(firestoreClient, this._authClient, new custom_shape_definition_validator_1.CustomShapeDefinitionValidator());
95
102
  }
96
103
  /**
97
104
  * Authentication client for sign-in/sign-out operations.
@@ -124,13 +131,21 @@ class GraphKnowledgeAPI {
124
131
  return this._batch;
125
132
  }
126
133
  /**
127
- * Template operations (list, get, clone, publish, unpublish).
134
+ * Template operations (create, list, get, update, delete, clone, publish, unpublish).
128
135
  * Templates are documents that can be cloned by premium users.
129
- * Admins can publish/unpublish templates to control visibility.
136
+ * Admins can create/update/delete and publish/unpublish templates.
130
137
  */
131
138
  get templates() {
132
139
  return this._templates;
133
140
  }
141
+ /**
142
+ * Custom shape operations (create, list, get, update, delete, publish, unpublish, listPublished, getPublished).
143
+ * Custom shapes are user-created SVG path-based shapes.
144
+ * Premium users can create and publish shapes to the public store.
145
+ */
146
+ get customShapes() {
147
+ return this._customShapes;
148
+ }
134
149
  // =========================================================================
135
150
  // Convenience methods delegating to authClient
136
151
  // =========================================================================
@@ -142,6 +157,14 @@ class GraphKnowledgeAPI {
142
157
  async signIn(email, password) {
143
158
  return this._authClient.signIn(email, password);
144
159
  }
160
+ /**
161
+ * Signs in with a Firebase custom token (for server-to-server auth).
162
+ * Used by remote MCP server to authenticate per-user sessions.
163
+ * @param token Custom token generated by Firebase Admin SDK
164
+ */
165
+ async signInWithCustomToken(token) {
166
+ return this._authClient.signInWithCustomToken(token);
167
+ }
145
168
  /**
146
169
  * Signs out the current user.
147
170
  */
@@ -161,6 +184,13 @@ class GraphKnowledgeAPI {
161
184
  async waitForAuthInit() {
162
185
  return this._authClient.waitForInit();
163
186
  }
187
+ /**
188
+ * Cleans up resources (auth state listeners).
189
+ * Call this when the API instance is no longer needed.
190
+ */
191
+ destroy() {
192
+ this._authClient.destroy();
193
+ }
164
194
  /**
165
195
  * Checks if the current user has premium status.
166
196
  * @returns Promise resolving to true if user is premium
@@ -8,6 +8,11 @@ export interface IAuthClient {
8
8
  * @throws AuthenticationError if sign in fails
9
9
  */
10
10
  signIn(email: string, password: string): Promise<void>;
11
+ /**
12
+ * Signs in with a Firebase custom token (for server-to-server auth).
13
+ * @throws AuthenticationError if sign in fails
14
+ */
15
+ signInWithCustomToken(token: string): Promise<void>;
11
16
  /**
12
17
  * Signs out the current user.
13
18
  */
@@ -43,4 +48,9 @@ export interface IAuthClient {
43
48
  * @throws PermissionError if not admin
44
49
  */
45
50
  requireAdmin(): Promise<void>;
51
+ /**
52
+ * Cleans up resources (e.g., auth state listeners).
53
+ * Call this when the client is no longer needed.
54
+ */
55
+ destroy(): void;
46
56
  }
@@ -0,0 +1,82 @@
1
+ import { CreateCustomShapeInput, UpdateCustomShapeInput, CustomShapeResult } from "../types/api-types";
2
+ /**
3
+ * Interface for custom shape operations.
4
+ *
5
+ * Custom shapes are user-created SVG path-based shapes stored in:
6
+ * - `/users/{uid}/customShapes/{shapeId}` (drafts)
7
+ * - `/shapeStore/{shapeId}` (published to public store)
8
+ */
9
+ export interface ICustomShapeOperations {
10
+ /**
11
+ * Creates a new draft custom shape.
12
+ * Requires premium access.
13
+ *
14
+ * @param input Shape creation parameters
15
+ * @returns The newly created shape
16
+ * @throws AuthenticationError if not authenticated
17
+ * @throws PermissionError if not premium
18
+ */
19
+ create(input: CreateCustomShapeInput): Promise<CustomShapeResult>;
20
+ /**
21
+ * Lists all draft shapes for the current user.
22
+ * @returns Array of the user's draft shapes
23
+ * @throws AuthenticationError if not authenticated
24
+ */
25
+ list(): Promise<CustomShapeResult[]>;
26
+ /**
27
+ * Gets a specific draft shape by ID.
28
+ * @param shapeId The shape ID
29
+ * @returns The shape
30
+ * @throws AuthenticationError if not authenticated
31
+ * @throws NotFoundError if shape doesn't exist
32
+ */
33
+ get(shapeId: string): Promise<CustomShapeResult>;
34
+ /**
35
+ * Updates a draft shape.
36
+ * @param shapeId The shape ID
37
+ * @param input The fields to update
38
+ * @throws AuthenticationError if not authenticated
39
+ * @throws NotFoundError if shape doesn't exist
40
+ */
41
+ update(shapeId: string, input: UpdateCustomShapeInput): Promise<void>;
42
+ /**
43
+ * Deletes a draft shape.
44
+ * @param shapeId The shape ID
45
+ * @throws AuthenticationError if not authenticated
46
+ * @throws NotFoundError if shape doesn't exist
47
+ */
48
+ delete(shapeId: string): Promise<void>;
49
+ /**
50
+ * Publishes a draft shape to the public store.
51
+ * Requires premium access.
52
+ *
53
+ * @param shapeId The shape ID to publish
54
+ * @throws AuthenticationError if not authenticated
55
+ * @throws PermissionError if not premium
56
+ * @throws NotFoundError if shape doesn't exist
57
+ */
58
+ publish(shapeId: string): Promise<void>;
59
+ /**
60
+ * Unpublishes a shape from the public store.
61
+ * Reverts the draft to "draft" status.
62
+ *
63
+ * @param shapeId The shape ID to unpublish
64
+ * @throws AuthenticationError if not authenticated
65
+ * @throws NotFoundError if shape doesn't exist
66
+ */
67
+ unpublish(shapeId: string): Promise<void>;
68
+ /**
69
+ * Lists all published shapes in the public store.
70
+ * @returns Array of published shapes
71
+ * @throws AuthenticationError if not authenticated
72
+ */
73
+ listPublished(): Promise<CustomShapeResult[]>;
74
+ /**
75
+ * Gets a specific published shape from the store.
76
+ * @param shapeId The shape ID
77
+ * @returns The published shape
78
+ * @throws AuthenticationError if not authenticated
79
+ * @throws NotFoundError if shape doesn't exist in store
80
+ */
81
+ getPublished(shapeId: string): Promise<CustomShapeResult>;
82
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,5 @@
1
1
  import { GraphNode } from "../models";
2
- import { CreateNodeInput, UpdateNodeInput } from "../types/api-types";
2
+ import { CreateNodeInput, UpdateNodeInput, CreateNodeWithElementsInput, CreateNodeWithElementsResult } from "../types/api-types";
3
3
  /**
4
4
  * Interface for node CRUD operations.
5
5
  */
@@ -59,4 +59,32 @@ export interface INodeOperations {
59
59
  * @throws AuthenticationError if not authenticated
60
60
  */
61
61
  delete(documentId: string, nodeId: string): Promise<void>;
62
+ /**
63
+ * Creates a new node with all its elements in a single atomic operation.
64
+ * All elements are validated before the node is created. If any element
65
+ * fails validation, no node or elements are created (all or nothing).
66
+ *
67
+ * @param documentId The parent document ID
68
+ * @param input Node creation parameters including elements array
69
+ * @returns The created node and all elements with their generated IDs
70
+ * @throws AuthenticationError if not authenticated
71
+ * @throws NotFoundError if document doesn't exist
72
+ * @throws ValidationError if node or any element input is invalid
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const result = await api.nodes.createWithElements(docId, {
77
+ * title: "Mars",
78
+ * canvasWidth: 1920,
79
+ * canvasHeight: 1080,
80
+ * elements: [
81
+ * { type: "rectangle", x: 100, y: 100, width: 200, height: 100 },
82
+ * { type: "text", x: 150, y: 140, text: "Planet Mars" }
83
+ * ]
84
+ * });
85
+ * // result.node — the created node
86
+ * // result.elements — array of created elements with IDs
87
+ * ```
88
+ */
89
+ createWithElements(documentId: string, input: CreateNodeWithElementsInput): Promise<CreateNodeWithElementsResult>;
62
90
  }
@@ -1,4 +1,4 @@
1
- import { CreateTemplateInput, DocumentResult } from "../types/api-types";
1
+ import { CreateTemplateInput, UpdateTemplateInput, DocumentResult } from "../types/api-types";
2
2
  /**
3
3
  * Interface for template operations.
4
4
  *
@@ -30,6 +30,27 @@ export interface ITemplateOperations {
30
30
  * @throws NotFoundError if template doesn't exist
31
31
  */
32
32
  get(templateId: string): Promise<DocumentResult>;
33
+ /**
34
+ * Updates a template's title and/or content.
35
+ * Requires admin access.
36
+ *
37
+ * @param templateId The template document ID
38
+ * @param input The fields to update
39
+ * @throws AuthenticationError if not authenticated
40
+ * @throws PermissionError if not admin
41
+ * @throws NotFoundError if template doesn't exist
42
+ */
43
+ update(templateId: string, input: UpdateTemplateInput): Promise<void>;
44
+ /**
45
+ * Deletes a template document.
46
+ * Requires admin access.
47
+ *
48
+ * @param templateId The template document ID
49
+ * @throws AuthenticationError if not authenticated
50
+ * @throws PermissionError if not admin
51
+ * @throws NotFoundError if template doesn't exist
52
+ */
53
+ delete(templateId: string): Promise<void>;
33
54
  /**
34
55
  * Clones a template into a new document owned by the current user.
35
56
  * Requires premium access.
@@ -2,29 +2,17 @@ import { GraphElement } from "../models";
2
2
  import { IBatchOperations, BatchUpdateElementInput } from "../interfaces/batch-operations.interface";
3
3
  import { IFirestoreClient } from "../interfaces/firestore-client.interface";
4
4
  import { IAuthClient } from "../interfaces/auth-client.interface";
5
- import { IElementValidatorRegistry } from "../interfaces/element-validator.interface";
6
5
  import { AnyElementInput } from "../types/element-input-types";
6
+ import { ElementBuilder } from "../utils/element-builder";
7
7
  /**
8
8
  * Implementation of batch element operations.
9
9
  */
10
10
  export declare class BatchOperations implements IBatchOperations {
11
11
  private readonly firestore;
12
12
  private readonly auth;
13
- private readonly validatorRegistry;
14
- constructor(firestore: IFirestoreClient, auth: IAuthClient, validatorRegistry: IElementValidatorRegistry);
13
+ private readonly elementBuilder;
14
+ constructor(firestore: IFirestoreClient, auth: IAuthClient, elementBuilder: ElementBuilder);
15
15
  createElements(documentId: string, nodeId: string, inputs: AnyElementInput[]): Promise<GraphElement[]>;
16
16
  updateElements(documentId: string, nodeId: string, updates: BatchUpdateElementInput[]): Promise<void>;
17
17
  deleteElements(documentId: string, nodeId: string, elementIds: string[]): Promise<void>;
18
- /**
19
- * Gets default dimensions for an element type.
20
- */
21
- private getDefaultDimensions;
22
- /**
23
- * Normalizes rotation to integer in range [0, 360).
24
- */
25
- private normalizeRotation;
26
- /**
27
- * Builds properties object from element input.
28
- */
29
- private buildProperties;
30
18
  }