Skip to main content

TreeAlpha Interface

Extensions to Tree and TreeBeta which are not yet stable.

This API is provided as an alpha preview and may change without notice.

To use, import via @fluidframework/tree/alpha.

For more information about our API support guarantees, see here.

Sealed

This type is "sealed," meaning that code outside of the library defining it should not implement or extend it. Future versions of this type may add members or make typing of readonly members more specific.

Signature​

/** @sealed */
export interface TreeAlpha

Remarks​

Use via the TreeAlpha singleton.

The unhydrated node creation APIs in this interface do not support unknown optional fields. This is because unknown optional fields still must have a schema: its just that the schema may come from the document's stored schema. Unhydrated nodes created via this interface are not associated with any document, so there is nowhere for them to get schema for unknown optional fields. Note that clone(node) can create an unhydrated node with unknown optional fields, as it uses the source node's stored schema (if any).

Export APIs in this interface include unknown optional fields if they are using allStoredKeys.

Properties​

PropertyAlertsModifiersTypeDescription
identifierAlphareadonlyTreeIdentifierUtilsAPIs for creating, converting, and retrieving identifiers.

Methods​

MethodAlertsReturn TypeDescription
child(node, key)AlphaTreeNode | TreeLeafValue | undefinedGets the child of the given node with the given property key if a child exists under that key.
children(node)AlphaIterable<[propertyKey: string | number, child: TreeNode | TreeLeafValue]>Gets the children of the provided node, paired with their property keys under the node.
context(node)AlphaTreeContextAlphaRetrieve the context for the given node.
create(schema, data)AlphaUnhydrated<TSchema extends ImplicitFieldSchema ? TreeFieldFromImplicitField<TSchema> : TreeNode | TreeLeafValue | undefined>Construct tree content that is compatible with the field defined by the provided schema.
exportCompressed(tree, options)AlphaJsonCompatible<IFluidHandle>Export the content of the provided tree in a compressed JSON compatible format.
exportConcise(node, options)AlphaConciseTreeCopy a snapshot of the current version of a TreeNode into a ConciseTree.
exportConcise(node, options)AlphaConciseTree | undefinedCopy a snapshot of the current version of a TreeNode into a ConciseTree, allowing undefined.
exportVerbose(node, options)AlphaVerboseTreeCopy a snapshot of the current version of a TreeNode into a JSON compatible plain old JavaScript Object (except for IFluidHandles). Uses the VerboseTree format, with an explicit type on every node.
importCompressed(schema, compressedData, options)AlphaUnhydrated<TreeFieldFromImplicitField<TSchema>>Import data encoded by exportCompressed(tree, options).
importConcise(schema, data)AlphaUnhydrated<TSchema extends ImplicitFieldSchema ? TreeFieldFromImplicitField<TSchema> : TreeNode | TreeLeafValue | undefined>A less type-safe version of create(schema, data), suitable for importing data.
importVerbose(schema, data, options)AlphaUnhydrated<TreeFieldFromImplicitField<TSchema>>Construct tree content compatible with a field defined by the provided schema.
key2(node)Alphastring | number | undefinedThe key of the given node under its parent.
on(node, eventName, listener)Alpha() => voidRegister an event listener on the given node.
tagContentSchema(schema, content)AlphaTContentEnsures that the provided content will be interpreted as the given schema when inserting into the tree.
trackObservations(onInvalidation, trackDuring)AlphaObservationResults<TResult>Track observations of any TreeNode content.
trackObservationsOnce(onInvalidation, trackDuring)AlphaObservationResults<TResult>trackObservations(onInvalidation, trackDuring) except automatically unsubscribes when the first invalidation occurs.

Property Details​

identifier​

APIs for creating, converting, and retrieving identifiers.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

readonly identifier: TreeIdentifierUtils;

Type: TreeIdentifierUtils

Method Details​

child​

Gets the child of the given node with the given property key if a child exists under that key.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

