@graph-knowledge/api 0.1.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 (74) hide show
  1. package/README.md +396 -0
  2. package/package.json +44 -0
  3. package/src/index.d.ts +18 -0
  4. package/src/index.js +19 -0
  5. package/src/lib/clients/firebase-auth-client.d.ts +24 -0
  6. package/src/lib/clients/firebase-auth-client.js +76 -0
  7. package/src/lib/clients/firebase-firestore-client.d.ts +22 -0
  8. package/src/lib/clients/firebase-firestore-client.js +79 -0
  9. package/src/lib/config/api-config.d.ts +20 -0
  10. package/src/lib/config/api-config.js +0 -0
  11. package/src/lib/constants/element-defaults.d.ts +15 -0
  12. package/src/lib/constants/element-defaults.js +19 -0
  13. package/src/lib/errors/api-errors.d.ts +33 -0
  14. package/src/lib/errors/api-errors.js +51 -0
  15. package/src/lib/graph-knowledge-api.d.ts +106 -0
  16. package/src/lib/graph-knowledge-api.js +154 -0
  17. package/src/lib/interfaces/auth-client.interface.d.ts +35 -0
  18. package/src/lib/interfaces/auth-client.interface.js +0 -0
  19. package/src/lib/interfaces/batch-operations.interface.d.ts +46 -0
  20. package/src/lib/interfaces/batch-operations.interface.js +0 -0
  21. package/src/lib/interfaces/document-operations.interface.d.ts +51 -0
  22. package/src/lib/interfaces/document-operations.interface.js +0 -0
  23. package/src/lib/interfaces/element-operations.interface.d.ts +57 -0
  24. package/src/lib/interfaces/element-operations.interface.js +0 -0
  25. package/src/lib/interfaces/element-validator.interface.d.ts +42 -0
  26. package/src/lib/interfaces/element-validator.interface.js +0 -0
  27. package/src/lib/interfaces/firestore-client.interface.d.ts +62 -0
  28. package/src/lib/interfaces/firestore-client.interface.js +0 -0
  29. package/src/lib/interfaces/node-operations.interface.d.ts +62 -0
  30. package/src/lib/interfaces/node-operations.interface.js +0 -0
  31. package/src/lib/models/document.model.d.ts +73 -0
  32. package/src/lib/models/document.model.js +13 -0
  33. package/src/lib/models/index.d.ts +6 -0
  34. package/src/lib/models/index.js +5 -0
  35. package/src/lib/operations/batch-operations.d.ts +30 -0
  36. package/src/lib/operations/batch-operations.js +181 -0
  37. package/src/lib/operations/document-operations.d.ts +20 -0
  38. package/src/lib/operations/document-operations.js +108 -0
  39. package/src/lib/operations/element-operations.d.ts +33 -0
  40. package/src/lib/operations/element-operations.js +175 -0
  41. package/src/lib/operations/node-operations.d.ts +22 -0
  42. package/src/lib/operations/node-operations.js +89 -0
  43. package/src/lib/testing/index.d.ts +2 -0
  44. package/src/lib/testing/index.js +3 -0
  45. package/src/lib/testing/mock-auth-client.d.ts +26 -0
  46. package/src/lib/testing/mock-auth-client.js +49 -0
  47. package/src/lib/testing/mock-firestore-client.d.ts +32 -0
  48. package/src/lib/testing/mock-firestore-client.js +126 -0
  49. package/src/lib/types/api-types.d.ts +61 -0
  50. package/src/lib/types/api-types.js +0 -0
  51. package/src/lib/types/element-input-types.d.ts +237 -0
  52. package/src/lib/types/element-input-types.js +3 -0
  53. package/src/lib/utils/link-level-manager.d.ts +66 -0
  54. package/src/lib/utils/link-level-manager.js +200 -0
  55. package/src/lib/utils/uuid.d.ts +5 -0
  56. package/src/lib/utils/uuid.js +16 -0
  57. package/src/lib/validators/document-validator.d.ts +22 -0
  58. package/src/lib/validators/document-validator.js +68 -0
  59. package/src/lib/validators/element-type-validators/base-element-validator.d.ts +35 -0
  60. package/src/lib/validators/element-type-validators/base-element-validator.js +96 -0
  61. package/src/lib/validators/element-type-validators/connector-validator.d.ts +13 -0
  62. package/src/lib/validators/element-type-validators/connector-validator.js +66 -0
  63. package/src/lib/validators/element-type-validators/custom-shape-validator.d.ts +22 -0
  64. package/src/lib/validators/element-type-validators/custom-shape-validator.js +44 -0
  65. package/src/lib/validators/element-type-validators/rectangle-validator.d.ts +11 -0
  66. package/src/lib/validators/element-type-validators/rectangle-validator.js +31 -0
  67. package/src/lib/validators/element-type-validators/text-validator.d.ts +14 -0
  68. package/src/lib/validators/element-type-validators/text-validator.js +66 -0
  69. package/src/lib/validators/element-type-validators/uml-validators.d.ts +58 -0
  70. package/src/lib/validators/element-type-validators/uml-validators.js +123 -0
  71. package/src/lib/validators/element-validator-registry.d.ts +18 -0
  72. package/src/lib/validators/element-validator-registry.js +58 -0
  73. package/src/lib/validators/node-validator.d.ts +26 -0
  74. package/src/lib/validators/node-validator.js +90 -0
