@fluidframework/datastore 2.0.0-rc.1.0.6 → 2.0.0-rc.2.0.1

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 (117) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +4 -1
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +42 -0
  4. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  5. package/api-extractor-lint.json +1 -1
  6. package/api-extractor.json +1 -1
  7. package/api-report/datastore.api.md +4 -11
  8. package/dist/channelContext.d.ts +4 -4
  9. package/dist/channelContext.d.ts.map +1 -1
  10. package/dist/channelContext.js +5 -5
  11. package/dist/channelContext.js.map +1 -1
  12. package/dist/channelDeltaConnection.d.ts +6 -3
  13. package/dist/channelDeltaConnection.d.ts.map +1 -1
  14. package/dist/channelDeltaConnection.js +46 -7
  15. package/dist/channelDeltaConnection.js.map +1 -1
  16. package/dist/dataStoreRuntime.d.ts +12 -4
  17. package/dist/dataStoreRuntime.d.ts.map +1 -1
  18. package/dist/dataStoreRuntime.js +50 -17
  19. package/dist/dataStoreRuntime.js.map +1 -1
  20. package/dist/datastore-alpha.d.ts +10 -4
  21. package/dist/datastore-beta.d.ts +1 -2
  22. package/dist/datastore-public.d.ts +1 -2
  23. package/dist/datastore-untrimmed.d.ts +10 -4
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +7 -7
  27. package/dist/index.js.map +1 -1
  28. package/dist/localChannelContext.d.ts +6 -3
  29. package/dist/localChannelContext.d.ts.map +1 -1
  30. package/dist/localChannelContext.js +17 -11
  31. package/dist/localChannelContext.js.map +1 -1
  32. package/dist/package.json +3 -0
  33. package/dist/remoteChannelContext.d.ts +2 -2
  34. package/dist/remoteChannelContext.d.ts.map +1 -1
  35. package/dist/remoteChannelContext.js +6 -5
  36. package/dist/remoteChannelContext.js.map +1 -1
  37. package/dist/tsdoc-metadata.json +1 -1
  38. package/lib/{channelContext.d.mts → channelContext.d.ts} +5 -5
  39. package/lib/channelContext.d.ts.map +1 -0
  40. package/lib/{channelContext.mjs → channelContext.js} +5 -5
  41. package/lib/channelContext.js.map +1 -0
  42. package/lib/{channelDeltaConnection.d.mts → channelDeltaConnection.d.ts} +7 -4
  43. package/lib/channelDeltaConnection.d.ts.map +1 -0
  44. package/lib/channelDeltaConnection.js +92 -0
  45. package/lib/channelDeltaConnection.js.map +1 -0
  46. package/lib/{channelStorageService.d.mts → channelStorageService.d.ts} +1 -1
  47. package/lib/channelStorageService.d.ts.map +1 -0
  48. package/lib/{channelStorageService.mjs → channelStorageService.js} +1 -1
  49. package/lib/channelStorageService.js.map +1 -0
  50. package/lib/{dataStoreRuntime.d.mts → dataStoreRuntime.d.ts} +13 -5
  51. package/lib/dataStoreRuntime.d.ts.map +1 -0
  52. package/lib/{dataStoreRuntime.mjs → dataStoreRuntime.js} +46 -13
  53. package/lib/dataStoreRuntime.js.map +1 -0
  54. package/lib/{datastore-alpha.d.mts → datastore-alpha.d.ts} +10 -4
  55. package/lib/{datastore-public.d.mts → datastore-beta.d.ts} +1 -2
  56. package/lib/{datastore-beta.d.mts → datastore-public.d.ts} +1 -2
  57. package/lib/{datastore-untrimmed.d.mts → datastore-untrimmed.d.ts} +10 -4
  58. package/lib/{fluidHandle.d.mts → fluidHandle.d.ts} +1 -1
  59. package/lib/fluidHandle.d.ts.map +1 -0
  60. package/lib/{fluidHandle.mjs → fluidHandle.js} +1 -1
  61. package/lib/fluidHandle.js.map +1 -0
  62. package/lib/{index.d.mts → index.d.ts} +3 -3
  63. package/lib/index.d.ts.map +1 -0
  64. package/lib/{index.mjs → index.js} +3 -3
  65. package/lib/index.js.map +1 -0
  66. package/lib/{localChannelContext.d.mts → localChannelContext.d.ts} +7 -4
  67. package/lib/localChannelContext.d.ts.map +1 -0
  68. package/lib/{localChannelContext.mjs → localChannelContext.js} +14 -8
  69. package/lib/localChannelContext.js.map +1 -0
  70. package/lib/{localChannelStorageService.d.mts → localChannelStorageService.d.ts} +1 -1
  71. package/lib/localChannelStorageService.d.ts.map +1 -0
  72. package/lib/{localChannelStorageService.mjs → localChannelStorageService.js} +1 -1
  73. package/lib/localChannelStorageService.js.map +1 -0
  74. package/lib/{remoteChannelContext.d.mts → remoteChannelContext.d.ts} +3 -3
  75. package/lib/remoteChannelContext.d.ts.map +1 -0
  76. package/lib/{remoteChannelContext.mjs → remoteChannelContext.js} +4 -3
  77. package/lib/remoteChannelContext.js.map +1 -0
  78. package/lib/test/channelStorageService.spec.js +70 -0
  79. package/lib/test/channelStorageService.spec.js.map +1 -0
  80. package/lib/test/dataStoreRuntime.spec.js +121 -0
  81. package/lib/test/dataStoreRuntime.spec.js.map +1 -0
  82. package/lib/test/localChannelContext.spec.js +41 -0
  83. package/lib/test/localChannelContext.spec.js.map +1 -0
  84. package/lib/test/localChannelStorageService.spec.js +72 -0
  85. package/lib/test/localChannelStorageService.spec.js.map +1 -0
  86. package/lib/test/remoteChannelContext.spec.js +33 -0
  87. package/lib/test/remoteChannelContext.spec.js.map +1 -0
  88. package/lib/test/types/validateDatastorePrevious.generated.js +16 -0
  89. package/lib/test/types/validateDatastorePrevious.generated.js.map +1 -0
  90. package/package.json +43 -49
  91. package/src/channelContext.ts +5 -3
  92. package/src/channelDeltaConnection.ts +69 -5
  93. package/src/dataStoreRuntime.ts +49 -18
  94. package/src/index.ts +2 -2
  95. package/src/localChannelContext.ts +21 -6
  96. package/src/remoteChannelContext.ts +4 -2
  97. package/tsconfig.cjs.json +7 -0
  98. package/tsconfig.json +2 -5
  99. package/lib/channelContext.d.mts.map +0 -1
  100. package/lib/channelContext.mjs.map +0 -1
  101. package/lib/channelDeltaConnection.d.mts.map +0 -1
  102. package/lib/channelDeltaConnection.mjs +0 -53
  103. package/lib/channelDeltaConnection.mjs.map +0 -1
  104. package/lib/channelStorageService.d.mts.map +0 -1
  105. package/lib/channelStorageService.mjs.map +0 -1
  106. package/lib/dataStoreRuntime.d.mts.map +0 -1
  107. package/lib/dataStoreRuntime.mjs.map +0 -1
  108. package/lib/fluidHandle.d.mts.map +0 -1
  109. package/lib/fluidHandle.mjs.map +0 -1
  110. package/lib/index.d.mts.map +0 -1
  111. package/lib/index.mjs.map +0 -1
  112. package/lib/localChannelContext.d.mts.map +0 -1
  113. package/lib/localChannelContext.mjs.map +0 -1
  114. package/lib/localChannelStorageService.d.mts.map +0 -1
  115. package/lib/localChannelStorageService.mjs.map +0 -1
  116. package/lib/remoteChannelContext.d.mts.map +0 -1
  117. package/lib/remoteChannelContext.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fluidHandle.js","sourceRoot":"","sources":["../src/fluidHandle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAQ7B;;OAEG;IACH,IAAW,YAAY;QACtB,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;OAEG;IACH,IAAW,UAAU;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAY,OAAO;QAClB;;;;;;;;;;;WAWG;QACH,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,cAAc,CAAC;IAC/C,CAAC;IAOD;;;;;;;OAOG;IACH,YACoB,KAAqB,EACxB,IAAY,EACZ,YAAiC;QAF9B,UAAK,GAAL,KAAK,CAAgB;QACxB,SAAI,GAAJ,IAAI,CAAQ;QACZ,iBAAY,GAAZ,YAAY,CAAqB;QAxDjC,gCAA2B,GAAsB,IAAI,GAAG,EAAE,CAAC;QAwC5E;;WAEG;QACK,mBAAc,GAAY,KAAK,CAAC;QAevC,IAAI,CAAC,YAAY,GAAG,yBAAyB,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACxE,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,GAAG;QACf,yGAAyG;QACzG,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,WAAW;QACjB,IAAI,IAAI,CAAC,OAAO,EAAE;YACjB,OAAO;SACP;QAED,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YACnD,MAAM,CAAC,WAAW,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,2BAA2B,CAAC,KAAK,EAAE,CAAC;QACzC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,IAAI,CAAC,MAAoB;QAC/B,8EAA8E;QAC9E,IAAI,IAAI,CAAC,OAAO,EAAE;YACjB,MAAM,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO;SACP;QACD,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IFluidHandle, IFluidHandleContext, FluidObject } from \"@fluidframework/core-interfaces\";\nimport { generateHandleContextPath } from \"@fluidframework/runtime-utils\";\n\n/**\n * Handle for a shared {@link @fluidframework/core-interfaces#FluidObject}.\n * @alpha\n */\nexport class FluidObjectHandle<T extends FluidObject = FluidObject> implements IFluidHandle {\n\tprivate readonly pendingHandlesToMakeVisible: Set<IFluidHandle> = new Set();\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IFluidHandle.absolutePath}\n\t */\n\tpublic readonly absolutePath: string;\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}\n\t */\n\tpublic get IFluidHandle(): IFluidHandle {\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IFluidHandle.isAttached}\n\t */\n\tpublic get isAttached(): boolean {\n\t\treturn this.routeContext.isAttached;\n\t}\n\n\t/**\n\t * Tells whether the object of this handle is visible in the container locally or globally.\n\t */\n\tprivate get visible(): boolean {\n\t\t/**\n\t\t * If the object of this handle is attached, it is visible in the container. Ideally, checking local visibility\n\t\t * should be enough for a handle. However, there are scenarios where the object becomes locally visible but the\n\t\t * handle does not know this - This will happen is attachGraph is never called on the handle. Couple of examples\n\t\t * where this can happen:\n\t\t *\n\t\t * 1. Handles to DDS other than the default handle won't know if the DDS becomes visible after the handle was\n\t\t * created.\n\t\t *\n\t\t * 2. Handles to root data stores will never know that it was visible because the handle will not be stores in\n\t\t * another DDS and so, attachGraph will never be called on it.\n\t\t */\n\t\treturn this.isAttached || this.locallyVisible;\n\t}\n\n\t/**\n\t * Tracks whether this handle is locally visible in the container.\n\t */\n\tprivate locallyVisible: boolean = false;\n\n\t/**\n\t * Creates a new `FluidObjectHandle`.\n\t *\n\t * @param value - The {@link @fluidframework/core-interfaces#FluidObject} object this handle is for.\n\t * @param path - The path to this handle relative to the `routeContext`.\n\t * @param routeContext - The parent {@link @fluidframework/core-interfaces#IFluidHandleContext} that has a route\n\t * to this handle.\n\t */\n\tconstructor(\n\t\tprotected readonly value: T | Promise<T>,\n\t\tpublic readonly path: string,\n\t\tpublic readonly routeContext: IFluidHandleContext,\n\t) {\n\t\tthis.absolutePath = generateHandleContextPath(path, this.routeContext);\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IFluidHandle.get}\n\t */\n\tpublic async get(): Promise<any> {\n\t\t// Note that this return works whether we received a T or a Promise<T> for this.value in the constructor.\n\t\treturn this.value;\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IFluidHandle.attachGraph }\n\t */\n\tpublic attachGraph(): void {\n\t\tif (this.visible) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.locallyVisible = true;\n\t\tthis.pendingHandlesToMakeVisible.forEach((handle) => {\n\t\t\thandle.attachGraph();\n\t\t});\n\t\tthis.pendingHandlesToMakeVisible.clear();\n\t\tthis.routeContext.attachGraph();\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IFluidHandle.bind}\n\t */\n\tpublic bind(handle: IFluidHandle) {\n\t\t// If this handle is visible, attach the graph of the incoming handle as well.\n\t\tif (this.visible) {\n\t\t\thandle.attachGraph();\n\t\t\treturn;\n\t\t}\n\t\tthis.pendingHandlesToMakeVisible.add(handle);\n\t}\n}\n"]}
