@fluidframework/tree 2.100.0 → 2.101.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/api-report/tree.alpha.api.md +3 -1
- package/api-report/tree.beta.api.md +3 -1
- package/api-report/tree.legacy.beta.api.md +3 -1
- package/dist/core/change-family/changeFamily.d.ts +23 -0
- package/dist/core/change-family/changeFamily.d.ts.map +1 -1
- package/dist/core/change-family/changeFamily.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodecV1.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodecV1.js +2 -0
- package/dist/core/tree/detachedFieldIndexCodecV1.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodecV2.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodecV2.js +2 -0
- package/dist/core/tree/detachedFieldIndexCodecV2.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +13 -4
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js +30 -3
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +27 -0
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.js +4 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +9 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js +6 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js +9 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts +3 -3
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +8 -8
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKindFormat.d.ts +2 -14
- package/dist/feature-libraries/modular-schema/genericFieldKindFormat.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKindFormat.js +1 -17
- package/dist/feature-libraries/modular-schema/genericFieldKindFormat.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js +4 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/independentView.d.ts.map +1 -1
- package/dist/shared-tree/independentView.js +2 -0
- package/dist/shared-tree/independentView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +35 -1
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +6 -0
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.js +1 -0
- package/dist/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/dist/shared-tree/treeAlpha.d.ts.map +1 -1
- package/dist/shared-tree/treeAlpha.js +2 -0
- package/dist/shared-tree/treeAlpha.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +2 -0
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.d.ts +3 -0
- package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsCommons.d.ts +14 -0
- package/dist/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsCommons.js +14 -0
- package/dist/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts +3 -0
- package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts +3 -0
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -1
- package/dist/shared-tree-core/editManagerSummarizer.d.ts +9 -1
- package/dist/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerSummarizer.js +20 -5
- package/dist/shared-tree-core/editManagerSummarizer.js.map +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.js +4 -0
- package/dist/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
- package/dist/shared-tree-core/messageCodecVSharedBranches.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecVSharedBranches.js +4 -0
- package/dist/shared-tree-core/messageCodecVSharedBranches.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +4 -0
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/api/schemaFactory.d.ts +3 -3
- package/dist/simple-tree/api/schemaFactory.js +3 -3
- package/dist/simple-tree/api/schemaFactory.js.map +1 -1
- package/dist/tableSchema.d.ts.map +1 -1
- package/dist/tableSchema.js +102 -20
- package/dist/tableSchema.js.map +1 -1
- package/lib/core/change-family/changeFamily.d.ts +23 -0
- package/lib/core/change-family/changeFamily.d.ts.map +1 -1
- package/lib/core/change-family/changeFamily.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodecV1.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodecV1.js +2 -0
- package/lib/core/tree/detachedFieldIndexCodecV1.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodecV2.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodecV2.js +2 -0
- package/lib/core/tree/detachedFieldIndexCodecV2.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +13 -4
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js +30 -3
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +27 -0
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.js +4 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +9 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js +6 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js +9 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts +3 -3
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +8 -8
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKindFormat.d.ts +2 -14
- package/lib/feature-libraries/modular-schema/genericFieldKindFormat.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKindFormat.js +1 -17
- package/lib/feature-libraries/modular-schema/genericFieldKindFormat.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js +4 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/independentView.d.ts.map +1 -1
- package/lib/shared-tree/independentView.js +2 -0
- package/lib/shared-tree/independentView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +35 -1
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +6 -0
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.js +1 -0
- package/lib/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/lib/shared-tree/treeAlpha.d.ts.map +1 -1
- package/lib/shared-tree/treeAlpha.js +2 -0
- package/lib/shared-tree/treeAlpha.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +2 -0
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.d.ts +3 -0
- package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsCommons.d.ts +14 -0
- package/lib/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsCommons.js +14 -0
- package/lib/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts +3 -0
- package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts +3 -0
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -1
- package/lib/shared-tree-core/editManagerSummarizer.d.ts +9 -1
- package/lib/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerSummarizer.js +20 -5
- package/lib/shared-tree-core/editManagerSummarizer.js.map +1 -1
- package/lib/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
- package/lib/shared-tree-core/messageCodecV1ToV4.js +4 -0
- package/lib/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
- package/lib/shared-tree-core/messageCodecVSharedBranches.d.ts.map +1 -1
- package/lib/shared-tree-core/messageCodecVSharedBranches.js +4 -0
- package/lib/shared-tree-core/messageCodecVSharedBranches.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +4 -0
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/api/schemaFactory.d.ts +3 -3
- package/lib/simple-tree/api/schemaFactory.js +3 -3
- package/lib/simple-tree/api/schemaFactory.js.map +1 -1
- package/lib/tableSchema.d.ts.map +1 -1
- package/lib/tableSchema.js +103 -21
- package/lib/tableSchema.js.map +1 -1
- package/package.json +22 -22
- package/src/core/change-family/changeFamily.ts +25 -0
- package/src/core/tree/detachedFieldIndexCodecV1.ts +2 -0
- package/src/core/tree/detachedFieldIndexCodecV2.ts +2 -0
- package/src/feature-libraries/chunked-forest/codec/chunkDecoding.ts +59 -10
- package/src/feature-libraries/chunked-forest/codec/codecs.ts +32 -0
- package/src/feature-libraries/chunked-forest/codec/compressedEncode.ts +6 -1
- package/src/feature-libraries/chunked-forest/codec/nodeEncoder.ts +9 -1
- package/src/feature-libraries/chunked-forest/codec/schemaBasedEncode.ts +9 -1
- package/src/feature-libraries/modular-schema/genericFieldKindFormat.ts +3 -21
- package/src/feature-libraries/modular-schema/modularChangeCodecV1.ts +4 -0
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/independentView.ts +2 -0
- package/src/shared-tree/sharedTree.ts +41 -1
- package/src/shared-tree/sharedTreeChangeCodecs.ts +1 -0
- package/src/shared-tree/treeAlpha.ts +2 -0
- package/src/shared-tree/treeCheckout.ts +2 -0
- package/src/shared-tree-core/editManagerCodecs.ts +3 -0
- package/src/shared-tree-core/editManagerCodecsCommons.ts +29 -0
- package/src/shared-tree-core/editManagerCodecsV1toV4.ts +3 -0
- package/src/shared-tree-core/editManagerCodecsVSharedBranches.ts +3 -0
- package/src/shared-tree-core/editManagerSummarizer.ts +17 -5
- package/src/shared-tree-core/messageCodecV1ToV4.ts +4 -0
- package/src/shared-tree-core/messageCodecVSharedBranches.ts +5 -1
- package/src/shared-tree-core/sharedTreeCore.ts +8 -1
- package/src/simple-tree/api/schemaFactory.ts +3 -3
- package/src/tableSchema.ts +134 -35
|
@@ -7,6 +7,8 @@ import type { IIdCompressor, SessionId } from "@fluidframework/id-compressor";
|
|
|
7
7
|
|
|
8
8
|
import type { ICodecFamily, IJsonCodec } from "../../codec/index.js";
|
|
9
9
|
import type { SchemaAndPolicy } from "../../core/index.js";
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- Referenced by doc comments
|
|
11
|
+
import type { FieldBatchEncodingContext } from "../../feature-libraries/index.js";
|
|
10
12
|
import type { JsonCompatibleReadOnly } from "../../util/index.js";
|
|
11
13
|
import type { ChangeRebaser, RevisionTag, TaggedChange } from "../rebase/index.js";
|
|
12
14
|
|
|
@@ -25,6 +27,29 @@ export interface ChangeEncodingContext {
|
|
|
25
27
|
readonly revision: RevisionTag | undefined;
|
|
26
28
|
readonly idCompressor: IIdCompressor;
|
|
27
29
|
readonly schema?: SchemaAndPolicy;
|
|
30
|
+
/**
|
|
31
|
+
* `true` when this context is encoding to or decoding from a summary blob.
|
|
32
|
+
* `false` when this context is for an op (or any other non-summary path,
|
|
33
|
+
* including utility encoders that aren't tied to persistence).
|
|
34
|
+
*
|
|
35
|
+
* @remarks
|
|
36
|
+
* Used to gate decode-time recovery behavior — for example, healing of
|
|
37
|
+
* unresolvable identifier IDs — that should only run when loading a
|
|
38
|
+
* (possibly broken) attach-summary blob, never when applying ops.
|
|
39
|
+
*/
|
|
40
|
+
readonly isSummary: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* If `true`, identifier values that the local id-compressor cannot resolve
|
|
43
|
+
* during decode are healed into deterministic stable UUIDs instead of
|
|
44
|
+
* throwing. See {@link FieldBatchEncodingContext.healUnresolvableIdentifiersOnDecode}.
|
|
45
|
+
* Only takes effect when `isSummary` is also `true`.
|
|
46
|
+
*/
|
|
47
|
+
readonly healUnresolvableIdentifiersOnDecode?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* The SharedTree's shared-object id, used as input to the deterministic
|
|
50
|
+
* UUID derivation when {@link healUnresolvableIdentifiersOnDecode} triggers.
|
|
51
|
+
*/
|
|
52
|
+
readonly sharedObjectId?: string;
|
|
28
53
|
}
|
|
29
54
|
|
|
30
55
|
export type ChangeFamilyCodec<TChange> = IJsonCodec<
|
|
@@ -61,6 +61,8 @@ class MajorCodec implements IJsonCodec<Major, EncodedRevisionTag> {
|
|
|
61
61
|
originatorId: this.revisionTagCodec.localSessionId,
|
|
62
62
|
idCompressor: this.idCompressor,
|
|
63
63
|
revision: undefined,
|
|
64
|
+
// DetachedFieldIndex codecs are only used by the summarizer.
|
|
65
|
+
isSummary: true,
|
|
64
66
|
});
|
|
65
67
|
}
|
|
66
68
|
}
|
|
@@ -49,6 +49,8 @@ class MajorCodec implements IJsonCodec<Major> {
|
|
|
49
49
|
originatorId: this.revisionTagCodec.localSessionId,
|
|
50
50
|
idCompressor: this.idCompressor,
|
|
51
51
|
revision: undefined,
|
|
52
|
+
// DetachedFieldIndex codecs are only used by the summarizer.
|
|
53
|
+
isSummary: true,
|
|
52
54
|
});
|
|
53
55
|
}
|
|
54
56
|
}
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
OpSpaceCompressedId,
|
|
10
10
|
SessionId,
|
|
11
11
|
} from "@fluidframework/id-compressor";
|
|
12
|
+
import { v5 as uuidV5 } from "uuid";
|
|
12
13
|
|
|
13
14
|
import { DiscriminatedUnionDispatcher } from "../../../codec/index.js";
|
|
14
15
|
import type {
|
|
@@ -37,7 +38,8 @@ import {
|
|
|
37
38
|
decode as genericDecode,
|
|
38
39
|
readStreamIdentifier,
|
|
39
40
|
} from "./chunkDecodingGeneric.js";
|
|
40
|
-
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- Referenced by doc comments
|
|
42
|
+
import type { FieldBatchEncodingContext, IncrementalDecoder } from "./codecs.js";
|
|
41
43
|
import {
|
|
42
44
|
type EncodedAnyShape,
|
|
43
45
|
type EncodedChunkShapeV1OrV2,
|
|
@@ -59,13 +61,32 @@ export interface IdDecodingContext {
|
|
|
59
61
|
* The creator of any local Ids to be decoded.
|
|
60
62
|
*/
|
|
61
63
|
originatorId: SessionId;
|
|
64
|
+
/**
|
|
65
|
+
* {@inheritdoc FieldBatchEncodingContext.isSummary}
|
|
66
|
+
*/
|
|
67
|
+
isSummary: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* See {@link FieldBatchEncodingContext.healUnresolvableIdentifiersOnDecode}.
|
|
70
|
+
*/
|
|
71
|
+
healUnresolvableIdentifiersOnDecode?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* See {@link FieldBatchEncodingContext.sharedObjectId}.
|
|
74
|
+
*/
|
|
75
|
+
sharedObjectId?: string;
|
|
62
76
|
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Random v4 UUID generated as a namespace for the "heal an unresolvable identifier into a stable UUID"
|
|
80
|
+
* path in {@link readValue}. This scheme requires consensus across all clients to function.
|
|
81
|
+
*/
|
|
82
|
+
const healingNamespace = "f8a89df3-6882-400f-b913-4c1f6f0157bd";
|
|
83
|
+
|
|
63
84
|
/**
|
|
64
85
|
* Decode `chunk` into a TreeChunk.
|
|
65
86
|
*/
|
|
66
87
|
export function decode(
|
|
67
88
|
chunk: EncodedFieldBatchV1OrV2,
|
|
68
|
-
idDecodingContext:
|
|
89
|
+
idDecodingContext: IdDecodingContext,
|
|
69
90
|
incrementalDecoder?: IncrementalDecoder,
|
|
70
91
|
): TreeChunk[] {
|
|
71
92
|
return genericDecode(
|
|
@@ -126,15 +147,43 @@ export function readValue(
|
|
|
126
147
|
typeof streamValue === "number" || typeof streamValue === "string",
|
|
127
148
|
0x997 /* identifier must be string or number. */,
|
|
128
149
|
);
|
|
150
|
+
if (typeof streamValue === "string") {
|
|
151
|
+
return streamValue;
|
|
152
|
+
}
|
|
129
153
|
const idCompressor = idDecodingContext.idCompressor;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
154
|
+
// OpSpaceCompressedIds are negative, and require a session-id to compute their value.
|
|
155
|
+
// Due to a bug, we have some special casing for them (see below).
|
|
156
|
+
// TODO: isFinalId should probably be exported from id-compressor and that could be used to do the narrowing here.
|
|
157
|
+
if (idDecodingContext.isSummary === true && streamValue < 0) {
|
|
158
|
+
if (
|
|
159
|
+
idDecodingContext.healUnresolvableIdentifiersOnDecode === true &&
|
|
160
|
+
idDecodingContext.sharedObjectId !== undefined
|
|
161
|
+
) {
|
|
162
|
+
// Documents written before the encode-side fix for non-finalized identifier
|
|
163
|
+
// values can persist negative op-space IDs that are no
|
|
164
|
+
// longer resolvable once the originating session's local state has been stripped.
|
|
165
|
+
// When loading such a summary with the heal-on-decode option on, synthesize a deterministic
|
|
166
|
+
// stable UUID so all readers of the same blob agree on the resulting value.
|
|
167
|
+
//
|
|
168
|
+
// The heal path is intentionally restricted to summary loads — an
|
|
169
|
+
// unresolvable ID encountered while applying an op should still surface as
|
|
170
|
+
// an error, since it indicates a real bug rather than a recoverable state.
|
|
171
|
+
return uuidV5(
|
|
172
|
+
`${idDecodingContext.sharedObjectId}|${streamValue}`,
|
|
173
|
+
healingNamespace,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
// See `SharedTreeOptionsBeta.healUnresolvableIdentifiersOnDecode` for details on this error.
|
|
177
|
+
throw new Error(
|
|
178
|
+
"Summary could not be loaded due incorrectly encoded identifier. See SharedTreeOptionsBeta.healUnresolvableIdentifiersOnDecode for mitigation.",
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
return idCompressor.decompress(
|
|
182
|
+
idCompressor.normalizeToSessionSpace(
|
|
183
|
+
streamValue as OpSpaceCompressedId,
|
|
184
|
+
idDecodingContext.originatorId,
|
|
185
|
+
),
|
|
186
|
+
);
|
|
138
187
|
} else {
|
|
139
188
|
// EncodedCounter case:
|
|
140
189
|
unreachableCase(shape, "decoding values as deltas is not yet supported");
|
|
@@ -106,6 +106,33 @@ export interface FieldBatchEncodingContext {
|
|
|
106
106
|
* This will be defined if incremental encoding is supported and enabled.
|
|
107
107
|
*/
|
|
108
108
|
readonly incrementalEncoderDecoder?: IncrementalEncoderDecoder;
|
|
109
|
+
/**
|
|
110
|
+
* `true` when encoding to or decoding from a summary blob. `false` for
|
|
111
|
+
* op-stream encode/decode paths and for utility encoders that are not
|
|
112
|
+
* tied to a persisted document. Healing behavior is gated on this flag.
|
|
113
|
+
*/
|
|
114
|
+
readonly isSummary: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* If `true`, when an op-space compressed ID encountered while decoding
|
|
117
|
+
* cannot be resolved by the local id-compressor (e.g. the attach-summary
|
|
118
|
+
* blob's originator session state was stripped), a deterministic stable
|
|
119
|
+
* UUID derived from `sharedObjectId` is returned instead of throwing.
|
|
120
|
+
* @remarks
|
|
121
|
+
* Off by default. Used only to recover documents whose attach summary was
|
|
122
|
+
* written with non-finalized op-space IDs before the encode-side fix
|
|
123
|
+
* shipped. Only takes effect when `isSummary` is also `true`.
|
|
124
|
+
* See {@link SharedTreeOptionsBeta.healUnresolvableIdentifiersOnDecode}.
|
|
125
|
+
*/
|
|
126
|
+
readonly healUnresolvableIdentifiersOnDecode?: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* The SharedTree's shared-object id, used as input to the deterministic
|
|
129
|
+
* UUID derivation when `healUnresolvableIdentifiersOnDecode` triggers. Required
|
|
130
|
+
* for that path; ignored otherwise.
|
|
131
|
+
* @remarks
|
|
132
|
+
* This allows us to ensure that multiple attaches,
|
|
133
|
+
* in the same or different documents, with the same session offsets, get different UUIDs.
|
|
134
|
+
*/
|
|
135
|
+
readonly sharedObjectId?: string;
|
|
109
136
|
}
|
|
110
137
|
/**
|
|
111
138
|
* @remarks
|
|
@@ -125,6 +152,7 @@ function makeFieldBatchCodecForVersion(
|
|
|
125
152
|
fieldBatch: FieldBatch,
|
|
126
153
|
idCompressor: IIdCompressor,
|
|
127
154
|
incrementalEncoder: IncrementalEncoder | undefined,
|
|
155
|
+
isSummary: boolean,
|
|
128
156
|
) => EncodedFieldBatchV1OrV2,
|
|
129
157
|
encodedFieldBatchType: TSchema,
|
|
130
158
|
): CodecAndSchema<FieldBatch, FieldBatchEncodingContext> {
|
|
@@ -167,6 +195,7 @@ function makeFieldBatchCodecForVersion(
|
|
|
167
195
|
data,
|
|
168
196
|
context.idCompressor,
|
|
169
197
|
incrementalEncoder,
|
|
198
|
+
context.isSummary,
|
|
170
199
|
);
|
|
171
200
|
}
|
|
172
201
|
|
|
@@ -190,6 +219,9 @@ function makeFieldBatchCodecForVersion(
|
|
|
190
219
|
{
|
|
191
220
|
idCompressor: context.idCompressor,
|
|
192
221
|
originatorId: context.originatorId,
|
|
222
|
+
isSummary: context.isSummary,
|
|
223
|
+
healUnresolvableIdentifiersOnDecode: context.healUnresolvableIdentifiersOnDecode,
|
|
224
|
+
sharedObjectId: context.sharedObjectId,
|
|
193
225
|
},
|
|
194
226
|
context.incrementalEncoderDecoder,
|
|
195
227
|
).map((chunk) => chunk.cursor());
|
|
@@ -26,7 +26,8 @@ import {
|
|
|
26
26
|
Shape as ShapeGeneric,
|
|
27
27
|
updateShapesAndIdentifiersEncoding,
|
|
28
28
|
} from "./chunkEncodingGeneric.js";
|
|
29
|
-
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- Referenced by doc comments
|
|
30
|
+
import type { FieldBatchEncodingContext, IncrementalEncoder } from "./codecs.js";
|
|
30
31
|
import type { FieldBatch } from "./fieldBatch.js";
|
|
31
32
|
import {
|
|
32
33
|
type EncodedAnyShape,
|
|
@@ -535,6 +536,10 @@ export class EncoderContext implements NodeEncodeBuilder, FieldEncodeBuilder {
|
|
|
535
536
|
*/
|
|
536
537
|
public readonly incrementalEncoder: IncrementalEncoder | undefined,
|
|
537
538
|
public readonly version: FieldBatchFormatVersion,
|
|
539
|
+
/**
|
|
540
|
+
* See {@link FieldBatchEncodingContext.isSummary}.
|
|
541
|
+
*/
|
|
542
|
+
public readonly isSummary: boolean,
|
|
538
543
|
) {}
|
|
539
544
|
|
|
540
545
|
public nodeEncoderFromSchema(schemaName: TreeNodeSchemaIdentifier): NodeEncoder {
|
|
@@ -77,7 +77,15 @@ export class NodeShapeBasedEncoder
|
|
|
77
77
|
if (isStableId(cursor.value)) {
|
|
78
78
|
const sessionSpaceCompressedId = context.idCompressor.tryRecompress(cursor.value);
|
|
79
79
|
if (sessionSpaceCompressedId !== undefined) {
|
|
80
|
-
|
|
80
|
+
const opSpaceId = context.idCompressor.normalizeToOpSpace(sessionSpaceCompressedId);
|
|
81
|
+
// Summaries can only contain finalized op-space ids unless they also include the originator's session id somewhere.
|
|
82
|
+
// This is not the case for forest summaries at the time of writing, so non-finalized ids are instead written using
|
|
83
|
+
// their long form (by falling through to the original cursor value).
|
|
84
|
+
// A scenario where such ids can appear in the summary is in the attach summary of a tree being attached to an already-attached container.
|
|
85
|
+
// TODO: isFinalId should probably be exported from id-compressor and that could be used to do the narrowing here.
|
|
86
|
+
if (!context.isSummary || opSpaceId >= 0) {
|
|
87
|
+
return opSpaceId;
|
|
88
|
+
}
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
91
|
}
|
|
@@ -54,6 +54,8 @@ export function schemaCompressedEncodeV1(
|
|
|
54
54
|
policy: SchemaPolicy,
|
|
55
55
|
fieldBatch: FieldBatch,
|
|
56
56
|
idCompressor: IIdCompressor,
|
|
57
|
+
_incrementalEncoder: IncrementalEncoder | undefined,
|
|
58
|
+
isSummary: boolean,
|
|
57
59
|
): EncodedFieldBatchV1 {
|
|
58
60
|
const encoded: EncodedFieldBatchV1OrV2 = schemaCompressedEncode(
|
|
59
61
|
schema,
|
|
@@ -62,6 +64,7 @@ export function schemaCompressedEncodeV1(
|
|
|
62
64
|
idCompressor,
|
|
63
65
|
undefined /* incrementalEncoder */,
|
|
64
66
|
brand(FieldBatchFormatVersion.v1),
|
|
67
|
+
isSummary,
|
|
65
68
|
);
|
|
66
69
|
// Since incrementalEncoder was not provided, no V2 features should be used, and this cast should be safe.
|
|
67
70
|
return encoded as EncodedFieldBatchV1;
|
|
@@ -78,6 +81,7 @@ export function schemaCompressedEncodeV2(
|
|
|
78
81
|
fieldBatch: FieldBatch,
|
|
79
82
|
idCompressor: IIdCompressor,
|
|
80
83
|
incrementalEncoder: IncrementalEncoder | undefined,
|
|
84
|
+
isSummary: boolean,
|
|
81
85
|
): EncodedFieldBatchV2 {
|
|
82
86
|
return schemaCompressedEncode(
|
|
83
87
|
schema,
|
|
@@ -86,6 +90,7 @@ export function schemaCompressedEncodeV2(
|
|
|
86
90
|
idCompressor,
|
|
87
91
|
incrementalEncoder,
|
|
88
92
|
brand(FieldBatchFormatVersion.v2),
|
|
93
|
+
isSummary,
|
|
89
94
|
);
|
|
90
95
|
}
|
|
91
96
|
|
|
@@ -106,10 +111,11 @@ function schemaCompressedEncode(
|
|
|
106
111
|
idCompressor: IIdCompressor,
|
|
107
112
|
incrementalEncoder: IncrementalEncoder | undefined,
|
|
108
113
|
version: FieldBatchFormatVersion,
|
|
114
|
+
isSummary: boolean,
|
|
109
115
|
): EncodedFieldBatchV1OrV2 {
|
|
110
116
|
return compressedEncode(
|
|
111
117
|
fieldBatch,
|
|
112
|
-
buildContext(schema, policy, idCompressor, incrementalEncoder, version),
|
|
118
|
+
buildContext(schema, policy, idCompressor, incrementalEncoder, version, isSummary),
|
|
113
119
|
);
|
|
114
120
|
}
|
|
115
121
|
|
|
@@ -119,6 +125,7 @@ export function buildContext(
|
|
|
119
125
|
idCompressor: IIdCompressor,
|
|
120
126
|
incrementalEncoder: IncrementalEncoder | undefined,
|
|
121
127
|
version: FieldBatchFormatVersion,
|
|
128
|
+
isSummary: boolean,
|
|
122
129
|
): EncoderContext {
|
|
123
130
|
const context: EncoderContext = new EncoderContext(
|
|
124
131
|
(fieldBuilder: FieldEncodeBuilder, schemaName: TreeNodeSchemaIdentifier) =>
|
|
@@ -129,6 +136,7 @@ export function buildContext(
|
|
|
129
136
|
idCompressor,
|
|
130
137
|
incrementalEncoder,
|
|
131
138
|
version,
|
|
139
|
+
isSummary,
|
|
132
140
|
);
|
|
133
141
|
return context;
|
|
134
142
|
}
|
|
@@ -3,33 +3,17 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { type Static, type TAnySchema, type TSchema, Type } from "@sinclair/typebox";
|
|
7
|
-
|
|
8
6
|
// Many of the return types in this module are intentionally derived, rather than explicitly specified.
|
|
9
7
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
* Note: TS doesn't easily support extracting a generic function's return type until 4.7:
|
|
13
|
-
* https://github.com/microsoft/TypeScript/pull/47607
|
|
14
|
-
* This type is a workaround and can be removed once we're on a version of typescript which
|
|
15
|
-
* supports expressions more like:
|
|
16
|
-
* `Static<ReturnType<typeof EncodedGenericChange<Schema>>>`
|
|
17
|
-
*/
|
|
18
|
-
class Wrapper<T extends TSchema> {
|
|
19
|
-
public encodedGenericChange(e: T) {
|
|
20
|
-
return EncodedGenericChange<T>(e);
|
|
21
|
-
}
|
|
22
|
-
public encodedGenericChangeset(e: T) {
|
|
23
|
-
return EncodedGenericChangeset<T>(e);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
9
|
+
import { type Static, type TAnySchema, type TSchema, Type } from "@sinclair/typebox";
|
|
26
10
|
|
|
27
11
|
export const EncodedGenericChange = <NodeChangesetSchema extends TSchema>(
|
|
28
12
|
tNodeChangeset: NodeChangesetSchema,
|
|
29
13
|
) => Type.Tuple([Type.Number({ minimum: 0, multipleOf: 1 }), tNodeChangeset]);
|
|
30
14
|
|
|
31
15
|
export type EncodedGenericChange<Schema extends TSchema = TAnySchema> = Static<
|
|
32
|
-
ReturnType<
|
|
16
|
+
ReturnType<typeof EncodedGenericChange<Schema>>
|
|
33
17
|
>;
|
|
34
18
|
|
|
35
19
|
export const EncodedGenericChangeset = <NodeChangesetSchema extends TSchema>(
|
|
@@ -37,7 +21,5 @@ export const EncodedGenericChangeset = <NodeChangesetSchema extends TSchema>(
|
|
|
37
21
|
) => Type.Array(EncodedGenericChange(tNodeChangeset));
|
|
38
22
|
|
|
39
23
|
export type EncodedGenericChangeset<Schema extends TSchema = TAnySchema> = Static<
|
|
40
|
-
ReturnType<
|
|
24
|
+
ReturnType<typeof EncodedGenericChangeset<Schema>>
|
|
41
25
|
>;
|
|
42
|
-
|
|
43
|
-
/* eslint-enable @typescript-eslint/explicit-function-return-type */
|
|
@@ -330,6 +330,7 @@ export function encodeDetachedNodes(
|
|
|
330
330
|
schema: context.schema,
|
|
331
331
|
originatorId: context.originatorId,
|
|
332
332
|
idCompressor: context.idCompressor,
|
|
333
|
+
isSummary: context.isSummary,
|
|
333
334
|
}),
|
|
334
335
|
};
|
|
335
336
|
}
|
|
@@ -353,6 +354,9 @@ export function decodeDetachedNodes(
|
|
|
353
354
|
encodeType: chunkCompressionStrategy,
|
|
354
355
|
originatorId: context.originatorId,
|
|
355
356
|
idCompressor: context.idCompressor,
|
|
357
|
+
isSummary: context.isSummary,
|
|
358
|
+
healUnresolvableIdentifiersOnDecode: context.healUnresolvableIdentifiersOnDecode,
|
|
359
|
+
sharedObjectId: context.sharedObjectId,
|
|
356
360
|
});
|
|
357
361
|
const getChunk = (index: number): TreeChunk => {
|
|
358
362
|
assert(index < chunks.length, 0x898 /* out of bounds index for build chunk */);
|
package/src/packageVersion.ts
CHANGED
|
@@ -238,6 +238,8 @@ export function createIndependentTreeAlpha<const TSchema extends ImplicitFieldSc
|
|
|
238
238
|
idCompressor,
|
|
239
239
|
originatorId: idCompressor.localSessionId, // Is this right? If so, why is is needed?
|
|
240
240
|
schema: { schema: newSchema, policy: defaultSchemaPolicy },
|
|
241
|
+
// Not a summary blob — this is a synthetic decode of inline content.
|
|
242
|
+
isSummary: false,
|
|
241
243
|
};
|
|
242
244
|
const fieldCursors = fieldBatchCodec.decode(
|
|
243
245
|
options.content.tree as JsonCompatibleReadOnly,
|
|
@@ -246,6 +246,11 @@ export class SharedTreeKernel
|
|
|
246
246
|
encodeType: options.treeEncodeType,
|
|
247
247
|
originatorId: idCompressor.localSessionId,
|
|
248
248
|
idCompressor,
|
|
249
|
+
// ForestSummarizer is the only consumer of this context, and it
|
|
250
|
+
// only invokes the codec in summary encode / load paths.
|
|
251
|
+
isSummary: true,
|
|
252
|
+
healUnresolvableIdentifiersOnDecode: options.healUnresolvableIdentifiersOnDecode,
|
|
253
|
+
sharedObjectId: sharedObject.id,
|
|
249
254
|
};
|
|
250
255
|
const forestSummarizer = new ForestSummarizer(
|
|
251
256
|
forest,
|
|
@@ -570,7 +575,41 @@ export function getCodecTreeForSharedTreeFormat(
|
|
|
570
575
|
* Configuration options for SharedTree.
|
|
571
576
|
* @beta @input
|
|
572
577
|
*/
|
|
573
|
-
export
|
|
578
|
+
export interface SharedTreeOptionsBeta extends ForestOptions, Partial<CodecWriteOptionsBeta> {
|
|
579
|
+
/**
|
|
580
|
+
* When `true`, when an improperly encoded identifier is encountered in a summary,
|
|
581
|
+
* a new identifier will be generated instead of throwing an error.
|
|
582
|
+
*
|
|
583
|
+
* @defaultValue `false`
|
|
584
|
+
*
|
|
585
|
+
* @remarks
|
|
586
|
+
* The intended use is recovering documents whose attach summary was persisted
|
|
587
|
+
* with unresolvable node identifiers (a SharedTree-attaches-to-already-attached-container
|
|
588
|
+
* scenario). Without this flag enabled, a client opening such a document will throw at summary load time.
|
|
589
|
+
* With this flag enabled, unresolvable identifiers are replaced at decode time with stable UUIDs
|
|
590
|
+
* derived deterministically from the data store id and the unresolvable op-space integer,
|
|
591
|
+
* so every reader of the same blob (other than the originator) agrees on the resulting in-memory id.
|
|
592
|
+
* Healed identifiers are written back out at the next summary in their stable UUID form,
|
|
593
|
+
* so the inconsistency does not need to be re-healed on every load.
|
|
594
|
+
*
|
|
595
|
+
* Off by default because enabling it for documents that are not actually corrupt
|
|
596
|
+
* would mask genuine bugs that otherwise surface as decode failures.
|
|
597
|
+
*
|
|
598
|
+
* This mitigation is also not perfect as the client that originated the non-finalized
|
|
599
|
+
* will not apply the same "healing" and will continue to use the original identifier.
|
|
600
|
+
* The difference in identifiers between the originating client and subsequent clients that load
|
|
601
|
+
* the document is not ideal but generally benign to Fluid. However, it may have application-level
|
|
602
|
+
* consequences (e.g. if the application stores the identifiers elsewhere, either in other parts of
|
|
603
|
+
* Fluid data or externally). Applications should consider whether this risk is acceptable before
|
|
604
|
+
* enabling this option.
|
|
605
|
+
*
|
|
606
|
+
* @privateRemarks
|
|
607
|
+
* "Unresolvable" in the public-facing remarks corresponds to non-finalized short IDs persisted without
|
|
608
|
+
* any corresponding context for their originating session. See id-compressor internal documentation
|
|
609
|
+
* for more details.
|
|
610
|
+
*/
|
|
611
|
+
readonly healUnresolvableIdentifiersOnDecode?: boolean;
|
|
612
|
+
}
|
|
574
613
|
|
|
575
614
|
/**
|
|
576
615
|
* Configuration options for SharedTree with alpha features.
|
|
@@ -724,6 +763,7 @@ export const defaultSharedTreeOptions: Required<SharedTreeOptionsInternal> = {
|
|
|
724
763
|
disposeForksAfterTransaction: true,
|
|
725
764
|
shouldEncodeIncrementally: defaultIncrementalEncodingPolicy,
|
|
726
765
|
enableSharedBranches: false,
|
|
766
|
+
healUnresolvableIdentifiersOnDecode: false,
|
|
727
767
|
writeVersionOverrides: new Map(),
|
|
728
768
|
allowPossiblyIncompatibleWriteVersionOverrides: false,
|
|
729
769
|
};
|
|
@@ -954,6 +954,8 @@ export const TreeAlpha: TreeAlpha = {
|
|
|
954
954
|
idCompressor,
|
|
955
955
|
originatorId: idCompressor.localSessionId, // TODO: Why is this needed?
|
|
956
956
|
schema: { schema: storedSchema, policy: defaultSchemaPolicy },
|
|
957
|
+
// Not a summary blob — this is `TreeAlpha`'s ad-hoc encoder.
|
|
958
|
+
isSummary: false,
|
|
957
959
|
};
|
|
958
960
|
const result = codec.encode(batch, context);
|
|
959
961
|
// TODO: codecs should better track which ones can contain handles, and which cannot. When done properly, casts like this can be removed.
|
|
@@ -750,6 +750,7 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
750
750
|
idCompressor: this.idCompressor,
|
|
751
751
|
originatorId: this.idCompressor.localSessionId,
|
|
752
752
|
revision,
|
|
753
|
+
isSummary: false,
|
|
753
754
|
};
|
|
754
755
|
const encodedChange = this.changeFamily.codecs.resolve(4).encode(change, context);
|
|
755
756
|
|
|
@@ -820,6 +821,7 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
820
821
|
idCompressor: this.idCompressor,
|
|
821
822
|
originatorId: this.idCompressor.localSessionId,
|
|
822
823
|
revision,
|
|
824
|
+
isSummary: false,
|
|
823
825
|
};
|
|
824
826
|
const decodedChange = this.changeFamily.codecs.resolve(4).decode(change, context);
|
|
825
827
|
// Apply the change to the branch, but _not_ the `activeBranch` - we do not support squashing serialized commits in a transaction.
|
|
@@ -36,6 +36,9 @@ import { EditManagerFormatVersion } from "./editManagerFormatCommons.js";
|
|
|
36
36
|
export interface EditManagerEncodingContext {
|
|
37
37
|
idCompressor: IIdCompressor;
|
|
38
38
|
readonly schema?: SchemaAndPolicy;
|
|
39
|
+
readonly isSummary: boolean;
|
|
40
|
+
readonly healUnresolvableIdentifiersOnDecode?: boolean;
|
|
41
|
+
readonly sharedObjectId?: string;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/**
|
|
@@ -28,6 +28,20 @@ import type {
|
|
|
28
28
|
export interface EditManagerEncodingContext {
|
|
29
29
|
idCompressor: IIdCompressor;
|
|
30
30
|
readonly schema?: SchemaAndPolicy;
|
|
31
|
+
/**
|
|
32
|
+
* See {@link ChangeEncodingContext.isSummary}. EditManager codec callers
|
|
33
|
+
* always set this to `true` (the codec is only invoked for summaries),
|
|
34
|
+
* but it is carried explicitly so downstream codecs can read it.
|
|
35
|
+
*/
|
|
36
|
+
readonly isSummary: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* See {@link ChangeEncodingContext.healUnresolvableIdentifiersOnDecode}.
|
|
39
|
+
*/
|
|
40
|
+
readonly healUnresolvableIdentifiersOnDecode?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* See {@link ChangeEncodingContext.sharedObjectId}.
|
|
43
|
+
*/
|
|
44
|
+
readonly sharedObjectId?: string;
|
|
31
45
|
}
|
|
32
46
|
|
|
33
47
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
@@ -53,6 +67,7 @@ function encodeCommit<TChangeset, T extends Commit<TChangeset>>(
|
|
|
53
67
|
originatorId: commit.sessionId,
|
|
54
68
|
idCompressor: context.idCompressor,
|
|
55
69
|
revision: undefined,
|
|
70
|
+
isSummary: context.isSummary,
|
|
56
71
|
}),
|
|
57
72
|
change: changeCodec.encode(commit.change, { ...context, revision: commit.revision }),
|
|
58
73
|
};
|
|
@@ -79,6 +94,7 @@ function decodeCommit<TChangeset, T extends EncodedCommit<JsonCompatibleReadOnly
|
|
|
79
94
|
originatorId: commit.sessionId,
|
|
80
95
|
idCompressor: context.idCompressor,
|
|
81
96
|
revision: undefined,
|
|
97
|
+
isSummary: context.isSummary,
|
|
82
98
|
});
|
|
83
99
|
|
|
84
100
|
return {
|
|
@@ -112,6 +128,7 @@ export function encodeSharedBranch<TChangeset>(
|
|
|
112
128
|
idCompressor: context.idCompressor,
|
|
113
129
|
schema: context.schema,
|
|
114
130
|
revision: undefined,
|
|
131
|
+
isSummary: context.isSummary,
|
|
115
132
|
}),
|
|
116
133
|
),
|
|
117
134
|
peers: Array.from(data.peerLocalBranches.entries(), ([sessionId, branch]) => [
|
|
@@ -121,6 +138,7 @@ export function encodeSharedBranch<TChangeset>(
|
|
|
121
138
|
originatorId: sessionId,
|
|
122
139
|
idCompressor: context.idCompressor,
|
|
123
140
|
revision: undefined,
|
|
141
|
+
isSummary: context.isSummary,
|
|
124
142
|
}),
|
|
125
143
|
commits: branch.commits.map((commit) =>
|
|
126
144
|
encodeCommit(changeCodec, revisionTagCodec, commit, {
|
|
@@ -128,6 +146,7 @@ export function encodeSharedBranch<TChangeset>(
|
|
|
128
146
|
idCompressor: context.idCompressor,
|
|
129
147
|
schema: context.schema,
|
|
130
148
|
revision: undefined,
|
|
149
|
+
isSummary: context.isSummary,
|
|
131
150
|
}),
|
|
132
151
|
),
|
|
133
152
|
},
|
|
@@ -154,6 +173,7 @@ export function encodeSharedBranch<TChangeset>(
|
|
|
154
173
|
originatorId,
|
|
155
174
|
idCompressor: context.idCompressor,
|
|
156
175
|
revision: undefined,
|
|
176
|
+
isSummary: context.isSummary,
|
|
157
177
|
});
|
|
158
178
|
}
|
|
159
179
|
return json;
|
|
@@ -186,6 +206,9 @@ export function decodeSharedBranch<TChangeset>(
|
|
|
186
206
|
originatorId: commit.sessionId,
|
|
187
207
|
idCompressor: context.idCompressor,
|
|
188
208
|
revision: undefined,
|
|
209
|
+
isSummary: context.isSummary,
|
|
210
|
+
healUnresolvableIdentifiersOnDecode: context.healUnresolvableIdentifiersOnDecode,
|
|
211
|
+
sharedObjectId: context.sharedObjectId,
|
|
189
212
|
}),
|
|
190
213
|
),
|
|
191
214
|
peerLocalBranches: new Map(
|
|
@@ -196,6 +219,7 @@ export function decodeSharedBranch<TChangeset>(
|
|
|
196
219
|
originatorId: sessionId,
|
|
197
220
|
idCompressor: context.idCompressor,
|
|
198
221
|
revision: undefined,
|
|
222
|
+
isSummary: context.isSummary,
|
|
199
223
|
}),
|
|
200
224
|
commits: branch.commits.map((commit) =>
|
|
201
225
|
// TODO: sort out EncodedCommit vs Commit, and make this type check without `as`.
|
|
@@ -207,6 +231,10 @@ export function decodeSharedBranch<TChangeset>(
|
|
|
207
231
|
originatorId: commit.sessionId,
|
|
208
232
|
idCompressor: context.idCompressor,
|
|
209
233
|
revision: undefined,
|
|
234
|
+
isSummary: context.isSummary,
|
|
235
|
+
healUnresolvableIdentifiersOnDecode:
|
|
236
|
+
context.healUnresolvableIdentifiersOnDecode,
|
|
237
|
+
sharedObjectId: context.sharedObjectId,
|
|
210
238
|
},
|
|
211
239
|
),
|
|
212
240
|
),
|
|
@@ -239,6 +267,7 @@ export function decodeSharedBranch<TChangeset>(
|
|
|
239
267
|
originatorId,
|
|
240
268
|
idCompressor: context.idCompressor,
|
|
241
269
|
revision: undefined,
|
|
270
|
+
isSummary: context.isSummary,
|
|
242
271
|
});
|
|
243
272
|
}
|
|
244
273
|
return data;
|
|
@@ -25,6 +25,9 @@ import { EncodedEditManager } from "./editManagerFormatV1toV4.js";
|
|
|
25
25
|
export interface EditManagerEncodingContext {
|
|
26
26
|
idCompressor: IIdCompressor;
|
|
27
27
|
readonly schema?: SchemaAndPolicy;
|
|
28
|
+
readonly isSummary: boolean;
|
|
29
|
+
readonly healUnresolvableIdentifiersOnDecode?: boolean;
|
|
30
|
+
readonly sharedObjectId?: string;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
/**
|
|
@@ -29,6 +29,9 @@ import { EncodedEditManager } from "./editManagerFormatVSharedBranches.js";
|
|
|
29
29
|
export interface EditManagerEncodingContext {
|
|
30
30
|
idCompressor: IIdCompressor;
|
|
31
31
|
readonly schema?: SchemaAndPolicy;
|
|
32
|
+
readonly isSummary: boolean;
|
|
33
|
+
readonly healUnresolvableIdentifiersOnDecode?: boolean;
|
|
34
|
+
readonly sharedObjectId?: string;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
export function makeSharedBranchesCodecWithVersion<TChangeset>(
|