@fluidframework/shared-object-base 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.
Files changed (56) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/dist/dataStoreKind.d.ts +118 -0
  3. package/dist/dataStoreKind.d.ts.map +1 -0
  4. package/dist/dataStoreKind.js +137 -0
  5. package/dist/dataStoreKind.js.map +1 -0
  6. package/dist/index.d.ts +4 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +7 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/packageVersion.d.ts +1 -1
  11. package/dist/packageVersion.d.ts.map +1 -1
  12. package/dist/packageVersion.js +1 -1
  13. package/dist/packageVersion.js.map +1 -1
  14. package/dist/sharedObject.d.ts +35 -1
  15. package/dist/sharedObject.d.ts.map +1 -1
  16. package/dist/sharedObject.js +27 -3
  17. package/dist/sharedObject.js.map +1 -1
  18. package/dist/sharedObjectKernel.d.ts +2 -2
  19. package/dist/sharedObjectKernel.d.ts.map +1 -1
  20. package/dist/sharedObjectKernel.js +1 -1
  21. package/dist/sharedObjectKernel.js.map +1 -1
  22. package/dist/stubSharedObject.d.ts +13 -0
  23. package/dist/stubSharedObject.d.ts.map +1 -0
  24. package/dist/stubSharedObject.js +58 -0
  25. package/dist/stubSharedObject.js.map +1 -0
  26. package/lib/dataStoreKind.d.ts +118 -0
  27. package/lib/dataStoreKind.d.ts.map +1 -0
  28. package/lib/dataStoreKind.js +132 -0
  29. package/lib/dataStoreKind.js.map +1 -0
  30. package/lib/index.d.ts +4 -1
  31. package/lib/index.d.ts.map +1 -1
  32. package/lib/index.js +3 -1
  33. package/lib/index.js.map +1 -1
  34. package/lib/packageVersion.d.ts +1 -1
  35. package/lib/packageVersion.d.ts.map +1 -1
  36. package/lib/packageVersion.js +1 -1
  37. package/lib/packageVersion.js.map +1 -1
  38. package/lib/sharedObject.d.ts +35 -1
  39. package/lib/sharedObject.d.ts.map +1 -1
  40. package/lib/sharedObject.js +25 -2
  41. package/lib/sharedObject.js.map +1 -1
  42. package/lib/sharedObjectKernel.d.ts +2 -2
  43. package/lib/sharedObjectKernel.d.ts.map +1 -1
  44. package/lib/sharedObjectKernel.js +2 -2
  45. package/lib/sharedObjectKernel.js.map +1 -1
  46. package/lib/stubSharedObject.d.ts +13 -0
  47. package/lib/stubSharedObject.d.ts.map +1 -0
  48. package/lib/stubSharedObject.js +54 -0
  49. package/lib/stubSharedObject.js.map +1 -0
  50. package/package.json +20 -20
  51. package/src/dataStoreKind.ts +301 -0
  52. package/src/index.ts +11 -0
  53. package/src/packageVersion.ts +1 -1
  54. package/src/sharedObject.ts +60 -2
  55. package/src/sharedObjectKernel.ts +4 -4
  56. package/src/stubSharedObject.ts +66 -0