child(node: TreeNode, key: string | number): TreeNode | TreeLeafValue | undefined;

Remarks​

Unknown optional fields of Object nodes will not be returned by this method.

Parameters​

ParameterTypeDescription
nodeTreeNodeThe parent node whose child is being requested.
keystring | numberThe property key under the node under which the child is being requested. For Object nodes, this is the developer-facing "property key", not the "stored keys".

Returns​

The child node or leaf value under the given key, or undefined if no such child exists.

Return type: TreeNode | TreeLeafValue | undefined

See Also​

key2(node)

parent(node)

children​

Gets the children of the provided node, paired with their property keys under the node.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

children(node: TreeNode): Iterable<[propertyKey: string | number, child: TreeNode | TreeLeafValue]>;

Remarks​

No guarantees are made regarding the order of the children in the returned array.

Optional properties of Object nodes with no value are not included in the result.

Unknown optional fields of Object nodes are not included in the result.

Parameters​

ParameterTypeDescription
nodeTreeNodeThe node whose children are being requested.

Returns​

An array of pairs of the form [propertyKey, child].

For Array nodes, the propertyKey is the index of the child in the array.

For Object nodes, the returned propertyKeys are the developer-facing "property keys", not the "stored keys".

Return type: Iterable<[propertyKey: string | number, child: TreeNode | TreeLeafValue]>

See Also​

key2(node)

parent(node)

context​

Retrieve the context for the given node.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

context(node: TreeNode): TreeContextAlpha;

Parameters​

ParameterTypeDescription
nodeTreeNodeThe node to query

Returns​

Return type: TreeContextAlpha

create​

Construct tree content that is compatible with the field defined by the provided schema.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

create<const TSchema extends ImplicitFieldSchema | UnsafeUnknownSchema>(schema: UnsafeUnknownSchema extends TSchema ? ImplicitFieldSchema : TSchema & ImplicitFieldSchema, data: InsertableField<TSchema>): Unhydrated<TSchema extends ImplicitFieldSchema ? TreeFieldFromImplicitField<TSchema> : TreeNode | TreeLeafValue | undefined>;
Type Parameters​
ParameterConstraintDescription
TSchemaImplicitFieldSchema | UnsafeUnknownSchema

Remarks​

When providing a TreeNodeSchemaClass, this is the same as invoking its constructor except that an unhydrated node can also be provided. This function exists as a generalization that can be used in other cases as well, such as when undefined might be allowed (for an optional field), or when the type should be inferred from the data when more than one type is possible.

Parameters​

ParameterTypeDescription
schemaUnsafeUnknownSchema extends TSchema ? ImplicitFieldSchema : TSchema & ImplicitFieldSchemaThe schema for what to construct. As this is an ImplicitFieldSchema, a FieldSchema, TreeNodeSchema or AllowedTypes array can be provided.
dataInsertableField<TSchema>The data used to construct the field content.

Returns​

Return type: Unhydrated<TSchema extends ImplicitFieldSchema ? TreeFieldFromImplicitField<TSchema> : TreeNode | TreeLeafValue | undefined>

exportCompressed​

Export the content of the provided tree in a compressed JSON compatible format.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

exportCompressed(tree: TreeNode | TreeLeafValue, options: {
idCompressor?: IIdCompressor;
} & Pick<CodecWriteOptions, "minVersionForCollab">): JsonCompatible<IFluidHandle>;

Remarks​

If an idCompressor is provided, it will be used to compress identifiers and thus will be needed to decompress the data.

Always uses "stored" keys. See allStoredKeys for details.

Parameters​

ParameterTypeDescription
treeTreeNode | TreeLeafValue
options{ idCompressor?: IIdCompressor; } & Pick<CodecWriteOptions, "minVersionForCollab">

Returns​

Return type: JsonCompatible<IFluidHandle>

exportConcise​

Copy a snapshot of the current version of a TreeNode into a ConciseTree.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

exportConcise(node: TreeNode | TreeLeafValue, options?: TreeEncodingOptions): ConciseTree;