@@ -2,6 +2,6 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export { FluidObjectHandle } from "./fluidHandle.mjs";
6
- export { DataStoreMessageType, FluidDataStoreRuntime, ISharedObjectRegistry, mixinRequestHandler, mixinSummaryHandler, } from "./dataStoreRuntime.mjs";
7
- //# sourceMappingURL=index.d.mts.map
5
+ export { FluidObjectHandle } from "./fluidHandle.js";
6
+ export { DataStoreMessageType, FluidDataStoreRuntime, ISharedObjectRegistry, mixinRequestHandler, mixinSummaryHandler, } from "./dataStoreRuntime.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,uBAAuB,CAAC"}
@@ -2,6 +2,6 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export { FluidObjectHandle } from "./fluidHandle.mjs";
6
- export { DataStoreMessageType, FluidDataStoreRuntime, mixinRequestHandler, mixinSummaryHandler, } from "./dataStoreRuntime.mjs";
7
- //# sourceMappingURL=index.mjs.map
5
+ export { FluidObjectHandle } from "./fluidHandle.js";
6
+ export { DataStoreMessageType, FluidDataStoreRuntime, mixinRequestHandler, mixinSummaryHandler, } from "./dataStoreRuntime.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EAErB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,uBAAuB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { FluidObjectHandle } from \"./fluidHandle.js\";\nexport {\n\tDataStoreMessageType,\n\tFluidDataStoreRuntime,\n\tISharedObjectRegistry,\n\tmixinRequestHandler,\n\tmixinSummaryHandler,\n} from \"./dataStoreRuntime.js\";\n"]}
@@ -9,8 +9,8 @@ import { IChannel, IFluidDataStoreRuntime } from "@fluidframework/datastore-defi
9
9
  import { IFluidDataStoreContext, IGarbageCollectionData, ISummarizeResult, ITelemetryContext } from "@fluidframework/runtime-definitions";
10
10
  import { Lazy } from "@fluidframework/core-utils";
11
11
  import { IFluidHandle } from "@fluidframework/core-interfaces";
12
- import { ChannelServiceEndpoints, IChannelContext } from "./channelContext.mjs";
13
- import { ISharedObjectRegistry } from "./dataStoreRuntime.mjs";
12
+ import { ChannelServiceEndpoints, IChannelContext } from "./channelContext.js";
13
+ import { ISharedObjectRegistry } from "./dataStoreRuntime.js";
14
14
  /**
15
15
  * Channel context for a locally created channel
16
16
  */
@@ -23,13 +23,14 @@ export declare abstract class LocalChannelContextBase implements IChannelContext
23
23
  private globallyVisible;
24
24
  protected readonly pending: ISequencedDocumentMessage[];
25
25
  constructor(id: string, runtime: IFluidDataStoreRuntime, services: Lazy<ChannelServiceEndpoints>, channelP: Promise<IChannel>, _channel?: IChannel | undefined);
26
+ protected get isGloballyVisible(): boolean;
26
27
  getChannel(): Promise<IChannel>;
27
28
  get isLoaded(): boolean;
28
29
  setConnectionState(connected: boolean, clientId?: string): void;
29
30
  processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void;
30
31
  reSubmit(content: any, localOpMetadata: unknown): void;
31
32
  rollback(content: any, localOpMetadata: unknown): void;
32
- applyStashedOp(): void;
33
+ abstract applyStashedOp(content: unknown): unknown;
33
34
  /**
34
35
  * Returns a summary at the current sequence number.
35
36
  * @param fullTree - true to bypass optimizations and force a full summary tree
@@ -64,6 +65,7 @@ export declare class RehydratedLocalChannelContext extends LocalChannelContextBa
64
65
  private readonly snapshotTree;
65
66
  private readonly dirtyFn;
66
67
  constructor(id: string, registry: ISharedObjectRegistry, runtime: IFluidDataStoreRuntime, dataStoreContext: IFluidDataStoreContext, storageService: IDocumentStorageService, logger: ITelemetryLoggerExt, submitFn: (content: any, localOpMetadata: unknown) => void, dirtyFn: (address: string) => void, addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void, snapshotTree: ISnapshotTree);
68
+ applyStashedOp(content: any): unknown;
67
69
  private isSnapshotInOldFormatAndCollectBlobs;
68
70
  private sanitizeSnapshot;
69
71
  }
@@ -71,5 +73,6 @@ export declare class LocalChannelContext extends LocalChannelContextBase {
71
73
  readonly channel: IChannel;
72
74
  private readonly dirtyFn;
73
75
  constructor(channel: IChannel, runtime: IFluidDataStoreRuntime, dataStoreContext: IFluidDataStoreContext, storageService: IDocumentStorageService, logger: ITelemetryLoggerExt, submitFn: (content: any, localOpMetadata: unknown) => void, dirtyFn: (address: string) => void, addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void);
76
+ applyStashedOp(): void;
74
77
  }
75
- //# sourceMappingURL=localChannelContext.d.mts.map
78
+ //# sourceMappingURL=localChannelContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localChannelContext.d.ts","sourceRoot":"","sources":["../src/localChannelContext.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAuB,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EACN,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAU,IAAI,EAAe,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAE/D,OAAO,EACN,uBAAuB,EAEvB,eAAe,EAKf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,8BAAsB,uBAAwB,YAAW,eAAe;IAItE,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM;IAC7B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,sBAAsB;IAClD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,uBAAuB,CAAC;IAC1D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC;IAPlB,OAAO,CAAC,eAAe,CAAS;IAChC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,yBAAyB,EAAE,CAAM;gBAEzC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,sBAAsB,EAC/B,QAAQ,EAAE,IAAI,CAAC,uBAAuB,CAAC,EACzC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,EACpC,QAAQ,CAAC,sBAAU;IAK5B,SAAS,KAAK,iBAAiB,YAE9B;IAEY,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAC;IAO5C,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAEM,kBAAkB,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM;IAOxD,SAAS,CACf,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,OAAO,GACtB,IAAI;IAoBA,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO;IAQ/C,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO;aAStC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAEzD;;;;;OAKG;IACU,SAAS,CACrB,QAAQ,GAAE,OAAe,EACzB,UAAU,GAAE,OAAe,EAC3B,gBAAgB,CAAC,EAAE,iBAAiB,GAClC,OAAO,CAAC,gBAAgB,CAAC;IAK5B;;;;OAIG;IACI,gBAAgB,CAAC,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,gBAAgB;IAa/E;;;;;OAKG;IACI,eAAe,CAAC,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,sBAAsB;IAU7E,WAAW,IAAI,IAAI;IAY1B;;;;;OAKG;IACU,SAAS,CAAC,MAAM,GAAE,OAAe,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAKzE,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE;CAO5C;AAED,qBAAa,6BAA8B,SAAQ,uBAAuB;IAYxE,OAAO,CAAC,QAAQ,CAAC,YAAY;IAX9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;gBAEpC,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,sBAAsB,EAC/B,gBAAgB,EAAE,sBAAsB,EACxC,cAAc,EAAE,uBAAuB,EACvC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,EAC1D,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAClC,0BAA0B,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,KAAK,IAAI,EAC1E,YAAY,EAAE,aAAa;IAkE7B,cAAc,CAAC,OAAO,KAAA;IAItC,OAAO,CAAC,oCAAoC;IAoB5C,OAAO,CAAC,gBAAgB;CAaxB;AAED,qBAAa,mBAAoB,SAAQ,uBAAuB;aAG9C,OAAO,EAAE,QAAQ;IAFlC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;gBAEpB,OAAO,EAAE,QAAQ,EACjC,OAAO,EAAE,sBAAsB,EAC/B,gBAAgB,EAAE,sBAAsB,EACxC,cAAc,EAAE,uBAAuB,EACvC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,EAC1D,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAClC,0BAA0B,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,KAAK,IAAI;IA0BrF,cAAc;CAGrB"}
@@ -7,7 +7,7 @@ import lodashPkg from "lodash";
7
7
  const { cloneDeep } = lodashPkg;
8
8
  import { DataProcessingError } from "@fluidframework/telemetry-utils";
9
9
  import { assert, Lazy, LazyPromise } from "@fluidframework/core-utils";
10
- import { createChannelServiceEndpoints, loadChannel, loadChannelFactoryAndAttributes, summarizeChannel, summarizeChannelAsync, } from "./channelContext.mjs";
10
+ import { createChannelServiceEndpoints, loadChannel, loadChannelFactoryAndAttributes, summarizeChannel, summarizeChannelAsync, } from "./channelContext.js";
11
11
  /**
12
12
  * Channel context for a locally created channel
13
13
  */
