@fluidframework/datastore 2.90.0 → 2.92.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/datastore",
3
- "version": "2.90.0",
3
+ "version": "2.92.0",
4
4
  "description": "Fluid data store implementation",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -69,29 +69,29 @@
69
69
  "temp-directory": "nyc/.nyc_output"
70
70
  },
71
71
  "dependencies": {
72
- "@fluid-internal/client-utils": "~2.90.0",
73
- "@fluidframework/container-definitions": "~2.90.0",
74
- "@fluidframework/core-interfaces": "~2.90.0",
75
- "@fluidframework/core-utils": "~2.90.0",
76
- "@fluidframework/datastore-definitions": "~2.90.0",
77
- "@fluidframework/driver-definitions": "~2.90.0",
78
- "@fluidframework/driver-utils": "~2.90.0",
79
- "@fluidframework/id-compressor": "~2.90.0",
80
- "@fluidframework/runtime-definitions": "~2.90.0",
81
- "@fluidframework/runtime-utils": "~2.90.0",
82
- "@fluidframework/telemetry-utils": "~2.90.0",
72
+ "@fluid-internal/client-utils": "~2.92.0",
73
+ "@fluidframework/container-definitions": "~2.92.0",
74
+ "@fluidframework/core-interfaces": "~2.92.0",
75
+ "@fluidframework/core-utils": "~2.92.0",
76
+ "@fluidframework/datastore-definitions": "~2.92.0",
77
+ "@fluidframework/driver-definitions": "~2.92.0",
78
+ "@fluidframework/driver-utils": "~2.92.0",
79
+ "@fluidframework/id-compressor": "~2.92.0",
80
+ "@fluidframework/runtime-definitions": "~2.92.0",
81
+ "@fluidframework/runtime-utils": "~2.92.0",
82
+ "@fluidframework/telemetry-utils": "~2.92.0",
83
83
  "uuid": "^11.1.0"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@arethetypeswrong/cli": "^0.18.2",
87
- "@biomejs/biome": "~1.9.3",
88
- "@fluid-internal/mocha-test-setup": "~2.90.0",
89
- "@fluid-tools/build-cli": "^0.63.0",
87
+ "@biomejs/biome": "~2.4.5",
88
+ "@fluid-internal/mocha-test-setup": "~2.92.0",
89
+ "@fluid-tools/build-cli": "^0.64.0",
90
90
  "@fluidframework/build-common": "^2.0.3",
91
- "@fluidframework/build-tools": "^0.63.0",
92
- "@fluidframework/datastore-previous": "npm:@fluidframework/datastore@2.83.0",
93
- "@fluidframework/eslint-config-fluid": "~2.90.0",
94
- "@fluidframework/test-runtime-utils": "~2.90.0",
91
+ "@fluidframework/build-tools": "^0.64.0",
92
+ "@fluidframework/datastore-previous": "npm:@fluidframework/datastore@2.91.0",
93
+ "@fluidframework/eslint-config-fluid": "^9.0.0",
94
+ "@fluidframework/test-runtime-utils": "~2.92.0",
95
95
  "@microsoft/api-extractor": "7.52.11",
96
96
  "@types/lodash": "^4.14.118",
97
97
  "@types/mocha": "^10.0.10",
@@ -115,7 +115,7 @@
115
115
  },
