@graph-knowledge/api 0.4.0 → 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 +2 -1
- 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/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 +38 -10
- 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/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/template-validator.d.ts +7 -1
- package/src/lib/validators/template-validator.js +21 -0
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -7,8 +7,9 @@ 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 { CreateDocumentInput, UpdateDocumentInput, DocumentResult, CreateNodeInput, UpdateNodeInput, NodeResult, CreateNodeWithElementsInput, CreateNodeWithElementsResult, CreateTemplateInput, UpdateTemplateInput, CreateCustomShapeInput, UpdateCustomShapeInput, CustomShapeResult, ViewBoxInput } from "./lib/types/api-types";
|
|
12
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";
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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));
|
|
@@ -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
|
|
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,
|
|
93
|
-
this._batch = new batch_operations_1.BatchOperations(firestoreClient, this._authClient,
|
|
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
|
|
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
|
+
}
|
|
@@ -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
|
|
14
|
-
constructor(firestore: IFirestoreClient, auth: IAuthClient,
|
|
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
|
}
|