package/README.md ADDED
@@ -0,0 +1,396 @@
1
+ # @graph-knowledge/api
2
+
3
+ Headless Document API for Graph Knowledge - provides programmatic access to documents, nodes, and elements without requiring the Angular UI.
4
+
5
+ ## Installation
6
+
7
+ ### npm (for external use)
8
+
9
+ ```bash
10
+ npm install @graph-knowledge/api firebase
11
+ ```
12
+
13
+ ### Monorepo (internal use)
14
+
15
+ ```typescript
16
+ import { GraphKnowledgeAPI } from "@graph-knowledge/api";
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { GraphKnowledgeAPI } from "@graph-knowledge/api";
23
+
24
+ // Initialize with your Firebase config
25
+ const api = new GraphKnowledgeAPI({
26
+ firebaseConfig: {
27
+ apiKey: "your-api-key",
28
+ authDomain: "your-project.firebaseapp.com",
29
+ projectId: "your-project",
30
+ storageBucket: "your-project.appspot.com",
31
+ messagingSenderId: "123456789",
32
+ appId: "1:123456789:web:abc123"
33
+ }
34
+ });
35
+
36
+ // Sign in
37
+ await api.signIn("user@example.com", "password");
38
+
39
+ // Create a document
40
+ const doc = await api.documents.create({
41
+ title: "My Document",
42
+ content: "Description"
43
+ });
44
+
45
+ // Create a node in the document
46
+ const node = await api.nodes.create(doc.id, {
47
+ title: "My Node",
48
+ canvasWidth: 1920,
49
+ canvasHeight: 1080
50
+ });
51
+
52
+ // Add elements to the node
53
+ await api.elements.create(doc.id, node.id, {
54
+ type: "rectangle",
55
+ x: 100,
56
+ y: 100,
57
+ width: 200,
58
+ height: 150,
59
+ fillColor: "#FF5733",
60
+ strokeColor: "#000000"
61
+ });
62
+
63
+ await api.elements.create(doc.id, node.id, {
64
+ type: "text",
65
+ x: 150,
66
+ y: 160,
67
+ text: "Hello World",
68
+ fontSize: 24
69
+ });
70
+
71
+ // Sign out
72
+ await api.signOut();
73
+ ```
74
+
75
+ ## API Reference
76
+
77
+ ### GraphKnowledgeAPI
78
+
79
+ Main entry point for the API.
80
+
81
+ #### Constructor
82
+
83
+ ```typescript
84
+ new GraphKnowledgeAPI(config: ApiConfig)
85
+ ```
86
+
87
+ #### Methods
88
+
89
+ | Method | Description |
90
+ |--------|-------------|
91
+ | `signIn(email, password)` | Signs in with email and password |
92
+ | `signOut()` | Signs out the current user |
93
+ | `waitForAuthInit()` | Waits for Firebase Auth to initialize |
94
+
95
+ #### Properties
96
+
97
+ | Property | Type | Description |
98
+ |----------|------|-------------|
99
+ | `currentUserId` | `string \| null` | Current user's ID |
100
+ | `documents` | `IDocumentOperations` | Document CRUD operations |
101
+ | `nodes` | `INodeOperations` | Node CRUD operations |
102
+ | `elements` | `IElementOperations` | Element CRUD operations |
103
+ | `batch` | `IBatchOperations` | Batch element operations |
104
+ | `authClient` | `IAuthClient` | Authentication client |
105
+
106
+ ### Document Operations
107
+
108
+ ```typescript
109
+ // Create a document
110
+ const doc = await api.documents.create({
111
+ title: "My Document",
112
+ content: "Optional description",
113
+ canvasWidth: 1920, // Optional, default: 1920
114
+ canvasHeight: 1080 // Optional, default: 1080
115
+ });
116
+
117
+ // Get a document by ID
118
+ const doc = await api.documents.get(documentId);
119
+
120
+ // List all documents
121
+ const docs = await api.documents.list();
122
+
123
+ // Update a document
124
+ await api.documents.update(documentId, {
125
+ title: "New Title",
126
+ content: "New description"
127
+ });
128
+
129
+ // Delete a document
130
+ await api.documents.delete(documentId);
131
+
132
+ // Share a document
133
+ await api.documents.share(documentId, ["user-id-1", "user-id-2"]);
134
+ ```
135
+
136
+ ### Node Operations
137
+
138
+ ```typescript
139
+ // Create a node
140
+ const node = await api.nodes.create(documentId, {
141
+ title: "My Node",
142
+ content: "Optional description",
143
+ parentNodeId: "parent-node-id", // Optional
144
+ canvasWidth: 1920,
145
+ canvasHeight: 1080
146
+ });
147
+
148
+ // Get a node
149
+ const node = await api.nodes.get(documentId, nodeId);
150
+
151
+ // List all nodes in a document
152
+ const nodes = await api.nodes.list(documentId);
153
+
154
+ // Update a node
155
+ await api.nodes.update(documentId, nodeId, {
156
+ title: "New Title"
157
+ });
158
+
159
+ // Delete a node
160
+ await api.nodes.delete(documentId, nodeId);
161
+ ```
162
+
163
+ ### Element Operations
164
+
165
+ ```typescript
166
+ // Get an element by ID
167
+ const element = await api.elements.get(documentId, nodeId, elementId);
168
+
169
+ // List all elements in a node
170
+ const elements = await api.elements.list(documentId, nodeId);
171
+
172
+ // Create a rectangle
173
+ const rect = await api.elements.create(documentId, nodeId, {
174
+ type: "rectangle",
175
+ x: 100,
176
+ y: 100,
177
+ width: 200,
178
+ height: 150,
179
+ fillColor: "#FF5733",
180
+ strokeColor: "#000000",
181
+ strokeWidth: 2,
182
+ cornerRadius: 10
183
+ });
184
+
185
+ // Create text
186
+ await api.elements.create(documentId, nodeId, {
187
+ type: "text",
188
+ x: 100,
189
+ y: 100,
190
+ text: "Hello World",
191
+ fontSize: 24,
192
+ fontFamily: "Arial",
193
+ fillColor: "#000000",
194
+ textAlign: "center"
195
+ });
196
+
197
+ // Create a connector
198
+ await api.elements.create(documentId, nodeId, {
199
+ type: "connector",
200
+ x: 0,
201
+ y: 0,
202
+ startElementId: "element-1",
203
+ endElementId: "element-2",
204
+ startAnchor: "right",
205
+ endAnchor: "left",
206
+ lineStyle: "solid",
207
+ endMarker: "arrow"
208
+ });
209
+
210
+ // Create a UML class
211
+ await api.elements.create(documentId, nodeId, {
212
+ type: "uml-class",
213
+ x: 100,
214
+ y: 100,
215
+ width: 200,
216
+ height: 150,
217
+ name: "MyClass",
218
+ attributes: "+ name: string\n- id: number",
219
+ methods: "+ getName(): string\n+ setName(name: string): void"
220
+ });
221
+
222
+ // Update an element
223
+ await api.elements.update(documentId, nodeId, elementId, {
224
+ x: 200,
225
+ y: 200,
226
+ properties: {
227
+ fillColor: "#00FF00"
228
+ }
229
+ });
230
+
231
+ // Delete an element
232
+ await api.elements.delete(documentId, nodeId, elementId);
233
+ ```
234
+
235
+ ### Batch Operations
236
+
237
+ For efficient bulk operations (ideal for AI agents and automation):
238
+
239
+ ```typescript
240
+ // Create multiple elements atomically
241
+ const elements = await api.batch.createElements(documentId, nodeId, [
242
+ { type: "rectangle", x: 100, y: 100 },
243
+ { type: "rectangle", x: 300, y: 100 },
244
+ { type: "text", x: 200, y: 200, text: "Connected" }
245
+ ]);
246
+
247
+ // Update multiple elements atomically
248
+ await api.batch.updateElements(documentId, nodeId, [
249
+ { elementId: "elem-1", x: 150, y: 150 },
250
+ { elementId: "elem-2", width: 300, height: 200 }
251
+ ]);
252
+
253
+ // Delete multiple elements atomically
254
+ await api.batch.deleteElements(documentId, nodeId, [
255
+ "elem-1",
256
+ "elem-2",
257
+ "elem-3"
258
+ ]);
259
+ ```
260
+
261
+ ## Supported Element Types
262
+
263
+ | Type | Description |
264
+ |------|-------------|
265
+ | `rectangle` | Rectangle shape with fill, stroke, corner radius |
266
+ | `text` | Text element with font customization |
267
+ | `connector` | Line connecting two elements |
268
+ | `uml-class` | UML class diagram element |
269
+ | `uml-interface` | UML interface element |
270
+ | `uml-component` | UML component element |
271
+ | `uml-package` | UML package element |
272
+ | `uml-artifact` | UML artifact element |
273
+ | `uml-note` | UML note element |
274
+ | `custom:{shapeId}` | Custom SVG shape (requires premium) |
275
+
276
+ ## Link Navigation
277
+
278
+ Elements can act as links to other nodes:
279
+
280
+ ```typescript
281
+ // Create an element that links to another node
282
+ await api.elements.create(documentId, nodeId, {
283
+ type: "rectangle",
284
+ x: 100,
285
+ y: 100,
286
+ isLink: true,
287
+ linkTarget: "other-node-id" // Node ID to navigate to
288
+ });
289
+ ```
290
+
291
+ ## Error Handling
292
+
293
+ The API throws typed errors for different failure cases:
294
+
295
+ ```typescript
296
+ import {
297
+ GraphKnowledgeAPI,
298
+ AuthenticationError,
299
+ NotFoundError,
300
+ ValidationError,
301
+ PermissionError
302
+ } from "@graph-knowledge/api";
303
+
304
+ try {
305
+ await api.documents.get("non-existent");
306
+ } catch (error) {
307
+ if (error instanceof NotFoundError) {
308
+ console.log("Document not found");
309
+ } else if (error instanceof AuthenticationError) {
310
+ console.log("Not authenticated");
311
+ } else if (error instanceof ValidationError) {
312
+ console.log("Invalid input:", error.field);
313
+ } else if (error instanceof PermissionError) {
314
+ console.log("Permission denied (e.g., premium required)");
315
+ }
316
+ }
317
+ ```
318
+
319
+ ## Testing
320
+
321
+ The library exports mock implementations for testing:
322
+
323
+ ```typescript
324
+ import {
325
+ MockAuthClient,
326
+ MockFirestoreClient
327
+ } from "@graph-knowledge/api";
328
+ import { ElementOperations } from "@graph-knowledge/api";
329
+ import { ElementValidatorRegistry } from "@graph-knowledge/api";
330
+
331
+ describe("MyTest", () => {
332
+ let mockAuth: MockAuthClient;
333
+ let mockFirestore: MockFirestoreClient;
334
+
335
+ beforeEach(() => {
336
+ mockAuth = new MockAuthClient({ userId: "test-user" });
337
+ mockFirestore = new MockFirestoreClient();
338
+ });
339
+
340
+ it("should work with mocks", async () => {
341
+ // Seed test data
342
+ mockFirestore.seed("documents/doc-1/nodes/node-1", {
343
+ id: "node-1",
344
+ title: "Test Node",
345
+ elements: []
346
+ });
347
+
348
+ // Test your code...
349
+ });
350
+ });
351
+ ```
352
+
353
+ ## Architecture
354
+
355
+ The library follows SOLID principles:
356
+
357
+ - **Single Responsibility**: Each class has one job
358
+ - **Open/Closed**: Element validators use registry pattern for extensibility
359
+ - **Liskov Substitution**: All implementations can be swapped via interfaces
360
+ - **Interface Segregation**: Small, focused interfaces
361
+ - **Dependency Inversion**: Operations depend on interfaces, not implementations
362
+
363
+ ```
364
+ GraphKnowledgeAPI (Composition Root)
365
+ ├── FirebaseAuthClient : IAuthClient
366
+ ├── FirebaseFirestoreClient : IFirestoreClient
367
+ ├── DocumentOperations : IDocumentOperations
368
+ ├── NodeOperations : INodeOperations
369
+ ├── ElementOperations : IElementOperations
370
+ ├── BatchOperations : IBatchOperations
371
+ └── ElementValidatorRegistry : IElementValidatorRegistry
372
+ ├── RectangleValidator
373
+ ├── TextValidator
374
+ ├── ConnectorValidator
375
+ └── UmlValidators...
376
+ ```
377
+
378
+ ## Building
379
+
380
+ ```bash
381
+ # Build
382
+ nx build api
383
+
384
+ # Test
385
+ nx test api
386
+
387
+ # Lint
388
+ nx lint api
389
+
390
+ # Publish to npm (after build)
391
+ nx publish api
392
+ ```
393
+
394
+ ## License
395
+
396
+ MIT
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@graph-knowledge/api",
3
+ "version": "0.1.0",
4
+ "description": "Headless Document API for Graph Knowledge - programmatic access to documents, nodes, and elements",
5
+ "license": "MIT",
6
+ "author": "Graph Knowledge Team",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/iliedanila/knowledge-graph.git",
10
+ "directory": "libs/api"
11
+ },
12
+ "keywords": [
13
+ "graph",
14
+ "knowledge-graph",
15
+ "document-api",
16
+ "firebase",
17
+ "uml",
18
+ "diagram"
19
+ ],
20
+ "main": "./src/index.js",
21
+ "module": "./src/index.mjs",
22
+ "types": "./src/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./src/index.d.ts",
26
+ "import": "./src/index.mjs",
27
+ "require": "./src/index.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "src/**/*.js",
32
+ "src/**/*.mjs",
33
+ "src/**/*.d.ts",
34
+ "README.md"
35
+ ],
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ },
39
+ "peerDependencies": {
40
+ "firebase": ">=10.0.0 <13.0.0"
41
+ },
42
+ "sideEffects": false,
43
+ "type": "commonjs"
44
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export { GraphKnowledgeAPI } from "./lib/graph-knowledge-api";
2
+ export type { ApiConfig, FirebaseConfig } from "./lib/config/api-config";
3
+ export type { IAuthClient } from "./lib/interfaces/auth-client.interface";
4
+ export type { IFirestoreClient, IBatchWriter } from "./lib/interfaces/firestore-client.interface";
5
+ export type { IDocumentOperations } from "./lib/interfaces/document-operations.interface";
6
+ export type { INodeOperations } from "./lib/interfaces/node-operations.interface";
7
+ export type { IElementOperations } from "./lib/interfaces/element-operations.interface";
8
+ export type { IBatchOperations, BatchUpdateElementInput } from "./lib/interfaces/batch-operations.interface";
9
+ export type { IElementTypeValidator, IElementValidatorRegistry } from "./lib/interfaces/element-validator.interface";
10
+ export type { CreateDocumentInput, UpdateDocumentInput, DocumentResult, CreateNodeInput, UpdateNodeInput, NodeResult } from "./lib/types/api-types";
11
+ export type { BaseElementInput, RectangleInput, TextInput, ConnectorInput, ConnectorAnchor, LineStyle, MarkerType, UmlClassInput, UmlInterfaceInput, UmlComponentInput, UmlPackageInput, UmlArtifactInput, UmlNoteInput, CustomShapeInput, AnyElementInput, UpdateElementInput } from "./lib/types/element-input-types";
12
+ export { GraphKnowledgeAPIError, AuthenticationError, NotFoundError, ValidationError, PermissionError } from "./lib/errors/api-errors";
13
+ export type { Document, GraphNode, GraphElement } from "./lib/models";
14
+ export { CURRENT_DOCUMENT_SCHEMA_VERSION } from "./lib/models";
15
+ export { LinkLevelManager } from "./lib/utils/link-level-manager";
16
+ export type { LevelChange, LinkState } from "./lib/utils/link-level-manager";
17
+ export { MockAuthClient } from "./lib/testing/mock-auth-client";
18
+ export { MockFirestoreClient } from "./lib/testing/mock-firestore-client";
package/src/index.js ADDED
@@ -0,0 +1,19 @@
1
+ // =============================================================================
2
+ // Graph Knowledge Headless Document API
3
+ // =============================================================================
4
+ // Main API Class
5
+ export { GraphKnowledgeAPI } from "./lib/graph-knowledge-api";
6
+ // =============================================================================
7
+ // Errors
8
+ // =============================================================================
9
+ export { GraphKnowledgeAPIError, AuthenticationError, NotFoundError, ValidationError, PermissionError } from "./lib/errors/api-errors";
10
+ export { CURRENT_DOCUMENT_SCHEMA_VERSION } from "./lib/models";
11
+ // =============================================================================
12
+ // Utilities
13
+ // =============================================================================
14
+ export { LinkLevelManager } from "./lib/utils/link-level-manager";
15
+ // =============================================================================
16
+ // Testing Utilities
17
+ // =============================================================================
18
+ export { MockAuthClient } from "./lib/testing/mock-auth-client";
19
+ export { MockFirestoreClient } from "./lib/testing/mock-firestore-client";
@@ -0,0 +1,24 @@
1
+ import { Auth } from "firebase/auth";
2
+ import { Firestore } from "firebase/firestore";
3
+ import { IAuthClient } from "../interfaces/auth-client.interface";
4
+ /**
5
+ * Firebase Auth implementation of IAuthClient.
6
+ */
7
+ export declare class FirebaseAuthClient implements IAuthClient {
8
+ private readonly auth;
9
+ private readonly firestore;
10
+ private _currentUser;
11
+ private _initialized;
12
+ private _initPromise;
13
+ constructor(auth: Auth, firestore: Firestore);
14
+ /**
15
+ * Waits for auth state to be initialized.
16
+ */
17
+ waitForInit(): Promise<void>;
18
+ signIn(email: string, password: string): Promise<void>;
19
+ signOut(): Promise<void>;
20
+ get currentUserId(): string | null;
21
+ requireAuth(): string;
22
+ isPremium(): Promise<boolean>;
23
+ requirePremium(): Promise<void>;
24
+ }
@@ -0,0 +1,76 @@
1
+ import { signInWithEmailAndPassword, signOut as firebaseSignOut, onAuthStateChanged } from "firebase/auth";
2
+ import { doc, getDoc } from "firebase/firestore";
3
+ import { AuthenticationError, PermissionError } from "../errors/api-errors";
4
+ /**
5
+ * Firebase Auth implementation of IAuthClient.
6
+ */
7
+ export class FirebaseAuthClient {
8
+ auth;
9
+ firestore;
10
+ _currentUser = null;
11
+ _initialized = false;
12
+ _initPromise;
13
+ constructor(auth, firestore) {
14
+ this.auth = auth;
15
+ this.firestore = firestore;
16
+ this._initPromise = new Promise((resolve) => {
17
+ const unsubscribe = onAuthStateChanged(this.auth, (user) => {
18
+ this._currentUser = user;
19
+ if (!this._initialized) {
20
+ this._initialized = true;
21
+ unsubscribe();
22
+ resolve();
23
+ }
24
+ });
25
+ });
26
+ }
27
+ /**
28
+ * Waits for auth state to be initialized.
29
+ */
30
+ async waitForInit() {
31
+ return this._initPromise;
32
+ }
33
+ async signIn(email, password) {
34
+ try {
35
+ const credential = await signInWithEmailAndPassword(this.auth, email, password);
36
+ this._currentUser = credential.user;
37
+ }
38
+ catch (error) {
39
+ const message = error instanceof Error ? error.message : "Sign in failed";
40
+ throw new AuthenticationError(message);
41
+ }
42
+ }
43
+ async signOut() {
44
+ await firebaseSignOut(this.auth);
45
+ this._currentUser = null;
46
+ }
47
+ get currentUserId() {
48
+ return this._currentUser?.uid ?? null;
49
+ }
50
+ requireAuth() {
51
+ if (!this._currentUser) {
52
+ throw new AuthenticationError("Not authenticated");
53
+ }
54
+ return this._currentUser.uid;
55
+ }
56
+ async isPremium() {
57
+ if (!this._currentUser) {
58
+ return false;
59
+ }
60
+ // Read premium status from user profile in Firestore
61
+ const userDoc = doc(this.firestore, `users/${this._currentUser.uid}`);
62
+ const snapshot = await getDoc(userDoc);
63
+ if (!snapshot.exists()) {
64
+ return false;
65
+ }
66
+ const profile = snapshot.data();
67
+ return profile?.["isPremium"] === true;
68
+ }
69
+ async requirePremium() {
70
+ this.requireAuth();
71
+ const premium = await this.isPremium();
72
+ if (!premium) {
73
+ throw new PermissionError("Premium subscription required");
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,22 @@
1
+ import { Firestore } from "firebase/firestore";
2
+ import { IFirestoreClient, IBatchWriter } from "../interfaces/firestore-client.interface";
3
+ /**
4
+ * Firebase Firestore implementation of IFirestoreClient.
5
+ */
6
+ export declare class FirebaseFirestoreClient implements IFirestoreClient {
7
+ private readonly db;
8
+ constructor(db: Firestore);
9
+ getDocument<T>(path: string): Promise<(T & {
10
+ id: string;
11
+ }) | null>;
12
+ setDocument<T extends object>(path: string, data: T): Promise<void>;
13
+ updateDocument<T extends object>(path: string, data: Partial<T>): Promise<void>;
14
+ deleteDocument(path: string): Promise<void>;
15
+ getCollection<T>(path: string): Promise<(T & {
16
+ id: string;
17
+ })[]>;
18
+ queryCollection<T>(path: string, field: string, value: string): Promise<(T & {
19
+ id: string;
20
+ })[]>;
21
+ batch(): IBatchWriter;
22
+ }
@@ -0,0 +1,79 @@
1
+ import { doc, getDoc, setDoc, updateDoc, deleteDoc, collection, getDocs, query, where, writeBatch } from "firebase/firestore";
2
+ /**
3
+ * Firebase Firestore batch writer implementation.
4
+ */
5
+ class FirestoreBatchWriter {
6
+ db;
7
+ batch;
8
+ constructor(db, batch) {
9
+ this.db = db;
10
+ this.batch = batch;
11
+ }
12
+ set(path, data) {
13
+ const docRef = doc(this.db, path);
14
+ this.batch.set(docRef, data);
15
+ }
16
+ update(path, data) {
17
+ const docRef = doc(this.db, path);
18
+ this.batch.update(docRef, data);
19
+ }
20
+ delete(path) {
21
+ const docRef = doc(this.db, path);
22
+ this.batch.delete(docRef);
23
+ }
24
+ async commit() {
25
+ await this.batch.commit();
26
+ }
27
+ }
28
+ /**
29
+ * Firebase Firestore implementation of IFirestoreClient.
30
+ */
31
+ export class FirebaseFirestoreClient {
32
+ db;
33
+ constructor(db) {
34
+ this.db = db;
35
+ }
36
+ async getDocument(path) {
37
+ const docRef = doc(this.db, path);
38
+ const snapshot = await getDoc(docRef);
39
+ if (!snapshot.exists()) {
40
+ return null;
41
+ }
42
+ return {
43
+ id: snapshot.id,
44
+ ...snapshot.data()
45
+ };
46
+ }
47
+ async setDocument(path, data) {
48
+ const docRef = doc(this.db, path);
49
+ await setDoc(docRef, data);
50
+ }
51
+ async updateDocument(path, data) {
52
+ const docRef = doc(this.db, path);
53
+ await updateDoc(docRef, data);
54
+ }
55
+ async deleteDocument(path) {
56
+ const docRef = doc(this.db, path);
57
+ await deleteDoc(docRef);
58
+ }
59
+ async getCollection(path) {
60
+ const collectionRef = collection(this.db, path);
61
+ const snapshot = await getDocs(collectionRef);
62
+ return snapshot.docs.map((doc) => ({
63
+ id: doc.id,
64
+ ...doc.data()
65
+ }));
66
+ }
67
+ async queryCollection(path, field, value) {
68
+ const collectionRef = collection(this.db, path);
69
+ const q = query(collectionRef, where(field, "==", value));
70
+ const snapshot = await getDocs(q);
71
+ return snapshot.docs.map((doc) => ({
72
+ id: doc.id,
73
+ ...doc.data()
74
+ }));
75
+ }
76
+ batch() {
77
+ return new FirestoreBatchWriter(this.db, writeBatch(this.db));
78
+ }
79
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Firebase configuration required to initialize the API.
3
+ */
4
+ export interface FirebaseConfig {
5
+ apiKey: string;
6
+ authDomain: string;
7
+ projectId: string;
8
+ storageBucket: string;
9
+ messagingSenderId: string;
10
+ appId: string;
11
+ }
12
+ /**
13
+ * Configuration options for GraphKnowledgeAPI.
14
+ */
15
+ export interface ApiConfig {
16
+ /** Firebase project configuration */
17
+ firebaseConfig: FirebaseConfig;
18
+ /** Optional app name for multiple Firebase instances */
19
+ appName?: string;
20
+ }