116
116
  "scripts": {
117
117
  "api": "fluid-build . --task api",
118
- "api-extractor:commonjs": "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./dist",
118
+ "api-extractor:commonjs": "flub generate entrypoints --resolutionConditions require --outFileLegacyBeta legacy --outDir ./dist",
119
119
  "api-extractor:esnext": "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib --node10TypeCompat",
120
120
  "build": "fluid-build . --task build",
121
121
  "build:api-reports": "concurrently \"npm:build:api-reports:*\"",
@@ -157,6 +157,78 @@ export interface ISharedObjectRegistry {
157
157
  get(name: string): IChannelFactory | undefined;
158
158
  }
159
159
 
160
+ /**
161
+ * The common URL prefix used by legacy DDS type strings.
162
+ * Factories originally used full URLs (e.g. `"https://graph.microsoft.com/types/map"`);
163
+ * new factories use only the trailing path segment (e.g. `"map"`).
164
+ *
165
+ * Support for reading both formats was added in 2.92.0.
166
+ * @remarks
167
+ * This is encoded using base64 to avoid replacement of URL-like values that we have seen some reverse proxies perform.
168
+ * The value at runtime is "https://graph.microsoft.com/types/".
169
+ */
170
+ const legacyTypeUrlPrefix = atob("aHR0cHM6Ly9ncmFwaC5taWNyb3NvZnQuY29tL3R5cGVzLw==");
171
+
172
+ /**
173
+ * Wraps an {@link ISharedObjectRegistry} to transparently redirect legacy URL-based DDS type
174
+ * strings to the factories registered under the corresponding short-name path segment.
175
+ *
176
+ * When a lookup by the full URL fails, this wrapper retries using only the portion of the URL
177
+ * after `"https://graph.microsoft.com/types/"`. This allows old documents whose summaries
178
+ * contain URL-based type strings to be loaded against a registry built with the current
179
+ * short-name factory types.
180
+ *
181
+ * @remarks
182
+ * See {@link legacyTypeUrlPrefix} for details on old vs. new formats
183
+ */
184
+ export class LegacyTypeAwareRegistry implements ISharedObjectRegistry {
185
+ public constructor(private readonly base: ISharedObjectRegistry) {}
186
+
187
+ public get(name: string): IChannelFactory | undefined {
188
+ let factory = this.base.get(name);
189
+ if (factory !== undefined) {
190
+ return factory;
191
+ }
192
+
193
+ // eslint-disable-next-line unicorn/prefer-ternary -- This is more readable as an if statement to clearly delineate which logic can be later removed vs. which needs to stay.
194
+ if (name.startsWith(legacyTypeUrlPrefix)) {
195
+ // Back-compat: if the name is a legacy URL-based type string, retry with just the trailing path segment.
196
+ factory = this.base.get(name.slice(legacyTypeUrlPrefix.length));
197
+ } else {
198
+ // Temporary compat: if the name is *not* a legacy URL-based type string and we haven't found a match yet, check if we have a match with the
199
+ // corresponding legacy scheme. This ensures that if a client containing an older code version with the legacy attribute types loads a document
200
+ // written by a newer code version, they are still able to find the correct factories. This block can be removed once collaboration between clients
201
+ // with legacy vs. new attribute types in their code is no longer supported.
202
+ factory = this.base.get(`${legacyTypeUrlPrefix}${name}`);
203
+ }
204
+
205
+ if (factory !== undefined) {
206
+ return factory;
207
+ }
208
+
209
+ if (isURL(name) && name.includes("graph.microsoft")) {
210
+ // Reasonably strong signal that this the document refers to a DDS type string that is using the legacy URL format, but
211
+ // the base URL was likely changed by a reverse proxy or similar. Assume that its final segment is still the short (modern) name of
212
+ // a valid DDS type and look it up as such.
213
+ const finalSegment = name.split("/").slice(-1)[0];
214
+ if (finalSegment !== undefined) {
215
+ return (
216
+ this.base.get(finalSegment) ?? this.base.get(`${legacyTypeUrlPrefix}${finalSegment}`)
217
+ );
218
+ }
219
+ }
220
+ }
221
+ }
222
+
223
+ function isURL(str: string): boolean {
224
+ try {
225
+ new URL(str);
226
+ return true;
227
+ } catch {
228
+ return false;
229
+ }
230
+ }
231
+
160
232
  const defaultPolicies: IFluidDataStorePolicies = {
161
233
  readonlyInStagingMode: false,
162
234
  };
@@ -277,6 +349,7 @@ export class FluidDataStoreRuntime
277
349
  ISequencedDocumentMessage,
278
350
  IDocumentMessage
279
351
  >;
352
+ private readonly sharedObjectRegistry: ISharedObjectRegistry;
280
353
  private readonly quorum: IQuorumClients;
281
354
  private readonly audience: IAudience;
282
355
  private readonly mc: MonitoringContext;
@@ -327,12 +400,13 @@ export class FluidDataStoreRuntime
327
400
  */
328
401
  public constructor(
329
402
  private readonly dataStoreContext: IFluidDataStoreContext,
330
- private readonly sharedObjectRegistry: ISharedObjectRegistry,
403
+ sharedObjectRegistry: ISharedObjectRegistry,
331
404
  existing: boolean,
332
405
  provideEntryPoint: (runtime: IFluidDataStoreRuntime) => Promise<FluidObject>,
333
406
  policies?: Partial<IFluidDataStorePolicies>,
334
407
  ) {
335
408
  super();
409
+ this.sharedObjectRegistry = new LegacyTypeAwareRegistry(sharedObjectRegistry);
336
410
 
337
411
  assert(
338
412
  !dataStoreContext.id.includes("/"),
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/datastore";
9
- export const pkgVersion = "2.90.0";
9
+ export const pkgVersion = "2.92.0";