SchemaStaticsAlpha Interface
Stateless APIs exposed via SchemaFactoryAlpha as both instance properties and as statics.
For more information about our API support guarantees, see here.
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 SchemaStaticsAlpha
Remarks
See SchemaStatics for why this is useful.
Properties
Property | Alerts | Type | Description |
---|---|---|---|
staged | Alpha |
<const T extends LazyItem<TreeNodeSchema>>(t: T | AnnotatedAllowedType<T>) => AnnotatedAllowedType<T> | Declares a staged type in a set of AllowedTypes. |
Property Details
staged
Declares a staged type in a set of AllowedTypes.
For more information about our API support guarantees, see here.
Signature
staged: <const T extends LazyItem<TreeNodeSchema>>(t: T | AnnotatedAllowedType<T>) => AnnotatedAllowedType<T>;
Type: <const T extends LazyItem<TreeNodeSchema>>(t: T | AnnotatedAllowedType<T>) => AnnotatedAllowedType<T>
Remarks
Staged allowed types add support for loading documents which may or may not permit an allowed type in a location in a schema. This allows for an incremental rollout of a schema change to add a TreeNodeSchema to an AllowedTypes without breaking cross version collaboration.
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. 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. This will also require upgrading the schema for existing documents.
Using a staged allowed type in a schema is just like using the schema as an allowed type with the following exceptions:
- initialize(content) will omit the staged allowed type from the newly created stored schema. 2. upgradeSchema() will omit the staged allowed type from the the upgraded stored schema. 3. When evaluating compatibility, it will be viewable even if the staged allowed type is not present in the stored schema's corresponding allowed types. 4. Because of the above, it is possible to get errors when inserting content which uses the staged allowed type when inserting the content into a tree who's stored schema does not permit it.
Currently, staged
is not supported in the recursive type APIs: this is a known limitation which future versions of the API will address.
Usage
Example 1
Suppose you have a schema which has a field that allows some type A
, but you want to add support for type B
.
The first change is to used to mark the new type as staged, replacing A
in the schema with [A, SchemaStaticsAlpha.staged(B)]
. 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.
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. This updated version of the app will need to call upgradeSchema() when opening documents created by earlier versions.
Adding a B
schema as an option in the root could look like this:
const factory = new SchemaFactoryAlpha("test");
class A extends factory.objectAlpha("A", {}) {}
class B extends factory.objectAlpha("B", {}) {}
// Does not support B
const configBefore = new TreeViewConfigurationAlpha({
schema: A,
});
// Supports documents with or without B
const configStaged = new TreeViewConfigurationAlpha({
// Adds staged support for B.
// Currently this requires wrapping the root field with `SchemaFactoryAlpha.required`:
// this is normally implicitly included, but is currently required while the "staged" APIs are `@alpha`.
schema: SchemaFactoryAlpha.required([A, SchemaFactoryAlpha.staged(B)]),
});
// Only supports documents with A and B: can be used to upgrade schema to add B.
const configAfter = new TreeViewConfigurationAlpha({
schema: [A, B],
});
Example 2
Below is a full example of how the schema migration process works. This can also be found in our tests.
// Schema A: only number allowed
const schemaA = SchemaFactoryAlpha.optional([SchemaFactoryAlpha.number]);
// Schema B: number or string (string is staged)
const schemaB = SchemaFactoryAlpha.optional([
SchemaFactoryAlpha.number,
SchemaFactoryAlpha.staged(SchemaFactoryAlpha.string),
]);
// Schema C: number or string, both fully allowed
const schemaC = SchemaFactoryAlpha.optional([
SchemaFactoryAlpha.number,
SchemaFactoryAlpha.string,
]);
// Initialize with schema A.
const configA = new TreeViewConfiguration({
schema: schemaA,
});
const viewA = treeA.viewWith(configA);
viewA.initialize(5);
// Since we are running all the different versions of the app in the same process making changes synchronously,
// an explicit flush is needed to make them available to each other.
synchronizeTrees();
assert.deepEqual(viewA.root, 5);
// View the same document with a second tree using schema B.
const configB = new TreeViewConfiguration({
schema: schemaB,
});
const viewB = treeB.viewWith(configB);
// B cannot write strings to the root.
assert.throws(() => (viewB.root = "test"));
// View the same document with a third tree using schema C.
const configC = new TreeViewConfiguration({
schema: schemaC,
});
const viewC = treeC.viewWith(configC);
// Upgrade to schema C
viewC.upgradeSchema();
// Use the newly enabled schema.
viewC.root = "test";
synchronizeTrees();
// View A is now incompatible with the stored schema:
assert.equal(viewA.compatibility.canView, false);
// View B can still read the document, and now sees the string root which relies on the staged schema.
assert.deepEqual(viewB.root, "test");