document-drive 6.0.0-dev.6 → 6.0.0-dev.61

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 (85) hide show
  1. package/dist/src/cache/lru.js +1 -1
  2. package/dist/src/cache/lru.js.map +1 -1
  3. package/dist/src/drive-document-model/gen/document-model.d.ts.map +1 -1
  4. package/dist/src/drive-document-model/gen/document-model.js +2 -2
  5. package/dist/src/drive-document-model/gen/document-model.js.map +1 -1
  6. package/dist/src/drive-document-model/gen/schema/types.d.ts +31 -2
  7. package/dist/src/drive-document-model/gen/schema/types.d.ts.map +1 -1
  8. package/dist/src/drive-document-model/gen/schema/zod.d.ts +6 -1
  9. package/dist/src/drive-document-model/gen/schema/zod.d.ts.map +1 -1
  10. package/dist/src/drive-document-model/gen/schema/zod.js +41 -2
  11. package/dist/src/drive-document-model/gen/schema/zod.js.map +1 -1
  12. package/dist/src/drive-document-model/src/reducers/drive.d.ts.map +1 -1
  13. package/dist/src/drive-document-model/src/reducers/drive.js +34 -6
  14. package/dist/src/drive-document-model/src/reducers/drive.js.map +1 -1
  15. package/dist/src/drive-document-model/src/reducers/node.d.ts.map +1 -1
  16. package/dist/src/drive-document-model/src/reducers/node.js +12 -0
  17. package/dist/src/drive-document-model/src/reducers/node.js.map +1 -1
  18. package/dist/src/processors/processor-manager.d.ts +4 -4
  19. package/dist/src/processors/processor-manager.d.ts.map +1 -1
  20. package/dist/src/processors/processor-manager.js +6 -6
  21. package/dist/src/processors/processor-manager.js.map +1 -1
  22. package/dist/src/processors/relational.d.ts +10 -10
  23. package/dist/src/processors/relational.d.ts.map +1 -1
  24. package/dist/src/processors/relational.js +4 -4
  25. package/dist/src/processors/relational.js.map +1 -1
  26. package/dist/src/processors/types.d.ts +25 -23
  27. package/dist/src/processors/types.d.ts.map +1 -1
  28. package/dist/src/processors/utils.d.ts +6 -6
  29. package/dist/src/processors/utils.d.ts.map +1 -1
  30. package/dist/src/processors/utils.js +11 -11
  31. package/dist/src/processors/utils.js.map +1 -1
  32. package/dist/src/queue/event.js +9 -9
  33. package/dist/src/queue/event.js.map +1 -1
  34. package/dist/src/read-mode/server.js +2 -2
  35. package/dist/src/read-mode/server.js.map +1 -1
  36. package/dist/src/server/base-server.d.ts.map +1 -1
  37. package/dist/src/server/base-server.js +54 -40
  38. package/dist/src/server/base-server.js.map +1 -1
  39. package/dist/src/server/listener/listener-manager.d.ts.map +1 -1
  40. package/dist/src/server/listener/listener-manager.js +32 -32
  41. package/dist/src/server/listener/listener-manager.js.map +1 -1
  42. package/dist/src/server/sync-manager.d.ts.map +1 -1
  43. package/dist/src/server/sync-manager.js +10 -13
  44. package/dist/src/server/sync-manager.js.map +1 -1
  45. package/dist/src/server/transmitter/internal.d.ts +3 -3
  46. package/dist/src/server/transmitter/internal.d.ts.map +1 -1
  47. package/dist/src/server/transmitter/internal.js +1 -1
  48. package/dist/src/server/transmitter/internal.js.map +1 -1
  49. package/dist/src/server/transmitter/pull-responder.d.ts.map +1 -1
  50. package/dist/src/server/transmitter/pull-responder.js +42 -42
  51. package/dist/src/server/transmitter/pull-responder.js.map +1 -1
  52. package/dist/src/server/transmitter/switchboard-push.d.ts.map +1 -1
  53. package/dist/src/server/transmitter/switchboard-push.js +7 -7
  54. package/dist/src/server/transmitter/switchboard-push.js.map +1 -1
  55. package/dist/src/storage/browser.js +1 -1
  56. package/dist/src/storage/browser.js.map +1 -1
  57. package/dist/src/storage/filesystem.js +1 -1
  58. package/dist/src/storage/filesystem.js.map +1 -1
  59. package/dist/src/storage/ipfs.d.ts +1 -43
  60. package/dist/src/storage/ipfs.d.ts.map +1 -1
  61. package/dist/src/storage/ipfs.js +490 -415
  62. package/dist/src/storage/ipfs.js.map +1 -1
  63. package/dist/src/storage/memory.js +1 -1
  64. package/dist/src/storage/memory.js.map +1 -1
  65. package/dist/src/storage/prisma/prisma.d.ts.map +1 -1
  66. package/dist/src/storage/prisma/prisma.js +6 -5
  67. package/dist/src/storage/prisma/prisma.js.map +1 -1
  68. package/dist/src/utils/default-drives-manager.js +2 -2
  69. package/dist/src/utils/default-drives-manager.js.map +1 -1
  70. package/dist/src/utils/gql-transformations.d.ts +2 -1
  71. package/dist/src/utils/gql-transformations.d.ts.map +1 -1
  72. package/dist/src/utils/gql-transformations.js +2 -1
  73. package/dist/src/utils/gql-transformations.js.map +1 -1
  74. package/dist/src/utils/graphql.d.ts.map +1 -1
  75. package/dist/src/utils/graphql.js +6 -34
  76. package/dist/src/utils/graphql.js.map +1 -1
  77. package/dist/src/utils/logger.d.ts +2 -20
  78. package/dist/src/utils/logger.d.ts.map +1 -1
  79. package/dist/src/utils/logger.js +1 -106
  80. package/dist/src/utils/logger.js.map +1 -1
  81. package/dist/src/utils/types.d.ts +1 -7
  82. package/dist/src/utils/types.d.ts.map +1 -1
  83. package/dist/test/internal-listener.test.js.map +1 -1
  84. package/dist/tsconfig.tsbuildinfo +1 -1
  85. package/package.json +19 -28