Parameters​

ParameterModifiersTypeDescription
nodeTreeNode | TreeLeafValue
optionsoptionalTreeEncodingOptions

Returns​

Return type: ConciseTree

exportConcise​

Copy a snapshot of the current version of a TreeNode into a ConciseTree, allowing undefined.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

exportConcise(node: TreeNode | TreeLeafValue | undefined, options?: TreeEncodingOptions): ConciseTree | undefined;

Parameters​

ParameterModifiersTypeDescription
nodeTreeNode | TreeLeafValue | undefined
optionsoptionalTreeEncodingOptions

Returns​

Return type: ConciseTree | undefined

exportVerbose​

Copy a snapshot of the current version of a TreeNode into a JSON compatible plain old JavaScript Object (except for IFluidHandles). Uses the VerboseTree format, with an explicit type on every node.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

exportVerbose(node: TreeNode | TreeLeafValue, options?: TreeEncodingOptions): VerboseTree;

Remarks​

There are several cases this may be preferred to exportConcise(node, options):

  1. When not using preventAmbiguity (or when using useStableFieldKeys), exportConcise can produce ambiguous data (the type may be unclear on some nodes). exportVerbose will always be unambiguous and thus lossless.
  1. When the data might be interpreted without access to the exact same view schema. In such cases, the types may be unknowable if not included.
  1. When easy access to the type is desired.

Parameters​

ParameterModifiersTypeDescription
nodeTreeNode | TreeLeafValue
optionsoptionalTreeEncodingOptions

Returns​

Return type: VerboseTree

importCompressed​

Import data encoded by exportCompressed(tree, options).

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

importCompressed<const TSchema extends ImplicitFieldSchema>(schema: TSchema, compressedData: JsonCompatible<IFluidHandle>, options: {
idCompressor?: IIdCompressor;
} & ICodecOptions): Unhydrated<TreeFieldFromImplicitField<TSchema>>;
Type Parameters​
ParameterConstraintDescription
TSchemaImplicitFieldSchema

Remarks​

If the data could have been encoded with a different schema, consider encoding the schema along side it using extractPersistedSchema(schema, minVersionForCollab, includeStaged) and loading the data using independentView(config, options).

Parameters​

ParameterTypeDescription
schemaTSchemaSchema with which the data must be compatible. This compatibility is not verified and must be ensured by the caller.
compressedDataJsonCompatible<IFluidHandle>Data compressed by exportCompressed(tree, options).
options{ idCompressor?: IIdCompressor; } & ICodecOptionsIf exportCompressed(tree, options) was given an idCompressor, it must be provided here.

Returns​

Return type: Unhydrated<TreeFieldFromImplicitField<TSchema>>

importConcise​

A less type-safe version of create(schema, data), suitable for importing data.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

importConcise<const TSchema extends ImplicitFieldSchema | UnsafeUnknownSchema>(schema: UnsafeUnknownSchema extends TSchema ? ImplicitFieldSchema : TSchema & ImplicitFieldSchema, data: ConciseTree | undefined): Unhydrated<TSchema extends ImplicitFieldSchema ? TreeFieldFromImplicitField<TSchema> : TreeNode | TreeLeafValue | undefined>;
Type Parameters​
ParameterConstraintDescription
TSchemaImplicitFieldSchema | UnsafeUnknownSchema

Remarks​

Due to ConciseTree relying on type inference from the data, its use is somewhat limited. This does not support ConciseTrees with customized handle encodings or using persisted keys. Use "compressed" or "verbose" formats for more flexibility.

When using this function, it is recommend to ensure your schema is unambiguous with preventAmbiguity. If the schema is ambiguous, consider using create(schema, data) and Unhydrated nodes where needed, or using importVerbose(schema, data, options) and specify all types.

Documented (and thus recoverable) error handling/reporting for this is not yet implemented, but for now most invalid inputs will throw a recoverable error.

Parameters​

