@fluidframework/aqueduct 2.0.0-rc.2.0.1 → 2.0.0-rc.3.0.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/.eslintrc.cjs +14 -0
- package/.mocharc.cjs +12 -0
- package/CHANGELOG.md +342 -0
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +4 -0
- package/api-report/aqueduct.api.md +165 -0
- package/dist/container-runtime-factories/baseContainerRuntimeFactory.d.ts +7 -7
- package/dist/container-runtime-factories/baseContainerRuntimeFactory.d.ts.map +1 -1
- package/dist/container-runtime-factories/baseContainerRuntimeFactory.js +9 -10
- package/dist/container-runtime-factories/baseContainerRuntimeFactory.js.map +1 -1
- package/dist/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.d.ts +5 -5
- package/dist/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.d.ts.map +1 -1
- package/dist/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.js +2 -2
- package/dist/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.js.map +1 -1
- package/dist/data-object-factories/dataObjectFactory.d.ts +4 -4
- package/dist/data-object-factories/dataObjectFactory.d.ts.map +1 -1
- package/dist/data-object-factories/dataObjectFactory.js +7 -7
- package/dist/data-object-factories/dataObjectFactory.js.map +1 -1
- package/dist/data-object-factories/pureDataObjectFactory.d.ts +5 -5
- package/dist/data-object-factories/pureDataObjectFactory.d.ts.map +1 -1
- package/dist/data-object-factories/pureDataObjectFactory.js +9 -9
- package/dist/data-object-factories/pureDataObjectFactory.js.map +1 -1
- package/dist/data-objects/dataObject.d.ts +1 -1
- package/dist/data-objects/dataObject.d.ts.map +1 -1
- package/dist/data-objects/dataObject.js +3 -3
- package/dist/data-objects/dataObject.js.map +1 -1
- package/dist/data-objects/pureDataObject.d.ts +2 -2
- package/dist/data-objects/pureDataObject.d.ts.map +1 -1
- package/dist/data-objects/pureDataObject.js +6 -6
- package/dist/data-objects/pureDataObject.js.map +1 -1
- package/dist/data-objects/types.d.ts +3 -3
- package/dist/data-objects/types.d.ts.map +1 -1
- package/dist/data-objects/types.js.map +1 -1
- package/dist/legacy.d.ts +23 -0
- package/dist/public.d.ts +12 -0
- package/internal.d.ts +11 -0
- package/legacy.d.ts +11 -0
- package/lib/container-runtime-factories/baseContainerRuntimeFactory.d.ts +7 -7
- package/lib/container-runtime-factories/baseContainerRuntimeFactory.d.ts.map +1 -1
- package/lib/container-runtime-factories/baseContainerRuntimeFactory.js +5 -4
- package/lib/container-runtime-factories/baseContainerRuntimeFactory.js.map +1 -1
- package/lib/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.d.ts +5 -5
- package/lib/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.d.ts.map +1 -1
- package/lib/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.js +1 -1
- package/lib/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.js.map +1 -1
- package/lib/data-object-factories/dataObjectFactory.d.ts +4 -4
- package/lib/data-object-factories/dataObjectFactory.d.ts.map +1 -1
- package/lib/data-object-factories/dataObjectFactory.js +2 -2
- package/lib/data-object-factories/dataObjectFactory.js.map +1 -1
- package/lib/data-object-factories/pureDataObjectFactory.d.ts +5 -5
- package/lib/data-object-factories/pureDataObjectFactory.d.ts.map +1 -1
- package/lib/data-object-factories/pureDataObjectFactory.js +3 -3
- package/lib/data-object-factories/pureDataObjectFactory.js.map +1 -1
- package/lib/data-objects/dataObject.d.ts +1 -1
- package/lib/data-objects/dataObject.d.ts.map +1 -1
- package/lib/data-objects/dataObject.js +1 -1
- package/lib/data-objects/dataObject.js.map +1 -1
- package/lib/data-objects/pureDataObject.d.ts +2 -2
- package/lib/data-objects/pureDataObject.d.ts.map +1 -1
- package/lib/data-objects/pureDataObject.js +2 -2
- package/lib/data-objects/pureDataObject.js.map +1 -1
- package/lib/data-objects/types.d.ts +3 -3
- package/lib/data-objects/types.d.ts.map +1 -1
- package/lib/data-objects/types.js.map +1 -1
- package/lib/legacy.d.ts +23 -0
- package/lib/public.d.ts +12 -0
- package/package.json +39 -64
- package/prettier.config.cjs +8 -0
- package/src/container-runtime-factories/baseContainerRuntimeFactory.ts +142 -0
- package/src/container-runtime-factories/containerRuntimeFactoryWithDefaultDataStore.ts +110 -0
- package/src/container-runtime-factories/index.ts +13 -0
- package/src/data-object-factories/dataObjectFactory.ts +61 -0
- package/src/data-object-factories/index.ts +7 -0
- package/src/data-object-factories/pureDataObjectFactory.ts +379 -0
- package/src/data-objects/dataObject.ts +78 -0
- package/src/data-objects/index.ts +8 -0
- package/src/data-objects/pureDataObject.ts +186 -0
- package/src/data-objects/types.ts +40 -0
- package/src/index.ts +33 -0
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +9 -0
- package/dist/aqueduct-alpha.d.ts +0 -433
- package/dist/aqueduct-beta.d.ts +0 -110
- package/dist/aqueduct-public.d.ts +0 -110
- package/dist/aqueduct-untrimmed.d.ts +0 -433
- package/lib/aqueduct-alpha.d.ts +0 -433
- package/lib/aqueduct-beta.d.ts +0 -110
- package/lib/aqueduct-public.d.ts +0 -110
- package/lib/aqueduct-untrimmed.d.ts +0 -433
- package/lib/test/aqueduct.spec.js +0 -8
- package/lib/test/aqueduct.spec.js.map +0 -1
- package/lib/test/tsconfig.tsbuildinfo +0 -1
- package/lib/test/types/validateAqueductPrevious.generated.js +0 -24
- package/lib/test/types/validateAqueductPrevious.generated.js.map +0 -1
- /package/{dist → lib}/tsdoc-metadata.json +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FluidDataStoreRuntime } from "@fluidframework/datastore/internal";
|
|
7
|
+
import { type IChannelFactory } from "@fluidframework/datastore-definitions";
|
|
8
|
+
import {
|
|
9
|
+
SharedMap,
|
|
10
|
+
DirectoryFactory,
|
|
11
|
+
MapFactory,
|
|
12
|
+
SharedDirectory,
|
|
13
|
+
} from "@fluidframework/map/internal";
|
|
14
|
+
import { type NamedFluidDataStoreRegistryEntries } from "@fluidframework/runtime-definitions/internal";
|
|
15
|
+
import { type FluidObjectSymbolProvider } from "@fluidframework/synthesize/internal";
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
type DataObject,
|
|
19
|
+
type DataObjectTypes,
|
|
20
|
+
type IDataObjectProps,
|
|
21
|
+
} from "../data-objects/index.js";
|
|
22
|
+
|
|
23
|
+
import { PureDataObjectFactory } from "./pureDataObjectFactory.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* DataObjectFactory is the IFluidDataStoreFactory for use with DataObjects.
|
|
27
|
+
* It facilitates DataObject's features (such as its shared directory) by
|
|
28
|
+
* ensuring relevant shared objects etc are available to the factory.
|
|
29
|
+
*
|
|
30
|
+
* @typeParam TObj - DataObject (concrete type)
|
|
31
|
+
* @typeParam I - The input types for the DataObject
|
|
32
|
+
* @alpha
|
|
33
|
+
*/
|
|
34
|
+
export class DataObjectFactory<
|
|
35
|
+
TObj extends DataObject<I>,
|
|
36
|
+
I extends DataObjectTypes = DataObjectTypes,
|
|
37
|
+
> extends PureDataObjectFactory<TObj, I> {
|
|
38
|
+
public constructor(
|
|
39
|
+
type: string,
|
|
40
|
+
ctor: new (props: IDataObjectProps<I>) => TObj,
|
|
41
|
+
sharedObjects: readonly IChannelFactory[] = [],
|
|
42
|
+
optionalProviders: FluidObjectSymbolProvider<I["OptionalProviders"]>,
|
|
43
|
+
registryEntries?: NamedFluidDataStoreRegistryEntries,
|
|
44
|
+
runtimeFactory: typeof FluidDataStoreRuntime = FluidDataStoreRuntime,
|
|
45
|
+
) {
|
|
46
|
+
const mergedObjects = [...sharedObjects];
|
|
47
|
+
|
|
48
|
+
if (!sharedObjects.some((factory) => factory.type === DirectoryFactory.Type)) {
|
|
49
|
+
// User did not register for directory
|
|
50
|
+
mergedObjects.push(SharedDirectory.getFactory());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// TODO: Remove SharedMap factory when compatibility with SharedMap DataObject is no longer needed in 0.10
|
|
54
|
+
if (!sharedObjects.some((factory) => factory.type === MapFactory.Type)) {
|
|
55
|
+
// User did not register for map
|
|
56
|
+
mergedObjects.push(SharedMap.getFactory());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
super(type, ctor, mergedObjects, optionalProviders, registryEntries, runtimeFactory);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FluidDataStoreRegistry } from "@fluidframework/container-runtime/internal";
|
|
7
|
+
import { type IContainerRuntime } from "@fluidframework/container-runtime-definitions/internal";
|
|
8
|
+
import { type FluidObject, type IRequest } from "@fluidframework/core-interfaces";
|
|
9
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
10
|
+
import {
|
|
11
|
+
FluidDataStoreRuntime,
|
|
12
|
+
type ISharedObjectRegistry,
|
|
13
|
+
mixinRequestHandler,
|
|
14
|
+
} from "@fluidframework/datastore/internal";
|
|
15
|
+
import {
|
|
16
|
+
type IChannelFactory,
|
|
17
|
+
type IFluidDataStoreRuntime,
|
|
18
|
+
} from "@fluidframework/datastore-definitions";
|
|
19
|
+
import {
|
|
20
|
+
type IContainerRuntimeBase,
|
|
21
|
+
type IDataStore,
|
|
22
|
+
type IFluidDataStoreChannel,
|
|
23
|
+
type IFluidDataStoreContext,
|
|
24
|
+
type IFluidDataStoreContextDetached,
|
|
25
|
+
type IFluidDataStoreFactory,
|
|
26
|
+
type IFluidDataStoreRegistry,
|
|
27
|
+
type IProvideFluidDataStoreRegistry,
|
|
28
|
+
type NamedFluidDataStoreRegistryEntries,
|
|
29
|
+
type NamedFluidDataStoreRegistryEntry,
|
|
30
|
+
} from "@fluidframework/runtime-definitions/internal";
|
|
31
|
+
import {
|
|
32
|
+
type AsyncFluidObjectProvider,
|
|
33
|
+
type FluidObjectSymbolProvider,
|
|
34
|
+
type IFluidDependencySynthesizer,
|
|
35
|
+
} from "@fluidframework/synthesize/internal";
|
|
36
|
+
|
|
37
|
+
import {
|
|
38
|
+
type DataObjectTypes,
|
|
39
|
+
type IDataObjectProps,
|
|
40
|
+
type PureDataObject,
|
|
41
|
+
} from "../data-objects/index.js";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Proxy over PureDataObject
|
|
45
|
+
* Does delayed creation & initialization of PureDataObject
|
|
46
|
+
*/
|
|
47
|
+
async function createDataObject<
|
|
48
|
+
TObj extends PureDataObject,
|
|
49
|
+
I extends DataObjectTypes = DataObjectTypes,
|
|
50
|
+
>(
|
|
51
|
+
ctor: new (props: IDataObjectProps<I>) => TObj,
|
|
52
|
+
context: IFluidDataStoreContext,
|
|
53
|
+
sharedObjectRegistry: ISharedObjectRegistry,
|
|
54
|
+
optionalProviders: FluidObjectSymbolProvider<I["OptionalProviders"]>,
|
|
55
|
+
runtimeClassArg: typeof FluidDataStoreRuntime,
|
|
56
|
+
existing: boolean,
|
|
57
|
+
initProps?: I["InitialState"],
|
|
58
|
+
): Promise<{
|
|
59
|
+
instance: TObj;
|
|
60
|
+
runtime: FluidDataStoreRuntime;
|
|
61
|
+
}> {
|
|
62
|
+
// base
|
|
63
|
+
let runtimeClass = runtimeClassArg;
|
|
64
|
+
|
|
65
|
+
// request mixin in
|
|
66
|
+
runtimeClass = mixinRequestHandler(
|
|
67
|
+
async (request: IRequest, runtimeArg: FluidDataStoreRuntime) => {
|
|
68
|
+
// The provideEntryPoint callback below always returns TObj, so this cast is safe
|
|
69
|
+
const dataObject = (await runtimeArg.entryPoint.get()) as TObj;
|
|
70
|
+
assert(
|
|
71
|
+
dataObject.request !== undefined,
|
|
72
|
+
0x795 /* Data store runtime entryPoint does not have request */,
|
|
73
|
+
);
|
|
74
|
+
return dataObject.request(request);
|
|
75
|
+
},
|
|
76
|
+
runtimeClass,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Create a new runtime for our data store, as if via new FluidDataStoreRuntime,
|
|
80
|
+
// but using the runtimeClass that's been augmented with mixins
|
|
81
|
+
// The runtime is what Fluid uses to create DDS' and route to your data store
|
|
82
|
+
const runtime: FluidDataStoreRuntime = new runtimeClass( // calls new FluidDataStoreRuntime(...)
|
|
83
|
+
context,
|
|
84
|
+
sharedObjectRegistry,
|
|
85
|
+
existing,
|
|
86
|
+
async (rt: IFluidDataStoreRuntime) => {
|
|
87
|
+
assert(instance !== undefined, 0x46a /* entryPoint is undefined */);
|
|
88
|
+
// Calling finishInitialization here like PureDataObject.getDataObject did, to keep the same behavior,
|
|
89
|
+
// since accessing the runtime's entryPoint is how we want the data object to be retrieved going forward.
|
|
90
|
+
// Without this I ran into issues with the load-existing flow not working correctly.
|
|
91
|
+
await instance.finishInitialization(true);
|
|
92
|
+
return instance;
|
|
93
|
+
} /* provideEntryPoint */,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Create object right away.
|
|
97
|
+
// This allows object to register various callbacks with runtime before runtime
|
|
98
|
+
// becomes globally available. But it's not full initialization - constructor can't
|
|
99
|
+
// access DDSes or other services of runtime as objects are not fully initialized.
|
|
100
|
+
// In order to use object, we need to go through full initialization by calling finishInitialization().
|
|
101
|
+
const scope: FluidObject<IFluidDependencySynthesizer> = context.scope;
|
|
102
|
+
const providers =
|
|
103
|
+
scope.IFluidDependencySynthesizer?.synthesize<I["OptionalProviders"]>(
|
|
104
|
+
optionalProviders,
|
|
105
|
+
{},
|
|
106
|
+
) ??
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
108
|
+
({} as AsyncFluidObjectProvider<never>);
|
|
109
|
+
|
|
110
|
+
const instance = new ctor({ runtime, context, providers, initProps });
|
|
111
|
+
|
|
112
|
+
// if it's a newly created object, we need to wait for it to finish initialization
|
|
113
|
+
// as that results in creation of DDSes, before it gets attached, providing atomic
|
|
114
|
+
// guarantee of creation.
|
|
115
|
+
// WARNING: we can't do the same (yet) for already existing PureDataObject!
|
|
116
|
+
// This will result in deadlock, as it tries to resolve internal handles, but any
|
|
117
|
+
// handle resolution goes through root (container runtime), which can't route it back
|
|
118
|
+
// to this data store, as it's still not initialized and not known to container runtime yet.
|
|
119
|
+
// In the future, we should address it by using relative paths for handles and be able to resolve
|
|
120
|
+
// local DDSes while data store is not fully initialized.
|
|
121
|
+
if (!existing) {
|
|
122
|
+
await instance.finishInitialization(existing);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { instance, runtime };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* PureDataObjectFactory is a barebones IFluidDataStoreFactory for use with PureDataObject.
|
|
130
|
+
* Consumers should typically use DataObjectFactory instead unless creating
|
|
131
|
+
* another base data store factory.
|
|
132
|
+
*
|
|
133
|
+
* @typeParam TObj - DataObject (concrete type)
|
|
134
|
+
* @typeParam I - The input types for the DataObject
|
|
135
|
+
* @alpha
|
|
136
|
+
*/
|
|
137
|
+
export class PureDataObjectFactory<
|
|
138
|
+
TObj extends PureDataObject<I>,
|
|
139
|
+
I extends DataObjectTypes = DataObjectTypes,
|
|
140
|
+
>
|
|
141
|
+
implements IFluidDataStoreFactory, Partial<IProvideFluidDataStoreRegistry>
|
|
142
|
+
{
|
|
143
|
+
private readonly sharedObjectRegistry: ISharedObjectRegistry;
|
|
144
|
+
private readonly registry: IFluidDataStoreRegistry | undefined;
|
|
145
|
+
|
|
146
|
+
public constructor(
|
|
147
|
+
/**
|
|
148
|
+
* {@inheritDoc @fluidframework/runtime-definitions#IFluidDataStoreFactory."type"}
|
|
149
|
+
*/
|
|
150
|
+
public readonly type: string,
|
|
151
|
+
private readonly ctor: new (props: IDataObjectProps<I>) => TObj,
|
|
152
|
+
sharedObjects: readonly IChannelFactory[],
|
|
153
|
+
private readonly optionalProviders: FluidObjectSymbolProvider<I["OptionalProviders"]>,
|
|
154
|
+
registryEntries?: NamedFluidDataStoreRegistryEntries,
|
|
155
|
+
private readonly runtimeClass: typeof FluidDataStoreRuntime = FluidDataStoreRuntime,
|
|
156
|
+
) {
|
|
157
|
+
if (this.type === "") {
|
|
158
|
+
throw new Error("undefined type member");
|
|
159
|
+
}
|
|
160
|
+
if (registryEntries !== undefined) {
|
|
161
|
+
this.registry = new FluidDataStoreRegistry(registryEntries);
|
|
162
|
+
}
|
|
163
|
+
this.sharedObjectRegistry = new Map(sharedObjects.map((ext) => [ext.type, ext]));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* {@inheritDoc @fluidframework/runtime-definitions#IProvideFluidDataStoreFactory.IFluidDataStoreFactory}
|
|
168
|
+
*/
|
|
169
|
+
public get IFluidDataStoreFactory(): this {
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* {@inheritDoc @fluidframework/runtime-definitions#IProvideFluidDataStoreRegistry.IFluidDataStoreRegistry}
|
|
175
|
+
*/
|
|
176
|
+
public get IFluidDataStoreRegistry(): IFluidDataStoreRegistry | undefined {
|
|
177
|
+
return this.registry;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Convenience helper to get the data store's/factory's data store registry entry.
|
|
182
|
+
* The return type hides the factory's generics, easing grouping of registry
|
|
183
|
+
* entries that differ only in this way into the same array.
|
|
184
|
+
* @returns The NamedFluidDataStoreRegistryEntry
|
|
185
|
+
*/
|
|
186
|
+
public get registryEntry(): NamedFluidDataStoreRegistryEntry {
|
|
187
|
+
return [this.type, Promise.resolve(this)];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* {@inheritDoc @fluidframework/runtime-definitions#IFluidDataStoreFactory.instantiateDataStore}
|
|
192
|
+
*/
|
|
193
|
+
public async instantiateDataStore(
|
|
194
|
+
context: IFluidDataStoreContext,
|
|
195
|
+
existing: boolean,
|
|
196
|
+
): Promise<IFluidDataStoreChannel> {
|
|
197
|
+
const { runtime } = await createDataObject(
|
|
198
|
+
this.ctor,
|
|
199
|
+
context,
|
|
200
|
+
this.sharedObjectRegistry,
|
|
201
|
+
this.optionalProviders,
|
|
202
|
+
this.runtimeClass,
|
|
203
|
+
existing,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
return runtime;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Creates a new instance of the object. Uses parent context's registry to build package path to this factory.
|
|
211
|
+
* In other words, registry of context passed in has to contain this factory, with the name that matches
|
|
212
|
+
* this factory's type.
|
|
213
|
+
* It is intended to be used by data store objects that create sub-objects.
|
|
214
|
+
* @param context - The context being used to create the runtime
|
|
215
|
+
* (the created object will have its own new context created as well)
|
|
216
|
+
* @param initialState - The initial state to provide to the created data store.
|
|
217
|
+
* @param loadingGroupId - NOT production ready, EXPERIMENTAL, please read {@link https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/README.md | README}. The service needs to support this feature, does not work for most services
|
|
218
|
+
* @returns an object created by this factory. Data store and objects created are not attached to container.
|
|
219
|
+
* They get attached only when a handle to one of them is attached to already attached objects.
|
|
220
|
+
*/
|
|
221
|
+
public async createChildInstance(
|
|
222
|
+
parentContext: IFluidDataStoreContext,
|
|
223
|
+
initialState?: I["InitialState"],
|
|
224
|
+
loadingGroupId?: string,
|
|
225
|
+
): Promise<TObj> {
|
|
226
|
+
return this.createNonRootInstanceCore(
|
|
227
|
+
parentContext.containerRuntime,
|
|
228
|
+
[...parentContext.packagePath, this.type],
|
|
229
|
+
initialState,
|
|
230
|
+
loadingGroupId,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Creates a new instance of the object. Uses peer context's registry and its package path to identify this factory.
|
|
236
|
+
* In other words, registry of context passed in has to have this factory.
|
|
237
|
+
* Intended to be used by data store objects that need to create peers (similar) instances of existing objects.
|
|
238
|
+
* @param context - The component context being used to create the object
|
|
239
|
+
* (the created object will have its own new context created as well)
|
|
240
|
+
* @param initialState - The initial state to provide to the created component.
|
|
241
|
+
* @param loadingGroupId - NOT production ready, EXPERIMENTAL, please read {@link https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/README.md | README}. The service needs to support this feature, does not work for most services
|
|
242
|
+
* @returns an object created by this factory. Data store and objects created are not attached to container.
|
|
243
|
+
* They get attached only when a handle to one of them is attached to already attached objects.
|
|
244
|
+
*/
|
|
245
|
+
public async createPeerInstance(
|
|
246
|
+
peerContext: IFluidDataStoreContext,
|
|
247
|
+
initialState?: I["InitialState"],
|
|
248
|
+
loadingGroupId?: string, // DO NOT USE, this is an experimental feature
|
|
249
|
+
): Promise<TObj> {
|
|
250
|
+
return this.createNonRootInstanceCore(
|
|
251
|
+
peerContext.containerRuntime,
|
|
252
|
+
peerContext.packagePath,
|
|
253
|
+
initialState,
|
|
254
|
+
loadingGroupId,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Creates a new instance of the object. Uses container's registry to find this factory.
|
|
260
|
+
* It's expected that only container owners would use this functionality, as only such developers
|
|
261
|
+
* have knowledge of entries in container registry.
|
|
262
|
+
* The name in this registry for such record should match type of this factory.
|
|
263
|
+
* @param runtime - container runtime. It's registry is used to create an object.
|
|
264
|
+
* @param initialState - The initial state to provide to the created component.
|
|
265
|
+
* @param loadingGroupId - NOT production ready, EXPERIMENTAL, please read {@link https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/README.md | README}. The service needs to support this feature, does not work for most services
|
|
266
|
+
* @returns an object created by this factory. Data store and objects created are not attached to container.
|
|
267
|
+
* They get attached only when a handle to one of them is attached to already attached objects.
|
|
268
|
+
*/
|
|
269
|
+
public async createInstance(
|
|
270
|
+
runtime: IContainerRuntimeBase,
|
|
271
|
+
initialState?: I["InitialState"],
|
|
272
|
+
loadingGroupId?: string,
|
|
273
|
+
): Promise<TObj> {
|
|
274
|
+
return this.createNonRootInstanceCore(runtime, [this.type], initialState, loadingGroupId);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Creates a new instance of the object with a datastore which exposes the aliasing api.
|
|
279
|
+
* @param runtime - container runtime. It is the runtime that will be used to create the object. It will produce
|
|
280
|
+
* the underlying infrastructure to get the data object to operate.
|
|
281
|
+
* @param initialState - The initial state to provide to the created component.
|
|
282
|
+
* @param packagePath - The path to the data store factory to use to create the data object.
|
|
283
|
+
* @param loadingGroupId - NOT production ready, EXPERIMENTAL, please read {@link https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/README.md | README}. The service needs to support this feature, does not work for most services
|
|
284
|
+
* @returns an array containing the object created by this factory and an IDataStore object that enables users to
|
|
285
|
+
* alias the data object.
|
|
286
|
+
* The data object is attached only when it is attached to the handle graph that connects to an aliased object or
|
|
287
|
+
* when the data object is aliased.
|
|
288
|
+
*/
|
|
289
|
+
public async createInstanceWithDataStore(
|
|
290
|
+
containerRuntime: IContainerRuntimeBase,
|
|
291
|
+
initialState?: I["InitialState"],
|
|
292
|
+
packagePath?: Readonly<string[]>,
|
|
293
|
+
loadingGroupId?: string,
|
|
294
|
+
): Promise<[TObj, IDataStore]> {
|
|
295
|
+
const context = containerRuntime.createDetachedDataStore(
|
|
296
|
+
packagePath ?? [this.type],
|
|
297
|
+
loadingGroupId,
|
|
298
|
+
);
|
|
299
|
+
const { instance, runtime } = await createDataObject(
|
|
300
|
+
this.ctor,
|
|
301
|
+
context,
|
|
302
|
+
this.sharedObjectRegistry,
|
|
303
|
+
this.optionalProviders,
|
|
304
|
+
this.runtimeClass,
|
|
305
|
+
false, // existing
|
|
306
|
+
initialState,
|
|
307
|
+
);
|
|
308
|
+
const dataStore = await context.attachRuntime(this, runtime);
|
|
309
|
+
|
|
310
|
+
return [instance, dataStore];
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Creates a new root instance of the object. Uses container's registry to find this factory.
|
|
315
|
+
* It's expected that only container owners would use this functionality, as only such developers
|
|
316
|
+
* have knowledge of entries in container registry.
|
|
317
|
+
* The name in this registry for such record should match type of this factory.
|
|
318
|
+
* @param runtime - container runtime. It's registry is used to create an object.
|
|
319
|
+
* @param initialState - The initial state to provide to the created component.
|
|
320
|
+
* @returns an object created by this factory. Data store and objects created are not attached to container.
|
|
321
|
+
* They get attached only when a handle to one of them is attached to already attached objects.
|
|
322
|
+
*
|
|
323
|
+
* @deprecated - the issue is that it does not allow the customer to decide the conflict resolution policy when an
|
|
324
|
+
* aliasing conflict occurs. Use {@link PureDataObjectFactory.createInstanceWithDataStore} instead.
|
|
325
|
+
*/
|
|
326
|
+
public async createRootInstance(
|
|
327
|
+
rootDataStoreId: string,
|
|
328
|
+
runtime: IContainerRuntime,
|
|
329
|
+
initialState?: I["InitialState"],
|
|
330
|
+
): Promise<TObj> {
|
|
331
|
+
const context = runtime.createDetachedDataStore([this.type]);
|
|
332
|
+
const { instance, runtime: dataStoreRuntime } = await createDataObject(
|
|
333
|
+
this.ctor,
|
|
334
|
+
context,
|
|
335
|
+
this.sharedObjectRegistry,
|
|
336
|
+
this.optionalProviders,
|
|
337
|
+
this.runtimeClass,
|
|
338
|
+
false, // existing
|
|
339
|
+
initialState,
|
|
340
|
+
);
|
|
341
|
+
const dataStore = await context.attachRuntime(this, dataStoreRuntime);
|
|
342
|
+
const result = await dataStore.trySetAlias(rootDataStoreId);
|
|
343
|
+
if (result !== "Success") {
|
|
344
|
+
const handle = await runtime.getAliasedDataStoreEntryPoint(rootDataStoreId);
|
|
345
|
+
assert(handle !== undefined, 0x8e1 /* Should have retrieved aliased handle */);
|
|
346
|
+
return (await handle.get()) as TObj;
|
|
347
|
+
}
|
|
348
|
+
return instance;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
protected async createNonRootInstanceCore(
|
|
352
|
+
containerRuntime: IContainerRuntimeBase,
|
|
353
|
+
packagePath: Readonly<string[]>,
|
|
354
|
+
initialState?: I["InitialState"],
|
|
355
|
+
loadingGroupId?: string,
|
|
356
|
+
): Promise<TObj> {
|
|
357
|
+
const context = containerRuntime.createDetachedDataStore(packagePath, loadingGroupId);
|
|
358
|
+
return this.createInstanceCore(context, initialState);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
protected async createInstanceCore(
|
|
362
|
+
context: IFluidDataStoreContextDetached,
|
|
363
|
+
initialState?: I["InitialState"],
|
|
364
|
+
): Promise<TObj> {
|
|
365
|
+
const { instance, runtime } = await createDataObject(
|
|
366
|
+
this.ctor,
|
|
367
|
+
context,
|
|
368
|
+
this.sharedObjectRegistry,
|
|
369
|
+
this.optionalProviders,
|
|
370
|
+
this.runtimeClass,
|
|
371
|
+
false, // existing
|
|
372
|
+
initialState,
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
await context.attachRuntime(this, runtime);
|
|
376
|
+
|
|
377
|
+
return instance;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { type ISharedDirectory, MapFactory, SharedDirectory } from "@fluidframework/map/internal";
|
|
7
|
+
|
|
8
|
+
import { PureDataObject } from "./pureDataObject.js";
|
|
9
|
+
import { type DataObjectTypes } from "./types.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* DataObject is a base data store that is primed with a root directory. It
|
|
13
|
+
* ensures that it is created and ready before you can access it.
|
|
14
|
+
*
|
|
15
|
+
* Having a single root directory allows for easier development. Instead of creating
|
|
16
|
+
* and registering channels with the runtime any new DDS that is set on the root
|
|
17
|
+
* will automatically be registered.
|
|
18
|
+
*
|
|
19
|
+
* @typeParam I - The optional input types used to strongly type the data object
|
|
20
|
+
* @alpha
|
|
21
|
+
*/
|
|
22
|
+
export abstract class DataObject<
|
|
23
|
+
I extends DataObjectTypes = DataObjectTypes,
|
|
24
|
+
> extends PureDataObject<I> {
|
|
25
|
+
private internalRoot: ISharedDirectory | undefined;
|
|
26
|
+
private readonly rootDirectoryId = "root";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The root directory will either be ready or will return an error. If an error is thrown
|
|
30
|
+
* the root has not been correctly created/set.
|
|
31
|
+
*/
|
|
32
|
+
protected get root(): ISharedDirectory {
|
|
33
|
+
if (!this.internalRoot) {
|
|
34
|
+
throw new Error(this.getUninitializedErrorString(`root`));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return this.internalRoot;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Initializes internal objects and calls initialization overrides.
|
|
42
|
+
* Caller is responsible for ensuring this is only invoked once.
|
|
43
|
+
*/
|
|
44
|
+
public async initializeInternal(existing: boolean): Promise<void> {
|
|
45
|
+
if (existing) {
|
|
46
|
+
// data store has a root directory so we just need to set it before calling initializingFromExisting
|
|
47
|
+
this.internalRoot = (await this.runtime.getChannel(
|
|
48
|
+
this.rootDirectoryId,
|
|
49
|
+
)) as ISharedDirectory;
|
|
50
|
+
|
|
51
|
+
// This will actually be an ISharedMap if the channel was previously created by the older version of
|
|
52
|
+
// DataObject which used a SharedMap. Since SharedMap and SharedDirectory are compatible unless
|
|
53
|
+
// SharedDirectory-only commands are used on SharedMap, this will mostly just work for compatibility.
|
|
54
|
+
if (this.internalRoot.attributes.type === MapFactory.Type) {
|
|
55
|
+
this.runtime.logger.send({
|
|
56
|
+
category: "generic",
|
|
57
|
+
eventName: "MapDataObject",
|
|
58
|
+
message:
|
|
59
|
+
"Legacy document, SharedMap is masquerading as SharedDirectory in DataObject",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
// Create a root directory and register it before calling initializingFirstTime
|
|
64
|
+
this.internalRoot = SharedDirectory.create(this.runtime, this.rootDirectoryId);
|
|
65
|
+
this.internalRoot.bindToContext();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await super.initializeInternal(existing);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Generates an error string indicating an item is uninitialized.
|
|
73
|
+
* @param item - The name of the item that was uninitialized.
|
|
74
|
+
*/
|
|
75
|
+
protected getUninitializedErrorString(item: string): string {
|
|
76
|
+
return `${item} must be initialized before being accessed.`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { DataObject } from "./dataObject.js";
|
|
7
|
+
export { PureDataObject } from "./pureDataObject.js";
|
|
8
|
+
export type { DataObjectTypes, IDataObjectProps } from "./types.js";
|