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,53 @@
1
+ /**
2
+ * Attachment chunk copying.
3
+ *
4
+ * Chunk entry ids embed the document id (`<docId>_a_<fileUuid7>_<chunkUuid>`)
5
+ * and a document's payload points at them by id through
6
+ * `_attachments[].lastChunkId`. That forces two different strategies depending
7
+ * on whether the copy crosses a store boundary:
8
+ *
9
+ * - **Different store** (the normal case, including every shard): keep the
10
+ * chunk ids exactly as they are and only re-home the `docId` metadata field.
11
+ * Nothing can collide, because the target store has never seen those ids, and
12
+ * leaving them alone is what lets the document's change bytes replay
13
+ * unmodified — the payload's `lastChunkId` values still resolve.
14
+ *
15
+ * - **Same store, new document id** (duplicating a document in place): the ids
16
+ * must be re-prefixed. Reusing them is not an option: the stores implement an
17
+ * id write as remove-then-insert, so a verbatim copy would overwrite the
18
+ * source's own chunk metadata and re-point it at the copy. The copied history
19
+ * keeps referring to the source's chunks (still present in the same store,
20
+ * holding identical bytes, so attachment time travel still works), and one
21
+ * trailing change re-points the copy's current revision at the chunks it owns.
22
+ *
23
+ * @module
24
+ */
25
+ import type { StoreEntryMetadata } from "../types";
26
+ import type { CopyEngineHost } from "./host";
27
+ import type { CopyContext } from "./feasibility";
28
+ import type { CopySigningKey, CopyProgressReporter } from "./copyDocument";
29
+ import type { CopyDocumentOptions, CopyFeasibility } from "./types";
30
+ /**
31
+ * The result of copying a document's attachment chunks, plus the deferred step
32
+ * that can only run once the document's own entries are in place.
33
+ *
34
+ * @internal
35
+ */
36
+ export interface AttachmentCopyPlan {
37
+ /** True when the abort signal fired before the chunks were fully copied. */
38
+ cancelled: boolean;
39
+ /**
40
+ * Same-store copies only: append the one trailing change that re-points
41
+ * `_attachments[].lastChunkId` at the re-prefixed chunks. A no-op otherwise.
42
+ */
43
+ finalize(signing?: CopySigningKey): Promise<void>;
44
+ }
45
+ /**
46
+ * Copy every attachment chunk belonging to a document.
47
+ *
48
+ * Runs before the document's own entries so that the signed `attachmentRefs`
49
+ * snapshot each copied revision carries always describes chunks that already
50
+ * exist in the target.
51
+ */
52
+ export declare function copyDocumentAttachments(source: CopyEngineHost, target: CopyEngineHost, context: CopyContext, feasibility: CopyFeasibility, options: CopyDocumentOptions, reporter: CopyProgressReporter, sourceDagEntries: StoreEntryMetadata[]): Promise<AttachmentCopyPlan>;
53
+ //# sourceMappingURL=attachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../../src/core/copy/attachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,OAAO,KAAK,EAAc,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAKpE;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAQD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,eAAe,EAC5B,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,oBAAoB,EAC9B,gBAAgB,EAAE,kBAAkB,EAAE,GACrC,OAAO,CAAC,kBAAkB,CAAC,CA8G7B"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ /**
3
+ * Attachment chunk copying.
4
+ *
5
+ * Chunk entry ids embed the document id (`<docId>_a_<fileUuid7>_<chunkUuid>`)
6
+ * and a document's payload points at them by id through
7
+ * `_attachments[].lastChunkId`. That forces two different strategies depending
8
+ * on whether the copy crosses a store boundary:
9
+ *
10
+ * - **Different store** (the normal case, including every shard): keep the
11
+ * chunk ids exactly as they are and only re-home the `docId` metadata field.
12
+ * Nothing can collide, because the target store has never seen those ids, and
13
+ * leaving them alone is what lets the document's change bytes replay
14
+ * unmodified — the payload's `lastChunkId` values still resolve.
15
+ *
16
+ * - **Same store, new document id** (duplicating a document in place): the ids
17
+ * must be re-prefixed. Reusing them is not an option: the stores implement an
18
+ * id write as remove-then-insert, so a verbatim copy would overwrite the
19
+ * source's own chunk metadata and re-point it at the copy. The copied history
20
+ * keeps referring to the source's chunks (still present in the same store,
21
+ * holding identical bytes, so attachment time travel still works), and one
22
+ * trailing change re-points the copy's current revision at the chunks it owns.
23
+ *
24
+ * @module
25
+ */
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.copyDocumentAttachments = copyDocumentAttachments;
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 entryRewrite_1 = require("./entryRewrite");
33
+ /** Default entries written per `putEntries` call. */
34
+ const DEFAULT_BATCH_SIZE = 200;
35
+ /** A plan that does nothing, for documents without attachments. */
36
+ const NO_ATTACHMENTS = {
37
+ cancelled: false,
38
+ finalize: async () => { },
39
+ };
40
+ /**
41
+ * Copy every attachment chunk belonging to a document.
42
+ *
43
+ * Runs before the document's own entries so that the signed `attachmentRefs`
44
+ * snapshot each copied revision carries always describes chunks that already
45
+ * exist in the target.
46
+ */
47
+ async function copyDocumentAttachments(source, target, context, feasibility, options, reporter, sourceDagEntries) {
48
+ if (options.includeAttachments === false) {
49
+ return NO_ATTACHMENTS;
50
+ }
51
+ const sourceChunks = (await source.attachmentStore.findNewEntriesForDoc([], context.sourceDocId)).filter((entry) => entry.entryType === "attachment_chunk");
52
+ if (sourceChunks.length === 0) {
53
+ return NO_ATTACHMENTS;
54
+ }
55
+ // Only a same-store copy is forced to rename chunks; see the module comment.
56
+ const reprefixChunkIds = context.sameStore;
57
+ const chunkTargetDocId = context.targetDocId;
58
+ const remapChunkId = (chunkId) => reprefixChunkIds
59
+ ? (0, entryRewrite_1.remapEntryId)(chunkId, context.sourceDocId, chunkTargetDocId)
60
+ : chunkId;
61
+ const ordered = (0, DocumentDagAnalysis_1.orderDagEntriesCausally)(sourceChunks);
62
+ const targetIds = ordered.map((entry) => remapChunkId(entry.id));
63
+ const alreadyPresent = new Set(await target.attachmentStore.hasEntries(targetIds));
64
+ const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
65
+ const signing = options.signingKeyPair && options.signingKeyPassword
66
+ ? {
67
+ signingKeyPair: options.signingKeyPair,
68
+ signingKeyPassword: options.signingKeyPassword,
69
+ }
70
+ : undefined;
71
+ const copierPublicKey = signing?.signingKeyPair.publicKey ??
72
+ (await target.tenant.getCurrentUserId()).userSigningPublicKey;
73
+ const copyTime = (0, timeSource_1.semanticNow)();
74
+ const copiedAttachmentIds = new Set();
75
+ for (let offset = 0; offset < ordered.length; offset += batchSize) {
76
+ if (options.signal?.aborted) {
77
+ return { cancelled: true, finalize: async () => { } };
78
+ }
79
+ const slice = ordered.slice(offset, offset + batchSize);
80
+ const needed = slice.filter((_entry, index) => !alreadyPresent.has(targetIds[offset + index]));
81
+ if (needed.length === 0)
82
+ continue;
83
+ const fetched = await source.attachmentStore.getEntries(needed.map((entry) => entry.id));
84
+ const transformed = [];
85
+ for (const sourceEntry of fetched) {
86
+ transformed.push(feasibility.strategy === "graft"
87
+ ? (0, entryRewrite_1.stripWitnessReceipt)({ ...sourceEntry })
88
+ : await replayChunk(source, target, context, feasibility, sourceEntry, {
89
+ id: remapChunkId(sourceEntry.id),
90
+ dependencyIds: sourceEntry.dependencyIds.map(remapChunkId),
91
+ createdAt: copyTime,
92
+ createdByPublicKey: copierPublicKey,
93
+ signing,
94
+ }));
95
+ if (sourceEntry.attachmentId) {
96
+ copiedAttachmentIds.add(sourceEntry.attachmentId);
97
+ }
98
+ }
99
+ if (transformed.length > 0) {
100
+ await target.attachmentStore.putEntries(transformed);
101
+ reporter.copiedEntries += transformed.length;
102
+ for (const entry of transformed) {
103
+ reporter.copiedBytes += entry.encryptedSize;
104
+ }
105
+ }
106
+ reporter.emit("transferring", `Copied ${transformed.length} attachment chunks of ${context.sourceDocId}`);
107
+ }
108
+ reporter.copiedAttachments += copiedAttachmentIds.size;
109
+ if (!reprefixChunkIds) {
110
+ return { cancelled: false, finalize: async () => { } };
111
+ }
112
+ // The re-prefixed chunks are in place but nothing points at them yet: the
113
+ // copied revisions still carry the source's chunk ids in their payloads. Look
114
+ // up the document's live attachment set from the newest signed refs snapshot
115
+ // (no decryption needed) and hand the re-pointing to the target database.
116
+ const liveRefs = latestAttachmentRefs(sourceDagEntries);
117
+ return {
118
+ cancelled: false,
119
+ finalize: async (finalizeSigning) => {
120
+ if (liveRefs.length === 0)
121
+ return;
122
+ const pointerRemap = new Map();
123
+ for (const ref of liveRefs) {
124
+ pointerRemap.set(ref.attachmentId, remapChunkId(ref.lastChunkId));
125
+ }
126
+ await target.remapAttachmentPointers(chunkTargetDocId, pointerRemap, finalizeSigning ?? signing);
127
+ },
128
+ };
129
+ }
130
+ /**
131
+ * The document's current attachment set, read from the signed `attachmentRefs`
132
+ * snapshot on its newest revision.
133
+ *
134
+ * Every document revision carries the complete set as of that revision, so the
135
+ * newest one is authoritative — and reading it needs no decryption key.
136
+ */
137
+ function latestAttachmentRefs(sourceDagEntries) {
138
+ let newest;
139
+ for (const entry of sourceDagEntries) {
140
+ if (!entry.attachmentRefs || entry.attachmentRefs.length === 0)
141
+ continue;
142
+ if (!newest || entry.createdAt > newest.createdAt) {
143
+ newest = entry;
144
+ }
145
+ }
146
+ return newest?.attachmentRefs ?? [];
147
+ }
148
+ /**
149
+ * Re-home and re-sign one attachment chunk.
150
+ *
151
+ * Attachment payloads use a deterministic IV, so re-encrypting the same chunk
152
+ * under the same key reproduces the same ciphertext and `contentHash` — which
153
+ * is why a same-tenant copy into the same store deduplicates the bytes instead
154
+ * of storing them twice.
155
+ */
156
+ async function replayChunk(source, target, context, feasibility, sourceEntry, rewrite) {
157
+ let encryptedData = sourceEntry.encryptedData;
158
+ let contentHash = sourceEntry.contentHash;
159
+ if (feasibility.requiresReEncryption) {
160
+ const plaintext = await source.decryptAttachmentPayload(sourceEntry.encryptedData, sourceEntry.decryptionKeyId);
161
+ encryptedData = await target.encryptAttachmentPayload(plaintext, context.targetDecryptionKeyId);
162
+ contentHash = await (0, idGeneration_1.computeContentHash)(encryptedData, target.tenant.getCryptoAdapter().getSubtle());
163
+ }
164
+ const signature = rewrite.signing
165
+ ? await target.tenant.signPayloadWithKey(encryptedData, rewrite.signing.signingKeyPair, rewrite.signing.signingKeyPassword)
166
+ : await target.tenant.signPayload(encryptedData);
167
+ const entry = {
168
+ entryType: "attachment_chunk",
169
+ id: rewrite.id,
170
+ contentHash,
171
+ docId: context.targetDocId,
172
+ dependencyIds: rewrite.dependencyIds,
173
+ createdAt: rewrite.createdAt,
174
+ attachmentId: sourceEntry.attachmentId,
175
+ createdByPublicKey: rewrite.createdByPublicKey,
176
+ decryptionKeyId: context.targetDecryptionKeyId,
177
+ signature,
178
+ originalSize: sourceEntry.originalSize,
179
+ encryptedSize: encryptedData.length,
180
+ entryVersion: types_1.CURRENT_STORE_ENTRY_VERSION,
181
+ encryptedData,
182
+ };
183
+ entry.metadataSignature = await target.computeEntryMetadataSignature(entry, rewrite.signing);
184
+ return entry;
185
+ }
186
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/core/copy/attachments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * The document copy engine.
3
+ *
4
+ * Orchestrates the three strategies described in `docs/document-copy.md`:
5
+ * `flatten` (delegated to `flatten.ts`, which goes through the public document
6
+ * API), and the two history-preserving strategies implemented here.
7
+ *
8
+ * `graft` and `replay` share one pipeline — order the source revision graph
9
+ * causally, skip what the target already has, transform in batches, write — and
10
+ * differ only in the per-entry transform:
11
+ *
12
+ * - **graft** strips the witness receipt and changes nothing else, so the
13
+ * original authors' signatures remain valid.
14
+ * - **replay** re-homes each entry under the target document id and re-signs it
15
+ * as the copying user, recording the original author in a verifiable
16
+ * provenance record.
17
+ *
18
+ * @module
19
+ */
20
+ import type { SigningKeyPair, StoreEntryMetadata } from "../types";
21
+ import type { CopyEngineHost } from "./host";
22
+ import { type CopyContext } from "./feasibility";
23
+ import type { CopyDocumentOptions, CopyDocumentResult, CopyFeasibility, CopyProgress, CopyProgressPhase } from "./types";
24
+ /**
25
+ * A resolved custom signing identity for a copy, or `undefined` to sign as the
26
+ * current user. Both fields are always present together.
27
+ *
28
+ * @internal
29
+ */
30
+ export interface CopySigningKey {
31
+ signingKeyPair: SigningKeyPair;
32
+ signingKeyPassword: string;
33
+ }
34
+ /**
35
+ * Normalize the caller's signing options: a key pair is only usable together
36
+ * with its password, so a half-supplied pair is treated as absent.
37
+ *
38
+ * @internal
39
+ */
40
+ export declare function resolveCopySigningKey(options: CopyDocumentOptions): CopySigningKey | undefined;
41
+ /**
42
+ * The key the copy's entries will be signed with: the caller's service identity
43
+ * when supplied, the current user's otherwise.
44
+ *
45
+ * @internal
46
+ */
47
+ export declare function resolveCopierPublicKey(target: CopyEngineHost, options: CopyDocumentOptions): Promise<string>;
48
+ /**
49
+ * Accumulates copy totals and emits {@link CopyProgress} events.
50
+ *
51
+ * Shared by the single-document and bulk paths so a bulk run reports one
52
+ * continuously rising total rather than restarting the counters per document.
53
+ */
54
+ export declare class CopyProgressReporter {
55
+ private readonly onProgress?;
56
+ copiedEntries: number;
57
+ copiedBytes: number;
58
+ scannedEntries: number;
59
+ copiedAttachments: number;
60
+ totalSourceEntries?: number;
61
+ currentDocId?: string;
62
+ documentsCompleted?: number;
63
+ totalDocuments?: number;
64
+ constructor(onProgress?: ((progress: CopyProgress) => void) | undefined);
65
+ emit(phase: CopyProgressPhase, message: string): void;
66
+ }
67
+ /**
68
+ * Gather the source/target facts the strategy resolver needs, then resolve it.
69
+ *
70
+ * Shared by `copyDocument` and `canCopyDocument` so the answer a caller gets
71
+ * from the dry run is the one the real run will act on.
72
+ */
73
+ export declare function prepareCopy(source: CopyEngineHost, target: CopyEngineHost, sourceDocId: string, options: CopyDocumentOptions, precomputedTargetDocId?: string): Promise<{
74
+ context: CopyContext;
75
+ feasibility: CopyFeasibility;
76
+ sourceEntries: StoreEntryMetadata[];
77
+ }>;
78
+ /** Dry run: report what a copy would do without writing anything. */
79
+ export declare function canCopyDocument(source: CopyEngineHost, target: CopyEngineHost, docId: string, options?: CopyDocumentOptions): Promise<CopyFeasibility>;
80
+ /**
81
+ * Copy one document into another database.
82
+ *
83
+ * @see `docs/document-copy.md` for the strategy matrix and caveats.
84
+ */
85
+ export declare function copyDocument(source: CopyEngineHost, target: CopyEngineHost, docId: string, options?: CopyDocumentOptions, sharedReporter?: CopyProgressReporter): Promise<CopyDocumentResult>;
86
+ //# sourceMappingURL=copyDocument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyDocument.d.ts","sourceRoot":"","sources":["../../../src/core/copy/copyDocument.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAc,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAUvB,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAKjB;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,cAAc,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,GAC3B,cAAc,GAAG,SAAS,CAM5B;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED;;;;;GAKG;AACH,qBAAa,oBAAoB;IAUnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IATxC,aAAa,SAAK;IAClB,WAAW,SAAK;IAChB,cAAc,SAAK;IACnB,iBAAiB,SAAK;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;gBAEK,UAAU,CAAC,GAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,aAAA;IAE1E,IAAI,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CActD;AAkCD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,mBAAmB,EAC5B,sBAAsB,CAAC,EAAE,MAAM,GAC9B,OAAO,CAAC;IACT,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,eAAe,CAAC;IAC7B,aAAa,EAAE,kBAAkB,EAAE,CAAC;CACrC,CAAC,CA8CD;AAED,qEAAqE;AACrE,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,eAAe,CAAC,CAG1B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,EACjC,cAAc,CAAC,EAAE,oBAAoB,GACpC,OAAO,CAAC,kBAAkB,CAAC,CA2B7B"}