fluid-framework 2.113.0-411909 → 2.114.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +284 -0
- package/api-report/fluid-framework.alpha.api.md +165 -4
- package/api-report/fluid-framework.beta.api.md +47 -4
- package/api-report/fluid-framework.legacy.beta.api.md +47 -4
- package/api-report/fluid-framework.legacy.public.api.md +79 -0
- package/api-report/fluid-framework.public.api.md +79 -0
- package/dist/alpha.d.ts +31 -4
- package/dist/beta.d.ts +5 -4
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -9
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +5 -4
- package/dist/public.d.ts +5 -0
- package/lib/alpha.d.ts +31 -4
- package/lib/beta.d.ts +5 -4
- package/lib/index.d.ts +5 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +12 -0
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +5 -4
- package/lib/public.d.ts +5 -0
- package/package.json +17 -17
- package/src/index.ts +36 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,289 @@
|
|
|
1
1
|
# fluid-framework
|
|
2
2
|
|
|
3
|
+
## 2.114.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add FluidReadonlyArray type independent of TypeScript lib ([#27747](https://github.com/microsoft/FluidFramework/pull/27747)) [040d35bc29](https://github.com/microsoft/FluidFramework/commit/040d35bc29901d58e9e778f5f2e75ba581a80dc0)
|
|
8
|
+
|
|
9
|
+
`FluidReadonlyArray<T>` provides an equivalent of the built-in `ReadonlyArray` type that is independent of TypeScript [`lib`](https://www.typescriptlang.org/tsconfig/#lib), following the same pattern as `FluidReadonlyMap` and `FluidMap`.
|
|
10
|
+
The interface includes stable methods through ES2023 (`at()`, `findLast()`, `findLastIndex()`) but excludes newer copy-on-write methods (`toReversed()`, `toSorted()`, `toSpliced()`, `with()`) that Fluid Framework implementations don't yet support.
|
|
11
|
+
This ensures these types remain safe to implement without `lib` changes breaking them.
|
|
12
|
+
|
|
13
|
+
- Add clear method to TreeMapNodeAlpha ([#27765](https://github.com/microsoft/FluidFramework/pull/27765)) [30c889b99c](https://github.com/microsoft/FluidFramework/commit/30c889b99caca3d6ad1ab276761092d94118eab1)
|
|
14
|
+
|
|
15
|
+
[`TreeMapNodeAlpha`](https://fluidframework.com/docs/api/fluid-framework/treemapnodealpha-interface) now has a `clear` method, further aligning it with JavaScript's built-in Map API. It removes all elements from the map.
|
|
16
|
+
|
|
17
|
+
The merge semantics of `clear` are loosely specified: either of the following may occur:
|
|
18
|
+
- `clear` may remove all elements that were in the map when the edit was authored, even if some of those elements have since been moved elsewhere in the tree (in which case they are removed from their new location).
|
|
19
|
+
- `clear` may remove all elements that are in the map when the edit is sequenced, even if some of those elements were not yet in the map when the edit was authored.
|
|
20
|
+
|
|
21
|
+
This method is available on `TreeMapNodeAlpha`, which can be obtained from an existing `TreeMapNode` via `asAlpha`, or by declaring the schema with `SchemaFactoryAlpha`'s `mapAlpha`.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
const schemaFactory = new SchemaFactoryAlpha("example");
|
|
25
|
+
class Inventory extends schemaFactory.mapAlpha(
|
|
26
|
+
"Inventory",
|
|
27
|
+
schemaFactory.number,
|
|
28
|
+
) {}
|
|
29
|
+
|
|
30
|
+
const inventory = new Inventory(
|
|
31
|
+
new Map([
|
|
32
|
+
["apples", 5],
|
|
33
|
+
["pears", 3],
|
|
34
|
+
]),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
inventory.size; // 2
|
|
38
|
+
inventory.clear();
|
|
39
|
+
inventory.size; // 0
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- Promote Fluid container type interfaces to public ([#27746](https://github.com/microsoft/FluidFramework/pull/27746)) [33e014ac63](https://github.com/microsoft/FluidFramework/commit/33e014ac636d43a5f90b1ce1f64b95e60aaf2bca)
|
|
43
|
+
|
|
44
|
+
`FluidIterable`, `FluidIterableIterator`, `FluidReadonlyMap`, `FluidMap`, and `FluidReadonlyArray` are promoted from `@beta` to `@public`.
|
|
45
|
+
These sealed interfaces provide equivalents of the built-in `Iterable`, `IterableIterator`, `ReadonlyMap`, `Map`, and `ReadonlyArray` types that are independent of TypeScript [`lib`](https://www.typescriptlang.org/tsconfig/#lib).
|
|
46
|
+
They can now be used in public API surfaces.
|
|
47
|
+
|
|
48
|
+
- Add new @alpha ServiceClient API for creating and loading Fluid containers ([#27693](https://github.com/microsoft/FluidFramework/pull/27693)) [ee47192d4a](https://github.com/microsoft/FluidFramework/commit/ee47192d4ae91bc28f9154c4d1ead2acad762f3c)
|
|
49
|
+
|
|
50
|
+
This introduces an experimental (`@alpha`), service-agnostic API for working with Fluid containers whose root is an arbitrary data store, along with an in-memory implementation for testing.
|
|
51
|
+
|
|
52
|
+
The new surface is made up of:
|
|
53
|
+
- `ServiceClient` (`@fluidframework/driver-definitions`): the entry point for creating and loading containers. Along with it come the supporting container types (`FluidContainer`, `FluidContainerWithService`, `FluidContainerAttached`), the data store model (`DataStoreKind`, `DataStoreKey`, `DataStoreRegistry`, `DataStoreCreator`), and the generic registry primitives (`Registry`, `RegistryKey`, `lookupInRegistry`, `createBasicRegistryKey`).
|
|
54
|
+
- `defineDataStore` and `sharedObjectRegistryFromIterable` (`@fluidframework/shared-object-base`): build a `DataStoreKind` from a root shared object and a registry of shared object kinds.
|
|
55
|
+
- `defineTreeDataStore` and `instantiateTreeFirstTime` (`@fluidframework/tree`): a SharedTree-specific convenience wrapper that produces a `DataStoreKind` backed by a `TreeView`.
|
|
56
|
+
- `startEphemeralService` (`@fluidframework/local-driver`): starts an in-memory `EphemeralService` for tests. The service owns the lifetime of the in-memory documents and resources, and produces `ServiceClient`s connected to it (via `EphemeralService.newClient` or `EphemeralService.defaultClient`). The helpers `cleanupEphemeralService` and `getDefaultEphemeralService` manage an optional default service instance.
|
|
57
|
+
|
|
58
|
+
Apart from the `@fluidframework/local-driver` helpers (which come from `@fluidframework/local-driver/alpha`), these APIs are also re-exported from `fluid-framework`. None reference any `@legacy` types.
|
|
59
|
+
|
|
60
|
+
Example:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { startEphemeralService } from "@fluidframework/local-driver/alpha";
|
|
64
|
+
import {
|
|
65
|
+
ServiceClient,
|
|
66
|
+
defineTreeDataStore,
|
|
67
|
+
TreeViewConfiguration,
|
|
68
|
+
SchemaFactory,
|
|
69
|
+
} from "fluid-framework/alpha";
|
|
70
|
+
import { strict as assert } from "node:assert";
|
|
71
|
+
|
|
72
|
+
// Start an ephemeral in-memory service and get a ServiceClient connected to it.
|
|
73
|
+
const service = startEphemeralService();
|
|
74
|
+
const client: ServiceClient = service.defaultClient;
|
|
75
|
+
// Define a DataStoreKind which uses a SharedTree.
|
|
76
|
+
// In this case the schema is for a single number with an initializer that starts the it at 1.
|
|
77
|
+
// This schema is captures in the type allowing for strongly typed access to the data in the tree,
|
|
78
|
+
// where the type matches the schema based runtime enforcement of the schema.
|
|
79
|
+
const numberStore = defineTreeDataStore({
|
|
80
|
+
type: "my-app-root",
|
|
81
|
+
config: new TreeViewConfiguration({ schema: SchemaFactory.number }),
|
|
82
|
+
initializer: () => 1,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Create a container in the service with the above DataStoreKind.
|
|
86
|
+
// Ideally this creation would use a service independent API, and only the attach call would be service dependent,
|
|
87
|
+
// but that is not supported yet.
|
|
88
|
+
const detachedContainer1 = await client.createContainer(numberStore);
|
|
89
|
+
const container1 = await detachedContainer1.attach();
|
|
90
|
+
|
|
91
|
+
// We now have easy and type safe access to the data in the tree, which will be synced over the service.
|
|
92
|
+
assert.equal(container1.data.root, 1);
|
|
93
|
+
|
|
94
|
+
// A second client can load the same container from the service, and will see the same data.
|
|
95
|
+
const container2 = await client.loadContainer(container1.id, numberStore);
|
|
96
|
+
assert.equal(container2.data.root, 1);
|
|
97
|
+
|
|
98
|
+
// Both clients can modify the data, and the changes will be synced over the service.
|
|
99
|
+
container2.data.root = 2;
|
|
100
|
+
// Since we are using an ephemeral service, we can await the synchronization using service.synchronize.
|
|
101
|
+
await service.synchronize();
|
|
102
|
+
|
|
103
|
+
// And now the changes are visible for all clients.
|
|
104
|
+
assert.equal(container1.data.root, 2);
|
|
105
|
+
assert.equal(container2.data.root, 2);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Note that this example does a couple of things which are difficult to do with the other API surfaces:
|
|
109
|
+
1. It creates a container, then loads a second copy of it, allowing for collaboration. There is currently no non-legacy API surface which allows this without spawning a server process. This is also cleaner than the exacting legacy API options, and can replace the test specific APIs for this as well.
|
|
110
|
+
2. It creates a container which has a SharedTree at the root, and nothing else. This avoids depending on legacy DDS implementations, which is great for long-term document support and bundle size. This is currently impossible using `fluid-static`, which forces a special root data store. It is also impossible if using `aqueduct`, which forces a root directory in every data store. It can be done using the low level legacy APIs directly, but this new API for it is much simpler.
|
|
111
|
+
3. There is a common interface all services implement (`ServiceClient`), making the container creation part of the code work for any service implementation.
|
|
112
|
+
|
|
113
|
+
## 2.113.0
|
|
114
|
+
|
|
115
|
+
### Minor Changes
|
|
116
|
+
|
|
117
|
+
- Enable select staged schema upgrades at runtime via view configuration ([#27542](https://github.com/microsoft/FluidFramework/pull/27542)) [44f40e8411](https://github.com/microsoft/FluidFramework/commit/44f40e8411d53bc22939a8f53343863f420bb0de)
|
|
118
|
+
|
|
119
|
+
SharedTree now supports enabling selected staged schema upgrades when initializing or upgrading a document's stored schema.
|
|
120
|
+
This lets applications deploy code that understands a schema change before enabling that change in documents.
|
|
121
|
+
It separates code rollout from feature rollout.
|
|
122
|
+
|
|
123
|
+
#### API
|
|
124
|
+
|
|
125
|
+
Pass `stagedUpgradePolicy` in the configuration object to
|
|
126
|
+
[`ITreeAlpha.viewWith`](https://fluidframework.com/docs/api/tree/viewabletree-interface#viewwith-methodsignature)
|
|
127
|
+
to select which schema upgrades to enable at runtime.
|
|
128
|
+
|
|
129
|
+
Use `StagedSchemaUpgradePolicy.enabledStagedUpgrades(...)` with `SchemaUpgrade` objects from
|
|
130
|
+
[`SchemaFactoryBeta.staged`](https://fluidframework.com/docs/api/tree/schemastaticsbeta-interface#staged-propertysignature)
|
|
131
|
+
or [`SchemaFactoryAlpha.stagedOptional`](https://fluidframework.com/docs/api/tree/schemafactoryalpha-class#stagedoptional-property):
|
|
132
|
+
|
|
133
|
+
The following example defines a staged type, extracts its `SchemaUpgrade` token, and passes it to the view configuration so the staged type is enabled when the schema is upgraded:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const sf = new SchemaFactoryBeta("my-app");
|
|
137
|
+
|
|
138
|
+
class ChecklistItem extends sf.object("ChecklistItem", { text: sf.string }) {}
|
|
139
|
+
|
|
140
|
+
// `staged` wraps the type so it can be enabled at runtime.
|
|
141
|
+
const stagedChecklist = SchemaFactoryBeta.staged(ChecklistItem);
|
|
142
|
+
// The SchemaUpgrade token identifies this staged type.
|
|
143
|
+
const checklistUpgrade = stagedChecklist.metadata.stagedSchemaUpgrade;
|
|
144
|
+
|
|
145
|
+
class AppSchema extends sf.object("AppSchema", {
|
|
146
|
+
items: sf.array([sf.string, stagedChecklist]),
|
|
147
|
+
}) {}
|
|
148
|
+
|
|
149
|
+
const view = tree.viewWith(
|
|
150
|
+
new TreeViewConfigurationAlpha({
|
|
151
|
+
schema: AppSchema,
|
|
152
|
+
stagedUpgradePolicy:
|
|
153
|
+
StagedSchemaUpgradePolicy.enabledStagedUpgrades(checklistUpgrade),
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
When `stagedUpgradePolicy` is omitted or `undefined`, the default is
|
|
159
|
+
`StagedSchemaUpgradePolicy.restrictive`.
|
|
160
|
+
This excludes all staged schema upgrades, producing the most conservative stored schema.
|
|
161
|
+
|
|
162
|
+
Advanced callers can provide a custom `StagedSchemaUpgradePolicy` object:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const enabledFeatures = new Set<SchemaUpgrade>([checklistUpgrade]);
|
|
166
|
+
|
|
167
|
+
const view = tree.viewWith(
|
|
168
|
+
new TreeViewConfigurationAlpha({
|
|
169
|
+
schema: AppSchema,
|
|
170
|
+
stagedUpgradePolicy: {
|
|
171
|
+
includeStaged: (upgrade) => enabledFeatures.has(upgrade),
|
|
172
|
+
includeStagedOptional: (upgrade) => enabledFeatures.has(upgrade),
|
|
173
|
+
},
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
This is useful for fine-grained rollout control or integration tests.
|
|
179
|
+
|
|
180
|
+
#### Pre-built Policies
|
|
181
|
+
|
|
182
|
+
The `StagedSchemaUpgradePolicy` namespace provides convenient pre-built policies:
|
|
183
|
+
- **`restrictive`** (default): excludes all staged upgrades.
|
|
184
|
+
- **`permissive`**: includes all staged upgrades. Useful in tests.
|
|
185
|
+
- **`enabledStagedUpgrades(...)`**: includes only the specified upgrades.
|
|
186
|
+
|
|
187
|
+
#### Production
|
|
188
|
+
|
|
189
|
+
Applications can use feature flags to control when staged schema upgrades are enabled.
|
|
190
|
+
Previously, enabling a staged schema required a code change that removed the staged wrapper.
|
|
191
|
+
With this API, the staged wrapper stays in code while `stagedUpgradePolicy` decides at runtime which documents enable it.
|
|
192
|
+
|
|
193
|
+
For example, an application adding checklist items can deploy clients that understand the new schema first,
|
|
194
|
+
then enable the stored-schema upgrade only where a feature flag is active:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
const sf = new SchemaFactoryBeta("example-app");
|
|
198
|
+
|
|
199
|
+
class ChecklistItem extends sf.object("ChecklistItem", {
|
|
200
|
+
text: sf.string,
|
|
201
|
+
}) {}
|
|
202
|
+
|
|
203
|
+
const stagedChecklistItem = SchemaFactoryBeta.staged(ChecklistItem);
|
|
204
|
+
const checklistItemSchemaUpgrade =
|
|
205
|
+
stagedChecklistItem.metadata.stagedSchemaUpgrade;
|
|
206
|
+
|
|
207
|
+
class AppSchema extends sf.object("AppSchema", {
|
|
208
|
+
// `taskItem` allows plain text today; the staged type is added for future rollout.
|
|
209
|
+
taskItem: sf.optional([sf.string, stagedChecklistItem]),
|
|
210
|
+
}) {}
|
|
211
|
+
|
|
212
|
+
const enableChecklistItems = featureFlags.enableChecklistItems;
|
|
213
|
+
|
|
214
|
+
const view = tree.viewWith(
|
|
215
|
+
new TreeViewConfigurationAlpha({
|
|
216
|
+
schema: AppSchema,
|
|
217
|
+
stagedUpgradePolicy: enableChecklistItems
|
|
218
|
+
? StagedSchemaUpgradePolicy.enabledStagedUpgrades(
|
|
219
|
+
checklistItemSchemaUpgrade,
|
|
220
|
+
)
|
|
221
|
+
: undefined,
|
|
222
|
+
}),
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
if (view.compatibility.canInitialize) {
|
|
226
|
+
// New documents include the checklist schema only while the rollout is enabled.
|
|
227
|
+
view.initialize(initialContent);
|
|
228
|
+
} else if (view.compatibility.canUpgrade) {
|
|
229
|
+
// Writes the staged type into the stored schema for this document.
|
|
230
|
+
view.upgradeSchema();
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Once a staged schema upgrade has been written to a document's stored schema, that change is permanent.
|
|
235
|
+
If `upgradeSchema` is later called from a view that does not include the previously enabled token,
|
|
236
|
+
it throws a `UsageError` because the new target would narrow the stored schema.
|
|
237
|
+
|
|
238
|
+
In practice, keep the upgrade token configured for as long as any document may have been upgraded.
|
|
239
|
+
Once the staged wrapper is removed from the code, the token is no longer needed.
|
|
240
|
+
|
|
241
|
+
#### Testing
|
|
242
|
+
|
|
243
|
+
Tests can verify that the current application version handles documents with staged types enabled.
|
|
244
|
+
Without such testing, it is hard to confirm that staging prepared the application—not just the schema—for the new types.
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
const currentView = currentAppTree.viewWith(
|
|
248
|
+
new TreeViewConfiguration({ schema: CurrentAppSchema }),
|
|
249
|
+
);
|
|
250
|
+
currentView.initialize(existingTaskDocument);
|
|
251
|
+
await ensureSynchronized();
|
|
252
|
+
|
|
253
|
+
const nextView = asAlpha(nextAppTree).viewWith(
|
|
254
|
+
new TreeViewConfigurationAlpha({
|
|
255
|
+
schema: AppSchemaWithStagedChecklist,
|
|
256
|
+
stagedUpgradePolicy: StagedSchemaUpgradePolicy.enabledStagedUpgrades(
|
|
257
|
+
checklistItemSchemaUpgrade,
|
|
258
|
+
),
|
|
259
|
+
}),
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// The next version can read the document, but the checklist shape is not yet
|
|
263
|
+
// in stored schema and cannot be written.
|
|
264
|
+
assert.throws(() =>
|
|
265
|
+
addChecklistItem(nextView.root, { text: "Review rollout" }),
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
nextView.upgradeSchema();
|
|
269
|
+
await ensureSynchronized();
|
|
270
|
+
|
|
271
|
+
// Older clients are now incompatible; the next version can use the staged shape.
|
|
272
|
+
assert.equal(currentView.compatibility.canView, false);
|
|
273
|
+
addChecklistItem(nextView.root, { text: "Review rollout" });
|
|
274
|
+
await validateChecklistScenario(nextView);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
- Fix assert when inserting the same node multiple times ([#27734](https://github.com/microsoft/FluidFramework/pull/27734)) [b509d00166](https://github.com/microsoft/FluidFramework/commit/b509d00166773585c42c60e97ec30a86fbd20cd5)
|
|
278
|
+
|
|
279
|
+
When inserting the same node multiple times in a single array insertion, a `UsageError` is now thrown instead of an assert `0xa2b`.
|
|
280
|
+
|
|
281
|
+
For example, this now throws a `UsageError` with message `A "ArrayNodeTest.Item" node was provided more than once in a single insertion. A node may not be in more than one place in the tree.`:
|
|
282
|
+
|
|
283
|
+
```TypeScript
|
|
284
|
+
array.insertAtEnd(item, item);
|
|
285
|
+
```
|
|
286
|
+
|
|
3
287
|
## 2.112.0
|
|
4
288
|
|
|
5
289
|
### Minor Changes
|
|
@@ -302,6 +302,9 @@ export const contentSchemaSymbol: unique symbol;
|
|
|
302
302
|
// @alpha
|
|
303
303
|
export function createArrayInsertionAnchor(node: TreeArrayNode, currentIndex: number): ArrayPlaceAnchor;
|
|
304
304
|
|
|
305
|
+
// @alpha
|
|
306
|
+
export function createBasicRegistryKey<T>(type: string): RegistryKey<T, T>;
|
|
307
|
+
|
|
305
308
|
// @beta
|
|
306
309
|
export function createIdentifierIndex<TSchema extends ImplicitFieldSchema>(view: TreeView<TSchema>): IdentifierIndex;
|
|
307
310
|
|
|
@@ -331,6 +334,33 @@ export function createTreeIndex<TFieldSchema extends ImplicitFieldSchema, TKey e
|
|
|
331
334
|
// @beta
|
|
332
335
|
export function createTreeIndex<TFieldSchema extends ImplicitFieldSchema, TKey extends TreeIndexKey, TValue, TSchema extends TreeNodeSchema>(view: TreeView<TFieldSchema>, indexer: Map<TreeNodeSchema, string>, getValue: (nodes: TreeIndexNodes<NodeFromSchema<TSchema>>) => TValue, isKeyValid: (key: TreeIndexKey) => key is TKey, indexableSchema: readonly TSchema[]): TreeIndex<TKey, TValue>;
|
|
333
336
|
|
|
337
|
+
// @alpha @sealed
|
|
338
|
+
export interface DataStoreContext extends SharedObjectCreator {
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// @alpha @sealed
|
|
342
|
+
export interface DataStoreCreator {
|
|
343
|
+
createDataStore<T>(kind: DataStoreKey<T>): Promise<T>;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// @alpha @input
|
|
347
|
+
export type DataStoreKey<T, TAll = unknown> = RegistryKey<Promise<DataStoreKind<T>>, Promise<DataStoreKind<TAll>>>;
|
|
348
|
+
|
|
349
|
+
// @alpha @sealed
|
|
350
|
+
export interface DataStoreKind<out T = unknown> extends DataStoreKey<T>, ErasedBaseType<readonly ["DataStoreKind", T]> {
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// @alpha @input
|
|
354
|
+
export interface DataStoreOptions<in out TRoot extends IFluidLoadable, out TOutput> {
|
|
355
|
+
instantiateFirstTime(rootCreator: SharedObjectCreator<TRoot>, context: DataStoreContext): Promise<TRoot>;
|
|
356
|
+
readonly registry: SharedObjectRegistry;
|
|
357
|
+
readonly type: string;
|
|
358
|
+
view(root: TRoot, context: DataStoreContext): Promise<TOutput>;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// @alpha @input
|
|
362
|
+
export type DataStoreRegistry<out T = unknown> = Registry<Promise<DataStoreKind<T>>>;
|
|
363
|
+
|
|
334
364
|
// @alpha
|
|
335
365
|
export function decodeSchemaCompatibilitySnapshot(encodedSchema: JsonCompatibleReadOnly, validator?: FormatValidator): SimpleTreeSchema;
|
|
336
366
|
|
|
@@ -338,6 +368,12 @@ export function decodeSchemaCompatibilitySnapshot(encodedSchema: JsonCompatibleR
|
|
|
338
368
|
interface DefaultProvider extends ErasedType<"@fluidframework/tree.FieldProvider"> {
|
|
339
369
|
}
|
|
340
370
|
|
|
371
|
+
// @alpha
|
|
372
|
+
export function defineDataStore<T, TRoot extends IFluidLoadable>(options: DataStoreOptions<TRoot, T>): DataStoreKind<T>;
|
|
373
|
+
|
|
374
|
+
// @alpha
|
|
375
|
+
export function defineTreeDataStore<const TSchema extends ImplicitFieldSchema>(options: TreeDataStoreOptions<TSchema>): DataStoreKind<TreeView<TSchema>>;
|
|
376
|
+
|
|
341
377
|
// @alpha
|
|
342
378
|
export interface DirtyTreeMap {
|
|
343
379
|
// (undocumented)
|
|
@@ -523,12 +559,29 @@ export const FluidClientVersion: {
|
|
|
523
559
|
readonly v2_80: "2.80.0";
|
|
524
560
|
};
|
|
525
561
|
|
|
526
|
-
// @
|
|
562
|
+
// @alpha @sealed
|
|
563
|
+
export interface FluidContainer<TData = unknown> extends DataStoreCreator, ErasedBaseType<readonly ["FluidContainer", TData]> {
|
|
564
|
+
close(): void;
|
|
565
|
+
readonly data: TData;
|
|
566
|
+
readonly id?: string | undefined;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// @alpha @sealed
|
|
570
|
+
export interface FluidContainerAttached<TData = unknown> extends FluidContainer<TData> {
|
|
571
|
+
readonly id: string;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// @alpha @sealed
|
|
575
|
+
export interface FluidContainerWithService<TData = unknown> extends FluidContainer<TData> {
|
|
576
|
+
attach(): Promise<FluidContainerAttached<TData>>;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// @public @sealed
|
|
527
580
|
export interface FluidIterable<T> {
|
|
528
581
|
[Symbol.iterator](): FluidIterableIterator<T>;
|
|
529
582
|
}
|
|
530
583
|
|
|
531
|
-
// @
|
|
584
|
+
// @public @sealed
|
|
532
585
|
export interface FluidIterableIterator<T> extends FluidIterable<T> {
|
|
533
586
|
next(): {
|
|
534
587
|
value: T;
|
|
@@ -539,7 +592,7 @@ export interface FluidIterableIterator<T> extends FluidIterable<T> {
|
|
|
539
592
|
};
|
|
540
593
|
}
|
|
541
594
|
|
|
542
|
-
// @
|
|
595
|
+
// @public @sealed
|
|
543
596
|
export interface FluidMap<K, V> extends FluidReadonlyMap<K, V> {
|
|
544
597
|
delete(key: K): void;
|
|
545
598
|
forEach(callbackfn: (value: V, key: K, map: FluidMap<K, V>) => void, thisArg?: any): void;
|
|
@@ -554,7 +607,50 @@ export type FluidObject<T = unknown> = {
|
|
|
554
607
|
// @public
|
|
555
608
|
export type FluidObjectProviderKeys<T, TProp extends keyof T = keyof T> = string extends TProp ? never : number extends TProp ? never : TProp extends keyof Required<T>[TProp] ? Required<T>[TProp] extends Required<Required<T>[TProp]>[TProp] ? TProp : never : never;
|
|
556
609
|
|
|
557
|
-
// @
|
|
610
|
+
// @public @sealed
|
|
611
|
+
export interface FluidReadonlyArray<T> {
|
|
612
|
+
[Symbol.iterator](): FluidIterableIterator<T>;
|
|
613
|
+
readonly [Symbol.unscopables]: {
|
|
614
|
+
[K in keyof (readonly any[])]?: boolean;
|
|
615
|
+
};
|
|
616
|
+
readonly [n: number]: T;
|
|
617
|
+
at(index: number): T | undefined;
|
|
618
|
+
concat(...items: ConcatArray<T>[]): T[];
|
|
619
|
+
concat(...items: (T | ConcatArray<T>)[]): T[];
|
|
620
|
+
entries(): FluidIterableIterator<[number, T]>;
|
|
621
|
+
every<S extends T>(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): this is FluidReadonlyArray<S>;
|
|
622
|
+
every(predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any): boolean;
|
|
623
|
+
filter<S extends T>(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): S[];
|
|
624
|
+
filter(predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any): T[];
|
|
625
|
+
find<S extends T>(predicate: (value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined;
|
|
626
|
+
find(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined;
|
|
627
|
+
findIndex(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): number;
|
|
628
|
+
findLast<S extends T>(predicate: (value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined;
|
|
629
|
+
findLast(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined;
|
|
630
|
+
findLastIndex(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): number;
|
|
631
|
+
flat<A, D extends number = 1>(this: A, depth?: D): FlatArray<A, D>[];
|
|
632
|
+
flatMap<U, This = undefined>(callback: (this: This, value: T, index: number, array: T[]) => U | readonly U[], thisArg?: This): U[];
|
|
633
|
+
forEach(callbackfn: (value: T, index: number, array: readonly T[]) => void, thisArg?: any): void;
|
|
634
|
+
includes(searchElement: T, fromIndex?: number): boolean;
|
|
635
|
+
indexOf(searchElement: T, fromIndex?: number): number;
|
|
636
|
+
join(separator?: string): string;
|
|
637
|
+
keys(): FluidIterableIterator<number>;
|
|
638
|
+
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
|
639
|
+
readonly length: number;
|
|
640
|
+
map<U>(callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: any): U[];
|
|
641
|
+
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T): T;
|
|
642
|
+
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, initialValue: U): U;
|
|
643
|
+
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T): T;
|
|
644
|
+
reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, initialValue: U): U;
|
|
645
|
+
slice(start?: number, end?: number): T[];
|
|
646
|
+
some(predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any): boolean;
|
|
647
|
+
// (undocumented)
|
|
648
|
+
toLocaleString(): string;
|
|
649
|
+
toString(): string;
|
|
650
|
+
values(): FluidIterableIterator<T>;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// @public @sealed
|
|
558
654
|
export interface FluidReadonlyMap<K, V> {
|
|
559
655
|
[Symbol.iterator](): FluidIterableIterator<[K, V]>;
|
|
560
656
|
readonly [Symbol.toStringTag]: string;
|
|
@@ -999,6 +1095,9 @@ TSchema
|
|
|
999
1095
|
// @public
|
|
1000
1096
|
export type InsertableTypedNode<TSchema extends TreeNodeSchema, T = UnionToIntersection<TSchema>> = (T extends TreeNodeSchema<string, NodeKind, TreeNode | TreeLeafValue, never, true> ? NodeBuilderData<T> : never) | (T extends TreeNodeSchema ? Unhydrated<TreeNode extends NodeFromSchema<T> ? never : NodeFromSchema<T>> : never);
|
|
1001
1097
|
|
|
1098
|
+
// @alpha
|
|
1099
|
+
export function instantiateTreeFirstTime<TSchema extends ImplicitFieldSchema>(rootCreator: SharedObjectCreator, creator: SharedObjectCreator, treeKind: SharedObjectKey<ITree>, options: Pick<TreeDataStoreOptions<TSchema>, "config" | "initializer">): Promise<ITree>;
|
|
1100
|
+
|
|
1002
1101
|
// @public @sealed
|
|
1003
1102
|
export interface InternalTreeNode extends ErasedType<"@fluidframework/tree.InternalTreeNode"> {
|
|
1004
1103
|
}
|
|
@@ -1273,6 +1372,9 @@ export interface LogLevelConst {
|
|
|
1273
1372
|
readonly verbose: 10;
|
|
1274
1373
|
}
|
|
1275
1374
|
|
|
1375
|
+
// @alpha
|
|
1376
|
+
export function lookupInRegistry<TOut, TIn>(registry: Registry<TIn>, key: RegistryKey<TOut, TIn>): TOut;
|
|
1377
|
+
|
|
1276
1378
|
// @public @sealed
|
|
1277
1379
|
export interface MakeNominal {
|
|
1278
1380
|
}
|
|
@@ -1313,6 +1415,9 @@ export type MemberChangedListener<M extends IMember> = (clientId: string, member
|
|
|
1313
1415
|
// @alpha @deprecated
|
|
1314
1416
|
export const minimize: TransactionPostProcessor;
|
|
1315
1417
|
|
|
1418
|
+
// @alpha @input
|
|
1419
|
+
export type MinimumVersionForCollaboration = `2.${bigint}.0`;
|
|
1420
|
+
|
|
1316
1421
|
// @public
|
|
1317
1422
|
export type Myself<M extends IMember = IMember> = M & {
|
|
1318
1423
|
readonly currentConnection: string;
|
|
@@ -1475,6 +1580,15 @@ export const RecordNodeSchema: {
|
|
|
1475
1580
|
readonly [Symbol.hasInstance]: (value: TreeNodeSchema) => value is RecordNodeSchema<string, ImplicitAllowedTypes, true, unknown>;
|
|
1476
1581
|
};
|
|
1477
1582
|
|
|
1583
|
+
// @alpha @input
|
|
1584
|
+
export type Registry<T> = (type: string) => T;
|
|
1585
|
+
|
|
1586
|
+
// @alpha @sealed @input
|
|
1587
|
+
export interface RegistryKey<TOut, TIn = unknown> {
|
|
1588
|
+
adapt(value: TIn): TOut;
|
|
1589
|
+
readonly type: string;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1478
1592
|
// @alpha @sealed
|
|
1479
1593
|
export interface RemoteChangeMetadata extends CommitMetadata {
|
|
1480
1594
|
readonly getChange?: undefined;
|
|
@@ -1722,14 +1836,51 @@ export class SchemaUpgrade {
|
|
|
1722
1836
|
// @public @system
|
|
1723
1837
|
type ScopedSchemaName<TScope extends string | undefined, TName extends number | string> = TScope extends undefined ? `${TName}` : `${TScope}.${TName}`;
|
|
1724
1838
|
|
|
1839
|
+
// @alpha @sealed
|
|
1840
|
+
export interface ServiceClient {
|
|
1841
|
+
createContainer<T>(root: DataStoreKind<T>): Promise<FluidContainerWithService<T>>;
|
|
1842
|
+
createContainer<T>(root: DataStoreKey<T>, registry: DataStoreRegistry): Promise<FluidContainerWithService<T>>;
|
|
1843
|
+
loadContainer<T>(id: string, root: DataStoreKind<T> | DataStoreRegistry<T>): Promise<FluidContainerAttached<T>>;
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
// @alpha @input
|
|
1847
|
+
export interface ServiceOptions {
|
|
1848
|
+
// (undocumented)
|
|
1849
|
+
readonly minVersionForCollaboration: MinimumVersionForCollaboration;
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
// @alpha @sealed
|
|
1853
|
+
export interface SharedObjectCreator<TConstraint = IFluidLoadable> {
|
|
1854
|
+
createSharedObject<T extends TConstraint>(kind: SharedObjectKey<T>): Promise<T>;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
// @alpha @input
|
|
1858
|
+
export type SharedObjectKey<T> = RegistryKey<SharedObjectKindAlpha<T>, SharedObjectKindAlpha>;
|
|
1859
|
+
|
|
1725
1860
|
// @public @sealed
|
|
1726
1861
|
export interface SharedObjectKind<out TSharedObject = unknown> extends ErasedType<readonly ["SharedObjectKind", TSharedObject]> {
|
|
1727
1862
|
is(value: IFluidLoadable): value is IFluidLoadable & TSharedObject;
|
|
1728
1863
|
}
|
|
1729
1864
|
|
|
1865
|
+
// @alpha @sealed
|
|
1866
|
+
export interface SharedObjectKindAlpha<out TSharedObject = unknown> extends SharedObjectKind<TSharedObject>, SharedObjectKey<TSharedObject> {
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
// @alpha @input
|
|
1870
|
+
export type SharedObjectRegistry = () => Promise<Registry<SharedObjectKindAlpha<IFluidLoadable>>>;
|
|
1871
|
+
|
|
1872
|
+
// @alpha
|
|
1873
|
+
export function sharedObjectRegistryFromIterable(entries: Iterable<SharedObjectKindAlpha<IFluidLoadable> | {
|
|
1874
|
+
type: string;
|
|
1875
|
+
kind: () => Promise<SharedObjectKindAlpha<IFluidLoadable>>;
|
|
1876
|
+
}>): SharedObjectRegistry;
|
|
1877
|
+
|
|
1730
1878
|
// @public
|
|
1731
1879
|
export const SharedTree: SharedObjectKind<ITree>;
|
|
1732
1880
|
|
|
1881
|
+
// @alpha
|
|
1882
|
+
export const SharedTreeAlpha: SharedObjectKindAlpha<ITree>;
|
|
1883
|
+
|
|
1733
1884
|
// @alpha @input
|
|
1734
1885
|
export interface SharedTreeFormatOptions {
|
|
1735
1886
|
treeEncodeType: TreeCompressionStrategy;
|
|
@@ -2354,6 +2505,15 @@ export interface TreeContextAlpha {
|
|
|
2354
2505
|
runTransactionAsync(transaction: () => Promise<void>, params?: RunTransactionParamsAlpha): Promise<TransactionVoidResult>;
|
|
2355
2506
|
}
|
|
2356
2507
|
|
|
2508
|
+
// @alpha @input
|
|
2509
|
+
export interface TreeDataStoreOptions<TSchema extends ImplicitFieldSchema> extends Pick<DataStoreOptions<never, never>, "type"> {
|
|
2510
|
+
readonly config: TreeViewConfiguration<TSchema>;
|
|
2511
|
+
readonly initializer?: (creator: SharedObjectCreator) => InsertableTreeFieldFromImplicitField<TSchema>;
|
|
2512
|
+
// (undocumented)
|
|
2513
|
+
readonly key?: SharedObjectKey<ITree>;
|
|
2514
|
+
readonly registry?: Iterable<SharedObjectKindAlpha<IFluidLoadable>> | SharedObjectRegistry;
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2357
2517
|
// @beta @input
|
|
2358
2518
|
export interface TreeEncodingOptions<TKeyOptions = KeyEncodingOptions> {
|
|
2359
2519
|
readonly keys?: TKeyOptions;
|
|
@@ -2397,6 +2557,7 @@ export interface TreeMapNode<T extends ImplicitAllowedTypes = ImplicitAllowedTyp
|
|
|
2397
2557
|
|
|
2398
2558
|
// @alpha @sealed
|
|
2399
2559
|
export interface TreeMapNodeAlpha<T extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends FluidReadonlyMap<string, TreeNodeFromImplicitAllowedTypes<T>>, TreeNode, Pick<TreeMapNode<T>, "set" | "delete"> {
|
|
2560
|
+
clear(): void;
|
|
2400
2561
|
}
|
|
2401
2562
|
|
|
2402
2563
|
// @public @sealed
|
|
@@ -268,12 +268,12 @@ type FlexList<Item = unknown> = readonly LazyItem<Item>[];
|
|
|
268
268
|
// @public @system
|
|
269
269
|
type FlexListToUnion<TList extends FlexList> = ExtractItemType<TList[number]>;
|
|
270
270
|
|
|
271
|
-
// @
|
|
271
|
+
// @public @sealed
|
|
272
272
|
export interface FluidIterable<T> {
|
|
273
273
|
[Symbol.iterator](): FluidIterableIterator<T>;
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
// @
|
|
276
|
+
// @public @sealed
|
|
277
277
|
export interface FluidIterableIterator<T> extends FluidIterable<T> {
|
|
278
278
|
next(): {
|
|
279
279
|
value: T;
|
|
@@ -284,7 +284,7 @@ export interface FluidIterableIterator<T> extends FluidIterable<T> {
|
|
|
284
284
|
};
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
-
// @
|
|
287
|
+
// @public @sealed
|
|
288
288
|
export interface FluidMap<K, V> extends FluidReadonlyMap<K, V> {
|
|
289
289
|
delete(key: K): void;
|
|
290
290
|
forEach(callbackfn: (value: V, key: K, map: FluidMap<K, V>) => void, thisArg?: any): void;
|
|
@@ -299,7 +299,50 @@ export type FluidObject<T = unknown> = {
|
|
|
299
299
|
// @public
|
|
300
300
|
export type FluidObjectProviderKeys<T, TProp extends keyof T = keyof T> = string extends TProp ? never : number extends TProp ? never : TProp extends keyof Required<T>[TProp] ? Required<T>[TProp] extends Required<Required<T>[TProp]>[TProp] ? TProp : never : never;
|
|
301
301
|
|
|
302
|
-
// @
|
|
302
|
+
// @public @sealed
|
|
303
|
+
export interface FluidReadonlyArray<T> {
|
|
304
|
+
[Symbol.iterator](): FluidIterableIterator<T>;
|
|
305
|
+
readonly [Symbol.unscopables]: {
|
|
306
|
+
[K in keyof (readonly any[])]?: boolean;
|
|
307
|
+
};
|
|
308
|
+
readonly [n: number]: T;
|
|
309
|
+
at(index: number): T | undefined;
|
|
310
|
+
concat(...items: ConcatArray<T>[]): T[];
|
|
311
|
+
concat(...items: (T | ConcatArray<T>)[]): T[];
|
|
312
|
+
entries(): FluidIterableIterator<[number, T]>;
|
|
313
|
+
every<S extends T>(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): this is FluidReadonlyArray<S>;
|
|
314
|
+
every(predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any): boolean;
|
|
315
|
+
filter<S extends T>(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): S[];
|
|
316
|
+
filter(predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any): T[];
|
|
317
|
+
find<S extends T>(predicate: (value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined;
|
|
318
|
+
find(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined;
|
|
319
|
+
findIndex(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): number;
|
|
320
|
+
findLast<S extends T>(predicate: (value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined;
|
|
321
|
+
findLast(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined;
|
|
322
|
+
findLastIndex(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): number;
|
|
323
|
+
flat<A, D extends number = 1>(this: A, depth?: D): FlatArray<A, D>[];
|
|
324
|
+
flatMap<U, This = undefined>(callback: (this: This, value: T, index: number, array: T[]) => U | readonly U[], thisArg?: This): U[];
|
|
325
|
+
forEach(callbackfn: (value: T, index: number, array: readonly T[]) => void, thisArg?: any): void;
|
|
326
|
+
includes(searchElement: T, fromIndex?: number): boolean;
|
|
327
|
+
indexOf(searchElement: T, fromIndex?: number): number;
|
|
328
|
+
join(separator?: string): string;
|
|
329
|
+
keys(): FluidIterableIterator<number>;
|
|
330
|
+
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
|
331
|
+
readonly length: number;
|
|
332
|
+
map<U>(callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: any): U[];
|
|
333
|
+
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T): T;
|
|
334
|
+
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, initialValue: U): U;
|
|
335
|
+
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T): T;
|
|
336
|
+
reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, initialValue: U): U;
|
|
337
|
+
slice(start?: number, end?: number): T[];
|
|
338
|
+
some(predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any): boolean;
|
|
339
|
+
// (undocumented)
|
|
340
|
+
toLocaleString(): string;
|
|
341
|
+
toString(): string;
|
|
342
|
+
values(): FluidIterableIterator<T>;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// @public @sealed
|
|
303
346
|
export interface FluidReadonlyMap<K, V> {
|
|
304
347
|
[Symbol.iterator](): FluidIterableIterator<[K, V]>;
|
|
305
348
|
readonly [Symbol.toStringTag]: string;
|