@@ -0,0 +1,301 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import type { IFluidLoadable, FluidObject } from "@fluidframework/core-interfaces";
7
+ import {
8
+ type ISharedObjectRegistry,
9
+ FluidDataStoreRuntime,
10
+ } from "@fluidframework/datastore/internal";
11
+ import type { IFluidDataStoreRuntime } from "@fluidframework/datastore-definitions/internal";
12
+ import {
13
+ type Registry,
14
+ type DataStoreKind,
15
+ lookupInRegistry,
16
+ } from "@fluidframework/driver-definitions/internal";
17
+ import type {
18
+ IFluidDataStoreContext,
19
+ IFluidDataStoreChannel,
20
+ } from "@fluidframework/runtime-definitions/internal";
21
+ import { DataStoreKindImplementation } from "@fluidframework/runtime-utils/internal";
22
+ import { UsageError } from "@fluidframework/telemetry-utils/internal";
23
+
24
+ import type {
25
+ ISharedObjectKind,
26
+ SharedObjectKey,
27
+ SharedObjectKindAlpha,
28
+ } from "./sharedObject.js";
29
+ import type { ISharedObject } from "./types.js";
30
+
31
+ /**
32
+ * This file provides the implementation of {@link @fluidframework/driver-definitions#DataStoreKind}
33
+ * and is therefore a key part of the implementation of the {@link @fluidframework/driver-definitions#ServiceClient} API surface.
34
+ *
35
+ * Note that much of the API surface beyond {@link defineDataStore} could be removed/deduplicated
36
+ * if the unification noted in the TODOs in {@link SharedObjectRegistry} is implemented.
37
+ */
38
+
39
+ /**
40
+ * A {@link @fluidframework/driver-definitions#Registry} of shared object kinds that can be created or loaded within a data store.
41
+ * @remarks
42
+ * Supports lazy code loading in a limited way (a single lazy load per registry).
43
+ * @privateRemarks
44
+ * TODO: The framework provided SharedObjects should be exposed in a way indistinguishable from custom sub-data stores.
45
+ * This can be done by unifying the DataStoreKind and SharedObjectKindAlpha types.
46
+ * For now, this would mean having DataStoreKind extend SharedObjectKindAlpha, since we can allow a data store in all places SharedObjects are allowed,
47
+ * but do not allow SharedObjects at the root.
48
+ * Fixing this, and allowing shared objects at the root (maybe use a trivial wrapper data store) could simplify things, allowing data stores and Containers to share some types (like how they create detached contents, have registries, have a root etc).
49
+ *
50
+ * Part of this unification could be to relax the output from the factories / registries. Allowing the output to be an arbitrary type, which might be a promise, and might not be one could help.
51
+ * Removal of the IFluidLoadable requirement, and allowing the returned type to expose handles to itself however it wants (or not at all) might be viable and simplify typing and allow for strongly typed handles at creation time at least).
52
+ * Maybe when Registry(type) gives a promise, it could instead give a factory which outputs a promise wrapped type? The check that the provided creation key is valid for that factory can be deferred until the promise resolves.
53
+ *
54
+ * Idea: creation key can have an interface that subsets the factory / SharedObjectKindAlpha / DataStoreKind so they can be used, or some branded key (string, and/or object with stronger identity what knows the type string) can be used.
55
+ * Have Key interface contain validation function to check that the factory used (or maybe the value produced from it) is valid for that key.
56
+ * During load, validation would simply check the factory's type string matches the key's type string.
57
+ * When using SharedObjectKindAlpha or DataStoreKind, validation can check factory object identity against key.
58
+ *
59
+ * Goal: Mostly unify container, data store and shared object abstractions.
60
+ * Maybe unify a bit with service client since it also has a way to create detached things with an initialized root then attach them.
61
+ * SharedObjects are just built in leaf data stores.
62
+ *
63
+ * @input
64
+ * @alpha
65
+ */
66
+ export type SharedObjectRegistry = () => Promise<
67
+ Registry<SharedObjectKindAlpha<IFluidLoadable>>
68
+ >;
69
+
70
+ /**
71
+ * Creates a {@link SharedObjectRegistry} from an iterable of {@link SharedObjectKindAlpha}s or async getters for them.
72
+ * @alpha
73
+ */
74
+ export function sharedObjectRegistryFromIterable(
75
+ entries: Iterable<
76
+ | SharedObjectKindAlpha<IFluidLoadable>
77
+ | { type: string; kind: () => Promise<SharedObjectKindAlpha<IFluidLoadable>> }
78
+ >,
79
+ ): SharedObjectRegistry {
80
+ return async () => {
81
+ const map = new Map<string, SharedObjectKindAlpha<IFluidLoadable>>();
82
+ for (const entry of entries) {
83
+ if ("kind" in entry) {
84
+ map.set(entry.type, await entry.kind());
85
+ } else {
86
+ map.set(asSharedObjectKind(entry).getFactory().type, entry);
87
+ }
88
+ }
89
+ return (type: string) => {
90
+ const entry = map.get(type);
91
+ if (entry === undefined) {
92
+ throw new UsageError(`Unknown shared object type: ${type}`);
93
+ }
94
+ return entry;
95
+ };
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Options which define how to construct a particular {@link @fluidframework/driver-definitions#DataStoreKind}.
101
+ * @remarks
102
+ * Use {@link defineDataStore} to create a {@link @fluidframework/driver-definitions#DataStoreKind} from these options.
103
+ * @input
104
+ * @alpha
105
+ */
106
+ export interface DataStoreOptions<in out TRoot extends IFluidLoadable, out TOutput> {
107
+ /**
108
+ * The type identifier for the data object factory.
109
+ * @remarks
110
+ * Persisted identifier which specifies which {@link @fluidframework/driver-definitions#DataStoreKind} to use when loading it.
111
+ * @privateRemarks
112
+ * Equivalent to `DataObjectFactoryProps.type`.
113
+ */
114
+ readonly type: string;
115
+
116
+ /**
117
+ * The registry of shared object kinds (including other data stores) that can be loaded or created within this data store.
118
+ *
119
+ * TODO: actually allow this to contain data stores.
120
+ */
121
+ readonly registry: SharedObjectRegistry;
122
+
123
+ /**
124
+ * Create the initial content of the data store, and return the root shared object.
125
+ * @privateRemarks
126
+ * TODO:
127
+ * This requires the caller to produce a single root shared object (which is keyed by {@link rootSharedObjectId}).
128
+ * This should be fine for new code, but code migrated from legacy APIs might need more flexibility.
129
+ * Such use-cases could be accommodated providing a legacy alternative to `defineDataStore` where `instantiateFirstTime` and `view` directly expose access to named root shared objects.
130
+ * This should be easy to implement, but is currently not included.
131
+ */
132
+ instantiateFirstTime(
133
+ rootCreator: SharedObjectCreator<TRoot>,
134
+ context: DataStoreContext,
135
+ ): Promise<TRoot>;
136
+
137
+ /**
138
+ * Construct a view of the data store's root shared object.
139
+ *
140
+ * @param root - The root shared object of the data store, created by `instantiateFirstTime` (though possibly created by another client and loaded by this one).
141
+ * @param context - A {@link DataStoreContext} that can be used to create additional shared objects.
142
+ */
143
+ view(root: TRoot, context: DataStoreContext): Promise<TOutput>;
144
+ }
145
+
146
+ /**
147
+ * Creates a {@link @fluidframework/driver-definitions#DataStoreKind} from {@link DataStoreOptions}.
148
+ * @alpha
149
+ */
150
+ export function defineDataStore<T, TRoot extends IFluidLoadable>(
151
+ options: DataStoreOptions<TRoot, T>,
152
+ ): DataStoreKind<T> {
153
+ return new DataStoreKindImplementation<T>({
154
+ type: options.type,
155
+ async instantiateDataStore(
156
+ context: IFluidDataStoreContext,
157
+ existing: boolean,
158
+ ): Promise<IFluidDataStoreChannel> {
159
+ return createDataStore(context, existing, options);
160
+ },
161
+ });
162
+ }
163
+
164
+ /**
165
+ * Casts a {@link SharedObjectKindAlpha} to its encapsulated {@link ISharedObjectKind} view.
166
+ *
167
+ * @remarks
168
+ * {@link SharedObjectKindAlpha} is a sealed type,
169
+ * so we can assume it implements {@link ISharedObjectKind} and down cast to it.
170
+ */
171
+ function asSharedObjectKind<T extends IFluidLoadable>(
172
+ kind: SharedObjectKindAlpha<T>,
173
+ ): ISharedObjectKind<T> {
174
+ const candidate = kind as unknown as Partial<ISharedObjectKind<T>>;
175
+ // Sanity check to help catch misuse since SharedObjectKindAlpha is typed structurally and seems implementable.
176
+ if (typeof candidate.getFactory !== "function" || typeof candidate.create !== "function") {
177
+ throw new UsageError(
178
+ "Invalid SharedObjectKindAlpha: this type is sealed and may not have custom implementations.",
179
+ );
180
+ }
181
+ return candidate as ISharedObjectKind<T>;
182
+ }
183
+
184
+ function convertRegistry(
185
+ lookup: Registry<SharedObjectKindAlpha<IFluidLoadable>>,
186
+ ): ISharedObjectRegistry {
187
+ return {
188
+ get: (type: string) => {
189
+ const entry = lookup(type);
190
+ return asSharedObjectKind(entry).getFactory();
191
+ },
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Data stores keep their shared objects inside channels which get names.
197
+ * This is the name of the channel which we conventionally use for the root shared object of a data store in most cases.
198
+ * @remarks
199
+ * There can be other named channels, or the root could use a different name, but we are trying to migrate away from such patterns.
200
+ * Currently the DataStoreKind pattern used in this file follows and requires this convention,
201
+ * but we may relax that in the future for interop with legacy data if necessary.
202
+ */
203
+ const rootSharedObjectId = "root";
204
+
205
+ /**
206
+ * Creates a data store channel.
207
+ * @param context - The data store context.
208
+ * @param existing - Whether the data store already exists. When true, this loads it, when false a new one is created.
209
+ * @param options - The data store options.
210
+ * @returns A promise that resolves to the created data store channel.
211
+ * @remarks
212
+ * Currently this is limited to data stores which have a single named channel,
213
+ * which must have the {@link rootSharedObjectId} and is attached at creation time.
214
+ * This limitation may be relaxed in the future.
215
+ */
216
+ async function createDataStore<T, TRoot extends IFluidLoadable>(
217
+ context: IFluidDataStoreContext,
218
+ existing: boolean,
219
+ options: DataStoreOptions<TRoot, T>,
220
+ ): Promise<IFluidDataStoreChannel> {
221
+ const sharedObjectRegistry = await options.registry();
222
+ const runtime: FluidDataStoreRuntime = new FluidDataStoreRuntime(
223
+ context,
224
+ convertRegistry(sharedObjectRegistry),
225
+ existing,
226
+ async (runtimeInner: IFluidDataStoreRuntime) => {
227
+ const innerContext: DataStoreContext = {
228
+ async createSharedObject<T2 extends IFluidLoadable>(
229
+ key: SharedObjectKey<T2>,
230
+ ): Promise<T2> {
231
+ const kind = lookupInRegistry(sharedObjectRegistry, key);
232
+ // Create detached channel.
233
+ return asSharedObjectKind(kind).create(runtimeInner);
234
+ },
235
+ };
236
+
237
+ let createdRoot: TRoot | undefined;
238
+
239
+ const rootCreator: SharedObjectCreator<TRoot> = {
240
+ async createSharedObject<T2 extends TRoot>(key: SharedObjectKey<T2>): Promise<T2> {
241
+ // Create named channel under the root id.
242
+ // Error if called twice.
243
+ if (createdRoot !== undefined) {
244
+ throw new UsageError("Root shared object already created");
245
+ }
246
+ const kind = lookupInRegistry(sharedObjectRegistry, key);
247
+ const result = asSharedObjectKind(kind).create(runtimeInner, rootSharedObjectId);
248
+
249
+ // Every shared object is also an ISharedObject;
250
+ const rootSharedObject = result as IFluidLoadable as ISharedObject;
251
+ // bind the newly created root so it becomes part of this data store.
252
+ rootSharedObject.bindToContext();
253
+
254
+ createdRoot = result;
255
+ return result;
256
+ },
257
+ };
258
+
259
+ let root: TRoot | undefined;
260
+ if (existing) {
261
+ // getChannel returns the type-erased IChannel; the registered root kind guarantees it is a TRoot.
262
+ root = (await runtimeInner.getChannel(rootSharedObjectId)) as IFluidLoadable as TRoot;
263
+ } else {
264
+ root = await options.instantiateFirstTime(rootCreator, innerContext);
265
+ if (root !== createdRoot) {
266
+ throw new UsageError(
267
+ "instantiateFirstTime did not return root created with rootCreator",
268
+ );
269
+ }
270
+ }
271
+
272
+ // view returns the data store's output type; the runtime only needs it as an opaque FluidObject entry point.
273
+ return (await options.view(root, innerContext)) as unknown as FluidObject;
274
+ },
275
+ );
276
+
277
+ return runtime;
278
+ }
279
+
280
+ /**
281
+ * Creates instances of SharedObjectKinds.
282
+ * @privateRemarks
283
+ * See IFluidContainer.create.
284
+ * @sealed
285
+ * @alpha
286
+ */
287
+ export interface SharedObjectCreator<TConstraint = IFluidLoadable> {
288
+ /**
289
+ * Create an instance of `kind`, which must be registered in the registry of the surrounding data store.
290
+ */
291
+ createSharedObject<T extends TConstraint>(kind: SharedObjectKey<T>): Promise<T>;
292
+ }
293
+
294
+ /**
295
+ * Contextual information about a data store which is provided when instantiating or loading it.
296
+ * @privateRemarks
297
+ * TODO: this can expose more contextual information about the data store as needed.
298
+ * @sealed
299
+ * @alpha
300
+ */
301
+ export interface DataStoreContext extends SharedObjectCreator {}
package/src/index.ts CHANGED
@@ -10,7 +10,10 @@ export {
10
10
  SharedObjectCore,
11
11
  type ISharedObjectKind,
12
12
  type SharedObjectKind,
13
+ type SharedObjectKindAlpha,
13
14
  createSharedObjectKind,
15
+ createSharedObjectKindAlpha,
16
+ type SharedObjectKey,
14
17
  } from "./sharedObject.js";
15
18
  export type { ISharedObject, ISharedObjectEvents } from "./types.js";
16
19
  export {
@@ -32,3 +35,11 @@ export {
32
35
  type SharedObjectOptions,
33
36
  mergeAPIs,
34
37
  } from "./sharedObjectKernel.js";
38
+ export { defineDataStore, sharedObjectRegistryFromIterable } from "./dataStoreKind.js";
39
+ export { makeStubDataStoreKind } from "./stubSharedObject.js";
40
+ export type {
41
+ DataStoreOptions,
42
+ SharedObjectCreator,
43
+ SharedObjectRegistry,
44
+ DataStoreContext,
45
+ } from "./dataStoreKind.js";
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/shared-object-base";
9
- export const pkgVersion = "2.113.0-411909";
9
+ export const pkgVersion = "2.114.0";
@@ -25,6 +25,7 @@ import type {
25
25
  import type {
26
26
  IDocumentMessage,
27
27
  ISequencedDocumentMessage,
28
+ RegistryKey,
28
29
  } from "@fluidframework/driver-definitions/internal";
29
30
  import {
30
31
  type IExperimentalIncrementalSummaryContext,
@@ -51,6 +52,7 @@ import {
51
52
  type ICustomData,
52
53
  type IFluidErrorBase,
53
54
  LoggingError,
55
+ UsageError,
54
56
  extractTelemetryLoggerExt,
55
57
  } from "@fluidframework/telemetry-utils/internal";
56
58
  // eslint-disable-next-line import-x/no-internal-modules -- Needed to avoid specialized /internal ITelemetryLoggerExt
@@ -985,6 +987,31 @@ export interface SharedObjectKind<out TSharedObject = unknown>
985
987
  is(value: IFluidLoadable): value is IFluidLoadable & TSharedObject;
986
988
  }
987
989
 
990
+ /**
991
+ * A {@link @fluidframework/driver-definitions#RegistryKey} for a {@link SharedObjectKind}.
992
+ * @remarks
993
+ * This is implemented by {@link SharedObjectKind}, but alternative implementations can be used if needed.
994
+ *
995
+ * If you want lazy loading and need a key that does not eagerly load the {@link SharedObjectKind}, an alternative {@link SharedObjectKey} can be implemented.
996
+ * @privateRemarks
997
+ * TODO: A built in common pattern for the lazy key case should be provided.
998
+ * TODO: things probably break if "adapt" does anything except throw or return the result from the input promise.
999
+ * @input
1000
+ * @alpha
1001
+ */
1002
+ export type SharedObjectKey<T> = RegistryKey<SharedObjectKindAlpha<T>, SharedObjectKindAlpha>;
1003
+
1004
+ /**
1005
+ * A {@link SharedObjectKind} that also implements {@link SharedObjectKey}.
1006
+ * @privateRemarks
1007
+ * All concrete shared object kinds (produced by {@link createSharedObjectKind}) implement this interface.
1008
+ * @sealed
1009
+ * @alpha
1010
+ */
1011
+ export interface SharedObjectKindAlpha<out TSharedObject = unknown>
1012
+ extends SharedObjectKind<TSharedObject>,
1013
+ SharedObjectKey<TSharedObject> {}
1014
+
988
1015
  /**
989
1016
  * Utility for creating ISharedObjectKind instances.
990
1017
  * @remarks
@@ -997,8 +1024,23 @@ export interface SharedObjectKind<out TSharedObject = unknown>
997
1024
  export function createSharedObjectKind<TSharedObject>(
998
1025
  factory: (new () => IChannelFactory<TSharedObject>) & { readonly Type: string },
999
1026
  ): ISharedObjectKind<TSharedObject> & SharedObjectKind<TSharedObject> {
1027
+ return createSharedObjectKindAlpha(factory);
1028
+ }
1029
+
1030
+ /**
1031
+ * Utility for creating ISharedObjectKind instances.
1032
+ * @remarks
1033
+ * This takes in a class which implements IChannelFactory,
1034
+ * and uses it to return a single value which is intended to be used as the API entry point for the corresponding shared object type.
1035
+ * The returned value implements {@link ISharedObjectKind} for use in the encapsulated API, as well as the type erased {@link SharedObjectKind} used by the declarative API.
1036
+ * See {@link @fluidframework/fluid-static#ContainerSchema} for how this is used in the declarative API.
1037
+ * @internal
1038
+ */
1039
+ export function createSharedObjectKindAlpha<TSharedObject>(
1040
+ factory: (new () => IChannelFactory<TSharedObject>) & { readonly Type: string },
1041
+ ): ISharedObjectKind<TSharedObject> & SharedObjectKindAlpha<TSharedObject> {
1000
1042
  const result: ISharedObjectKind<TSharedObject> &
1001
- Omit<SharedObjectKind<TSharedObject>, "brand"> = {
1043
+ Omit<SharedObjectKindAlpha<TSharedObject>, "brand"> = {
1002
1044
  getFactory(): IChannelFactory<TSharedObject> {
1003
1045
  return new factory();
1004
1046
  },
@@ -1010,9 +1052,25 @@ export function createSharedObjectKind<TSharedObject>(
1010
1052
  is(value: IFluidLoadable): value is IFluidLoadable & TSharedObject {
1011
1053
  return isChannel(value) && value.attributes.type === factory.Type;
1012
1054
  },
1055
+
1056
+ type: factory.Type,
1057
+
1058
+ adapt: (value: SharedObjectKindAlpha): SharedObjectKindAlpha<TSharedObject> => {
1059
+ if (value === resultFinal) {
1060
+ return resultFinal;
1061
+ }
1062
+ if (value.type === result.type) {
1063
+ throw new UsageError(`Conflicting SharedObjectKinds with same type: ${result.type}`);
1064
+ }
1065
+ throw new UsageError(
1066
+ `Mismatched SharedObjectKind type. Expected: ${result.type}, got: ${value.type}`,
1067
+ );
1068
+ },
1013
1069
  };
1014
1070
 
1015
- return result as typeof result & SharedObjectKind<TSharedObject>;
1071
+ const resultFinal = result as typeof result & SharedObjectKindAlpha<TSharedObject>;
1072
+
1073
+ return resultFinal;
1016
1074
  }
1017
1075
 
1018
1076
  function isChannel(loadable: IFluidLoadable): loadable is IChannel {
@@ -28,10 +28,10 @@ import { extractTelemetryLoggerExt } from "@fluidframework/telemetry-utils/inter
28
28
 
29
29
  import type { IFluidSerializer } from "./serializer.js";
30
30
  import {
31
- createSharedObjectKind,
31
+ createSharedObjectKindAlpha,
32
32
  SharedObject,
33
33
  type ISharedObjectKind,
34
- type SharedObjectKind,
34
+ type SharedObjectKindAlpha,
35
35
  } from "./sharedObject.js";
36
36
  import type { ISharedObjectEvents, ISharedObject } from "./types.js";
37
37
  import type { IChannelView } from "./utils.js";
@@ -494,6 +494,6 @@ function makeChannelFactory<T extends object>(options: SharedObjectOptions<T>) {
494
494
  */
495
495
  export function makeSharedObjectKind<T extends object>(
496
496
  options: SharedObjectOptions<T>,
497
- ): ISharedObjectKind<T> & SharedObjectKind<T> {
498
- return createSharedObjectKind<T>(makeChannelFactory(options));
497
+ ): ISharedObjectKind<T> & SharedObjectKindAlpha<T> {
498
+ return createSharedObjectKindAlpha<T>(makeChannelFactory(options));
499
499
  }
@@ -0,0 +1,66 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import type { IFluidLoadable } from "@fluidframework/core-interfaces";
7
+ import type { DataStoreKind } from "@fluidframework/driver-definitions/internal";
8
+ import type { ISummaryTreeWithStats } from "@fluidframework/runtime-definitions/internal";
9
+
10
+ import { defineDataStore, sharedObjectRegistryFromIterable } from "./dataStoreKind.js";
11
+ import {
12
+ type SharedKernel,
13
+ type SharedKernelFactory,
14
+ makeSharedObjectKind,
15
+ } from "./sharedObjectKernel.js";
16
+ import { createSingleBlobSummary } from "./utils.js";
17
+
18
+ class StatelessKernel implements SharedKernel {
19
+ summarizeCore(): ISummaryTreeWithStats {
20
+ return createSingleBlobSummary("header", "{}");
21
+ }
22
+ onDisconnect(): void {}
23
+ reSubmitCore(): void {}
24
+ applyStashedOp(): void {}
25
+ processMessagesCore(): void {}
26
+ }
27
+
28
+ const statelessKernelFactory: SharedKernelFactory<object> = {
29
+ create() {
30
+ const kernel = new StatelessKernel();
31
+ return { kernel, view: {} };
32
+ },
33
+ async loadCore() {
34
+ const kernel = new StatelessKernel();
35
+ return { kernel, view: {} };
36
+ },
37
+ };
38
+
39
+ const statelessSharedObjectKind = makeSharedObjectKind<IFluidLoadable>({
40
+ type: "com.microsoft.fluid.test.stateless",
41
+ attributes: {
42
+ type: "com.microsoft.fluid.test.stateless",
43
+ snapshotFormatVersion: "0.1",
44
+ },
45
+ telemetryContextPrefix: "test_stateless_",
46
+ factory: statelessKernelFactory,
47
+ });
48
+
49
+ /**
50
+ * Creates a trivial stub {@link @fluidframework/driver-definitions#DataStoreKind} backed by a
51
+ * stateless shared object.
52
+ * Useful in tests that need a valid data store but don't care about the content.
53
+ * @internal
54
+ */
55
+ export function makeStubDataStoreKind(type: string): DataStoreKind {
56
+ return defineDataStore({
57
+ type,
58
+ registry: sharedObjectRegistryFromIterable([statelessSharedObjectKind]),
59
+ async instantiateFirstTime(rootCreator) {
60
+ return rootCreator.createSharedObject(statelessSharedObjectKind);
61
+ },
62
+ async view() {
63
+ return {};
64
+ },
65
+ });
66
+ }