@fluidframework/tree 2.114.0 → 2.115.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 +191 -0
- package/api-report/tree.alpha.api.md +108 -39
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/rebase/index.d.ts +1 -1
- package/dist/core/rebase/index.d.ts.map +1 -1
- package/dist/core/rebase/index.js +2 -1
- package/dist/core/rebase/index.js.map +1 -1
- package/dist/core/rebase/types.d.ts +110 -0
- package/dist/core/rebase/types.d.ts.map +1 -1
- package/dist/core/rebase/types.js +47 -1
- package/dist/core/rebase/types.js.map +1 -1
- package/dist/entrypoints/alpha.d.ts +1 -1
- package/dist/entrypoints/alpha.d.ts.map +1 -1
- package/dist/entrypoints/alpha.js +6 -4
- package/dist/entrypoints/alpha.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +9 -6
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.js +16 -13
- package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -5
- package/dist/index.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/sharedTree.d.ts +5 -0
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +1 -1
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts +5 -0
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +58 -12
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts +1 -0
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js.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/index.d.ts +1 -1
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +2 -3
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +3 -3
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaStatics.d.ts +6 -7
- package/dist/simple-tree/api/schemaStatics.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaStatics.js.map +1 -1
- package/dist/simple-tree/api/treeNodeApi.d.ts +20 -24
- package/dist/simple-tree/api/treeNodeApi.d.ts.map +1 -1
- package/dist/simple-tree/api/treeNodeApi.js +48 -49
- package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
- package/dist/simple-tree/core/treeNode.d.ts +5 -6
- package/dist/simple-tree/core/treeNode.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNode.js +2 -4
- package/dist/simple-tree/core/treeNode.js.map +1 -1
- package/dist/simple-tree/core/withType.d.ts +20 -7
- package/dist/simple-tree/core/withType.d.ts.map +1 -1
- package/dist/simple-tree/core/withType.js +4 -7
- package/dist/simple-tree/core/withType.js.map +1 -1
- package/dist/simple-tree/index.d.ts +2 -2
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +3 -4
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/leafNodeSchema.d.ts +6 -1
- package/dist/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/dist/simple-tree/leafNodeSchema.js +0 -1
- package/dist/simple-tree/leafNodeSchema.js.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNode.d.ts +32 -3
- package/dist/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNode.js +91 -10
- package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/map/mapNode.d.ts +77 -0
- package/dist/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/map/mapNode.js +17 -1
- package/dist/simple-tree/node-kinds/map/mapNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/object/objectNode.js +2 -2
- package/dist/simple-tree/node-kinds/object/objectNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNode.js +2 -2
- package/dist/simple-tree/node-kinds/record/recordNode.js.map +1 -1
- package/dist/text/codePointUtils.d.ts +2 -2
- package/dist/text/codePointUtils.js +2 -2
- package/dist/text/codePointUtils.js.map +1 -1
- package/dist/text/index.d.ts +3 -3
- package/dist/text/index.d.ts.map +1 -1
- package/dist/text/index.js +4 -4
- package/dist/text/index.js.map +1 -1
- package/dist/text/textDomain.d.ts +18 -18
- package/dist/text/textDomain.d.ts.map +1 -1
- package/dist/text/textDomain.js +8 -8
- package/dist/text/textDomain.js.map +1 -1
- package/dist/text/textDomainFormatted.d.ts +46 -42
- package/dist/text/textDomainFormatted.d.ts.map +1 -1
- package/dist/text/textDomainFormatted.js +32 -28
- package/dist/text/textDomainFormatted.js.map +1 -1
- package/dist/text/textDomainFormattedDefault.d.ts +18 -18
- package/dist/text/textDomainFormattedDefault.d.ts.map +1 -1
- package/dist/text/textDomainFormattedDefault.js +14 -17
- package/dist/text/textDomainFormattedDefault.js.map +1 -1
- package/dist/util/compressedIds.d.ts +22 -2
- package/dist/util/compressedIds.d.ts.map +1 -1
- package/dist/util/compressedIds.js +22 -1
- package/dist/util/compressedIds.js.map +1 -1
- package/lib/core/index.d.ts +1 -1
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +1 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/rebase/index.d.ts +1 -1
- package/lib/core/rebase/index.d.ts.map +1 -1
- package/lib/core/rebase/index.js +1 -1
- package/lib/core/rebase/index.js.map +1 -1
- package/lib/core/rebase/types.d.ts +110 -0
- package/lib/core/rebase/types.d.ts.map +1 -1
- package/lib/core/rebase/types.js +46 -0
- package/lib/core/rebase/types.js.map +1 -1
- package/lib/entrypoints/alpha.d.ts +1 -1
- package/lib/entrypoints/alpha.d.ts.map +1 -1
- package/lib/entrypoints/alpha.js +1 -1
- package/lib/entrypoints/alpha.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +9 -6
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.js +16 -13
- package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.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/sharedTree.d.ts +5 -0
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +1 -1
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts +5 -0
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +60 -14
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts +1 -0
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js.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/index.d.ts +1 -1
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js +1 -1
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts +3 -3
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaStatics.d.ts +6 -7
- package/lib/simple-tree/api/schemaStatics.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaStatics.js.map +1 -1
- package/lib/simple-tree/api/treeNodeApi.d.ts +20 -24
- package/lib/simple-tree/api/treeNodeApi.d.ts.map +1 -1
- package/lib/simple-tree/api/treeNodeApi.js +46 -46
- package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
- package/lib/simple-tree/core/treeNode.d.ts +5 -6
- package/lib/simple-tree/core/treeNode.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNode.js +2 -4
- package/lib/simple-tree/core/treeNode.js.map +1 -1
- package/lib/simple-tree/core/withType.d.ts +20 -7
- package/lib/simple-tree/core/withType.d.ts.map +1 -1
- package/lib/simple-tree/core/withType.js +4 -7
- package/lib/simple-tree/core/withType.js.map +1 -1
- package/lib/simple-tree/index.d.ts +2 -2
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +1 -1
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/simple-tree/leafNodeSchema.d.ts +6 -1
- package/lib/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/lib/simple-tree/leafNodeSchema.js +0 -1
- package/lib/simple-tree/leafNodeSchema.js.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNode.d.ts +32 -3
- package/lib/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNode.js +93 -12
- package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/map/mapNode.d.ts +77 -0
- package/lib/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/map/mapNode.js +18 -2
- package/lib/simple-tree/node-kinds/map/mapNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/object/objectNode.js +3 -3
- package/lib/simple-tree/node-kinds/object/objectNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNode.js +3 -3
- package/lib/simple-tree/node-kinds/record/recordNode.js.map +1 -1
- package/lib/text/codePointUtils.d.ts +2 -2
- package/lib/text/codePointUtils.js +2 -2
- package/lib/text/codePointUtils.js.map +1 -1
- package/lib/text/index.d.ts +3 -3
- package/lib/text/index.d.ts.map +1 -1
- package/lib/text/index.js +3 -3
- package/lib/text/index.js.map +1 -1
- package/lib/text/textDomain.d.ts +18 -18
- package/lib/text/textDomain.d.ts.map +1 -1
- package/lib/text/textDomain.js +7 -7
- package/lib/text/textDomain.js.map +1 -1
- package/lib/text/textDomainFormatted.d.ts +46 -42
- package/lib/text/textDomainFormatted.d.ts.map +1 -1
- package/lib/text/textDomainFormatted.js +31 -27
- package/lib/text/textDomainFormatted.js.map +1 -1
- package/lib/text/textDomainFormattedDefault.d.ts +18 -18
- package/lib/text/textDomainFormattedDefault.d.ts.map +1 -1
- package/lib/text/textDomainFormattedDefault.js +14 -17
- package/lib/text/textDomainFormattedDefault.js.map +1 -1
- package/lib/util/compressedIds.d.ts +22 -2
- package/lib/util/compressedIds.d.ts.map +1 -1
- package/lib/util/compressedIds.js +22 -1
- package/lib/util/compressedIds.js.map +1 -1
- package/package.json +29 -22
- package/src/core/index.ts +2 -0
- package/src/core/rebase/index.ts +2 -0
- package/src/core/rebase/types.ts +113 -0
- package/src/entrypoints/alpha.ts +10 -6
- package/src/feature-libraries/chunked-forest/codec/codecs.ts +17 -14
- package/src/index.ts +7 -4
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/sharedTree.ts +6 -1
- package/src/shared-tree/treeCheckout.ts +81 -14
- package/src/shared-tree-core/branch.ts +1 -0
- package/src/shared-tree-core/sharedTreeCore.ts +1 -1
- package/src/simple-tree/api/index.ts +0 -1
- package/src/simple-tree/api/schemaStatics.ts +2 -2
- package/src/simple-tree/api/treeNodeApi.ts +64 -48
- package/src/simple-tree/core/treeNode.ts +13 -10
- package/src/simple-tree/core/withType.ts +20 -7
- package/src/simple-tree/index.ts +1 -2
- package/src/simple-tree/leafNodeSchema.ts +6 -1
- package/src/simple-tree/node-kinds/array/arrayNode.ts +109 -14
- package/src/simple-tree/node-kinds/map/mapNode.ts +113 -3
- package/src/simple-tree/node-kinds/object/objectNode.ts +3 -3
- package/src/simple-tree/node-kinds/record/recordNode.ts +3 -3
- package/src/text/README.md +1 -1
- package/src/text/codePointUtils.ts +2 -2
- package/src/text/index.ts +3 -3
- package/src/text/textDomain.ts +21 -21
- package/src/text/textDomainFormatted.ts +56 -52
- package/src/text/textDomainFormattedDefault.ts +14 -23
- package/src/util/compressedIds.ts +36 -3
package/src/index.ts
CHANGED
|
@@ -12,6 +12,8 @@ export {
|
|
|
12
12
|
CommitKind,
|
|
13
13
|
RevertibleStatus,
|
|
14
14
|
type CommitMetadata,
|
|
15
|
+
CommitOutcome,
|
|
16
|
+
type LocalCommitEvents,
|
|
15
17
|
type LocalChangeMetadata,
|
|
16
18
|
type RemoteChangeMetadata,
|
|
17
19
|
type ChangeMetadata,
|
|
@@ -300,6 +302,7 @@ export {
|
|
|
300
302
|
type HandleConverter,
|
|
301
303
|
allowUnused,
|
|
302
304
|
type LeafSchema,
|
|
305
|
+
type StringSchema,
|
|
303
306
|
type ArrayNodeCustomizableSchema,
|
|
304
307
|
type ArrayNodeCustomizableSchemaAlpha,
|
|
305
308
|
type ArrayNodePojoEmulationSchema,
|
|
@@ -404,7 +407,7 @@ import * as InternalTypes from "./internalTypes.js";
|
|
|
404
407
|
export { InternalTypes };
|
|
405
408
|
|
|
406
409
|
// Internal/System types:
|
|
407
|
-
// These would be put in `internalTypes` except doing so
|
|
410
|
+
// These would be put in `internalTypes` except doing so tends to cause errors like:
|
|
408
411
|
// The inferred type of 'NodeMap' cannot be named without a reference to '../../node_modules/@fluidframework/tree/lib/internalTypes.js'. This is likely not portable. A type annotation is necessary.
|
|
409
412
|
export type { MapNodeInsertableData } from "./simple-tree/index.js";
|
|
410
413
|
|
|
@@ -414,9 +417,9 @@ export { TableSchema, type System_TableSchema } from "./tableSchema.js";
|
|
|
414
417
|
export { asAlpha, asBeta } from "./api.js";
|
|
415
418
|
|
|
416
419
|
export {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
+
PlainText,
|
|
421
|
+
FormattedText,
|
|
422
|
+
FormattedTextDefault,
|
|
420
423
|
codePointCount,
|
|
421
424
|
utf16LengthForCodePoints,
|
|
422
425
|
} from "./text/index.js";
|
package/src/packageVersion.ts
CHANGED
|
@@ -252,7 +252,7 @@ export class SharedTreeKernel
|
|
|
252
252
|
idCompressor,
|
|
253
253
|
healing:
|
|
254
254
|
options.healUnresolvableIdentifiersOnDecode === true
|
|
255
|
-
? { sharedObjectId: sharedObject.id }
|
|
255
|
+
? { sharedObjectId: sharedObject.id, logger }
|
|
256
256
|
: undefined,
|
|
257
257
|
});
|
|
258
258
|
const forestSummarizer = new ForestSummarizer(
|
|
@@ -602,6 +602,11 @@ export interface SharedTreeOptionsBeta extends ForestOptions, Partial<CodecWrite
|
|
|
602
602
|
* Healed identifiers are written back out at the next summary in their stable UUID form,
|
|
603
603
|
* so the inconsistency does not need to be re-healed on every load.
|
|
604
604
|
*
|
|
605
|
+
* When this flag is enabled, each time an unresolvable identifier is healed a
|
|
606
|
+
* `HealUnresolvableIdentifierOnDecode` telemetry event is emitted (at
|
|
607
|
+
* {@link @fluidframework/core-interfaces#LogLevelConst.info | LogLevel.info}) through the shared
|
|
608
|
+
* object's logger, allowing applications to detect which documents actually required healing.
|
|
609
|
+
*
|
|
605
610
|
* Off by default because enabling it for documents that are not actually corrupt
|
|
606
611
|
* would mask genuine bugs that otherwise surface as decode failures.
|
|
607
612
|
*
|
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { createEmitter } from "@fluid-internal/client-utils";
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
IEmitter,
|
|
9
|
+
IFluidHandle,
|
|
10
|
+
Listenable,
|
|
11
|
+
} from "@fluidframework/core-interfaces/internal";
|
|
8
12
|
import { assert, unreachableCase, fail } from "@fluidframework/core-utils/internal";
|
|
9
13
|
import type { IIdCompressor } from "@fluidframework/id-compressor";
|
|
10
14
|
import { type TelemetryLoggerExt, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
@@ -21,6 +25,7 @@ import {
|
|
|
21
25
|
type AnchorSetRootEvents,
|
|
22
26
|
type ChangeFamily,
|
|
23
27
|
CommitKind,
|
|
28
|
+
CommitOutcome,
|
|
24
29
|
type DeltaVisitor,
|
|
25
30
|
type DetachedFieldIndex,
|
|
26
31
|
type IEditableForest,
|
|
@@ -57,6 +62,7 @@ import {
|
|
|
57
62
|
deltaFieldMapHasVisibleChanges,
|
|
58
63
|
findCommonAncestor,
|
|
59
64
|
rebaseBranch,
|
|
65
|
+
type LocalCommitEvents,
|
|
60
66
|
} from "../core/index.js";
|
|
61
67
|
import {
|
|
62
68
|
type FieldBatchCodec,
|
|
@@ -115,7 +121,12 @@ import {
|
|
|
115
121
|
import { SchematizingSimpleTreeView } from "./schematizingTreeView.js";
|
|
116
122
|
import { SharedTreeChangeEnricher } from "./sharedTreeChangeEnricher.js";
|
|
117
123
|
import type { SharedTreeChangeProcessingContext } from "./sharedTreeChangeFamily.js";
|
|
118
|
-
import {
|
|
124
|
+
import {
|
|
125
|
+
ConstraintStatus,
|
|
126
|
+
SharedTreeChangeFamily,
|
|
127
|
+
getConstraintStatus,
|
|
128
|
+
hasSchemaChange,
|
|
129
|
+
} from "./sharedTreeChangeFamily.js";
|
|
119
130
|
import type { SharedTreeChange } from "./sharedTreeChangeTypes.js";
|
|
120
131
|
import type { ISharedTreeEditor, SharedTreeEditBuilder } from "./sharedTreeEditBuilder.js";
|
|
121
132
|
import { extractTransactionChangeProcessor } from "./transactionPostProcessor.js";
|
|
@@ -500,6 +511,14 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
500
511
|
|
|
501
512
|
private readonly views = new Set<TreeView<ImplicitFieldSchema>>();
|
|
502
513
|
|
|
514
|
+
/**
|
|
515
|
+
* Event emitters for local commits.
|
|
516
|
+
*/
|
|
517
|
+
private readonly localCommitEventEmitters = new Map<
|
|
518
|
+
RevisionTag,
|
|
519
|
+
IEmitter<LocalCommitEvents>
|
|
520
|
+
>();
|
|
521
|
+
|
|
503
522
|
/**
|
|
504
523
|
* Revertibles maintained for automatic disposal
|
|
505
524
|
*/
|
|
@@ -668,12 +687,14 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
668
687
|
|
|
669
688
|
private registerForBranchEvents(): void {
|
|
670
689
|
this.#transaction.branch.events.on("afterChange", this.onAfterBranchChange);
|
|
690
|
+
this.#transaction.branch.events.on("commitSequenced", this.onCommitSequenced);
|
|
671
691
|
this.#transaction.activeBranchEvents.on("afterChange", this.onAfterChange);
|
|
672
692
|
this.#transaction.activeBranchEvents.on("ancestryTrimmed", this.onAncestryTrimmed);
|
|
673
693
|
}
|
|
674
694
|
|
|
675
695
|
private unregisterFromBranchEvents(): void {
|
|
676
696
|
this.#transaction.branch.events.off("afterChange", this.onAfterBranchChange);
|
|
697
|
+
this.#transaction.branch.events.off("commitSequenced", this.onCommitSequenced);
|
|
677
698
|
this.#transaction.activeBranchEvents.off("afterChange", this.onAfterChange);
|
|
678
699
|
this.#transaction.activeBranchEvents.off("ancestryTrimmed", this.onAncestryTrimmed);
|
|
679
700
|
}
|
|
@@ -739,6 +760,39 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
739
760
|
}
|
|
740
761
|
}
|
|
741
762
|
|
|
763
|
+
private readonly onCommitSequenced = (commit: GraphCommit<SharedTreeChange>): void => {
|
|
764
|
+
const emitter = this.localCommitEventEmitters.get(commit.revision);
|
|
765
|
+
if (emitter === undefined) {
|
|
766
|
+
// If the commit predates the creation of this checkout, there will be no emitter associated with the commit.
|
|
767
|
+
// In that case, we don't need to emit any events.
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
const constraintStatus = getConstraintStatus(commit.change);
|
|
771
|
+
let outcome: CommitOutcome;
|
|
772
|
+
switch (constraintStatus) {
|
|
773
|
+
case ConstraintStatus.Satisfied: {
|
|
774
|
+
outcome = CommitOutcome.FullyApplied;
|
|
775
|
+
break;
|
|
776
|
+
}
|
|
777
|
+
case ConstraintStatus.ImplicitViolation: {
|
|
778
|
+
outcome = CommitOutcome.FullyDropped;
|
|
779
|
+
break;
|
|
780
|
+
}
|
|
781
|
+
case ConstraintStatus.ExplicitViolation: {
|
|
782
|
+
outcome = CommitOutcome.NewContentOnly;
|
|
783
|
+
break;
|
|
784
|
+
}
|
|
785
|
+
default: {
|
|
786
|
+
unreachableCase(constraintStatus);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
this.emitChangedLocked(() => {
|
|
790
|
+
emitter.emit("settled", outcome);
|
|
791
|
+
}, "a commit settled event callback");
|
|
792
|
+
// No more events will be emitted for this commit, so we can remove the emitter from the map.
|
|
793
|
+
this.localCommitEventEmitters.delete(commit.revision);
|
|
794
|
+
};
|
|
795
|
+
|
|
742
796
|
private readonly onAfterBranchChange = (
|
|
743
797
|
event: SharedTreeBranchChange<SharedTreeChange>,
|
|
744
798
|
): void => {
|
|
@@ -787,6 +841,8 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
787
841
|
|
|
788
842
|
let withinEventContext = true;
|
|
789
843
|
|
|
844
|
+
const events = createEmitter<LocalCommitEvents>();
|
|
845
|
+
this.localCommitEventEmitters.set(commit.revision, events);
|
|
790
846
|
const metadata: ChangeMetadata = {
|
|
791
847
|
kind,
|
|
792
848
|
isLocal: true,
|
|
@@ -805,6 +861,7 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
805
861
|
getRevertible: (onDisposed) => getRevertible?.(onDisposed),
|
|
806
862
|
label: this.labelTreeNode?.label,
|
|
807
863
|
labels: buildLabelsSet(this.labelTreeNode),
|
|
864
|
+
events,
|
|
808
865
|
};
|
|
809
866
|
|
|
810
867
|
this.emitChangedLocked(() => {
|
|
@@ -838,8 +895,11 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
838
895
|
* Shared by both the local and remote `changed` emission paths in {@link TreeCheckout.onAfterBranchChange}.
|
|
839
896
|
* The `try`/`finally` ensures the lock is released even if a listener throws.
|
|
840
897
|
*/
|
|
841
|
-
private emitChangedLocked(
|
|
842
|
-
|
|
898
|
+
private emitChangedLocked(
|
|
899
|
+
emit: () => void,
|
|
900
|
+
reason: string = "a change event callback",
|
|
901
|
+
): void {
|
|
902
|
+
this.editLock.lock(reason);
|
|
843
903
|
try {
|
|
844
904
|
emit();
|
|
845
905
|
} finally {
|
|
@@ -855,7 +915,7 @@ export class TreeCheckout implements ITreeCheckout {
|
|
|
855
915
|
}
|
|
856
916
|
|
|
857
917
|
private readonly onAfterChange = (event: SharedTreeBranchChange<SharedTreeChange>): void => {
|
|
858
|
-
this.editLock.lock();
|
|
918
|
+
this.editLock.lock("a change event callback");
|
|
859
919
|
this.#events.emit("beforeBatch", event);
|
|
860
920
|
if (event.change !== undefined) {
|
|
861
921
|
const revision =
|
|
@@ -1703,7 +1763,13 @@ class EditLock {
|
|
|
1703
1763
|
* @remarks Edits will throw an error if the lock is currently locked.
|
|
1704
1764
|
*/
|
|
1705
1765
|
public readonly editor: ISharedTreeEditor;
|
|
1706
|
-
|
|
1766
|
+
/**
|
|
1767
|
+
* The current status of the lock.
|
|
1768
|
+
* The `reason` string will be included in the error message if an attempt is made to edit the tree while the lock is held.
|
|
1769
|
+
*/
|
|
1770
|
+
private status:
|
|
1771
|
+
| { readonly isLocked: false }
|
|
1772
|
+
| { readonly isLocked: true; readonly reason: string } = { isLocked: false };
|
|
1707
1773
|
|
|
1708
1774
|
/**
|
|
1709
1775
|
* @param editor - an editor which will be used to create a new editor that is monitored to determine if any changes are happening to the tree.
|
|
@@ -1767,14 +1833,15 @@ class EditLock {
|
|
|
1767
1833
|
|
|
1768
1834
|
/**
|
|
1769
1835
|
* Prevent further changes from being made to {@link EditLock.editor} until {@link EditLock.unlock} is called.
|
|
1836
|
+
* @param reason - A string describing why the lock is being acquired. This will be included in the error message if an attempt is made to edit while the lock is held.
|
|
1770
1837
|
* @remarks May only be called when the lock is not already locked.
|
|
1771
1838
|
*/
|
|
1772
|
-
public lock(): void {
|
|
1773
|
-
if (this.
|
|
1839
|
+
public lock(reason: string): void {
|
|
1840
|
+
if (this.status.isLocked) {
|
|
1774
1841
|
debugger;
|
|
1775
1842
|
}
|
|
1776
|
-
assert(!this.
|
|
1777
|
-
this.
|
|
1843
|
+
assert(!this.status.isLocked, 0xaa7 /* Checkout has already been locked */);
|
|
1844
|
+
this.status = { isLocked: true, reason };
|
|
1778
1845
|
}
|
|
1779
1846
|
|
|
1780
1847
|
/**
|
|
@@ -1783,8 +1850,8 @@ class EditLock {
|
|
|
1783
1850
|
* This must start with a capital letter, as it shows up as the first part of the error message and we want it to look nice.
|
|
1784
1851
|
*/
|
|
1785
1852
|
public checkUnlocked<T extends string>(action: T extends Capitalize<T> ? T : never): void {
|
|
1786
|
-
if (this.
|
|
1787
|
-
throw new UsageError(`${action} is forbidden during
|
|
1853
|
+
if (this.status.isLocked) {
|
|
1854
|
+
throw new UsageError(`${action} is forbidden during ${this.status.reason}`);
|
|
1788
1855
|
}
|
|
1789
1856
|
}
|
|
1790
1857
|
|
|
@@ -1793,8 +1860,8 @@ class EditLock {
|
|
|
1793
1860
|
* @remarks May only be called when the lock is currently locked.
|
|
1794
1861
|
*/
|
|
1795
1862
|
public unlock(): void {
|
|
1796
|
-
assert(this.
|
|
1797
|
-
this.
|
|
1863
|
+
assert(this.status.isLocked, 0xaa8 /* Checkout has not been locked */);
|
|
1864
|
+
this.status = { isLocked: false };
|
|
1798
1865
|
}
|
|
1799
1866
|
}
|
|
1800
1867
|
|
|
@@ -214,7 +214,7 @@ export class SharedTreeCore<
|
|
|
214
214
|
options.minVersionForCollab,
|
|
215
215
|
this.schemaAndPolicy,
|
|
216
216
|
options.healUnresolvableIdentifiersOnDecode === true
|
|
217
|
-
? { sharedObjectId: sharedObject.id }
|
|
217
|
+
? { sharedObjectId: sharedObject.id, logger }
|
|
218
218
|
: undefined,
|
|
219
219
|
),
|
|
220
220
|
...summarizables,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
type FieldSchema,
|
|
17
17
|
type FieldSchemaAlpha,
|
|
18
18
|
} from "../fieldSchema.js";
|
|
19
|
-
import type { LeafSchema } from "../leafNodeSchema.js";
|
|
19
|
+
import type { LeafSchema, StringSchema } from "../leafNodeSchema.js";
|
|
20
20
|
import {
|
|
21
21
|
stringSchema,
|
|
22
22
|
numberSchema,
|
|
@@ -252,7 +252,7 @@ export const schemaStatics = {
|
|
|
252
252
|
props?: Omit<FieldProps<TCustomMetadata>, "defaultProvider">,
|
|
253
253
|
): FieldSchemaAlpha<
|
|
254
254
|
FieldKind.Identifier,
|
|
255
|
-
|
|
255
|
+
StringSchema,
|
|
256
256
|
TCustomMetadata,
|
|
257
257
|
FieldPropsAlpha<TCustomMetadata>
|
|
258
258
|
> => {
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type ImplicitAllowedTypes,
|
|
26
26
|
type TreeNodeFromImplicitAllowedTypes,
|
|
27
27
|
normalizeAllowedTypes,
|
|
28
|
+
type TreeNodeKernel,
|
|
28
29
|
} from "../core/index.js";
|
|
29
30
|
import { type ImplicitFieldSchema, FieldSchema } from "../fieldSchema.js";
|
|
30
31
|
import { tryGetTreeNodeForField } from "../getTreeNodeForField.js";
|
|
@@ -115,6 +116,10 @@ export interface ArrayNodeRemoveOp {
|
|
|
115
116
|
* `"remove"` and the destination array's delta contains an `"insert"` — they cannot be
|
|
116
117
|
* correlated without additional bookkeeping on the caller's side.
|
|
117
118
|
*
|
|
119
|
+
* The operations cover the complete array: trailing elements that were not changed are included
|
|
120
|
+
* in a final `"retain"` op. Applying every operation therefore consumes the entire pre-edit array
|
|
121
|
+
* and produces the entire post-edit array.
|
|
122
|
+
*
|
|
118
123
|
* @sealed @alpha
|
|
119
124
|
*/
|
|
120
125
|
export type ArrayNodeDeltaOp = ArrayNodeRetainOp | ArrayNodeInsertOp | ArrayNodeRemoveOp;
|
|
@@ -296,7 +301,13 @@ export const treeNodeApi: TreeNodeApi = {
|
|
|
296
301
|
// unavailable rather than receiving stale marks from only the first batch.
|
|
297
302
|
// TODO: Once the eventing stack is rewritten to walk the composed delta at
|
|
298
303
|
// flush time, `marks` will always be defined. Remove the `undefined` fallback.
|
|
299
|
-
const delta =
|
|
304
|
+
const delta =
|
|
305
|
+
marks === undefined
|
|
306
|
+
? undefined
|
|
307
|
+
: deltaMarksToArrayOpsWithRetain(marks, getArrayLength(kernel), (count) => ({
|
|
308
|
+
type: "retain",
|
|
309
|
+
count,
|
|
310
|
+
}));
|
|
300
311
|
listener({ delta });
|
|
301
312
|
});
|
|
302
313
|
} else {
|
|
@@ -314,7 +325,17 @@ export const treeNodeApi: TreeNodeApi = {
|
|
|
314
325
|
return kernel.events.on("childrenChangedAfterBatch", ({ fieldMarks }) => {
|
|
315
326
|
const marks = fieldMarks.get(EmptyKey);
|
|
316
327
|
const delta =
|
|
317
|
-
marks === undefined
|
|
328
|
+
marks === undefined
|
|
329
|
+
? undefined
|
|
330
|
+
: deltaMarksToArrayOpsWithRetain(
|
|
331
|
+
marks,
|
|
332
|
+
getArrayLength(kernel),
|
|
333
|
+
(count, subtreeChanged) => ({
|
|
334
|
+
type: "retain",
|
|
335
|
+
count,
|
|
336
|
+
subtreeChanged,
|
|
337
|
+
}),
|
|
338
|
+
);
|
|
318
339
|
(listener as (data: { readonly delta: typeof delta }) => void)({ delta });
|
|
319
340
|
});
|
|
320
341
|
}
|
|
@@ -351,73 +372,68 @@ export const treeNodeApi: TreeNodeApi = {
|
|
|
351
372
|
};
|
|
352
373
|
|
|
353
374
|
/**
|
|
354
|
-
* Converts
|
|
355
|
-
*
|
|
375
|
+
* Converts internal {@link DeltaMark}s for an array's sequence field into sequential array delta
|
|
376
|
+
* operations.
|
|
377
|
+
*
|
|
378
|
+
* @remarks
|
|
379
|
+
* Each mark describes a contiguous run:
|
|
380
|
+
* - A mark with only `count` becomes a retain.
|
|
381
|
+
* - A mark with only `attach` becomes an insert.
|
|
382
|
+
* - A mark with only `detach` becomes a remove.
|
|
383
|
+
* - A mark with both `attach` and `detach` becomes a remove followed by an insert.
|
|
356
384
|
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
* - A mark with only `detach` → `"remove"` (elements removed)
|
|
361
|
-
* - A mark with both `attach` and `detach` → `"remove"` + `"insert"`
|
|
385
|
+
* Internal mark arrays may omit an unchanged suffix. The returned operations always cover the
|
|
386
|
+
* complete array, so this function uses the array's post-edit length to append a trailing retain
|
|
387
|
+
* when needed.
|
|
362
388
|
*
|
|
363
389
|
* @param marks - The low-level delta marks for the array's sequence field.
|
|
390
|
+
* @param postEditLength - The array's length after the edit.
|
|
391
|
+
* @param buildRetainOp - Builds a retain operation. Its second argument indicates whether the
|
|
392
|
+
* retained element's subtree changed; it is `false` for a synthesized trailing retain.
|
|
364
393
|
*
|
|
365
394
|
* @privateRemarks
|
|
366
395
|
* The case where both `attach` and `detach` are set is unreachable today: the sequence-field
|
|
367
|
-
* encoder never emits such marks for array (EmptyKey) fields. It is handled defensively.
|
|
396
|
+
* encoder never emits such marks for array (`EmptyKey`) fields. It is handled defensively.
|
|
368
397
|
*/
|
|
369
|
-
export function
|
|
370
|
-
|
|
398
|
+
export function deltaMarksToArrayOpsWithRetain<TRetain extends ArrayNodeRetainOp>(
|
|
399
|
+
marks: readonly DeltaMark[],
|
|
400
|
+
postEditLength: number,
|
|
401
|
+
buildRetainOp: (count: number, subtreeChanged: boolean) => TRetain,
|
|
402
|
+
): (TRetain | ArrayNodeInsertOp | ArrayNodeRemoveOp)[] {
|
|
403
|
+
const ops: (TRetain | ArrayNodeInsertOp | ArrayNodeRemoveOp)[] = [];
|
|
404
|
+
let processedLength = 0;
|
|
371
405
|
for (const mark of marks) {
|
|
372
406
|
if (mark.detach !== undefined) {
|
|
373
407
|
ops.push({ type: "remove", count: mark.count });
|
|
374
408
|
}
|
|
375
409
|
if (mark.attach !== undefined) {
|
|
376
410
|
ops.push({ type: "insert", count: mark.count });
|
|
411
|
+
processedLength += mark.count;
|
|
377
412
|
} else if (mark.detach === undefined) {
|
|
378
|
-
//
|
|
379
|
-
ops.push(
|
|
413
|
+
// When `fields` is set, `count` is guaranteed to be 1 (DeltaMark invariant).
|
|
414
|
+
ops.push(buildRetainOp(mark.count, mark.fields !== undefined));
|
|
415
|
+
processedLength += mark.count;
|
|
380
416
|
}
|
|
381
417
|
}
|
|
418
|
+
// DeltaMark arrays are allowed to omit the trailing retain, while our user facing array equivalents are not, so add it if necessary.
|
|
419
|
+
assert(
|
|
420
|
+
processedLength <= postEditLength,
|
|
421
|
+
0xd19 /* Array delta exceeds post-edit array length */,
|
|
422
|
+
);
|
|
423
|
+
if (processedLength < postEditLength) {
|
|
424
|
+
ops.push(buildRetainOp(postEditLength - processedLength, false));
|
|
425
|
+
}
|
|
382
426
|
return ops;
|
|
383
427
|
}
|
|
384
428
|
|
|
385
429
|
/**
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
* Same conversion rules as {@link deltaMarksToArrayOps}, but retain ops additionally carry a
|
|
391
|
-
* {@link ArrayNodeTreeChangedRetainOp.subtreeChanged} flag derived from whether the mark has
|
|
392
|
-
* a `fields` property (indicating a descendant changed).
|
|
393
|
-
*
|
|
394
|
-
* @param marks - The low-level delta marks for the array's sequence field.
|
|
395
|
-
*
|
|
396
|
-
* @privateRemarks
|
|
397
|
-
* The case where both `attach` and `detach` are set is unreachable today: the sequence-field
|
|
398
|
-
* encoder never emits such marks for array (EmptyKey) fields. It is handled defensively.
|
|
430
|
+
* Returns the length of the `EmptyKey` field under the provided node kernel.
|
|
431
|
+
* @remarks
|
|
432
|
+
* Use this with the kernel of an array node to get the current length of the array.
|
|
433
|
+
* This is the same as `.length` on the array node, but is usable without having to get (and possible create) the node and narrow to the proper type to access that.
|
|
399
434
|
*/
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
): ArrayNodeTreeChangedDeltaOp[] {
|
|
403
|
-
const ops: ArrayNodeTreeChangedDeltaOp[] = [];
|
|
404
|
-
for (const mark of marks) {
|
|
405
|
-
if (mark.detach !== undefined) {
|
|
406
|
-
ops.push({ type: "remove", count: mark.count });
|
|
407
|
-
}
|
|
408
|
-
if (mark.attach !== undefined) {
|
|
409
|
-
ops.push({ type: "insert", count: mark.count });
|
|
410
|
-
} else if (mark.detach === undefined) {
|
|
411
|
-
// Retain: elements were not added or removed (but may have deep changes).
|
|
412
|
-
// When `fields` is set, `count` is guaranteed to be 1 (DeltaMark invariant).
|
|
413
|
-
ops.push({
|
|
414
|
-
type: "retain",
|
|
415
|
-
count: mark.count,
|
|
416
|
-
subtreeChanged: mark.fields !== undefined,
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
return ops;
|
|
435
|
+
function getArrayLength(arrayNodeKernel: TreeNodeKernel): number {
|
|
436
|
+
return arrayNodeKernel.getInnerNode().getBoxed(EmptyKey).length;
|
|
421
437
|
}
|
|
422
438
|
|
|
423
439
|
/**
|
|
@@ -9,8 +9,12 @@ import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
|
9
9
|
import { markEager } from "./flexList.js";
|
|
10
10
|
import { tryGetTreeNodeSchema } from "./treeNodeKernel.js";
|
|
11
11
|
import { NodeKind, type TreeNodeSchemaClass } from "./treeNodeSchema.js";
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
import type {
|
|
13
|
+
WithType,
|
|
14
|
+
// eslint-disable-next-line import-x/no-deprecated -- Required to implement the deprecated typeNameSymbol API.
|
|
15
|
+
typeNameSymbol,
|
|
16
|
+
typeSchemaSymbol,
|
|
17
|
+
} from "./withType.js";
|
|
14
18
|
|
|
15
19
|
/**
|
|
16
20
|
* A non-{@link NodeKind.Leaf|leaf} SharedTree node. Includes objects, arrays, and maps.
|
|
@@ -72,22 +76,21 @@ export abstract class TreeNode implements WithType {
|
|
|
72
76
|
* someone could manually (or via Intellisense auto-implement completion, or in response to a type error)
|
|
73
77
|
* make an object literal with the [type] field and pass it off as a node: this private brand prevents that.
|
|
74
78
|
*/
|
|
75
|
-
// eslint-disable-next-line no-unused-private-class-members
|
|
79
|
+
// eslint-disable-next-line no-unused-private-class-members -- Exists for type checking sideeffect. See private remarks above.
|
|
76
80
|
readonly #brand!: unknown;
|
|
77
81
|
|
|
78
82
|
/**
|
|
79
|
-
* Adds a
|
|
80
|
-
* @privateRemarks
|
|
81
|
-
* Subclasses provide more specific strings for this to get strong typing of otherwise type compatible nodes.
|
|
83
|
+
* Adds a schema identifier brand for stronger and more efficient type checking.
|
|
84
|
+
* @privateRemarks Subclasses provide more specific values to distinguish otherwise type-compatible nodes.
|
|
82
85
|
* @deprecated Use {@link typeSchemaSymbol} instead.
|
|
83
86
|
*/
|
|
84
|
-
// eslint-disable-next-line import-x/no-deprecated
|
|
87
|
+
// eslint-disable-next-line import-x/no-deprecated -- Required to implement the deprecated typeNameSymbol API.
|
|
85
88
|
public abstract get [typeNameSymbol](): string;
|
|
86
89
|
|
|
87
90
|
/**
|
|
88
|
-
*
|
|
91
|
+
* {@inheritDoc typeSchemaSymbol}
|
|
89
92
|
* @privateRemarks
|
|
90
|
-
* Subclasses provide more specific
|
|
93
|
+
* Subclasses provide more specific values for this to get strong typing of otherwise type compatible nodes.
|
|
91
94
|
*/
|
|
92
95
|
public abstract get [typeSchemaSymbol](): TreeNodeSchemaClass;
|
|
93
96
|
|
|
@@ -152,7 +155,7 @@ export const privateToken = {};
|
|
|
152
155
|
* @param base - prototype to search for
|
|
153
156
|
* @returns true iff `base` is in the prototype chain starting at `derived`.
|
|
154
157
|
*/
|
|
155
|
-
// eslint-disable-next-line @rushstack/no-new-null
|
|
158
|
+
// eslint-disable-next-line @rushstack/no-new-null -- getPrototypeOf uses null.
|
|
156
159
|
export function inPrototypeChain(derived: object | null, base: object): boolean {
|
|
157
160
|
let checking = derived;
|
|
158
161
|
while (checking !== null) {
|
|
@@ -11,17 +11,14 @@ import type { TreeNode } from "./treeNode.js";
|
|
|
11
11
|
import type { NodeKind, TreeNodeSchemaClass } from "./treeNodeSchema.js";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* An internal brand to improve compiler performance.
|
|
15
15
|
* For more information about the type, use `Tree.schema(theNode)` instead.
|
|
16
16
|
* @remarks
|
|
17
|
-
* This symbol mainly exists on nodes to allow TypeScript to provide more accurate type checking.
|
|
18
17
|
* `Tree.is` and `Tree.schema` provide a superset of this information in more friendly ways.
|
|
19
|
-
*
|
|
20
|
-
* This symbol should not manually be added to objects as doing so allows the object to be invalidly used where nodes are expected.
|
|
21
|
-
* Instead construct a real node of the desired type using its constructor.
|
|
22
18
|
* @privateRemarks
|
|
23
|
-
*
|
|
24
|
-
*
|
|
19
|
+
* The identifier of a {@link TreeNode}'s schema.
|
|
20
|
+
* This allows the type checker to distinguish different node types more efficiently than via {@link typeSchemaSymbol}.
|
|
21
|
+
* @deprecated External code should use `Tree.schema(theNode)` for schema related runtime data access. For type narrowing, use {@link WithType} instead of the symbols directly.
|
|
25
22
|
* @system @public
|
|
26
23
|
*/
|
|
27
24
|
export const typeNameSymbol: unique symbol = Symbol("TreeNode Type");
|
|
@@ -97,6 +94,13 @@ export const contentSchemaSymbol: unique symbol = Symbol("SharedTree Schema");
|
|
|
97
94
|
* }
|
|
98
95
|
* }
|
|
99
96
|
* ```
|
|
97
|
+
* @privateRemarks
|
|
98
|
+
* The properties of this are implemented as getters rather than instance properties as that is the easiest way to make them non-enumerable,
|
|
99
|
+
* and also saves memory and time as they only have to be setup on the prototype.
|
|
100
|
+
* These being non-enumerable inherited properties minimizes impact on users,
|
|
101
|
+
* hiding them from things like `Reflect.ownKeys`, Object spread, `Object.getOwnPropertyDescriptors`, and `for...in` loops.
|
|
102
|
+
* How we declare them here actually doesn't impact that,
|
|
103
|
+
* but is a good way to communicate to users and internal devs that these should be implemented as inherited getters to accomplish the above.
|
|
100
104
|
* @sealed @public
|
|
101
105
|
*/
|
|
102
106
|
export interface WithType<
|
|
@@ -106,6 +110,15 @@ export interface WithType<
|
|
|
106
110
|
> {
|
|
107
111
|
/**
|
|
108
112
|
* Type symbol, marking a type in a way to increase type safety via strong type checking.
|
|
113
|
+
*
|
|
114
|
+
* Use `Tree.schema(theNode)` for schema related runtime data access. For type narrowing, use `WithType` instead of the symbols directly.
|
|
115
|
+
* @remarks
|
|
116
|
+
* This should be redundant with {@link typeSchemaSymbol}, but is kept for improved compiler performance.
|
|
117
|
+
* If we just rely on {@link typeSchemaSymbol}, the compiler has to work much harder to distinguish schema in unions,
|
|
118
|
+
* which can cause large schema unions to hit "error TS2859: Excessive complexity comparing types".
|
|
119
|
+
*
|
|
120
|
+
* This property is not intended for any use other than helping the compiler distinguish schema types,
|
|
121
|
+
* and should not be referenced in any code other than internal to the tree package.
|
|
109
122
|
* @deprecated Use {@link typeSchemaSymbol} instead.
|
|
110
123
|
*/
|
|
111
124
|
get [typeNameSymbol](): TName;
|
package/src/simple-tree/index.ts
CHANGED
|
@@ -100,7 +100,6 @@ export {
|
|
|
100
100
|
type ArrayNodeRetainOp,
|
|
101
101
|
type ArrayNodeTreeChangedDeltaOp,
|
|
102
102
|
type ArrayNodeTreeChangedRetainOp,
|
|
103
|
-
deltaMarksToArrayOps,
|
|
104
103
|
type NodeChangedData,
|
|
105
104
|
type NodeChangedDataAlpha,
|
|
106
105
|
type NodeChangedDataDelta,
|
|
@@ -328,6 +327,6 @@ export {
|
|
|
328
327
|
handleSchema,
|
|
329
328
|
nullSchema,
|
|
330
329
|
} from "./leafNodeSchema.js";
|
|
331
|
-
export type { LeafSchema } from "./leafNodeSchema.js";
|
|
330
|
+
export type { LeafSchema, StringSchema } from "./leafNodeSchema.js";
|
|
332
331
|
export { getUnhydratedContext } from "./createContext.js";
|
|
333
332
|
export { type TreeSchema, createTreeSchema } from "./treeSchema.js";
|
|
@@ -125,7 +125,12 @@ export interface LeafSchema<Name extends string, T extends TreeLeafValue>
|
|
|
125
125
|
> {}
|
|
126
126
|
|
|
127
127
|
// Leaf schema shared between all SchemaFactory instances.
|
|
128
|
-
|
|
128
|
+
/**
|
|
129
|
+
* A {@link LeafSchema} for a `string`.
|
|
130
|
+
* @system @sealed @alpha
|
|
131
|
+
*/
|
|
132
|
+
export type StringSchema = LeafSchema<"string", string> & SimpleLeafNodeSchema;
|
|
133
|
+
export const stringSchema: StringSchema = makeLeaf("string", ValueSchema.String);
|
|
129
134
|
export const numberSchema = makeLeaf("number", ValueSchema.Number);
|
|
130
135
|
export const booleanSchema = makeLeaf("boolean", ValueSchema.Boolean);
|
|
131
136
|
export const nullSchema = makeLeaf("null", ValueSchema.Null);
|