Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP - Specific APIs for nodeChanged event depending on node-kind #7

Draft
wants to merge 2 commits into
base: node-changed-details
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Trying to get per-node-kind API shapes to work
alexvy86 committed Aug 2, 2024
commit 6fde8b8828b788788533e7e77ee7937bdfeedb26
5 changes: 5 additions & 0 deletions packages/dds/tree/src/simple-tree/arrayNode.ts
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ import {
type TreeNodeSchema,
typeNameSymbol,
normalizeFieldSchema,
nodeKindSymbol,
} from "./schemaTypes.js";
import { mapTreeFromNodeData } from "./toMapTree.js";
import {
@@ -976,6 +977,10 @@ export function arraySchema<
return identifier;
}

public get [nodeKindSymbol](): NodeKind {
return NodeKind.Array;
}

protected get simpleSchema(): T {
return info;
}
5 changes: 5 additions & 0 deletions packages/dds/tree/src/simple-tree/mapNode.ts
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ import {
type TreeNodeSchema,
type TreeNodeFromImplicitAllowedTypes,
typeNameSymbol,
nodeKindSymbol,
} from "./schemaTypes.js";
import { mapTreeFromNodeData } from "./toMapTree.js";
import { type MostDerivedData, type TreeNode, TreeNodeValid } from "./types.js";
@@ -257,6 +258,10 @@ export function mapSchema<
public get [typeNameSymbol](): TName {
return identifier;
}

public get [nodeKindSymbol](): NodeKind {
return NodeKind.Map;
}
}
const schemaErased: TreeNodeSchemaClass<
TName,
5 changes: 5 additions & 0 deletions packages/dds/tree/src/simple-tree/objectNode.ts
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ import {
typeNameSymbol,
type ImplicitAllowedTypes,
FieldKind,
nodeKindSymbol,
} from "./schemaTypes.js";
import { mapTreeFromNodeData } from "./toMapTree.js";
import {
@@ -305,6 +306,10 @@ abstract class CustomObjectNodeBase<
const T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>,
> extends TreeNodeValid<InsertableObjectFromSchemaRecord<T>> {
public static readonly kind = NodeKind.Object;

public get [nodeKindSymbol](): NodeKind {
return NodeKind.Object;
}
}

/**
11 changes: 10 additions & 1 deletion packages/dds/tree/src/simple-tree/schemaCreationUtilities.ts
Original file line number Diff line number Diff line change
@@ -9,7 +9,12 @@ import type { EmptyObject } from "../feature-libraries/index.js";
import { fail } from "../util/index.js";

import type { SchemaFactory, ScopedSchemaName } from "./schemaFactory.js";
import type { NodeFromSchema, NodeKind, TreeNodeSchemaClass } from "./schemaTypes.js";
import {
NodeKind,
nodeKindSymbol,
type NodeFromSchema,
type TreeNodeSchemaClass,
} from "./schemaTypes.js";
import type { TreeNode } from "./types.js";
import type {
InsertableObjectFromSchemaRecord,
@@ -36,6 +41,10 @@ export function singletonSchema<TScope extends string, TName extends string | nu
public get value(): TName {
return name;
}

public get [nodeKindSymbol](): NodeKind {
return NodeKind.Object;
}
}

type NodeType = object &
13 changes: 13 additions & 0 deletions packages/dds/tree/src/simple-tree/schemaTypes.ts
Original file line number Diff line number Diff line change
@@ -600,6 +600,19 @@ export type TreeLeafValue = number | string | boolean | IFluidHandle | null;
*/
export const typeNameSymbol: unique symbol = Symbol("TreeNode Type");

/**
* The node kind of a {@link TreeNode}.
* @remarks
* This symbol mainly exists on nodes to allow TypeScript to provide more accurate type checking.
*
* This symbol should not manually be added to objects as doing so allows the object to be invalidly used where nodes are expected.
* Instead construct a real node of the desired type using its constructor.
* @privateRemarks
* This prevents non-nodes from being accidentally used as nodes, as well as allows the type checker to distinguish different node kinds.
* @public
*/
export const nodeKindSymbol: unique symbol = Symbol("TreeNode Kind");

/**
* Adds a type symbol to a type for stronger typing.
* @remarks
8 changes: 6 additions & 2 deletions packages/dds/tree/src/simple-tree/testRecursiveDomain.ts
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ import { SchemaFactory } from "./schemaFactory.js";
// If we let TypeScript generate these includes, they use relative paths which break API extractor's rollup.
// API-Extractor issue: https://github.com/microsoft/rushstack/issues/4507
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-imports
import type { FieldKind, NodeKind } from "./schemaTypes.js";
import { NodeKind, nodeKindSymbol, type FieldKind } from "./schemaTypes.js";

const builder = new SchemaFactory("Test Recursive Domain");

@@ -38,7 +38,11 @@ export const base = builder.objectRecursive("testObject", {
/**
* @internal
*/
export class RecursiveObject extends base {}
export class RecursiveObject extends base {
public get [nodeKindSymbol](): NodeKind {
return NodeKind.Object;
}
}

/**
* Due to https://github.com/microsoft/TypeScript/issues/55832 this is expected to compile to a d.ts file which contain `any`, and therefore the other (above) approach using class definitions is recommended for recursive schema.
8 changes: 8 additions & 0 deletions packages/dds/tree/src/simple-tree/types.ts
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import {
type TreeNodeSchema,
type TreeNodeSchemaClass,
type WithType,
type nodeKindSymbol,
typeNameSymbol,
} from "./schemaTypes.js";
import {
@@ -308,6 +309,13 @@ export abstract class TreeNode implements WithType {
*/
public abstract get [typeNameSymbol](): string;

/**
* Adds a node kind symbol for stronger typing.
* @privateRemarks
* Subclasses provide more specific strings for this to get strong typing of otherwise type compatible nodes.
*/
public abstract get [nodeKindSymbol](): NodeKind;

/**
* Provides `instanceof` support for testing if a value is a `TreeNode`.
* @remarks