mindoodb 0.0.44 → 0.0.46

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 (91) hide show
  1. package/README.md +9 -0
  2. package/dist/appendonlystores/network/HttpTransport.d.ts.map +1 -1
  3. package/dist/appendonlystores/network/HttpTransport.js +4 -0
  4. package/dist/appendonlystores/network/HttpTransport.js.map +1 -1
  5. package/dist/browser/index.mjs +31 -0
  6. package/dist/core/BaseMindooDB.d.ts +74 -0
  7. package/dist/core/BaseMindooDB.d.ts.map +1 -1
  8. package/dist/core/BaseMindooDB.js +160 -0
  9. package/dist/core/BaseMindooDB.js.map +1 -1
  10. package/dist/core/BaseMindooTenant.d.ts +22 -0
  11. package/dist/core/BaseMindooTenant.d.ts.map +1 -1
  12. package/dist/core/BaseMindooTenant.js +57 -6
  13. package/dist/core/BaseMindooTenant.js.map +1 -1
  14. package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -1
  15. package/dist/core/BaseMindooTenantFactory.js +31 -9
  16. package/dist/core/BaseMindooTenantFactory.js.map +1 -1
  17. package/dist/core/copy/attachments.d.ts +53 -0
  18. package/dist/core/copy/attachments.d.ts.map +1 -0
  19. package/dist/core/copy/attachments.js +186 -0
  20. package/dist/core/copy/attachments.js.map +1 -0
  21. package/dist/core/copy/copyDocument.d.ts +86 -0
  22. package/dist/core/copy/copyDocument.d.ts.map +1 -0
  23. package/dist/core/copy/copyDocument.js +369 -0
  24. package/dist/core/copy/copyDocument.js.map +1 -0
  25. package/dist/core/copy/copyDocuments.d.ts +57 -0
  26. package/dist/core/copy/copyDocuments.d.ts.map +1 -0
  27. package/dist/core/copy/copyDocuments.js +167 -0
  28. package/dist/core/copy/copyDocuments.js.map +1 -0
  29. package/dist/core/copy/entryRewrite.d.ts +49 -0
  30. package/dist/core/copy/entryRewrite.d.ts.map +1 -0
  31. package/dist/core/copy/entryRewrite.js +74 -0
  32. package/dist/core/copy/entryRewrite.js.map +1 -0
  33. package/dist/core/copy/feasibility.d.ts +73 -0
  34. package/dist/core/copy/feasibility.d.ts.map +1 -0
  35. package/dist/core/copy/feasibility.js +169 -0
  36. package/dist/core/copy/feasibility.js.map +1 -0
  37. package/dist/core/copy/flatten.d.ts +55 -0
  38. package/dist/core/copy/flatten.d.ts.map +1 -0
  39. package/dist/core/copy/flatten.js +155 -0
  40. package/dist/core/copy/flatten.js.map +1 -0
  41. package/dist/core/copy/host.d.ts +92 -0
  42. package/dist/core/copy/host.d.ts.map +1 -0
  43. package/dist/core/copy/host.js +16 -0
  44. package/dist/core/copy/host.js.map +1 -0
  45. package/dist/core/copy/preflight.d.ts +62 -0
  46. package/dist/core/copy/preflight.d.ts.map +1 -0
  47. package/dist/core/copy/preflight.js +98 -0
  48. package/dist/core/copy/preflight.js.map +1 -0
  49. package/dist/core/copy/provenance.d.ts +74 -0
  50. package/dist/core/copy/provenance.d.ts.map +1 -0
  51. package/dist/core/copy/provenance.js +91 -0
  52. package/dist/core/copy/provenance.js.map +1 -0
  53. package/dist/core/copy/types.d.ts +418 -0
  54. package/dist/core/copy/types.d.ts.map +1 -0
  55. package/dist/core/copy/types.js +21 -0
  56. package/dist/core/copy/types.js.map +1 -0
  57. package/dist/core/crypto/DomainStatement.d.ts +44 -0
  58. package/dist/core/crypto/DomainStatement.d.ts.map +1 -0
  59. package/dist/core/crypto/DomainStatement.js +71 -0
  60. package/dist/core/crypto/DomainStatement.js.map +1 -0
  61. package/dist/core/crypto/EntrySignature.d.ts +109 -15
  62. package/dist/core/crypto/EntrySignature.d.ts.map +1 -1
  63. package/dist/core/crypto/EntrySignature.js +83 -22
  64. package/dist/core/crypto/EntrySignature.js.map +1 -1
  65. package/dist/core/index.d.ts +21 -0
  66. package/dist/core/index.d.ts.map +1 -1
  67. package/dist/core/index.js +54 -3
  68. package/dist/core/index.js.map +1 -1
  69. package/dist/core/timestamps/timestampClient.d.ts +88 -0
  70. package/dist/core/timestamps/timestampClient.d.ts.map +1 -0
  71. package/dist/core/timestamps/timestampClient.js +157 -0
  72. package/dist/core/timestamps/timestampClient.js.map +1 -0
  73. package/dist/core/types.d.ts +134 -4
  74. package/dist/core/types.d.ts.map +1 -1
  75. package/dist/core/types.js.map +1 -1
  76. package/dist/node/server/MindooDBServer.d.ts +37 -0
  77. package/dist/node/server/MindooDBServer.d.ts.map +1 -1
  78. package/dist/node/server/MindooDBServer.js +157 -0
  79. package/dist/node/server/MindooDBServer.js.map +1 -1
  80. package/dist/node/server/config.d.ts.map +1 -1
  81. package/dist/node/server/config.js +16 -0
  82. package/dist/node/server/config.js.map +1 -1
  83. package/dist/node/server/timestampProxy.d.ts +129 -0
  84. package/dist/node/server/timestampProxy.d.ts.map +1 -0
  85. package/dist/node/server/timestampProxy.js +361 -0
  86. package/dist/node/server/timestampProxy.js.map +1 -0
  87. package/dist/node/server/types.d.ts +20 -0
  88. package/dist/node/server/types.d.ts.map +1 -1
  89. package/dist/node/server/types.js +12 -0
  90. package/dist/node/server/types.js.map +1 -1
  91. package/package.json +1 -1