@@ -1,416 +1,491 @@
1
- import { mfs } from "@helia/mfs";
2
- import { DocumentAlreadyExistsError, DocumentAlreadyExistsReason, DocumentNotFoundError, mergeOperations, } from "document-drive";
3
- import {} from "document-model";
4
- import stringify from "json-stringify-deterministic";
5
- export class IPFSStorage {
6
- fs;
7
- constructor(helia) {
8
- this.fs = mfs(helia);
9
- }
10
- ////////////////////////////////
11
- // IDocumentView
12
- ////////////////////////////////
13
- async resolveIds(slugs, signal) {
14
- const ids = [];
15
- for (const slug of slugs) {
16
- const documentId = this.slugToDocumentId[slug];
17
- if (!documentId) {
18
- throw new DocumentNotFoundError(slug);
19
- }
20
- ids.push(documentId);
21
- }
22
- if (signal?.aborted) {
23
- throw new AbortError("Aborted");
24
- }
25
- return Promise.resolve(ids);
26
- }
27
- async resolveSlugs(ids, signal) {
28
- const slugs = [];
29
- for (const id of ids) {
30
- const document = await this.get(id);
31
- if (!document) {
32
- throw new DocumentNotFoundError(id);
33
- }
34
- if (signal?.aborted) {
35
- throw new AbortError("Aborted");
36
- }
37
- slugs.push(document.slug);
38
- }
39
- return Promise.resolve(slugs);
40
- }
41
- ////////////////////////////////
42
- // IDocumentStorage
43
- ////////////////////////////////
44
- async exists(documentId) {
45
- try {
46
- await this.fs.stat(this._buildDocumentPath(documentId));
47
- return true;
48
- }
49
- catch (error) {
50
- //
51
- }
52
- try {
53
- await this.fs.stat(this._buildDrivePath(documentId));
54
- return true;
55
- }
56
- catch (error) {
57
- //
58
- }
59
- return false;
60
- }
61
- async create(document) {
62
- const documentId = document.id;
63
- if (await this.exists(documentId)) {
64
- throw new DocumentAlreadyExistsError(documentId);
65
- }
66
- const slug = document.header.slug?.length > 0 ? document.header.slug : documentId;
67
- const slugManifest = await this.getSlugManifest();
68
- if (slugManifest.slugToId[slug]) {
69
- throw new DocumentAlreadyExistsError(documentId, DocumentAlreadyExistsReason.SLUG);
70
- }
71
- document.header.slug = slug;
72
- await this.fs.writeBytes(new TextEncoder().encode(stringify(document)), this._buildDocumentPath(documentId));
73
- // Update the slug manifest if the document has a slug
74
- slugManifest.slugToId[slug] = documentId;
75
- await this.updateSlugManifest(slugManifest);
76
- // temporary: initialize an empty manifest for new drives
77
- if (document.header.documentType === "powerhouse/document-drive") {
78
- this.updateDriveManifest(documentId, { documentIds: [] });
79
- }
80
- }
81
- async get(documentId) {
82
- try {
83
- const documentPath = this._buildDocumentPath(documentId);
84
- const chunks = [];
85
- for await (const chunk of this.fs.cat(documentPath)) {
86
- chunks.push(chunk);
87
- }
88
- const buffer = Buffer.concat(chunks);
89
- const content = new TextDecoder().decode(buffer);
90
- return JSON.parse(content);
91
- }
92
- catch (error) {
93
- return Promise.reject(new DocumentNotFoundError(documentId));
94
- }
95
- }
96
- async getBySlug(slug) {
97
- const slugManifest = await this.getSlugManifest();
98
- const documentId = slugManifest.slugToId[slug];
99
- if (!documentId) {
100
- return Promise.reject(new DocumentNotFoundError(slug));
101
- }
102
- return this.get(documentId);
103
- }
104
- async findByType(documentModelType, limit = 100, cursor) {
105
- // Get all document files from IPFS
106
- const documentFiles = [];
107
- try {
108
- for await (const entry of this.fs.ls("/")) {
109
- if (entry.name.startsWith("document-") &&
110
- entry.name.endsWith(".json")) {
111
- documentFiles.push(entry.name);
112
- }
113
- }
114
- }
115
- catch (error) {
116
- // If directory listing fails, return empty results
117
- return { documents: [], nextCursor: undefined };
118
- }
119
- // Load documents with matching type and collect their metadata
120
- const documentsAndIds = [];
121
- for (const fileName of documentFiles) {
122
- // Extract the document ID from the filename
123
- const documentId = fileName.replace("document-", "").replace(".json", "");
124
- try {
125
- // Read and parse the document from IPFS
126
- const chunks = [];
127
- for await (const chunk of this.fs.cat(`/${fileName}`)) {
128
- chunks.push(chunk);
129
- }
130
- const buffer = Buffer.concat(chunks);
131
- const content = new TextDecoder().decode(buffer);
132
- const document = JSON.parse(content);
133
- // Only include documents of the requested type
134
- if (document.header.documentType === documentModelType) {
135
- documentsAndIds.push({ id: documentId, document });
136
- }
137
- }
138
- catch (error) {
139
- // Skip files that can't be read or parsed
140
- continue;
141
- }
142
- }
143
- // Sort by creation date first, then by ID
144
- documentsAndIds.sort((a, b) => {
145
- const aDate = new Date(a.document.header.createdAtUtcIso);
146
- const bDate = new Date(b.document.header.createdAtUtcIso);
147
- if (aDate.getTime() === bDate.getTime()) {
148
- return a.id.localeCompare(b.id);
149
- }
150
- return aDate.getTime() - bDate.getTime();
151
- });
152
- // cursor
153
- let startIndex = 0;
154
- if (cursor) {
155
- const index = documentsAndIds.findIndex(({ id }) => id === cursor);
156
- if (index !== -1) {
157
- startIndex = index;
158
- }
159
- }
160
- // count to limit
161
- const endIndex = Math.min(startIndex + limit, documentsAndIds.length);
162
- let nextCursor;
163
- if (endIndex < documentsAndIds.length) {
164
- nextCursor = documentsAndIds[endIndex].id;
165
- }
166
- return {
167
- documents: documentsAndIds
168
- .slice(startIndex, endIndex)
169
- .map(({ id }) => id),
170
- nextCursor,
171
- };
172
- }
173
- async delete(documentId) {
174
- // Remove from slug manifest if it has a slug
175
- try {
176
- const document = await this.get(documentId);
177
- const slug = document.header.slug?.length > 0 ? document.header.slug : documentId;
178
- if (slug) {
179
- const slugManifest = await this.getSlugManifest();
180
- if (slugManifest.slugToId[slug] === documentId) {
181
- delete slugManifest.slugToId[slug];
182
- await this.updateSlugManifest(slugManifest);
183
- }
184
- }
185
- }
186
- catch (error) {
187
- // If we can't get the document, we can't remove its slug
188
- }
189
- // delete the document from parent manifests
190
- const parents = await this.getParents(documentId);
191
- for (const parent of parents) {
192
- await this.removeChild(parent, documentId);
193
- }
194
- // check children: any children that are only children of this document should be deleted
195
- const children = await this.getChildren(documentId);
196
- for (const child of children) {
197
- const childParents = await this.getParents(child);
198
- if (childParents.length === 1 && childParents[0] === documentId) {
199
- await this.delete(child);
200
- }
201
- }
202
- // delete any manifest for this document
203
- try {
204
- await this.fs.rm(this._buildDriveManifestPath(documentId));
205
- }
206
- catch (error) {
207
- // there may be no manifest for this document
208
- }
209
- // finally, delete the specified document
210
- try {
211
- await this.fs.rm(this._buildDocumentPath(documentId));
212
- return true;
213
- }
214
- catch (error) {
215
- return false;
216
- }
217
- }
218
- async addChild(parentId, childId) {
219
- if (parentId === childId) {
220
- throw new Error("Cannot associate a document with itself");
221
- }
222
- // check if the child is a parent of the parent
223
- const children = await this.getChildren(childId);
224
- if (children.includes(parentId)) {
225
- throw new Error("Cannot associate a document with its child");
226
- }
227
- const manifest = await this.getDriveManifest(parentId);
228
- if (!manifest.documentIds.includes(childId)) {
229
- manifest.documentIds.push(childId);
230
- await this.updateDriveManifest(parentId, manifest);
231
- }
232
- }
233
- async removeChild(parentId, childId) {
234
- const manifest = await this.getDriveManifest(parentId);
235
- const docIndex = manifest.documentIds.indexOf(childId);
236
- if (docIndex !== -1) {
237
- manifest.documentIds.splice(docIndex, 1);
238
- await this.updateDriveManifest(parentId, manifest);
239
- return true;
240
- }
241
- return false;
242
- }
243
- async getChildren(parentId) {
244
- const manifest = await this.getDriveManifest(parentId);
245
- return manifest.documentIds;
246
- }
247
- async getParents(childId) {
248
- const parents = [];
249
- // Get all manifest files by listing the directory and finding manifest files
250
- try {
251
- for await (const entry of this.fs.ls("/")) {
252
- if (entry.name.startsWith("manifest-") &&
253
- entry.name.endsWith(".json")) {
254
- // Extract the driveId from the manifest filename
255
- const driveId = entry.name
256
- .replace("manifest-", "")
257
- .replace(".json", "");
258
- // Check if the manifest contains the childId
259
- const manifest = await this.getDriveManifest(driveId);
260
- if (manifest.documentIds.includes(childId)) {
261
- parents.push(driveId);
262
- }
263
- }
264
- }
265
- }
266
- catch (error) {
267
- // If listing fails, return empty array
268
- }
269
- return parents;
270
- }
271
- // IDriveStorage
272
- ////////////////////////////////
273
- async addDocumentOperations(drive, id, operations, header) {
274
- const document = await this.get(id);
275
- if (!document) {
276
- throw new Error(`Document with id ${id} not found`);
277
- }
278
- const mergedOperations = mergeOperations(document.operations, operations);
279
- await this.create(id, {
280
- ...document,
281
- header,
282
- operations: mergedOperations,
283
- });
284
- await this.addChild(drive, id);
285
- }
286
- async getDrives() {
287
- const result = await this.findByType("powerhouse/document-drive");
288
- return result.documents;
289
- }
290
- async getDrive(id) {
291
- try {
292
- const drivePath = this._buildDrivePath(id);
293
- const chunks = [];
294
- for await (const chunk of this.fs.cat(drivePath)) {
295
- chunks.push(chunk);
296
- }
297
- const buffer = Buffer.concat(chunks);
298
- const content = new TextDecoder().decode(buffer);
299
- return JSON.parse(content);
300
- }
301
- catch {
302
- throw new Error(`Drive with id ${id} not found`);
303
- }
304
- }
305
- async addDriveOperations(id, operations, header) {
306
- const drive = await this.getDrive(id);
307
- const mergedOperations = mergeOperations(drive.operations, operations);
308
- await this.create(id, {
309
- ...drive,
310
- header,
311
- operations: mergedOperations,
312
- });
313
- }
314
- async clearStorage() {
315
- // Delete all files
316
- try {
317
- for await (const entry of this.fs.ls("/")) {
318
- if (entry.type === "file") {
319
- await this.fs.rm(`/${entry.name}`);
320
- }
321
- }
322
- }
323
- catch (error) {
324
- // Ignore any errors when trying to list/delete files
325
- }
326
- }
327
- async getSynchronizationUnitsRevision(units) {
328
- const results = await Promise.allSettled(units.map(async (unit) => {
329
- try {
330
- const document = await this.get(unit.documentId);
331
- if (!document) {
332
- return undefined;
333
- }
334
- const operation = document.operations[unit.scope].at(-1);
335
- if (operation) {
336
- return {
337
- documentId: unit.documentId,
338
- scope: unit.scope,
339
- branch: unit.branch,
340
- lastUpdated: operation.timestampUtcMs,
341
- revision: operation.index,
342
- };
343
- }
344
- }
345
- catch {
346
- return undefined;
347
- }
348
- }));
349
- return results.reduce((acc, curr) => {
350
- if (curr.status === "fulfilled" && curr.value !== undefined) {
351
- acc.push(curr.value);
352
- }
353
- return acc;
354
- }, []);
355
- }
356
- ////////////////////////////////
357
- // Private methods
358
- ////////////////////////////////
359
- _buildDocumentPath(documentId) {
360
- return `/document-${documentId}.json`;
361
- }
362
- _buildDrivePath(driveId) {
363
- return `/drive-${driveId}.json`;
364
- }
365
- _buildDriveManifestPath(driveId) {
366
- return `/manifest-${driveId}.json`;
367
- }
368
- _buildSlugManifestPath() {
369
- return `/slugs.json`;
370
- }
371
- async getDriveManifest(driveId) {
372
- try {
373
- const manifestPath = this._buildDriveManifestPath(driveId);
374
- const chunks = [];
375
- for await (const chunk of this.fs.cat(manifestPath)) {
376
- chunks.push(chunk);
377
- }
378
- const buffer = Buffer.concat(chunks);
379
- const content = new TextDecoder().decode(buffer);
380
- return JSON.parse(content);
381
- }
382
- catch (error) {
383
- // If manifest doesn't exist, return an empty one
384
- return { documentIds: [] };
385
- }
386
- }
387
- async updateDriveManifest(driveId, manifest) {
388
- const manifestPath = this._buildDriveManifestPath(driveId);
389
- const manifestContent = stringify(manifest);
390
- const manifestBuffer = new TextEncoder().encode(manifestContent);
391
- await this.fs.writeBytes(manifestBuffer, manifestPath, { force: true });
392
- }
393
- async getSlugManifest() {
394
- try {
395
- const manifestPath = this._buildSlugManifestPath();
396
- const chunks = [];
397
- for await (const chunk of this.fs.cat(manifestPath)) {
398
- chunks.push(chunk);
399
- }
400
- const buffer = Buffer.concat(chunks);
401
- const content = new TextDecoder().decode(buffer);
402
- return JSON.parse(content);
403
- }
404
- catch (error) {
405
- // If manifest doesn't exist, return an empty one
406
- return { slugToId: {} };
407
- }
408
- }
409
- async updateSlugManifest(manifest) {
410
- const manifestPath = this._buildSlugManifestPath();
411
- const manifestContent = stringify(manifest);
412
- const manifestBuffer = new TextEncoder().encode(manifestContent);
413
- await this.fs.writeBytes(manifestBuffer, manifestPath, { force: true });
414
- }
415
- }
1
+ // @ts-nocheck
2
+ // TODO fix interface errors
3
+ // import type { MFS } from "@helia/mfs";
4
+ // import { mfs } from "@helia/mfs";
5
+ // import type {
6
+ // IDocumentOperationStorage,
7
+ // IDocumentStorage,
8
+ // } from "document-drive";
9
+ // import {
10
+ // DocumentAlreadyExistsError,
11
+ // DocumentAlreadyExistsReason,
12
+ // DocumentNotFoundError,
13
+ // mergeOperations,
14
+ // type DocumentDriveAction,
15
+ // type DocumentDriveDocument,
16
+ // type SynchronizationUnitQuery,
17
+ // } from "document-drive";
18
+ // import {
19
+ // type Operation,
20
+ // type PHDocument,
21
+ // type PHDocumentHeader,
22
+ // } from "document-model";
23
+ // import type { Helia } from "helia";
24
+ // import stringify from "json-stringify-deterministic";
25
+ export {};
26
+ // // Interface for drive manifest that tracks document IDs in a drive
27
+ // interface DriveManifest {
28
+ // documentIds: string[];
29
+ // }
30
+ // // Interface for slug manifest that maps slugs to document IDs
31
+ // interface SlugManifest {
32
+ // slugToId: Record<string, string>;
33
+ // }
34
+ // export class IPFSStorage
35
+ // implements IDriveStorage, IDocumentOperationStorage, IDocumentStorage
36
+ // {
37
+ // private fs: MFS;
38
+ // constructor(helia: Helia) {
39
+ // this.fs = mfs(helia);
40
+ // }
41
+ // ////////////////////////////////
42
+ // // IDocumentView
43
+ // ////////////////////////////////
44
+ // async resolveIds(slugs: string[], signal?: AbortSignal): Promise<string[]> {
45
+ // const ids = [];
46
+ // for (const slug of slugs) {
47
+ // const documentId = this.slugToDocumentId[slug];
48
+ // if (!documentId) {
49
+ // throw new DocumentNotFoundError(slug);
50
+ // }
51
+ // ids.push(documentId);
52
+ // }
53
+ // if (signal?.aborted) {
54
+ // throw new AbortError("Aborted");
55
+ // }
56
+ // return Promise.resolve(ids);
57
+ // }
58
+ // async resolveSlugs(ids: string[], signal?: AbortSignal): Promise<string[]> {
59
+ // const slugs = [];
60
+ // for (const id of ids) {
61
+ // const document = await this.get<PHDocument>(id);
62
+ // if (!document) {
63
+ // throw new DocumentNotFoundError(id);
64
+ // }
65
+ // if (signal?.aborted) {
66
+ // throw new AbortError("Aborted");
67
+ // }
68
+ // slugs.push(document.slug);
69
+ // }
70
+ // return Promise.resolve(slugs);
71
+ // }
72
+ // ////////////////////////////////
73
+ // // IDocumentStorage
74
+ // ////////////////////////////////
75
+ // async exists(documentId: string): Promise<boolean> {
76
+ // try {
77
+ // await this.fs.stat(this._buildDocumentPath(documentId));
78
+ // return true;
79
+ // } catch (error) {
80
+ // //
81
+ // }
82
+ // try {
83
+ // await this.fs.stat(this._buildDrivePath(documentId));
84
+ // return true;
85
+ // } catch (error) {
86
+ // //
87
+ // }
88
+ // return false;
89
+ // }
90
+ // async create(document: PHDocument): Promise<void> {
91
+ // const documentId = document.id;
92
+ // if (await this.exists(documentId)) {
93
+ // throw new DocumentAlreadyExistsError(documentId);
94
+ // }
95
+ // const slug =
96
+ // document.header.slug?.length > 0 ? document.header.slug : documentId;
97
+ // const slugManifest = await this.getSlugManifest();
98
+ // if (slugManifest.slugToId[slug]) {
99
+ // throw new DocumentAlreadyExistsError(
100
+ // documentId,
101
+ // DocumentAlreadyExistsReason.SLUG,
102
+ // );
103
+ // }
104
+ // document.header.slug = slug;
105
+ // await this.fs.writeBytes(
106
+ // new TextEncoder().encode(stringify(document)),
107
+ // this._buildDocumentPath(documentId),
108
+ // );
109
+ // // Update the slug manifest if the document has a slug
110
+ // slugManifest.slugToId[slug] = documentId;
111
+ // await this.updateSlugManifest(slugManifest);
112
+ // // temporary: initialize an empty manifest for new drives
113
+ // if (document.header.documentType === "powerhouse/document-drive") {
114
+ // this.updateDriveManifest(documentId, { documentIds: [] });
115
+ // }
116
+ // }
117
+ // async get<TDocument extends PHDocument>(
118
+ // documentId: string,
119
+ // ): Promise<TDocument> {
120
+ // try {
121
+ // const documentPath = this._buildDocumentPath(documentId);
122
+ // const chunks = [];
123
+ // for await (const chunk of this.fs.cat(documentPath)) {
124
+ // chunks.push(chunk);
125
+ // }
126
+ // const buffer = Buffer.concat(chunks);
127
+ // const content = new TextDecoder().decode(buffer);
128
+ // return JSON.parse(content) as TDocument;
129
+ // } catch (error) {
130
+ // return Promise.reject(new DocumentNotFoundError(documentId));
131
+ // }
132
+ // }
133
+ // async getBySlug<TDocument extends PHDocument>(
134
+ // slug: string,
135
+ // ): Promise<TDocument> {
136
+ // const slugManifest = await this.getSlugManifest();
137
+ // const documentId = slugManifest.slugToId[slug];
138
+ // if (!documentId) {
139
+ // return Promise.reject(new DocumentNotFoundError(slug));
140
+ // }
141
+ // return this.get<TDocument>(documentId);
142
+ // }
143
+ // async findByType(
144
+ // documentModelType: string,
145
+ // limit = 100,
146
+ // cursor?: string,
147
+ // ): Promise<{
148
+ // documents: string[];
149
+ // nextCursor: string | undefined;
150
+ // }> {
151
+ // // Get all document files from IPFS
152
+ // const documentFiles = [];
153
+ // try {
154
+ // for await (const entry of this.fs.ls("/")) {
155
+ // if (
156
+ // entry.name.startsWith("document-") &&
157
+ // entry.name.endsWith(".json")
158
+ // ) {
159
+ // documentFiles.push(entry.name);
160
+ // }
161
+ // }
162
+ // } catch (error) {
163
+ // // If directory listing fails, return empty results
164
+ // return { documents: [], nextCursor: undefined };
165
+ // }
166
+ // // Load documents with matching type and collect their metadata
167
+ // const documentsAndIds: Array<{ id: string; document: PHDocument }> = [];
168
+ // for (const fileName of documentFiles) {
169
+ // // Extract the document ID from the filename
170
+ // const documentId = fileName.replace("document-", "").replace(".json", "");
171
+ // try {
172
+ // // Read and parse the document from IPFS
173
+ // const chunks = [];
174
+ // for await (const chunk of this.fs.cat(`/${fileName}`)) {
175
+ // chunks.push(chunk);
176
+ // }
177
+ // const buffer = Buffer.concat(chunks);
178
+ // const content = new TextDecoder().decode(buffer);
179
+ // const document = JSON.parse(content) as PHDocument;
180
+ // // Only include documents of the requested type
181
+ // if (document.header.documentType === documentModelType) {
182
+ // documentsAndIds.push({ id: documentId, document });
183
+ // }
184
+ // } catch (error) {
185
+ // // Skip files that can't be read or parsed
186
+ // continue;
187
+ // }
188
+ // }
189
+ // // Sort by creation date first, then by ID
190
+ // documentsAndIds.sort((a, b) => {
191
+ // const aDate = new Date(a.document.header.createdAtUtcIso);
192
+ // const bDate = new Date(b.document.header.createdAtUtcIso);
193
+ // if (aDate.getTime() === bDate.getTime()) {
194
+ // return a.id.localeCompare(b.id);
195
+ // }
196
+ // return aDate.getTime() - bDate.getTime();
197
+ // });
198
+ // // cursor
199
+ // let startIndex = 0;
200
+ // if (cursor) {
201
+ // const index = documentsAndIds.findIndex(({ id }) => id === cursor);
202
+ // if (index !== -1) {
203
+ // startIndex = index;
204
+ // }
205
+ // }
206
+ // // count to limit
207
+ // const endIndex = Math.min(startIndex + limit, documentsAndIds.length);
208
+ // let nextCursor: string | undefined;
209
+ // if (endIndex < documentsAndIds.length) {
210
+ // nextCursor = documentsAndIds[endIndex].id;
211
+ // }
212
+ // return {
213
+ // documents: documentsAndIds
214
+ // .slice(startIndex, endIndex)
215
+ // .map(({ id }) => id),
216
+ // nextCursor,
217
+ // };
218
+ // }
219
+ // async delete(documentId: string): Promise<boolean> {
220
+ // // Remove from slug manifest if it has a slug
221
+ // try {
222
+ // const document = await this.get<PHDocument>(documentId);
223
+ // const slug =
224
+ // document.header.slug?.length > 0 ? document.header.slug : documentId;
225
+ // if (slug) {
226
+ // const slugManifest = await this.getSlugManifest();
227
+ // if (slugManifest.slugToId[slug] === documentId) {
228
+ // delete slugManifest.slugToId[slug];
229
+ // await this.updateSlugManifest(slugManifest);
230
+ // }
231
+ // }
232
+ // } catch (error) {
233
+ // // If we can't get the document, we can't remove its slug
234
+ // }
235
+ // // delete the document from parent manifests
236
+ // const parents = await this.getParents(documentId);
237
+ // for (const parent of parents) {
238
+ // await this.removeChild(parent, documentId);
239
+ // }
240
+ // // check children: any children that are only children of this document should be deleted
241
+ // const children = await this.getChildren(documentId);
242
+ // for (const child of children) {
243
+ // const childParents = await this.getParents(child);
244
+ // if (childParents.length === 1 && childParents[0] === documentId) {
245
+ // await this.delete(child);
246
+ // }
247
+ // }
248
+ // // delete any manifest for this document
249
+ // try {
250
+ // await this.fs.rm(this._buildDriveManifestPath(documentId));
251
+ // } catch (error) {
252
+ // // there may be no manifest for this document
253
+ // }
254
+ // // finally, delete the specified document
255
+ // try {
256
+ // await this.fs.rm(this._buildDocumentPath(documentId));
257
+ // return true;
258
+ // } catch (error) {
259
+ // return false;
260
+ // }
261
+ // }
262
+ // async addChild(parentId: string, childId: string): Promise<void> {
263
+ // if (parentId === childId) {
264
+ // throw new Error("Cannot associate a document with itself");
265
+ // }
266
+ // // check if the child is a parent of the parent
267
+ // const children = await this.getChildren(childId);
268
+ // if (children.includes(parentId)) {
269
+ // throw new Error("Cannot associate a document with its child");
270
+ // }
271
+ // const manifest = await this.getDriveManifest(parentId);
272
+ // if (!manifest.documentIds.includes(childId)) {
273
+ // manifest.documentIds.push(childId);
274
+ // await this.updateDriveManifest(parentId, manifest);
275
+ // }
276
+ // }
277
+ // async removeChild(parentId: string, childId: string): Promise<boolean> {
278
+ // const manifest = await this.getDriveManifest(parentId);
279
+ // const docIndex = manifest.documentIds.indexOf(childId);
280
+ // if (docIndex !== -1) {
281
+ // manifest.documentIds.splice(docIndex, 1);
282
+ // await this.updateDriveManifest(parentId, manifest);
283
+ // return true;
284
+ // }
285
+ // return false;
286
+ // }
287
+ // async getChildren(parentId: string): Promise<string[]> {
288
+ // const manifest = await this.getDriveManifest(parentId);
289
+ // return manifest.documentIds;
290
+ // }
291
+ // async getParents(childId: string): Promise<string[]> {
292
+ // const parents: string[] = [];
293
+ // // Get all manifest files by listing the directory and finding manifest files
294
+ // try {
295
+ // for await (const entry of this.fs.ls("/")) {
296
+ // if (
297
+ // entry.name.startsWith("manifest-") &&
298
+ // entry.name.endsWith(".json")
299
+ // ) {
300
+ // // Extract the driveId from the manifest filename
301
+ // const driveId = entry.name
302
+ // .replace("manifest-", "")
303
+ // .replace(".json", "");
304
+ // // Check if the manifest contains the childId
305
+ // const manifest = await this.getDriveManifest(driveId);
306
+ // if (manifest.documentIds.includes(childId)) {
307
+ // parents.push(driveId);
308
+ // }
309
+ // }
310
+ // }
311
+ // } catch (error) {
312
+ // // If listing fails, return empty array
313
+ // }
314
+ // return parents;
315
+ // }
316
+ // // IDriveStorage
317
+ // ////////////////////////////////
318
+ // async addDocumentOperations<TDocument extends PHDocument>(
319
+ // drive: string,
320
+ // id: string,
321
+ // operations: Operation[],
322
+ // header: PHDocumentHeader,
323
+ // ): Promise<void> {
324
+ // const document = await this.get<TDocument>(id);
325
+ // if (!document) {
326
+ // throw new Error(`Document with id ${id} not found`);
327
+ // }
328
+ // const mergedOperations = mergeOperations(document.operations, operations);
329
+ // await this.create(id, {
330
+ // ...document,
331
+ // header,
332
+ // operations: mergedOperations,
333
+ // });
334
+ // await this.addChild(drive, id);
335
+ // }
336
+ // async getDrives(): Promise<string[]> {
337
+ // const result = await this.findByType("powerhouse/document-drive");
338
+ // return result.documents;
339
+ // }
340
+ // async getDrive(id: string): Promise<DocumentDriveDocument> {
341
+ // try {
342
+ // const drivePath = this._buildDrivePath(id);
343
+ // const chunks = [];
344
+ // for await (const chunk of this.fs.cat(drivePath)) {
345
+ // chunks.push(chunk);
346
+ // }
347
+ // const buffer = Buffer.concat(chunks);
348
+ // const content = new TextDecoder().decode(buffer);
349
+ // return JSON.parse(content) as DocumentDriveDocument;
350
+ // } catch {
351
+ // throw new Error(`Drive with id ${id} not found`);
352
+ // }
353
+ // }
354
+ // async addDriveOperations(
355
+ // id: string,
356
+ // operations: Operation<DocumentDriveAction>[],
357
+ // header: PHDocumentHeader,
358
+ // ): Promise<void> {
359
+ // const drive = await this.getDrive(id);
360
+ // const mergedOperations = mergeOperations<DocumentDriveDocument>(
361
+ // drive.operations,
362
+ // operations,
363
+ // );
364
+ // await this.create(id, {
365
+ // ...drive,
366
+ // header,
367
+ // operations: mergedOperations,
368
+ // });
369
+ // }
370
+ // async clearStorage(): Promise<void> {
371
+ // // Delete all files
372
+ // try {
373
+ // for await (const entry of this.fs.ls("/")) {
374
+ // if (entry.type === "file") {
375
+ // await this.fs.rm(`/${entry.name}`);
376
+ // }
377
+ // }
378
+ // } catch (error) {
379
+ // // Ignore any errors when trying to list/delete files
380
+ // }
381
+ // }
382
+ // async getSynchronizationUnitsRevision(
383
+ // units: SynchronizationUnitQuery[],
384
+ // ): Promise<
385
+ // {
386
+ // documentId: string;
387
+ // scope: string;
388
+ // branch: string;
389
+ // lastUpdated: string;
390
+ // revision: number;
391
+ // }[]
392
+ // > {
393
+ // const results = await Promise.allSettled(
394
+ // units.map(async (unit) => {
395
+ // try {
396
+ // const document = await this.get<PHDocument>(unit.documentId);
397
+ // if (!document) {
398
+ // return undefined;
399
+ // }
400
+ // const operation = document.operations[unit.scope].at(-1);
401
+ // if (operation) {
402
+ // return {
403
+ // documentId: unit.documentId,
404
+ // scope: unit.scope,
405
+ // branch: unit.branch,
406
+ // lastUpdated: operation.timestampUtcMs,
407
+ // revision: operation.index,
408
+ // };
409
+ // }
410
+ // } catch {
411
+ // return undefined;
412
+ // }
413
+ // }),
414
+ // );
415
+ // return results.reduce<
416
+ // {
417
+ // documentId: string;
418
+ // scope: string;
419
+ // branch: string;
420
+ // lastUpdated: string;
421
+ // revision: number;
422
+ // }[]
423
+ // >((acc, curr) => {
424
+ // if (curr.status === "fulfilled" && curr.value !== undefined) {
425
+ // acc.push(curr.value);
426
+ // }
427
+ // return acc;
428
+ // }, []);
429
+ // }
430
+ // ////////////////////////////////
431
+ // // Private methods
432
+ // ////////////////////////////////
433
+ // private _buildDocumentPath(documentId: string): string {
434
+ // return `/document-${documentId}.json`;
435
+ // }
436
+ // private _buildDrivePath(driveId: string): string {
437
+ // return `/drive-${driveId}.json`;
438
+ // }
439
+ // private _buildDriveManifestPath(driveId: string): string {
440
+ // return `/manifest-${driveId}.json`;
441
+ // }
442
+ // private _buildSlugManifestPath(): string {
443
+ // return `/slugs.json`;
444
+ // }
445
+ // private async getDriveManifest(driveId: string): Promise<DriveManifest> {
446
+ // try {
447
+ // const manifestPath = this._buildDriveManifestPath(driveId);
448
+ // const chunks = [];
449
+ // for await (const chunk of this.fs.cat(manifestPath)) {
450
+ // chunks.push(chunk);
451
+ // }
452
+ // const buffer = Buffer.concat(chunks);
453
+ // const content = new TextDecoder().decode(buffer);
454
+ // return JSON.parse(content) as DriveManifest;
455
+ // } catch (error) {
456
+ // // If manifest doesn't exist, return an empty one
457
+ // return { documentIds: [] };
458
+ // }
459
+ // }
460
+ // private async updateDriveManifest(
461
+ // driveId: string,
462
+ // manifest: DriveManifest,
463
+ // ): Promise<void> {
464
+ // const manifestPath = this._buildDriveManifestPath(driveId);
465
+ // const manifestContent = stringify(manifest);
466
+ // const manifestBuffer = new TextEncoder().encode(manifestContent);
467
+ // await this.fs.writeBytes(manifestBuffer, manifestPath, { force: true });
468
+ // }
469
+ // private async getSlugManifest(): Promise<SlugManifest> {
470
+ // try {
471
+ // const manifestPath = this._buildSlugManifestPath();
472
+ // const chunks = [];
473
+ // for await (const chunk of this.fs.cat(manifestPath)) {
474
+ // chunks.push(chunk);
475
+ // }
476
+ // const buffer = Buffer.concat(chunks);
477
+ // const content = new TextDecoder().decode(buffer);
478
+ // return JSON.parse(content) as SlugManifest;
479
+ // } catch (error) {
480
+ // // If manifest doesn't exist, return an empty one
481
+ // return { slugToId: {} };
482
+ // }
483
+ // }
484
+ // private async updateSlugManifest(manifest: SlugManifest): Promise<void> {
485
+ // const manifestPath = this._buildSlugManifestPath();
486
+ // const manifestContent = stringify(manifest);
487
+ // const manifestBuffer = new TextEncoder().encode(manifestContent);
488
+ // await this.fs.writeBytes(manifestBuffer, manifestPath, { force: true });
489
+ // }
490
+ // }
416
491
  //# sourceMappingURL=ipfs.js.map