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,49 @@
1
+ /**
2
+ * Pure entry-rewriting helpers shared by the graft and replay strategies.
3
+ *
4
+ * @internal
5
+ * @module
6
+ */
7
+ import type { StoreEntry, StoreEntryMetadata, StoreEntryType } from "../types";
8
+ /**
9
+ * The entry types that make up a document's revision graph. `doc_snapshot` is
10
+ * included deliberately: after a dense sync it can be the only entry a peer
11
+ * holds for a document, so skipping it would silently drop content.
12
+ */
13
+ export declare const DOCUMENT_DAG_ENTRY_TYPES: ReadonlySet<StoreEntryType>;
14
+ /** True when the entry is part of the document revision graph. */
15
+ export declare function isDocumentDagEntry(entry: StoreEntryMetadata): boolean;
16
+ /**
17
+ * Re-point an entry id from one document to another.
18
+ *
19
+ * Every entry id — document (`<docId>_d_<depsFingerprint>_<automergeHash>`) and
20
+ * attachment chunk (`<docId>_a_<fileUuid7>_<chunkUuid>`) alike — begins with the
21
+ * document id followed by `_`, so re-homing an entry is a prefix swap.
22
+ *
23
+ * This is exact rather than a shortcut, and it is what makes a replay cheap:
24
+ * the deps fingerprint is `SHA-256` over the sorted *Automerge* dependency
25
+ * hashes, which a copy never changes, and the Automerge hash is a property of
26
+ * the change bytes, which a copy reuses verbatim. So the re-derived id is
27
+ * identical to what `generateDocEntryId()` would return under the new document
28
+ * id — without decrypting or decoding anything — and it is deterministic, which
29
+ * is what lets an interrupted copy resume by simply running again.
30
+ *
31
+ * Ids that do not carry the source prefix (a dependency on a foreign entry)
32
+ * are returned unchanged.
33
+ */
34
+ export declare function remapEntryId(entryId: string, sourceDocId: string, targetDocId: string): string;
35
+ /**
36
+ * Remove the server's witness receipt from a copied entry.
37
+ *
38
+ * The receipt signature binds the database id (see `crypto/WitnessReceipt.ts`),
39
+ * so carrying it into a different database would fail verification and
40
+ * quarantine the entry as `invalid_witness_receipt`. Stripped entries are
41
+ * provisional until the target database is pushed and re-witnessed.
42
+ *
43
+ * `receiptOrder` goes too: it is a per-store sequence the receiving store
44
+ * assigns, meaningless in another one.
45
+ */
46
+ export declare function stripWitnessReceipt<T extends StoreEntryMetadata>(entry: T): T;
47
+ /** Sum the encrypted payload sizes of a batch, for progress and result totals. */
48
+ export declare function sumEncryptedSize(entries: StoreEntry[]): number;
49
+ //# sourceMappingURL=entryRewrite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entryRewrite.d.ts","sourceRoot":"","sources":["../../../src/core/copy/entryRewrite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,cAAc,CAM/D,CAAC;AAEH,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAErE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,MAAM,CAIR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,kBAAkB,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAS7E;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAE9D"}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ /**
3
+ * Pure entry-rewriting helpers shared by the graft and replay strategies.
4
+ *
5
+ * @internal
6
+ * @module
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.DOCUMENT_DAG_ENTRY_TYPES = void 0;
10
+ exports.isDocumentDagEntry = isDocumentDagEntry;
11
+ exports.remapEntryId = remapEntryId;
12
+ exports.stripWitnessReceipt = stripWitnessReceipt;
13
+ exports.sumEncryptedSize = sumEncryptedSize;
14
+ /**
15
+ * The entry types that make up a document's revision graph. `doc_snapshot` is
16
+ * included deliberately: after a dense sync it can be the only entry a peer
17
+ * holds for a document, so skipping it would silently drop content.
18
+ */
19
+ exports.DOCUMENT_DAG_ENTRY_TYPES = new Set([
20
+ "doc_create",
21
+ "doc_change",
22
+ "doc_delete",
23
+ "doc_undelete",
24
+ "doc_snapshot",
25
+ ]);
26
+ /** True when the entry is part of the document revision graph. */
27
+ function isDocumentDagEntry(entry) {
28
+ return exports.DOCUMENT_DAG_ENTRY_TYPES.has(entry.entryType);
29
+ }
30
+ /**
31
+ * Re-point an entry id from one document to another.
32
+ *
33
+ * Every entry id — document (`<docId>_d_<depsFingerprint>_<automergeHash>`) and
34
+ * attachment chunk (`<docId>_a_<fileUuid7>_<chunkUuid>`) alike — begins with the
35
+ * document id followed by `_`, so re-homing an entry is a prefix swap.
36
+ *
37
+ * This is exact rather than a shortcut, and it is what makes a replay cheap:
38
+ * the deps fingerprint is `SHA-256` over the sorted *Automerge* dependency
39
+ * hashes, which a copy never changes, and the Automerge hash is a property of
40
+ * the change bytes, which a copy reuses verbatim. So the re-derived id is
41
+ * identical to what `generateDocEntryId()` would return under the new document
42
+ * id — without decrypting or decoding anything — and it is deterministic, which
43
+ * is what lets an interrupted copy resume by simply running again.
44
+ *
45
+ * Ids that do not carry the source prefix (a dependency on a foreign entry)
46
+ * are returned unchanged.
47
+ */
48
+ function remapEntryId(entryId, sourceDocId, targetDocId) {
49
+ if (sourceDocId === targetDocId)
50
+ return entryId;
51
+ if (!entryId.startsWith(`${sourceDocId}_`))
52
+ return entryId;
53
+ return `${targetDocId}${entryId.slice(sourceDocId.length)}`;
54
+ }
55
+ /**
56
+ * Remove the server's witness receipt from a copied entry.
57
+ *
58
+ * The receipt signature binds the database id (see `crypto/WitnessReceipt.ts`),
59
+ * so carrying it into a different database would fail verification and
60
+ * quarantine the entry as `invalid_witness_receipt`. Stripped entries are
61
+ * provisional until the target database is pushed and re-witnessed.
62
+ *
63
+ * `receiptOrder` goes too: it is a per-store sequence the receiving store
64
+ * assigns, meaningless in another one.
65
+ */
66
+ function stripWitnessReceipt(entry) {
67
+ const { receivedAt: _receivedAt, receivedByPublicKey: _receivedByPublicKey, receivedDateSignature: _receivedDateSignature, receiptOrder: _receiptOrder, ...rest } = entry;
68
+ return rest;
69
+ }
70
+ /** Sum the encrypted payload sizes of a batch, for progress and result totals. */
71
+ function sumEncryptedSize(entries) {
72
+ return entries.reduce((total, entry) => total + entry.encryptedSize, 0);
73
+ }
74
+ //# sourceMappingURL=entryRewrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entryRewrite.js","sourceRoot":"","sources":["../../../src/core/copy/entryRewrite.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAkBH,gDAEC;AAoBD,oCAQC;AAaD,kDASC;AAGD,4CAEC;AAvED;;;;GAIG;AACU,QAAA,wBAAwB,GAAgC,IAAI,GAAG,CAAiB;IAC3F,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,cAAc;CACf,CAAC,CAAC;AAEH,kEAAkE;AAClE,SAAgB,kBAAkB,CAAC,KAAyB;IAC1D,OAAO,gCAAwB,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,YAAY,CAC1B,OAAe,EACf,WAAmB,EACnB,WAAmB;IAEnB,IAAI,WAAW,KAAK,WAAW;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,WAAW,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAC3D,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,mBAAmB,CAA+B,KAAQ;IACxE,MAAM,EACJ,UAAU,EAAE,WAAW,EACvB,mBAAmB,EAAE,oBAAoB,EACzC,qBAAqB,EAAE,sBAAsB,EAC7C,YAAY,EAAE,aAAa,EAC3B,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IACV,OAAO,IAAS,CAAC;AACnB,CAAC;AAED,kFAAkF;AAClF,SAAgB,gBAAgB,CAAC,OAAqB;IACpD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Pure strategy resolution for document copies.
3
+ *
4
+ * Everything here is a side-effect-free function of a {@link CopyContext} plus
5
+ * the caller's {@link CopyDocumentOptions}, which keeps the "can I do this, and
6
+ * what would it cost me" question answerable without touching a store, and
7
+ * keeps the rules unit-testable in isolation from the copy engine.
8
+ *
9
+ * @module
10
+ */
11
+ import type { CopyDocumentOptions, CopyFeasibility } from "./types";
12
+ /** The tenant directory database id. Never a valid copy source or target. */
13
+ export declare const DIRECTORY_DB_ID = "directory";
14
+ /**
15
+ * Everything the resolver needs to know about the source and target, gathered
16
+ * by the copy engine before any work starts.
17
+ *
18
+ * @internal
19
+ */
20
+ export interface CopyContext {
21
+ /** Tenant owning the source database. */
22
+ sourceTenantId: string;
23
+ /** Tenant owning the target database. */
24
+ targetTenantId: string;
25
+ /** Source database (store) id. */
26
+ sourceDbId: string;
27
+ /** Target database (store) id. */
28
+ targetDbId: string;
29
+ /** The document id being read from the source. */
30
+ sourceDocId: string;
31
+ /** The document id that will be written in the target, already resolved. */
32
+ targetDocId: string;
33
+ /** The `decryptionKeyId` the source document's entries currently use. */
34
+ sourceDecryptionKeyId: string;
35
+ /** The `decryptionKeyId` the copy will be written under, already resolved. */
36
+ targetDecryptionKeyId: string;
37
+ /** True when source and target document entries live in the same store. */
38
+ sameStore: boolean;
39
+ /** True when the target store already holds an entry for {@link targetDocId}. */
40
+ targetHasDocId: boolean;
41
+ }
42
+ /**
43
+ * Resolve the effective target `decryptionKeyId` for a copy.
44
+ *
45
+ * Within one tenant the source document's own key is kept, so a copy stays
46
+ * readable by exactly the same people and — crucially — stays eligible for
47
+ * authorship preservation. Across tenants the source key id is meaningless
48
+ * (key ids resolve tenant-scoped), so the copy falls back to the target
49
+ * tenant's `"default"` key.
50
+ */
51
+ export declare function resolveTargetDecryptionKeyId(requested: string | undefined, sourceDecryptionKeyId: string, sameTenant: boolean): string;
52
+ /**
53
+ * Decide what a copy would do, and whether it can run at all.
54
+ *
55
+ * The rules, in order:
56
+ *
57
+ * 1. Neither side may be the tenant directory database.
58
+ * 2. `flatten` mode always resolves to the flatten strategy and never preserves
59
+ * authorship (there is no original entry left to preserve).
60
+ * 3. `history` mode preserves authorship only in the exact configuration where
61
+ * the original `metadataSignature` remains valid: same tenant, same document
62
+ * id, same key, different database. Anything else re-authors.
63
+ * 4. Asking for `authorship: "preserve"` outside that configuration is refused
64
+ * rather than silently downgraded, because a caller who asked for it is
65
+ * relying on the signatures being real.
66
+ */
67
+ export declare function resolveCopyFeasibility(context: CopyContext, options?: CopyDocumentOptions): CopyFeasibility;
68
+ /**
69
+ * Turn an unusable {@link CopyFeasibility} into the error thrown by
70
+ * `copyDocumentTo` / `copyDocumentsTo`.
71
+ */
72
+ export declare function copyFeasibilityError(feasibility: CopyFeasibility): Error;
73
+ //# sourceMappingURL=feasibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feasibility.d.ts","sourceRoot":"","sources":["../../../src/core/copy/feasibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EAIhB,MAAM,SAAS,CAAC;AAEjB,6EAA6E;AAC7E,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,8EAA8E;IAC9E,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2EAA2E;IAC3E,SAAS,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,qBAAqB,EAAE,MAAM,EAC7B,UAAU,EAAE,OAAO,GAClB,MAAM,CAGR;AAUD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,mBAAwB,GAChC,eAAe,CAgJjB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,eAAe,GAAG,KAAK,CAKxE"}
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ /**
3
+ * Pure strategy resolution for document copies.
4
+ *
5
+ * Everything here is a side-effect-free function of a {@link CopyContext} plus
6
+ * the caller's {@link CopyDocumentOptions}, which keeps the "can I do this, and
7
+ * what would it cost me" question answerable without touching a store, and
8
+ * keeps the rules unit-testable in isolation from the copy engine.
9
+ *
10
+ * @module
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.DIRECTORY_DB_ID = void 0;
14
+ exports.resolveTargetDecryptionKeyId = resolveTargetDecryptionKeyId;
15
+ exports.resolveCopyFeasibility = resolveCopyFeasibility;
16
+ exports.copyFeasibilityError = copyFeasibilityError;
17
+ /** The tenant directory database id. Never a valid copy source or target. */
18
+ exports.DIRECTORY_DB_ID = "directory";
19
+ /**
20
+ * Resolve the effective target `decryptionKeyId` for a copy.
21
+ *
22
+ * Within one tenant the source document's own key is kept, so a copy stays
23
+ * readable by exactly the same people and — crucially — stays eligible for
24
+ * authorship preservation. Across tenants the source key id is meaningless
25
+ * (key ids resolve tenant-scoped), so the copy falls back to the target
26
+ * tenant's `"default"` key.
27
+ */
28
+ function resolveTargetDecryptionKeyId(requested, sourceDecryptionKeyId, sameTenant) {
29
+ if (requested)
30
+ return requested;
31
+ return sameTenant ? sourceDecryptionKeyId : "default";
32
+ }
33
+ /** Build a reason record with a stable code and a human-readable message. */
34
+ function reason(code, message) {
35
+ return { code, message };
36
+ }
37
+ /**
38
+ * Decide what a copy would do, and whether it can run at all.
39
+ *
40
+ * The rules, in order:
41
+ *
42
+ * 1. Neither side may be the tenant directory database.
43
+ * 2. `flatten` mode always resolves to the flatten strategy and never preserves
44
+ * authorship (there is no original entry left to preserve).
45
+ * 3. `history` mode preserves authorship only in the exact configuration where
46
+ * the original `metadataSignature` remains valid: same tenant, same document
47
+ * id, same key, different database. Anything else re-authors.
48
+ * 4. Asking for `authorship: "preserve"` outside that configuration is refused
49
+ * rather than silently downgraded, because a caller who asked for it is
50
+ * relying on the signatures being real.
51
+ */
52
+ function resolveCopyFeasibility(context, options = {}) {
53
+ const mode = options.mode ?? "flatten";
54
+ const authorship = options.authorship ?? "reauthor";
55
+ const wantsPreserve = authorship === "preserve";
56
+ const sameTenant = context.sourceTenantId === context.targetTenantId;
57
+ const sameDocId = context.sourceDocId === context.targetDocId;
58
+ const sameKey = context.sourceDecryptionKeyId === context.targetDecryptionKeyId;
59
+ // Key ids resolve per tenant, so an identical id across tenants still names a
60
+ // different key and still forces re-encryption.
61
+ const requiresReEncryption = !sameTenant || !sameKey;
62
+ const reasons = [];
63
+ const isDirectory = (dbId) => dbId === exports.DIRECTORY_DB_ID;
64
+ if (isDirectory(context.sourceDbId) || isDirectory(context.targetDbId)) {
65
+ reasons.push(reason("directory_database", "The tenant directory database cannot be used as a copy source or target."));
66
+ return {
67
+ allowed: false,
68
+ strategy: mode === "flatten" ? "flatten" : "replay",
69
+ authorshipPreserved: false,
70
+ willMergeIntoExisting: false,
71
+ sameStore: context.sameStore,
72
+ requiresReEncryption,
73
+ reasons,
74
+ };
75
+ }
76
+ if (context.sameStore && sameDocId) {
77
+ reasons.push(reason("same_database_same_doc_id", `Source and target are the same database (${context.sourceDbId}) and the ` +
78
+ `target document id is unchanged (${context.targetDocId}), so there is ` +
79
+ "nothing to copy. Use targetDocId 'new' to duplicate in place."));
80
+ return {
81
+ allowed: false,
82
+ strategy: mode === "flatten" ? "flatten" : "replay",
83
+ authorshipPreserved: false,
84
+ willMergeIntoExisting: true,
85
+ sameStore: true,
86
+ requiresReEncryption,
87
+ reasons,
88
+ };
89
+ }
90
+ if (mode === "flatten") {
91
+ if (wantsPreserve) {
92
+ reasons.push(reason("flatten_mode", "Flatten mode writes a single new change, so there is no original " +
93
+ "entry whose authorship could be preserved. Use mode 'history' with " +
94
+ "authorship 'preserve'."));
95
+ return {
96
+ allowed: false,
97
+ strategy: "flatten",
98
+ authorshipPreserved: false,
99
+ willMergeIntoExisting: context.targetHasDocId,
100
+ sameStore: context.sameStore,
101
+ requiresReEncryption,
102
+ reasons,
103
+ };
104
+ }
105
+ return {
106
+ allowed: true,
107
+ strategy: "flatten",
108
+ authorshipPreserved: false,
109
+ willMergeIntoExisting: context.targetHasDocId,
110
+ sameStore: context.sameStore,
111
+ requiresReEncryption,
112
+ reasons,
113
+ };
114
+ }
115
+ // mode === "history": collect every condition that blocks preservation.
116
+ if (!sameTenant) {
117
+ reasons.push(reason("different_tenant", `Source tenant '${context.sourceTenantId}' differs from target tenant ` +
118
+ `'${context.targetTenantId}'. The payload must be re-encrypted under the ` +
119
+ "target tenant key, and the source authors' keys are not in the target " +
120
+ "tenant's directory, so their signatures could not be verified there."));
121
+ }
122
+ if (!sameDocId) {
123
+ reasons.push(reason("different_doc_id", `The copy lands under document id '${context.targetDocId}' instead of ` +
124
+ `'${context.sourceDocId}'. Entry ids embed the document id and the ` +
125
+ "author's metadataSignature binds both, so the original signatures " +
126
+ "cannot carry over. Use targetDocId 'same' to preserve authorship."));
127
+ }
128
+ if (!sameKey) {
129
+ reasons.push(reason("different_key", `The copy is encrypted under key '${context.targetDecryptionKeyId}' instead ` +
130
+ `of '${context.sourceDecryptionKeyId}'. Re-encryption changes contentHash, ` +
131
+ "which the author's metadataSignature binds."));
132
+ }
133
+ const canPreserve = reasons.length === 0;
134
+ if (wantsPreserve && !canPreserve) {
135
+ return {
136
+ allowed: false,
137
+ strategy: "replay",
138
+ authorshipPreserved: false,
139
+ willMergeIntoExisting: context.targetHasDocId,
140
+ sameStore: context.sameStore,
141
+ requiresReEncryption,
142
+ reasons,
143
+ };
144
+ }
145
+ const strategy = wantsPreserve ? "graft" : "replay";
146
+ return {
147
+ allowed: true,
148
+ strategy,
149
+ authorshipPreserved: strategy === "graft",
150
+ willMergeIntoExisting: context.targetHasDocId,
151
+ sameStore: context.sameStore,
152
+ requiresReEncryption,
153
+ // A successful graft has nothing to explain. A replay lists what would have
154
+ // had to be true for authorship to survive, so callers can tell an
155
+ // unavoidable re-author from an accidental one.
156
+ reasons: strategy === "graft" ? [] : reasons,
157
+ };
158
+ }
159
+ /**
160
+ * Turn an unusable {@link CopyFeasibility} into the error thrown by
161
+ * `copyDocumentTo` / `copyDocumentsTo`.
162
+ */
163
+ function copyFeasibilityError(feasibility) {
164
+ const detail = feasibility.reasons
165
+ .map((entry) => `[${entry.code}] ${entry.message}`)
166
+ .join(" ");
167
+ return new Error(`Document copy is not possible with the requested options. ${detail}`);
168
+ }
169
+ //# sourceMappingURL=feasibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feasibility.js","sourceRoot":"","sources":["../../../src/core/copy/feasibility.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAmDH,oEAOC;AAyBD,wDAmJC;AAMD,oDAKC;AAvOD,6EAA6E;AAChE,QAAA,eAAe,GAAG,WAAW,CAAC;AA+B3C;;;;;;;;GAQG;AACH,SAAgB,4BAA4B,CAC1C,SAA6B,EAC7B,qBAA6B,EAC7B,UAAmB;IAEnB,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,OAAO,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC;AAED,6EAA6E;AAC7E,SAAS,MAAM,CACb,IAA+B,EAC/B,OAAe;IAEf,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,sBAAsB,CACpC,OAAoB,EACpB,UAA+B,EAAE;IAEjC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC;IACpD,MAAM,aAAa,GAAG,UAAU,KAAK,UAAU,CAAC;IAEhD,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,KAAK,OAAO,CAAC,cAAc,CAAC;IACrE,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC;IAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,qBAAqB,KAAK,OAAO,CAAC,qBAAqB,CAAC;IAChF,8EAA8E;IAC9E,gDAAgD;IAChD,MAAM,oBAAoB,GAAG,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC;IAErD,MAAM,OAAO,GAA4B,EAAE,CAAC;IAE5C,MAAM,WAAW,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,IAAI,KAAK,uBAAe,CAAC;IACxE,IAAI,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,IAAI,CACV,MAAM,CACJ,oBAAoB,EACpB,0EAA0E,CAC3E,CACF,CAAC;QACF,OAAO;YACL,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;YACnD,mBAAmB,EAAE,KAAK;YAC1B,qBAAqB,EAAE,KAAK;YAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,oBAAoB;YACpB,OAAO;SACR,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,IAAI,SAAS,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CACV,MAAM,CACJ,2BAA2B,EAC3B,4CAA4C,OAAO,CAAC,UAAU,YAAY;YACxE,oCAAoC,OAAO,CAAC,WAAW,iBAAiB;YACxE,+DAA+D,CAClE,CACF,CAAC;QACF,OAAO;YACL,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;YACnD,mBAAmB,EAAE,KAAK;YAC1B,qBAAqB,EAAE,IAAI;YAC3B,SAAS,EAAE,IAAI;YACf,oBAAoB;YACpB,OAAO;SACR,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CACV,MAAM,CACJ,cAAc,EACd,mEAAmE;gBACjE,qEAAqE;gBACrE,wBAAwB,CAC3B,CACF,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,SAAS;gBACnB,mBAAmB,EAAE,KAAK;gBAC1B,qBAAqB,EAAE,OAAO,CAAC,cAAc;gBAC7C,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,oBAAoB;gBACpB,OAAO;aACR,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,SAAS;YACnB,mBAAmB,EAAE,KAAK;YAC1B,qBAAqB,EAAE,OAAO,CAAC,cAAc;YAC7C,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,oBAAoB;YACpB,OAAO;SACR,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CACV,MAAM,CACJ,kBAAkB,EAClB,kBAAkB,OAAO,CAAC,cAAc,+BAA+B;YACrE,IAAI,OAAO,CAAC,cAAc,gDAAgD;YAC1E,wEAAwE;YACxE,sEAAsE,CACzE,CACF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CACV,MAAM,CACJ,kBAAkB,EAClB,qCAAqC,OAAO,CAAC,WAAW,eAAe;YACrE,IAAI,OAAO,CAAC,WAAW,6CAA6C;YACpE,oEAAoE;YACpE,mEAAmE,CACtE,CACF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CACV,MAAM,CACJ,eAAe,EACf,oCAAoC,OAAO,CAAC,qBAAqB,YAAY;YAC3E,OAAO,OAAO,CAAC,qBAAqB,wCAAwC;YAC5E,6CAA6C,CAChD,CACF,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;IACzC,IAAI,aAAa,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,QAAQ;YAClB,mBAAmB,EAAE,KAAK;YAC1B,qBAAqB,EAAE,OAAO,CAAC,cAAc;YAC7C,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,oBAAoB;YACpB,OAAO;SACR,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAiB,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,QAAQ;QACR,mBAAmB,EAAE,QAAQ,KAAK,OAAO;QACzC,qBAAqB,EAAE,OAAO,CAAC,cAAc;QAC7C,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,oBAAoB;QACpB,4EAA4E;QAC5E,mEAAmE;QACnE,gDAAgD;QAChD,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;KAC7C,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,WAA4B;IAC/D,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO;SAC/B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;SAClD,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,IAAI,KAAK,CAAC,6DAA6D,MAAM,EAAE,CAAC,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The flatten copy strategy.
3
+ *
4
+ * Reads the source document's state — at its head, or as of
5
+ * {@link CopyDocumentOptions.atTimestamp} — and writes it into the target as a
6
+ * brand-new document with a single revision. History, original authors and the
7
+ * CRDT structure are all deliberately left behind; what arrives is a clean
8
+ * document that happens to have the same content.
9
+ *
10
+ * Unlike the two history strategies this one goes entirely through the public
11
+ * document API, which is what makes it work regardless of tenant, key or
12
+ * document id: `createDocument` + one `changeDoc`, with attachments re-uploaded
13
+ * through `addAttachmentStream` so they get fresh chunk ids in the target.
14
+ *
15
+ * **Caveat worth knowing:** materializing an Automerge document to plain JS
16
+ * collapses its text fields into ordinary strings. A flattened copy therefore
17
+ * loses the character-level text CRDT structure, and concurrent edits to those
18
+ * fields merge as whole-value conflicts rather than per-character. That is
19
+ * usually the right trade for a fresh document, but it is the reason
20
+ * `mode: "history"` exists.
21
+ *
22
+ * @module
23
+ */
24
+ import type { CopyEngineHost } from "./host";
25
+ import type { CopyContext } from "./feasibility";
26
+ import type { CopyProgressReporter } from "./copyDocument";
27
+ import type { CopyDocumentOptions, CopyDocumentResult } from "./types";
28
+ /**
29
+ * Document-level provenance for a flattened copy.
30
+ *
31
+ * Per-change provenance would be meaningless here — the copy has exactly one
32
+ * change, authored by the copying user, that corresponds to no single source
33
+ * revision — so the origin is recorded once in the payload instead, which also
34
+ * keeps flatten free of any store-format concern.
35
+ */
36
+ export interface FlattenedDocumentProvenance {
37
+ /** When the copy ran (epoch millis). */
38
+ copiedAt: number;
39
+ /** Tenant the content came from. */
40
+ sourceTenantId: string;
41
+ /** Database the content came from. */
42
+ sourceDbId: string;
43
+ /** Document the content came from. */
44
+ sourceDocId: string;
45
+ /**
46
+ * The point in the source's history that was captured, when the caller asked
47
+ * for a specific one via {@link CopyDocumentOptions.atTimestamp}.
48
+ */
49
+ sourceAtTimestamp?: number;
50
+ /** Signing key of the user who made the copy. */
51
+ copiedByPublicKey: string;
52
+ }
53
+ /** Flatten one document into the target database. */
54
+ export declare function flattenDocument(source: CopyEngineHost, target: CopyEngineHost, context: CopyContext, options: CopyDocumentOptions, reporter: CopyProgressReporter): Promise<CopyDocumentResult>;
55
+ //# sourceMappingURL=flatten.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten.d.ts","sourceRoot":"","sources":["../../../src/core/copy/flatten.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAqBD,qDAAqD;AACrD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAyI7B"}
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ /**
3
+ * The flatten copy strategy.
4
+ *
5
+ * Reads the source document's state — at its head, or as of
6
+ * {@link CopyDocumentOptions.atTimestamp} — and writes it into the target as a
7
+ * brand-new document with a single revision. History, original authors and the
8
+ * CRDT structure are all deliberately left behind; what arrives is a clean
9
+ * document that happens to have the same content.
10
+ *
11
+ * Unlike the two history strategies this one goes entirely through the public
12
+ * document API, which is what makes it work regardless of tenant, key or
13
+ * document id: `createDocument` + one `changeDoc`, with attachments re-uploaded
14
+ * through `addAttachmentStream` so they get fresh chunk ids in the target.
15
+ *
16
+ * **Caveat worth knowing:** materializing an Automerge document to plain JS
17
+ * collapses its text fields into ordinary strings. A flattened copy therefore
18
+ * loses the character-level text CRDT structure, and concurrent edits to those
19
+ * fields merge as whole-value conflicts rather than per-character. That is
20
+ * usually the right trade for a fresh document, but it is the reason
21
+ * `mode: "history"` exists.
22
+ *
23
+ * @module
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.flattenDocument = flattenDocument;
27
+ const types_1 = require("../types");
28
+ /** Payload key holding {@link FlattenedDocumentProvenance}. */
29
+ const PROVENANCE_FIELD = "_provenance";
30
+ /**
31
+ * Materialize the source payload as plain data the target can accept.
32
+ *
33
+ * `_`-prefixed keys are MindooDB's own namespace (`_attachments`,
34
+ * `_lastModified`) and are managed by the target database, so they are dropped
35
+ * rather than copied over stale.
36
+ */
37
+ function copyablePayload(payload) {
38
+ const copy = {};
39
+ for (const [key, value] of Object.entries(payload)) {
40
+ if (key.startsWith("_"))
41
+ continue;
42
+ copy[key] = structuredClone(value);
43
+ }
44
+ return copy;
45
+ }
46
+ /** Flatten one document into the target database. */
47
+ async function flattenDocument(source, target, context, options, reporter) {
48
+ const { sourceDocId, targetDocId } = context;
49
+ reporter.emit("planning", `Reading ${sourceDocId} for a flattened copy`);
50
+ const sourceDoc = options.atTimestamp != null
51
+ ? await source.db.getDocumentAtTimestamp(sourceDocId, options.atTimestamp)
52
+ : await source.db.getDocument(sourceDocId);
53
+ if (!sourceDoc) {
54
+ throw new Error(options.atTimestamp != null
55
+ ? `Document ${sourceDocId} did not exist at timestamp ${options.atTimestamp}.`
56
+ : `Document ${sourceDocId} was not found in database ${context.sourceDbId}.`);
57
+ }
58
+ const usesGeneratedId = (options.targetDocId ?? "new") === "new";
59
+ if (!usesGeneratedId && !types_1.CUSTOM_DOC_ID_REGEX.test(targetDocId)) {
60
+ // Ids minted by MindooDB may start with a digit, which the caller-provided
61
+ // id rules reject. Say so here rather than letting createDocument fail with
62
+ // a message that gives no hint about the copy.
63
+ throw new Error(`Cannot flatten into document id '${targetDocId}': caller-provided ids must ` +
64
+ "match /^[A-Za-z][A-Za-z0-9_]*$/. Copy with mode 'history' to keep a " +
65
+ "MindooDB-generated id, or pass an explicit targetDocId that satisfies the rule.");
66
+ }
67
+ const copiedByPublicKey = options.signingKeyPair?.publicKey ??
68
+ (await target.tenant.getCurrentUserId()).userSigningPublicKey;
69
+ const payload = copyablePayload(sourceDoc.getData());
70
+ let provenance;
71
+ if (options.provenance !== false) {
72
+ provenance = {
73
+ copiedAt: Date.now(),
74
+ sourceTenantId: context.sourceTenantId,
75
+ sourceDbId: context.sourceDbId,
76
+ sourceDocId,
77
+ copiedByPublicKey,
78
+ };
79
+ if (options.atTimestamp != null) {
80
+ // Automerge rejects an explicit `undefined`, so optional fields have to be
81
+ // left out entirely rather than assigned an absent value.
82
+ provenance.sourceAtTimestamp = options.atTimestamp;
83
+ }
84
+ }
85
+ const includeAttachments = options.includeAttachments !== false;
86
+ const sourceAttachments = includeAttachments ? sourceDoc.getAttachments() : [];
87
+ // Fold the payload into the `doc_create` change instead of writing a second
88
+ // entry for it. A caller-provided id normally cannot do this: it is seeded
89
+ // from a hard-coded Automerge change so independent replicas converge on the
90
+ // same hash, and baking content into that change would diverge it per
91
+ // document — `createDocument` rejects the combination. `assumeUniqueId` is
92
+ // the caller's assertion that concurrent same-id creation cannot happen, so
93
+ // convergence is moot and the create can take the generated-id path.
94
+ //
95
+ // `copyablePayload` has already dropped every `_`-prefixed key, so nothing is
96
+ // silently lost to `initialValues`' own reserved-field sanitizer.
97
+ const assumeUniqueId = !usesGeneratedId && options.assumeUniqueTargetDocId === true;
98
+ const seedPayloadIntoCreate = usesGeneratedId || assumeUniqueId;
99
+ const idsBefore = new Set((await target.store.findNewEntriesForDoc([], targetDocId)).map((entry) => entry.id));
100
+ reporter.emit("transferring", `Writing flattened copy as ${targetDocId}`);
101
+ const targetDoc = await target.db.createDocument({
102
+ ...(usesGeneratedId
103
+ ? { idPrefix: options.idPrefix }
104
+ : { id: targetDocId, assumeUniqueId }),
105
+ ...(seedPayloadIntoCreate ? { initialValues: payload } : {}),
106
+ decryptionKeyId: context.targetDecryptionKeyId,
107
+ signingKeyPair: options.signingKeyPair,
108
+ signingKeyPassword: options.signingKeyPassword,
109
+ bypassAccessControlPrecheck: options.bypassAccessControlPrecheck,
110
+ });
111
+ // Whatever the create could not carry. `_provenance` is in MindooDB's
112
+ // reserved namespace, which `initialValues` refuses to seed, so asking for
113
+ // provenance costs the second entry — the price of keeping the marker out of
114
+ // the caller's field namespace, where a later re-copy would treat it as
115
+ // ordinary content.
116
+ const needsFollowUpChange = !seedPayloadIntoCreate || provenance !== undefined || sourceAttachments.length > 0;
117
+ if (needsFollowUpChange) {
118
+ await target.db.changeDoc(targetDoc, async (draft) => {
119
+ if (!seedPayloadIntoCreate) {
120
+ Object.assign(draft.getData(), payload);
121
+ }
122
+ if (provenance) {
123
+ draft.getData()[PROVENANCE_FIELD] = provenance;
124
+ }
125
+ for (const attachment of sourceAttachments) {
126
+ if (options.signal?.aborted)
127
+ break;
128
+ await draft.addAttachmentStream(sourceDoc.streamAttachment(attachment.attachmentId), attachment.fileName, attachment.mimeType);
129
+ }
130
+ }, {
131
+ signingKeyPair: options.signingKeyPair,
132
+ signingKeyPassword: options.signingKeyPassword,
133
+ bypassAccessControlPrecheck: options.bypassAccessControlPrecheck,
134
+ });
135
+ }
136
+ const written = (await target.store.findNewEntriesForDoc([], targetDoc.getId())).filter((entry) => !idsBefore.has(entry.id));
137
+ reporter.copiedEntries += written.length;
138
+ for (const entry of written) {
139
+ reporter.copiedBytes += entry.encryptedSize;
140
+ }
141
+ reporter.copiedAttachments += sourceAttachments.length;
142
+ reporter.emit("complete", `Flattened ${sourceDocId} into ${targetDoc.getId()}`);
143
+ return {
144
+ sourceDocId,
145
+ targetDocId: targetDoc.getId(),
146
+ strategy: "flatten",
147
+ authorshipPreserved: false,
148
+ mergedIntoExisting: context.targetHasDocId,
149
+ copiedEntries: written.length,
150
+ copiedBytes: written.reduce((total, entry) => total + entry.encryptedSize, 0),
151
+ copiedAttachments: sourceAttachments.length,
152
+ cancelled: options.signal?.aborted ?? false,
153
+ };
154
+ }
155
+ //# sourceMappingURL=flatten.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten.js","sourceRoot":"","sources":["../../../src/core/copy/flatten.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;AAuDH,0CA+IC;AApMD,oCAA+C;AAiC/C,+DAA+D;AAC/D,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAEvC;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,OAAyB;IAChD,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClC,IAAI,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qDAAqD;AAC9C,KAAK,UAAU,eAAe,CACnC,MAAsB,EACtB,MAAsB,EACtB,OAAoB,EACpB,OAA4B,EAC5B,QAA8B;IAE9B,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAE7C,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,WAAW,uBAAuB,CAAC,CAAC;IACzE,MAAM,SAAS,GACb,OAAO,CAAC,WAAW,IAAI,IAAI;QACzB,CAAC,CAAC,MAAM,MAAM,CAAC,EAAE,CAAC,sBAAsB,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC;QAC1E,CAAC,CAAC,MAAM,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,WAAW,IAAI,IAAI;YACzB,CAAC,CAAC,YAAY,WAAW,+BAA+B,OAAO,CAAC,WAAW,GAAG;YAC9E,CAAC,CAAC,YAAY,WAAW,8BAA8B,OAAO,CAAC,UAAU,GAAG,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC;IACjE,IAAI,CAAC,eAAe,IAAI,CAAC,2BAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/D,2EAA2E;QAC3E,4EAA4E;QAC5E,+CAA+C;QAC/C,MAAM,IAAI,KAAK,CACb,oCAAoC,WAAW,8BAA8B;YAC3E,sEAAsE;YACtE,iFAAiF,CACpF,CAAC;IACJ,CAAC;IAED,MAAM,iBAAiB,GACrB,OAAO,CAAC,cAAc,EAAE,SAAS;QACjC,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,oBAAoB,CAAC;IAChE,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAErD,IAAI,UAAmD,CAAC;IACxD,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;QACjC,UAAU,GAAG;YACX,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;YACpB,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,WAAW;YACX,iBAAiB;SAClB,CAAC;QACF,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC;YAChC,2EAA2E;YAC3E,0DAA0D;YAC1D,UAAU,CAAC,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;QACrD,CAAC;IACH,CAAC;IAED,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,KAAK,KAAK,CAAC;IAChE,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/E,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,sEAAsE;IACtE,2EAA2E;IAC3E,4EAA4E;IAC5E,qEAAqE;IACrE,EAAE;IACF,8EAA8E;IAC9E,kEAAkE;IAClE,MAAM,cAAc,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,uBAAuB,KAAK,IAAI,CAAC;IACpF,MAAM,qBAAqB,GAAG,eAAe,IAAI,cAAc,CAAC;IAEhE,MAAM,SAAS,GAAG,IAAI,GAAG,CACvB,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CACpF,CAAC;IAEF,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,6BAA6B,WAAW,EAAE,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC;QAC/C,GAAG,CAAC,eAAe;YACjB,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;YAChC,CAAC,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;QACxC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,eAAe,EAAE,OAAO,CAAC,qBAAqB;QAC9C,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,2BAA2B,EAAE,OAAO,CAAC,2BAA2B;KACjE,CAAC,CAAC;IAEH,sEAAsE;IACtE,2EAA2E;IAC3E,6EAA6E;IAC7E,wEAAwE;IACxE,oBAAoB;IACpB,MAAM,mBAAmB,GACvB,CAAC,qBAAqB,IAAI,UAAU,KAAK,SAAS,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;IAErF,IAAI,mBAAmB,EAAE,CAAC;QACxB,MAAM,MAAM,CAAC,EAAE,CAAC,SAAS,CACvB,SAAS,EACT,KAAK,EAAE,KAAgB,EAAE,EAAE;YACzB,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;YACD,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,CAAC,OAAO,EAAE,CAAC,gBAAgB,CAAC,GAAG,UAAU,CAAC;YACjD,CAAC;YACD,KAAK,MAAM,UAAU,IAAI,iBAAiB,EAAE,CAAC;gBAC3C,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;oBAAE,MAAM;gBACnC,MAAM,KAAK,CAAC,mBAAmB,CAC7B,SAAS,CAAC,gBAAgB,CAAC,UAAU,CAAC,YAAY,CAAC,EACnD,UAAU,CAAC,QAAQ,EACnB,UAAU,CAAC,QAAQ,CACpB,CAAC;YACJ,CAAC;QACH,CAAC,EACD;YACE,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,2BAA2B,EAAE,OAAO,CAAC,2BAA2B;SACjE,CACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,CACd,MAAM,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAC/D,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9C,QAAQ,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IACzC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,QAAQ,CAAC,WAAW,IAAI,KAAK,CAAC,aAAa,CAAC;IAC9C,CAAC;IACD,QAAQ,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,CAAC;IACvD,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,WAAW,SAAS,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEhF,OAAO;QACL,WAAW;QACX,WAAW,EAAE,SAAS,CAAC,KAAK,EAAE;QAC9B,QAAQ,EAAE,SAAS;QACnB,mBAAmB,EAAE,KAAK;QAC1B,kBAAkB,EAAE,OAAO,CAAC,cAAc;QAC1C,aAAa,EAAE,OAAO,CAAC,MAAM;QAC7B,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;QAC7E,iBAAiB,EAAE,iBAAiB,CAAC,MAAM;QAC3C,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,KAAK;KAC5C,CAAC;AACJ,CAAC"}