@@ -22,6 +22,9 @@ export class LocalChannelContextBase {
22
22
  this.pending = [];
23
23
  assert(!this.id.includes("/"), 0x30f /* Channel context ID cannot contain slashes */);
24
24
  }
25
+ get isGloballyVisible() {
26
+ return this.globallyVisible;
27
+ }
25
28
  async getChannel() {
26
29
  if (this._channel === undefined) {
27
30
  return this.channelP.then((c) => (this._channel = c));
@@ -60,9 +63,6 @@ export class LocalChannelContextBase {
60
63
  assert(this.globallyVisible, 0x2ef /* "Local channel must be globally visible when rolling back op" */);
61
64
  this.services.value.deltaConnection.rollback(content, localOpMetadata);
62
65
  }
63
- applyStashedOp() {
64
- throw new Error("no stashed ops on local channel");
65
- }
66
66
  /**
67
67
  * Returns a summary at the current sequence number.
68
68
  * @param fullTree - true to bypass optimizations and force a full summary tree
@@ -89,7 +89,7 @@ export class LocalChannelContextBase {
89
89
  * to be joined with the same from the DataStore's other channels
90
90
  */
91
91
  getAttachGCData(telemetryContext) {
92
- assert(this._channel !== undefined, "Local Channel should be loaded before being attached");
92
+ assert(this._channel !== undefined, 0x8fd /* Local Channel should be loaded before being attached */);
93
93
  // We need the GC Data to detect references added in this attach op
94
94
  return this._channel.getGCData(/* fullGC: */ true);
95
95
  }
@@ -132,7 +132,7 @@ export class RehydratedLocalChannelContext extends LocalChannelContextBase {
132
132
  if (this.isSnapshotInOldFormatAndCollectBlobs(clonedSnapshotTree, blobMap)) {
133
133
  this.sanitizeSnapshot(clonedSnapshotTree);
134
134
  }
135
- return createChannelServiceEndpoints(dataStoreContext.connected, submitFn, this.dirtyFn, addedGCOutboundReferenceFn, storageService, logger, clonedSnapshotTree, blobMap);
135
+ return createChannelServiceEndpoints(dataStoreContext.connected, submitFn, this.dirtyFn, addedGCOutboundReferenceFn, () => this.isGloballyVisible, storageService, logger, clonedSnapshotTree, blobMap);
136
136
  }), new LazyPromise(async () => {
137
137
  try {
138
138
  const { attributes, factory } = await loadChannelFactoryAndAttributes(dataStoreContext, this.services.value, this.id, registry);
@@ -152,6 +152,9 @@ export class RehydratedLocalChannelContext extends LocalChannelContextBase {
152
152
  dirtyFn(id);
153
153
  };
154
154
  }
155
+ applyStashedOp(content) {
156
+ return this.services.value.deltaConnection.applyStashedOp(content);
157
+ }
155
158
  isSnapshotInOldFormatAndCollectBlobs(snapshotTree, blobMap) {
156
159
  let sanitize = false;
157
160
  const blobsContents = snapshotTree.blobsContents;
@@ -185,7 +188,7 @@ export class RehydratedLocalChannelContext extends LocalChannelContextBase {
185
188
  export class LocalChannelContext extends LocalChannelContextBase {
186
189
  constructor(channel, runtime, dataStoreContext, storageService, logger, submitFn, dirtyFn, addedGCOutboundReferenceFn) {
187
190
  super(channel.id, runtime, new Lazy(() => {
188
- return createChannelServiceEndpoints(dataStoreContext.connected, submitFn, this.dirtyFn, addedGCOutboundReferenceFn, storageService, logger);
191
+ return createChannelServiceEndpoints(dataStoreContext.connected, submitFn, this.dirtyFn, addedGCOutboundReferenceFn, () => this.isGloballyVisible, storageService, logger);
189
192
  }), Promise.resolve(channel), channel);
190
193
  this.channel = channel;
191
194
  this.channel = channel;
@@ -193,5 +196,8 @@ export class LocalChannelContext extends LocalChannelContextBase {
193
196
  dirtyFn(channel.id);
194
197
  };
195
198
  }
199
+ applyStashedOp() {
200
+ throw new Error("no stashed ops on local channel");
201
+ }
196
202
  }
197
- //# sourceMappingURL=localChannelContext.mjs.map
203
+ //# sourceMappingURL=localChannelContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localChannelContext.js","sourceRoot":"","sources":["../src/localChannelContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport lodashPkg from \"lodash\";\n// eslint-disable-next-line @typescript-eslint/unbound-method\nconst { cloneDeep } = lodashPkg;\n\nimport { DataProcessingError, ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { IChannel, IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions\";\nimport {\n\tIFluidDataStoreContext,\n\tIGarbageCollectionData,\n\tISummarizeResult,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport { assert, Lazy, LazyPromise } from \"@fluidframework/core-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { ISnapshotTreeWithBlobContents } from \"@fluidframework/container-definitions\";\nimport {\n\tChannelServiceEndpoints,\n\tcreateChannelServiceEndpoints,\n\tIChannelContext,\n\tloadChannel,\n\tloadChannelFactoryAndAttributes,\n\tsummarizeChannel,\n\tsummarizeChannelAsync,\n} from \"./channelContext.js\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime.js\";\n\n/**\n * Channel context for a locally created channel\n */\nexport abstract class LocalChannelContextBase implements IChannelContext {\n\tprivate globallyVisible = false;\n\tprotected readonly pending: ISequencedDocumentMessage[] = [];\n\tconstructor(\n\t\tprotected readonly id: string,\n\t\tprotected readonly runtime: IFluidDataStoreRuntime,\n\t\tprotected readonly services: Lazy<ChannelServiceEndpoints>,\n\t\tprivate readonly channelP: Promise<IChannel>,\n\t\tprivate _channel?: IChannel,\n\t) {\n\t\tassert(!this.id.includes(\"/\"), 0x30f /* Channel context ID cannot contain slashes */);\n\t}\n\n\tprotected get isGloballyVisible() {\n\t\treturn this.globallyVisible;\n\t}\n\n\tpublic async getChannel(): Promise<IChannel> {\n\t\tif (this._channel === undefined) {\n\t\t\treturn this.channelP.then((c) => (this._channel = c));\n\t\t}\n\t\treturn this.channelP;\n\t}\n\n\tpublic get isLoaded(): boolean {\n\t\treturn this._channel !== undefined;\n\t}\n\n\tpublic setConnectionState(connected: boolean, clientId?: string) {\n\t\t// Connection events are ignored if the data store is not yet globallyVisible or loaded\n\t\tif (this.globallyVisible && this.isLoaded) {\n\t\t\tthis.services.value.deltaConnection.setConnectionState(connected);\n\t\t}\n\t}\n\n\tpublic processOp(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t): void {\n\t\tassert(\n\t\t\tthis.globallyVisible,\n\t\t\t0x2d3 /* \"Local channel must be globally visible when processing op\" */,\n\t\t);\n\n\t\t// A local channel may not be loaded in case where we rehydrate the container from a snapshot because of\n\t\t// delay loading. So after the container is attached and some other client joins which start generating\n\t\t// ops for this channel. So not loaded local channel can still receive ops and we store them to process later.\n\t\tif (this.isLoaded) {\n\t\t\tthis.services.value.deltaConnection.process(message, local, localOpMetadata);\n\t\t} else {\n\t\t\tassert(\n\t\t\t\tlocal === false,\n\t\t\t\t0x189 /* \"Should always be remote because a local dds shouldn't generate ops before loading\" */,\n\t\t\t);\n\t\t\tthis.pending.push(message);\n\t\t}\n\t}\n\n\tpublic reSubmit(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x18a /* \"Channel should be loaded to resubmit ops\" */);\n\t\tassert(\n\t\t\tthis.globallyVisible,\n\t\t\t0x2d4 /* \"Local channel must be globally visible when resubmitting op\" */,\n\t\t);\n\t\tthis.services.value.deltaConnection.reSubmit(content, localOpMetadata);\n\t}\n\tpublic rollback(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x2ee /* \"Channel should be loaded to rollback ops\" */);\n\t\tassert(\n\t\t\tthis.globallyVisible,\n\t\t\t0x2ef /* \"Local channel must be globally visible when rolling back op\" */,\n\t\t);\n\t\tthis.services.value.deltaConnection.rollback(content, localOpMetadata);\n\t}\n\n\tpublic abstract applyStashedOp(content: unknown): unknown;\n\n\t/**\n\t * Returns a summary at the current sequence number.\n\t * @param fullTree - true to bypass optimizations and force a full summary tree\n\t * @param trackState - This tells whether we should track state from this summary.\n\t * @param telemetryContext - summary data passed through the layers for telemetry purposes\n\t */\n\tpublic async summarize(\n\t\tfullTree: boolean = false,\n\t\ttrackState: boolean = false,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<ISummarizeResult> {\n\t\tconst channel = await this.getChannel();\n\t\treturn summarizeChannelAsync(channel, fullTree, trackState, telemetryContext);\n\t}\n\n\t/**\n\t * For crafting the DataStore attach op. Only to be called when the channel is loaded (if applicable).\n\t *\n\t * Synchronously generates the channel's attach summary to be joined with the same from the DataStore's other channels\n\t */\n\tpublic getAttachSummary(telemetryContext?: ITelemetryContext): ISummarizeResult {\n\t\tassert(\n\t\t\tthis._channel !== undefined,\n\t\t\t0x18d /* \"Channel should be loaded to take snapshot\" */,\n\t\t);\n\t\treturn summarizeChannel(\n\t\t\tthis._channel,\n\t\t\ttrue /* fullTree */,\n\t\t\tfalse /* trackState */,\n\t\t\ttelemetryContext,\n\t\t);\n\t}\n\n\t/**\n\t * For crafting the DataStore attach op. Only to be called when the channel is loaded (if applicable).\n\t *\n\t * Synchronously generates the channel's attach GC data (set of outbound routes in the initial state)\n\t * to be joined with the same from the DataStore's other channels\n\t */\n\tpublic getAttachGCData(telemetryContext?: ITelemetryContext): IGarbageCollectionData {\n\t\tassert(\n\t\t\tthis._channel !== undefined,\n\t\t\t0x8fd /* Local Channel should be loaded before being attached */,\n\t\t);\n\n\t\t// We need the GC Data to detect references added in this attach op\n\t\treturn this._channel.getGCData(/* fullGC: */ true);\n\t}\n\n\tpublic makeVisible(): void {\n\t\tif (this.globallyVisible) {\n\t\t\tthrow new Error(\"Channel is already globally visible\");\n\t\t}\n\n\t\tif (this.isLoaded) {\n\t\t\tassert(!!this._channel, 0x192 /* \"Channel should be there if loaded!!\" */);\n\t\t\tthis._channel.connect(this.services.value);\n\t\t}\n\t\tthis.globallyVisible = true;\n\t}\n\n\t/**\n\t * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.\n\t * Each node has a set of outbound routes to other GC nodes in the document. This should be called only after\n\t * the context has loaded.\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tpublic async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\tconst channel = await this.getChannel();\n\t\treturn channel.getGCData(fullGC);\n\t}\n\n\tpublic updateUsedRoutes(usedRoutes: string[]) {\n\t\t/**\n\t\t * Currently, DDSes are always considered referenced and are not garbage collected.\n\t\t * Once we have GC at DDS level, this channel context's used routes will be updated as per the passed\n\t\t * value. See - https://github.com/microsoft/FluidFramework/issues/4611\n\t\t */\n\t}\n}\n\nexport class RehydratedLocalChannelContext extends LocalChannelContextBase {\n\tprivate readonly dirtyFn: () => void;\n\tconstructor(\n\t\tid: string,\n\t\tregistry: ISharedObjectRegistry,\n\t\truntime: IFluidDataStoreRuntime,\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tstorageService: IDocumentStorageService,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tsubmitFn: (content: any, localOpMetadata: unknown) => void,\n\t\tdirtyFn: (address: string) => void,\n\t\taddedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n\t\tprivate readonly snapshotTree: ISnapshotTree,\n\t) {\n\t\tsuper(\n\t\t\tid,\n\t\t\truntime,\n\t\t\tnew Lazy(() => {\n\t\t\t\tconst blobMap: Map<string, ArrayBufferLike> = new Map<string, ArrayBufferLike>();\n\t\t\t\tconst clonedSnapshotTree = cloneDeep(this.snapshotTree);\n\t\t\t\t// 0.47 back-compat Need to sanitize if snapshotTree.blobs still contains blob contents too.\n\t\t\t\t// This is for older snapshot which is generated by loader <=0.47 version which still contains\n\t\t\t\t// the contents within blobs. After a couple of revisions we can remove it.\n\t\t\t\tif (this.isSnapshotInOldFormatAndCollectBlobs(clonedSnapshotTree, blobMap)) {\n\t\t\t\t\tthis.sanitizeSnapshot(clonedSnapshotTree);\n\t\t\t\t}\n\t\t\t\treturn createChannelServiceEndpoints(\n\t\t\t\t\tdataStoreContext.connected,\n\t\t\t\t\tsubmitFn,\n\t\t\t\t\tthis.dirtyFn,\n\t\t\t\t\taddedGCOutboundReferenceFn,\n\t\t\t\t\t() => this.isGloballyVisible,\n\t\t\t\t\tstorageService,\n\t\t\t\t\tlogger,\n\t\t\t\t\tclonedSnapshotTree,\n\t\t\t\t\tblobMap,\n\t\t\t\t);\n\t\t\t}),\n\t\t\tnew LazyPromise<IChannel>(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { attributes, factory } = await loadChannelFactoryAndAttributes(\n\t\t\t\t\t\tdataStoreContext,\n\t\t\t\t\t\tthis.services.value,\n\t\t\t\t\t\tthis.id,\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t);\n\t\t\t\t\tconst channel = await loadChannel(\n\t\t\t\t\t\truntime,\n\t\t\t\t\t\tattributes,\n\t\t\t\t\t\tfactory,\n\t\t\t\t\t\tthis.services.value,\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t\tthis.id,\n\t\t\t\t\t);\n\t\t\t\t\t// Send all pending messages to the channel\n\t\t\t\t\tfor (const message of this.pending) {\n\t\t\t\t\t\tthis.services.value.deltaConnection.process(\n\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tundefined /* localOpMetadata */,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn channel;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthrow DataProcessingError.wrapIfUnrecognized(\n\t\t\t\t\t\terr,\n\t\t\t\t\t\t\"rehydratedLocalChannelContextFailedToLoadChannel\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\tthis.dirtyFn = () => {\n\t\t\tdirtyFn(id);\n\t\t};\n\t}\n\n\tpublic override applyStashedOp(content) {\n\t\treturn this.services.value.deltaConnection.applyStashedOp(content);\n\t}\n\n\tprivate isSnapshotInOldFormatAndCollectBlobs(\n\t\tsnapshotTree: ISnapshotTreeWithBlobContents,\n\t\tblobMap: Map<string, ArrayBufferLike>,\n\t): boolean {\n\t\tlet sanitize = false;\n\t\tconst blobsContents = snapshotTree.blobsContents;\n\t\tif (blobsContents !== undefined) {\n\t\t\tObject.entries(blobsContents).forEach(([key, value]) => {\n\t\t\t\tblobMap.set(key, value);\n\t\t\t\tif (snapshotTree.blobs[key] !== undefined) {\n\t\t\t\t\tsanitize = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tfor (const value of Object.values(snapshotTree.trees)) {\n\t\t\tsanitize = sanitize || this.isSnapshotInOldFormatAndCollectBlobs(value, blobMap);\n\t\t}\n\t\treturn sanitize;\n\t}\n\n\tprivate sanitizeSnapshot(snapshotTree: ISnapshotTree) {\n\t\tconst blobMapInitial = new Map(Object.entries(snapshotTree.blobs));\n\t\tfor (const [blobName, blobId] of blobMapInitial.entries()) {\n\t\t\tconst blobValue = blobMapInitial.get(blobId);\n\t\t\tif (blobValue === undefined) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n\t\t\t\tdelete snapshotTree.blobs[blobName];\n\t\t\t}\n\t\t}\n\t\tfor (const value of Object.values(snapshotTree.trees)) {\n\t\t\tthis.sanitizeSnapshot(value);\n\t\t}\n\t}\n}\n\nexport class LocalChannelContext extends LocalChannelContextBase {\n\tprivate readonly dirtyFn: () => void;\n\tconstructor(\n\t\tpublic readonly channel: IChannel,\n\t\truntime: IFluidDataStoreRuntime,\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tstorageService: IDocumentStorageService,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tsubmitFn: (content: any, localOpMetadata: unknown) => void,\n\t\tdirtyFn: (address: string) => void,\n\t\taddedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n\t) {\n\t\tsuper(\n\t\t\tchannel.id,\n\t\t\truntime,\n\t\t\tnew Lazy(() => {\n\t\t\t\treturn createChannelServiceEndpoints(\n\t\t\t\t\tdataStoreContext.connected,\n\t\t\t\t\tsubmitFn,\n\t\t\t\t\tthis.dirtyFn,\n\t\t\t\t\taddedGCOutboundReferenceFn,\n\t\t\t\t\t() => this.isGloballyVisible,\n\t\t\t\t\tstorageService,\n\t\t\t\t\tlogger,\n\t\t\t\t);\n\t\t\t}),\n\t\t\tPromise.resolve(channel),\n\t\t\tchannel,\n\t\t);\n\t\tthis.channel = channel;\n\n\t\tthis.dirtyFn = () => {\n\t\t\tdirtyFn(channel.id);\n\t\t};\n\t}\n\n\tpublic applyStashedOp() {\n\t\tthrow new Error(\"no stashed ops on local channel\");\n\t}\n}\n"]}
@@ -13,4 +13,4 @@ export declare class LocalChannelStorageService implements IChannelStorageServic
13
13
  private readBlobSync;
14
14
  private readBlobSyncInternal;
15
15
  }
16
- //# sourceMappingURL=localChannelStorageService.d.mts.map
16
+ //# sourceMappingURL=localChannelStorageService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localChannelStorageService.d.ts","sourceRoot":"","sources":["../src/localChannelStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,OAAO,EAAS,KAAK,EAAa,MAAM,sCAAsC,CAAC;AAG/E,qBAAa,0BAA2B,YAAW,sBAAsB;IAC5D,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,KAAK;IAE3B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAQhD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIlD,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,oBAAoB;CAwB5B"}
@@ -45,4 +45,4 @@ export class LocalChannelStorageService {
45
45
  return undefined;
46
46
  }
47
47
  }
48
- //# sourceMappingURL=localChannelStorageService.mjs.map
48
+ //# sourceMappingURL=localChannelStorageService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localChannelStorageService.js","sourceRoot":"","sources":["../src/localChannelStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAgB,SAAS,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,MAAM,OAAO,0BAA0B;IACtC,YAA6B,IAAW;QAAX,SAAI,GAAJ,IAAI,CAAO;IAAG,CAAC;IAErC,KAAK,CAAC,QAAQ,CAAC,IAAY;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,IAAI,KAAK,SAAS,EAAE;YACvB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;SAClC;QACD,OAAO,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,IAAY;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IACjE,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,IAAY;QAC7B,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAEO,YAAY,CAAC,IAAY;QAChC,OAAO,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC;IAEO,oBAAoB,CAAC,IAAY,EAAE,IAAW;QACrD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE;YACjC,QAAQ,KAAK,CAAC,IAAI,EAAE;gBACnB,KAAK,SAAS,CAAC,IAAI;oBAClB,IAAI,IAAI,KAAK,KAAK,CAAC,IAAI,EAAE;wBACxB,OAAO,KAAK,CAAC,KAAK,CAAC;qBACnB;oBACD,MAAM;gBAEP,KAAK,SAAS,CAAC,IAAI;oBAClB,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;wBAChC,OAAO,IAAI,CAAC,oBAAoB,CAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAClC,KAAK,CAAC,KAAK,CACX,CAAC;qBACF;oBACD,MAAM;gBAEP,QAAQ;aACR;SACD;QAED,OAAO,SAAS,CAAC;IAClB,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IChannelStorageService } from \"@fluidframework/datastore-definitions\";\nimport { stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { IBlob, ITree, TreeEntry } from \"@fluidframework/protocol-definitions\";\nimport { listBlobsAtTreePath } from \"@fluidframework/runtime-utils\";\n\nexport class LocalChannelStorageService implements IChannelStorageService {\n\tconstructor(private readonly tree: ITree) {}\n\n\tpublic async readBlob(path: string): Promise<ArrayBufferLike> {\n\t\tconst blob = this.readBlobSync(path);\n\t\tif (blob === undefined) {\n\t\t\tthrow new Error(\"Blob Not Found\");\n\t\t}\n\t\treturn stringToBuffer(blob.contents, blob.encoding);\n\t}\n\n\tpublic async contains(path: string): Promise<boolean> {\n\t\tconst blob = this.readBlobSync(path);\n\t\treturn blob !== undefined ? blob.contents !== undefined : false;\n\t}\n\n\tpublic async list(path: string): Promise<string[]> {\n\t\treturn listBlobsAtTreePath(this.tree, path);\n\t}\n\n\tprivate readBlobSync(path: string): IBlob | undefined {\n\t\treturn this.readBlobSyncInternal(path, this.tree);\n\t}\n\n\tprivate readBlobSyncInternal(path: string, tree: ITree): IBlob | undefined {\n\t\tfor (const entry of tree.entries) {\n\t\t\tswitch (entry.type) {\n\t\t\t\tcase TreeEntry.Blob:\n\t\t\t\t\tif (path === entry.path) {\n\t\t\t\t\t\treturn entry.value;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TreeEntry.Tree:\n\t\t\t\t\tif (path.startsWith(entry.path)) {\n\t\t\t\t\t\treturn this.readBlobSyncInternal(\n\t\t\t\t\t\t\tpath.substr(entry.path.length + 1),\n\t\t\t\t\t\t\tentry.value,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -7,8 +7,8 @@ import { IChannel, IFluidDataStoreRuntime } from "@fluidframework/datastore-defi
7
7
  import { IDocumentStorageService } from "@fluidframework/driver-definitions";
8
8
  import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
9
9
  import { CreateChildSummarizerNodeFn, IFluidDataStoreContext, IGarbageCollectionData, ISummarizeResult, ITelemetryContext } from "@fluidframework/runtime-definitions";
10
- import { IChannelContext } from "./channelContext.mjs";
11
- import { ISharedObjectRegistry } from "./dataStoreRuntime.mjs";
10
+ import { IChannelContext } from "./channelContext.js";
11
+ import { ISharedObjectRegistry } from "./dataStoreRuntime.js";
12
12
  export declare class RemoteChannelContext implements IChannelContext {
13
13
  private readonly id;
14
14
  private isLoaded;
@@ -51,4 +51,4 @@ export declare class RemoteChannelContext implements IChannelContext {
51
51
  private getGCDataInternal;
52
52
  updateUsedRoutes(usedRoutes: string[]): void;
53
53
  }
54
- //# sourceMappingURL=remoteChannelContext.d.mts.map
54
+ //# sourceMappingURL=remoteChannelContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteChannelContext.d.ts","sourceRoot":"","sources":["../src/remoteChannelContext.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAChG,OAAO,EACN,2BAA2B,EAC3B,sBAAsB,EACtB,sBAAsB,EAGtB,gBAAgB,EAEhB,iBAAiB,EACjB,MAAM,qCAAqC,CAAC;AAO7C,OAAO,EAGN,eAAe,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,qBAAa,oBAAqB,YAAW,eAAe;IAkB1D,OAAO,CAAC,QAAQ,CAAC,EAAE;IAjBpB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAA+C;IAC9D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAmB;IACvD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAQ;gBAGvD,OAAO,EAAE,sBAAsB,EAC/B,gBAAgB,EAAE,sBAAsB,EACxC,cAAc,EAAE,uBAAuB,EACvC,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,EAC1D,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAClC,0BAA0B,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,KAAK,IAAI,EAC1E,EAAE,EAAE,MAAM,EAC3B,YAAY,EAAE,aAAa,EAC3B,QAAQ,EAAE,qBAAqB,EAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,EACpD,oBAAoB,EAAE,2BAA2B,EACjD,iBAAiB,CAAC,EAAE,MAAM;IAsFpB,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAC;IAI/B,kBAAkB,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM;IASxD,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAKrC,SAAS,CACf,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,OAAO,GACtB,IAAI;IAaA,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO;IAM/C,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO;IAMtD;;;;;OAKG;IACU,SAAS,CACrB,QAAQ,GAAE,OAAe,EACzB,UAAU,GAAE,OAAc,EAC1B,gBAAgB,CAAC,EAAE,iBAAiB,GAClC,OAAO,CAAC,gBAAgB,CAAC;YAId,iBAAiB;IAiB/B;;;;;;OAMG;IACU,SAAS,CAAC,MAAM,GAAE,OAAe,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAIhF;;;;OAIG;YACW,iBAAiB;IAKxB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE;CAS5C"}
@@ -4,7 +4,8 @@
4
4
  */
5
5
  import { assert, LazyPromise } from "@fluidframework/core-utils";
6
6
  import { createChildLogger, ThresholdCounter, } from "@fluidframework/telemetry-utils";
7
- import { createChannelServiceEndpoints, loadChannel, loadChannelFactoryAndAttributes, summarizeChannelAsync, } from "./channelContext.mjs";
7
+ import { AttachState } from "@fluidframework/container-definitions";
8
+ import { createChannelServiceEndpoints, loadChannel, loadChannelFactoryAndAttributes, summarizeChannelAsync, } from "./channelContext.js";
8
9
  export class RemoteChannelContext {
9
10
  constructor(runtime, dataStoreContext, storageService, submitFn, dirtyFn, addedGCOutboundReferenceFn, id, baseSnapshot, registry, extraBlobs, createSummarizerNode, attachMessageType) {
10
11
  this.id = id;
@@ -15,7 +16,7 @@ export class RemoteChannelContext {
15
16
  logger: runtime.logger,
16
17
  namespace: "RemoteChannelContext",
17
18
  });
18
- this.services = createChannelServiceEndpoints(dataStoreContext.connected, submitFn, () => dirtyFn(this.id), addedGCOutboundReferenceFn, storageService, this.subLogger, baseSnapshot, extraBlobs);
19
+ this.services = createChannelServiceEndpoints(dataStoreContext.connected, submitFn, () => dirtyFn(this.id), addedGCOutboundReferenceFn, () => runtime.attachState !== AttachState.Detached, storageService, this.subLogger, baseSnapshot, extraBlobs);
19
20
  this.channelP = new LazyPromise(async () => {
20
21
  const { attributes, factory } = await loadChannelFactoryAndAttributes(dataStoreContext, this.services, this.id, registry, attachMessageType);
21
22
  const channel = await loadChannel(runtime, attributes, factory, this.services, this.subLogger, this.id);
@@ -117,4 +118,4 @@ export class RemoteChannelContext {
117
118
  }
118
119
  }
119
120
  RemoteChannelContext.pendingOpsCountThreshold = 1000;
120
- //# sourceMappingURL=remoteChannelContext.mjs.map
121
+ //# sourceMappingURL=remoteChannelContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteChannelContext.js","sourceRoot":"","sources":["../src/remoteChannelContext.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAejE,OAAO,EACN,iBAAiB,EAEjB,gBAAgB,GAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAEN,6BAA6B,EAE7B,WAAW,EACX,+BAA+B,EAC/B,qBAAqB,GACrB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,OAAO,oBAAoB;IAWhC,YACC,OAA+B,EAC/B,gBAAwC,EACxC,cAAuC,EACvC,QAA0D,EAC1D,OAAkC,EAClC,0BAA2F,EAC1E,EAAU,EAC3B,YAA2B,EAC3B,QAA+B,EAC/B,UAAoD,EACpD,oBAAiD,EACjD,iBAA0B;QALT,OAAE,GAAF,EAAE,CAAQ;QAjBpB,aAAQ,GAAG,KAAK,CAAC;QACjB,YAAO,GAA4C,EAAE,CAAC;QAuB7D,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAEtF,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC;YAClC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE,sBAAsB;SACjC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,GAAG,6BAA6B,CAC5C,gBAAgB,CAAC,SAAS,EAC1B,QAAQ,EACR,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EACtB,0BAA0B,EAC1B,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAClD,cAAc,EACd,IAAI,CAAC,SAAS,EACd,YAAY,EACZ,UAAU,CACV,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAW,KAAK,IAAI,EAAE;YACpD,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,+BAA+B,CACpE,gBAAgB,EAChB,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,EAAE,EACP,QAAQ,EACR,iBAAiB,CACjB,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,WAAW,CAChC,OAAO,EACP,UAAU,EACV,OAAO,EACP,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,EAAE,CACP,CAAC;YAEF,2CAA2C;YAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC;YACpE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE;gBACnC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,OAAO,CACpC,OAAO,EACP,KAAK,EACL,SAAS,CAAC,qBAAqB,CAC/B,CAAC;aACF;YACD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAExE,kBAAkB;YAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;YACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YAErB,2GAA2G;YAC3G,wGAAwG;YACxG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC,OAAO,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,MAAM,qBAAqB,GAAG,KAAK,EAClC,QAAiB,EACjB,UAAmB,EACnB,gBAAoC,EACpC,yBAAkE,EACjE,EAAE,CACH,IAAI,CAAC,iBAAiB,CACrB,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,yBAAyB,CACzB,CAAC;QAEH,IAAI,CAAC,cAAc,GAAG,oBAAoB,CACzC,qBAAqB,EACrB,KAAK,EAAE,MAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC1D,CAAC;QAEF,IAAI,CAAC,mBAAmB,GAAG,IAAI,gBAAgB,CAC9C,oBAAoB,CAAC,wBAAwB,EAC7C,IAAI,CAAC,SAAS,CACd,CAAC;IACH,CAAC;IAED,qEAAqE;IAC9D,UAAU;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAEM,kBAAkB,CAAC,SAAkB,EAAE,QAAiB;QAC9D,oEAAoE;QACpE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACnB,OAAO;SACP;QAED,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC;IAEM,cAAc,CAAC,OAAY;QACjC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACpF,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9D,CAAC;IAEM,SAAS,CACf,OAAkC,EAClC,KAAc,EACd,eAAwB;QAExB,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEvD,IAAI,IAAI,CAAC,QAAQ,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;SACvE;aAAM;YACN,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,2DAA2D,CAAC,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,KAAK,CAAC,4BAA4B,CAAC,CAAC;YACvE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;SAChF;IACF,CAAC;IAEM,QAAQ,CAAC,OAAY,EAAE,eAAwB;QACrD,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAExF,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAClE,CAAC;IAEM,QAAQ,CAAC,OAAY,EAAE,eAAwB;QACrD,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAExF,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAClE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,SAAS,CACrB,WAAoB,KAAK,EACzB,aAAsB,IAAI,EAC1B,gBAAoC;QAEpC,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAC9E,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAC9B,QAAiB,EACjB,UAAmB,EACnB,gBAAoC,EACpC,yBAAkE;QAElE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAClD,OAAO,EACP,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,yBAAyB,CACzB,CAAC;QACF,OAAO,EAAE,GAAG,eAAe,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;IAC5C,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,SAAS,CAAC,SAAkB,KAAK;QAC7C,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,iBAAiB,CAAC,SAAkB,KAAK;QACtD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,OAAO,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAEM,gBAAgB,CAAC,UAAoB;QAC3C;;;;;WAKG;QACH,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;;AA/MuB,6CAAwB,GAAG,IAAI,AAAP,CAAQ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, LazyPromise } from \"@fluidframework/core-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IChannel, IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tCreateChildSummarizerNodeFn,\n\tIFluidDataStoreContext,\n\tIGarbageCollectionData,\n\tIExperimentalIncrementalSummaryContext,\n\tISummarizeInternalResult,\n\tISummarizeResult,\n\tISummarizerNodeWithGC,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n\tcreateChildLogger,\n\tITelemetryLoggerExt,\n\tThresholdCounter,\n} from \"@fluidframework/telemetry-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport {\n\tChannelServiceEndpoints,\n\tcreateChannelServiceEndpoints,\n\tIChannelContext,\n\tloadChannel,\n\tloadChannelFactoryAndAttributes,\n\tsummarizeChannelAsync,\n} from \"./channelContext.js\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime.js\";\n\nexport class RemoteChannelContext implements IChannelContext {\n\tprivate isLoaded = false;\n\tprivate pending: ISequencedDocumentMessage[] | undefined = [];\n\tprivate readonly channelP: Promise<IChannel>;\n\tprivate channel: IChannel | undefined;\n\tprivate readonly services: ChannelServiceEndpoints;\n\tprivate readonly summarizerNode: ISummarizerNodeWithGC;\n\tprivate readonly subLogger: ITelemetryLoggerExt;\n\tprivate readonly thresholdOpsCounter: ThresholdCounter;\n\tprivate static readonly pendingOpsCountThreshold = 1000;\n\n\tconstructor(\n\t\truntime: IFluidDataStoreRuntime,\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tstorageService: IDocumentStorageService,\n\t\tsubmitFn: (content: any, localOpMetadata: unknown) => void,\n\t\tdirtyFn: (address: string) => void,\n\t\taddedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n\t\tprivate readonly id: string,\n\t\tbaseSnapshot: ISnapshotTree,\n\t\tregistry: ISharedObjectRegistry,\n\t\textraBlobs: Map<string, ArrayBufferLike> | undefined,\n\t\tcreateSummarizerNode: CreateChildSummarizerNodeFn,\n\t\tattachMessageType?: string,\n\t) {\n\t\tassert(!this.id.includes(\"/\"), 0x310 /* Channel context ID cannot contain slashes */);\n\n\t\tthis.subLogger = createChildLogger({\n\t\t\tlogger: runtime.logger,\n\t\t\tnamespace: \"RemoteChannelContext\",\n\t\t});\n\n\t\tthis.services = createChannelServiceEndpoints(\n\t\t\tdataStoreContext.connected,\n\t\t\tsubmitFn,\n\t\t\t() => dirtyFn(this.id),\n\t\t\taddedGCOutboundReferenceFn,\n\t\t\t() => runtime.attachState !== AttachState.Detached,\n\t\t\tstorageService,\n\t\t\tthis.subLogger,\n\t\t\tbaseSnapshot,\n\t\t\textraBlobs,\n\t\t);\n\n\t\tthis.channelP = new LazyPromise<IChannel>(async () => {\n\t\t\tconst { attributes, factory } = await loadChannelFactoryAndAttributes(\n\t\t\t\tdataStoreContext,\n\t\t\t\tthis.services,\n\t\t\t\tthis.id,\n\t\t\t\tregistry,\n\t\t\t\tattachMessageType,\n\t\t\t);\n\n\t\t\tconst channel = await loadChannel(\n\t\t\t\truntime,\n\t\t\t\tattributes,\n\t\t\t\tfactory,\n\t\t\t\tthis.services,\n\t\t\t\tthis.subLogger,\n\t\t\t\tthis.id,\n\t\t\t);\n\n\t\t\t// Send all pending messages to the channel\n\t\t\tassert(this.pending !== undefined, 0x23f /* \"pending undefined\" */);\n\t\t\tfor (const message of this.pending) {\n\t\t\t\tthis.services.deltaConnection.process(\n\t\t\t\t\tmessage,\n\t\t\t\t\tfalse,\n\t\t\t\t\tundefined /* localOpMetadata */,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.thresholdOpsCounter.send(\"ProcessPendingOps\", this.pending.length);\n\n\t\t\t// Commit changes.\n\t\t\tthis.channel = channel;\n\t\t\tthis.pending = undefined;\n\t\t\tthis.isLoaded = true;\n\n\t\t\t// Because have some await between we created the service and here, the connection state might have changed\n\t\t\t// and we don't propagate the connection state when we are not loaded. So we have to set it again here.\n\t\t\tthis.services.deltaConnection.setConnectionState(dataStoreContext.connected);\n\t\t\treturn this.channel;\n\t\t});\n\n\t\tconst thisSummarizeInternal = async (\n\t\t\tfullTree: boolean,\n\t\t\ttrackState: boolean,\n\t\t\ttelemetryContext?: ITelemetryContext,\n\t\t\tincrementalSummaryContext?: IExperimentalIncrementalSummaryContext,\n\t\t) =>\n\t\t\tthis.summarizeInternal(\n\t\t\t\tfullTree,\n\t\t\t\ttrackState,\n\t\t\t\ttelemetryContext,\n\t\t\t\tincrementalSummaryContext,\n\t\t\t);\n\n\t\tthis.summarizerNode = createSummarizerNode(\n\t\t\tthisSummarizeInternal,\n\t\t\tasync (fullGC?: boolean) => this.getGCDataInternal(fullGC),\n\t\t);\n\n\t\tthis.thresholdOpsCounter = new ThresholdCounter(\n\t\t\tRemoteChannelContext.pendingOpsCountThreshold,\n\t\t\tthis.subLogger,\n\t\t);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\tpublic getChannel(): Promise<IChannel> {\n\t\treturn this.channelP;\n\t}\n\n\tpublic setConnectionState(connected: boolean, clientId?: string) {\n\t\t// Connection events are ignored if the data store is not yet loaded\n\t\tif (!this.isLoaded) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.services.deltaConnection.setConnectionState(connected);\n\t}\n\n\tpublic applyStashedOp(content: any): unknown {\n\t\tassert(this.isLoaded, 0x194 /* \"Remote channel must be loaded when rebasing op\" */);\n\t\treturn this.services.deltaConnection.applyStashedOp(content);\n\t}\n\n\tpublic processOp(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t): void {\n\t\tthis.summarizerNode.invalidate(message.sequenceNumber);\n\n\t\tif (this.isLoaded) {\n\t\t\tthis.services.deltaConnection.process(message, local, localOpMetadata);\n\t\t} else {\n\t\t\tassert(!local, 0x195 /* \"Remote channel must not be local when processing op\" */);\n\t\t\tassert(this.pending !== undefined, 0x23e /* \"pending is undefined\" */);\n\t\t\tthis.pending.push(message);\n\t\t\tthis.thresholdOpsCounter.sendIfMultiple(\"StorePendingOps\", this.pending.length);\n\t\t}\n\t}\n\n\tpublic reSubmit(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x196 /* \"Remote channel must be loaded when resubmitting op\" */);\n\n\t\tthis.services.deltaConnection.reSubmit(content, localOpMetadata);\n\t}\n\n\tpublic rollback(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x2f0 /* \"Remote channel must be loaded when rolling back op\" */);\n\n\t\tthis.services.deltaConnection.rollback(content, localOpMetadata);\n\t}\n\n\t/**\n\t * Returns a summary at the current sequence number.\n\t * @param fullTree - true to bypass optimizations and force a full summary tree\n\t * @param trackState - This tells whether we should track state from this summary.\n\t * @param telemetryContext - summary data passed through the layers for telemetry purposes\n\t */\n\tpublic async summarize(\n\t\tfullTree: boolean = false,\n\t\ttrackState: boolean = true,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<ISummarizeResult> {\n\t\treturn this.summarizerNode.summarize(fullTree, trackState, telemetryContext);\n\t}\n\n\tprivate async summarizeInternal(\n\t\tfullTree: boolean,\n\t\ttrackState: boolean,\n\t\ttelemetryContext?: ITelemetryContext,\n\t\tincrementalSummaryContext?: IExperimentalIncrementalSummaryContext,\n\t): Promise<ISummarizeInternalResult> {\n\t\tconst channel = await this.getChannel();\n\t\tconst summarizeResult = await summarizeChannelAsync(\n\t\t\tchannel,\n\t\t\tfullTree,\n\t\t\ttrackState,\n\t\t\ttelemetryContext,\n\t\t\tincrementalSummaryContext,\n\t\t);\n\t\treturn { ...summarizeResult, id: this.id };\n\t}\n\n\t/**\n\t * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.\n\t * Each node has a set of outbound routes to other GC nodes in the document.\n\t * If there is no new data in this context since the last summary, previous GC data is used.\n\t * If there is new data, the GC data is generated again (by calling getGCDataInternal).\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tpublic async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\treturn this.summarizerNode.getGCData(fullGC);\n\t}\n\n\t/**\n\t * Generates the data used for garbage collection. This is called when there is new data since last summary. It\n\t * loads the context and calls into the channel to get its GC data.\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tprivate async getGCDataInternal(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\tconst channel = await this.getChannel();\n\t\treturn channel.getGCData(fullGC);\n\t}\n\n\tpublic updateUsedRoutes(usedRoutes: string[]) {\n\t\t/**\n\t\t * Currently, DDSes are always considered referenced and are not garbage collected. Update the summarizer node's\n\t\t * used routes to contain a route to this channel context.\n\t\t * Once we have GC at DDS level, this will be updated to use the passed usedRoutes. See -\n\t\t * https://github.com/microsoft/FluidFramework/issues/4611\n\t\t */\n\t\tthis.summarizerNode.updateUsedRoutes([\"\"]);\n\t}\n}\n"]}
@@ -0,0 +1,70 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "assert";
6
+ import { stringToBuffer } from "@fluid-internal/client-utils";
7
+ import { MockLogger } from "@fluidframework/telemetry-utils";
8
+ import { ChannelStorageService } from "../channelStorageService.js";
9
+ describe("ChannelStorageService", () => {
10
+ it("Empty Tree", async () => {
11
+ const tree = {
12
+ blobs: {},
13
+ trees: {},
14
+ };
15
+ const storage = {
16
+ readBlob: async (id) => {
17
+ throw new Error("not implemented");
18
+ },
19
+ };
20
+ const logger = new MockLogger();
21
+ const ss = new ChannelStorageService(tree, storage, logger.toTelemetryLogger());
22
+ assert.strictEqual(await ss.contains("/"), false);
23
+ assert.deepStrictEqual(await ss.list(""), []);
24
+ logger.assertMatchNone([{ category: "error" }]);
25
+ });
26
+ it("Top Level Blob", async () => {
27
+ const tree = {
28
+ blobs: {
29
+ foo: "bar",
30
+ },
31
+ trees: {},
32
+ };
33
+ const storage = {
34
+ readBlob: async (id) => {
35
+ return stringToBuffer(id, "utf8");
36
+ },
37
+ };
38
+ const logger = new MockLogger();
39
+ const ss = new ChannelStorageService(tree, storage, logger.toTelemetryLogger());
40
+ assert.strictEqual(await ss.contains("foo"), true);
41
+ assert.deepStrictEqual(await ss.list(""), ["foo"]);
42
+ assert.deepStrictEqual(await ss.readBlob("foo"), stringToBuffer("bar", "utf8"));
43
+ logger.assertMatchNone([{ category: "error" }]);
44
+ });
45
+ it("Nested Blob", async () => {
46
+ const tree = {
47
+ blobs: {},
48
+ trees: {
49
+ nested: {
50
+ blobs: {
51
+ foo: "bar",
52
+ },
53
+ trees: {},
54
+ },
55
+ },
56
+ };
57
+ const storage = {
58
+ readBlob: async (id) => {
59
+ return stringToBuffer(id, "utf8");
60
+ },
61
+ };
62
+ const logger = new MockLogger();
63
+ const ss = new ChannelStorageService(tree, storage, logger.toTelemetryLogger());
64
+ assert.strictEqual(await ss.contains("nested/foo"), true);
65
+ assert.deepStrictEqual(await ss.list("nested/"), ["foo"]);
66
+ assert.deepStrictEqual(await ss.readBlob("nested/foo"), stringToBuffer("bar", "utf8"));
67
+ logger.assertMatchNone([{ category: "error" }]);
68
+ });
69
+ });
70
+ //# sourceMappingURL=channelStorageService.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channelStorageService.spec.js","sourceRoot":"","sources":["../../src/test/channelStorageService.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { MockLogger } from \"@fluidframework/telemetry-utils\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { ChannelStorageService } from \"../channelStorageService.js\";\n\ndescribe(\"ChannelStorageService\", () => {\n\tit(\"Empty Tree\", async () => {\n\t\tconst tree: ISnapshotTree = {\n\t\t\tblobs: {},\n\t\t\ttrees: {},\n\t\t};\n\t\tconst storage: Pick<IDocumentStorageService, \"readBlob\"> = {\n\t\t\treadBlob: async (id: string) => {\n\t\t\t\tthrow new Error(\"not implemented\");\n\t\t\t},\n\t\t};\n\t\tconst logger = new MockLogger();\n\t\tconst ss = new ChannelStorageService(tree, storage, logger.toTelemetryLogger());\n\n\t\tassert.strictEqual(await ss.contains(\"/\"), false);\n\t\tassert.deepStrictEqual(await ss.list(\"\"), []);\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t});\n\n\tit(\"Top Level Blob\", async () => {\n\t\tconst tree: ISnapshotTree = {\n\t\t\tblobs: {\n\t\t\t\tfoo: \"bar\",\n\t\t\t},\n\t\t\ttrees: {},\n\t\t};\n\t\tconst storage: Pick<IDocumentStorageService, \"readBlob\"> = {\n\t\t\treadBlob: async (id: string) => {\n\t\t\t\treturn stringToBuffer(id, \"utf8\");\n\t\t\t},\n\t\t};\n\t\tconst logger = new MockLogger();\n\t\tconst ss = new ChannelStorageService(tree, storage, logger.toTelemetryLogger());\n\n\t\tassert.strictEqual(await ss.contains(\"foo\"), true);\n\t\tassert.deepStrictEqual(await ss.list(\"\"), [\"foo\"]);\n\t\tassert.deepStrictEqual(await ss.readBlob(\"foo\"), stringToBuffer(\"bar\", \"utf8\"));\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t});\n\n\tit(\"Nested Blob\", async () => {\n\t\tconst tree: ISnapshotTree = {\n\t\t\tblobs: {},\n\t\t\ttrees: {\n\t\t\t\tnested: {\n\t\t\t\t\tblobs: {\n\t\t\t\t\t\tfoo: \"bar\",\n\t\t\t\t\t},\n\t\t\t\t\ttrees: {},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tconst storage: Pick<IDocumentStorageService, \"readBlob\"> = {\n\t\t\treadBlob: async (id: string) => {\n\t\t\t\treturn stringToBuffer(id, \"utf8\");\n\t\t\t},\n\t\t};\n\t\tconst logger = new MockLogger();\n\t\tconst ss = new ChannelStorageService(tree, storage, logger.toTelemetryLogger());\n\n\t\tassert.strictEqual(await ss.contains(\"nested/foo\"), true);\n\t\tassert.deepStrictEqual(await ss.list(\"nested/\"), [\"foo\"]);\n\t\tassert.deepStrictEqual(await ss.readBlob(\"nested/foo\"), stringToBuffer(\"bar\", \"utf8\"));\n\t\tlogger.assertMatchNone([{ category: \"error\" }]);\n\t});\n});\n"]}
@@ -0,0 +1,121 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "assert";
6
+ import { SummaryType } from "@fluidframework/protocol-definitions";
7
+ import { MockFluidDataStoreContext, validateAssertionError, } from "@fluidframework/test-runtime-utils";
8
+ import { ContainerErrorTypes } from "@fluidframework/container-definitions";
9
+ import { FluidDataStoreRuntime } from "../dataStoreRuntime.js";
10
+ describe("FluidDataStoreRuntime Tests", () => {
11
+ let dataStoreContext;
12
+ let sharedObjectRegistry;
13
+ function createRuntime(context, registry, entrypointInitializationFn) {
14
+ const runtime = new FluidDataStoreRuntime(context, registry,
15
+ /* existing */ false, entrypointInitializationFn ?? (async () => runtime));
16
+ return runtime;
17
+ }
18
+ beforeEach(() => {
19
+ dataStoreContext = new MockFluidDataStoreContext();
20
+ // back-compat 0.38 - DataStoreRuntime looks in container runtime for certain properties that are unavailable
21
+ // in the data store context.
22
+ dataStoreContext.containerRuntime = {};
23
+ sharedObjectRegistry = {
24
+ get(type) {
25
+ return {
26
+ type,
27
+ attributes: { type, snapshotFormatVersion: "0" },
28
+ create: (runtime, id) => ({
29
+ id,
30
+ type,
31
+ attributes: { type, snapshotFormatVersion: "0" },
32
+ clientDetails: {},
33
+ }),
34
+ load: async () => Promise.resolve({}),
35
+ };
36
+ },
37
+ };
38
+ });
39
+ it("constructor rejects ids with forward slashes", () => {
40
+ const invalidId = "beforeSlash/afterSlash";
41
+ dataStoreContext = new MockFluidDataStoreContext(invalidId);
42
+ const codeBlock = () => new FluidDataStoreRuntime(dataStoreContext, sharedObjectRegistry, false, async (dataStoreRuntime) => {
43
+ throw new Error("This shouldn't be called during the test");
44
+ });
45
+ assert.throws(codeBlock, (e) => validateAssertionError(e, "Id cannot contain slashes. DataStoreContext should have validated this."));
46
+ });
47
+ it("can create a data store runtime", () => {
48
+ let failed = false;
49
+ let dataStoreRuntime;
50
+ try {
51
+ dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);
52
+ }
53
+ catch (error) {
54
+ failed = true;
55
+ }
56
+ assert.strictEqual(failed, false, "Data store runtime creation failed");
57
+ assert.strictEqual(dataStoreRuntime?.id, dataStoreContext.id, "Data store runtime's id in incorrect");
58
+ });
59
+ it("can summarize an empty data store runtime", async () => {
60
+ const dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);
61
+ const summarizeResult = await dataStoreRuntime.summarize(true, false);
62
+ assert(summarizeResult.summary.type === SummaryType.Tree, "Data store runtime did not return a summary tree");
63
+ assert(Object.keys(summarizeResult.summary.tree).length === 0, "The summary should be empty");
64
+ });
65
+ it("can get GC data of an empty data store runtime", async () => {
66
+ // The GC data should have a single node for the data store runtime with empty outbound routes.
67
+ const expectedGCData = {
68
+ gcNodes: { "/": [] },
69
+ };
70
+ const dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);
71
+ const gcData = await dataStoreRuntime.getGCData();
72
+ assert.deepStrictEqual(gcData, expectedGCData, "The GC data is incorrect");
73
+ });
74
+ it("createChannel rejects ids with slashes", async () => {
75
+ const dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);
76
+ const invalidId = "beforeSlash/afterSlash";
77
+ const codeBlock = () => dataStoreRuntime.createChannel(invalidId, "SomeType");
78
+ assert.throws(codeBlock, (e) => e.errorType === ContainerErrorTypes.usageError &&
79
+ e.message === `Id cannot contain slashes: ${invalidId}`);
80
+ });
81
+ it("createChannel with default guid", async () => {
82
+ const dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);
83
+ const type = "SomeType";
84
+ const channel = dataStoreRuntime.createChannel(undefined, type);
85
+ assert(channel !== undefined, "channel should be created");
86
+ assert(type === channel.attributes.type, "type should be as expected");
87
+ });
88
+ it("createChannel and then attach to dataStore runtime", async () => {
89
+ const dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);
90
+ const type = "SomeType";
91
+ const channel = {
92
+ id: "id",
93
+ type,
94
+ attributes: { type, snapshotFormatVersion: "0" },
95
+ clientDetails: {},
96
+ };
97
+ dataStoreRuntime.addChannel(channel);
98
+ const channel1 = await dataStoreRuntime.getChannel(channel.id);
99
+ assert.deepStrictEqual(channel, channel1, "both channel should match");
100
+ });
101
+ it("createChannel rejects ids with slashes when channel is created first", async () => {
102
+ const dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);
103
+ const invalidId = "beforeSlash/afterSlash";
104
+ const type = "SomeType";
105
+ const channel = {
106
+ id: invalidId,
107
+ type,
108
+ attributes: { type, snapshotFormatVersion: "0" },
109
+ clientDetails: {},
110
+ };
111
+ const codeBlock = () => dataStoreRuntime.addChannel(channel);
112
+ assert.throws(codeBlock, (e) => e.errorType === ContainerErrorTypes.usageError &&
113
+ e.message === `Id cannot contain slashes: ${invalidId}`);
114
+ });
115
+ it("entryPoint is initialized correctly", async () => {
116
+ const myObj = { fakeProp: "fakeValue" };
117
+ const dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry, async (dsRuntime) => myObj);
118
+ assert((await dataStoreRuntime.entryPoint?.get()) === myObj, "entryPoint was not initialized");
119
+ });
120
+ });
121
+ //# sourceMappingURL=dataStoreRuntime.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataStoreRuntime.spec.js","sourceRoot":"","sources":["../../src/test/dataStoreRuntime.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { SummaryType } from \"@fluidframework/protocol-definitions\";\nimport {\n\tIContainerRuntimeBase,\n\tIGarbageCollectionData,\n\tIFluidDataStoreContext,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n\tMockFluidDataStoreContext,\n\tvalidateAssertionError,\n} from \"@fluidframework/test-runtime-utils\";\nimport { ContainerErrorTypes } from \"@fluidframework/container-definitions\";\nimport { IFluidDataStoreRuntime, IChannel } from \"@fluidframework/datastore-definitions\";\nimport { IErrorBase, FluidObject } from \"@fluidframework/core-interfaces\";\nimport { FluidDataStoreRuntime, ISharedObjectRegistry } from \"../dataStoreRuntime.js\";\n\ndescribe(\"FluidDataStoreRuntime Tests\", () => {\n\tlet dataStoreContext: MockFluidDataStoreContext;\n\tlet sharedObjectRegistry: ISharedObjectRegistry;\n\tfunction createRuntime(\n\t\tcontext: IFluidDataStoreContext,\n\t\tregistry: ISharedObjectRegistry,\n\t\tentrypointInitializationFn?: (rt: IFluidDataStoreRuntime) => Promise<FluidObject>,\n\t) {\n\t\tconst runtime: FluidDataStoreRuntime = new FluidDataStoreRuntime(\n\t\t\tcontext,\n\t\t\tregistry,\n\t\t\t/* existing */ false,\n\t\t\tentrypointInitializationFn ?? (async () => runtime),\n\t\t);\n\t\treturn runtime;\n\t}\n\n\tbeforeEach(() => {\n\t\tdataStoreContext = new MockFluidDataStoreContext();\n\t\t// back-compat 0.38 - DataStoreRuntime looks in container runtime for certain properties that are unavailable\n\t\t// in the data store context.\n\t\tdataStoreContext.containerRuntime = {} as unknown as IContainerRuntimeBase;\n\t\tsharedObjectRegistry = {\n\t\t\tget(type: string) {\n\t\t\t\treturn {\n\t\t\t\t\ttype,\n\t\t\t\t\tattributes: { type, snapshotFormatVersion: \"0\" },\n\t\t\t\t\tcreate: (runtime, id: string) =>\n\t\t\t\t\t\t({\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\tattributes: { type, snapshotFormatVersion: \"0\" },\n\t\t\t\t\t\t\tclientDetails: {},\n\t\t\t\t\t\t}) as any as IChannel,\n\t\t\t\t\tload: async () => Promise.resolve({} as any as IChannel),\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\t});\n\n\tit(\"constructor rejects ids with forward slashes\", () => {\n\t\tconst invalidId = \"beforeSlash/afterSlash\";\n\t\tdataStoreContext = new MockFluidDataStoreContext(invalidId);\n\t\tconst codeBlock = () =>\n\t\t\tnew FluidDataStoreRuntime(\n\t\t\t\tdataStoreContext,\n\t\t\t\tsharedObjectRegistry,\n\t\t\t\tfalse,\n\t\t\t\tasync (dataStoreRuntime) => {\n\t\t\t\t\tthrow new Error(\"This shouldn't be called during the test\");\n\t\t\t\t},\n\t\t\t);\n\t\tassert.throws(codeBlock, (e: Error) =>\n\t\t\tvalidateAssertionError(\n\t\t\t\te,\n\t\t\t\t\"Id cannot contain slashes. DataStoreContext should have validated this.\",\n\t\t\t),\n\t\t);\n\t});\n\n\tit(\"can create a data store runtime\", () => {\n\t\tlet failed: boolean = false;\n\t\tlet dataStoreRuntime: FluidDataStoreRuntime | undefined;\n\t\ttry {\n\t\t\tdataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);\n\t\t} catch (error) {\n\t\t\tfailed = true;\n\t\t}\n\t\tassert.strictEqual(failed, false, \"Data store runtime creation failed\");\n\t\tassert.strictEqual(\n\t\t\tdataStoreRuntime?.id,\n\t\t\tdataStoreContext.id,\n\t\t\t\"Data store runtime's id in incorrect\",\n\t\t);\n\t});\n\n\tit(\"can summarize an empty data store runtime\", async () => {\n\t\tconst dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);\n\t\tconst summarizeResult = await dataStoreRuntime.summarize(true, false);\n\t\tassert(\n\t\t\tsummarizeResult.summary.type === SummaryType.Tree,\n\t\t\t\"Data store runtime did not return a summary tree\",\n\t\t);\n\t\tassert(\n\t\t\tObject.keys(summarizeResult.summary.tree).length === 0,\n\t\t\t\"The summary should be empty\",\n\t\t);\n\t});\n\n\tit(\"can get GC data of an empty data store runtime\", async () => {\n\t\t// The GC data should have a single node for the data store runtime with empty outbound routes.\n\t\tconst expectedGCData: IGarbageCollectionData = {\n\t\t\tgcNodes: { \"/\": [] },\n\t\t};\n\t\tconst dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);\n\t\tconst gcData = await dataStoreRuntime.getGCData();\n\t\tassert.deepStrictEqual(gcData, expectedGCData, \"The GC data is incorrect\");\n\t});\n\n\tit(\"createChannel rejects ids with slashes\", async () => {\n\t\tconst dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);\n\t\tconst invalidId = \"beforeSlash/afterSlash\";\n\t\tconst codeBlock = () => dataStoreRuntime.createChannel(invalidId, \"SomeType\");\n\t\tassert.throws(\n\t\t\tcodeBlock,\n\t\t\t(e: IErrorBase) =>\n\t\t\t\te.errorType === ContainerErrorTypes.usageError &&\n\t\t\t\te.message === `Id cannot contain slashes: ${invalidId}`,\n\t\t);\n\t});\n\n\tit(\"createChannel with default guid\", async () => {\n\t\tconst dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);\n\t\tconst type = \"SomeType\";\n\t\tconst channel = dataStoreRuntime.createChannel(undefined, type);\n\t\tassert(channel !== undefined, \"channel should be created\");\n\t\tassert(type === channel.attributes.type, \"type should be as expected\");\n\t});\n\n\tit(\"createChannel and then attach to dataStore runtime\", async () => {\n\t\tconst dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);\n\t\tconst type = \"SomeType\";\n\t\tconst channel = {\n\t\t\tid: \"id\",\n\t\t\ttype,\n\t\t\tattributes: { type, snapshotFormatVersion: \"0\" },\n\t\t\tclientDetails: {},\n\t\t} as any as IChannel;\n\t\tdataStoreRuntime.addChannel(channel);\n\t\tconst channel1 = await dataStoreRuntime.getChannel(channel.id);\n\t\tassert.deepStrictEqual(channel, channel1, \"both channel should match\");\n\t});\n\n\tit(\"createChannel rejects ids with slashes when channel is created first\", async () => {\n\t\tconst dataStoreRuntime = createRuntime(dataStoreContext, sharedObjectRegistry);\n\t\tconst invalidId = \"beforeSlash/afterSlash\";\n\t\tconst type = \"SomeType\";\n\t\tconst channel = {\n\t\t\tid: invalidId,\n\t\t\ttype,\n\t\t\tattributes: { type, snapshotFormatVersion: \"0\" },\n\t\t\tclientDetails: {},\n\t\t} as any as IChannel;\n\t\tconst codeBlock = () => dataStoreRuntime.addChannel(channel);\n\t\tassert.throws(\n\t\t\tcodeBlock,\n\t\t\t(e: IErrorBase) =>\n\t\t\t\te.errorType === ContainerErrorTypes.usageError &&\n\t\t\t\te.message === `Id cannot contain slashes: ${invalidId}`,\n\t\t);\n\t});\n\n\tit(\"entryPoint is initialized correctly\", async () => {\n\t\tconst myObj: FluidObject = { fakeProp: \"fakeValue\" };\n\t\tconst dataStoreRuntime = createRuntime(\n\t\t\tdataStoreContext,\n\t\t\tsharedObjectRegistry,\n\t\t\tasync (dsRuntime) => myObj,\n\t\t);\n\t\tassert(\n\t\t\t(await dataStoreRuntime.entryPoint?.get()) === myObj,\n\t\t\t\"entryPoint was not initialized\",\n\t\t);\n\t});\n});\n"]}
@@ -0,0 +1,41 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "assert";
6
+ import { MockFluidDataStoreContext, validateAssertionError, } from "@fluidframework/test-runtime-utils";
7
+ import { FluidDataStoreRuntime } from "../dataStoreRuntime.js";
8
+ import { LocalChannelContext, RehydratedLocalChannelContext } from "../localChannelContext.js";
9
+ describe("LocalChannelContext Tests", () => {
10
+ let dataStoreContext;
11
+ let sharedObjectRegistry;
12
+ const loadRuntime = (context, registry) => new FluidDataStoreRuntime(context, registry, /* existing */ false, async () => ({
13
+ myProp: "myValue",
14
+ }));
15
+ beforeEach(() => {
16
+ dataStoreContext = new MockFluidDataStoreContext();
17
+ sharedObjectRegistry = {
18
+ get(type) {
19
+ return {
20
+ type,
21
+ attributes: { type, snapshotFormatVersion: "0" },
22
+ create: () => ({}),
23
+ load: async () => Promise.resolve({}),
24
+ };
25
+ },
26
+ };
27
+ });
28
+ it("LocalChannelContext rejects ids with forward slashes", () => {
29
+ const invalidId = "beforeSlash/afterSlash";
30
+ const dataStoreRuntime = loadRuntime(dataStoreContext, sharedObjectRegistry);
31
+ const codeBlock = () => new LocalChannelContext({ id: invalidId }, dataStoreRuntime, dataStoreContext, dataStoreContext.storage, dataStoreContext.logger, () => { }, (s) => { }, (s) => { });
32
+ assert.throws(codeBlock, (e) => validateAssertionError(e, "Channel context ID cannot contain slashes"), "Expected exception was not thrown");
33
+ });
34
+ it("RehydratedLocalChannelContext rejects ids with forward slashes", () => {
35
+ const invalidId = "beforeSlash/afterSlash";
36
+ const dataStoreRuntime = loadRuntime(dataStoreContext, sharedObjectRegistry);
37
+ const codeBlock = () => new RehydratedLocalChannelContext(invalidId, sharedObjectRegistry, dataStoreRuntime, dataStoreContext, dataStoreContext.storage, dataStoreContext.logger, (content, localOpMetadata) => { }, (s) => { }, (s, o) => { }, null);
38
+ assert.throws(codeBlock, (e) => validateAssertionError(e, "Channel context ID cannot contain slashes"), "Expected exception was not thrown");
39
+ });
40
+ });
41
+ //# sourceMappingURL=localChannelContext.spec.js.map