ParameterTypeDescription
schemaUnsafeUnknownSchema extends TSchema ? ImplicitFieldSchema : TSchema & ImplicitFieldSchema
dataConciseTree | undefined

Returns​

Return type: Unhydrated<TSchema extends ImplicitFieldSchema ? TreeFieldFromImplicitField<TSchema> : TreeNode | TreeLeafValue | undefined>

importVerbose​

Construct tree content compatible with a field defined by the provided schema.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

importVerbose<const TSchema extends ImplicitFieldSchema>(schema: TSchema, data: VerboseTree | undefined, options?: TreeParsingOptions): Unhydrated<TreeFieldFromImplicitField<TSchema>>;
Type Parameters​
ParameterConstraintDescription
TSchemaImplicitFieldSchema

Remarks​

This currently does not support input containing unknown optional fields but does support staged allowed types. Non-empty default values for fields are currently not supported (must be provided in the input). The content will be validated against the schema and an error will be thrown if out of schema.

Parameters​

ParameterModifiersTypeDescription
schemaTSchemaThe schema for what to construct. As this is an ImplicitFieldSchema, a FieldSchema, TreeNodeSchema or AllowedTypes array can be provided.
dataVerboseTree | undefinedThe data used to construct the field content. See exportVerbose(node, options).
optionsoptionalTreeParsingOptions

Returns​

Return type: Unhydrated<TreeFieldFromImplicitField<TSchema>>

key2​

The key of the given node under its parent.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

key2(node: TreeNode): string | number | undefined;

Remarks​

If node is an element in a TreeArrayNode, this returns the index of node in the array node (a number). If node is the root node, this returns undefined. Otherwise, this returns the key of the field that it is under (a string).

Parameters​

ParameterTypeDescription
nodeTreeNode

Returns​

Return type: string | number | undefined

on​

Register an event listener on the given node.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

on<K extends keyof TreeChangeEventsAlpha<TNode>, TNode extends TreeNode>(node: TNode, eventName: K, listener: NoInfer<TreeChangeEventsAlpha<TNode>[K]>): () => void;
Type Parameters​
ParameterConstraintDescription
Kkeyof TreeChangeEventsAlpha<TNode>
TNodeTreeNode

Remarks​

Provides richer events than on(node, eventName, listener) for array nodes: - nodeChanged includes a delta payload for direct changes (insert, remove, move). - treeChanged also includes a delta payload and fires for both shallow changes and deep changes (e.g. a property of an element changed without any direct array change).

Parameters​

ParameterTypeDescription
nodeTNodeThe node whose events should be subscribed to.
eventNameKWhich event to subscribe to.
listenerNoInfer<TreeChangeEventsAlpha<TNode>[K]>The callback to trigger for the event. The tree can be read during the callback, but it is invalid to modify the tree during this callback.

Returns​

A callback function which will deregister the event. This callback should be called only once.

Return type: () => void

tagContentSchema​

Ensures that the provided content will be interpreted as the given schema when inserting into the tree.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

tagContentSchema<TSchema extends TreeNodeSchema, TContent extends InsertableField<TSchema>>(schema: TSchema, content: TContent): TContent;
Type Parameters​
ParameterConstraintDescription
TSchemaTreeNodeSchema
TContentInsertableField<TSchema>

Remarks​

If applicable, this will tag the given content with a special property that indicates its intended schema. The content will be interpreted as the given schema when later inserted into the tree.

This does not validate that the content actually conforms to the given schema (such validation will be done at insert time). If the content is not compatible with the tagged schema, an error will be thrown when the content is inserted.

This is particularly useful when the content's schema cannot be inferred from its structure alone because it is compatible with multiple schemas.

Example​

const sf = new SchemaFactory("example");
class Dog extends sf.object("Dog", { name: sf.string() }) {}
class Cat extends sf.object("Cat", { name: sf.string() }) {}
class Root extends sf.object("Root", { pet: [Dog, Cat] }) {}
// ...
const pet = { name: "Max" };
view.root.pet = pet; // Error: ambiguous schema - is it a Dog or a Cat?
TreeAlpha.ensureSchema(Dog, pet); // Tags `pet` as a Dog.
view.root.pet = pet; // No error - it's a Dog.

