From 8e93b63a5c2dcb2b7d2ff41fd815bcab8d9fb3f3 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Tue, 4 Mar 2025 16:48:59 -0800 Subject: [PATCH] Add scopedFactory --- .changeset/grumpy-crabs-hide.md | 11 +++++++++++ packages/dds/tree/api-report/tree.alpha.api.md | 1 + packages/dds/tree/api-report/tree.beta.api.md | 1 + .../dds/tree/api-report/tree.legacy.alpha.api.md | 1 + .../dds/tree/api-report/tree.legacy.public.api.md | 1 + packages/dds/tree/api-report/tree.public.api.md | 1 + .../dds/tree/src/simple-tree/api/schemaFactory.ts | 12 ++++++++++++ .../simple-tree/api/schemaCreationUtilities.spec.ts | 12 ++++-------- .../api-report/fluid-framework.alpha.api.md | 1 + .../api-report/fluid-framework.beta.api.md | 1 + .../api-report/fluid-framework.legacy.alpha.api.md | 1 + .../api-report/fluid-framework.legacy.public.api.md | 1 + .../api-report/fluid-framework.public.api.md | 1 + 13 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 .changeset/grumpy-crabs-hide.md diff --git a/.changeset/grumpy-crabs-hide.md b/.changeset/grumpy-crabs-hide.md new file mode 100644 index 000000000000..2ee49e59be81 --- /dev/null +++ b/.changeset/grumpy-crabs-hide.md @@ -0,0 +1,11 @@ +--- +"fluid-framework": minor +"@fluidframework/tree": minor +--- +--- +"section": tree +--- + +Add `SchemaFactory.scopedFactory` + +Add `SchemaFactory.scopedFactory` method as an easy way to create a new `SchemaFactory` with a nested scope string. diff --git a/packages/dds/tree/api-report/tree.alpha.api.md b/packages/dds/tree/api-report/tree.alpha.api.md index ad81f1ba836e..8daa9a09fff0 100644 --- a/packages/dds/tree/api-report/tree.alpha.api.md +++ b/packages/dds/tree/api-report/tree.alpha.api.md @@ -692,6 +692,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/dds/tree/api-report/tree.beta.api.md b/packages/dds/tree/api-report/tree.beta.api.md index bd9eaa384d61..7f65268ae273 100644 --- a/packages/dds/tree/api-report/tree.beta.api.md +++ b/packages/dds/tree/api-report/tree.beta.api.md @@ -411,6 +411,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/dds/tree/api-report/tree.legacy.alpha.api.md b/packages/dds/tree/api-report/tree.legacy.alpha.api.md index 78e9288fabc1..41a82299d384 100644 --- a/packages/dds/tree/api-report/tree.legacy.alpha.api.md +++ b/packages/dds/tree/api-report/tree.legacy.alpha.api.md @@ -406,6 +406,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/dds/tree/api-report/tree.legacy.public.api.md b/packages/dds/tree/api-report/tree.legacy.public.api.md index 887541fa6fed..2b7d0c993b59 100644 --- a/packages/dds/tree/api-report/tree.legacy.public.api.md +++ b/packages/dds/tree/api-report/tree.legacy.public.api.md @@ -406,6 +406,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/dds/tree/api-report/tree.public.api.md b/packages/dds/tree/api-report/tree.public.api.md index 887541fa6fed..2b7d0c993b59 100644 --- a/packages/dds/tree/api-report/tree.public.api.md +++ b/packages/dds/tree/api-report/tree.public.api.md @@ -406,6 +406,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/dds/tree/src/simple-tree/api/schemaFactory.ts b/packages/dds/tree/src/simple-tree/api/schemaFactory.ts index 0a7ead94e5f3..5d48db41234d 100644 --- a/packages/dds/tree/src/simple-tree/api/schemaFactory.ts +++ b/packages/dds/tree/src/simple-tree/api/schemaFactory.ts @@ -1045,6 +1045,18 @@ export class SchemaFactory< undefined >; } + + /** + * Create a {@link SchemaFactory} with a {@link SchemaFactory.scope|scope} which is a combination of this factory's scope and the provided name. + * @remarks + * The main use-case for this is when creating a collection of related schema (for example using a function that creates multiple schema). + * Creating such related schema using a sub-scope helps ensure they won't collide with other schema in the parent scope. + */ + public scopedFactory( + name: T, + ): SchemaFactory, TNameInner> { + return new SchemaFactory(this.scoped(name)); + } } export function structuralName( diff --git a/packages/dds/tree/src/test/simple-tree/api/schemaCreationUtilities.spec.ts b/packages/dds/tree/src/test/simple-tree/api/schemaCreationUtilities.spec.ts index 5a7a944aea30..2945bd63e234 100644 --- a/packages/dds/tree/src/test/simple-tree/api/schemaCreationUtilities.spec.ts +++ b/packages/dds/tree/src/test/simple-tree/api/schemaCreationUtilities.spec.ts @@ -83,11 +83,7 @@ describe("schemaCreationUtilities", () => { it("enumFromStrings - construction tests", () => { const schemaFactory = new SchemaFactory("com.myApp"); - const ModeNodes = enumFromStrings(new SchemaFactory(`${schemaFactory.scope}.Mode`), [ - "A", - "B", - "C", - ]); + const ModeNodes = enumFromStrings(schemaFactory.scopedFactory("Mode"), ["A", "B", "C"]); type ModeNodes = TreeNodeFromImplicitAllowedTypes; type I0 = NodeFromSchema<(typeof ModeNodes.schema)[0]>; @@ -128,7 +124,7 @@ describe("schemaCreationUtilities", () => { b = "B", } // Define the schema for each member of the enum using a nested scope to group them together. - const ModeNodes = adaptEnum(new SchemaFactory(`${schemaFactory.scope}.Mode`), Mode); + const ModeNodes = adaptEnum(schemaFactory.scopedFactory("Mode"), Mode); // Defined the types of the nodes which correspond to this the schema. type ModeNodes = TreeNodeFromImplicitAllowedTypes; // An example schema which has an enum as a child. @@ -156,7 +152,7 @@ describe("schemaCreationUtilities", () => { b = "b", c = 6.3, } - const ModeNodes = adaptEnum(new SchemaFactory(`${schemaFactory.scope}.Mode`), Mode); + const ModeNodes = adaptEnum(schemaFactory.scopedFactory("Mode"), Mode); type ModeNodes = TreeNodeFromImplicitAllowedTypes; const fromEnumValue = ModeNodes(Mode.a); @@ -198,7 +194,7 @@ describe("schemaCreationUtilities", () => { c = "C", } // Uses a nested schema factory, as recommended by adaptEnum's docs to ensure that pattern works. - const ModeNodes = adaptEnum(new SchemaFactory(`${schemaFactory.scope}.Mode`), Mode); + const ModeNodes = adaptEnum(schemaFactory.scopedFactory("Mode"), Mode); type ModeNodes = TreeNodeFromImplicitAllowedTypes; const fromEnumValue = ModeNodes(Mode.a); diff --git a/packages/framework/fluid-framework/api-report/fluid-framework.alpha.api.md b/packages/framework/fluid-framework/api-report/fluid-framework.alpha.api.md index 781ffdf8bfc7..251dfb9357c2 100644 --- a/packages/framework/fluid-framework/api-report/fluid-framework.alpha.api.md +++ b/packages/framework/fluid-framework/api-report/fluid-framework.alpha.api.md @@ -1050,6 +1050,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/framework/fluid-framework/api-report/fluid-framework.beta.api.md b/packages/framework/fluid-framework/api-report/fluid-framework.beta.api.md index 6557b7dae1e3..8f516e8dcf10 100644 --- a/packages/framework/fluid-framework/api-report/fluid-framework.beta.api.md +++ b/packages/framework/fluid-framework/api-report/fluid-framework.beta.api.md @@ -766,6 +766,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md index e8d7c1aad0d1..1faa8d423dc6 100644 --- a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md +++ b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md @@ -1063,6 +1063,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.public.api.md b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.public.api.md index 32ffa5a2ac1b..d02422699808 100644 --- a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.public.api.md +++ b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.public.api.md @@ -797,6 +797,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; } diff --git a/packages/framework/fluid-framework/api-report/fluid-framework.public.api.md b/packages/framework/fluid-framework/api-report/fluid-framework.public.api.md index c3c3e20415ab..cb6ca8f65c0e 100644 --- a/packages/framework/fluid-framework/api-report/fluid-framework.public.api.md +++ b/packages/framework/fluid-framework/api-report/fluid-framework.public.api.md @@ -761,6 +761,7 @@ export class SchemaFactory(t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; static readonly requiredRecursive: (t: T, props?: Omit, "defaultProvider"> | undefined) => FieldSchemaUnsafe; readonly scope: TScope; + scopedFactory(name: T): SchemaFactory, TNameInner>; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; static readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never, unknown>; }