@fluidframework/container-loader 2.117.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -2
- package/README.md +53 -50
- package/{api-extractor.json → api-extractor/api-extractor-model.json} +1 -1
- package/api-report/container-loader.legacy.alpha.api.md +4 -3
- package/dist/attachment.d.ts.map +1 -1
- package/dist/audience.js +3 -2
- package/dist/audience.js.map +1 -1
- package/dist/captureReferencedContents.js +9 -9
- package/dist/captureReferencedContents.js.map +1 -1
- package/dist/catchUpMonitor.js +11 -8
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +86 -51
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.js +40 -14
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +1 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +193 -143
- package/dist/container.js.map +1 -1
- package/dist/containerContext.js +48 -11
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.js +25 -17
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/createAndLoadContainerUtils.d.ts +34 -13
- package/dist/createAndLoadContainerUtils.d.ts.map +1 -1
- package/dist/createAndLoadContainerUtils.js +97 -37
- package/dist/createAndLoadContainerUtils.js.map +1 -1
- package/dist/debugLogger.d.ts +7 -22
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js +34 -34
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +16 -4
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +75 -49
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaManagerFactory.d.ts +23 -0
- package/dist/deltaManagerFactory.d.ts.map +1 -0
- package/dist/deltaManagerFactory.js +17 -0
- package/dist/deltaManagerFactory.js.map +1 -0
- package/dist/deltaQueue.js +14 -7
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.js +1 -2
- package/dist/disposal.js.map +1 -1
- package/dist/error.js +5 -4
- package/dist/error.js.map +1 -1
- package/dist/frozenServices.d.ts +2 -2
- package/dist/frozenServices.d.ts.map +1 -1
- package/dist/frozenServices.js +52 -34
- package/dist/frozenServices.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/loadContainerToSequenceNumber.d.ts +6 -5
- package/dist/loadContainerToSequenceNumber.d.ts.map +1 -1
- package/dist/loadContainerToSequenceNumber.js +5 -6
- package/dist/loadContainerToSequenceNumber.js.map +1 -1
- package/dist/loadPaused.js +1 -2
- package/dist/loadPaused.js.map +1 -1
- package/dist/loader.js +5 -1
- package/dist/loader.js.map +1 -1
- package/dist/loaderLayerCompatState.d.ts +25 -1
- package/dist/loaderLayerCompatState.d.ts.map +1 -1
- package/dist/loaderLayerCompatState.js +79 -11
- package/dist/loaderLayerCompatState.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +2 -3
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/dist/memoryBlobStorage.js +2 -3
- package/dist/memoryBlobStorage.js.map +1 -1
- package/dist/noopHeuristic.js +3 -1
- package/dist/noopHeuristic.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingLocalStateStore.d.ts +4 -3
- package/dist/pendingLocalStateStore.d.ts.map +1 -1
- package/dist/pendingLocalStateStore.js +26 -37
- package/dist/pendingLocalStateStore.js.map +1 -1
- package/dist/pointInTimeServices.js +4 -2
- package/dist/pointInTimeServices.js.map +1 -1
- package/dist/protocol/protocol.js +3 -0
- package/dist/protocol/protocol.js.map +1 -1
- package/dist/protocol/quorum.js +26 -5
- package/dist/protocol/quorum.js.map +1 -1
- package/dist/protocol.js +5 -3
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js +10 -0
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.js +1 -2
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +5 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +6 -0
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +19 -24
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/snapshotRefresher.js +31 -36
- package/dist/snapshotRefresher.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +13 -13
- package/dist/utils.js.map +1 -1
- package/lib/attachment.d.ts.map +1 -1
- package/lib/audience.js +3 -2
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.js +11 -8
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +86 -51
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.js +37 -11
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +1 -1
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +191 -141
- package/lib/container.js.map +1 -1
- package/lib/containerContext.js +48 -11
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.js +22 -14
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts.map +1 -1
- package/lib/createAndLoadContainerUtils.d.ts +34 -13
- package/lib/createAndLoadContainerUtils.d.ts.map +1 -1
- package/lib/createAndLoadContainerUtils.js +93 -32
- package/lib/createAndLoadContainerUtils.js.map +1 -1
- package/lib/debugLogger.d.ts +7 -22
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js +34 -33
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +16 -4
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +75 -49
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaManagerFactory.d.ts +23 -0
- package/lib/deltaManagerFactory.d.ts.map +1 -0
- package/lib/deltaManagerFactory.js +14 -0
- package/lib/deltaManagerFactory.js.map +1 -0
- package/lib/deltaQueue.js +14 -7
- package/lib/deltaQueue.js.map +1 -1
- package/lib/error.js +5 -4
- package/lib/error.js.map +1 -1
- package/lib/frozenServices.d.ts +2 -2
- package/lib/frozenServices.d.ts.map +1 -1
- package/lib/frozenServices.js +48 -30
- package/lib/frozenServices.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +1 -1
- package/lib/legacyAlpha.d.ts +1 -1
- package/lib/loadContainerToSequenceNumber.d.ts +6 -5
- package/lib/loadContainerToSequenceNumber.d.ts.map +1 -1
- package/lib/loadContainerToSequenceNumber.js +4 -4
- package/lib/loadContainerToSequenceNumber.js.map +1 -1
- package/lib/loader.js +6 -2
- package/lib/loader.js.map +1 -1
- package/lib/loaderLayerCompatState.d.ts +25 -1
- package/lib/loaderLayerCompatState.d.ts.map +1 -1
- package/lib/loaderLayerCompatState.js +76 -9
- package/lib/loaderLayerCompatState.js.map +1 -1
- package/lib/noopHeuristic.js +3 -1
- package/lib/noopHeuristic.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingLocalStateStore.d.ts +4 -3
- package/lib/pendingLocalStateStore.d.ts.map +1 -1
- package/lib/pendingLocalStateStore.js +26 -37
- package/lib/pendingLocalStateStore.js.map +1 -1
- package/lib/pointInTimeServices.js +2 -0
- package/lib/pointInTimeServices.js.map +1 -1
- package/lib/protocol/protocol.js +3 -0
- package/lib/protocol/protocol.js.map +1 -1
- package/lib/protocol/quorum.js +26 -5
- package/lib/protocol/quorum.js.map +1 -1
- package/lib/protocol.js +2 -0
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js +10 -0
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +5 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +6 -0
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +15 -20
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/snapshotRefresher.js +31 -36
- package/lib/snapshotRefresher.js.map +1 -1
- package/lib/utils.d.ts +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +3 -3
- package/lib/utils.js.map +1 -1
- package/package.json +44 -106
- package/src/container.ts +35 -22
- package/src/createAndLoadContainerUtils.ts +131 -46
- package/src/debugLogger.ts +39 -40
- package/src/deltaManager.ts +18 -5
- package/src/deltaManagerFactory.ts +53 -0
- package/src/frozenServices.ts +6 -7
- package/src/index.ts +1 -0
- package/src/loadContainerToSequenceNumber.ts +7 -6
- package/src/loader.ts +2 -2
- package/src/loaderLayerCompatState.ts +85 -20
- package/src/packageVersion.ts +1 -1
- package/src/pendingLocalStateStore.ts +7 -3
- package/src/pointInTime/DEV.md +47 -4
- package/src/serializedStateManager.ts +6 -0
- package/src/utils.ts +3 -3
- package/tsconfig.json +1 -1
- package/internal.d.ts +0 -11
- package/legacy/alpha.d.ts +0 -11
- package/legacy.d.ts +0 -11
- /package/api-extractor/{api-extractor.current.json → api-extractor-report.current.json} +0 -0
- /package/api-extractor/{api-extractor.legacy.json → api-extractor-report.legacy.json} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,82 @@
|
|
|
1
1
|
# @fluidframework/container-loader
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 3.0.0
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Removal of direct CommonJS support ([#28124](https://github.com/microsoft/FluidFramework/pull/28124)) [0f84e3b8878](https://github.com/microsoft/FluidFramework/commit/0f84e3b8878a5e75b2253976d98fd963bbd9db88)
|
|
8
|
+
|
|
9
|
+
Direct `require()` import is no longer directly supported.
|
|
10
|
+
Package is transpiled as ECMAScript Module.
|
|
11
|
+
|
|
12
|
+
See [Removal of direct CommonJS support in v3.0](https://github.com/microsoft/FluidFramework/issues/27444) for more information.
|
|
13
|
+
|
|
14
|
+
- Full container state capture now includes recently sequenced operations ([#28009](https://github.com/microsoft/FluidFramework/pull/28009)) [6a2354f2146](https://github.com/microsoft/FluidFramework/commit/6a2354f2146440e6cbb8121957c4558cb47f6d5b)
|
|
15
|
+
|
|
16
|
+
`captureFullContainerState` now connects to the delta stream and catches up through the latest operation known when the connection is established.
|
|
17
|
+
This prevents captured state from omitting operations that have been broadcast over the websocket but have not yet reached delta storage.
|
|
18
|
+
|
|
19
|
+
- Require modern TypeScript module resolution ([#27970](https://github.com/microsoft/FluidFramework/pull/27970)) [325e2016ca9](https://github.com/microsoft/FluidFramework/commit/325e2016ca9978d4a1f7552c97ba34feac9df41f)
|
|
20
|
+
|
|
21
|
+
Fluid Framework Client packages no longer include type declaration compatibility entrypoints for TypeScript's legacy Node10 resolution mode (`"moduleResolution": "node"` or `"node10"`).
|
|
22
|
+
Applications upgrading to Fluid Framework 3.0 must use one of the following supported configurations:
|
|
23
|
+
- `"module": "Node16"` with `"moduleResolution": "Node16"`
|
|
24
|
+
- `"module": "NodeNext"` with `"moduleResolution": "NodeNext"`
|
|
25
|
+
- `"module": "ESNext"` with `"moduleResolution": "Bundler"`
|
|
26
|
+
|
|
27
|
+
Existing public package entrypoints exposed through `package.json` exports, including `/alpha`, `/beta`, and `/legacy`, remain available under supported module resolution modes.
|
|
28
|
+
|
|
29
|
+
See [Removal of Node10 resolutions in v3.0](https://github.com/microsoft/FluidFramework/issues/27457) for more information.
|
|
30
|
+
|
|
31
|
+
- Add reference-only capture for reusable container baselines ([#28006](https://github.com/microsoft/FluidFramework/pull/28006)) [4374770404e](https://github.com/microsoft/FluidFramework/commit/4374770404ee485456abc128c3266f24f25251c3)
|
|
32
|
+
|
|
33
|
+
[`captureFullContainerState`](https://fluidframework.com/docs/api/container-loader/#capturefullcontainerstate-function) now accepts a `blobCaptureMode` option. The default `"inline"` mode remains self-contained, while `"reference"` omits structural and attachment blob payloads so repeated online loads can fetch them from live storage.
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
const baseline = await captureFullContainerState({
|
|
37
|
+
urlResolver,
|
|
38
|
+
documentServiceFactory,
|
|
39
|
+
request,
|
|
40
|
+
blobCaptureMode: "reference",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const container = await loadExistingContainer({
|
|
44
|
+
...loaderProps,
|
|
45
|
+
request,
|
|
46
|
+
pendingLocalState: baseline,
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- Client packages now target ES2022 ([#27846](https://github.com/microsoft/FluidFramework/pull/27846)) [91c78541bdd](https://github.com/microsoft/FluidFramework/commit/91c78541bddcbca5d6c5f357b023eeaee617d885)
|
|
51
|
+
|
|
52
|
+
The TypeScript compilation `target` and `lib` for the Fluid Framework client packages have been raised from ES2021/ES2020 to **ES2022**.
|
|
53
|
+
The published JavaScript now uses ES2022 language features (with correspondingly less down-leveling), so consuming these packages requires a runtime that supports ES2022.
|
|
54
|
+
All actively supported Node.js versions and evergreen browsers already meet this requirement.
|
|
55
|
+
|
|
56
|
+
Note that Fluid Framework has not officially supported targets older than ES2022 since before 2.0: this is documented in [ClientRequirements.md](https://github.com/microsoft/FluidFramework/blob/main/ClientRequirements.md) as well as the README for every client package.
|
|
57
|
+
|
|
58
|
+
It is possible this change could impact users of less up to date JavaScript runtimes.
|
|
59
|
+
Impacted users can use a tool like [babel](https://babeljs.io/) to transpile out unsupported language features.
|
|
60
|
+
|
|
61
|
+
- Pending local state uses Fluid-owned iterator types ([#27908](https://github.com/microsoft/FluidFramework/pull/27908)) [5035f7cfed4](https://github.com/microsoft/FluidFramework/commit/5035f7cfed4dedec8ded17b29be97f91f2a4b675)
|
|
62
|
+
|
|
63
|
+
[`PendingLocalStateStore`](https://fluidframework.com/docs/api/container-loader/pendinglocalstatestore-class) iteration methods now return [`FluidIterableIterator`](https://fluidframework.com/docs/api/core-interfaces/fluiditerableiterator-interface) instead of TypeScript's built-in iterator types.
|
|
64
|
+
This prevents changes to TypeScript's standard iterator interfaces from affecting the container loader API.
|
|
65
|
+
|
|
66
|
+
#### Migration
|
|
67
|
+
|
|
68
|
+
The returned iterators continue to support `next()`, spreading, and `for...of`.
|
|
69
|
+
Methods available only on newer built-in iterator types are not available.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
for (const [key, pendingState] of pendingLocalStateStore.entries()) {
|
|
73
|
+
// ...
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- Build with TypeScript 6 ([#28052](https://github.com/microsoft/FluidFramework/pull/28052)) [7ab015c49de](https://github.com/microsoft/FluidFramework/commit/7ab015c49deec84833cdfe1fb5e1606b901f6e81)
|
|
78
|
+
|
|
79
|
+
FluidFramework Client SDK is now built using TypeScript 6. Consumers should build with TypeScript v6 or v7 or compatible tooling.
|
|
6
80
|
|
|
7
81
|
## 2.116.0
|
|
8
82
|
|
package/README.md
CHANGED
|
@@ -47,15 +47,15 @@
|
|
|
47
47
|
|
|
48
48
|
## Using Fluid Framework libraries
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
library consumers should always prefer `^`.
|
|
50
|
+
For a dependency on a Fluid Framework library's public APIs, we recommend a `^` (caret) version range.
|
|
51
|
+
For example, use `^1.3.4`.
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
For a dependency on an unstable API, such as a `beta` API, we recommend a more restrictive version range.
|
|
54
|
+
For example, use a `~` version range.
|
|
55
55
|
|
|
56
56
|
## Installation
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Run this command to install the package:
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
61
|
npm i @fluidframework/container-loader
|
|
@@ -63,16 +63,16 @@ npm i @fluidframework/container-loader
|
|
|
63
63
|
|
|
64
64
|
## Importing from this package
|
|
65
65
|
|
|
66
|
-
This package
|
|
67
|
-
For
|
|
66
|
+
This package uses [package.json exports](https://nodejs.org/api/packages.html#exports) to separate APIs by support level.
|
|
67
|
+
For information about the support guarantees, read [API Support Levels](https://fluidframework.com/docs/build/releases-and-apitags/#api-support-levels).
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Import the `public` APIs from `@fluidframework/container-loader`.
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
Import the `legacy` APIs from `@fluidframework/container-loader/legacy`.
|
|
72
72
|
|
|
73
73
|
## API Documentation
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
Read the **@fluidframework/container-loader** API documentation at <https://fluidframework.com/docs/apis/container-loader>.
|
|
76
76
|
|
|
77
77
|
<!-- prettier-ignore-end -->
|
|
78
78
|
|
|
@@ -302,62 +302,69 @@ Note that when an active connection is in place, it's just a matter of time befo
|
|
|
302
302
|
|
|
303
303
|
## Minimum Client Requirements
|
|
304
304
|
|
|
305
|
-
|
|
306
|
-
These requirements
|
|
307
|
-
|
|
305
|
+
Fluid Framework client libraries support the platforms in this document.
|
|
306
|
+
These requirements are intentionally restrictive.
|
|
307
|
+
Within a major version series, we can relax these requirements, but we cannot make them stricter.
|
|
308
|
+
For a Long Term Support (LTS) version, we might need to support these platforms for several years.
|
|
308
309
|
|
|
309
|
-
|
|
310
|
-
If
|
|
311
|
-
|
|
310
|
+
Other configurations can work, but Fluid Framework does not support them.
|
|
311
|
+
If an unsupported configuration stops working, we do not classify this as a bug.
|
|
312
|
+
To request support for a configuration that is not listed, file an issue.
|
|
313
|
+
The product team will evaluate your request.
|
|
314
|
+
In the issue, specify the current status of the configuration:
|
|
315
|
+
|
|
316
|
+
- The configuration works but needs official support.
|
|
317
|
+
- The configuration does not work and requires changes.
|
|
312
318
|
|
|
313
319
|
### Supported Runtimes
|
|
314
320
|
|
|
315
|
-
-
|
|
316
|
-
-
|
|
317
|
-
-
|
|
321
|
+
- Fluid Framework supports Node.js versions 22 and 24 while they receive [upstream support](https://nodejs.org/en/about/previous-releases).
|
|
322
|
+
- Fluid Framework will stop support for version 22 [when upstream support ends on 2027-04-30](https://github.com/nodejs/release#release-schedule).
|
|
323
|
+
- Fluid Framework does not support Node.js with the `--no-experimental-fetch` flag.
|
|
324
|
+
- Fluid Framework supports modern browsers that support the ES2022 standard library.
|
|
318
325
|
|
|
319
326
|
### Supported Tools
|
|
320
327
|
|
|
321
|
-
- TypeScript
|
|
322
|
-
-
|
|
323
|
-
-
|
|
324
|
-
- [
|
|
325
|
-
-
|
|
326
|
-
|
|
328
|
+
- [TypeScript 6.0](https://typescriptdocs.com/release-notes/TypeScript%206.0):
|
|
329
|
+
- Fluid Framework supports all [`strict`](https://www.typescriptlang.org/tsconfig) options.
|
|
330
|
+
- Set the build targets (`lib`, `target`) to `ES2022` or later.
|
|
331
|
+
- Enable [`strictNullChecks`](https://www.typescriptlang.org/tsconfig).
|
|
332
|
+
- Fluid Framework does not support [configuration options deprecated in TypeScript 6.0](https://typescriptdocs.com/release-notes/TypeScript%206.0#breaking-changes-and-deprecations-in-typescript-6-0).
|
|
333
|
+
- Fluid Framework does not fully support `exactOptionalPropertyTypes`.
|
|
334
|
+
If you enable this option, do not use `in`, `Reflect.has`, `Object.hasOwn`, or `Object.prototype.hasOwnProperty` to narrow members of Fluid Framework types.
|
|
335
|
+
These methods can incorrectly exclude `undefined` from the possible values.
|
|
327
336
|
- [webpack](https://webpack.js.org/) 5
|
|
328
|
-
- We
|
|
329
|
-
Other bundlers
|
|
337
|
+
- We do not require a specific bundler.
|
|
338
|
+
Other bundlers that handle ES Modules can work, but we actively test only webpack.
|
|
330
339
|
|
|
331
340
|
### Module Resolution
|
|
332
341
|
|
|
333
|
-
[`Node16`, `NodeNext`, or `Bundler`](https://www.typescriptlang.org/tsconfig#moduleResolution)
|
|
334
|
-
|
|
342
|
+
In TypeScript `compilerOptions`, use [`Node16`, `Node20`, `NodeNext`, or `Bundler`](https://www.typescriptlang.org/tsconfig#moduleResolution) module resolution.
|
|
343
|
+
These settings follow the [Node.js v12+ ESM Resolution and Loading algorithm](https://nodejs.github.io/nodejs.dev/en/api/v20/esm/#resolution-and-loading-algorithm).
|
|
344
|
+
|
|
345
|
+
Do not use `Node10` module resolution.
|
|
335
346
|
|
|
336
347
|
### Module Formats
|
|
337
348
|
|
|
338
349
|
- ES Modules:
|
|
339
|
-
ES Modules
|
|
340
|
-
-
|
|
341
|
-
|
|
342
|
-
This is done to accommodate some workflows without good ES Module support.
|
|
343
|
-
If you have a workflow you would like included in this list, file an issue.
|
|
344
|
-
Once this list of workflows motivating CommonJS support is empty, we may drop support for CommonJS one year after notice of the change is posted here.
|
|
345
|
-
|
|
346
|
-
- Testing with Jest (which lacks [stable ESM support](https://jestjs.io/docs/ecmascript-modules) due to [unstable APIs in NodeJs](https://github.com/nodejs/node/issues/37648))
|
|
350
|
+
Use ES Modules to consume Fluid Framework client packages, including in Node.js.
|
|
351
|
+
- CommonJS:
|
|
352
|
+
Fluid Framework does not officially support CommonJS in version 3.0 or later.
|
|
347
353
|
|
|
348
354
|
## Contribution Guidelines
|
|
349
355
|
|
|
350
|
-
|
|
356
|
+
You can [contribute](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md) to Fluid Framework in these ways:
|
|
351
357
|
|
|
352
|
-
-
|
|
353
|
-
- [Submit
|
|
354
|
-
- Review
|
|
358
|
+
- Answer questions in [GitHub Discussions](https://github.com/microsoft/FluidFramework/discussions).
|
|
359
|
+
- [Submit bug reports](https://github.com/microsoft/FluidFramework/issues) and help verify fixes.
|
|
360
|
+
- Review [source code changes](https://github.com/microsoft/FluidFramework/pulls).
|
|
355
361
|
- [Contribute bug fixes](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md).
|
|
356
362
|
|
|
357
|
-
|
|
363
|
+
For detailed instructions, read the [repo documentation](https://github.com/microsoft/FluidFramework/blob/main/docs/content/Home.md).
|
|
358
364
|
|
|
359
|
-
This project
|
|
360
|
-
For more information
|
|
365
|
+
This project follows the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
|
366
|
+
For more information, read the [Code of Conduct frequently asked questions](https://opensource.microsoft.com/codeofconduct/faq/).
|
|
367
|
+
For questions or comments, contact [opencode@microsoft.com](mailto:opencode@microsoft.com).
|
|
361
368
|
|
|
362
369
|
This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services.
|
|
363
370
|
Use of these trademarks or logos must follow Microsoft’s [Trademark & Brand Guidelines](https://www.microsoft.com/trademarks).
|
|
@@ -365,13 +372,9 @@ Use of Microsoft trademarks or logos in modified versions of this project must n
|
|
|
365
372
|
|
|
366
373
|
## Help
|
|
367
374
|
|
|
368
|
-
|
|
369
|
-
Check out [fluidframework.com](https://fluidframework.com/docs/).
|
|
370
|
-
|
|
371
|
-
Still not finding what you're looking for?
|
|
372
|
-
Please [file an issue](https://github.com/microsoft/FluidFramework/blob/main/docs/content/Contributing/Submitting-Bugs-and-Feature-Requests.md).
|
|
375
|
+
Read the [Fluid Framework documentation](https://fluidframework.com/docs/) for information about Fluid Framework concepts and APIs.
|
|
373
376
|
|
|
374
|
-
|
|
377
|
+
To request information that the documentation does not contain, [create an issue](https://github.com/microsoft/FluidFramework/blob/main/docs/content/Contributing/Submitting-Bugs-and-Feature-Requests.md).
|
|
375
378
|
|
|
376
379
|
## Trademark
|
|
377
380
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
-
"extends": "
|
|
3
|
+
"extends": "<projectFolder>/../../../common/build/build-common/api-extractor-model.esm.json"
|
|
4
4
|
}
|
|
@@ -49,6 +49,7 @@ export interface IBaseProtocolHandler {
|
|
|
49
49
|
|
|
50
50
|
// @alpha @legacy
|
|
51
51
|
export interface ICaptureFullContainerStateProps {
|
|
52
|
+
readonly blobCaptureMode?: "inline" | "reference" | undefined;
|
|
52
53
|
readonly documentServiceFactory: IDocumentServiceFactory;
|
|
53
54
|
readonly logger?: ITelemetryBaseLogger | undefined;
|
|
54
55
|
readonly request: IRequest;
|
|
@@ -240,13 +241,13 @@ export interface OnDemandSummaryResults {
|
|
|
240
241
|
|
|
241
242
|
// @alpha @legacy
|
|
242
243
|
export class PendingLocalStateStore<TKey> {
|
|
243
|
-
[Symbol.iterator]():
|
|
244
|
+
[Symbol.iterator](): FluidIterableIterator<[TKey, string]>;
|
|
244
245
|
clear(): void;
|
|
245
246
|
delete(key: TKey): boolean;
|
|
246
|
-
entries():
|
|
247
|
+
entries(): FluidIterableIterator<[TKey, string]>;
|
|
247
248
|
get(key: TKey): string | undefined;
|
|
248
249
|
has(key: TKey): boolean;
|
|
249
|
-
keys():
|
|
250
|
+
keys(): FluidIterableIterator<TKey>;
|
|
250
251
|
set(key: TKey, pendingLocalState: string): this;
|
|
251
252
|
get size(): number;
|
|
252
253
|
}
|
package/dist/attachment.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../src/attachment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,KAAK,EACX,uBAAuB,EACvB,SAAS,EACT,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAE3F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGxE;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,gCAAgC;IAChD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,6BAA6B,CAAC;CAChD;AAED;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,6BAA6B,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACvB,mBAAmB,GACnB,gCAAgC,GAChC,yBAAyB,GACzB,sBAAsB,GACtB,YAAY,CAAC;AAEhB;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC;;OAEG;IACH,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAEtE;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,IAAI,CAAC;IAErE;;;;;OAKG;IACH,QAAQ,CAAC,yBAAyB,EAAE,CACnC,IAAI,EAAE,YAAY,GAAG,SAAS,KAC1B,OAAO,CAAC,IAAI,CAAC,uBAAuB,EAAE,YAAY,GAAG,0BAA0B,CAAC,CAAC,CAAC;IAEvF;;OAEG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAClC,yBAAyB,EACzB,YAAY,GAAG,UAAU,GAAG,MAAM,CAClC,CAAC;IAEF;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,EAAE,CACjC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAC/B,6BAA6B,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../src/attachment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,KAAK,EACX,uBAAuB,EACvB,SAAS,EACT,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAE3F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGxE;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,gCAAgC;IAChD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,6BAA6B,CAAC;CAChD;AAED;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,6BAA6B,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACvB,mBAAmB,GACnB,gCAAgC,GAChC,yBAAyB,GACzB,sBAAsB,GACtB,YAAY,CAAC;AAEhB;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC;;OAEG;IACH,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAEtE;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,IAAI,CAAC;IAErE;;;;;OAKG;IACH,QAAQ,CAAC,yBAAyB,EAAE,CACnC,IAAI,EAAE,YAAY,GAAG,SAAS,KAC1B,OAAO,CAAC,IAAI,CAAC,uBAAuB,EAAE,YAAY,GAAG,0BAA0B,CAAC,CAAC,CAAC;IAEvF;;OAEG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAClC,yBAAyB,EACzB,YAAY,GAAG,UAAU,GAAG,MAAM,CAClC,CAAC;IAEF;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,EAAE,CACjC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAC/B,6BAA6B,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,GAAU,wHAM7C,kBAAkB,KAAG,OAAO,CAAC,SAAS,CA4ExC,CAAC"}
|
package/dist/audience.js
CHANGED
|
@@ -11,9 +11,10 @@ const internal_1 = require("@fluidframework/core-utils/internal");
|
|
|
11
11
|
* Audience represents all clients connected to the op stream.
|
|
12
12
|
*/
|
|
13
13
|
class Audience extends client_utils_1.TypedEventEmitter {
|
|
14
|
+
members = new Map();
|
|
15
|
+
_currentClientId;
|
|
14
16
|
constructor() {
|
|
15
17
|
super();
|
|
16
|
-
this.members = new Map();
|
|
17
18
|
// We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging.
|
|
18
19
|
super.setMaxListeners(0);
|
|
19
20
|
}
|
|
@@ -32,7 +33,7 @@ class Audience extends client_utils_1.TypedEventEmitter {
|
|
|
32
33
|
// this.getMember(clientId) could resolve to undefined in these two cases:
|
|
33
34
|
// 1) Feature gates controlling ConnectionStateHandler() behavior are off
|
|
34
35
|
// 2) we are loading from stashed state and audience is empty, but we remember and set prior clientId
|
|
35
|
-
this.emit("selfChanged", oldId === undefined ? undefined :
|
|
36
|
+
this.emit("selfChanged", oldId === undefined ? undefined : { clientId: oldId }, { clientId, client: this.getMember(clientId) });
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
/**
|
package/dist/audience.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAGjE,kEAA6D;AAG7D;;GAEG;AACH,MAAa,QAAS,SAAQ,gCAAkC;
|
|
1
|
+
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAGjE,kEAA6D;AAG7D;;GAEG;AACH,MAAa,QAAS,SAAQ,gCAAkC;IAC9C,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC9C,gBAAgB,CAAqB;IAE7C;QACC,KAAK,EAAE,CAAC;QACR,kHAAkH;QAClH,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAEM,OAAO;QACb,OAAO,IAAI,CAAC,gBAAgB,KAAK,SAAS;YACzC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC;gBACA,QAAQ,EAAE,IAAI,CAAC,gBAAgB;gBAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC;aAC7C,CAAC;IACL,CAAC;IAEM,kBAAkB,CAAC,QAAgB;QACzC,IAAI,IAAI,CAAC,gBAAgB,KAAK,QAAQ,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;YACjC,0EAA0E;YAC1E,yEAAyE;YACzE,qGAAqG;YACrG,IAAI,CAAC,IAAI,CACR,aAAa,EACb,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,EAAE,QAAQ,EAAE,KAAK,EAAmB,EACvE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAkB,CAC9D,CAAC;QACH,CAAC;IACF,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,QAAgB,EAAE,OAAgB;QAClD,mGAAmG;QACnG,+FAA+F;QAC/F,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAA,iBAAM,EACL,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAClD,KAAK,CAAC,wDAAwD,CAC9D,CAAC;QACH,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,YAAY,CAAC,QAAgB;QACnC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACd,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACI,UAAU;QAChB,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACI,SAAS,CAAC,QAAgB;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;CACD;AAtFD,4BAsFC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IAudienceEvents, ISelf } from \"@fluidframework/container-definitions\";\nimport type { IAudienceOwner } from \"@fluidframework/container-definitions/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { IClient } from \"@fluidframework/driver-definitions\";\n\n/**\n * Audience represents all clients connected to the op stream.\n */\nexport class Audience extends TypedEventEmitter<IAudienceEvents> implements IAudienceOwner {\n\tprivate readonly members = new Map<string, IClient>();\n\tprivate _currentClientId: string | undefined;\n\n\tconstructor() {\n\t\tsuper();\n\t\t// We are expecting this class to have many listeners, so we suppress noisy \"MaxListenersExceededWarning\" logging.\n\t\tsuper.setMaxListeners(0);\n\t}\n\n\tpublic getSelf(): ISelf | undefined {\n\t\treturn this._currentClientId === undefined\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\tclientId: this._currentClientId,\n\t\t\t\t\tclient: this.getMember(this._currentClientId),\n\t\t\t\t};\n\t}\n\n\tpublic setCurrentClientId(clientId: string): void {\n\t\tif (this._currentClientId !== clientId) {\n\t\t\tconst oldId = this._currentClientId;\n\t\t\tthis._currentClientId = clientId;\n\t\t\t// this.getMember(clientId) could resolve to undefined in these two cases:\n\t\t\t// 1) Feature gates controlling ConnectionStateHandler() behavior are off\n\t\t\t// 2) we are loading from stashed state and audience is empty, but we remember and set prior clientId\n\t\t\tthis.emit(\n\t\t\t\t\"selfChanged\",\n\t\t\t\toldId === undefined ? undefined : ({ clientId: oldId } satisfies ISelf),\n\t\t\t\t{ clientId, client: this.getMember(clientId) } satisfies ISelf,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Adds a new client to the audience\n\t */\n\tpublic addMember(clientId: string, details: IClient): void {\n\t\t// Given that signal delivery is unreliable process, we might observe same client being added twice\n\t\t// In such case we should see exactly same payload (IClient), and should not raise event twice!\n\t\tif (this.members.has(clientId)) {\n\t\t\tconst client = this.members.get(clientId);\n\t\t\tassert(\n\t\t\t\tJSON.stringify(client) === JSON.stringify(details),\n\t\t\t\t0x4b2 /* new client has different payload from existing one */,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.members.set(clientId, details);\n\t\t\tthis.emit(\"addMember\", clientId, details);\n\t\t}\n\t}\n\n\t/**\n\t * Removes a client from the audience. Only emits an event if a client is actually removed\n\t * @returns if a client was removed from the audience\n\t */\n\tpublic removeMember(clientId: string): boolean {\n\t\tconst removedClient = this.members.get(clientId);\n\t\tif (removedClient === undefined) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\tthis.members.delete(clientId);\n\t\t\tthis.emit(\"removeMember\", clientId, removedClient);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves all the members in the audience.\n\t *\n\t * @remarks When the container is disconnected, this will keep returning the audience as it was last seen before the\n\t * container disconnected.\n\t */\n\tpublic getMembers(): Map<string, IClient> {\n\t\treturn new Map(this.members);\n\t}\n\n\t/**\n\t * Retrieves a specific member of the audience.\n\t *\n\t * @remarks When the container is disconnected, this will keep returning members from the audience as it was last seen\n\t * before the container disconnected.\n\t */\n\tpublic getMember(clientId: string): IClient | undefined {\n\t\treturn this.members.get(clientId);\n\t}\n}\n"]}
|
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
7
|
+
exports.wireFormatConstants = void 0;
|
|
8
|
+
exports.mapWithConcurrency = mapWithConcurrency;
|
|
9
|
+
exports.parseGcSnapshotData = parseGcSnapshotData;
|
|
10
|
+
exports.readReferencedSnapshotBlobs = readReferencedSnapshotBlobs;
|
|
11
|
+
exports.captureReferencedAttachmentBlobs = captureReferencedAttachmentBlobs;
|
|
12
|
+
exports.extractBlobAttachReferences = extractBlobAttachReferences;
|
|
13
|
+
exports.unreferencedAttachmentBlobLocalIds = unreferencedAttachmentBlobLocalIds;
|
|
14
|
+
exports.inlineAttachmentBlobsByReference = inlineAttachmentBlobsByReference;
|
|
15
|
+
exports.snapshotHasLoadingGroups = snapshotHasLoadingGroups;
|
|
8
16
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
9
17
|
const internal_1 = require("@fluidframework/driver-utils/internal");
|
|
10
18
|
/**
|
|
@@ -63,7 +71,6 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
63
71
|
await Promise.all(workers);
|
|
64
72
|
return results;
|
|
65
73
|
}
|
|
66
|
-
exports.mapWithConcurrency = mapWithConcurrency;
|
|
67
74
|
/**
|
|
68
75
|
* Parses the `gc` subtree of a base snapshot. Returns `undefined` if the
|
|
69
76
|
* snapshot has no GC tree (GC disabled or pre-GC document).
|
|
@@ -97,7 +104,6 @@ async function parseGcSnapshotData(baseSnapshot, storage) {
|
|
|
97
104
|
}
|
|
98
105
|
return { gcState, tombstones, deletedNodes };
|
|
99
106
|
}
|
|
100
|
-
exports.parseGcSnapshotData = parseGcSnapshotData;
|
|
101
107
|
/**
|
|
102
108
|
* Walks a snapshot and inlines the contents of every blob reachable without
|
|
103
109
|
* crossing an `unreferenced` subtree boundary. Subtrees flagged
|
|
@@ -120,7 +126,6 @@ async function readReferencedSnapshotBlobs(snapshot, storage) {
|
|
|
120
126
|
});
|
|
121
127
|
return blobs;
|
|
122
128
|
}
|
|
123
|
-
exports.readReferencedSnapshotBlobs = readReferencedSnapshotBlobs;
|
|
124
129
|
/**
|
|
125
130
|
* Synchronously walks the snapshot tree and gathers the set of blob ids that
|
|
126
131
|
* should be inlined. Subtrees flagged `unreferenced: true` are skipped
|
|
@@ -198,7 +203,6 @@ async function captureReferencedAttachmentBlobs(baseSnapshot, storage, gcData) {
|
|
|
198
203
|
});
|
|
199
204
|
return contents;
|
|
200
205
|
}
|
|
201
|
-
exports.captureReferencedAttachmentBlobs = captureReferencedAttachmentBlobs;
|
|
202
206
|
/**
|
|
203
207
|
* Reconstructs the BlobManager's redirect table from a `.blobs` subtree.
|
|
204
208
|
* Mirrors `toRedirectTable` in blobManagerSnapSum.ts.
|
|
@@ -277,7 +281,6 @@ function extractBlobAttachReferences(op) {
|
|
|
277
281
|
}
|
|
278
282
|
return [{ localId: op.metadata.localId, storageId: op.metadata.blobId }];
|
|
279
283
|
}
|
|
280
|
-
exports.extractBlobAttachReferences = extractBlobAttachReferences;
|
|
281
284
|
/**
|
|
282
285
|
* Set of attachment-blob localIds that GC has marked unreferenced,
|
|
283
286
|
* tombstoned, or deleted in the base snapshot. `undefined` if `gcData`
|
|
@@ -288,7 +291,6 @@ exports.extractBlobAttachReferences = extractBlobAttachReferences;
|
|
|
288
291
|
function unreferencedAttachmentBlobLocalIds(gcData) {
|
|
289
292
|
return gcData === undefined ? undefined : collectUnreferencedBlobLocalIds(gcData);
|
|
290
293
|
}
|
|
291
|
-
exports.unreferencedAttachmentBlobLocalIds = unreferencedAttachmentBlobLocalIds;
|
|
292
294
|
/**
|
|
293
295
|
* Inline attachment blob contents for the given `(localId, storageId)`
|
|
294
296
|
* references. Skips entries already present in `existing` (de-dupe with
|
|
@@ -319,7 +321,6 @@ async function inlineAttachmentBlobsByReference(references, storage, unreference
|
|
|
319
321
|
});
|
|
320
322
|
return added;
|
|
321
323
|
}
|
|
322
|
-
exports.inlineAttachmentBlobsByReference = inlineAttachmentBlobsByReference;
|
|
323
324
|
/**
|
|
324
325
|
* Returns true if any referenced subtree of `baseSnapshot` declares a
|
|
325
326
|
* `groupId` — the snapshot-tree wire field that carries the runtime's
|
|
@@ -345,5 +346,4 @@ function snapshotHasLoadingGroups(baseSnapshot) {
|
|
|
345
346
|
}
|
|
346
347
|
return false;
|
|
347
348
|
}
|
|
348
|
-
exports.snapshotHasLoadingGroups = snapshotHasLoadingGroups;
|
|
349
349
|
//# sourceMappingURL=captureReferencedContents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureReferencedContents.js","sourceRoot":"","sources":["../src/captureReferencedContents.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 { bufferToString } from \"@fluid-internal/client-utils\";\nimport type {\n\tIDocumentStorageService,\n\tISequencedDocumentMessage,\n\tISnapshot,\n\tISnapshotTree,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { readAndParse } from \"@fluidframework/driver-utils/internal\";\n\nimport type {\n\tIBase64BlobContents,\n\tISerializableBlobContents,\n} from \"./containerStorageAdapter.js\";\n\n/**\n * Wire-format constants this module needs to walk and filter snapshots.\n * Authoritative definitions live in `container-runtime` and\n * `runtime-definitions`; the values are duplicated here to avoid a\n * loader → runtime layering dependency. A contract test in\n * `packages/test/local-server-tests` asserts these match the authoritative\n * values; do not change them in isolation.\n *\n * Authoritative sources:\n * - `blobsTreeName`, `redirectTableBlobName`: `packages/runtime/container-runtime/src/blobManager/blobManagerSnapSum.ts`\n * - `blobManagerBasePath`: `packages/runtime/container-runtime/src/blobManager/blobManager.ts`\n * - `gcTreeKey`, `gcBlobPrefix`, `gcTombstoneBlobKey`, `gcDeletedBlobKey`: `packages/runtime/runtime-definitions/src/garbageCollectionDefinitions.ts`\n *\n * @internal\n */\nexport const wireFormatConstants = {\n\tblobsTreeName: \".blobs\",\n\tredirectTableBlobName: \".redirectTable\",\n\tblobManagerBasePath: \"_blobs\",\n\tgcTreeKey: \"gc\",\n\tgcBlobPrefix: \"__gc\",\n\tgcTombstoneBlobKey: \"__tombstones\",\n\tgcDeletedBlobKey: \"__deletedNodes\",\n} as const;\n\nconst {\n\tblobsTreeName,\n\tredirectTableBlobName,\n\tblobManagerBasePath,\n\tgcTreeKey,\n\tgcBlobPrefix,\n\tgcTombstoneBlobKey,\n\tgcDeletedBlobKey,\n} = wireFormatConstants;\n\ninterface IGcNodeData {\n\toutboundRoutes: string[];\n\tunreferencedTimestampMs?: number;\n}\n\ninterface IGcState {\n\tgcNodes: { [id: string]: IGcNodeData };\n}\n\n/**\n * The parsed subset of the `gc` subtree that drives reachability decisions.\n */\nexport interface IGcSnapshotData {\n\tgcState: IGcState | undefined;\n\ttombstones: string[] | undefined;\n\tdeletedNodes: string[] | undefined;\n}\n\n/** Reader that returns a blob's contents for a given storage id. */\ntype BlobReader = (id: string) => Promise<ArrayBufferLike>;\n\n/**\n * Upper bound on concurrent `readBlob` calls. Driver/service back-pressure is\n * real for large documents, and unbounded `Promise.all` can trigger throttling\n * or spike memory. The value is a pragmatic middle ground — high enough to\n * keep a typical driver's request pipeline full, low enough to avoid storms.\n */\nconst maxReadConcurrency = 32;\n\n/**\n * Runs `fn` over `items` with at most `limit` promises in flight. Preserves\n * input order on output (not that any caller depends on it today).\n *\n * Exported for unit tests; not part of the package public API.\n *\n * @internal\n */\nexport async function mapWithConcurrency<T, R>(\n\titems: readonly T[],\n\tlimit: number,\n\tfn: (item: T) => Promise<R>,\n): Promise<R[]> {\n\tconst results: R[] = Array.from({ length: items.length });\n\tlet cursor = 0;\n\tconst workerCount = Math.min(limit, items.length);\n\tconst workers = Array.from({ length: workerCount }, async () => {\n\t\twhile (cursor < items.length) {\n\t\t\tconst index = cursor++;\n\t\t\tconst item = items[index];\n\t\t\tif (item !== undefined) {\n\t\t\t\tresults[index] = await fn(item);\n\t\t\t}\n\t\t}\n\t});\n\tawait Promise.all(workers);\n\treturn results;\n}\n\n/**\n * Parses the `gc` subtree of a base snapshot. Returns `undefined` if the\n * snapshot has no GC tree (GC disabled or pre-GC document).\n */\nexport async function parseGcSnapshotData(\n\tbaseSnapshot: ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): Promise<IGcSnapshotData | undefined> {\n\tconst gcSnapshotTree: ISnapshotTree | undefined = baseSnapshot.trees[gcTreeKey];\n\tif (gcSnapshotTree === undefined) {\n\t\treturn undefined;\n\t}\n\tlet gcState: IGcState | undefined;\n\tlet tombstones: string[] | undefined;\n\tlet deletedNodes: string[] | undefined;\n\tfor (const [key, blobId] of Object.entries(gcSnapshotTree.blobs)) {\n\t\tif (key === gcDeletedBlobKey) {\n\t\t\tdeletedNodes = await readAndParse<string[]>(storage, blobId);\n\t\t} else if (key === gcTombstoneBlobKey) {\n\t\t\ttombstones = await readAndParse<string[]>(storage, blobId);\n\t\t} else if (key.startsWith(gcBlobPrefix)) {\n\t\t\tconst partial = await readAndParse<IGcState>(storage, blobId);\n\t\t\tif (gcState === undefined) {\n\t\t\t\tgcState = { gcNodes: { ...partial.gcNodes } };\n\t\t\t} else {\n\t\t\t\tfor (const [nodeId, nodeData] of Object.entries(partial.gcNodes)) {\n\t\t\t\t\tgcState.gcNodes[nodeId] ??= nodeData;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn { gcState, tombstones, deletedNodes };\n}\n\n/**\n * Walks a snapshot and inlines the contents of every blob reachable without\n * crossing an `unreferenced` subtree boundary. Subtrees flagged\n * `unreferenced: true` are skipped entirely — the summarizer sets that flag\n * from GC state, so honouring it filters out dead subtrees without a\n * separate GC-path traversal.\n *\n * The root-level `.blobs` subtree is special-cased: only its `.redirectTable`\n * blob is read, because attachment blob contents are captured separately via\n * {@link captureReferencedAttachmentBlobs}.\n */\nexport async function readReferencedSnapshotBlobs(\n\tsnapshot: ISnapshot | ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): Promise<ISerializableBlobContents> {\n\tconst { tree, read } = toTreeAndReader(snapshot, storage);\n\tconst ids = new Set<string>();\n\tcollectReferencedBlobIds(tree, true, ids);\n\tconst blobs: ISerializableBlobContents = {};\n\tawait mapWithConcurrency([...ids], maxReadConcurrency, async (id) => {\n\t\tconst data = await read(id);\n\t\tblobs[id] = bufferToString(data, \"utf8\");\n\t});\n\treturn blobs;\n}\n\n/**\n * Synchronously walks the snapshot tree and gathers the set of blob ids that\n * should be inlined. Subtrees flagged `unreferenced: true` are skipped\n * entirely. The root-level `.blobs` subtree is special-cased: only its\n * `.redirectTable` id is collected, because attachment blob contents are\n * captured separately via {@link captureReferencedAttachmentBlobs}.\n */\nfunction collectReferencedBlobIds(\n\ttree: ISnapshotTree,\n\tisRoot: boolean,\n\tids: Set<string>,\n): void {\n\tif (tree.unreferenced === true) {\n\t\treturn;\n\t}\n\tfor (const blobId of Object.values(tree.blobs)) {\n\t\tids.add(blobId);\n\t}\n\tfor (const [key, subTree] of Object.entries(tree.trees)) {\n\t\tif (isRoot && key === blobsTreeName) {\n\t\t\tconst tableBlobId = subTree.blobs[redirectTableBlobName];\n\t\t\tif (tableBlobId !== undefined) {\n\t\t\t\tids.add(tableBlobId);\n\t\t\t}\n\t\t} else {\n\t\t\tcollectReferencedBlobIds(subTree, false, ids);\n\t\t}\n\t}\n}\n\nfunction toTreeAndReader(\n\tsnapshot: ISnapshot | ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): { tree: ISnapshotTree; read: BlobReader } {\n\tif (\"snapshotTree\" in snapshot) {\n\t\tconst blobContents = snapshot.blobContents;\n\t\treturn {\n\t\t\ttree: snapshot.snapshotTree,\n\t\t\tread: async (id) => blobContents.get(id) ?? storage.readBlob(id),\n\t\t};\n\t}\n\treturn { tree: snapshot, read: async (id) => storage.readBlob(id) };\n}\n\n/**\n * Fetches attachment blob contents from a snapshot, filtered by GC\n * reachability. Blobs GC has explicitly marked unreferenced, tombstoned, or\n * deleted are skipped. Blobs absent from the GC graph are kept — GC state\n * lags behind recent attachments and dropping them would lose live data.\n * If `gcData` is `undefined`, every attachment blob is returned.\n *\n * The returned map is keyed by attachment blob storage id. Values are the\n * raw bytes encoded as **base64** strings — attachment blobs may carry\n * arbitrary binary payloads (images, encrypted data, etc.) and a\n * UTF-8 round-trip would silently corrupt non-UTF-8 byte sequences with\n * replacement characters. The runtime's own pending-blob serializer uses\n * base64 for the same reason. This diverges from the structural-blob path\n * in {@link readReferencedSnapshotBlobs}, which encodes UTF-8 because those\n * blobs are JSON or other text the runtime authored. Callers must keep the\n * two encodings on separate fields of the pending state so the load side\n * can decode each correctly.\n */\nexport async function captureReferencedAttachmentBlobs(\n\tbaseSnapshot: ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n\tgcData: IGcSnapshotData | undefined,\n): Promise<IBase64BlobContents> {\n\tconst blobsTree: ISnapshotTree | undefined = baseSnapshot.trees[blobsTreeName];\n\tif (blobsTree === undefined) {\n\t\treturn {};\n\t}\n\tconst localIdToStorageId = await readRedirectTable(blobsTree, storage);\n\tif (localIdToStorageId.size === 0) {\n\t\treturn {};\n\t}\n\n\tconst unreferencedLocalIds =\n\t\tgcData === undefined ? undefined : collectUnreferencedBlobLocalIds(gcData);\n\n\tconst storageIdsToFetch = new Set<string>();\n\tfor (const [localId, storageId] of localIdToStorageId) {\n\t\tif (unreferencedLocalIds?.has(localId) !== true) {\n\t\t\tstorageIdsToFetch.add(storageId);\n\t\t}\n\t}\n\n\tconst contents: IBase64BlobContents = {};\n\tawait mapWithConcurrency([...storageIdsToFetch], maxReadConcurrency, async (storageId) => {\n\t\tconst buffer = await storage.readBlob(storageId);\n\t\tcontents[storageId] = bufferToString(buffer, \"base64\");\n\t});\n\treturn contents;\n}\n\n/**\n * Reconstructs the BlobManager's redirect table from a `.blobs` subtree.\n * Mirrors `toRedirectTable` in blobManagerSnapSum.ts.\n */\nasync function readRedirectTable(\n\tblobsTree: ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): Promise<Map<string, string>> {\n\tconst redirectTable = new Map<string, string>();\n\tconst tableBlobId: string | undefined = blobsTree.blobs[redirectTableBlobName];\n\tif (tableBlobId !== undefined) {\n\t\tconst entries = await readAndParse<[string, string][]>(storage, tableBlobId);\n\t\tfor (const [localId, storageId] of entries) {\n\t\t\tredirectTable.set(localId, storageId);\n\t\t}\n\t}\n\tfor (const [key, storageId] of Object.entries(blobsTree.blobs)) {\n\t\tif (key !== redirectTableBlobName) {\n\t\t\t// Identity mapping: storage ids referenced directly in handles (legacy).\n\t\t\tredirectTable.set(storageId, storageId);\n\t\t}\n\t}\n\treturn redirectTable;\n}\n\n/**\n * Collects the set of blob localIds that GC has explicitly marked as\n * unreferenced (via `unreferencedTimestampMs` on a gc node), tombstoned, or\n * deleted. Tombstones and deletedNodes are applied regardless of whether\n * `gcState` is present — they are authoritative on their own and must not\n * be silently dropped when gc state is absent but tombstone/deleted lists\n * exist.\n */\nfunction collectUnreferencedBlobLocalIds(gcData: IGcSnapshotData): Set<string> {\n\tconst blobPathPrefix = `/${blobManagerBasePath}/`;\n\tconst unreferenced = new Set<string>();\n\tif (gcData.gcState !== undefined) {\n\t\tfor (const [nodePath, nodeData] of Object.entries(gcData.gcState.gcNodes)) {\n\t\t\tif (\n\t\t\t\tnodePath.startsWith(blobPathPrefix) &&\n\t\t\t\tnodeData.unreferencedTimestampMs !== undefined\n\t\t\t) {\n\t\t\t\tunreferenced.add(nodePath.slice(blobPathPrefix.length));\n\t\t\t}\n\t\t}\n\t}\n\tfor (const nodePath of [...(gcData.tombstones ?? []), ...(gcData.deletedNodes ?? [])]) {\n\t\tif (nodePath.startsWith(blobPathPrefix)) {\n\t\t\tunreferenced.add(nodePath.slice(blobPathPrefix.length));\n\t\t}\n\t}\n\treturn unreferenced;\n}\n\n/**\n * A blob reference extracted from a `BlobAttach` op. `localId` is the\n * `BlobManager` GC identity for the blob; `storageId` is the id used for\n * `IDocumentStorageService.readBlob`.\n *\n * @internal\n */\nexport interface IBlobAttachReference {\n\treadonly localId: string;\n\treadonly storageId: string;\n}\n\ninterface IBlobAttachLikeMetadata {\n\treadonly localId: string;\n\treadonly blobId: string;\n}\n\nfunction isBlobAttachLikeMetadata(metadata: unknown): metadata is IBlobAttachLikeMetadata {\n\tif (typeof metadata !== \"object\" || metadata === null) {\n\t\treturn false;\n\t}\n\tconst candidate = metadata as { localId?: unknown; blobId?: unknown };\n\treturn typeof candidate.localId === \"string\" && typeof candidate.blobId === \"string\";\n}\n\n/**\n * Extracts every `BlobAttach` reference an op carries. Returns an empty array\n * for non-blobAttach ops.\n *\n * This is the single place in the loader that interprets the BlobAttach\n * wire format. Capture and load-side reasoning about ops should call into\n * this function rather than reading `op.metadata` directly, so a future\n * protocol change touches one site.\n *\n * BlobAttach ops carry `(localId, storageId)` directly on\n * `ISequencedDocumentMessage.metadata` and are not grouped — the container\n * runtime routes them through a separate `outbox.submitBlobAttach` lane,\n * and `OpGroupingManager.groupBatch` asserts (0x5dd) that no op carrying\n * non-batch metadata enters a grouped batch. If either guarantee changes,\n * extend this function rather than each call site.\n *\n * @internal\n */\nexport function extractBlobAttachReferences(\n\top: Pick<ISequencedDocumentMessage, \"metadata\">,\n): IBlobAttachReference[] {\n\tif (!isBlobAttachLikeMetadata(op.metadata)) {\n\t\treturn [];\n\t}\n\treturn [{ localId: op.metadata.localId, storageId: op.metadata.blobId }];\n}\n\n/**\n * Set of attachment-blob localIds that GC has marked unreferenced,\n * tombstoned, or deleted in the base snapshot. `undefined` if `gcData`\n * is `undefined` (GC disabled / pre-GC document).\n *\n * @internal\n */\nexport function unreferencedAttachmentBlobLocalIds(\n\tgcData: IGcSnapshotData | undefined,\n): Set<string> | undefined {\n\treturn gcData === undefined ? undefined : collectUnreferencedBlobLocalIds(gcData);\n}\n\n/**\n * Inline attachment blob contents for the given `(localId, storageId)`\n * references. Skips entries already present in `existing` (de-dupe with\n * the snapshot path) and entries whose `localId` is in\n * `unreferencedLocalIds`. Returns only the freshly-read entries; the\n * caller merges them into the existing map.\n *\n * @internal\n */\nexport async function inlineAttachmentBlobsByReference(\n\treferences: readonly IBlobAttachReference[],\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n\tunreferencedLocalIds: ReadonlySet<string> | undefined,\n\texisting: Readonly<IBase64BlobContents>,\n): Promise<IBase64BlobContents> {\n\tconst storageIdsToFetch = new Set<string>();\n\tfor (const { localId, storageId } of references) {\n\t\tif (unreferencedLocalIds?.has(localId) === true) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (existing[storageId] !== undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tstorageIdsToFetch.add(storageId);\n\t}\n\tconst added: IBase64BlobContents = {};\n\tif (storageIdsToFetch.size === 0) {\n\t\treturn added;\n\t}\n\tawait mapWithConcurrency([...storageIdsToFetch], maxReadConcurrency, async (storageId) => {\n\t\tconst buffer = await storage.readBlob(storageId);\n\t\tadded[storageId] = bufferToString(buffer, \"base64\");\n\t});\n\treturn added;\n}\n\n/**\n * Returns true if any referenced subtree of `baseSnapshot` declares a\n * `groupId` — the snapshot-tree wire field that carries the runtime's\n * loading-group identifier. Subtrees flagged `unreferenced` are skipped —\n * a dead subtree's `groupId` would not be loaded by the runtime either.\n *\n * `captureFullContainerState` does not yet support loading groups: prefetching\n * per-group snapshots adds a code path that has no end-to-end coverage and no\n * known production consumer. Callers use this to fail fast with a `UsageError`\n * rather than silently producing a pending state that omits group data.\n */\nexport function snapshotHasLoadingGroups(baseSnapshot: ISnapshotTree): boolean {\n\tif (baseSnapshot.unreferenced === true) {\n\t\treturn false;\n\t}\n\tif (baseSnapshot.groupId !== undefined) {\n\t\treturn true;\n\t}\n\tfor (const child of Object.values(baseSnapshot.trees)) {\n\t\tif (snapshotHasLoadingGroups(child)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"captureReferencedContents.js","sourceRoot":"","sources":["../src/captureReferencedContents.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 { bufferToString } from \"@fluid-internal/client-utils\";\nimport type {\n\tIDocumentStorageService,\n\tISequencedDocumentMessage,\n\tISnapshot,\n\tISnapshotTree,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { readAndParse } from \"@fluidframework/driver-utils/internal\";\n\nimport type {\n\tIBase64BlobContents,\n\tISerializableBlobContents,\n} from \"./containerStorageAdapter.js\";\n\n/**\n * Wire-format constants this module needs to walk and filter snapshots.\n * Authoritative definitions live in `container-runtime` and\n * `runtime-definitions`; the values are duplicated here to avoid a\n * loader → runtime layering dependency. A contract test in\n * `packages/test/local-server-tests` asserts these match the authoritative\n * values; do not change them in isolation.\n *\n * Authoritative sources:\n * - `blobsTreeName`, `redirectTableBlobName`: `packages/runtime/container-runtime/src/blobManager/blobManagerSnapSum.ts`\n * - `blobManagerBasePath`: `packages/runtime/container-runtime/src/blobManager/blobManager.ts`\n * - `gcTreeKey`, `gcBlobPrefix`, `gcTombstoneBlobKey`, `gcDeletedBlobKey`: `packages/runtime/runtime-definitions/src/garbageCollectionDefinitions.ts`\n *\n * @internal\n */\nexport const wireFormatConstants = {\n\tblobsTreeName: \".blobs\",\n\tredirectTableBlobName: \".redirectTable\",\n\tblobManagerBasePath: \"_blobs\",\n\tgcTreeKey: \"gc\",\n\tgcBlobPrefix: \"__gc\",\n\tgcTombstoneBlobKey: \"__tombstones\",\n\tgcDeletedBlobKey: \"__deletedNodes\",\n} as const;\n\nconst {\n\tblobsTreeName,\n\tredirectTableBlobName,\n\tblobManagerBasePath,\n\tgcTreeKey,\n\tgcBlobPrefix,\n\tgcTombstoneBlobKey,\n\tgcDeletedBlobKey,\n} = wireFormatConstants;\n\ninterface IGcNodeData {\n\toutboundRoutes: string[];\n\tunreferencedTimestampMs?: number;\n}\n\ninterface IGcState {\n\tgcNodes: { [id: string]: IGcNodeData };\n}\n\n/**\n * The parsed subset of the `gc` subtree that drives reachability decisions.\n */\nexport interface IGcSnapshotData {\n\tgcState: IGcState | undefined;\n\ttombstones: string[] | undefined;\n\tdeletedNodes: string[] | undefined;\n}\n\n/** Reader that returns a blob's contents for a given storage id. */\ntype BlobReader = (id: string) => Promise<ArrayBufferLike>;\n\n/**\n * Upper bound on concurrent `readBlob` calls. Driver/service back-pressure is\n * real for large documents, and unbounded `Promise.all` can trigger throttling\n * or spike memory. The value is a pragmatic middle ground — high enough to\n * keep a typical driver's request pipeline full, low enough to avoid storms.\n */\nconst maxReadConcurrency = 32;\n\n/**\n * Runs `fn` over `items` with at most `limit` promises in flight. Preserves\n * input order on output (not that any caller depends on it today).\n *\n * Exported for unit tests; not part of the package public API.\n *\n * @internal\n */\nexport async function mapWithConcurrency<T, R>(\n\titems: readonly T[],\n\tlimit: number,\n\tfn: (item: T) => Promise<R>,\n): Promise<R[]> {\n\tconst results: R[] = Array.from({ length: items.length });\n\tlet cursor = 0;\n\tconst workerCount = Math.min(limit, items.length);\n\tconst workers = Array.from({ length: workerCount }, async () => {\n\t\twhile (cursor < items.length) {\n\t\t\tconst index = cursor++;\n\t\t\tconst item = items[index];\n\t\t\tif (item !== undefined) {\n\t\t\t\tresults[index] = await fn(item);\n\t\t\t}\n\t\t}\n\t});\n\tawait Promise.all(workers);\n\treturn results;\n}\n\n/**\n * Parses the `gc` subtree of a base snapshot. Returns `undefined` if the\n * snapshot has no GC tree (GC disabled or pre-GC document).\n */\nexport async function parseGcSnapshotData(\n\tbaseSnapshot: ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): Promise<IGcSnapshotData | undefined> {\n\tconst gcSnapshotTree: ISnapshotTree | undefined = baseSnapshot.trees[gcTreeKey];\n\tif (gcSnapshotTree === undefined) {\n\t\treturn undefined;\n\t}\n\tlet gcState: IGcState | undefined;\n\tlet tombstones: string[] | undefined;\n\tlet deletedNodes: string[] | undefined;\n\tfor (const [key, blobId] of Object.entries(gcSnapshotTree.blobs)) {\n\t\tif (key === gcDeletedBlobKey) {\n\t\t\tdeletedNodes = await readAndParse<string[]>(storage, blobId);\n\t\t} else if (key === gcTombstoneBlobKey) {\n\t\t\ttombstones = await readAndParse<string[]>(storage, blobId);\n\t\t} else if (key.startsWith(gcBlobPrefix)) {\n\t\t\tconst partial = await readAndParse<IGcState>(storage, blobId);\n\t\t\tif (gcState === undefined) {\n\t\t\t\tgcState = { gcNodes: { ...partial.gcNodes } };\n\t\t\t} else {\n\t\t\t\tfor (const [nodeId, nodeData] of Object.entries(partial.gcNodes)) {\n\t\t\t\t\tgcState.gcNodes[nodeId] ??= nodeData;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn { gcState, tombstones, deletedNodes };\n}\n\n/**\n * Walks a snapshot and inlines the contents of every blob reachable without\n * crossing an `unreferenced` subtree boundary. Subtrees flagged\n * `unreferenced: true` are skipped entirely — the summarizer sets that flag\n * from GC state, so honouring it filters out dead subtrees without a\n * separate GC-path traversal.\n *\n * The root-level `.blobs` subtree is special-cased: only its `.redirectTable`\n * blob is read, because attachment blob contents are captured separately via\n * {@link captureReferencedAttachmentBlobs}.\n */\nexport async function readReferencedSnapshotBlobs(\n\tsnapshot: ISnapshot | ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): Promise<ISerializableBlobContents> {\n\tconst { tree, read } = toTreeAndReader(snapshot, storage);\n\tconst ids = new Set<string>();\n\tcollectReferencedBlobIds(tree, true, ids);\n\tconst blobs: ISerializableBlobContents = {};\n\tawait mapWithConcurrency([...ids], maxReadConcurrency, async (id) => {\n\t\tconst data = await read(id);\n\t\tblobs[id] = bufferToString(data, \"utf8\");\n\t});\n\treturn blobs;\n}\n\n/**\n * Synchronously walks the snapshot tree and gathers the set of blob ids that\n * should be inlined. Subtrees flagged `unreferenced: true` are skipped\n * entirely. The root-level `.blobs` subtree is special-cased: only its\n * `.redirectTable` id is collected, because attachment blob contents are\n * captured separately via {@link captureReferencedAttachmentBlobs}.\n */\nfunction collectReferencedBlobIds(\n\ttree: ISnapshotTree,\n\tisRoot: boolean,\n\tids: Set<string>,\n): void {\n\tif (tree.unreferenced === true) {\n\t\treturn;\n\t}\n\tfor (const blobId of Object.values(tree.blobs)) {\n\t\tids.add(blobId);\n\t}\n\tfor (const [key, subTree] of Object.entries(tree.trees)) {\n\t\tif (isRoot && key === blobsTreeName) {\n\t\t\tconst tableBlobId = subTree.blobs[redirectTableBlobName];\n\t\t\tif (tableBlobId !== undefined) {\n\t\t\t\tids.add(tableBlobId);\n\t\t\t}\n\t\t} else {\n\t\t\tcollectReferencedBlobIds(subTree, false, ids);\n\t\t}\n\t}\n}\n\nfunction toTreeAndReader(\n\tsnapshot: ISnapshot | ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): { tree: ISnapshotTree; read: BlobReader } {\n\tif (\"snapshotTree\" in snapshot) {\n\t\tconst blobContents = snapshot.blobContents;\n\t\treturn {\n\t\t\ttree: snapshot.snapshotTree,\n\t\t\tread: async (id) => blobContents.get(id) ?? storage.readBlob(id),\n\t\t};\n\t}\n\treturn { tree: snapshot, read: async (id) => storage.readBlob(id) };\n}\n\n/**\n * Fetches attachment blob contents from a snapshot, filtered by GC\n * reachability. Blobs GC has explicitly marked unreferenced, tombstoned, or\n * deleted are skipped. Blobs absent from the GC graph are kept — GC state\n * lags behind recent attachments and dropping them would lose live data.\n * If `gcData` is `undefined`, every attachment blob is returned.\n *\n * The returned map is keyed by attachment blob storage id. Values are the\n * raw bytes encoded as **base64** strings — attachment blobs may carry\n * arbitrary binary payloads (images, encrypted data, etc.) and a\n * UTF-8 round-trip would silently corrupt non-UTF-8 byte sequences with\n * replacement characters. The runtime's own pending-blob serializer uses\n * base64 for the same reason. This diverges from the structural-blob path\n * in {@link readReferencedSnapshotBlobs}, which encodes UTF-8 because those\n * blobs are JSON or other text the runtime authored. Callers must keep the\n * two encodings on separate fields of the pending state so the load side\n * can decode each correctly.\n */\nexport async function captureReferencedAttachmentBlobs(\n\tbaseSnapshot: ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n\tgcData: IGcSnapshotData | undefined,\n): Promise<IBase64BlobContents> {\n\tconst blobsTree: ISnapshotTree | undefined = baseSnapshot.trees[blobsTreeName];\n\tif (blobsTree === undefined) {\n\t\treturn {};\n\t}\n\tconst localIdToStorageId = await readRedirectTable(blobsTree, storage);\n\tif (localIdToStorageId.size === 0) {\n\t\treturn {};\n\t}\n\n\tconst unreferencedLocalIds =\n\t\tgcData === undefined ? undefined : collectUnreferencedBlobLocalIds(gcData);\n\n\tconst storageIdsToFetch = new Set<string>();\n\tfor (const [localId, storageId] of localIdToStorageId) {\n\t\tif (unreferencedLocalIds?.has(localId) !== true) {\n\t\t\tstorageIdsToFetch.add(storageId);\n\t\t}\n\t}\n\n\tconst contents: IBase64BlobContents = {};\n\tawait mapWithConcurrency([...storageIdsToFetch], maxReadConcurrency, async (storageId) => {\n\t\tconst buffer = await storage.readBlob(storageId);\n\t\tcontents[storageId] = bufferToString(buffer, \"base64\");\n\t});\n\treturn contents;\n}\n\n/**\n * Reconstructs the BlobManager's redirect table from a `.blobs` subtree.\n * Mirrors `toRedirectTable` in blobManagerSnapSum.ts.\n */\nasync function readRedirectTable(\n\tblobsTree: ISnapshotTree,\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n): Promise<Map<string, string>> {\n\tconst redirectTable = new Map<string, string>();\n\tconst tableBlobId: string | undefined = blobsTree.blobs[redirectTableBlobName];\n\tif (tableBlobId !== undefined) {\n\t\tconst entries = await readAndParse<[string, string][]>(storage, tableBlobId);\n\t\tfor (const [localId, storageId] of entries) {\n\t\t\tredirectTable.set(localId, storageId);\n\t\t}\n\t}\n\tfor (const [key, storageId] of Object.entries(blobsTree.blobs)) {\n\t\tif (key !== redirectTableBlobName) {\n\t\t\t// Identity mapping: storage ids referenced directly in handles (legacy).\n\t\t\tredirectTable.set(storageId, storageId);\n\t\t}\n\t}\n\treturn redirectTable;\n}\n\n/**\n * Collects the set of blob localIds that GC has explicitly marked as\n * unreferenced (via `unreferencedTimestampMs` on a gc node), tombstoned, or\n * deleted. Tombstones and deletedNodes are applied regardless of whether\n * `gcState` is present — they are authoritative on their own and must not\n * be silently dropped when gc state is absent but tombstone/deleted lists\n * exist.\n */\nfunction collectUnreferencedBlobLocalIds(gcData: IGcSnapshotData): Set<string> {\n\tconst blobPathPrefix = `/${blobManagerBasePath}/`;\n\tconst unreferenced = new Set<string>();\n\tif (gcData.gcState !== undefined) {\n\t\tfor (const [nodePath, nodeData] of Object.entries(gcData.gcState.gcNodes)) {\n\t\t\tif (\n\t\t\t\tnodePath.startsWith(blobPathPrefix) &&\n\t\t\t\tnodeData.unreferencedTimestampMs !== undefined\n\t\t\t) {\n\t\t\t\tunreferenced.add(nodePath.slice(blobPathPrefix.length));\n\t\t\t}\n\t\t}\n\t}\n\tfor (const nodePath of [...(gcData.tombstones ?? []), ...(gcData.deletedNodes ?? [])]) {\n\t\tif (nodePath.startsWith(blobPathPrefix)) {\n\t\t\tunreferenced.add(nodePath.slice(blobPathPrefix.length));\n\t\t}\n\t}\n\treturn unreferenced;\n}\n\n/**\n * A blob reference extracted from a `BlobAttach` op. `localId` is the\n * `BlobManager` GC identity for the blob; `storageId` is the id used for\n * `IDocumentStorageService.readBlob`.\n *\n * @internal\n */\nexport interface IBlobAttachReference {\n\treadonly localId: string;\n\treadonly storageId: string;\n}\n\ninterface IBlobAttachLikeMetadata {\n\treadonly localId: string;\n\treadonly blobId: string;\n}\n\nfunction isBlobAttachLikeMetadata(metadata: unknown): metadata is IBlobAttachLikeMetadata {\n\tif (typeof metadata !== \"object\" || metadata === null) {\n\t\treturn false;\n\t}\n\tconst candidate = metadata as { localId?: unknown; blobId?: unknown };\n\treturn typeof candidate.localId === \"string\" && typeof candidate.blobId === \"string\";\n}\n\n/**\n * Extracts every `BlobAttach` reference an op carries. Returns an empty array\n * for non-blobAttach ops.\n *\n * This is the single place in the loader that interprets the BlobAttach\n * wire format. Capture and load-side reasoning about ops should call into\n * this function rather than reading `op.metadata` directly, so a future\n * protocol change touches one site.\n *\n * BlobAttach ops carry `(localId, storageId)` directly on\n * `ISequencedDocumentMessage.metadata` and are not grouped — the container\n * runtime routes them through a separate `outbox.submitBlobAttach` lane,\n * and `OpGroupingManager.groupBatch` asserts (0x5dd) that no op carrying\n * non-batch metadata enters a grouped batch. If either guarantee changes,\n * extend this function rather than each call site.\n *\n * @internal\n */\nexport function extractBlobAttachReferences(\n\top: Pick<ISequencedDocumentMessage, \"metadata\">,\n): IBlobAttachReference[] {\n\tif (!isBlobAttachLikeMetadata(op.metadata)) {\n\t\treturn [];\n\t}\n\treturn [{ localId: op.metadata.localId, storageId: op.metadata.blobId }];\n}\n\n/**\n * Set of attachment-blob localIds that GC has marked unreferenced,\n * tombstoned, or deleted in the base snapshot. `undefined` if `gcData`\n * is `undefined` (GC disabled / pre-GC document).\n *\n * @internal\n */\nexport function unreferencedAttachmentBlobLocalIds(\n\tgcData: IGcSnapshotData | undefined,\n): Set<string> | undefined {\n\treturn gcData === undefined ? undefined : collectUnreferencedBlobLocalIds(gcData);\n}\n\n/**\n * Inline attachment blob contents for the given `(localId, storageId)`\n * references. Skips entries already present in `existing` (de-dupe with\n * the snapshot path) and entries whose `localId` is in\n * `unreferencedLocalIds`. Returns only the freshly-read entries; the\n * caller merges them into the existing map.\n *\n * @internal\n */\nexport async function inlineAttachmentBlobsByReference(\n\treferences: readonly IBlobAttachReference[],\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n\tunreferencedLocalIds: ReadonlySet<string> | undefined,\n\texisting: Readonly<IBase64BlobContents>,\n): Promise<IBase64BlobContents> {\n\tconst storageIdsToFetch = new Set<string>();\n\tfor (const { localId, storageId } of references) {\n\t\tif (unreferencedLocalIds?.has(localId) === true) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (existing[storageId] !== undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tstorageIdsToFetch.add(storageId);\n\t}\n\tconst added: IBase64BlobContents = {};\n\tif (storageIdsToFetch.size === 0) {\n\t\treturn added;\n\t}\n\tawait mapWithConcurrency([...storageIdsToFetch], maxReadConcurrency, async (storageId) => {\n\t\tconst buffer = await storage.readBlob(storageId);\n\t\tadded[storageId] = bufferToString(buffer, \"base64\");\n\t});\n\treturn added;\n}\n\n/**\n * Returns true if any referenced subtree of `baseSnapshot` declares a\n * `groupId` — the snapshot-tree wire field that carries the runtime's\n * loading-group identifier. Subtrees flagged `unreferenced` are skipped —\n * a dead subtree's `groupId` would not be loaded by the runtime either.\n *\n * `captureFullContainerState` does not yet support loading groups: prefetching\n * per-group snapshots adds a code path that has no end-to-end coverage and no\n * known production consumer. Callers use this to fail fast with a `UsageError`\n * rather than silently producing a pending state that omits group data.\n */\nexport function snapshotHasLoadingGroups(baseSnapshot: ISnapshotTree): boolean {\n\tif (baseSnapshot.unreferenced === true) {\n\t\treturn false;\n\t}\n\tif (baseSnapshot.groupId !== undefined) {\n\t\treturn true;\n\t}\n\tfor (const child of Object.values(baseSnapshot.trees)) {\n\t\tif (snapshotHasLoadingGroups(child)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n"]}
|
package/dist/catchUpMonitor.js
CHANGED
|
@@ -11,6 +11,16 @@ const internal_1 = require("@fluidframework/core-utils/internal");
|
|
|
11
11
|
* that were known at the time the monitor was created.
|
|
12
12
|
*/
|
|
13
13
|
class CatchUpMonitor {
|
|
14
|
+
deltaManager;
|
|
15
|
+
listener;
|
|
16
|
+
targetSeqNumber;
|
|
17
|
+
caughtUp = false;
|
|
18
|
+
opHandler = (message) => {
|
|
19
|
+
if (!this.caughtUp && message.sequenceNumber >= this.targetSeqNumber) {
|
|
20
|
+
this.caughtUp = true;
|
|
21
|
+
this.listener();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
14
24
|
/**
|
|
15
25
|
* Create the CatchUpMonitor, setting the target sequence number to wait for based on DeltaManager's current state.
|
|
16
26
|
*
|
|
@@ -25,14 +35,6 @@ class CatchUpMonitor {
|
|
|
25
35
|
constructor(deltaManager, listener) {
|
|
26
36
|
this.deltaManager = deltaManager;
|
|
27
37
|
this.listener = listener;
|
|
28
|
-
this.caughtUp = false;
|
|
29
|
-
this.opHandler = (message) => {
|
|
30
|
-
if (!this.caughtUp && message.sequenceNumber >= this.targetSeqNumber) {
|
|
31
|
-
this.caughtUp = true;
|
|
32
|
-
this.listener();
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
this._disposed = false;
|
|
36
38
|
this.targetSeqNumber = this.deltaManager.lastKnownSeqNumber;
|
|
37
39
|
(0, internal_1.assert)(this.targetSeqNumber >= this.deltaManager.lastSequenceNumber, 0x37c /* Cannot wait for seqNumber below last processed sequence number */);
|
|
38
40
|
this.deltaManager.on("op", this.opHandler);
|
|
@@ -47,6 +49,7 @@ class CatchUpMonitor {
|
|
|
47
49
|
// Simulate the last processed op to set caughtUp in case we already are
|
|
48
50
|
this.opHandler({ sequenceNumber: this.deltaManager.lastSequenceNumber });
|
|
49
51
|
}
|
|
52
|
+
_disposed = false;
|
|
50
53
|
/**
|
|
51
54
|
* {@inheritDoc @fluidframework/core-interfaces#IDisposable.disposed}
|
|
52
55
|
*/
|