@@ -0,0 +1,369 @@
1
+ "use strict";
2
+ /**
3
+ * The document copy engine.
4
+ *
5
+ * Orchestrates the three strategies described in `docs/document-copy.md`:
6
+ * `flatten` (delegated to `flatten.ts`, which goes through the public document
7
+ * API), and the two history-preserving strategies implemented here.
8
+ *
9
+ * `graft` and `replay` share one pipeline — order the source revision graph
10
+ * causally, skip what the target already has, transform in batches, write — and
11
+ * differ only in the per-entry transform:
12
+ *
13
+ * - **graft** strips the witness receipt and changes nothing else, so the
14
+ * original authors' signatures remain valid.
15
+ * - **replay** re-homes each entry under the target document id and re-signs it
16
+ * as the copying user, recording the original author in a verifiable
17
+ * provenance record.
18
+ *
19
+ * @module
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.CopyProgressReporter = void 0;
23
+ exports.resolveCopySigningKey = resolveCopySigningKey;
24
+ exports.resolveCopierPublicKey = resolveCopierPublicKey;
25
+ exports.prepareCopy = prepareCopy;
26
+ exports.canCopyDocument = canCopyDocument;
27
+ exports.copyDocument = copyDocument;
28
+ const DocumentDagAnalysis_1 = require("../DocumentDagAnalysis");
29
+ const idGeneration_1 = require("../utils/idGeneration");
30
+ const timeSource_1 = require("../utils/timeSource");
31
+ const types_1 = require("../types");
32
+ const feasibility_1 = require("./feasibility");
33
+ const entryRewrite_1 = require("./entryRewrite");
34
+ const provenance_1 = require("./provenance");
35
+ const preflight_1 = require("./preflight");
36
+ const attachments_1 = require("./attachments");
37
+ const flatten_1 = require("./flatten");
38
+ /** Default entries written per `putEntries` call. */
39
+ const DEFAULT_BATCH_SIZE = 200;
40
+ /**
41
+ * Normalize the caller's signing options: a key pair is only usable together
42
+ * with its password, so a half-supplied pair is treated as absent.
43
+ *
44
+ * @internal
45
+ */
46
+ function resolveCopySigningKey(options) {
47
+ if (!options.signingKeyPair || !options.signingKeyPassword)
48
+ return undefined;
49
+ return {
50
+ signingKeyPair: options.signingKeyPair,
51
+ signingKeyPassword: options.signingKeyPassword,
52
+ };
53
+ }
54
+ /**
55
+ * The key the copy's entries will be signed with: the caller's service identity
56
+ * when supplied, the current user's otherwise.
57
+ *
58
+ * @internal
59
+ */
60
+ async function resolveCopierPublicKey(target, options) {
61
+ return (resolveCopySigningKey(options)?.signingKeyPair.publicKey ??
62
+ (await target.tenant.getCurrentUserId()).userSigningPublicKey);
63
+ }
64
+ /**
65
+ * Accumulates copy totals and emits {@link CopyProgress} events.
66
+ *
67
+ * Shared by the single-document and bulk paths so a bulk run reports one
68
+ * continuously rising total rather than restarting the counters per document.
69
+ */
70
+ class CopyProgressReporter {
71
+ constructor(onProgress) {
72
+ this.onProgress = onProgress;
73
+ this.copiedEntries = 0;
74
+ this.copiedBytes = 0;
75
+ this.scannedEntries = 0;
76
+ this.copiedAttachments = 0;
77
+ }
78
+ emit(phase, message) {
79
+ if (!this.onProgress)
80
+ return;
81
+ this.onProgress({
82
+ phase,
83
+ message,
84
+ copiedEntries: this.copiedEntries,
85
+ copiedBytes: this.copiedBytes,
86
+ scannedEntries: this.scannedEntries,
87
+ totalSourceEntries: this.totalSourceEntries,
88
+ currentDocId: this.currentDocId,
89
+ documentsCompleted: this.documentsCompleted,
90
+ totalDocuments: this.totalDocuments,
91
+ });
92
+ }
93
+ }
94
+ exports.CopyProgressReporter = CopyProgressReporter;
95
+ /**
96
+ * Read the source document's revision-graph metadata and derive the key it is
97
+ * encrypted under.
98
+ *
99
+ * Uses the raw store rather than the database's filtered scan so a copy sees
100
+ * the document exactly as stored, independent of any time-travel view the
101
+ * source database happens to be opened at.
102
+ */
103
+ async function readSourceDagEntries(source, docId) {
104
+ const all = await source.store.findNewEntriesForDoc([], docId);
105
+ return all.filter(entryRewrite_1.isDocumentDagEntry);
106
+ }
107
+ /**
108
+ * Resolve the document id the copy will be written under.
109
+ *
110
+ * An explicit string is taken as-is; `"same"` keeps the source id (the sharding
111
+ * case); `"new"` mints a fresh one.
112
+ */
113
+ function resolveTargetDocId(sourceDocId, options) {
114
+ const requested = options.targetDocId ?? "new";
115
+ if (requested === "same")
116
+ return sourceDocId;
117
+ if (requested === "new")
118
+ return (0, idGeneration_1.generateDocId)(options.idPrefix);
119
+ return requested;
120
+ }
121
+ /**
122
+ * Gather the source/target facts the strategy resolver needs, then resolve it.
123
+ *
124
+ * Shared by `copyDocument` and `canCopyDocument` so the answer a caller gets
125
+ * from the dry run is the one the real run will act on.
126
+ */
127
+ async function prepareCopy(source, target, sourceDocId, options, precomputedTargetDocId) {
128
+ const sourceEntries = await readSourceDagEntries(source, sourceDocId);
129
+ if (sourceEntries.length === 0) {
130
+ throw new Error(`Document ${sourceDocId} was not found in database ${source.store.getId()}.`);
131
+ }
132
+ const targetDocId = precomputedTargetDocId ?? resolveTargetDocId(sourceDocId, options);
133
+ const sourceTenantId = source.tenant.getId();
134
+ const targetTenantId = target.tenant.getId();
135
+ const sameTenant = sourceTenantId === targetTenantId;
136
+ // Every lifecycle entry of a document shares one decryptionKeyId, so the
137
+ // oldest one speaks for the document.
138
+ const sourceDecryptionKeyId = sourceEntries
139
+ .slice()
140
+ .sort((left, right) => left.createdAt - right.createdAt)[0].decryptionKeyId;
141
+ const context = {
142
+ sourceTenantId,
143
+ targetTenantId,
144
+ sourceDbId: source.store.getId(),
145
+ targetDbId: target.store.getId(),
146
+ sourceDocId,
147
+ targetDocId,
148
+ sourceDecryptionKeyId,
149
+ targetDecryptionKeyId: (0, feasibility_1.resolveTargetDecryptionKeyId)(options.decryptionKeyId, sourceDecryptionKeyId, sameTenant),
150
+ // Store ids are only unique within a tenant: each tenant has its own store
151
+ // factory, so the same db id in two tenants is two different stores.
152
+ sameStore: source.store === target.store ||
153
+ (sameTenant && source.store.getId() === target.store.getId()),
154
+ targetHasDocId: (await target.store.findNewEntriesForDoc([], targetDocId)).length > 0,
155
+ };
156
+ return {
157
+ context,
158
+ feasibility: (0, feasibility_1.resolveCopyFeasibility)(context, options),
159
+ sourceEntries,
160
+ };
161
+ }
162
+ /** Dry run: report what a copy would do without writing anything. */
163
+ async function canCopyDocument(source, target, docId, options = {}) {
164
+ const { feasibility } = await prepareCopy(source, target, docId, options);
165
+ return feasibility;
166
+ }
167
+ /**
168
+ * Copy one document into another database.
169
+ *
170
+ * @see `docs/document-copy.md` for the strategy matrix and caveats.
171
+ */
172
+ async function copyDocument(source, target, docId, options = {}, sharedReporter) {
173
+ const reporter = sharedReporter ?? new CopyProgressReporter(options.onProgress);
174
+ reporter.currentDocId = docId;
175
+ reporter.emit("preparing", `Preparing to copy document ${docId}`);
176
+ const { context, feasibility, sourceEntries } = await prepareCopy(source, target, docId, options);
177
+ if (!feasibility.allowed) {
178
+ throw (0, feasibility_1.copyFeasibilityError)(feasibility);
179
+ }
180
+ if (feasibility.strategy === "flatten") {
181
+ return (0, flatten_1.flattenDocument)(source, target, context, options, reporter);
182
+ }
183
+ return copyDocumentHistory(source, target, context, feasibility, options, sourceEntries, reporter);
184
+ }
185
+ /**
186
+ * The shared graft/replay pipeline.
187
+ *
188
+ * Entries are ordered causally so a dependency is always written before the
189
+ * entry that needs it, pre-screened against the target so a re-run after a
190
+ * cancellation transfers only the remainder, and written in batches with an
191
+ * abort check between each.
192
+ */
193
+ async function copyDocumentHistory(source, target, context, feasibility, options, sourceEntries, reporter) {
194
+ const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
195
+ const ordered = (0, DocumentDagAnalysis_1.orderDagEntriesCausally)(sourceEntries);
196
+ const startedAtCopiedEntries = reporter.copiedEntries;
197
+ const startedAtCopiedBytes = reporter.copiedBytes;
198
+ const startedAtAttachments = reporter.copiedAttachments;
199
+ reporter.emit("planning", `Planning copy of ${ordered.length} revisions of ${context.sourceDocId}`);
200
+ // Ask the target's write policy before doing any work. The copy writes store
201
+ // entries directly, so it does not inherit the precheck that changeDoc runs,
202
+ // and a graft carries signers the target may never have granted anything to.
203
+ if (!options.bypassAccessControlPrecheck) {
204
+ const copierKey = await resolveCopierPublicKey(target, options);
205
+ const preflight = await (0, preflight_1.preflightCopyAdmission)(target, ordered, feasibility.strategy === "graft"
206
+ ? (entry) => entry.createdByPublicKey
207
+ : () => copierKey, ordered.find((entry) => entry.entryType === "doc_create")?.createdByPublicKey ??
208
+ null);
209
+ if (!preflight.admitted) {
210
+ throw new Error((0, preflight_1.describeAdmissionFailure)(preflight, target.store.getId()));
211
+ }
212
+ }
213
+ // Attachments first: a document entry's signed attachmentRefs snapshot has to
214
+ // describe chunks that already exist in the target, and the same-store
215
+ // strategy needs the chunk id remapping before document entries are rewritten.
216
+ const attachmentPlan = await (0, attachments_1.copyDocumentAttachments)(source, target, context, feasibility, options, reporter, sourceEntries);
217
+ if (attachmentPlan.cancelled) {
218
+ return buildResult(context, feasibility, reporter, {
219
+ startedAtCopiedEntries,
220
+ startedAtCopiedBytes,
221
+ startedAtAttachments,
222
+ cancelled: true,
223
+ });
224
+ }
225
+ const targetIds = ordered.map((entry) => (0, entryRewrite_1.remapEntryId)(entry.id, context.sourceDocId, context.targetDocId));
226
+ const alreadyPresent = new Set(await target.store.hasEntries(targetIds));
227
+ const causalIndexById = new Map(ordered.map((entry, index) => [entry.id, index]));
228
+ // Anchor the rewritten timestamps so the last entry lands at copy time and
229
+ // earlier ones stay strictly before it. Copies are never backdated to the
230
+ // original write time — that would collide with provisional-entry handling
231
+ // and access-control time travel — but relative order still has to survive,
232
+ // because delete/undelete resolution compares createdAt.
233
+ const copyTime = (0, timeSource_1.semanticNow)();
234
+ const timeAnchor = copyTime - (ordered.length - 1);
235
+ const signing = resolveCopySigningKey(options);
236
+ const copierPublicKey = signing?.signingKeyPair.publicKey ??
237
+ (await target.tenant.getCurrentUserId()).userSigningPublicKey;
238
+ for (let offset = 0; offset < ordered.length; offset += batchSize) {
239
+ if (options.signal?.aborted) {
240
+ return buildResult(context, feasibility, reporter, {
241
+ startedAtCopiedEntries,
242
+ startedAtCopiedBytes,
243
+ startedAtAttachments,
244
+ cancelled: true,
245
+ });
246
+ }
247
+ const slice = ordered.slice(offset, offset + batchSize);
248
+ reporter.scannedEntries += slice.length;
249
+ const needed = slice.filter((_entry, index) => !alreadyPresent.has(targetIds[offset + index]));
250
+ if (needed.length === 0) {
251
+ reporter.emit("transferring", `Skipped ${slice.length} revisions already present in the target`);
252
+ continue;
253
+ }
254
+ const fetched = await source.store.getEntries(needed.map((entry) => entry.id));
255
+ const byId = new Map(fetched.map((entry) => [entry.id, entry]));
256
+ const transformed = [];
257
+ for (const metadata of needed) {
258
+ const sourceEntry = byId.get(metadata.id);
259
+ if (!sourceEntry) {
260
+ // The entry vanished between the metadata scan and the read (a
261
+ // concurrent purge). Skip it: the copy stays consistent because the
262
+ // document's remaining revisions still form a valid graph.
263
+ continue;
264
+ }
265
+ const index = causalIndexById.get(metadata.id) ?? 0;
266
+ transformed.push(feasibility.strategy === "graft"
267
+ ? graftEntry(sourceEntry)
268
+ : await replayEntry(source, target, context, feasibility, options, sourceEntry, {
269
+ createdAt: timeAnchor + index,
270
+ createdByPublicKey: copierPublicKey,
271
+ signing,
272
+ }));
273
+ }
274
+ if (transformed.length > 0) {
275
+ await target.store.putEntries(transformed);
276
+ reporter.copiedEntries += transformed.length;
277
+ for (const entry of transformed) {
278
+ reporter.copiedBytes += entry.encryptedSize;
279
+ }
280
+ }
281
+ reporter.emit("transferring", `Copied ${reporter.copiedEntries} revisions of ${context.sourceDocId}`);
282
+ }
283
+ // The same-store variant re-homes attachment chunks under the new document
284
+ // id, which the copied history still points at by their old ids. One trailing
285
+ // change repoints the current revision at the chunks the copy owns.
286
+ await target.syncStoreChanges();
287
+ await attachmentPlan.finalize(signing);
288
+ reporter.emit("processing", `Materializing ${context.targetDocId}`);
289
+ await target.syncStoreChanges();
290
+ reporter.emit("complete", `Copied document ${context.sourceDocId}`);
291
+ return buildResult(context, feasibility, reporter, {
292
+ startedAtCopiedEntries,
293
+ startedAtCopiedBytes,
294
+ startedAtAttachments,
295
+ cancelled: false,
296
+ });
297
+ }
298
+ /**
299
+ * Graft transform: keep every byte, drop only the witness receipt.
300
+ *
301
+ * There is deliberately nothing else here. Not re-deriving the id, not
302
+ * re-encrypting and not re-signing is precisely what leaves the original
303
+ * author's `metadataSignature` valid — and it is why sharding never needs a
304
+ * decryption key.
305
+ */
306
+ function graftEntry(sourceEntry) {
307
+ return (0, entryRewrite_1.stripWitnessReceipt)({ ...sourceEntry });
308
+ }
309
+ /** Replay transform: re-home the entry and re-sign it as the copying user. */
310
+ async function replayEntry(source, target, context, feasibility, options, sourceEntry, rewrite) {
311
+ const { sourceDocId, targetDocId, targetDecryptionKeyId } = context;
312
+ // The Automerge change bytes are reused verbatim, so the whole CRDT history —
313
+ // actor ids, per-change timestamps, text structure — survives intact. Only
314
+ // the encryption envelope is redone, and only when it has to be.
315
+ let encryptedData = sourceEntry.encryptedData;
316
+ let contentHash = sourceEntry.contentHash;
317
+ if (feasibility.requiresReEncryption) {
318
+ const plaintext = await source.tenant.decryptPayload(sourceEntry.encryptedData, sourceEntry.decryptionKeyId);
319
+ encryptedData = await target.tenant.encryptPayload(plaintext, targetDecryptionKeyId);
320
+ contentHash = await (0, idGeneration_1.computeContentHash)(encryptedData, target.tenant.getCryptoAdapter().getSubtle());
321
+ }
322
+ const signature = rewrite.signing
323
+ ? await target.tenant.signPayloadWithKey(encryptedData, rewrite.signing.signingKeyPair, rewrite.signing.signingKeyPassword)
324
+ : await target.tenant.signPayload(encryptedData);
325
+ const entry = {
326
+ entryType: sourceEntry.entryType,
327
+ id: (0, entryRewrite_1.remapEntryId)(sourceEntry.id, sourceDocId, targetDocId),
328
+ contentHash,
329
+ docId: targetDocId,
330
+ dependencyIds: sourceEntry.dependencyIds.map((dependencyId) => (0, entryRewrite_1.remapEntryId)(dependencyId, sourceDocId, targetDocId)),
331
+ createdAt: rewrite.createdAt,
332
+ createdByPublicKey: rewrite.createdByPublicKey,
333
+ decryptionKeyId: targetDecryptionKeyId,
334
+ snapshotHeadHashes: sourceEntry.snapshotHeadHashes,
335
+ snapshotHeadEntryIds: sourceEntry.snapshotHeadEntryIds?.map((entryId) => (0, entryRewrite_1.remapEntryId)(entryId, sourceDocId, targetDocId)),
336
+ attachmentId: sourceEntry.attachmentId,
337
+ attachmentIds: sourceEntry.attachmentIds,
338
+ // Carried verbatim. The refs name chunk ids, and a chunk id is only renamed
339
+ // for a same-store copy — where the copied history deliberately keeps
340
+ // pointing at the source's chunks, matching its own unmodified payload,
341
+ // until the trailing remap change repoints the current revision.
342
+ attachmentRefs: sourceEntry.attachmentRefs,
343
+ signature,
344
+ originalSize: sourceEntry.originalSize,
345
+ encryptedSize: encryptedData.length,
346
+ entryVersion: types_1.CURRENT_STORE_ENTRY_VERSION,
347
+ encryptedData,
348
+ };
349
+ if (options.provenance !== false) {
350
+ entry.provenance = (0, provenance_1.buildProvenanceFromEntry)(sourceEntry, context.sourceTenantId, context.sourceDbId);
351
+ }
352
+ entry.metadataSignature = await target.computeEntryMetadataSignature(entry, rewrite.signing);
353
+ return entry;
354
+ }
355
+ /** Assemble the per-document result from the reporter's running totals. */
356
+ function buildResult(context, feasibility, reporter, baseline) {
357
+ return {
358
+ sourceDocId: context.sourceDocId,
359
+ targetDocId: context.targetDocId,
360
+ strategy: feasibility.strategy,
361
+ authorshipPreserved: feasibility.authorshipPreserved,
362
+ mergedIntoExisting: feasibility.willMergeIntoExisting,
363
+ copiedEntries: reporter.copiedEntries - baseline.startedAtCopiedEntries,
364
+ copiedBytes: reporter.copiedBytes - baseline.startedAtCopiedBytes,
365
+ copiedAttachments: reporter.copiedAttachments - baseline.startedAtAttachments,
366
+ cancelled: baseline.cancelled,
367
+ };
368
+ }
369
+ //# sourceMappingURL=copyDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyDocument.js","sourceRoot":"","sources":["../../../src/core/copy/copyDocument.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Bulk document copy — and, with `mode: "history"` plus `targetDocId: "same"`
3
+ * plus `authorship: "preserve"`, the database sharding primitive.
4
+ *
5
+ * The per-document API is the wrong shape for moving thousands of documents:
6
+ * each call would scan the source store's metadata again. This path selects the
7
+ * documents in one pass and then reuses the per-document engine, sharing one
8
+ * progress reporter so the totals accumulate across the whole run.
9
+ *
10
+ * Errors are per-document rather than fatal: the run continues and reports what
11
+ * failed, mirroring how `pushChangesTo` reports `rejectedEntries`. Because every
12
+ * produced entry id is deterministic, re-running after a failure or a
13
+ * cancellation transfers only what is still missing.
14
+ *
15
+ * @module
16
+ */
17
+ import type { DocHistoryPurgeRequest } from "../accesscontrol/types";
18
+ import type { CopyEngineHost } from "./host";
19
+ import type { CopyDocumentSelector, CopyDocumentsOptions, CopyDocumentsResult } from "./types";
20
+ /** Copy many documents into another database in one pass. */
21
+ export declare function copyDocuments(source: CopyEngineHost, target: CopyEngineHost, selector: CopyDocumentSelector, options?: CopyDocumentsOptions): Promise<CopyDocumentsResult>;
22
+ /**
23
+ * Turn a completed shard into the purge request that reclaims the source.
24
+ *
25
+ * No new purge machinery is involved: this only shapes the result for the
26
+ * existing pipeline. The admin publishes the returned request into the
27
+ * directory database, and the server's `executePendingPurges` denylists each
28
+ * document id before deleting it, so a stale replica cannot re-push into the
29
+ * gap.
30
+ *
31
+ * Two ordering rules matter and are not enforceable here:
32
+ *
33
+ * 1. Publish only after the shard target has been pushed **and witnessed**.
34
+ * Copied entries are provisional until they are re-witnessed, and a purge is
35
+ * irreversible.
36
+ * 2. `dbId` must name the **source** database. The denylist is keyed by
37
+ * database id, which is precisely why purging the source leaves the shard
38
+ * target — holding the same document ids under a different database id —
39
+ * untouched.
40
+ *
41
+ * For a very large shard, split {@link CopyDocumentsResult.copiedDocIds} across
42
+ * several requests: the id list lives inside a single directory document, and
43
+ * idempotency is tracked per `requestId`.
44
+ */
45
+ export declare function buildDocHistoryPurgeRequest(result: CopyDocumentsResult, options: {
46
+ /** The SOURCE database to reclaim. Never the shard target. */
47
+ dbId: string;
48
+ /** Unique id for this request; also forms the directory document id. */
49
+ requestId: string;
50
+ /** Signing key of the admin preparing the request. */
51
+ preparedByPublicKey: string;
52
+ /** Optional human-readable justification, encrypted by the admin on save. */
53
+ reason?: string;
54
+ /** Optional explicit tenant id, when the request is prepared out of band. */
55
+ tenantId?: string;
56
+ }): DocHistoryPurgeRequest;
57
+ //# sourceMappingURL=copyDocuments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyDocuments.d.ts","sourceRoot":"","sources":["../../../src/core/copy/copyDocuments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG7C,OAAO,KAAK,EAGV,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAmDjB,6DAA6D;AAC7D,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA6E9B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE;IACP,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,sBAAsB,CAsBxB"}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ /**
3
+ * Bulk document copy — and, with `mode: "history"` plus `targetDocId: "same"`
4
+ * plus `authorship: "preserve"`, the database sharding primitive.
5
+ *
6
+ * The per-document API is the wrong shape for moving thousands of documents:
7
+ * each call would scan the source store's metadata again. This path selects the
8
+ * documents in one pass and then reuses the per-document engine, sharing one
9
+ * progress reporter so the totals accumulate across the whole run.
10
+ *
11
+ * Errors are per-document rather than fatal: the run continues and reports what
12
+ * failed, mirroring how `pushChangesTo` reports `rejectedEntries`. Because every
13
+ * produced entry id is deterministic, re-running after a failure or a
14
+ * cancellation transfers only what is still missing.
15
+ *
16
+ * @module
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.copyDocuments = copyDocuments;
20
+ exports.buildDocHistoryPurgeRequest = buildDocHistoryPurgeRequest;
21
+ const idGeneration_1 = require("../utils/idGeneration");
22
+ const feasibility_1 = require("./feasibility");
23
+ const copyDocument_1 = require("./copyDocument");
24
+ /** How many entries one metadata scan page pulls when a cursor scan is available. */
25
+ const SCAN_PAGE_SIZE = 1000;
26
+ /**
27
+ * Collect the source document ids a selector matches.
28
+ *
29
+ * Prefix selection reads store metadata only — never a payload — which is what
30
+ * keeps a shard keyless. Only the ids are retained, so the working set stays
31
+ * proportional to the document count rather than the entry count even on a
32
+ * store with millions of entries.
33
+ */
34
+ async function selectDocIds(source, selector) {
35
+ const selected = new Set(selector.docIds ?? []);
36
+ const prefixes = selector.idPrefix === undefined
37
+ ? []
38
+ : Array.isArray(selector.idPrefix)
39
+ ? selector.idPrefix
40
+ : [selector.idPrefix];
41
+ if (prefixes.length > 0) {
42
+ const matches = (docId) => prefixes.some((prefix) => (0, idGeneration_1.matchesDocIdPrefix)(docId, prefix));
43
+ const store = source.store;
44
+ if (store.scanEntriesSince) {
45
+ let cursor = null;
46
+ for (;;) {
47
+ const page = await store.scanEntriesSince(cursor, SCAN_PAGE_SIZE);
48
+ for (const entry of page.entries) {
49
+ if (matches(entry.docId))
50
+ selected.add(entry.docId);
51
+ }
52
+ if (!page.hasMore || !page.nextCursor)
53
+ break;
54
+ cursor = page.nextCursor;
55
+ }
56
+ }
57
+ else {
58
+ for (const entry of await store.findNewEntries([])) {
59
+ if (matches(entry.docId))
60
+ selected.add(entry.docId);
61
+ }
62
+ }
63
+ }
64
+ return [...selected].sort();
65
+ }
66
+ /** Copy many documents into another database in one pass. */
67
+ async function copyDocuments(source, target, selector, options = {}) {
68
+ if ((selector.docIds === undefined || selector.docIds.length === 0) &&
69
+ selector.idPrefix === undefined) {
70
+ throw new Error("copyDocumentsTo requires a selector with at least one of docIds or idPrefix.");
71
+ }
72
+ for (const [role, host] of [
73
+ ["source", source],
74
+ ["target", target],
75
+ ]) {
76
+ if (host.store.getId() === feasibility_1.DIRECTORY_DB_ID) {
77
+ throw new Error(`The tenant directory database cannot be used as a copy ${role}.`);
78
+ }
79
+ }
80
+ const reporter = new copyDocument_1.CopyProgressReporter(options.onProgress);
81
+ reporter.emit("preparing", "Selecting documents to copy");
82
+ const docIds = await selectDocIds(source, selector);
83
+ reporter.totalDocuments = docIds.length;
84
+ reporter.documentsCompleted = 0;
85
+ reporter.emit("planning", `Selected ${docIds.length} documents to copy`);
86
+ const documents = [];
87
+ const failed = [];
88
+ let cancelled = false;
89
+ for (const docId of docIds) {
90
+ if (options.signal?.aborted) {
91
+ cancelled = true;
92
+ break;
93
+ }
94
+ try {
95
+ const result = await (0, copyDocument_1.copyDocument)(source, target, docId, { ...options, targetDocId: options.targetDocId ?? "new" }, reporter);
96
+ documents.push(result);
97
+ if (result.cancelled) {
98
+ cancelled = true;
99
+ break;
100
+ }
101
+ }
102
+ catch (error) {
103
+ failed.push({
104
+ docId,
105
+ error: error instanceof Error ? error.message : String(error),
106
+ });
107
+ }
108
+ reporter.documentsCompleted = (reporter.documentsCompleted ?? 0) + 1;
109
+ }
110
+ reporter.currentDocId = undefined;
111
+ reporter.emit("complete", `Copied ${documents.length} of ${docIds.length} documents` +
112
+ (failed.length > 0 ? `, ${failed.length} failed` : ""));
113
+ return {
114
+ documents,
115
+ copiedDocIds: documents
116
+ .filter((result) => !result.cancelled)
117
+ .map((result) => result.sourceDocId),
118
+ failed,
119
+ copiedEntries: reporter.copiedEntries,
120
+ copiedBytes: reporter.copiedBytes,
121
+ copiedAttachments: reporter.copiedAttachments,
122
+ cancelled,
123
+ };
124
+ }
125
+ /**
126
+ * Turn a completed shard into the purge request that reclaims the source.
127
+ *
128
+ * No new purge machinery is involved: this only shapes the result for the
129
+ * existing pipeline. The admin publishes the returned request into the
130
+ * directory database, and the server's `executePendingPurges` denylists each
131
+ * document id before deleting it, so a stale replica cannot re-push into the
132
+ * gap.
133
+ *
134
+ * Two ordering rules matter and are not enforceable here:
135
+ *
136
+ * 1. Publish only after the shard target has been pushed **and witnessed**.
137
+ * Copied entries are provisional until they are re-witnessed, and a purge is
138
+ * irreversible.
139
+ * 2. `dbId` must name the **source** database. The denylist is keyed by
140
+ * database id, which is precisely why purging the source leaves the shard
141
+ * target — holding the same document ids under a different database id —
142
+ * untouched.
143
+ *
144
+ * For a very large shard, split {@link CopyDocumentsResult.copiedDocIds} across
145
+ * several requests: the id list lives inside a single directory document, and
146
+ * idempotency is tracked per `requestId`.
147
+ */
148
+ function buildDocHistoryPurgeRequest(result, options) {
149
+ if (result.copiedDocIds.length === 0) {
150
+ throw new Error("Refusing to build a purge request from a copy that moved no documents.");
151
+ }
152
+ if (result.failed.length > 0) {
153
+ throw new Error(`Refusing to build a purge request: ${result.failed.length} document(s) failed to copy ` +
154
+ `(${result.failed.map((failure) => failure.docId).join(", ")}). ` +
155
+ "Re-run the copy until it completes cleanly, or build the request from a filtered id list.");
156
+ }
157
+ return {
158
+ v: 1,
159
+ tenantId: options.tenantId,
160
+ requestId: options.requestId,
161
+ dbId: options.dbId,
162
+ docIds: result.copiedDocIds,
163
+ reason: options.reason,
164
+ preparedByPublicKey: options.preparedByPublicKey,
165
+ };
166
+ }
167
+ //# sourceMappingURL=copyDocuments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyDocuments.js","sourceRoot":"","sources":["../../../src/core/copy/copyDocuments.ts"],"names":[],"mappings":"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"}