Parameters​

ParameterTypeDescription
schemaTSchema
contentTContent

Returns​

content, for convenience.

Return type: TContent

trackObservations​

Track observations of any TreeNode content.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

trackObservations<TResult>(onInvalidation: () => void, trackDuring: () => TResult): ObservationResults<TResult>;
Type Parameters​
ParameterDescription
TResult

Remarks​

This subscribes to changes to any nodes content observed during trackDuring.

Currently this does not support tracking parentage (see trackObservationsOnce(onInvalidation, trackDuring) for a version which does): if accessing parentage during trackDuring, this will throw a usage error.

This also does not track node status changes (e.g. whether a node is attached to a view or not). The current behavior of checking status is unspecified: future versions may track it, error, or ignore it.

These subscriptions remain active until unsubscribe is called: onInvalidation may be called multiple times. See trackObservationsOnce(onInvalidation, trackDuring) for a version which automatically unsubscribes on the first invalidation.

Parameters​

ParameterTypeDescription
onInvalidation() => void
trackDuring() => TResult

Returns​

Return type: ObservationResults<TResult>

trackObservationsOnce​

trackObservations(onInvalidation, trackDuring) except automatically unsubscribes when the first invalidation occurs.

This API is provided as an alpha preview and may change without notice.

For more information about our API support guarantees, see here.

Signature​

trackObservationsOnce<TResult>(onInvalidation: () => void, trackDuring: () => TResult): ObservationResults<TResult>;
Type Parameters​
ParameterDescription
TResult

Remarks​

This also supports tracking parentage, unlike trackObservations(onInvalidation, trackDuring), as long as the parent is not undefined.

Usage​

Example 1​

Simple cached value invalidation

// Compute and cache this "foo" value, and clear the cache when the fields read in the callback to compute it change.
cachedFoo ??= TreeAlpha.trackObservationsOnce(
() => {
cachedFoo = undefined;
},
() => nodeA.someChild.bar + nodeB.someChild.baz,
).result;

That is equivalent to doing the following:

if (cachedFoo === undefined) {
cachedFoo = nodeA.someChild.bar + nodeB.someChild.baz;
const invalidate = (): void => {
cachedFoo = undefined;
for (const u of unsubscribe) {
u();
}
};
const unsubscribe: (() => void)[] = [
TreeBeta.on(nodeA, "nodeChanged", (data) => {
if (data.changedProperties.has("someChild")) {
invalidate();
}
}),
TreeBeta.on(nodeB, "nodeChanged", (data) => {
if (data.changedProperties.has("someChild")) {
invalidate();
}
}),
TreeBeta.on(nodeA.someChild, "nodeChanged", (data) => {
if (data.changedProperties.has("bar")) {
invalidate();
}
}),
TreeBeta.on(nodeB.someChild, "nodeChanged", (data) => {
if (data.changedProperties.has("baz")) {
invalidate();
}
}),
];
}
Example 2​

Cached derived schema property

const factory = new SchemaFactory("com.example");
class Vector extends factory.object("Vector", {
x: SchemaFactory.number,
y: SchemaFactory.number,
}) {
#length: number | undefined = undefined;
public length(): number {
if (this.#length === undefined) {
const result = TreeAlpha.trackObservationsOnce(
() => {
this.#length = undefined;
},
() => Math.hypot(this.x, this.y),
);
this.#length = result.result;
}
return this.#length;
}
}
const vec = new Vector({ x: 3, y: 4 });
assert.equal(vec.length(), 5);
vec.x = 0;
assert.equal(vec.length(), 4);

Parameters​

ParameterTypeDescription
onInvalidation() => void
trackDuring() => TResult

Returns​

Return type: ObservationResults<TResult>