@fluidframework/tree 2.62.0 → 2.63.0-359286
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 +4 -0
- package/api-report/tree.alpha.api.md +31 -5
- package/api-report/tree.beta.api.md +26 -0
- package/api-report/tree.legacy.beta.api.md +26 -0
- package/dist/alpha.d.ts +4 -3
- package/dist/beta.d.ts +3 -0
- package/dist/codec/codec.d.ts +32 -0
- package/dist/codec/codec.d.ts.map +1 -1
- package/dist/codec/codec.js +32 -1
- package/dist/codec/codec.js.map +1 -1
- package/dist/codec/index.d.ts +1 -1
- package/dist/codec/index.d.ts.map +1 -1
- package/dist/codec/index.js +3 -1
- package/dist/codec/index.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/schema-stored/index.d.ts +1 -1
- package/dist/core/schema-stored/index.d.ts.map +1 -1
- package/dist/core/schema-stored/index.js.map +1 -1
- package/dist/core/schema-stored/schema.d.ts +5 -7
- package/dist/core/schema-stored/schema.d.ts.map +1 -1
- package/dist/core/schema-stored/schema.js +3 -6
- package/dist/core/schema-stored/schema.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodecs.d.ts +4 -1
- package/dist/core/tree/detachedFieldIndexCodecs.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodecs.js +5 -1
- package/dist/core/tree/detachedFieldIndexCodecs.js.map +1 -1
- package/dist/core/tree/index.d.ts +1 -0
- package/dist/core/tree/index.d.ts.map +1 -1
- package/dist/core/tree/index.js +3 -1
- package/dist/core/tree/index.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +3 -2
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.js +5 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/format.d.ts +2 -0
- package/dist/feature-libraries/chunked-forest/codec/format.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/format.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/index.d.ts +2 -2
- package/dist/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/index.js +2 -1
- package/dist/feature-libraries/chunked-forest/codec/index.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/index.d.ts +1 -1
- package/dist/feature-libraries/chunked-forest/index.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/index.js +2 -1
- package/dist/feature-libraries/chunked-forest/index.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts +5 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js +19 -5
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/dist/feature-libraries/default-schema/index.d.ts +1 -1
- package/dist/feature-libraries/default-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/index.js +2 -1
- package/dist/feature-libraries/default-schema/index.js.map +1 -1
- package/dist/feature-libraries/forest-summary/codec.d.ts +4 -1
- package/dist/feature-libraries/forest-summary/codec.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/codec.js +5 -1
- package/dist/feature-libraries/forest-summary/codec.js.map +1 -1
- package/dist/feature-libraries/forest-summary/index.d.ts +1 -0
- package/dist/feature-libraries/forest-summary/index.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/index.js +3 -1
- package/dist/feature-libraries/forest-summary/index.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +5 -5
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +7 -2
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/schema-edits/index.d.ts +1 -1
- package/dist/feature-libraries/schema-edits/index.d.ts.map +1 -1
- package/dist/feature-libraries/schema-edits/index.js +2 -1
- package/dist/feature-libraries/schema-edits/index.js.map +1 -1
- package/dist/feature-libraries/schema-edits/schemaChangeCodecs.d.ts +4 -1
- package/dist/feature-libraries/schema-edits/schemaChangeCodecs.d.ts.map +1 -1
- package/dist/feature-libraries/schema-edits/schemaChangeCodecs.js +9 -1
- package/dist/feature-libraries/schema-edits/schemaChangeCodecs.js.map +1 -1
- package/dist/feature-libraries/schema-index/codec.d.ts +2 -1
- package/dist/feature-libraries/schema-index/codec.d.ts.map +1 -1
- package/dist/feature-libraries/schema-index/codec.js +5 -1
- package/dist/feature-libraries/schema-index/codec.js.map +1 -1
- package/dist/feature-libraries/schema-index/index.d.ts +1 -1
- package/dist/feature-libraries/schema-index/index.d.ts.map +1 -1
- package/dist/feature-libraries/schema-index/index.js +2 -1
- package/dist/feature-libraries/schema-index/index.js.map +1 -1
- package/dist/legacy.d.ts +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/serializableDomainSchema.d.ts +12 -16
- package/dist/serializableDomainSchema.d.ts.map +1 -1
- package/dist/serializableDomainSchema.js +8 -8
- package/dist/serializableDomainSchema.js.map +1 -1
- package/dist/shared-tree/index.d.ts +2 -1
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js +4 -1
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +18 -2
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +122 -8
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.d.ts +17 -2
- package/dist/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.js +31 -18
- package/dist/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/defaultResubmitMachine.d.ts +7 -12
- package/dist/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
- package/dist/shared-tree-core/defaultResubmitMachine.js +53 -73
- package/dist/shared-tree-core/defaultResubmitMachine.js.map +1 -1
- package/dist/shared-tree-core/editManager.js +8 -4
- package/dist/shared-tree-core/editManager.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.d.ts +7 -4
- package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.js +42 -11
- package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/dist/shared-tree-core/index.d.ts +2 -1
- package/dist/shared-tree-core/index.d.ts.map +1 -1
- package/dist/shared-tree-core/index.js +6 -1
- package/dist/shared-tree-core/index.js.map +1 -1
- package/dist/shared-tree-core/messageCodecs.d.ts +7 -4
- package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecs.js +44 -23
- package/dist/shared-tree-core/messageCodecs.js.map +1 -1
- package/dist/shared-tree-core/resubmitMachine.d.ts +9 -18
- package/dist/shared-tree-core/resubmitMachine.d.ts.map +1 -1
- package/dist/shared-tree-core/resubmitMachine.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +6 -4
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +12 -13
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +7 -166
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.js +11 -44
- package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryBeta.d.ts +90 -1
- package/dist/simple-tree/api/schemaFactoryBeta.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryBeta.js +55 -0
- package/dist/simple-tree/api/schemaFactoryBeta.js.map +1 -1
- package/dist/simple-tree/api/treeBeta.d.ts +12 -2
- package/dist/simple-tree/api/treeBeta.d.ts.map +1 -1
- package/dist/simple-tree/api/treeBeta.js +6 -0
- package/dist/simple-tree/api/treeBeta.js.map +1 -1
- package/dist/simple-tree/api/typesUnsafe.d.ts +1 -1
- package/dist/simple-tree/api/typesUnsafe.js.map +1 -1
- package/dist/simple-tree/core/treeNode.d.ts +3 -2
- package/dist/simple-tree/core/treeNode.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNode.js +3 -2
- package/dist/simple-tree/core/treeNode.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNodeTypes.d.ts +2 -2
- package/dist/simple-tree/node-kinds/record/recordNodeTypes.js.map +1 -1
- package/dist/util/brand.d.ts +1 -1
- package/dist/util/brand.js.map +1 -1
- package/docs/main/compatibility.md +8 -0
- package/lib/alpha.d.ts +4 -3
- package/lib/beta.d.ts +3 -0
- package/lib/codec/codec.d.ts +32 -0
- package/lib/codec/codec.d.ts.map +1 -1
- package/lib/codec/codec.js +28 -0
- package/lib/codec/codec.js.map +1 -1
- package/lib/codec/index.d.ts +1 -1
- package/lib/codec/index.d.ts.map +1 -1
- package/lib/codec/index.js +1 -1
- package/lib/codec/index.js.map +1 -1
- package/lib/core/index.d.ts +2 -2
- 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/schema-stored/index.d.ts +1 -1
- package/lib/core/schema-stored/index.d.ts.map +1 -1
- package/lib/core/schema-stored/index.js.map +1 -1
- package/lib/core/schema-stored/schema.d.ts +5 -7
- package/lib/core/schema-stored/schema.d.ts.map +1 -1
- package/lib/core/schema-stored/schema.js +3 -6
- package/lib/core/schema-stored/schema.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodecs.d.ts +4 -1
- package/lib/core/tree/detachedFieldIndexCodecs.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodecs.js +3 -0
- package/lib/core/tree/detachedFieldIndexCodecs.js.map +1 -1
- package/lib/core/tree/index.d.ts +1 -0
- package/lib/core/tree/index.d.ts.map +1 -1
- package/lib/core/tree/index.js +1 -0
- package/lib/core/tree/index.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +3 -2
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.js +3 -0
- package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/format.d.ts +2 -0
- package/lib/feature-libraries/chunked-forest/codec/format.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/format.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/index.d.ts +2 -2
- package/lib/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/index.js +1 -1
- package/lib/feature-libraries/chunked-forest/codec/index.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/index.d.ts +1 -1
- package/lib/feature-libraries/chunked-forest/index.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/index.js +1 -1
- package/lib/feature-libraries/chunked-forest/index.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts +5 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js +17 -4
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/lib/feature-libraries/default-schema/index.d.ts +1 -1
- package/lib/feature-libraries/default-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/index.js +1 -1
- package/lib/feature-libraries/default-schema/index.js.map +1 -1
- package/lib/feature-libraries/forest-summary/codec.d.ts +4 -1
- package/lib/feature-libraries/forest-summary/codec.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/codec.js +3 -0
- package/lib/feature-libraries/forest-summary/codec.js.map +1 -1
- package/lib/feature-libraries/forest-summary/index.d.ts +1 -0
- package/lib/feature-libraries/forest-summary/index.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/index.js +1 -0
- package/lib/feature-libraries/forest-summary/index.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +5 -5
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +5 -5
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/schema-edits/index.d.ts +1 -1
- package/lib/feature-libraries/schema-edits/index.d.ts.map +1 -1
- package/lib/feature-libraries/schema-edits/index.js +1 -1
- package/lib/feature-libraries/schema-edits/index.js.map +1 -1
- package/lib/feature-libraries/schema-edits/schemaChangeCodecs.d.ts +4 -1
- package/lib/feature-libraries/schema-edits/schemaChangeCodecs.d.ts.map +1 -1
- package/lib/feature-libraries/schema-edits/schemaChangeCodecs.js +8 -1
- package/lib/feature-libraries/schema-edits/schemaChangeCodecs.js.map +1 -1
- package/lib/feature-libraries/schema-index/codec.d.ts +2 -1
- package/lib/feature-libraries/schema-index/codec.d.ts.map +1 -1
- package/lib/feature-libraries/schema-index/codec.js +3 -0
- package/lib/feature-libraries/schema-index/codec.js.map +1 -1
- package/lib/feature-libraries/schema-index/index.d.ts +1 -1
- package/lib/feature-libraries/schema-index/index.d.ts.map +1 -1
- package/lib/feature-libraries/schema-index/index.js +1 -1
- package/lib/feature-libraries/schema-index/index.js.map +1 -1
- package/lib/legacy.d.ts +3 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/serializableDomainSchema.d.ts +12 -16
- package/lib/serializableDomainSchema.d.ts.map +1 -1
- package/lib/serializableDomainSchema.js +9 -9
- package/lib/serializableDomainSchema.js.map +1 -1
- package/lib/shared-tree/index.d.ts +2 -1
- package/lib/shared-tree/index.d.ts.map +1 -1
- package/lib/shared-tree/index.js +2 -1
- package/lib/shared-tree/index.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +18 -2
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +126 -13
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.d.ts +17 -2
- package/lib/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.js +30 -18
- package/lib/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/defaultResubmitMachine.d.ts +7 -12
- package/lib/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
- package/lib/shared-tree-core/defaultResubmitMachine.js +55 -75
- package/lib/shared-tree-core/defaultResubmitMachine.js.map +1 -1
- package/lib/shared-tree-core/editManager.js +8 -4
- package/lib/shared-tree-core/editManager.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.d.ts +7 -4
- package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.js +40 -10
- package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/lib/shared-tree-core/index.d.ts +2 -1
- package/lib/shared-tree-core/index.d.ts.map +1 -1
- package/lib/shared-tree-core/index.js +2 -1
- package/lib/shared-tree-core/index.js.map +1 -1
- package/lib/shared-tree-core/messageCodecs.d.ts +7 -4
- package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/messageCodecs.js +42 -22
- package/lib/shared-tree-core/messageCodecs.js.map +1 -1
- package/lib/shared-tree-core/resubmitMachine.d.ts +9 -18
- package/lib/shared-tree-core/resubmitMachine.d.ts.map +1 -1
- package/lib/shared-tree-core/resubmitMachine.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +6 -4
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +13 -14
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts +7 -166
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.js +12 -45
- package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryBeta.d.ts +90 -1
- package/lib/simple-tree/api/schemaFactoryBeta.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryBeta.js +56 -1
- package/lib/simple-tree/api/schemaFactoryBeta.js.map +1 -1
- package/lib/simple-tree/api/treeBeta.d.ts +12 -2
- package/lib/simple-tree/api/treeBeta.d.ts.map +1 -1
- package/lib/simple-tree/api/treeBeta.js +7 -1
- package/lib/simple-tree/api/treeBeta.js.map +1 -1
- package/lib/simple-tree/api/typesUnsafe.d.ts +1 -1
- package/lib/simple-tree/api/typesUnsafe.js.map +1 -1
- package/lib/simple-tree/core/treeNode.d.ts +3 -2
- package/lib/simple-tree/core/treeNode.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNode.js +3 -2
- package/lib/simple-tree/core/treeNode.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNodeTypes.d.ts +2 -2
- package/lib/simple-tree/node-kinds/record/recordNodeTypes.js.map +1 -1
- package/lib/util/brand.d.ts +1 -1
- package/lib/util/brand.js.map +1 -1
- package/package.json +21 -21
- package/src/codec/codec.ts +60 -0
- package/src/codec/index.ts +3 -0
- package/src/core/index.ts +3 -0
- package/src/core/schema-stored/index.ts +1 -0
- package/src/core/schema-stored/schema.ts +5 -6
- package/src/core/tree/detachedFieldIndexCodecs.ts +9 -0
- package/src/core/tree/index.ts +6 -0
- package/src/feature-libraries/chunked-forest/codec/codecs.ts +6 -1
- package/src/feature-libraries/chunked-forest/codec/format.ts +2 -0
- package/src/feature-libraries/chunked-forest/codec/index.ts +2 -1
- package/src/feature-libraries/chunked-forest/index.ts +2 -0
- package/src/feature-libraries/default-schema/defaultFieldKinds.ts +29 -5
- package/src/feature-libraries/default-schema/index.ts +2 -0
- package/src/feature-libraries/forest-summary/codec.ts +7 -0
- package/src/feature-libraries/forest-summary/index.ts +1 -0
- package/src/feature-libraries/index.ts +12 -1
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +1 -1
- package/src/feature-libraries/schema-edits/index.ts +5 -1
- package/src/feature-libraries/schema-edits/schemaChangeCodecs.ts +17 -1
- package/src/feature-libraries/schema-index/codec.ts +5 -0
- package/src/feature-libraries/schema-index/index.ts +1 -0
- package/src/packageVersion.ts +1 -1
- package/src/serializableDomainSchema.ts +12 -11
- package/src/shared-tree/index.ts +6 -0
- package/src/shared-tree/sharedTree.ts +151 -11
- package/src/shared-tree/sharedTreeChangeCodecs.ts +68 -30
- package/src/shared-tree/treeCheckout.ts +1 -1
- package/src/shared-tree-core/defaultResubmitMachine.ts +77 -120
- package/src/shared-tree-core/editManager.ts +10 -4
- package/src/shared-tree-core/editManagerCodecs.ts +62 -9
- package/src/shared-tree-core/index.ts +12 -1
- package/src/shared-tree-core/messageCodecs.ts +70 -27
- package/src/shared-tree-core/resubmitMachine.ts +12 -20
- package/src/shared-tree-core/sharedTreeCore.ts +26 -18
- package/src/simple-tree/api/schemaFactoryAlpha.ts +16 -296
- package/src/simple-tree/api/schemaFactoryBeta.ts +269 -1
- package/src/simple-tree/api/treeBeta.ts +36 -1
- package/src/simple-tree/api/typesUnsafe.ts +1 -1
- package/src/simple-tree/core/treeNode.ts +3 -2
- package/src/simple-tree/core/treeNodeKernel.ts +1 -1
- package/src/simple-tree/node-kinds/record/recordNodeTypes.ts +2 -2
- package/src/util/brand.ts +1 -1
|
@@ -11,14 +11,11 @@ import {
|
|
|
11
11
|
type ObjectNodeSchema,
|
|
12
12
|
objectSchema,
|
|
13
13
|
type RecordNodeCustomizableSchema,
|
|
14
|
-
type RecordNodeInsertableData,
|
|
15
14
|
recordSchema,
|
|
16
|
-
type TreeRecordNode,
|
|
17
15
|
} from "../node-kinds/index.js";
|
|
18
16
|
import {
|
|
19
17
|
defaultSchemaFactoryObjectOptions,
|
|
20
18
|
scoped,
|
|
21
|
-
structuralName,
|
|
22
19
|
type NodeSchemaOptionsAlpha,
|
|
23
20
|
type SchemaFactoryObjectOptions,
|
|
24
21
|
type ScopedSchemaName,
|
|
@@ -29,14 +26,12 @@ import type { RestrictiveStringRecord } from "../../util/index.js";
|
|
|
29
26
|
import type {
|
|
30
27
|
NodeKind,
|
|
31
28
|
TreeNodeSchema,
|
|
32
|
-
TreeNodeSchemaBoth,
|
|
33
29
|
TreeNodeSchemaClass,
|
|
34
|
-
TreeNodeSchemaNonClass,
|
|
35
|
-
WithType,
|
|
36
30
|
ImplicitAllowedTypes,
|
|
37
31
|
ImplicitAnnotatedAllowedTypes,
|
|
38
32
|
AnnotatedAllowedType,
|
|
39
33
|
LazyItem,
|
|
34
|
+
WithType,
|
|
40
35
|
} from "../core/index.js";
|
|
41
36
|
import { normalizeToAnnotatedAllowedType, createSchemaUpgrade } from "../core/index.js";
|
|
42
37
|
import type {
|
|
@@ -48,7 +43,7 @@ import type {
|
|
|
48
43
|
import type { SimpleObjectNodeSchema } from "../simpleSchema.js";
|
|
49
44
|
import { SchemaFactoryBeta } from "./schemaFactoryBeta.js";
|
|
50
45
|
|
|
51
|
-
//
|
|
46
|
+
// These imports prevent a large number of type references in the API reports from showing up as *_2.
|
|
52
47
|
/* eslint-disable unused-imports/no-unused-imports, @typescript-eslint/no-unused-vars, import/no-duplicates */
|
|
53
48
|
import type {
|
|
54
49
|
FieldProps,
|
|
@@ -73,8 +68,9 @@ export interface SchemaStaticsAlpha {
|
|
|
73
68
|
* Declares a staged type in a set of {@link AllowedTypes}.
|
|
74
69
|
*
|
|
75
70
|
* @remarks
|
|
76
|
-
* Staged allowed types add support for loading documents which may
|
|
71
|
+
* Staged allowed types add support for loading documents which may contain that type at the declared location.
|
|
77
72
|
* This allows for an incremental rollout of a schema change to add a {@link TreeNodeSchema} to an {@link AllowedTypes} without breaking cross version collaboration.
|
|
73
|
+
* A guide on this process can be found here: https://fluidframework.com/docs/data-structures/tree/schema-evolution/allowed-types-rollout
|
|
78
74
|
*
|
|
79
75
|
* Once enough clients have the type staged (and thus can read documents which allow it), documents can start being created and upgraded to allow the staged type.
|
|
80
76
|
* This is done by deploying a new version of the app which removes the `staged` wrapper around the allowed type in the the schema definition.
|
|
@@ -85,107 +81,17 @@ export interface SchemaStaticsAlpha {
|
|
|
85
81
|
* 1. {@link TreeView.initialize} will omit the staged allowed type from the newly created stored schema.
|
|
86
82
|
* 2. {@link TreeView.upgradeSchema} will omit the staged allowed type from the the upgraded stored schema.
|
|
87
83
|
* 3. When evaluating {@link TreeView.compatibility}, it will be viewable even if the staged allowed type is not present in the stored schema's corresponding allowed types.
|
|
88
|
-
* 4. Because of the above, it is possible to get errors when inserting content which uses the staged allowed type
|
|
84
|
+
* 4. Because of the above, it is possible to get errors when inserting content which uses the staged allowed type into a tree whose stored schema does not permit it.
|
|
89
85
|
*
|
|
90
86
|
* Currently, `staged` is not supported in the recursive type APIs: this is a known limitation which future versions of the API will address.
|
|
91
87
|
*
|
|
92
88
|
* @example
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* The first change is to used to mark the new type as staged, replacing `A` in the schema with `[A, SchemaStaticsAlpha.staged(B)]`.
|
|
96
|
-
* Once this is done, and any code which reads contents from documents is updated to handle any `B` content that may be present, this version of the code can be deployed.
|
|
97
|
-
*
|
|
98
|
-
* Once all users have the above changes, the schema can be updated again to `[A, B]`, and the app can be updated to allow creating of `B` content.
|
|
99
|
-
* This updated version of the app will need to call {@link TreeView.upgradeSchema} when opening documents created by earlier versions.
|
|
100
|
-
*
|
|
101
|
-
* Adding a `B` schema as an option in the root could look like this:
|
|
102
|
-
* ```typescript
|
|
103
|
-
* const factory = new SchemaFactoryAlpha("test");
|
|
104
|
-
* class A extends factory.objectAlpha("A", {}) {}
|
|
105
|
-
* class B extends factory.objectAlpha("B", {}) {}
|
|
106
|
-
*
|
|
107
|
-
* // Does not support B
|
|
108
|
-
* const configBefore = new TreeViewConfigurationAlpha({
|
|
109
|
-
* schema: A,
|
|
110
|
-
* });
|
|
111
|
-
*
|
|
112
|
-
* // Supports documents with or without B
|
|
113
|
-
* const configStaged = new TreeViewConfigurationAlpha({
|
|
114
|
-
* // Adds staged support for B.
|
|
115
|
-
* // Currently this requires wrapping the root field with `SchemaFactoryAlpha.required`:
|
|
116
|
-
* // this is normally implicitly included, but is currently required while the "staged" APIs are `@alpha`.
|
|
117
|
-
* schema: SchemaFactoryAlpha.required([A, SchemaFactoryAlpha.staged(B)]),
|
|
118
|
-
* });
|
|
119
|
-
*
|
|
120
|
-
* // Only supports documents with A and B: can be used to upgrade schema to add B.
|
|
121
|
-
* const configAfter = new TreeViewConfigurationAlpha({
|
|
122
|
-
* schema: [A, B],
|
|
123
|
-
* });
|
|
124
|
-
* ```
|
|
125
|
-
* @example
|
|
126
|
-
* Below is a full example of how the schema migration process works.
|
|
127
|
-
* This can also be found in our {@link https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/src/test/simple-tree/api/stagedSchemaUpgrade.spec.ts | tests}.
|
|
128
|
-
* ```typescript
|
|
129
|
-
* // Schema A: only number allowed
|
|
130
|
-
* const schemaA = SchemaFactoryAlpha.optional([SchemaFactoryAlpha.number]);
|
|
131
|
-
*
|
|
132
|
-
* // Schema B: number or string (string is staged)
|
|
133
|
-
* const schemaB = SchemaFactoryAlpha.optional([
|
|
134
|
-
* SchemaFactoryAlpha.number,
|
|
135
|
-
* SchemaFactoryAlpha.staged(SchemaFactoryAlpha.string),
|
|
136
|
-
* ]);
|
|
89
|
+
* A full code example of the schema migration process can be found in our {@link https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/src/test/simple-tree/api/stagedSchemaUpgrade.spec.ts | tests}.
|
|
137
90
|
*
|
|
138
|
-
* // Schema C: number or string, both fully allowed
|
|
139
|
-
* const schemaC = SchemaFactoryAlpha.optional([
|
|
140
|
-
* SchemaFactoryAlpha.number,
|
|
141
|
-
* SchemaFactoryAlpha.string,
|
|
142
|
-
* ]);
|
|
143
|
-
*
|
|
144
|
-
* // Initialize with schema A.
|
|
145
|
-
* const configA = new TreeViewConfiguration({
|
|
146
|
-
* schema: schemaA,
|
|
147
|
-
* });
|
|
148
|
-
* const viewA = treeA.viewWith(configA);
|
|
149
|
-
* viewA.initialize(5);
|
|
150
|
-
*
|
|
151
|
-
* // Since we are running all the different versions of the app in the same process making changes synchronously,
|
|
152
|
-
* // an explicit flush is needed to make them available to each other.
|
|
153
|
-
* synchronizeTrees();
|
|
154
|
-
*
|
|
155
|
-
* assert.deepEqual(viewA.root, 5);
|
|
156
|
-
*
|
|
157
|
-
* // View the same document with a second tree using schema B.
|
|
158
|
-
* const configB = new TreeViewConfiguration({
|
|
159
|
-
* schema: schemaB,
|
|
160
|
-
* });
|
|
161
|
-
* const viewB = treeB.viewWith(configB);
|
|
162
|
-
* // B cannot write strings to the root.
|
|
163
|
-
* assert.throws(() => (viewB.root = "test"));
|
|
164
|
-
*
|
|
165
|
-
* // View the same document with a third tree using schema C.
|
|
166
|
-
* const configC = new TreeViewConfiguration({
|
|
167
|
-
* schema: schemaC,
|
|
168
|
-
* });
|
|
169
|
-
* const viewC = treeC.viewWith(configC);
|
|
170
|
-
* // Upgrade to schema C
|
|
171
|
-
* viewC.upgradeSchema();
|
|
172
|
-
* // Use the newly enabled schema.
|
|
173
|
-
* viewC.root = "test";
|
|
174
|
-
*
|
|
175
|
-
* synchronizeTrees();
|
|
176
|
-
*
|
|
177
|
-
* // View A is now incompatible with the stored schema:
|
|
178
|
-
* assert.equal(viewA.compatibility.canView, false);
|
|
179
|
-
*
|
|
180
|
-
* // View B can still read the document, and now sees the string root which relies on the staged schema.
|
|
181
|
-
* assert.deepEqual(viewB.root, "test");
|
|
182
|
-
* ```
|
|
183
91
|
* @privateRemarks
|
|
184
92
|
* TODO:#44317 staged allowed types rely on schema validation of stored schema to output errors, these errors are not very
|
|
185
93
|
* user friendly and should be improved, particularly in the case of staged allowed types
|
|
186
94
|
*
|
|
187
|
-
* TODO: the example above does not work tell in intellisense: its formatted to work onm the website. We should find a solution that works well for both.
|
|
188
|
-
*
|
|
189
95
|
* TODO: AB#45711: Update the docs above when recursive type support is added.
|
|
190
96
|
*/
|
|
191
97
|
staged: <const T extends LazyItem<TreeNodeSchema>>(
|
|
@@ -485,193 +391,6 @@ export class SchemaFactoryAlpha<
|
|
|
485
391
|
>;
|
|
486
392
|
}
|
|
487
393
|
|
|
488
|
-
/**
|
|
489
|
-
* Define a structurally typed {@link TreeNodeSchema} for a {@link (TreeRecordNode:interface)}.
|
|
490
|
-
*
|
|
491
|
-
* @param allowedTypes - The types that may appear in the record.
|
|
492
|
-
*
|
|
493
|
-
* @remarks
|
|
494
|
-
* The identifier for this record is defined as a function of the provided types.
|
|
495
|
-
* It is still scoped to this `SchemaFactory`, but multiple calls with the same arguments will return the same
|
|
496
|
-
* schema object, providing somewhat structural typing.
|
|
497
|
-
* This does not support recursive types.
|
|
498
|
-
*
|
|
499
|
-
* If using these structurally named records, other types in this schema builder should avoid names of the form `Record<${string}>`.
|
|
500
|
-
*
|
|
501
|
-
* @example
|
|
502
|
-
* The returned schema should be used as a schema directly:
|
|
503
|
-
* ```typescript
|
|
504
|
-
* const MyRecord = factory.record(factory.number);
|
|
505
|
-
* type MyRecord = NodeFromSchema<typeof Record>;
|
|
506
|
-
* ```
|
|
507
|
-
* Or inline:
|
|
508
|
-
* ```typescript
|
|
509
|
-
* factory.object("Foo", { myRecord: factory.record(factory.number) });
|
|
510
|
-
* ```
|
|
511
|
-
*
|
|
512
|
-
* @privateRemarks
|
|
513
|
-
* The name produced at the type-level here is not as specific as it could be; however, doing type-level sorting and escaping is a real mess.
|
|
514
|
-
* There are cases where not having this full type provided will be less than ideal, since TypeScript's structural types will allow assignment between runtime incompatible types at compile time.
|
|
515
|
-
* For example, attempts to narrow unions of structural records by name won't work.
|
|
516
|
-
* Planned future changes to move to a class based schema system as well as factor function based node construction should mostly avoid these issues,
|
|
517
|
-
* though there may still be some problematic cases even after that work is done.
|
|
518
|
-
*
|
|
519
|
-
* The return value is a class, but its type is intentionally not specific enough to indicate it is a class.
|
|
520
|
-
* This prevents callers of this from sub-classing it, which is unlikely to work well (due to the ease of accidentally giving two different calls to this different subclasses)
|
|
521
|
-
* when working with structural typing.
|
|
522
|
-
*
|
|
523
|
-
* {@label STRUCTURAL}
|
|
524
|
-
*/
|
|
525
|
-
public record<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(
|
|
526
|
-
allowedTypes: T,
|
|
527
|
-
): TreeNodeSchemaNonClass<
|
|
528
|
-
/* Name */ ScopedSchemaName<TScope, `Record<${string}>`>,
|
|
529
|
-
/* Kind */ NodeKind.Record,
|
|
530
|
-
/* TNode */ TreeRecordNode<T> &
|
|
531
|
-
WithType<ScopedSchemaName<TScope, `Record<${string}>`>, NodeKind.Record>,
|
|
532
|
-
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
533
|
-
/* ImplicitlyConstructable */ true,
|
|
534
|
-
/* Info */ T,
|
|
535
|
-
/* TConstructorExtra */ undefined
|
|
536
|
-
>;
|
|
537
|
-
/**
|
|
538
|
-
* Define (and add to this library) a {@link TreeNodeSchemaClass} for a {@link (TreeRecordNode:interface)}.
|
|
539
|
-
*
|
|
540
|
-
* @param name - Unique identifier for this schema within this factory's scope.
|
|
541
|
-
* @param allowedTypes - The types that may appear in the record.
|
|
542
|
-
*
|
|
543
|
-
* @remarks
|
|
544
|
-
* Like TypeScript `Record`s, record nodes have some potential pitfalls.
|
|
545
|
-
* For example: TypeScript makes assumptions about built-in keys being present (e.g. `toString`, `hasOwnProperty`, etc.).
|
|
546
|
-
* Since these are otherwise valid keys in a record, this can lead to unexpected behavior.
|
|
547
|
-
* To prevent inconsistent behavior, these built-ins are hidden by record nodes.
|
|
548
|
-
* This means that if you try to call these built-ins (e.g. `toString()`) on a record node, you will get an error.
|
|
549
|
-
*
|
|
550
|
-
* In most cases, it is probably preferable to use {@link SchemaFactory.(map:2)} instead.
|
|
551
|
-
*
|
|
552
|
-
* @example
|
|
553
|
-
* ```typescript
|
|
554
|
-
* class NamedRecord extends factory.record("name", factory.number) {}
|
|
555
|
-
* ```
|
|
556
|
-
*
|
|
557
|
-
* {@label NAMED}
|
|
558
|
-
*/
|
|
559
|
-
public record<const Name extends TName, const T extends ImplicitAllowedTypes>(
|
|
560
|
-
name: Name,
|
|
561
|
-
allowedTypes: T,
|
|
562
|
-
): TreeNodeSchemaClass<
|
|
563
|
-
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
564
|
-
/* Kind */ NodeKind.Record,
|
|
565
|
-
/* TNode */ TreeRecordNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Record>,
|
|
566
|
-
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
567
|
-
/* ImplicitlyConstructable */ true,
|
|
568
|
-
/* Info */ T,
|
|
569
|
-
/* TConstructorExtra */ undefined
|
|
570
|
-
>;
|
|
571
|
-
/**
|
|
572
|
-
* {@link SchemaFactory.array} implementation.
|
|
573
|
-
*
|
|
574
|
-
* @privateRemarks
|
|
575
|
-
* This should return TreeNodeSchemaBoth: see note on "map" implementation for details.
|
|
576
|
-
*/
|
|
577
|
-
public record<const T extends ImplicitAllowedTypes>(
|
|
578
|
-
nameOrAllowedTypes: TName | ((T & TreeNodeSchema) | readonly TreeNodeSchema[]),
|
|
579
|
-
maybeAllowedTypes?: T,
|
|
580
|
-
): TreeNodeSchema<
|
|
581
|
-
/* Name */ ScopedSchemaName<TScope, string>,
|
|
582
|
-
/* Kind */ NodeKind.Record,
|
|
583
|
-
/* TNode */ TreeRecordNode<T>,
|
|
584
|
-
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
585
|
-
/* ImplicitlyConstructable */ true,
|
|
586
|
-
/* Info */ T
|
|
587
|
-
> {
|
|
588
|
-
if (maybeAllowedTypes === undefined) {
|
|
589
|
-
const types = nameOrAllowedTypes as (T & TreeNodeSchema) | readonly TreeNodeSchema[];
|
|
590
|
-
const fullName = structuralName("Record", types);
|
|
591
|
-
return this.getStructuralType(fullName, types, () =>
|
|
592
|
-
this.namedRecord(
|
|
593
|
-
fullName,
|
|
594
|
-
nameOrAllowedTypes as T,
|
|
595
|
-
/* customizable */ false,
|
|
596
|
-
/* implicitlyConstructable */ true,
|
|
597
|
-
),
|
|
598
|
-
) as TreeNodeSchemaClass<
|
|
599
|
-
/* Name */ ScopedSchemaName<TScope, string>,
|
|
600
|
-
/* Kind */ NodeKind.Record,
|
|
601
|
-
/* TNode */ TreeRecordNode<T>,
|
|
602
|
-
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
603
|
-
/* ImplicitlyConstructable */ true,
|
|
604
|
-
/* Info */ T,
|
|
605
|
-
/* TConstructorExtra */ undefined
|
|
606
|
-
>;
|
|
607
|
-
}
|
|
608
|
-
const out: TreeNodeSchemaBoth<
|
|
609
|
-
/* Name */ ScopedSchemaName<TScope, string>,
|
|
610
|
-
/* Kind */ NodeKind.Record,
|
|
611
|
-
/* TNode */ TreeRecordNode<T>,
|
|
612
|
-
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
613
|
-
/* ImplicitlyConstructable */ true,
|
|
614
|
-
/* Info */ T,
|
|
615
|
-
/* TConstructorExtra */ undefined
|
|
616
|
-
> = this.namedRecord(
|
|
617
|
-
nameOrAllowedTypes as TName,
|
|
618
|
-
maybeAllowedTypes,
|
|
619
|
-
/* customizable */ true,
|
|
620
|
-
/* implicitlyConstructable */ true,
|
|
621
|
-
);
|
|
622
|
-
return out;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* Define a {@link TreeNodeSchema} for a {@link (TreeRecordNode:interface)}.
|
|
627
|
-
*
|
|
628
|
-
* @param name - Unique identifier for this schema within this factory's scope.
|
|
629
|
-
*
|
|
630
|
-
* @remarks
|
|
631
|
-
* This is not intended to be used directly, use the overload of `record` which takes a name instead.
|
|
632
|
-
*/
|
|
633
|
-
private namedRecord<
|
|
634
|
-
Name extends TName | string,
|
|
635
|
-
const T extends ImplicitAllowedTypes,
|
|
636
|
-
const ImplicitlyConstructable extends boolean,
|
|
637
|
-
const TCustomMetadata = unknown,
|
|
638
|
-
>(
|
|
639
|
-
name: Name,
|
|
640
|
-
allowedTypes: T,
|
|
641
|
-
customizable: boolean,
|
|
642
|
-
implicitlyConstructable: ImplicitlyConstructable,
|
|
643
|
-
options?: NodeSchemaOptionsAlpha<TCustomMetadata>,
|
|
644
|
-
): TreeNodeSchemaBoth<
|
|
645
|
-
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
646
|
-
/* Kind */ NodeKind.Record,
|
|
647
|
-
/* TNode */ TreeRecordNode<T> &
|
|
648
|
-
WithType<ScopedSchemaName<TScope, string>, NodeKind.Record>,
|
|
649
|
-
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
650
|
-
/* ImplicitlyConstructable */ ImplicitlyConstructable,
|
|
651
|
-
/* Info */ T,
|
|
652
|
-
/* TConstructorExtra */ undefined
|
|
653
|
-
> {
|
|
654
|
-
const record = recordSchema({
|
|
655
|
-
identifier: scoped<TScope, TName, Name>(this, name),
|
|
656
|
-
info: allowedTypes,
|
|
657
|
-
customizable,
|
|
658
|
-
implicitlyConstructable,
|
|
659
|
-
metadata: options?.metadata,
|
|
660
|
-
persistedMetadata: options?.persistedMetadata,
|
|
661
|
-
});
|
|
662
|
-
|
|
663
|
-
return record as TreeNodeSchemaBoth<
|
|
664
|
-
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
665
|
-
/* Kind */ NodeKind.Record,
|
|
666
|
-
/* TNode */ TreeRecordNode<T> &
|
|
667
|
-
WithType<ScopedSchemaName<TScope, string>, NodeKind.Record>,
|
|
668
|
-
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
669
|
-
/* ImplicitlyConstructable */ ImplicitlyConstructable,
|
|
670
|
-
/* Info */ T,
|
|
671
|
-
/* TConstructorExtra */ undefined
|
|
672
|
-
>;
|
|
673
|
-
}
|
|
674
|
-
|
|
675
394
|
/**
|
|
676
395
|
* Define (and add to this library) a {@link TreeNodeSchemaClass} for a {@link (TreeRecordNode:interface)}.
|
|
677
396
|
*
|
|
@@ -704,27 +423,28 @@ export class SchemaFactoryAlpha<
|
|
|
704
423
|
}
|
|
705
424
|
|
|
706
425
|
/**
|
|
707
|
-
* {@link
|
|
426
|
+
* {@link SchemaFactoryBeta.(record:2)} except tweaked to work better for recursive types.
|
|
708
427
|
* Use with {@link ValidateRecursiveSchema} for improved type safety.
|
|
709
428
|
* @remarks
|
|
710
429
|
* This version of `SchemaFactory.record` uses the same workarounds as {@link SchemaFactory.objectRecursive}.
|
|
711
430
|
* See {@link ValidateRecursiveSchema} for additional information about using recursive schema.
|
|
712
431
|
*/
|
|
713
432
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
714
|
-
public recordRecursive<
|
|
433
|
+
public override recordRecursive<
|
|
715
434
|
Name extends TName,
|
|
716
435
|
const T extends System_Unsafe.ImplicitAllowedTypesUnsafe,
|
|
717
436
|
const TCustomMetadata = unknown,
|
|
718
437
|
>(name: Name, allowedTypes: T, options?: NodeSchemaOptionsAlpha<TCustomMetadata>) {
|
|
719
|
-
const RecordSchema =
|
|
720
|
-
name,
|
|
721
|
-
allowedTypes as T & ImplicitAllowedTypes,
|
|
722
|
-
|
|
438
|
+
const RecordSchema = recordSchema({
|
|
439
|
+
identifier: scoped<TScope, TName, Name>(this, name),
|
|
440
|
+
info: allowedTypes as T & ImplicitAllowedTypes,
|
|
441
|
+
customizable: true,
|
|
723
442
|
// Setting this to true seems to work ok currently, but not for other node kinds.
|
|
724
443
|
// Supporting this could be fragile and might break other future changes, so it's being kept as false for now.
|
|
725
|
-
|
|
726
|
-
options,
|
|
727
|
-
|
|
444
|
+
implicitlyConstructable: false,
|
|
445
|
+
metadata: options?.metadata,
|
|
446
|
+
persistedMetadata: options?.persistedMetadata,
|
|
447
|
+
});
|
|
728
448
|
|
|
729
449
|
return RecordSchema as TreeNodeSchemaClass<
|
|
730
450
|
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
@@ -3,7 +3,41 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import type {
|
|
7
|
+
ImplicitAllowedTypes,
|
|
8
|
+
NodeKind,
|
|
9
|
+
TreeNodeSchema,
|
|
10
|
+
TreeNodeSchemaBoth,
|
|
11
|
+
TreeNodeSchemaClass,
|
|
12
|
+
TreeNodeSchemaNonClass,
|
|
13
|
+
WithType,
|
|
14
|
+
} from "../core/index.js";
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
recordSchema,
|
|
18
|
+
type RecordNodeInsertableData,
|
|
19
|
+
type TreeRecordNode,
|
|
20
|
+
} from "../node-kinds/index.js";
|
|
21
|
+
import {
|
|
22
|
+
SchemaFactory,
|
|
23
|
+
scoped,
|
|
24
|
+
structuralName,
|
|
25
|
+
type NodeSchemaOptions,
|
|
26
|
+
type ScopedSchemaName,
|
|
27
|
+
} from "./schemaFactory.js";
|
|
28
|
+
import type { System_Unsafe, TreeRecordNodeUnsafe } from "./typesUnsafe.js";
|
|
29
|
+
|
|
30
|
+
// These imports prevent a large number of type references in the API reports from showing up as *_2.
|
|
31
|
+
/* eslint-disable unused-imports/no-unused-imports, @typescript-eslint/no-unused-vars, import/no-duplicates */
|
|
32
|
+
import type {
|
|
33
|
+
FieldProps,
|
|
34
|
+
FieldSchemaAlpha,
|
|
35
|
+
FieldPropsAlpha,
|
|
36
|
+
FieldKind,
|
|
37
|
+
} from "../fieldSchema.js";
|
|
38
|
+
import type { LeafSchema } from "../leafNodeSchema.js";
|
|
39
|
+
import type { SimpleLeafNodeSchema } from "../simpleSchema.js";
|
|
40
|
+
/* eslint-enable unused-imports/no-unused-imports, @typescript-eslint/no-unused-vars, import/no-duplicates */
|
|
7
41
|
|
|
8
42
|
/**
|
|
9
43
|
* {@link SchemaFactory} with additional beta APIs.
|
|
@@ -25,4 +59,238 @@ export class SchemaFactoryBeta<
|
|
|
25
59
|
): SchemaFactoryBeta<ScopedSchemaName<TScope, T>, TNameInner> {
|
|
26
60
|
return new SchemaFactoryBeta(scoped(this, name));
|
|
27
61
|
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Define a structurally typed {@link TreeNodeSchema} for a {@link (TreeRecordNode:interface)}.
|
|
65
|
+
*
|
|
66
|
+
* @param allowedTypes - The types that may appear in the record.
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
* The identifier for this record is defined as a function of the provided types.
|
|
70
|
+
* It is still scoped to this `SchemaFactory`, but multiple calls with the same arguments will return the same
|
|
71
|
+
* schema object, providing somewhat structural typing.
|
|
72
|
+
* This does not support recursive types.
|
|
73
|
+
*
|
|
74
|
+
* If using these structurally named records, other types in this schema builder should avoid names of the form `Record<${string}>`.
|
|
75
|
+
*
|
|
76
|
+
* The underlying data format for `Record` nodes is the same as that for `Map` nodes.
|
|
77
|
+
* Therefore, changing an existing `Map` schema to a `Record` schema (or vice versa) is
|
|
78
|
+
* a non-breaking change and does not require schema migration.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* The returned schema should be used as a schema directly:
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const MyRecord = factory.record(factory.number);
|
|
84
|
+
* type MyRecord = NodeFromSchema<typeof Record>;
|
|
85
|
+
* ```
|
|
86
|
+
* Or inline:
|
|
87
|
+
* ```typescript
|
|
88
|
+
* factory.object("Foo", { myRecord: factory.record(factory.number) });
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @privateRemarks
|
|
92
|
+
* The name produced at the type-level here is not as specific as it could be; however, doing type-level sorting and escaping is a real mess.
|
|
93
|
+
* There are cases where not having this full type provided will be less than ideal, since TypeScript's structural types will allow assignment between runtime incompatible types at compile time.
|
|
94
|
+
* For example, attempts to narrow unions of structural records by name won't work.
|
|
95
|
+
* Planned future changes to move to a class based schema system as well as factor function based node construction should mostly avoid these issues,
|
|
96
|
+
* though there may still be some problematic cases even after that work is done.
|
|
97
|
+
*
|
|
98
|
+
* The return value is a class, but its type is intentionally not specific enough to indicate it is a class.
|
|
99
|
+
* This prevents callers of this from sub-classing it, which is unlikely to work well (due to the ease of accidentally giving two different calls to this different subclasses)
|
|
100
|
+
* when working with structural typing.
|
|
101
|
+
*
|
|
102
|
+
* {@label STRUCTURAL}
|
|
103
|
+
*/
|
|
104
|
+
public record<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(
|
|
105
|
+
allowedTypes: T,
|
|
106
|
+
): TreeNodeSchemaNonClass<
|
|
107
|
+
/* Name */ ScopedSchemaName<TScope, `Record<${string}>`>,
|
|
108
|
+
/* Kind */ NodeKind.Record,
|
|
109
|
+
/* TNode */ TreeRecordNode<T> &
|
|
110
|
+
WithType<ScopedSchemaName<TScope, `Record<${string}>`>, NodeKind.Record>,
|
|
111
|
+
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
112
|
+
/* ImplicitlyConstructable */ true,
|
|
113
|
+
/* Info */ T,
|
|
114
|
+
/* TConstructorExtra */ undefined
|
|
115
|
+
>;
|
|
116
|
+
/**
|
|
117
|
+
* Define (and add to this library) a {@link TreeNodeSchemaClass} for a {@link (TreeRecordNode:interface)}.
|
|
118
|
+
*
|
|
119
|
+
* @param name - Unique identifier for this schema within this factory's scope.
|
|
120
|
+
* @param allowedTypes - The types that may appear in the record.
|
|
121
|
+
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* The underlying data format for `Record` nodes is the same as that for `Map` nodes.
|
|
124
|
+
* Therefore, changing an existing `Map` schema to a `Record` schema (or vice versa) is
|
|
125
|
+
* a non-breaking change and does not require schema migration.
|
|
126
|
+
*
|
|
127
|
+
* Like TypeScript `Record`s, record nodes have some potential pitfalls.
|
|
128
|
+
* For example: TypeScript makes assumptions about built-in keys being present (e.g. `toString`, `hasOwnProperty`, etc.).
|
|
129
|
+
* Since these are otherwise valid keys in a record, this can lead to unexpected behavior.
|
|
130
|
+
* To prevent inconsistent behavior, these built-ins are hidden by record nodes.
|
|
131
|
+
* This means that if you try to call these built-ins (e.g. `toString()`) on a record node, you will get an error.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* class NamedRecord extends factory.record("name", factory.number) {}
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* {@label NAMED}
|
|
139
|
+
*/
|
|
140
|
+
public record<const Name extends TName, const T extends ImplicitAllowedTypes>(
|
|
141
|
+
name: Name,
|
|
142
|
+
allowedTypes: T,
|
|
143
|
+
): TreeNodeSchemaClass<
|
|
144
|
+
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
145
|
+
/* Kind */ NodeKind.Record,
|
|
146
|
+
/* TNode */ TreeRecordNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Record>,
|
|
147
|
+
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
148
|
+
/* ImplicitlyConstructable */ true,
|
|
149
|
+
/* Info */ T,
|
|
150
|
+
/* TConstructorExtra */ undefined
|
|
151
|
+
>;
|
|
152
|
+
/**
|
|
153
|
+
* {@link SchemaFactoryBeta.record} implementation.
|
|
154
|
+
*
|
|
155
|
+
* @privateRemarks
|
|
156
|
+
* This should return {@link TreeNodeSchemaBoth}: see note on {@link SchemaFactory.map} implementation for details.
|
|
157
|
+
*/
|
|
158
|
+
public record<const T extends ImplicitAllowedTypes>(
|
|
159
|
+
nameOrAllowedTypes: TName | ((T & TreeNodeSchema) | readonly TreeNodeSchema[]),
|
|
160
|
+
maybeAllowedTypes?: T,
|
|
161
|
+
): TreeNodeSchema<
|
|
162
|
+
/* Name */ ScopedSchemaName<TScope, string>,
|
|
163
|
+
/* Kind */ NodeKind.Record,
|
|
164
|
+
/* TNode */ TreeRecordNode<T>,
|
|
165
|
+
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
166
|
+
/* ImplicitlyConstructable */ true,
|
|
167
|
+
/* Info */ T
|
|
168
|
+
> {
|
|
169
|
+
if (maybeAllowedTypes === undefined) {
|
|
170
|
+
const types = nameOrAllowedTypes as (T & TreeNodeSchema) | readonly TreeNodeSchema[];
|
|
171
|
+
const fullName = structuralName("Record", types);
|
|
172
|
+
return this.getStructuralType(fullName, types, () =>
|
|
173
|
+
this.namedRecord(
|
|
174
|
+
fullName,
|
|
175
|
+
nameOrAllowedTypes as T,
|
|
176
|
+
/* customizable */ false,
|
|
177
|
+
/* implicitlyConstructable */ true,
|
|
178
|
+
),
|
|
179
|
+
) as TreeNodeSchemaClass<
|
|
180
|
+
/* Name */ ScopedSchemaName<TScope, string>,
|
|
181
|
+
/* Kind */ NodeKind.Record,
|
|
182
|
+
/* TNode */ TreeRecordNode<T>,
|
|
183
|
+
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
184
|
+
/* ImplicitlyConstructable */ true,
|
|
185
|
+
/* Info */ T,
|
|
186
|
+
/* TConstructorExtra */ undefined
|
|
187
|
+
>;
|
|
188
|
+
}
|
|
189
|
+
const out: TreeNodeSchemaBoth<
|
|
190
|
+
/* Name */ ScopedSchemaName<TScope, string>,
|
|
191
|
+
/* Kind */ NodeKind.Record,
|
|
192
|
+
/* TNode */ TreeRecordNode<T>,
|
|
193
|
+
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
194
|
+
/* ImplicitlyConstructable */ true,
|
|
195
|
+
/* Info */ T,
|
|
196
|
+
/* TConstructorExtra */ undefined
|
|
197
|
+
> = this.namedRecord(
|
|
198
|
+
nameOrAllowedTypes as TName,
|
|
199
|
+
maybeAllowedTypes,
|
|
200
|
+
/* customizable */ true,
|
|
201
|
+
/* implicitlyConstructable */ true,
|
|
202
|
+
);
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Define a {@link TreeNodeSchema} for a {@link (TreeRecordNode:interface)}.
|
|
208
|
+
*
|
|
209
|
+
* @param name - Unique identifier for this schema within this factory's scope.
|
|
210
|
+
*
|
|
211
|
+
* @remarks
|
|
212
|
+
* This is not intended to be used directly, use the overload of `record` which takes a name instead.
|
|
213
|
+
*/
|
|
214
|
+
private namedRecord<
|
|
215
|
+
Name extends TName | string,
|
|
216
|
+
const T extends ImplicitAllowedTypes,
|
|
217
|
+
const ImplicitlyConstructable extends boolean,
|
|
218
|
+
const TCustomMetadata = unknown,
|
|
219
|
+
>(
|
|
220
|
+
name: Name,
|
|
221
|
+
allowedTypes: T,
|
|
222
|
+
customizable: boolean,
|
|
223
|
+
implicitlyConstructable: ImplicitlyConstructable,
|
|
224
|
+
options?: NodeSchemaOptions<TCustomMetadata>,
|
|
225
|
+
): TreeNodeSchemaBoth<
|
|
226
|
+
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
227
|
+
/* Kind */ NodeKind.Record,
|
|
228
|
+
/* TNode */ TreeRecordNode<T> &
|
|
229
|
+
WithType<ScopedSchemaName<TScope, string>, NodeKind.Record>,
|
|
230
|
+
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
231
|
+
/* ImplicitlyConstructable */ ImplicitlyConstructable,
|
|
232
|
+
/* Info */ T,
|
|
233
|
+
/* TConstructorExtra */ undefined
|
|
234
|
+
> {
|
|
235
|
+
const record = recordSchema({
|
|
236
|
+
identifier: scoped<TScope, TName, Name>(this, name),
|
|
237
|
+
info: allowedTypes,
|
|
238
|
+
customizable,
|
|
239
|
+
implicitlyConstructable,
|
|
240
|
+
metadata: options?.metadata,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return record as TreeNodeSchemaBoth<
|
|
244
|
+
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
245
|
+
/* Kind */ NodeKind.Record,
|
|
246
|
+
/* TNode */ TreeRecordNode<T> &
|
|
247
|
+
WithType<ScopedSchemaName<TScope, string>, NodeKind.Record>,
|
|
248
|
+
/* TInsertable */ RecordNodeInsertableData<T>,
|
|
249
|
+
/* ImplicitlyConstructable */ ImplicitlyConstructable,
|
|
250
|
+
/* Info */ T,
|
|
251
|
+
/* TConstructorExtra */ undefined
|
|
252
|
+
>;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* {@link SchemaFactoryBeta.(record:2)} except tweaked to work better for recursive types.
|
|
257
|
+
* Use with {@link ValidateRecursiveSchema} for improved type safety.
|
|
258
|
+
* @remarks
|
|
259
|
+
* This version of `SchemaFactory.record` uses the same workarounds as {@link SchemaFactory.objectRecursive}.
|
|
260
|
+
* See {@link ValidateRecursiveSchema} for additional information about using recursive schema.
|
|
261
|
+
*/
|
|
262
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
263
|
+
public recordRecursive<
|
|
264
|
+
Name extends TName,
|
|
265
|
+
const T extends System_Unsafe.ImplicitAllowedTypesUnsafe,
|
|
266
|
+
const TCustomMetadata = unknown,
|
|
267
|
+
>(name: Name, allowedTypes: T, options?: NodeSchemaOptions<TCustomMetadata>) {
|
|
268
|
+
const RecordSchema = this.namedRecord(
|
|
269
|
+
name,
|
|
270
|
+
allowedTypes as T & ImplicitAllowedTypes,
|
|
271
|
+
/* customizable */ true,
|
|
272
|
+
// Setting this to true seems to work ok currently, but not for other node kinds.
|
|
273
|
+
// Supporting this could be fragile and might break other future changes, so it's being kept as false for now.
|
|
274
|
+
/* implicitlyConstructable */ false,
|
|
275
|
+
options,
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
return RecordSchema as TreeNodeSchemaClass<
|
|
279
|
+
/* Name */ ScopedSchemaName<TScope, Name>,
|
|
280
|
+
/* Kind */ NodeKind.Record,
|
|
281
|
+
/* TNode */ TreeRecordNodeUnsafe<T> &
|
|
282
|
+
WithType<ScopedSchemaName<TScope, Name>, NodeKind.Record>,
|
|
283
|
+
/* TInsertable */ {
|
|
284
|
+
// Ideally this would be
|
|
285
|
+
// RestrictiveStringRecord<InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>>,
|
|
286
|
+
// but doing so breaks recursive types.
|
|
287
|
+
// Instead we do a less nice version:
|
|
288
|
+
readonly [P in string]: System_Unsafe.InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>;
|
|
289
|
+
},
|
|
290
|
+
/* ImplicitlyConstructable */ false,
|
|
291
|
+
/* Info */ T,
|
|
292
|
+
/* TConstructorExtra */ undefined,
|
|
293
|
+
/* TCustomMetadata */ TCustomMetadata
|
|
294
|
+
>;
|
|
295
|
+
}
|
|
28
296
|
}
|