@fluidframework/container-loader 2.1.0-276985 → 2.1.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 (74) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +132 -30
  3. package/api-extractor/api-extractor.current.json +5 -0
  4. package/api-extractor/api-extractor.legacy.json +1 -1
  5. package/api-extractor.json +1 -1
  6. package/api-report/container-loader.legacy.public.api.md +17 -0
  7. package/dist/connectionManager.d.ts.map +1 -1
  8. package/dist/connectionManager.js +9 -6
  9. package/dist/connectionManager.js.map +1 -1
  10. package/dist/container.d.ts.map +1 -1
  11. package/dist/container.js +28 -6
  12. package/dist/container.js.map +1 -1
  13. package/dist/containerStorageAdapter.d.ts +1 -1
  14. package/dist/containerStorageAdapter.d.ts.map +1 -1
  15. package/dist/containerStorageAdapter.js +14 -4
  16. package/dist/containerStorageAdapter.js.map +1 -1
  17. package/dist/contracts.d.ts.map +1 -1
  18. package/dist/contracts.js +4 -12
  19. package/dist/contracts.js.map +1 -1
  20. package/dist/deltaManager.d.ts.map +1 -1
  21. package/dist/deltaManager.js +18 -3
  22. package/dist/deltaManager.js.map +1 -1
  23. package/dist/legacy.d.ts +1 -1
  24. package/dist/packageVersion.d.ts +1 -1
  25. package/dist/packageVersion.d.ts.map +1 -1
  26. package/dist/packageVersion.js +1 -1
  27. package/dist/packageVersion.js.map +1 -1
  28. package/dist/public.d.ts +1 -1
  29. package/dist/serializedStateManager.d.ts.map +1 -1
  30. package/dist/serializedStateManager.js +18 -5
  31. package/dist/serializedStateManager.js.map +1 -1
  32. package/dist/utils.d.ts.map +1 -1
  33. package/dist/utils.js +11 -2
  34. package/dist/utils.js.map +1 -1
  35. package/internal.d.ts +1 -1
  36. package/legacy.d.ts +1 -1
  37. package/lib/connectionManager.d.ts.map +1 -1
  38. package/lib/connectionManager.js +9 -6
  39. package/lib/connectionManager.js.map +1 -1
  40. package/lib/container.d.ts.map +1 -1
  41. package/lib/container.js +28 -6
  42. package/lib/container.js.map +1 -1
  43. package/lib/containerStorageAdapter.d.ts +1 -1
  44. package/lib/containerStorageAdapter.d.ts.map +1 -1
  45. package/lib/containerStorageAdapter.js +16 -6
  46. package/lib/containerStorageAdapter.js.map +1 -1
  47. package/lib/contracts.d.ts.map +1 -1
  48. package/lib/contracts.js +4 -12
  49. package/lib/contracts.js.map +1 -1
  50. package/lib/deltaManager.d.ts.map +1 -1
  51. package/lib/deltaManager.js +18 -3
  52. package/lib/deltaManager.js.map +1 -1
  53. package/lib/legacy.d.ts +1 -1
  54. package/lib/packageVersion.d.ts +1 -1
  55. package/lib/packageVersion.d.ts.map +1 -1
  56. package/lib/packageVersion.js +1 -1
  57. package/lib/packageVersion.js.map +1 -1
  58. package/lib/public.d.ts +1 -1
  59. package/lib/serializedStateManager.d.ts.map +1 -1
  60. package/lib/serializedStateManager.js +18 -5
  61. package/lib/serializedStateManager.js.map +1 -1
  62. package/lib/utils.d.ts.map +1 -1
  63. package/lib/utils.js +11 -2
  64. package/lib/utils.js.map +1 -1
  65. package/package.json +25 -23
  66. package/src/connectionManager.ts +13 -12
  67. package/src/container.ts +31 -8
  68. package/src/containerStorageAdapter.ts +22 -7
  69. package/src/contracts.ts +5 -11
  70. package/src/deltaManager.ts +18 -6
  71. package/src/packageVersion.ts +1 -1
  72. package/src/serializedStateManager.ts +20 -12
  73. package/src/utils.ts +15 -6
  74. package/tsconfig.json +0 -1
@@ -20,7 +20,7 @@ import {
20
20
  ISnapshotTree,
21
21
  IVersion,
22
22
  } from "@fluidframework/driver-definitions/internal";
23
- import { UsageError } from "@fluidframework/driver-utils/internal";
23
+ import { isInstanceOfISnapshot, UsageError } from "@fluidframework/driver-utils/internal";
24
24
  import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
25
25
 
26
26
  // eslint-disable-next-line import/no-deprecated
