@fluidframework/tree 2.1.0-276326 → 2.1.0-281041
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/.eslintrc.cjs +7 -0
- package/.vscode/Tree.code-workspace +7 -1
- package/README.md +134 -29
- package/api-report/tree.alpha.api.md +1 -0
- package/api-report/tree.beta.api.md +1 -0
- package/api-report/tree.public.api.md +1 -0
- package/beta.d.ts +1 -1
- package/dist/beta.d.ts +1 -1
- package/dist/core/forest/editableForest.d.ts +6 -3
- package/dist/core/forest/editableForest.d.ts.map +1 -1
- package/dist/core/forest/editableForest.js +14 -4
- package/dist/core/forest/editableForest.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- 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 +3 -1
- package/dist/core/rebase/index.js.map +1 -1
- package/dist/core/rebase/types.d.ts +2 -0
- package/dist/core/rebase/types.d.ts.map +1 -1
- package/dist/core/rebase/types.js +9 -1
- package/dist/core/rebase/types.js.map +1 -1
- package/dist/core/tree/visitDelta.d.ts.map +1 -1
- package/dist/core/tree/visitDelta.js.map +1 -1
- package/dist/events/events.d.ts +4 -1
- package/dist/events/events.d.ts.map +1 -1
- package/dist/events/events.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.js +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js +1 -0
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts +0 -2
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.js +0 -20
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +0 -38
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/index.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +0 -4
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +1 -14
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts +0 -1
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.js +0 -3
- package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +3 -3
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +2 -2
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +11 -0
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/dist/feature-libraries/modular-schema/discrepancies.d.ts +96 -0
- package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/discrepancies.js +264 -0
- package/dist/feature-libraries/modular-schema/discrepancies.js.map +1 -0
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +9 -2
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.js +3 -0
- package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts +2 -1
- package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/index.js +3 -1
- package/dist/feature-libraries/modular-schema/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +42 -26
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +51 -2
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +830 -245
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormat.js +2 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormat.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +44 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/dist/feature-libraries/node-key/index.d.ts +0 -1
- package/dist/feature-libraries/node-key/index.d.ts.map +1 -1
- package/dist/feature-libraries/node-key/index.js +1 -3
- package/dist/feature-libraries/node-key/index.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.js +1 -0
- package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/dist/feature-libraries/sequence-field/index.d.ts +1 -1
- package/dist/feature-libraries/sequence-field/index.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/index.js +1 -2
- package/dist/feature-libraries/sequence-field/index.js.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.js +1 -1
- package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
- package/dist/feature-libraries/sequence-field/rebase.js +6 -1
- package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +1 -0
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.d.ts +2 -17
- package/dist/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.js +31 -39
- package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
- package/dist/feature-libraries/typed-schema/typedTreeSchema.d.ts +1 -0
- package/dist/feature-libraries/typed-schema/typedTreeSchema.d.ts.map +1 -1
- package/dist/feature-libraries/typed-schema/typedTreeSchema.js +2 -0
- package/dist/feature-libraries/typed-schema/typedTreeSchema.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- 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/public.d.ts +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +4 -2
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +240 -184
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +3 -2
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +150 -90
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +2 -1
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js +1 -0
- package/dist/shared-tree-core/branch.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +4 -6
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +265 -209
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/arrayNode.d.ts +4 -0
- package/dist/simple-tree/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/arrayNode.js +36 -19
- package/dist/simple-tree/arrayNode.js.map +1 -1
- package/dist/simple-tree/leafNodeSchema.d.ts +22 -1
- package/dist/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/dist/simple-tree/leafNodeSchema.js +2 -1
- package/dist/simple-tree/leafNodeSchema.js.map +1 -1
- package/dist/simple-tree/mapNode.d.ts.map +1 -1
- package/dist/simple-tree/mapNode.js.map +1 -1
- package/dist/simple-tree/objectNode.d.ts.map +1 -1
- package/dist/simple-tree/objectNode.js +2 -1
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/proxies.d.ts.map +1 -1
- package/dist/simple-tree/proxies.js +2 -4
- package/dist/simple-tree/proxies.js.map +1 -1
- package/dist/simple-tree/schemaFactory.d.ts +24 -1
- package/dist/simple-tree/schemaFactory.d.ts.map +1 -1
- package/dist/simple-tree/schemaFactory.js +40 -4
- package/dist/simple-tree/schemaFactory.js.map +1 -1
- package/dist/simple-tree/schemaTypes.d.ts +36 -1
- package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
- package/dist/simple-tree/schemaTypes.js.map +1 -1
- package/dist/simple-tree/toFlexSchema.d.ts +2 -2
- package/dist/simple-tree/toFlexSchema.d.ts.map +1 -1
- package/dist/simple-tree/toFlexSchema.js +3 -2
- package/dist/simple-tree/toFlexSchema.js.map +1 -1
- package/dist/simple-tree/tree.d.ts +4 -1
- package/dist/simple-tree/tree.d.ts.map +1 -1
- package/dist/simple-tree/tree.js +48 -1
- package/dist/simple-tree/tree.js.map +1 -1
- package/dist/simple-tree/treeNodeApi.d.ts.map +1 -1
- package/dist/simple-tree/treeNodeApi.js +10 -10
- package/dist/simple-tree/treeNodeApi.js.map +1 -1
- package/dist/simple-tree/types.d.ts +22 -3
- package/dist/simple-tree/types.d.ts.map +1 -1
- package/dist/simple-tree/types.js +32 -21
- package/dist/simple-tree/types.js.map +1 -1
- package/dist/util/breakable.d.ts +83 -0
- package/dist/util/breakable.d.ts.map +1 -0
- package/dist/util/breakable.js +178 -0
- package/dist/util/breakable.js.map +1 -0
- package/dist/util/index.d.ts +3 -2
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +9 -2
- package/dist/util/index.js.map +1 -1
- package/dist/util/nestedMap.d.ts +23 -3
- package/dist/util/nestedMap.d.ts.map +1 -1
- package/dist/util/nestedMap.js +38 -7
- package/dist/util/nestedMap.js.map +1 -1
- package/dist/util/utils.d.ts +7 -0
- package/dist/util/utils.d.ts.map +1 -1
- package/dist/util/utils.js +15 -1
- package/dist/util/utils.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/main/compatibility.md +1 -1
- package/docs/main/stored-and-view-schema.md +1 -1
- package/internal.d.ts +1 -1
- package/lib/beta.d.ts +1 -1
- package/lib/core/forest/editableForest.d.ts +6 -3
- package/lib/core/forest/editableForest.d.ts.map +1 -1
- package/lib/core/forest/editableForest.js +15 -5
- package/lib/core/forest/editableForest.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 +2 -0
- package/lib/core/rebase/types.d.ts.map +1 -1
- package/lib/core/rebase/types.js +7 -1
- package/lib/core/rebase/types.js.map +1 -1
- package/lib/core/tree/visitDelta.d.ts.map +1 -1
- package/lib/core/tree/visitDelta.js.map +1 -1
- package/lib/events/events.d.ts +4 -1
- package/lib/events/events.d.ts.map +1 -1
- package/lib/events/events.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.js +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js +1 -0
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts +0 -2
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.js +0 -20
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +0 -38
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/index.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +0 -4
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +1 -14
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts +0 -1
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.js +0 -3
- package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +3 -3
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +2 -2
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +11 -0
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/lib/feature-libraries/modular-schema/discrepancies.d.ts +96 -0
- package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/discrepancies.js +260 -0
- package/lib/feature-libraries/modular-schema/discrepancies.js.map +1 -0
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +9 -2
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.js +3 -0
- package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts +2 -1
- package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/index.js +1 -0
- package/lib/feature-libraries/modular-schema/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +42 -26
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +51 -2
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +829 -247
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormat.js +2 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormat.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +44 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/lib/feature-libraries/node-key/index.d.ts +0 -1
- package/lib/feature-libraries/node-key/index.d.ts.map +1 -1
- package/lib/feature-libraries/node-key/index.js +0 -1
- package/lib/feature-libraries/node-key/index.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.js +1 -0
- package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/lib/feature-libraries/sequence-field/index.d.ts +1 -1
- package/lib/feature-libraries/sequence-field/index.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/index.js +1 -1
- package/lib/feature-libraries/sequence-field/index.js.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.js +1 -1
- package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
- package/lib/feature-libraries/sequence-field/rebase.js +6 -1
- package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +2 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.d.ts +2 -17
- package/lib/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.js +31 -39
- package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
- package/lib/feature-libraries/typed-schema/typedTreeSchema.d.ts +1 -0
- package/lib/feature-libraries/typed-schema/typedTreeSchema.d.ts.map +1 -1
- package/lib/feature-libraries/typed-schema/typedTreeSchema.js +4 -2
- package/lib/feature-libraries/typed-schema/typedTreeSchema.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- 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/public.d.ts +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +4 -2
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +242 -185
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +3 -2
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +151 -90
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +2 -1
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js +1 -0
- package/lib/shared-tree-core/branch.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +4 -6
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +267 -210
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/arrayNode.d.ts +4 -0
- package/lib/simple-tree/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/arrayNode.js +38 -21
- package/lib/simple-tree/arrayNode.js.map +1 -1
- package/lib/simple-tree/leafNodeSchema.d.ts +22 -1
- package/lib/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/lib/simple-tree/leafNodeSchema.js +1 -1
- package/lib/simple-tree/leafNodeSchema.js.map +1 -1
- package/lib/simple-tree/mapNode.d.ts.map +1 -1
- package/lib/simple-tree/mapNode.js.map +1 -1
- package/lib/simple-tree/objectNode.d.ts.map +1 -1
- package/lib/simple-tree/objectNode.js +3 -2
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/proxies.d.ts.map +1 -1
- package/lib/simple-tree/proxies.js +2 -4
- package/lib/simple-tree/proxies.js.map +1 -1
- package/lib/simple-tree/schemaFactory.d.ts +24 -1
- package/lib/simple-tree/schemaFactory.d.ts.map +1 -1
- package/lib/simple-tree/schemaFactory.js +38 -3
- package/lib/simple-tree/schemaFactory.js.map +1 -1
- package/lib/simple-tree/schemaTypes.d.ts +36 -1
- package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
- package/lib/simple-tree/schemaTypes.js.map +1 -1
- package/lib/simple-tree/toFlexSchema.d.ts +2 -2
- package/lib/simple-tree/toFlexSchema.d.ts.map +1 -1
- package/lib/simple-tree/toFlexSchema.js +3 -2
- package/lib/simple-tree/toFlexSchema.js.map +1 -1
- package/lib/simple-tree/tree.d.ts +4 -1
- package/lib/simple-tree/tree.d.ts.map +1 -1
- package/lib/simple-tree/tree.js +44 -0
- package/lib/simple-tree/tree.js.map +1 -1
- package/lib/simple-tree/treeNodeApi.d.ts.map +1 -1
- package/lib/simple-tree/treeNodeApi.js +11 -11
- package/lib/simple-tree/treeNodeApi.js.map +1 -1
- package/lib/simple-tree/types.d.ts +22 -3
- package/lib/simple-tree/types.d.ts.map +1 -1
- package/lib/simple-tree/types.js +32 -21
- package/lib/simple-tree/types.js.map +1 -1
- package/lib/util/breakable.d.ts +83 -0
- package/lib/util/breakable.d.ts.map +1 -0
- package/lib/util/breakable.js +171 -0
- package/lib/util/breakable.js.map +1 -0
- package/lib/util/index.d.ts +3 -2
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +3 -2
- package/lib/util/index.js.map +1 -1
- package/lib/util/nestedMap.d.ts +23 -3
- package/lib/util/nestedMap.d.ts.map +1 -1
- package/lib/util/nestedMap.js +36 -6
- package/lib/util/nestedMap.js.map +1 -1
- package/lib/util/utils.d.ts +7 -0
- package/lib/util/utils.d.ts.map +1 -1
- package/lib/util/utils.js +13 -0
- package/lib/util/utils.js.map +1 -1
- package/package.json +29 -27
- package/src/core/forest/editableForest.ts +17 -4
- package/src/core/index.ts +2 -0
- package/src/core/rebase/index.ts +2 -0
- package/src/core/rebase/types.ts +17 -0
- package/src/core/tree/visitDelta.ts +1 -0
- package/src/events/events.ts +4 -2
- package/src/feature-libraries/default-schema/defaultEditBuilder.ts +1 -1
- package/src/feature-libraries/default-schema/defaultFieldKinds.ts +1 -0
- package/src/feature-libraries/flex-map-tree/mapTreeNode.ts +0 -30
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +0 -43
- package/src/feature-libraries/flex-tree/index.ts +0 -1
- package/src/feature-libraries/flex-tree/lazyField.ts +1 -21
- package/src/feature-libraries/flex-tree/lazyNode.ts +0 -6
- package/src/feature-libraries/index.ts +1 -2
- package/src/feature-libraries/modular-schema/crossFieldQueries.ts +18 -0
- package/src/feature-libraries/modular-schema/discrepancies.ts +395 -0
- package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +10 -2
- package/src/feature-libraries/modular-schema/genericFieldKind.ts +3 -0
- package/src/feature-libraries/modular-schema/index.ts +2 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +81 -35
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +1529 -454
- package/src/feature-libraries/modular-schema/modularChangeFormat.ts +2 -0
- package/src/feature-libraries/modular-schema/modularChangeTypes.ts +51 -0
- package/src/feature-libraries/node-key/index.ts +0 -1
- package/src/feature-libraries/optional-field/optionalField.ts +1 -0
- package/src/feature-libraries/sequence-field/index.ts +0 -2
- package/src/feature-libraries/sequence-field/invert.ts +1 -1
- package/src/feature-libraries/sequence-field/rebase.ts +7 -1
- package/src/feature-libraries/sequence-field/sequenceFieldChangeHandler.ts +2 -1
- package/src/feature-libraries/sequence-field/utils.ts +37 -85
- package/src/feature-libraries/typed-schema/typedTreeSchema.ts +10 -0
- package/src/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/schematizingTreeView.ts +6 -2
- package/src/shared-tree/sharedTree.ts +5 -2
- package/src/shared-tree/treeCheckout.ts +6 -2
- package/src/shared-tree-core/branch.ts +1 -0
- package/src/shared-tree-core/sharedTreeCore.ts +18 -6
- package/src/simple-tree/arrayNode.ts +49 -22
- package/src/simple-tree/leafNodeSchema.ts +1 -1
- package/src/simple-tree/mapNode.ts +2 -2
- package/src/simple-tree/objectNode.ts +9 -3
- package/src/simple-tree/proxies.ts +2 -4
- package/src/simple-tree/schemaFactory.ts +45 -2
- package/src/simple-tree/schemaTypes.ts +36 -1
- package/src/simple-tree/toFlexSchema.ts +5 -4
- package/src/simple-tree/tree.ts +65 -4
- package/src/simple-tree/treeNodeApi.ts +15 -15
- package/src/simple-tree/types.ts +60 -30
- package/src/util/breakable.ts +214 -0
- package/src/util/index.ts +10 -0
- package/src/util/nestedMap.ts +49 -11
- package/src/util/utils.ts +17 -0
- package/dist/feature-libraries/node-key/nodeKeyIndex.d.ts +0 -41
- package/dist/feature-libraries/node-key/nodeKeyIndex.d.ts.map +0 -1
- package/dist/feature-libraries/node-key/nodeKeyIndex.js +0 -101
- package/dist/feature-libraries/node-key/nodeKeyIndex.js.map +0 -1
- package/lib/feature-libraries/node-key/nodeKeyIndex.d.ts +0 -41
- package/lib/feature-libraries/node-key/nodeKeyIndex.d.ts.map +0 -1
- package/lib/feature-libraries/node-key/nodeKeyIndex.js +0 -97
- package/lib/feature-libraries/node-key/nodeKeyIndex.js.map +0 -1
- package/src/feature-libraries/node-key/nodeKeyIndex.ts +0 -132
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
getOrCreateMapTreeNode,
|
|
20
20
|
getSchemaAndPolicy,
|
|
21
21
|
isMapTreeNode,
|
|
22
|
+
isFlexTreeNode,
|
|
22
23
|
} from "../feature-libraries/index.js";
|
|
23
24
|
import {
|
|
24
25
|
type InsertableContent,
|
|
@@ -39,7 +40,12 @@ import {
|
|
|
39
40
|
normalizeFieldSchema,
|
|
40
41
|
} from "./schemaTypes.js";
|
|
41
42
|
import { mapTreeFromNodeData } from "./toMapTree.js";
|
|
42
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
type TreeNode,
|
|
45
|
+
TreeNodeValid,
|
|
46
|
+
type InternalTreeNode,
|
|
47
|
+
type MostDerivedData,
|
|
48
|
+
} from "./types.js";
|
|
43
49
|
import { fail } from "../util/index.js";
|
|
44
50
|
import { getFlexSchema } from "./toFlexSchema.js";
|
|
45
51
|
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
@@ -215,6 +221,11 @@ export interface TreeArrayNodeBase<out T, in TNew, in TMoveFrom>
|
|
|
215
221
|
sourceEnd: number,
|
|
216
222
|
source: TMoveFrom,
|
|
217
223
|
): void;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Returns a custom IterableIterator which throws usage errors if concurrent editing and iteration occurs.
|
|
227
|
+
*/
|
|
228
|
+
values(): IterableIterator<T>;
|
|
218
229
|
}
|
|
219
230
|
|
|
220
231
|
/**
|
|
@@ -315,7 +326,6 @@ const arrayPrototypeKeys = [
|
|
|
315
326
|
"some",
|
|
316
327
|
"toLocaleString",
|
|
317
328
|
"toString",
|
|
318
|
-
"values",
|
|
319
329
|
|
|
320
330
|
// "copyWithin",
|
|
321
331
|
// "fill",
|
|
@@ -489,7 +499,6 @@ declare abstract class NodeWithArrayFeatures<Input, T>
|
|
|
489
499
|
): boolean;
|
|
490
500
|
toLocaleString(): string;
|
|
491
501
|
toString(): string;
|
|
492
|
-
values(): IterableIterator<T>;
|
|
493
502
|
}
|
|
494
503
|
/* eslint-enable @typescript-eslint/explicit-member-accessibility, @typescript-eslint/no-explicit-any */
|
|
495
504
|
|
|
@@ -554,16 +563,8 @@ function createArrayNodeProxy(
|
|
|
554
563
|
return Reflect.get(dispatchTarget, key, receiver) as unknown;
|
|
555
564
|
}
|
|
556
565
|
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
if (value === undefined) {
|
|
560
|
-
return undefined;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// TODO: Ideally, we would return leaves without first boxing them. However, this is not
|
|
564
|
-
// as simple as calling '.content' since this skips the node and returns the FieldNode's
|
|
565
|
-
// inner field.
|
|
566
|
-
return getOrCreateNodeProxy(value);
|
|
566
|
+
const maybeContent = field.at(maybeIndex);
|
|
567
|
+
return isFlexTreeNode(maybeContent) ? getOrCreateNodeProxy(maybeContent) : maybeContent;
|
|
567
568
|
},
|
|
568
569
|
set: (target, key, newValue, receiver) => {
|
|
569
570
|
if (key === "length") {
|
|
@@ -590,7 +591,7 @@ function createArrayNodeProxy(
|
|
|
590
591
|
"Cannot set indexed properties on array nodes. Use array node mutation APIs to alter the array.",
|
|
591
592
|
);
|
|
592
593
|
}
|
|
593
|
-
return allowAdditionalProperties ? Reflect.set(target, key, newValue) : false;
|
|
594
|
+
return allowAdditionalProperties ? Reflect.set(target, key, newValue, receiver) : false;
|
|
594
595
|
},
|
|
595
596
|
has: (target, key) => {
|
|
596
597
|
const field = getSequenceField(proxy);
|
|
@@ -672,6 +673,21 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
|
|
|
672
673
|
|
|
673
674
|
protected abstract get simpleSchema(): T;
|
|
674
675
|
|
|
676
|
+
/**
|
|
677
|
+
* Generation number which is incremented any time we have an edit on the node.
|
|
678
|
+
* Used during iteration to make sure there has been no edits that were concurrently made.
|
|
679
|
+
*/
|
|
680
|
+
#generationNumber: number = 0;
|
|
681
|
+
|
|
682
|
+
public constructor(
|
|
683
|
+
input: Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>> | InternalTreeNode,
|
|
684
|
+
) {
|
|
685
|
+
super(input);
|
|
686
|
+
getFlexNode(this).on("nodeChanged", () => {
|
|
687
|
+
this.#generationNumber += 1;
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
|
|
675
691
|
#cursorFromFieldData(value: Insertable<T>): ITreeCursorSynchronous {
|
|
676
692
|
if (isMapTreeNode(getFlexNode(this))) {
|
|
677
693
|
throw new UsageError(`An array cannot be mutated before being inserted into the tree`);
|
|
@@ -827,13 +843,7 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
|
|
|
827
843
|
const destinationField = getSequenceField(this);
|
|
828
844
|
validateIndex(destinationIndex, destinationField, "moveRangeToIndex", true);
|
|
829
845
|
validateIndexRange(sourceStart, sourceEnd, source ?? destinationField, "moveRangeToIndex");
|
|
830
|
-
const sourceField =
|
|
831
|
-
source !== undefined
|
|
832
|
-
? destinationField.isSameAs(getSequenceField(source))
|
|
833
|
-
? destinationField
|
|
834
|
-
: getSequenceField(source)
|
|
835
|
-
: destinationField;
|
|
836
|
-
|
|
846
|
+
const sourceField = source !== undefined ? getSequenceField(source) : destinationField;
|
|
837
847
|
// TODO: determine support for move across different sequence types
|
|
838
848
|
if (destinationField.schema.types !== undefined && sourceField !== destinationField) {
|
|
839
849
|
for (let i = sourceStart; i < sourceEnd; i++) {
|
|
@@ -855,6 +865,23 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
|
|
|
855
865
|
destinationIndex,
|
|
856
866
|
);
|
|
857
867
|
}
|
|
868
|
+
|
|
869
|
+
public values(): IterableIterator<TreeNodeFromImplicitAllowedTypes<T>> {
|
|
870
|
+
return this.generateValues(this.#generationNumber);
|
|
871
|
+
}
|
|
872
|
+
private *generateValues(
|
|
873
|
+
initialLastUpdatedStamp: number,
|
|
874
|
+
): Generator<TreeNodeFromImplicitAllowedTypes<T>> {
|
|
875
|
+
if (initialLastUpdatedStamp !== this.#generationNumber) {
|
|
876
|
+
throw new UsageError(`Concurrent editing and iteration is not allowed.`);
|
|
877
|
+
}
|
|
878
|
+
for (let i = 0; i < this.length; i++) {
|
|
879
|
+
yield this.at(i) ?? fail("Index is out of bounds");
|
|
880
|
+
if (initialLastUpdatedStamp !== this.#generationNumber) {
|
|
881
|
+
throw new UsageError(`Concurrent editing and iteration is not allowed.`);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
858
885
|
}
|
|
859
886
|
|
|
860
887
|
/**
|
|
@@ -921,7 +948,7 @@ export function arraySchema<
|
|
|
921
948
|
);
|
|
922
949
|
}
|
|
923
950
|
|
|
924
|
-
protected static override constructorCached:
|
|
951
|
+
protected static override constructorCached: MostDerivedData | undefined = undefined;
|
|
925
952
|
|
|
926
953
|
protected static override oneTimeSetup<T2>(this: typeof TreeNodeValid<T2>): void {
|
|
927
954
|
flexSchema = getFlexSchema(this as unknown as TreeNodeSchema) as FlexFieldNodeSchema;
|
|
@@ -32,7 +32,7 @@ type UnbrandedName<T extends FlexLeafNodeSchema> = T["name"] extends TreeNodeSch
|
|
|
32
32
|
* @privateRemarks
|
|
33
33
|
* This class refers to the underlying flex tree schema in its constructor, so this class can't be included in the package API.
|
|
34
34
|
*/
|
|
35
|
-
class LeafNodeSchema<T extends FlexLeafNodeSchema>
|
|
35
|
+
export class LeafNodeSchema<T extends FlexLeafNodeSchema>
|
|
36
36
|
implements TreeNodeSchemaNonClass<UnbrandedName<T>, NodeKind.Leaf, TreeValue<T["info"]>>
|
|
37
37
|
{
|
|
38
38
|
public readonly identifier: UnbrandedName<T>;
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
typeNameSymbol,
|
|
33
33
|
} from "./schemaTypes.js";
|
|
34
34
|
import { mapTreeFromNodeData } from "./toMapTree.js";
|
|
35
|
-
import { type TreeNode, TreeNodeValid } from "./types.js";
|
|
35
|
+
import { type MostDerivedData, type TreeNode, TreeNodeValid } from "./types.js";
|
|
36
36
|
import { getFlexSchema } from "./toFlexSchema.js";
|
|
37
37
|
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
38
38
|
|
|
@@ -246,7 +246,7 @@ export function mapSchema<
|
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
protected static override constructorCached:
|
|
249
|
+
protected static override constructorCached: MostDerivedData | undefined = undefined;
|
|
250
250
|
|
|
251
251
|
protected static override oneTimeSetup<T2>(this: typeof TreeNodeValid<T2>): void {
|
|
252
252
|
flexSchema = getFlexSchema(this as unknown as TreeNodeSchema) as FlexMapNodeSchema;
|
|
@@ -44,7 +44,12 @@ import {
|
|
|
44
44
|
FieldKind,
|
|
45
45
|
} from "./schemaTypes.js";
|
|
46
46
|
import { mapTreeFromNodeData } from "./toMapTree.js";
|
|
47
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
type InternalTreeNode,
|
|
49
|
+
type MostDerivedData,
|
|
50
|
+
type TreeNode,
|
|
51
|
+
TreeNodeValid,
|
|
52
|
+
} from "./types.js";
|
|
48
53
|
import { type RestrictiveReadonlyRecord, fail, type FlattenKeys } from "../util/index.js";
|
|
49
54
|
import { getFlexSchema } from "./toFlexSchema.js";
|
|
50
55
|
|
|
@@ -187,7 +192,8 @@ function createProxyHandler(
|
|
|
187
192
|
set(target, viewKey, value: InsertableContent | undefined, proxy) {
|
|
188
193
|
const fieldInfo = flexKeyMap.get(viewKey);
|
|
189
194
|
if (fieldInfo === undefined) {
|
|
190
|
-
|
|
195
|
+
// Pass the proxy as the receiver here, so that setters on the prototype receive `proxy` as `this`.
|
|
196
|
+
return allowAdditionalProperties ? Reflect.set(target, viewKey, value, proxy) : false;
|
|
191
197
|
}
|
|
192
198
|
|
|
193
199
|
const flexNode = getFlexNode(proxy);
|
|
@@ -359,7 +365,7 @@ export function objectSchema<
|
|
|
359
365
|
);
|
|
360
366
|
}
|
|
361
367
|
|
|
362
|
-
protected static override constructorCached:
|
|
368
|
+
protected static override constructorCached: MostDerivedData | undefined = undefined;
|
|
363
369
|
|
|
364
370
|
protected static override oneTimeSetup<T2>(this: typeof TreeNodeValid<T2>): void {
|
|
365
371
|
// One time initialization that required knowing the most derived type (from this.constructor) and thus has to be lazy.
|
|
@@ -61,10 +61,8 @@ export function getProxyForField(field: FlexTreeField): TreeNode | TreeValue | u
|
|
|
61
61
|
FlexFieldSchema<typeof FieldKinds.required | typeof FieldKinds.optional>
|
|
62
62
|
>,
|
|
63
63
|
): TreeNode | TreeValue | undefined {
|
|
64
|
-
const
|
|
65
|
-
return isFlexTreeNode(
|
|
66
|
-
? getOrCreateNodeProxy(maybeUnboxedContent)
|
|
67
|
-
: maybeUnboxedContent;
|
|
64
|
+
const maybeContent = flexField.content;
|
|
65
|
+
return isFlexTreeNode(maybeContent) ? getOrCreateNodeProxy(maybeContent) : maybeContent;
|
|
68
66
|
}
|
|
69
67
|
switch (field.schema.kind) {
|
|
70
68
|
case FieldKinds.required: {
|
|
@@ -8,6 +8,8 @@ import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
|
8
8
|
// which degrades the API-Extractor report quality since API-Extractor can not tell the inline import is the same as the non-inline one.
|
|
9
9
|
// eslint-disable-next-line unused-imports/no-unused-imports
|
|
10
10
|
import type { IFluidHandle as _dummyImport } from "@fluidframework/core-interfaces";
|
|
11
|
+
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
12
|
+
import { isFluidHandle } from "@fluidframework/runtime-utils/internal";
|
|
11
13
|
|
|
12
14
|
import type { TreeValue } from "../core/index.js";
|
|
13
15
|
import { type NodeKeyManager, type Unenforced, isLazy } from "../feature-libraries/index.js";
|
|
@@ -20,6 +22,7 @@ import {
|
|
|
20
22
|
import {
|
|
21
23
|
booleanSchema,
|
|
22
24
|
handleSchema,
|
|
25
|
+
LeafNodeSchema,
|
|
23
26
|
nullSchema,
|
|
24
27
|
numberSchema,
|
|
25
28
|
stringSchema,
|
|
@@ -40,7 +43,6 @@ import {
|
|
|
40
43
|
getDefaultProvider,
|
|
41
44
|
} from "./schemaTypes.js";
|
|
42
45
|
import { type TreeArrayNode, arraySchema } from "./arrayNode.js";
|
|
43
|
-
import { isFluidHandle } from "@fluidframework/runtime-utils/internal";
|
|
44
46
|
import {
|
|
45
47
|
type InsertableObjectFromSchemaRecord,
|
|
46
48
|
type TreeObjectNode,
|
|
@@ -64,6 +66,7 @@ import type {
|
|
|
64
66
|
TreeObjectNodeUnsafe,
|
|
65
67
|
} from "./typesUnsafe.js";
|
|
66
68
|
import { createFieldSchemaUnsafe } from "./schemaFactoryRecursive.js";
|
|
69
|
+
import { inPrototypeChain, TreeNodeValid } from "./types.js";
|
|
67
70
|
/**
|
|
68
71
|
* Gets the leaf domain schema compatible with a given {@link TreeValue}.
|
|
69
72
|
*/
|
|
@@ -161,9 +164,24 @@ export class SchemaFactory<
|
|
|
161
164
|
out TScope extends string | undefined = string | undefined,
|
|
162
165
|
TName extends number | string = string,
|
|
163
166
|
> {
|
|
167
|
+
/**
|
|
168
|
+
* TODO:
|
|
169
|
+
* If users of this generate the same name because two different schema with the same identifier were used,
|
|
170
|
+
* the second use can get a cache hit, and reference the wrong schema.
|
|
171
|
+
* Such usage should probably return a distinct type or error but currently does not.
|
|
172
|
+
* The use of markSchemaMostDerived in structuralName at least ensure an error in the case where the collision is from two types extending the same schema factor class.
|
|
173
|
+
*/
|
|
164
174
|
private readonly structuralTypes: Map<string, TreeNodeSchema> = new Map();
|
|
165
175
|
|
|
166
176
|
/**
|
|
177
|
+
* Construct a SchemaFactory with a given scope.
|
|
178
|
+
* @remarks
|
|
179
|
+
* There are no restrictions on mixing schema from different schema factories:
|
|
180
|
+
* this is encouraged when a single schema references schema from different libraries.
|
|
181
|
+
* If each library exporting schema picks its own globally unique scope for its SchemaFactory,
|
|
182
|
+
* then all schema an application might depend on, directly or transitively,
|
|
183
|
+
* will end up with a unique fully qualified name which is required to refer to it in persisted data and errors.
|
|
184
|
+
*
|
|
167
185
|
* @param scope - Prefix appended to the identifiers of all {@link TreeNodeSchema} produced by this builder.
|
|
168
186
|
* Use of [Reverse domain name notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation) or a UUIDv4 is recommended to avoid collisions.
|
|
169
187
|
* You may opt out of using a scope by passing `undefined`, but note that this increases the risk of collisions.
|
|
@@ -228,7 +246,7 @@ export class SchemaFactory<
|
|
|
228
246
|
public readonly handle = handleSchema;
|
|
229
247
|
|
|
230
248
|
/**
|
|
231
|
-
* Define a {@link
|
|
249
|
+
* Define a {@link TreeNodeSchemaClass} for a {@link TreeObjectNode}.
|
|
232
250
|
*
|
|
233
251
|
* @param name - Unique identifier for this schema within this factory's scope.
|
|
234
252
|
* @param fields - Schema for fields of the object node's schema. Defines what children can be placed under each key.
|
|
@@ -721,6 +739,7 @@ export function structuralName<const T extends string>(
|
|
|
721
739
|
const names = allowedTypes.map((t): string => {
|
|
722
740
|
// Ensure that lazy types (functions) don't slip through here.
|
|
723
741
|
assert(!isLazy(t), 0x83d /* invalid type provided */);
|
|
742
|
+
markSchemaMostDerived(t);
|
|
724
743
|
return t.identifier;
|
|
725
744
|
});
|
|
726
745
|
// Ensure name is order independent
|
|
@@ -732,3 +751,27 @@ export function structuralName<const T extends string>(
|
|
|
732
751
|
}
|
|
733
752
|
return `${collectionName}<${inner}>`;
|
|
734
753
|
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Indicates that a schema is the "most derived" version which is allowed to be used, see {@link MostDerivedData}.
|
|
757
|
+
* Calling helps with error messages about invalid schema usage (using more than one type from single schema factor produced type,
|
|
758
|
+
* and thus calling this for one than one subclass).
|
|
759
|
+
* @remarks
|
|
760
|
+
* Helper for invoking {@link TreeNodeValid.markMostDerived} for any {@link TreeNodeSchema} if it needed.
|
|
761
|
+
*/
|
|
762
|
+
export function markSchemaMostDerived(schema: TreeNodeSchema): void {
|
|
763
|
+
if (schema instanceof LeafNodeSchema) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
if (!inPrototypeChain(schema, TreeNodeValid)) {
|
|
768
|
+
// Use JSON.stringify to quote and escape identifier string.
|
|
769
|
+
throw new UsageError(
|
|
770
|
+
`Schema for ${JSON.stringify(
|
|
771
|
+
schema.identifier,
|
|
772
|
+
)} does not extend a SchemaFactory generated class. This is invalid.`,
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
(schema as typeof TreeNodeValid & TreeNodeSchema).markMostDerived();
|
|
777
|
+
}
|
|
@@ -67,6 +67,41 @@ export interface TreeNodeSchemaNonClass<
|
|
|
67
67
|
*
|
|
68
68
|
* Using classes in this way allows introducing a named type and a named value at the same time, helping keep the runtime and compile time information together and easy to refer to un a uniform way.
|
|
69
69
|
* Additionally, this works around https://github.com/microsoft/TypeScript/issues/55832 which causes similar patterns with less explicit types to infer "any" in the d.ts file.
|
|
70
|
+
*
|
|
71
|
+
* When sub-classing a a `TreeNodeSchemaClass`, some extra rules must be followed:
|
|
72
|
+
*
|
|
73
|
+
* - Only ever use a single class from the schema's class hierarchy within a document and its schema.
|
|
74
|
+
* For example, if using {@link SchemaFactory.object} you can do:
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // Recommended "customizable" object schema pattern.
|
|
77
|
+
* class Good extends schemaFactory.object("A", {
|
|
78
|
+
* exampleField: schemaFactory.number,
|
|
79
|
+
* }) {
|
|
80
|
+
* public exampleCustomMethod(): void {
|
|
81
|
+
* this.exampleField++;
|
|
82
|
+
* }
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
* But should avoid:
|
|
86
|
+
* ```typescript
|
|
87
|
+
* // This by itself is ok, and opts into "POJO mode".
|
|
88
|
+
* const base = schemaFactory.object("A", {});
|
|
89
|
+
* // This is a bad pattern since it leaves two classes in scope which derive from the same SchemaFactory defined class.
|
|
90
|
+
* // If both get used, its an error!
|
|
91
|
+
* class Invalid extends base {}
|
|
92
|
+
* ```
|
|
93
|
+
* - Do not modify the constructor input parameter types or values:
|
|
94
|
+
* ```typescript
|
|
95
|
+
* class Invalid extends schemaFactory.object("A", {
|
|
96
|
+
* exampleField: schemaFactory.number,
|
|
97
|
+
* }) {
|
|
98
|
+
* // This Modifies the type of the constructor input.
|
|
99
|
+
* // This is unsupported due to programmatic access to the constructor being used internally.
|
|
100
|
+
* public constructor(a: number) {
|
|
101
|
+
* super({ exampleField: a });
|
|
102
|
+
* }
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
70
105
|
* @sealed @public
|
|
71
106
|
*/
|
|
72
107
|
export interface TreeNodeSchemaClass<
|
|
@@ -81,7 +116,7 @@ export interface TreeNodeSchemaClass<
|
|
|
81
116
|
* Constructs an {@link Unhydrated} node with this schema.
|
|
82
117
|
* @remarks
|
|
83
118
|
* This constructor is also used internally to construct hydrated nodes with a different parameter type.
|
|
84
|
-
*
|
|
119
|
+
* Therefore, overriding this constructor with different argument types is not type-safe and is not supported.
|
|
85
120
|
* @sealed
|
|
86
121
|
*/
|
|
87
122
|
new (data: TInsertable | InternalTreeNode): Unhydrated<TNode>;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
/* eslint-disable import/no-internal-modules */
|
|
7
7
|
import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
8
|
+
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
8
9
|
|
|
9
10
|
import type {
|
|
10
11
|
ITreeCursorSynchronous,
|
|
@@ -75,8 +76,8 @@ export function cursorFromUnhydratedRoot(
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
interface SchemaInfo {
|
|
78
|
-
toFlex: () => FlexTreeNodeSchema;
|
|
79
|
-
original: TreeNodeSchema;
|
|
79
|
+
readonly toFlex: () => FlexTreeNodeSchema;
|
|
80
|
+
readonly original: TreeNodeSchema;
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
type SchemaMap = Map<TreeNodeSchemaIdentifier, SchemaInfo>;
|
|
@@ -180,8 +181,8 @@ export function convertNodeSchema(
|
|
|
180
181
|
const fromMap = schemaMap.get(brand(schema.identifier));
|
|
181
182
|
if (fromMap !== undefined) {
|
|
182
183
|
if (fromMap.original !== schema) {
|
|
183
|
-
// Use JSON.stringify to quote and escape string.
|
|
184
|
-
throw new
|
|
184
|
+
// Use JSON.stringify to quote and escape identifier string.
|
|
185
|
+
throw new UsageError(
|
|
185
186
|
`Multiple schema encountered with the identifier ${JSON.stringify(
|
|
186
187
|
schema.identifier,
|
|
187
188
|
)}. Remove or rename them to avoid the collision.`,
|
package/src/simple-tree/tree.ts
CHANGED
|
@@ -9,11 +9,20 @@ import type { CommitMetadata } from "../core/index.js";
|
|
|
9
9
|
import type { Listenable } from "../events/index.js";
|
|
10
10
|
import type { RevertibleFactory } from "../shared-tree/index.js";
|
|
11
11
|
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
import {
|
|
13
|
+
type ImplicitAllowedTypes,
|
|
14
|
+
NodeKind,
|
|
15
|
+
normalizeFieldSchema,
|
|
16
|
+
type ImplicitFieldSchema,
|
|
17
|
+
type InsertableTreeFieldFromImplicitField,
|
|
18
|
+
type TreeFieldFromImplicitField,
|
|
19
|
+
type TreeNodeSchema,
|
|
16
20
|
} from "./schemaTypes.js";
|
|
21
|
+
import { toFlexSchema } from "./toFlexSchema.js";
|
|
22
|
+
import { LeafNodeSchema } from "./leafNodeSchema.js";
|
|
23
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
24
|
+
import { isObjectNodeSchema } from "./objectNode.js";
|
|
25
|
+
import { markSchemaMostDerived } from "./schemaFactory.js";
|
|
17
26
|
|
|
18
27
|
/**
|
|
19
28
|
* Channel for a Fluid Tree DDS.
|
|
@@ -130,6 +139,58 @@ export class TreeViewConfiguration<TSchema extends ImplicitFieldSchema = Implici
|
|
|
130
139
|
const config = { ...defaultTreeConfigurationOptions, ...props };
|
|
131
140
|
this.schema = config.schema;
|
|
132
141
|
this.enableSchemaValidation = config.enableSchemaValidation;
|
|
142
|
+
|
|
143
|
+
// Ensure all reachable schema are marked as most derived.
|
|
144
|
+
// This ensures if multiple schema extending the same schema factory generated class are present (or have been constructed, or get constructed in the future),
|
|
145
|
+
// an error is reported.
|
|
146
|
+
walkFieldSchema(config.schema, markSchemaMostDerived);
|
|
147
|
+
// Eagerly perform this conversion to surface errors sooner.
|
|
148
|
+
toFlexSchema(config.schema);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function walkNodeSchema(
|
|
153
|
+
schema: TreeNodeSchema,
|
|
154
|
+
visitor: (schema: TreeNodeSchema) => void,
|
|
155
|
+
visitedSet: Set<TreeNodeSchema>,
|
|
156
|
+
): void {
|
|
157
|
+
if (visitedSet.has(schema)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
visitedSet.add(schema);
|
|
161
|
+
if (schema instanceof LeafNodeSchema) {
|
|
162
|
+
// nothing to do
|
|
163
|
+
} else if (isObjectNodeSchema(schema)) {
|
|
164
|
+
for (const field of schema.fields.values()) {
|
|
165
|
+
walkAllowedTypes(field.allowedTypeSet, visitor, visitedSet);
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
assert(schema.kind === NodeKind.Array || schema.kind === NodeKind.Map, "invalid schema");
|
|
169
|
+
const childTypes = schema.info as ImplicitAllowedTypes;
|
|
170
|
+
walkFieldSchema(childTypes, visitor, visitedSet);
|
|
171
|
+
}
|
|
172
|
+
// This visit is done at the end so the traversal order is most inner types first.
|
|
173
|
+
// This was picked since when fixing errors,
|
|
174
|
+
// working from the inner types out to the types that use them will probably go better than the reverse.
|
|
175
|
+
// This does not however ensure all types referenced by a type are visited before it, since in recursive cases thats impossible.
|
|
176
|
+
visitor(schema);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function walkFieldSchema(
|
|
180
|
+
schema: ImplicitFieldSchema,
|
|
181
|
+
visitor: (schema: TreeNodeSchema) => void,
|
|
182
|
+
visitedSet: Set<TreeNodeSchema> = new Set(),
|
|
183
|
+
): void {
|
|
184
|
+
walkAllowedTypes(normalizeFieldSchema(schema).allowedTypeSet, visitor, visitedSet);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function walkAllowedTypes(
|
|
188
|
+
allowedTypes: Iterable<TreeNodeSchema>,
|
|
189
|
+
visitor: (schema: TreeNodeSchema) => void,
|
|
190
|
+
visitedSet: Set<TreeNodeSchema>,
|
|
191
|
+
): void {
|
|
192
|
+
for (const childType of allowedTypes) {
|
|
193
|
+
walkNodeSchema(childType, visitor, visitedSet);
|
|
133
194
|
}
|
|
134
195
|
}
|
|
135
196
|
|
|
@@ -7,11 +7,11 @@ import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
|
7
7
|
|
|
8
8
|
import { Multiplicity, rootFieldKey } from "../core/index.js";
|
|
9
9
|
import {
|
|
10
|
-
FieldKinds,
|
|
11
10
|
type LazyItem,
|
|
12
11
|
type TreeStatus,
|
|
13
12
|
isLazy,
|
|
14
13
|
isTreeValue,
|
|
14
|
+
FlexObjectNodeSchema,
|
|
15
15
|
} from "../feature-libraries/index.js";
|
|
16
16
|
import { fail, extractFromOpaque, isReadonlyArray } from "../util/index.js";
|
|
17
17
|
|
|
@@ -201,26 +201,26 @@ export const treeNodeApi: TreeNodeApi = {
|
|
|
201
201
|
},
|
|
202
202
|
shortId(node: TreeNode): number | string | undefined {
|
|
203
203
|
const flexNode = getFlexNode(node);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const identifier =
|
|
204
|
+
const flexSchema = flexNode.schema;
|
|
205
|
+
const identifierFieldKeys =
|
|
206
|
+
flexSchema instanceof FlexObjectNodeSchema ? flexSchema.identifierFieldKeys : [];
|
|
207
|
+
|
|
208
|
+
switch (identifierFieldKeys.length) {
|
|
209
|
+
case 0:
|
|
210
|
+
return undefined;
|
|
211
|
+
case 1: {
|
|
212
|
+
const identifier = flexNode.tryGetField(identifierFieldKeys[0])?.boxedAt(0);
|
|
213
213
|
assert(identifier !== undefined, 0x927 /* The identifier must exist */);
|
|
214
214
|
const identifierValue = identifier.value as string;
|
|
215
215
|
const localNodeKey =
|
|
216
216
|
identifier.context.nodeKeyManager.tryLocalizeNodeKey(identifierValue);
|
|
217
|
-
|
|
218
|
-
shortId =
|
|
219
|
-
localNodeKey !== undefined ? extractFromOpaque(localNodeKey) : identifierValue;
|
|
217
|
+
return localNodeKey !== undefined ? extractFromOpaque(localNodeKey) : identifierValue;
|
|
220
218
|
}
|
|
219
|
+
default:
|
|
220
|
+
throw new UsageError(
|
|
221
|
+
"shortId() may not be called on a node with more than one identifier. Consider converting extraneous identifier fields to string fields.",
|
|
222
|
+
);
|
|
221
223
|
}
|
|
222
|
-
|
|
223
|
-
return shortId;
|
|
224
224
|
},
|
|
225
225
|
};
|
|
226
226
|
|
package/src/simple-tree/types.ts
CHANGED
|
@@ -208,51 +208,65 @@ export abstract class TreeNodeValid<TInput> extends TreeNode {
|
|
|
208
208
|
* Also used to detect if oneTimeSetup has run.
|
|
209
209
|
*
|
|
210
210
|
* @privateRemarks
|
|
211
|
-
* This defaults to
|
|
211
|
+
* This defaults to "default", which is used to trigger an error if not overridden in the derived class.
|
|
212
212
|
*
|
|
213
213
|
* The value of this on TreeNodeValid must only be overridden by base classes and never modified.
|
|
214
214
|
* Ways to enforce this immutability prevent it from being overridden,
|
|
215
215
|
* so code modifying constructorCached should be extra careful to avoid accidentally modifying the base/inherited value.
|
|
216
216
|
*/
|
|
217
|
-
protected static constructorCached:
|
|
217
|
+
protected static constructorCached: MostDerivedData | "default" | undefined = "default";
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Indicate that `this` is the most derived version of a schema, and thus the only one allowed to be used (other than by being subclassed a single time).
|
|
221
|
+
*/
|
|
222
|
+
public static markMostDerived(this: typeof TreeNodeValid & TreeNodeSchema): MostDerivedData {
|
|
223
|
+
assert(this.constructorCached !== "default", 0x95f /* invalid schema class */);
|
|
224
|
+
|
|
225
|
+
if (this.constructorCached === undefined) {
|
|
226
|
+
// Set the constructorCached on the layer of the prototype chain that declared it.
|
|
227
|
+
// This is necessary to ensure there is only one subclass of that type used:
|
|
228
|
+
// if constructorCached was simply set on `schema`,
|
|
229
|
+
// then a base classes between `schema` (exclusive) and where `constructorCached` is set (inclusive) and other subclasses of them
|
|
230
|
+
// would not see the stored `constructorCached`, and the validation above against multiple derived classes would not work.
|
|
231
|
+
|
|
232
|
+
// This is not just an alias of `this`, but a reference to the item in the prototype chain being walked, which happens to start at `this`.
|
|
233
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
234
|
+
let schemaBase: typeof TreeNodeValid = this;
|
|
235
|
+
while (!Object.prototype.hasOwnProperty.call(schemaBase, "constructorCached")) {
|
|
236
|
+
schemaBase = Reflect.getPrototypeOf(schemaBase) as typeof TreeNodeValid;
|
|
237
|
+
}
|
|
238
|
+
assert(schemaBase.constructorCached === undefined, 0x962 /* overwriting wrong cache */);
|
|
239
|
+
schemaBase.constructorCached = { constructor: this, oneTimeInitialized: false };
|
|
240
|
+
assert(
|
|
241
|
+
this.constructorCached === schemaBase.constructorCached,
|
|
242
|
+
"Inheritance should work",
|
|
243
|
+
);
|
|
244
|
+
return this.constructorCached;
|
|
245
|
+
} else if (this.constructorCached.constructor === this) {
|
|
246
|
+
return this.constructorCached;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
throw new UsageError(
|
|
250
|
+
`Two schema classes were used (${this.name} and ${
|
|
251
|
+
this.constructorCached.constructor.name
|
|
252
|
+
}) which derived from the same SchemaFactory generated class (${JSON.stringify(
|
|
253
|
+
this.identifier,
|
|
254
|
+
)}). This is invalid.`,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
218
257
|
|
|
219
258
|
public constructor(input: TInput | InternalTreeNode) {
|
|
220
259
|
super();
|
|
221
260
|
const schema = this.constructor as typeof TreeNodeValid & TreeNodeSchema;
|
|
222
|
-
|
|
223
|
-
if (
|
|
224
|
-
if (schema.constructorCached !== undefined) {
|
|
225
|
-
assert(
|
|
226
|
-
schema.constructorCached !== TreeNodeValid,
|
|
227
|
-
0x960 /* Schema class schema must override static constructorCached member */,
|
|
228
|
-
);
|
|
229
|
-
throw new UsageError(
|
|
230
|
-
`Two schema classes were instantiated (${schema.name} and ${schema.constructorCached.name}) which derived from the same SchemaFactory generated class. This is invalid`,
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
261
|
+
const cache = schema.markMostDerived();
|
|
262
|
+
if (!cache.oneTimeInitialized) {
|
|
234
263
|
const flexSchema = getFlexSchema(schema);
|
|
235
264
|
assert(
|
|
236
265
|
tryGetSimpleNodeSchema(flexSchema) === schema,
|
|
237
266
|
0x961 /* Schema class not properly configured */,
|
|
238
267
|
);
|
|
239
268
|
schema.oneTimeSetup();
|
|
240
|
-
|
|
241
|
-
// This is necessary to ensure there is only one subclass of that type used:
|
|
242
|
-
// if constructorCached was simply set on `schema`,
|
|
243
|
-
// then a base classes between `schema` (exclusive) and where `constructorCached` is set (inclusive) and other subclasses of them
|
|
244
|
-
// would not see the stored `constructorCached`, and the validation above against multiple derived classes would not work.
|
|
245
|
-
{
|
|
246
|
-
let schemaBase: typeof TreeNodeValid = schema;
|
|
247
|
-
while (!Object.prototype.hasOwnProperty.call(schemaBase, "constructorCached")) {
|
|
248
|
-
schemaBase = Reflect.getPrototypeOf(schemaBase) as typeof TreeNodeValid;
|
|
249
|
-
}
|
|
250
|
-
assert(
|
|
251
|
-
schemaBase.constructorCached === undefined,
|
|
252
|
-
0x962 /* overwriting wrong cache */,
|
|
253
|
-
);
|
|
254
|
-
schemaBase.constructorCached = schema;
|
|
255
|
-
}
|
|
269
|
+
cache.oneTimeInitialized = true;
|
|
256
270
|
}
|
|
257
271
|
|
|
258
272
|
if (isTreeNode(input)) {
|
|
@@ -278,6 +292,22 @@ export abstract class TreeNodeValid<TInput> extends TreeNode {
|
|
|
278
292
|
// Class objects are functions (callable), so we need a strong way to distinguish between `schema` and `() => schema` when used as a `LazyItem`.
|
|
279
293
|
markEager(TreeNodeValid);
|
|
280
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Data cached about the most derived type in a schema's class hierarchy.
|
|
297
|
+
* @remarks
|
|
298
|
+
* The most derived type is the only one allowed to be referenced by other schema or constructed as a node.
|
|
299
|
+
* It has to be discovered lazily (when a node is constructed or when a {@link TreeViewConfiguration} is made),
|
|
300
|
+
* since JavaScript provides no way to find derived classes, or inject static class initialization time logic into base classes.
|
|
301
|
+
* Additionally since schema can reference other schema through lazy references which might be forward or recursive references,
|
|
302
|
+
* this can not be evaluated for one schema when referenced by another schema.
|
|
303
|
+
*
|
|
304
|
+
* See {@link TreeNodeValid.constructorCached} and {@link TreeNodeValid.markMostDerived}.
|
|
305
|
+
*/
|
|
306
|
+
export interface MostDerivedData {
|
|
307
|
+
readonly constructor: typeof TreeNodeValid & TreeNodeSchema;
|
|
308
|
+
oneTimeInitialized: boolean;
|
|
309
|
+
}
|
|
310
|
+
|
|
281
311
|
/**
|
|
282
312
|
* A node type internal to `@fluidframework/tree`.
|
|
283
313
|
* @remarks
|