From 5405422d8118ea071e09a3bb310f563c293ad086 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:05:54 -0800 Subject: [PATCH] docs: More scope docs (#23026) ## Description More docs for SchemaFactory.scope. Convert docs to other format for parameter properties so it can have its own subsections. --- .../dds/tree/api-report/tree.alpha.api.md | 4 +- packages/dds/tree/api-report/tree.beta.api.md | 4 +- .../tree/api-report/tree.legacy.alpha.api.md | 4 +- .../tree/api-report/tree.legacy.public.api.md | 4 +- .../dds/tree/api-report/tree.public.api.md | 4 +- .../tree/src/simple-tree/api/schemaFactory.ts | 48 ++++++++++++++----- .../api-report/fluid-framework.alpha.api.md | 4 +- .../api-report/fluid-framework.beta.api.md | 4 +- .../fluid-framework.legacy.alpha.api.md | 4 +- .../fluid-framework.legacy.public.api.md | 4 +- .../api-report/fluid-framework.public.api.md | 4 +- 11 files changed, 57 insertions(+), 31 deletions(-) diff --git a/packages/dds/tree/api-report/tree.alpha.api.md b/packages/dds/tree/api-report/tree.alpha.api.md index 8a5cefd238e4..3265e4a9b9aa 100644 --- a/packages/dds/tree/api-report/tree.alpha.api.md +++ b/packages/dds/tree/api-report/tree.alpha.api.md @@ -577,7 +577,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -602,7 +603,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } diff --git a/packages/dds/tree/api-report/tree.beta.api.md b/packages/dds/tree/api-report/tree.beta.api.md index 2130d8b61985..7c570d89640b 100644 --- a/packages/dds/tree/api-report/tree.beta.api.md +++ b/packages/dds/tree/api-report/tree.beta.api.md @@ -365,7 +365,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -390,7 +391,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } 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 24a1cc4960cd..4df875307225 100644 --- a/packages/dds/tree/api-report/tree.legacy.alpha.api.md +++ b/packages/dds/tree/api-report/tree.legacy.alpha.api.md @@ -360,7 +360,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -385,7 +386,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } 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 77991adaf27a..b2d24dd09fc8 100644 --- a/packages/dds/tree/api-report/tree.legacy.public.api.md +++ b/packages/dds/tree/api-report/tree.legacy.public.api.md @@ -360,7 +360,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -385,7 +386,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } diff --git a/packages/dds/tree/api-report/tree.public.api.md b/packages/dds/tree/api-report/tree.public.api.md index 77991adaf27a..b2d24dd09fc8 100644 --- a/packages/dds/tree/api-report/tree.public.api.md +++ b/packages/dds/tree/api-report/tree.public.api.md @@ -360,7 +360,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -385,7 +386,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } diff --git a/packages/dds/tree/src/simple-tree/api/schemaFactory.ts b/packages/dds/tree/src/simple-tree/api/schemaFactory.ts index 1564f0fa95c4..995ae0809407 100644 --- a/packages/dds/tree/src/simple-tree/api/schemaFactory.ts +++ b/packages/dds/tree/src/simple-tree/api/schemaFactory.ts @@ -216,19 +216,45 @@ export class SchemaFactory< private readonly structuralTypes: Map = new Map(); /** - * Construct a SchemaFactory with a given scope. + * Construct a SchemaFactory with a given {@link SchemaFactory.scope|scope}. * @remarks - * There are no restrictions on mixing schema from different schema factories: - * this is encouraged when a single schema references schema from different libraries. - * If each library exporting schema picks its own globally unique scope for its SchemaFactory, - * then all schema an application might depend on, directly or transitively, - * will end up with a unique fully qualified name which is required to refer to it in persisted data and errors. - * - * @param scope - Prefix appended to the identifiers of all {@link TreeNodeSchema} produced by this builder. - * Use of [Reverse domain name notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation) or a UUIDv4 is recommended to avoid collisions. - * You may opt out of using a scope by passing `undefined`, but note that this increases the risk of collisions. + * There are no restrictions on mixing schema from different schema factories. + * Typically each library will create one or more SchemaFactories and use them to define its schema. */ - public constructor(public readonly scope: TScope) {} + public constructor( + /** + * Prefix appended to the identifiers of all {@link TreeNodeSchema} produced by this builder. + * + * @remarks + * Generally each independently developed library + * (possibly a package, but could also be part of a package or multiple packages developed together) + * should get its own unique `scope`. + * Then each schema in the library get a name which is unique within the library. + * The scope and name are joined (with a period) to form the {@link TreeNodeSchemaCore.identifier|schema identifier}. + * Following this pattern allows a single application to depend on multiple libraries which define their own schema, and use them together in a single tree without risk of collisions. + * If a library logically contains sub-libraries with their own schema, they can be given a scope nested inside the parent scope, such as "ParentScope.ChildScope". + * + * To avoid collisions between the scopes of libraries + * it is recommended that the libraries use {@link https://en.wikipedia.org/wiki/Reverse_domain_name_notation | Reverse domain name notation} or a UUIDv4 for their scope. + * If this pattern is followed, application can safely use third party libraries without risk of the schema in them colliding. + * + * You may opt out of using a scope by passing `undefined`, but note that this increases the risk of collisions. + * + * @example + * Fluid Framework follows this pattern, placing the schema for the built in leaf types in the `com.fluidframework.leaf` scope. + * If Fluid Framework publishes more schema in the future, they would be under some other `com.fluidframework` scope. + * This ensures that any schema defined by any other library will not conflict with Fluid Framework's schema + * as long as the library uses the recommended patterns for how to scope its schema.. + * + * @example + * A library could generate a random UUIDv4, like `242c4397-49ed-47e6-8dd0-d5c3bc31778b` and use that as the scope. + * Note: do not use this UUID: a new one must be randomly generated when needed to ensure collision resistance. + * ```typescript + * const factory = new SchemaFactory("242c4397-49ed-47e6-8dd0-d5c3bc31778b"); + * ``` + */ + public readonly scope: TScope, + ) {} private scoped(name: Name): ScopedSchemaName { return ( 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 c300a3cccf9e..37eac2a1a112 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 @@ -930,7 +930,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -955,7 +956,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } 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 a56d27cd3862..267375e03fa0 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 @@ -715,7 +715,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -740,7 +741,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } 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 2e56b7da7a2c..cb71efc1816b 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 @@ -1012,7 +1012,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -1037,7 +1038,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } 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 b44190210ce4..8b4ca68b0fba 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 @@ -746,7 +746,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -771,7 +772,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; } 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 2066318bd80d..8eedb915642f 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 @@ -710,7 +710,8 @@ export interface SchemaCompatibilityStatus { // @public @sealed export class SchemaFactory { - constructor(scope: TScope); + constructor( + scope: TScope); array(allowedTypes: T): TreeNodeSchemaNonClass`>, NodeKind.Array, TreeArrayNode & WithType`>, NodeKind.Array>, Iterable>, true, T, undefined>; array(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNode & WithType, NodeKind.Array>, Iterable>, true, T, undefined>; arrayRecursive>(name: Name, allowedTypes: T): TreeNodeSchemaClass, NodeKind.Array, TreeArrayNodeUnsafe & WithType, NodeKind.Array, unknown>, { @@ -735,7 +736,6 @@ export class SchemaFactory>(t: T, props?: Omit): FieldSchemaUnsafe; required(t: T, props?: Omit, "defaultProvider">): FieldSchema; requiredRecursive>(t: T, props?: Omit): FieldSchemaUnsafe; - // (undocumented) readonly scope: TScope; readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>; }