@@ -31,7 +31,7 @@ import type {
31
31
  ISerializedStateManagerDocumentStorageService,
32
32
  ISnapshotInfo,
33
33
  } from "./serializedStateManager.js";
34
- import { convertSnapshotInfoToSnapshot, getDocumentAttributes } from "./utils.js";
34
+ import { convertSnapshotInfoToSnapshot } from "./utils.js";
35
35
 
36
36
  /**
37
37
  * Stringified blobs from a summary/snapshot tree.
@@ -174,13 +174,15 @@ export class ContainerStorageAdapter
174
174
  let snapshot: ISnapshot;
175
175
  if (
176
176
  this.loadingGroupIdSnapshotsFromPendingState !== undefined &&
177
- snapshotFetchOptions?.loadingGroupIds !== undefined
177
+ snapshotFetchOptions?.loadingGroupIds?.[0] !== undefined
178
178
  ) {
179
179
  const localSnapshot =
180
180
  this.loadingGroupIdSnapshotsFromPendingState[snapshotFetchOptions.loadingGroupIds[0]];
181
181
  assert(localSnapshot !== undefined, 0x970 /* Local snapshot must be present */);
182
- const attributes = await getDocumentAttributes(this, localSnapshot.baseSnapshot);
183
- snapshot = convertSnapshotInfoToSnapshot(localSnapshot, attributes.sequenceNumber);
182
+ snapshot = convertSnapshotInfoToSnapshot(
183
+ localSnapshot,
184
+ localSnapshot.snapshotSequenceNumber,
185
+ );
184
186
  } else {
185
187
  if (this._storageService.getSnapshot === undefined) {
186
188
  throw new UsageError(
@@ -315,11 +317,19 @@ const redirectTableBlobName = ".redirectTable";
315
317
  * Get blob contents of a snapshot tree from storage (or, ideally, cache)
316
318
  */
317
319
  export async function getBlobContentsFromTree(
318
- snapshot: ISnapshotTree,
320
+ snapshot: ISnapshot | ISnapshotTree,
319
321
  storage: Pick<IDocumentStorageService, "readBlob">,
320
322
  ): Promise<ISerializableBlobContents> {
321
323
  const blobs = {};
322
- await getBlobContentsFromTreeCore(snapshot, blobs, storage);
324
+ if (isInstanceOfISnapshot(snapshot)) {
325
+ const blobContents = snapshot.blobContents;
326
+ for (const [id, content] of blobContents.entries()) {
327
+ // ArrayBufferLike will not survive JSON.stringify()
328
+ blobs[id] = bufferToString(content, "utf8");
329
+ }
330
+ } else {
331
+ await getBlobContentsFromTreeCore(snapshot, blobs, storage);
332
+ }
323
333
  return blobs;
324
334
  }
325
335
 
@@ -352,6 +362,7 @@ async function getBlobManagerTreeFromTree(
352
362
  storage: Pick<IDocumentStorageService, "readBlob">,
353
363
  ): Promise<void> {
354
364
  const id = tree.blobs[redirectTableBlobName];
365
+ assert(id !== undefined, 0x9ce /* id is undefined in getBlobManagerTreeFromTree */);
355
366
  const blob = await storage.readBlob(id);
356
367
  // ArrayBufferLike will not survive JSON.stringify()
357
368
  blobs[id] = bufferToString(blob, "utf8");
@@ -394,6 +405,10 @@ function getBlobManagerTreeFromTreeWithBlobContents(
394
405
  blobs: ISerializableBlobContents,
395
406
  ): void {
396
407
  const id = tree.blobs[redirectTableBlobName];
408
+ assert(
409
+ id !== undefined,
410
+ 0x9cf /* id is undefined in getBlobManagerTreeFromTreeWithBlobContents */,
411
+ );
397
412
  const blob = tree.blobsContents?.[id];
398
413
  assert(blob !== undefined, 0x70f /* Blob must be present in blobsContents */);
399
414
  // ArrayBufferLike will not survive JSON.stringify()
package/src/contracts.ts CHANGED
@@ -214,15 +214,9 @@ export const getPackageName = (
214
214
  codeDetails: IFluidCodeDetails | undefined,
215
215
  ): IContainerPackageInfo => {
216
216
  // TODO: use a real type
217
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
218
- let containerPackageName: any;
219
- if (codeDetails && "name" in codeDetails) {
220
- containerPackageName = codeDetails;
221
- } else if (isFluidPackage(codeDetails?.package)) {
222
- containerPackageName = codeDetails?.package.name;
223
- } else {
224
- containerPackageName = codeDetails?.package;
225
- }
226
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
227
- return { name: containerPackageName };
217
+ // This is the normal path that any modern customer would hit
218
+ const containerPackageName: string | undefined = isFluidPackage(codeDetails?.package)
219
+ ? codeDetails?.package.name
220
+ : codeDetails?.package;
221
+ return { name: containerPackageName as string };
228
222
  };
@@ -357,16 +357,22 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
357
357
 
358
358
  if (batch.length === 1) {
359
359
  assert(
360
- (batch[0].metadata as IBatchMetadata)?.batch === undefined,
360
+ // Non null asserting here because of the length check above
361
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
362
+ (batch[0]!.metadata as IBatchMetadata)?.batch === undefined,
361
363
  0x3c9 /* no batch markup on single message */,
362
364
  );
363
365
  } else {
364
366
  assert(
365
- (batch[0].metadata as IBatchMetadata)?.batch === true,
367
+ // TODO why are we non null asserting here?
368
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
369
+ (batch[0]!.metadata as IBatchMetadata)?.batch === true,
366
370
  0x3ca /* no start batch markup */,
367
371
  );
368
372
  assert(
369
- (batch[batch.length - 1].metadata as IBatchMetadata)?.batch === false,
373
+ // TODO why are we non null asserting here?
374
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
375
+ (batch[batch.length - 1]!.metadata as IBatchMetadata)?.batch === false,
370
376
  0x3cb /* no end batch markup */,
371
377
  );
372
378
  }
@@ -892,8 +898,12 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
892
898
  return;
893
899
  }
894
900
 
895
- const from = messages[0].sequenceNumber;
896
- const last = messages[messages.length - 1].sequenceNumber;
901
+ // Non null asserting here because of the length check above
902
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
903
+ const from = messages[0]!.sequenceNumber;
904
+ // Non null asserting here because of the length check above
905
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
906
+ const last = messages[messages.length - 1]!.sequenceNumber;
897
907
 
898
908
  // Report stats about missing and duplicate ops
899
909
  // This helps better understand why we fetch ops from storage, and thus may delay
@@ -960,7 +970,9 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
960
970
  }
961
971
  }
962
972
 
963
- this.updateLatestKnownOpSeqNumber(messages[messages.length - 1].sequenceNumber);
973
+ // Non null asserting here because of the length check above
974
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
975
+ this.updateLatestKnownOpSeqNumber(messages[messages.length - 1]!.sequenceNumber);
964
976
 
965
977
  const n = this.previouslyProcessedMessage?.sequenceNumber;
966
978
  assert(
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-loader";
9
- export const pkgVersion = "2.1.0-276985";
9
+ export const pkgVersion = "2.1.0";
@@ -188,7 +188,9 @@ export class SerializedStateManager {
188
188
  if (pendingLocalState && pendingLocalState.savedOps.length > 0) {
189
189
  const savedOpsSize = pendingLocalState.savedOps.length;
190
190
  this.lastSavedOpSequenceNumber =
191
- pendingLocalState.savedOps[savedOpsSize - 1].sequenceNumber;
191
+ // Non null asserting here because of the length check above
192
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
193
+ pendingLocalState.savedOps[savedOpsSize - 1]!.sequenceNumber;
192
194
  }
193
195
  containerEvent.on("saved", () => this.updateSnapshotAndProcessedOpsMaybe());
194
196
  }
@@ -240,10 +242,7 @@ export class SerializedStateManager {
240
242
  const baseSnapshotTree: ISnapshotTree | undefined = getSnapshotTree(baseSnapshot);
241
243
  // non-interactive clients will not have any pending state we want to save
242
244
  if (this.offlineLoadEnabled) {
243
- const snapshotBlobs = await getBlobContentsFromTree(
244
- baseSnapshotTree,
245
- this.storageAdapter,
246
- );
245
+ const snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, this.storageAdapter);
247
246
  const attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshotTree);
248
247
  this.snapshot = {
249
248
  baseSnapshot: baseSnapshotTree,
@@ -344,7 +343,9 @@ export class SerializedStateManager {
344
343
  if (
345
344
  snapshotSequenceNumber === undefined ||
346
345
  this.processedOps.length === 0 ||
347
- this.processedOps[this.processedOps.length - 1].sequenceNumber <
346
+ // Non null asserting here because of the length check above
347
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
348
+ this.processedOps[this.processedOps.length - 1]!.sequenceNumber <
348
349
  this.lastSavedOpSequenceNumber ||
349
350
  this.containerDirty()
350
351
  ) {
@@ -352,9 +353,13 @@ export class SerializedStateManager {
352
353
  // Pending state would be behind the latest snapshot.
353
354
  return -1;
354
355
  }
355
- const firstProcessedOpSequenceNumber = this.processedOps[0].sequenceNumber;
356
+ // Non null asserting here because of the length check above
357
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
358
+ const firstProcessedOpSequenceNumber = this.processedOps[0]!.sequenceNumber;
356
359
  const lastProcessedOpSequenceNumber =
357
- this.processedOps[this.processedOps.length - 1].sequenceNumber;
360
+ // Non null asserting here because of the length check above
361
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
362
+ this.processedOps[this.processedOps.length - 1]!.sequenceNumber;
358
363
 
359
364
  if (snapshotSequenceNumber < firstProcessedOpSequenceNumber) {
360
365
  // Snapshot seq number is older than our first processed op, which could mean we're fetching
@@ -380,7 +385,9 @@ export class SerializedStateManager {
380
385
  snapshotSequenceNumber,
381
386
  firstProcessedOpSequenceNumber,
382
387
  newFirstProcessedOpSequenceNumber:
383
- this.processedOps.length === 0 ? undefined : this.processedOps[0].sequenceNumber,
388
+ // Non null asserting here because of the length check above
389
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
390
+ this.processedOps.length === 0 ? undefined : this.processedOps[0]!.sequenceNumber,
384
391
  });
385
392
  }
386
393
  return snapshotSequenceNumber;
@@ -404,8 +411,9 @@ export class SerializedStateManager {
404
411
  ".protocol" in baseSnapshot.trees
405
412
  ? baseSnapshot.trees[".protocol"].blobs.attributes
406
413
  : baseSnapshot.blobs[".attributes"];
407
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
408
- const attributes = JSON.parse(snapshotBlobs[attributesHash]);
414
+ // TODO why are we non null asserting here?
415
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-non-null-assertion
416
+ const attributes = JSON.parse(snapshotBlobs[attributesHash!]!);
409
417
  assert(
410
418
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
411
419
  attributes.sequenceNumber === 0,
@@ -513,7 +521,7 @@ export async function getLatestSnapshotInfo(
513
521
 
514
522
  const baseSnapshotTree: ISnapshotTree | undefined = getSnapshotTree(baseSnapshot);
515
523
  const snapshotFetchedTime = Date.now();
516
- const snapshotBlobs = await getBlobContentsFromTree(baseSnapshotTree, storageAdapter);
524
+ const snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, storageAdapter);
517
525
  const attributes: IDocumentAttributes = await getDocumentAttributes(
518
526
  storageAdapter,
519
527
  baseSnapshotTree,
package/src/utils.ts CHANGED
@@ -94,8 +94,12 @@ export function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefin
94
94
  const match = regex.exec(parsed.pathname);
95
95
  return match?.length === 3
96
96
  ? {
97
- id: match[1],
98
- path: match[2],
97
+ // Non null asserting here because of the length check above
98
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
99
+ id: match[1]!,
100
+ // Non null asserting here because of the length check above
101
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
102
+ path: match[2]!,
99
103
  query,
100
104
  // URLSearchParams returns null if the param is not provided.
101
105
  version: parsed.searchParams.get("version") ?? undefined,
@@ -147,7 +151,9 @@ function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): SnapshotWithBl
147
151
  };
148
152
  const keys = Object.keys(summary.tree);
149
153
  for (const key of keys) {
150
- const summaryObject = summary.tree[key];
154
+ // TODO change this to use object.entries
155
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
156
+ const summaryObject = summary.tree[key]!;
151
157
 
152
158
  switch (summaryObject.type) {
153
159
  case SummaryType.Tree: {
@@ -280,8 +286,9 @@ export const combineSnapshotTreeAndSnapshotBlobs = (
280
286
 
281
287
  // Process blobs in the current level
282
288
  for (const [, id] of Object.entries(baseSnapshot.blobs)) {
283
- if (snapshotBlobs[id]) {
284
- blobsContents[id] = stringToBuffer(snapshotBlobs[id], "utf8");
289
+ const snapshot = snapshotBlobs[id];
290
+ if (snapshot !== undefined) {
291
+ blobsContents[id] = stringToBuffer(snapshot, "utf8");
285
292
  }
286
293
  }
287
294
 
@@ -420,7 +427,9 @@ export async function getDocumentAttributes(
420
427
  ? tree.trees[".protocol"].blobs.attributes
421
428
  : tree.blobs[".attributes"];
422
429
 
423
- const attributes = await readAndParse<IDocumentAttributes>(storage, attributesHash);
430
+ // Non null asserting here because of the length check above
431
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
432
+ const attributes = await readAndParse<IDocumentAttributes>(storage, attributesHash!);
424
433
 
425
434
  return attributes;
426
435
  }
package/tsconfig.json CHANGED
@@ -5,7 +5,6 @@
5
5
  "compilerOptions": {
6
6
  "rootDir": "./src",
7
7
  "outDir": "./lib",
8
- "noUncheckedIndexedAccess": false,
9
8
  "exactOptionalPropertyTypes": false,
10
9
  },
11
10
  }