@fluidframework/container-loader 2.93.0 → 2.101.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 +12 -0
- package/api-report/container-loader.legacy.alpha.api.md +13 -1
- package/dist/captureReferencedContents.d.ts +154 -0
- package/dist/captureReferencedContents.d.ts.map +1 -0
- package/dist/captureReferencedContents.js +349 -0
- package/dist/captureReferencedContents.js.map +1 -0
- package/dist/connectionManager.d.ts +2 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +39 -8
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +3 -1
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +13 -4
- package/dist/container.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +20 -2
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +2 -2
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/createAndLoadContainerUtils.d.ts +95 -0
- package/dist/createAndLoadContainerUtils.d.ts.map +1 -1
- package/dist/createAndLoadContainerUtils.js +137 -11
- package/dist/createAndLoadContainerUtils.js.map +1 -1
- package/dist/frozenServices.d.ts +113 -30
- package/dist/frozenServices.d.ts.map +1 -1
- package/dist/frozenServices.js +236 -58
- package/dist/frozenServices.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/legacyAlpha.d.ts +2 -0
- package/dist/loader.d.ts +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1 -1
- package/dist/loader.js.map +1 -1
- package/dist/loaderLayerCompatState.d.ts +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.map +1 -1
- package/dist/pendingLocalStateStore.js +9 -3
- package/dist/pendingLocalStateStore.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +2 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +3 -2
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +16 -1
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +11 -1
- package/dist/serializedStateManager.js.map +1 -1
- package/lib/captureReferencedContents.d.ts +154 -0
- package/lib/captureReferencedContents.d.ts.map +1 -0
- package/lib/captureReferencedContents.js +338 -0
- package/lib/captureReferencedContents.js.map +1 -0
- package/lib/connectionManager.d.ts +2 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +40 -9
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +3 -1
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +14 -5
- package/lib/container.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +20 -2
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +2 -2
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/createAndLoadContainerUtils.d.ts +95 -0
- package/lib/createAndLoadContainerUtils.d.ts.map +1 -1
- package/lib/createAndLoadContainerUtils.js +128 -3
- package/lib/createAndLoadContainerUtils.js.map +1 -1
- package/lib/frozenServices.d.ts +113 -30
- package/lib/frozenServices.d.ts.map +1 -1
- package/lib/frozenServices.js +233 -57
- package/lib/frozenServices.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/legacyAlpha.d.ts +2 -0
- package/lib/loader.d.ts +1 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +2 -2
- package/lib/loader.js.map +1 -1
- package/lib/loaderLayerCompatState.d.ts +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.map +1 -1
- package/lib/pendingLocalStateStore.js +9 -3
- package/lib/pendingLocalStateStore.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +2 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +3 -2
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +16 -1
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +11 -1
- package/lib/serializedStateManager.js.map +1 -1
- package/package.json +13 -13
- package/src/captureReferencedContents.ts +446 -0
- package/src/connectionManager.ts +47 -8
- package/src/connectionStateHandler.ts +14 -9
- package/src/container.ts +18 -4
- package/src/containerStorageAdapter.ts +22 -2
- package/src/createAndLoadContainerUtils.ts +229 -2
- package/src/frozenServices.ts +285 -64
- package/src/index.ts +7 -0
- package/src/loader.ts +4 -2
- package/src/packageVersion.ts +1 -1
- package/src/pendingLocalStateStore.ts +8 -1
- package/src/retriableDocumentStorageService.ts +11 -4
- package/src/serializedStateManager.ts +28 -1
package/dist/frozenServices.js
CHANGED
|
@@ -4,35 +4,53 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.isFrozenDeltaStreamConnection = exports.FrozenDeltaStream = exports.FrozenDocumentServiceFactory = exports.createFrozenDocumentServiceFactory = void 0;
|
|
7
|
+
exports.isWritableFrozenDeltaStreamConnection = exports.isFrozenDeltaStreamConnection = exports.WritableFrozenDeltaStream = exports.FrozenDeltaStream = exports.FrozenDocumentServiceFactory = exports.createFrozenDocumentServiceFactory = void 0;
|
|
8
8
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
9
9
|
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
10
10
|
const internal_2 = require("@fluidframework/driver-definitions/internal");
|
|
11
|
+
const uuid_1 = require("uuid");
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* Creates an `IDocumentServiceFactory` that produces a "frozen" document service: one whose
|
|
14
|
+
* delta stream never sends or receives ops, and whose storage service only supports
|
|
15
|
+
* `IDocumentStorageService.readBlob`. Used to load a container from pending local state
|
|
16
|
+
* without re-establishing a live connection.
|
|
14
17
|
*
|
|
15
|
-
* @param
|
|
16
|
-
*
|
|
18
|
+
* @param factory - The underlying factory to wrap. Its storage backs blob reads; all other
|
|
19
|
+
* storage operations throw. May be omitted when blob fetches are not required.
|
|
20
|
+
* @param readOnly - When `true` (the default), the document service advertises the
|
|
21
|
+
* `IDocumentServicePolicies.storageOnly` policy, which causes the loader to surface the
|
|
22
|
+
* container as read-only (see `IContainer.readOnlyInfo`).
|
|
23
|
+
*
|
|
24
|
+
* When `false`, the container is loaded as writable so the runtime will accept DDS submissions.
|
|
25
|
+
* The connection itself stays `Connected`: `ConnectionManager.sendMessages` recognizes the
|
|
26
|
+
* `WritableFrozenDeltaStream` as the live connection and short-circuits — the message is dropped
|
|
27
|
+
* at the network layer rather than triggering a read→write reconnect. Local DDS state continues
|
|
28
|
+
* to update via optimistic apply, and submitted ops accumulate in the runtime's pending-state
|
|
29
|
+
* manager, which is exactly the state needed to capture pending local state. Use `false` when
|
|
30
|
+
* callers want to accrue and capture pending state without publishing it.
|
|
31
|
+
* @returns A factory that produces frozen document services.
|
|
17
32
|
* @legacy @alpha
|
|
18
33
|
*/
|
|
19
|
-
function createFrozenDocumentServiceFactory(factory) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
function createFrozenDocumentServiceFactory(factory, readOnly = true) {
|
|
35
|
+
if (factory instanceof FrozenDocumentServiceFactory) {
|
|
36
|
+
// Already wrapped. Reuse if readOnly matches; otherwise unwrap and rewrap so the caller's
|
|
37
|
+
// most recent readOnly intent wins (silently honoring caller intent rather than dropping
|
|
38
|
+
// the new argument).
|
|
39
|
+
return factory.readOnly === readOnly
|
|
40
|
+
? factory
|
|
41
|
+
: new FrozenDocumentServiceFactory(readOnly, factory.inner);
|
|
42
|
+
}
|
|
43
|
+
return new FrozenDocumentServiceFactory(readOnly, factory);
|
|
24
44
|
}
|
|
25
45
|
exports.createFrozenDocumentServiceFactory = createFrozenDocumentServiceFactory;
|
|
26
46
|
class FrozenDocumentServiceFactory {
|
|
27
|
-
constructor(
|
|
28
|
-
this.
|
|
47
|
+
constructor(readOnly, inner) {
|
|
48
|
+
this.readOnly = readOnly;
|
|
49
|
+
this.inner = inner;
|
|
29
50
|
}
|
|
30
51
|
async createDocumentService(resolvedUrl) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
factory = await this.documentServiceFactory;
|
|
34
|
-
}
|
|
35
|
-
return new FrozenDocumentService(resolvedUrl, await factory?.createDocumentService(resolvedUrl));
|
|
52
|
+
const factory = (0, internal_1.isPromiseLike)(this.inner) ? await this.inner : this.inner;
|
|
53
|
+
return new FrozenDocumentService(resolvedUrl, this.readOnly, await factory?.createDocumentService(resolvedUrl));
|
|
36
54
|
}
|
|
37
55
|
async createContainer() {
|
|
38
56
|
throw new Error("The FrozenDocumentServiceFactory cannot be used to create containers.");
|
|
@@ -40,39 +58,117 @@ class FrozenDocumentServiceFactory {
|
|
|
40
58
|
}
|
|
41
59
|
exports.FrozenDocumentServiceFactory = FrozenDocumentServiceFactory;
|
|
42
60
|
class FrozenDocumentService extends client_utils_1.TypedEventEmitter {
|
|
43
|
-
constructor(resolvedUrl, documentService) {
|
|
61
|
+
constructor(resolvedUrl, readOnly, documentService) {
|
|
44
62
|
super();
|
|
45
63
|
this.resolvedUrl = resolvedUrl;
|
|
64
|
+
this.readOnly = readOnly;
|
|
46
65
|
this.documentService = documentService;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
66
|
+
// Tracks every storage instance handed out by `connectToStorage` so `dispose()` can cascade
|
|
67
|
+
// disposal to each one (rejecting their hanging `createBlob` deferreds). A Set rather than
|
|
68
|
+
// a single field because `IDocumentService.connectToStorage` is a public API that can be
|
|
69
|
+
// called more than once — we cannot assume the Container holds a single instance.
|
|
70
|
+
this.storageServices = new Set();
|
|
71
|
+
// When readOnly, advertise the storageOnly policy. The connectionManager short-circuits
|
|
72
|
+
// on it: it synthesizes a FrozenDeltaStream itself and never calls
|
|
73
|
+
// connectToDeltaStream, and the readOnlyInfo getter forces the container to read-only
|
|
74
|
+
// because the live connection is a FrozenDeltaStream.
|
|
75
|
+
//
|
|
76
|
+
// Audit (2026-05-05): the only consumer of `policies.storageOnly` as a frozen-container
|
|
77
|
+
// signal is `ConnectionManager` (synthesizing a `FrozenDeltaStream` when set). All other
|
|
78
|
+
// matches in the loader/runtime/driver layers are either drivers reading their own
|
|
79
|
+
// policies (e.g. local-driver) or `IReadOnlyInfo.storageOnly`, which is derived from the
|
|
80
|
+
// live connection — not the policy. So the writable-frozen container is intentionally
|
|
81
|
+
// indistinguishable from a normal container at the policies layer; downstream behavior
|
|
82
|
+
// flows through the live `WritableFrozenDeltaStream` instead.
|
|
83
|
+
this.policies = readOnly ? { storageOnly: true } : {};
|
|
50
84
|
}
|
|
51
85
|
async connectToStorage() {
|
|
52
|
-
|
|
86
|
+
const storage = new FrozenDocumentStorageService(this.readOnly, await this.documentService?.connectToStorage());
|
|
87
|
+
this.storageServices.add(storage);
|
|
88
|
+
return storage;
|
|
53
89
|
}
|
|
54
90
|
async connectToDeltaStorage() {
|
|
55
91
|
return frozenDocumentDeltaStorageService;
|
|
56
92
|
}
|
|
57
|
-
async connectToDeltaStream(
|
|
58
|
-
|
|
93
|
+
async connectToDeltaStream(_client) {
|
|
94
|
+
if (this.readOnly) {
|
|
95
|
+
// connectionManager short-circuits via policies.storageOnly before reaching here
|
|
96
|
+
// in the read-only path; reaching this branch indicates a non-connectionManager
|
|
97
|
+
// consumer or a regression of the short-circuit. Throw to surface the misuse
|
|
98
|
+
// rather than silently produce a working stream.
|
|
99
|
+
throw new Error("FrozenDocumentService is read-only; connectToDeltaStream should not be called (connectionManager short-circuits via policies.storageOnly)");
|
|
100
|
+
}
|
|
101
|
+
// Writable path: hand out a fresh WritableFrozenDeltaStream regardless of client.mode
|
|
102
|
+
// or whether this is the initial connect or a reconnect. The stream's own mode is
|
|
103
|
+
// "read" (advertising "write" would imply quorum membership we cannot honor), and
|
|
104
|
+
// `ConnectionManager.sendMessages` short-circuits on WritableFrozenDeltaStream so
|
|
105
|
+
// outbound writes never reach a real network. The per-instance clientId minted in
|
|
106
|
+
// FrozenDeltaStreamBase prevents pendingStateManager 0x173 on replay across reconnects.
|
|
107
|
+
return new WritableFrozenDeltaStream();
|
|
108
|
+
}
|
|
109
|
+
dispose(error) {
|
|
110
|
+
// Cascade disposal to each storage instance so any hanging `createBlob` promises (the
|
|
111
|
+
// writable-frozen pending-blob mechanism) reject and the BlobManager can release its
|
|
112
|
+
// references. Without this, hung promises remain held by BlobManager closures for the
|
|
113
|
+
// lifetime of the process.
|
|
114
|
+
for (const storage of this.storageServices) {
|
|
115
|
+
storage.dispose();
|
|
116
|
+
}
|
|
117
|
+
this.storageServices.clear();
|
|
118
|
+
// Forward disposal to the wrapped service. We own its lifetime (it was created for us
|
|
119
|
+
// by the wrapping factory and is never exposed to callers), so the contract from
|
|
120
|
+
// `IDocumentService.dispose` ("called by storage consumer when done with storage")
|
|
121
|
+
// applies here.
|
|
122
|
+
this.documentService?.dispose(error);
|
|
59
123
|
}
|
|
60
|
-
dispose() { }
|
|
61
124
|
}
|
|
62
125
|
const frozenDocumentStorageServiceHandler = () => {
|
|
63
126
|
throw new Error("Operations are not supported on the FrozenDocumentStorageService.");
|
|
64
127
|
};
|
|
65
128
|
class FrozenDocumentStorageService {
|
|
66
|
-
|
|
129
|
+
get disposed() {
|
|
130
|
+
return this._disposed;
|
|
131
|
+
}
|
|
132
|
+
constructor(readOnly, documentStorageService) {
|
|
67
133
|
this.documentStorageService = documentStorageService;
|
|
134
|
+
this._disposed = false;
|
|
68
135
|
this.getSnapshotTree = frozenDocumentStorageServiceHandler;
|
|
69
136
|
this.getSnapshot = frozenDocumentStorageServiceHandler;
|
|
70
137
|
this.getVersions = frozenDocumentStorageServiceHandler;
|
|
71
|
-
this.createBlob = frozenDocumentStorageServiceHandler;
|
|
72
138
|
this.readBlob = this.documentStorageService?.readBlob.bind(this.documentStorageService) ??
|
|
73
139
|
frozenDocumentStorageServiceHandler;
|
|
74
140
|
this.uploadSummaryWithContext = frozenDocumentStorageServiceHandler;
|
|
75
141
|
this.downloadSummary = frozenDocumentStorageServiceHandler;
|
|
142
|
+
let rejectFn;
|
|
143
|
+
const promise = new Promise((_, reject) => {
|
|
144
|
+
rejectFn = reject;
|
|
145
|
+
});
|
|
146
|
+
// Attach a no-op catch so node doesn't log an unhandled-rejection warning when
|
|
147
|
+
// dispose runs before any caller has awaited the promise. Callers awaiting the
|
|
148
|
+
// original promise still observe the rejection.
|
|
149
|
+
promise.catch(() => { });
|
|
150
|
+
this.disposalDeferred = { promise, reject: rejectFn };
|
|
151
|
+
// In the writable-frozen path, `createBlob` returns a never-resolving promise instead
|
|
152
|
+
// of throwing. This keeps the BlobManager's `localBlobCache` entry in the `uploading`
|
|
153
|
+
// state: `getPendingBlobs` downgrades `uploading` blobs to `localOnly` in pending
|
|
154
|
+
// state, so the blob survives `getPendingLocalState`. A subsequent live load runs
|
|
155
|
+
// `sharePendingBlobs`, which re-enters `uploadAndAttach` against the real storage to
|
|
156
|
+
// complete the upload. Throwing here would instead delete the cache entry (in
|
|
157
|
+
// `uploadAndAttach`'s catch handler) and lose the blob — defeating the whole point of
|
|
158
|
+
// accruing pending state.
|
|
159
|
+
this.createBlob = readOnly
|
|
160
|
+
? frozenDocumentStorageServiceHandler
|
|
161
|
+
: async () => this.disposalDeferred.promise;
|
|
162
|
+
}
|
|
163
|
+
dispose() {
|
|
164
|
+
if (this._disposed) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this._disposed = true;
|
|
168
|
+
// Don't propagate any caller-supplied error here. `IDocumentService.dispose` already
|
|
169
|
+
// logs the Container's error path; the createBlob deferred's consumer (BlobManager)
|
|
170
|
+
// only needs the "this storage is going away" signal — not a chain of error causes.
|
|
171
|
+
this.disposalDeferred.reject(new Error("FrozenDocumentStorageService is disposed"));
|
|
76
172
|
}
|
|
77
173
|
}
|
|
78
174
|
const frozenDocumentDeltaStorageService = {
|
|
@@ -90,54 +186,71 @@ const clientFrozenDeltaStream = {
|
|
|
90
186
|
scopes: [],
|
|
91
187
|
};
|
|
92
188
|
const clientIdFrozenDeltaStream = "storage-only client";
|
|
189
|
+
// Cast rationale: ITokenClaims requires tenantId/documentId/user/iat/exp/ver, but a frozen
|
|
190
|
+
// delta stream has no tenant or session to draw real values from — it's a synthetic
|
|
191
|
+
// in-process connection that never reaches a service. Inventing sentinel values would imply
|
|
192
|
+
// quorum membership we cannot honor; only `scopes` actually drives behavior here (DocRead vs
|
|
193
|
+
// DocWrite gates readOnlyInfo). The cast is the honest representation of "this connection
|
|
194
|
+
// has no claims worth populating."
|
|
195
|
+
/* eslint-disable @typescript-eslint/consistent-type-assertions */
|
|
196
|
+
const readOnlyClaims = { scopes: [internal_2.ScopeType.DocRead] };
|
|
197
|
+
const writableClaims = {
|
|
198
|
+
scopes: [internal_2.ScopeType.DocRead, internal_2.ScopeType.DocWrite],
|
|
199
|
+
};
|
|
200
|
+
/* eslint-enable @typescript-eslint/consistent-type-assertions */
|
|
93
201
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
202
|
+
* Inert `IDocumentDeltaConnection` for frozen container loads. Has no server upstream:
|
|
203
|
+
* op and signal streams are empty, and `initialClients` contains only its own synthetic
|
|
204
|
+
* read-only client — which lets the connection state handler observe "self" in the audience
|
|
205
|
+
* and transition the container to Connected without waiting for a real join op or signal.
|
|
206
|
+
*
|
|
207
|
+
* Two concrete variants share this base — see their JSDoc for variant-specific details:
|
|
208
|
+
*
|
|
209
|
+
* - {@link FrozenDeltaStream} — read-only.
|
|
210
|
+
* - {@link WritableFrozenDeltaStream} — writable.
|
|
211
|
+
*
|
|
212
|
+
* Both variants nack any incoming `submit`: this connection has no upstream and
|
|
213
|
+
* `ConnectionManager.sendMessages` recognizes `WritableFrozenDeltaStream` and drops messages
|
|
214
|
+
* before they reach `submit`, so under normal flow it should never fire. A nack reaching the
|
|
215
|
+
* connectionManager surfaces the misuse — and may close the container — which is the right
|
|
216
|
+
* defensive signal that something has bypassed the expected flow.
|
|
217
|
+
*
|
|
218
|
+
* `submitSignal` is a silent no-op for both variants. Signals are ephemeral and best-effort —
|
|
219
|
+
* runtime/presence subsystems may submit them at any point in the writable-frozen lifetime, and
|
|
220
|
+
* dropping them is the correct behavior here (we have no upstream). Closing the container or
|
|
221
|
+
* triggering a reconnect on a stray signal would be strictly worse than dropping it.
|
|
96
222
|
*/
|
|
97
|
-
class
|
|
98
|
-
|
|
99
|
-
* Connection which is not connected to socket.
|
|
100
|
-
* @param storageOnlyReason - Reason on why the connection to delta stream is not allowed.
|
|
101
|
-
* @param readonlyConnectionReason - reason/error if any which lead to using FrozenDeltaStream.
|
|
102
|
-
*/
|
|
103
|
-
constructor(storageOnlyReason, readonlyConnectionReason) {
|
|
223
|
+
class FrozenDeltaStreamBase extends client_utils_1.TypedEventEmitter {
|
|
224
|
+
constructor(clientId, claims) {
|
|
104
225
|
super();
|
|
105
|
-
this.storageOnlyReason = storageOnlyReason;
|
|
106
|
-
this.readonlyConnectionReason = readonlyConnectionReason;
|
|
107
|
-
this.clientId = clientIdFrozenDeltaStream;
|
|
108
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
109
|
-
this.claims = {
|
|
110
|
-
scopes: [internal_2.ScopeType.DocRead],
|
|
111
|
-
};
|
|
112
226
|
this.mode = "read";
|
|
113
227
|
this.existing = true;
|
|
114
228
|
this.maxMessageSize = 0;
|
|
115
229
|
this.version = "";
|
|
116
230
|
this.initialMessages = [];
|
|
117
231
|
this.initialSignals = [];
|
|
118
|
-
this.initialClients = [
|
|
119
|
-
{ client: clientFrozenDeltaStream, clientId: clientIdFrozenDeltaStream },
|
|
120
|
-
];
|
|
121
232
|
this.serviceConfiguration = {
|
|
122
233
|
maxMessageSize: 0,
|
|
123
234
|
blockSize: 0,
|
|
124
235
|
};
|
|
125
236
|
this.checkpointSequenceNumber = undefined;
|
|
126
237
|
this._disposed = false;
|
|
238
|
+
this.clientId = clientId;
|
|
239
|
+
this.claims = claims;
|
|
240
|
+
// initialClients mirrors clientId so the audience handler observes "self" and
|
|
241
|
+
// transitions the container to Connected without waiting for a real join op or signal.
|
|
242
|
+
this.initialClients = [{ client: clientFrozenDeltaStream, clientId }];
|
|
127
243
|
}
|
|
128
244
|
submit(messages) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
}));
|
|
135
|
-
}
|
|
136
|
-
submitSignal(
|
|
137
|
-
|
|
138
|
-
operation: message,
|
|
139
|
-
content: { message: "Cannot submit signal with storage-only connection", code: 403 },
|
|
140
|
-
});
|
|
245
|
+
// Defensive nack: nothing should send on a frozen delta stream. If this fires, an
|
|
246
|
+
// invariant in connectionManager has changed and we want it to surface loudly.
|
|
247
|
+
this.emit("nack", this.clientId, messages.map((operation) => ({
|
|
248
|
+
operation,
|
|
249
|
+
content: { message: "Cannot submit on a frozen delta stream", code: 403 },
|
|
250
|
+
})));
|
|
251
|
+
}
|
|
252
|
+
submitSignal(_message) {
|
|
253
|
+
// Intentional no-op. See class JSDoc for rationale.
|
|
141
254
|
}
|
|
142
255
|
get disposed() {
|
|
143
256
|
return this._disposed;
|
|
@@ -146,9 +259,74 @@ class FrozenDeltaStream extends client_utils_1.TypedEventEmitter {
|
|
|
146
259
|
this._disposed = true;
|
|
147
260
|
}
|
|
148
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Read-only variant of {@link FrozenDeltaStreamBase}. Claims show only `DocRead`. Used by
|
|
264
|
+
* storage-only loads (where `connectionManager` synthesizes one directly via
|
|
265
|
+
* `policies.storageOnly`) and by the forbidden / out-of-storage fallback paths.
|
|
266
|
+
* {@link isFrozenDeltaStreamConnection} matches this variant and drives the read-only forcing
|
|
267
|
+
* in `ConnectionManager.readOnlyInfo`. Uses the historical `"storage-only client"` constant
|
|
268
|
+
* `clientId`, preserving existing behavior for any consumer that keys off it.
|
|
269
|
+
*
|
|
270
|
+
* `storageOnlyReason` and `readonlyConnectionReason` are surfaced through `IContainer.readOnlyInfo`
|
|
271
|
+
* for diagnostics on the fallback paths (`isDeltaStreamConnectionForbiddenError`,
|
|
272
|
+
* `outOfStorageError`).
|
|
273
|
+
*/
|
|
274
|
+
class FrozenDeltaStream extends FrozenDeltaStreamBase {
|
|
275
|
+
constructor(options) {
|
|
276
|
+
// Constant clientId: preserves the pre-PR `"storage-only client"` identity for any
|
|
277
|
+
// consumer that keys off it. The 0x173 replay-assert risk that motivates per-instance
|
|
278
|
+
// clientIds applies only to the writable variant, where the runtime accumulates dirty
|
|
279
|
+
// pending ops across reconnects; the read-only variant does not.
|
|
280
|
+
super(clientIdFrozenDeltaStream, readOnlyClaims);
|
|
281
|
+
this.storageOnlyReason = options?.storageOnlyReason;
|
|
282
|
+
this.readonlyConnectionReason = options?.readonlyConnectionReason;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
149
285
|
exports.FrozenDeltaStream = FrozenDeltaStream;
|
|
286
|
+
/**
|
|
287
|
+
* Variant of {@link FrozenDeltaStreamBase} that appears to support writing but remains
|
|
288
|
+
* "frozen" — no messages are actually sent or received. The stream itself does not enforce
|
|
289
|
+
* the no-send guarantee; that lives in `ConnectionManager.sendMessages`, which recognizes
|
|
290
|
+
* any `WritableFrozenDeltaStream` (via {@link isWritableFrozenDeltaStreamConnection}) and
|
|
291
|
+
* short-circuits before its read-mode upgrade branch. Submitted ops are dropped at the
|
|
292
|
+
* connection-manager layer, so the container stays `Connected` and the runtime accumulates
|
|
293
|
+
* them in `pendingStateManager`.
|
|
294
|
+
*
|
|
295
|
+
* "Appears writable" mechanics: claims include `DocWrite` so the container surfaces as
|
|
296
|
+
* writable; not matched by {@link isFrozenDeltaStreamConnection}, so `readOnlyInfo` reports
|
|
297
|
+
* `readonly: false`. Connection mode stays `"read"` (advertising `"write"` would imply quorum
|
|
298
|
+
* membership we cannot honor).
|
|
299
|
+
*
|
|
300
|
+
* Each instance mints a fresh `frozen-delta-stream/<uuid>` `clientId` to avoid
|
|
301
|
+
* `pendingStateManager` `0x173` (`replayPendingStates called twice for same clientId!`) on
|
|
302
|
+
* reconnect with dirty pending ops. Sibling (not subclass) of `FrozenDeltaStream` so
|
|
303
|
+
* `instanceof` cleanly distinguishes the two for `ConnectionManager`'s short-circuits.
|
|
304
|
+
*/
|
|
305
|
+
class WritableFrozenDeltaStream extends FrozenDeltaStreamBase {
|
|
306
|
+
constructor() {
|
|
307
|
+
super(`frozen-delta-stream/${(0, uuid_1.v4)()}`, writableClaims);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
exports.WritableFrozenDeltaStream = WritableFrozenDeltaStream;
|
|
311
|
+
/**
|
|
312
|
+
* Recognizes the read-only variant of {@link FrozenDeltaStreamBase}. Drives the storage-only
|
|
313
|
+
* forcing in `ConnectionManager.readOnlyInfo`: only the read-only variant should make the
|
|
314
|
+
* container surface as read-only. {@link WritableFrozenDeltaStream} is a sibling class, not
|
|
315
|
+
* a subclass, so `instanceof FrozenDeltaStream` already excludes it.
|
|
316
|
+
*/
|
|
150
317
|
function isFrozenDeltaStreamConnection(connection) {
|
|
151
318
|
return connection instanceof FrozenDeltaStream;
|
|
152
319
|
}
|
|
153
320
|
exports.isFrozenDeltaStreamConnection = isFrozenDeltaStreamConnection;
|
|
321
|
+
/**
|
|
322
|
+
* Recognizes the writable variant of {@link FrozenDeltaStreamBase}. Drives the
|
|
323
|
+
* `ConnectionManager.sendMessages` short-circuit: writable-frozen submits must be dropped at
|
|
324
|
+
* the network layer instead of triggering a read→write reconnect. Sibling (not subclass) of
|
|
325
|
+
* {@link FrozenDeltaStream}, so `instanceof WritableFrozenDeltaStream` excludes the read-only
|
|
326
|
+
* variant.
|
|
327
|
+
*/
|
|
328
|
+
function isWritableFrozenDeltaStreamConnection(connection) {
|
|
329
|
+
return connection instanceof WritableFrozenDeltaStream;
|
|
330
|
+
}
|
|
331
|
+
exports.isWritableFrozenDeltaStreamConnection = isWritableFrozenDeltaStreamConnection;
|
|
154
332
|
//# sourceMappingURL=frozenServices.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frozenServices.js","sourceRoot":"","sources":["../src/frozenServices.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { isPromiseLike } from \"@fluidframework/core-utils/internal\";\nimport {\n\tScopeType,\n\ttype ConnectionMode,\n\ttype IClient,\n\ttype IClientConfiguration,\n\ttype IDocumentDeltaConnection,\n\ttype IDocumentDeltaConnectionEvents,\n\ttype IDocumentDeltaStorageService,\n\ttype IDocumentMessage,\n\ttype IDocumentService,\n\ttype IDocumentServiceEvents,\n\ttype IDocumentServiceFactory,\n\ttype IDocumentServicePolicies,\n\ttype IDocumentStorageService,\n\ttype IResolvedUrl,\n\ttype ISequencedDocumentMessage,\n\ttype ISignalClient,\n\ttype ISignalMessage,\n\ttype ITokenClaims,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { IConnectionStateChangeReason } from \"./contracts.js\";\n\n/**\n * Creation of a FrozenDocumentServiceFactory which wraps an existing\n * DocumentServiceFactory to provide a storage-only document service.\n *\n * @param documentServiceFactory - The underlying DocumentServiceFactory to wrap.\n * @returns A FrozenDocumentServiceFactory\n * @legacy @alpha\n */\nexport function createFrozenDocumentServiceFactory(\n\tfactory?: IDocumentServiceFactory | Promise<IDocumentServiceFactory>,\n): IDocumentServiceFactory {\n\t// Sync path\n\treturn factory instanceof FrozenDocumentServiceFactory\n\t\t? factory\n\t\t: new FrozenDocumentServiceFactory(factory);\n}\n\nexport class FrozenDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tprivate readonly documentServiceFactory?:\n\t\t\t| IDocumentServiceFactory\n\t\t\t| Promise<IDocumentServiceFactory>,\n\t) {}\n\n\tasync createDocumentService(resolvedUrl: IResolvedUrl): Promise<IDocumentService> {\n\t\tlet factory = this.documentServiceFactory;\n\t\tif (isPromiseLike(factory)) {\n\t\t\tfactory = await this.documentServiceFactory;\n\t\t}\n\t\treturn new FrozenDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tawait factory?.createDocumentService(resolvedUrl),\n\t\t);\n\t}\n\tasync createContainer(): Promise<IDocumentService> {\n\t\tthrow new Error(\"The FrozenDocumentServiceFactory cannot be used to create containers.\");\n\t}\n}\n\nclass FrozenDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly documentService?: IDocumentService,\n\t) {\n\t\tsuper();\n\t}\n\n\tpublic readonly policies: IDocumentServicePolicies = {\n\t\tstorageOnly: true,\n\t};\n\tasync connectToStorage(): Promise<IDocumentStorageService> {\n\t\treturn new FrozenDocumentStorageService(await this.documentService?.connectToStorage());\n\t}\n\tasync connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn frozenDocumentDeltaStorageService;\n\t}\n\tasync connectToDeltaStream(client: IClient): Promise<IDocumentDeltaConnection> {\n\t\treturn new FrozenDeltaStream();\n\t}\n\tdispose(): void {}\n}\n\nconst frozenDocumentStorageServiceHandler = (): never => {\n\tthrow new Error(\"Operations are not supported on the FrozenDocumentStorageService.\");\n};\nclass FrozenDocumentStorageService implements IDocumentStorageService {\n\tconstructor(private readonly documentStorageService?: IDocumentStorageService) {}\n\n\tgetSnapshotTree = frozenDocumentStorageServiceHandler;\n\tgetSnapshot = frozenDocumentStorageServiceHandler;\n\tgetVersions = frozenDocumentStorageServiceHandler;\n\tcreateBlob = frozenDocumentStorageServiceHandler;\n\treadBlob =\n\t\tthis.documentStorageService?.readBlob.bind(this.documentStorageService) ??\n\t\tfrozenDocumentStorageServiceHandler;\n\tuploadSummaryWithContext = frozenDocumentStorageServiceHandler;\n\tdownloadSummary = frozenDocumentStorageServiceHandler;\n}\n\nconst frozenDocumentDeltaStorageService: IDocumentDeltaStorageService = {\n\tfetchMessages: () => ({\n\t\tread: async () => ({\n\t\t\tdone: true,\n\t\t}),\n\t}),\n};\n\nconst clientFrozenDeltaStream: IClient = {\n\tmode: \"read\",\n\tdetails: { capabilities: { interactive: true } },\n\tpermission: [],\n\tuser: { id: \"storage-only client\" }, // we need some \"fake\" ID here.\n\tscopes: [],\n};\nconst clientIdFrozenDeltaStream: string = \"storage-only client\";\n\n/**\n * Implementation of IDocumentDeltaConnection that does not support submitting\n * or receiving ops. Used in storage-only mode and in frozen loads.\n */\nexport class FrozenDeltaStream\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\tclientId = clientIdFrozenDeltaStream;\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tclaims = {\n\t\tscopes: [ScopeType.DocRead],\n\t} as ITokenClaims;\n\tmode: ConnectionMode = \"read\";\n\texisting: boolean = true;\n\tmaxMessageSize: number = 0;\n\tversion: string = \"\";\n\tinitialMessages: ISequencedDocumentMessage[] = [];\n\tinitialSignals: ISignalMessage[] = [];\n\tinitialClients: ISignalClient[] = [\n\t\t{ client: clientFrozenDeltaStream, clientId: clientIdFrozenDeltaStream },\n\t];\n\tserviceConfiguration: IClientConfiguration = {\n\t\tmaxMessageSize: 0,\n\t\tblockSize: 0,\n\t};\n\tcheckpointSequenceNumber?: number | undefined = undefined;\n\t/**\n\t * Connection which is not connected to socket.\n\t * @param storageOnlyReason - Reason on why the connection to delta stream is not allowed.\n\t * @param readonlyConnectionReason - reason/error if any which lead to using FrozenDeltaStream.\n\t */\n\tconstructor(\n\t\tpublic readonly storageOnlyReason?: string,\n\t\tpublic readonly readonlyConnectionReason?: IConnectionStateChangeReason,\n\t) {\n\t\tsuper();\n\t}\n\tsubmit(messages: IDocumentMessage[]): void {\n\t\tthis.emit(\n\t\t\t\"nack\",\n\t\t\tthis.clientId,\n\t\t\tmessages.map((operation) => {\n\t\t\t\treturn {\n\t\t\t\t\toperation,\n\t\t\t\t\tcontent: { message: \"Cannot submit with storage-only connection\", code: 403 },\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t}\n\tsubmitSignal(message: unknown): void {\n\t\tthis.emit(\"nack\", this.clientId, {\n\t\t\toperation: message,\n\t\t\tcontent: { message: \"Cannot submit signal with storage-only connection\", code: 403 },\n\t\t});\n\t}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\nexport function isFrozenDeltaStreamConnection(\n\tconnection: unknown,\n): connection is FrozenDeltaStream {\n\treturn connection instanceof FrozenDeltaStream;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"frozenServices.js","sourceRoot":"","sources":["../src/frozenServices.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { isPromiseLike } from \"@fluidframework/core-utils/internal\";\nimport {\n\tScopeType,\n\ttype ConnectionMode,\n\ttype IClient,\n\ttype IClientConfiguration,\n\ttype IDocumentDeltaConnection,\n\ttype IDocumentDeltaConnectionEvents,\n\ttype IDocumentDeltaStorageService,\n\ttype IDocumentMessage,\n\ttype IDocumentService,\n\ttype IDocumentServiceEvents,\n\ttype IDocumentServiceFactory,\n\ttype IDocumentServicePolicies,\n\ttype IDocumentStorageService,\n\ttype IResolvedUrl,\n\ttype ISequencedDocumentMessage,\n\ttype ISignalClient,\n\ttype ISignalMessage,\n\ttype ITokenClaims,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport type { IConnectionStateChangeReason } from \"./contracts.js\";\n\n/**\n * Creates an `IDocumentServiceFactory` that produces a \"frozen\" document service: one whose\n * delta stream never sends or receives ops, and whose storage service only supports\n * `IDocumentStorageService.readBlob`. Used to load a container from pending local state\n * without re-establishing a live connection.\n *\n * @param factory - The underlying factory to wrap. Its storage backs blob reads; all other\n * storage operations throw. May be omitted when blob fetches are not required.\n * @param readOnly - When `true` (the default), the document service advertises the\n * `IDocumentServicePolicies.storageOnly` policy, which causes the loader to surface the\n * container as read-only (see `IContainer.readOnlyInfo`).\n *\n * When `false`, the container is loaded as writable so the runtime will accept DDS submissions.\n * The connection itself stays `Connected`: `ConnectionManager.sendMessages` recognizes the\n * `WritableFrozenDeltaStream` as the live connection and short-circuits — the message is dropped\n * at the network layer rather than triggering a read→write reconnect. Local DDS state continues\n * to update via optimistic apply, and submitted ops accumulate in the runtime's pending-state\n * manager, which is exactly the state needed to capture pending local state. Use `false` when\n * callers want to accrue and capture pending state without publishing it.\n * @returns A factory that produces frozen document services.\n * @legacy @alpha\n */\nexport function createFrozenDocumentServiceFactory(\n\tfactory?: IDocumentServiceFactory | Promise<IDocumentServiceFactory>,\n\treadOnly: boolean = true,\n): IDocumentServiceFactory {\n\tif (factory instanceof FrozenDocumentServiceFactory) {\n\t\t// Already wrapped. Reuse if readOnly matches; otherwise unwrap and rewrap so the caller's\n\t\t// most recent readOnly intent wins (silently honoring caller intent rather than dropping\n\t\t// the new argument).\n\t\treturn factory.readOnly === readOnly\n\t\t\t? factory\n\t\t\t: new FrozenDocumentServiceFactory(readOnly, factory.inner);\n\t}\n\treturn new FrozenDocumentServiceFactory(readOnly, factory);\n}\n\nexport class FrozenDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tpublic readonly readOnly: boolean,\n\t\tpublic readonly inner?: IDocumentServiceFactory | Promise<IDocumentServiceFactory>,\n\t) {}\n\n\tasync createDocumentService(resolvedUrl: IResolvedUrl): Promise<IDocumentService> {\n\t\tconst factory = isPromiseLike(this.inner) ? await this.inner : this.inner;\n\t\treturn new FrozenDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tthis.readOnly,\n\t\t\tawait factory?.createDocumentService(resolvedUrl),\n\t\t);\n\t}\n\tasync createContainer(): Promise<IDocumentService> {\n\t\tthrow new Error(\"The FrozenDocumentServiceFactory cannot be used to create containers.\");\n\t}\n}\n\nclass FrozenDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\t// Tracks every storage instance handed out by `connectToStorage` so `dispose()` can cascade\n\t// disposal to each one (rejecting their hanging `createBlob` deferreds). A Set rather than\n\t// a single field because `IDocumentService.connectToStorage` is a public API that can be\n\t// called more than once — we cannot assume the Container holds a single instance.\n\tprivate readonly storageServices = new Set<FrozenDocumentStorageService>();\n\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly readOnly: boolean,\n\t\tprivate readonly documentService?: IDocumentService,\n\t) {\n\t\tsuper();\n\t\t// When readOnly, advertise the storageOnly policy. The connectionManager short-circuits\n\t\t// on it: it synthesizes a FrozenDeltaStream itself and never calls\n\t\t// connectToDeltaStream, and the readOnlyInfo getter forces the container to read-only\n\t\t// because the live connection is a FrozenDeltaStream.\n\t\t//\n\t\t// Audit (2026-05-05): the only consumer of `policies.storageOnly` as a frozen-container\n\t\t// signal is `ConnectionManager` (synthesizing a `FrozenDeltaStream` when set). All other\n\t\t// matches in the loader/runtime/driver layers are either drivers reading their own\n\t\t// policies (e.g. local-driver) or `IReadOnlyInfo.storageOnly`, which is derived from the\n\t\t// live connection — not the policy. So the writable-frozen container is intentionally\n\t\t// indistinguishable from a normal container at the policies layer; downstream behavior\n\t\t// flows through the live `WritableFrozenDeltaStream` instead.\n\t\tthis.policies = readOnly ? { storageOnly: true } : {};\n\t}\n\n\tpublic readonly policies: IDocumentServicePolicies;\n\tasync connectToStorage(): Promise<IDocumentStorageService> {\n\t\tconst storage = new FrozenDocumentStorageService(\n\t\t\tthis.readOnly,\n\t\t\tawait this.documentService?.connectToStorage(),\n\t\t);\n\t\tthis.storageServices.add(storage);\n\t\treturn storage;\n\t}\n\tasync connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn frozenDocumentDeltaStorageService;\n\t}\n\tasync connectToDeltaStream(_client: IClient): Promise<IDocumentDeltaConnection> {\n\t\tif (this.readOnly) {\n\t\t\t// connectionManager short-circuits via policies.storageOnly before reaching here\n\t\t\t// in the read-only path; reaching this branch indicates a non-connectionManager\n\t\t\t// consumer or a regression of the short-circuit. Throw to surface the misuse\n\t\t\t// rather than silently produce a working stream.\n\t\t\tthrow new Error(\n\t\t\t\t\"FrozenDocumentService is read-only; connectToDeltaStream should not be called (connectionManager short-circuits via policies.storageOnly)\",\n\t\t\t);\n\t\t}\n\t\t// Writable path: hand out a fresh WritableFrozenDeltaStream regardless of client.mode\n\t\t// or whether this is the initial connect or a reconnect. The stream's own mode is\n\t\t// \"read\" (advertising \"write\" would imply quorum membership we cannot honor), and\n\t\t// `ConnectionManager.sendMessages` short-circuits on WritableFrozenDeltaStream so\n\t\t// outbound writes never reach a real network. The per-instance clientId minted in\n\t\t// FrozenDeltaStreamBase prevents pendingStateManager 0x173 on replay across reconnects.\n\t\treturn new WritableFrozenDeltaStream();\n\t}\n\tdispose(error?: unknown): void {\n\t\t// Cascade disposal to each storage instance so any hanging `createBlob` promises (the\n\t\t// writable-frozen pending-blob mechanism) reject and the BlobManager can release its\n\t\t// references. Without this, hung promises remain held by BlobManager closures for the\n\t\t// lifetime of the process.\n\t\tfor (const storage of this.storageServices) {\n\t\t\tstorage.dispose();\n\t\t}\n\t\tthis.storageServices.clear();\n\t\t// Forward disposal to the wrapped service. We own its lifetime (it was created for us\n\t\t// by the wrapping factory and is never exposed to callers), so the contract from\n\t\t// `IDocumentService.dispose` (\"called by storage consumer when done with storage\")\n\t\t// applies here.\n\t\tthis.documentService?.dispose(error);\n\t}\n}\n\nconst frozenDocumentStorageServiceHandler = (): never => {\n\tthrow new Error(\"Operations are not supported on the FrozenDocumentStorageService.\");\n};\n\nclass FrozenDocumentStorageService implements IDocumentStorageService, IDisposable {\n\t// Single deferred shared by every in-flight `createBlob` call. The writable-frozen\n\t// `createBlob` returns this promise so the BlobManager keeps the blob in `uploading`\n\t// state (see comment in the constructor). Rejecting the deferred on disposal fans the\n\t// rejection out to every awaiter at once — and to any future `createBlob` calls too,\n\t// since they receive the already-rejected promise.\n\tprivate readonly disposalDeferred: {\n\t\treadonly promise: Promise<never>;\n\t\treadonly reject: (error: Error) => void;\n\t};\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\n\tconstructor(\n\t\treadOnly: boolean,\n\t\tprivate readonly documentStorageService?: IDocumentStorageService,\n\t) {\n\t\tlet rejectFn!: (error: Error) => void;\n\t\tconst promise = new Promise<never>((_, reject) => {\n\t\t\trejectFn = reject;\n\t\t});\n\t\t// Attach a no-op catch so node doesn't log an unhandled-rejection warning when\n\t\t// dispose runs before any caller has awaited the promise. Callers awaiting the\n\t\t// original promise still observe the rejection.\n\t\tpromise.catch(() => {});\n\t\tthis.disposalDeferred = { promise, reject: rejectFn };\n\n\t\t// In the writable-frozen path, `createBlob` returns a never-resolving promise instead\n\t\t// of throwing. This keeps the BlobManager's `localBlobCache` entry in the `uploading`\n\t\t// state: `getPendingBlobs` downgrades `uploading` blobs to `localOnly` in pending\n\t\t// state, so the blob survives `getPendingLocalState`. A subsequent live load runs\n\t\t// `sharePendingBlobs`, which re-enters `uploadAndAttach` against the real storage to\n\t\t// complete the upload. Throwing here would instead delete the cache entry (in\n\t\t// `uploadAndAttach`'s catch handler) and lose the blob — defeating the whole point of\n\t\t// accruing pending state.\n\t\tthis.createBlob = readOnly\n\t\t\t? frozenDocumentStorageServiceHandler\n\t\t\t: async () => this.disposalDeferred.promise;\n\t}\n\n\tgetSnapshotTree = frozenDocumentStorageServiceHandler;\n\tgetSnapshot = frozenDocumentStorageServiceHandler;\n\tgetVersions = frozenDocumentStorageServiceHandler;\n\tcreateBlob: IDocumentStorageService[\"createBlob\"];\n\treadBlob =\n\t\tthis.documentStorageService?.readBlob.bind(this.documentStorageService) ??\n\t\tfrozenDocumentStorageServiceHandler;\n\tuploadSummaryWithContext = frozenDocumentStorageServiceHandler;\n\tdownloadSummary = frozenDocumentStorageServiceHandler;\n\n\tpublic dispose(): void {\n\t\tif (this._disposed) {\n\t\t\treturn;\n\t\t}\n\t\tthis._disposed = true;\n\t\t// Don't propagate any caller-supplied error here. `IDocumentService.dispose` already\n\t\t// logs the Container's error path; the createBlob deferred's consumer (BlobManager)\n\t\t// only needs the \"this storage is going away\" signal — not a chain of error causes.\n\t\tthis.disposalDeferred.reject(new Error(\"FrozenDocumentStorageService is disposed\"));\n\t}\n}\n\nconst frozenDocumentDeltaStorageService: IDocumentDeltaStorageService = {\n\tfetchMessages: () => ({\n\t\tread: async () => ({\n\t\t\tdone: true,\n\t\t}),\n\t}),\n};\n\nconst clientFrozenDeltaStream: IClient = {\n\tmode: \"read\",\n\tdetails: { capabilities: { interactive: true } },\n\tpermission: [],\n\tuser: { id: \"storage-only client\" }, // we need some \"fake\" ID here.\n\tscopes: [],\n};\n\nconst clientIdFrozenDeltaStream: string = \"storage-only client\";\n\n// Cast rationale: ITokenClaims requires tenantId/documentId/user/iat/exp/ver, but a frozen\n// delta stream has no tenant or session to draw real values from — it's a synthetic\n// in-process connection that never reaches a service. Inventing sentinel values would imply\n// quorum membership we cannot honor; only `scopes` actually drives behavior here (DocRead vs\n// DocWrite gates readOnlyInfo). The cast is the honest representation of \"this connection\n// has no claims worth populating.\"\n/* eslint-disable @typescript-eslint/consistent-type-assertions */\nconst readOnlyClaims: ITokenClaims = { scopes: [ScopeType.DocRead] } as ITokenClaims;\nconst writableClaims: ITokenClaims = {\n\tscopes: [ScopeType.DocRead, ScopeType.DocWrite],\n} as ITokenClaims;\n/* eslint-enable @typescript-eslint/consistent-type-assertions */\n\n/**\n * Inert `IDocumentDeltaConnection` for frozen container loads. Has no server upstream:\n * op and signal streams are empty, and `initialClients` contains only its own synthetic\n * read-only client — which lets the connection state handler observe \"self\" in the audience\n * and transition the container to Connected without waiting for a real join op or signal.\n *\n * Two concrete variants share this base — see their JSDoc for variant-specific details:\n *\n * - {@link FrozenDeltaStream} — read-only.\n * - {@link WritableFrozenDeltaStream} — writable.\n *\n * Both variants nack any incoming `submit`: this connection has no upstream and\n * `ConnectionManager.sendMessages` recognizes `WritableFrozenDeltaStream` and drops messages\n * before they reach `submit`, so under normal flow it should never fire. A nack reaching the\n * connectionManager surfaces the misuse — and may close the container — which is the right\n * defensive signal that something has bypassed the expected flow.\n *\n * `submitSignal` is a silent no-op for both variants. Signals are ephemeral and best-effort —\n * runtime/presence subsystems may submit them at any point in the writable-frozen lifetime, and\n * dropping them is the correct behavior here (we have no upstream). Closing the container or\n * triggering a reconnect on a stray signal would be strictly worse than dropping it.\n */\nabstract class FrozenDeltaStreamBase\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\tpublic readonly clientId: string;\n\tpublic readonly claims: ITokenClaims;\n\tpublic readonly initialClients: ISignalClient[];\n\tpublic readonly mode: ConnectionMode = \"read\";\n\tpublic readonly existing: boolean = true;\n\tpublic readonly maxMessageSize: number = 0;\n\tpublic readonly version: string = \"\";\n\tpublic readonly initialMessages: ISequencedDocumentMessage[] = [];\n\tpublic readonly initialSignals: ISignalMessage[] = [];\n\tpublic readonly serviceConfiguration: IClientConfiguration = {\n\t\tmaxMessageSize: 0,\n\t\tblockSize: 0,\n\t};\n\tpublic readonly checkpointSequenceNumber?: number | undefined = undefined;\n\n\tconstructor(clientId: string, claims: ITokenClaims) {\n\t\tsuper();\n\t\tthis.clientId = clientId;\n\t\tthis.claims = claims;\n\t\t// initialClients mirrors clientId so the audience handler observes \"self\" and\n\t\t// transitions the container to Connected without waiting for a real join op or signal.\n\t\tthis.initialClients = [{ client: clientFrozenDeltaStream, clientId }];\n\t}\n\n\tsubmit(messages: IDocumentMessage[]): void {\n\t\t// Defensive nack: nothing should send on a frozen delta stream. If this fires, an\n\t\t// invariant in connectionManager has changed and we want it to surface loudly.\n\t\tthis.emit(\n\t\t\t\"nack\",\n\t\t\tthis.clientId,\n\t\t\tmessages.map((operation) => ({\n\t\t\t\toperation,\n\t\t\t\tcontent: { message: \"Cannot submit on a frozen delta stream\", code: 403 },\n\t\t\t})),\n\t\t);\n\t}\n\n\tsubmitSignal(_message: unknown): void {\n\t\t// Intentional no-op. See class JSDoc for rationale.\n\t}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\n\n/**\n * Read-only variant of {@link FrozenDeltaStreamBase}. Claims show only `DocRead`. Used by\n * storage-only loads (where `connectionManager` synthesizes one directly via\n * `policies.storageOnly`) and by the forbidden / out-of-storage fallback paths.\n * {@link isFrozenDeltaStreamConnection} matches this variant and drives the read-only forcing\n * in `ConnectionManager.readOnlyInfo`. Uses the historical `\"storage-only client\"` constant\n * `clientId`, preserving existing behavior for any consumer that keys off it.\n *\n * `storageOnlyReason` and `readonlyConnectionReason` are surfaced through `IContainer.readOnlyInfo`\n * for diagnostics on the fallback paths (`isDeltaStreamConnectionForbiddenError`,\n * `outOfStorageError`).\n */\nexport class FrozenDeltaStream extends FrozenDeltaStreamBase {\n\tpublic readonly storageOnlyReason: string | undefined;\n\tpublic readonly readonlyConnectionReason: IConnectionStateChangeReason | undefined;\n\n\tconstructor(options?: {\n\t\tstorageOnlyReason?: string;\n\t\treadonlyConnectionReason?: IConnectionStateChangeReason;\n\t}) {\n\t\t// Constant clientId: preserves the pre-PR `\"storage-only client\"` identity for any\n\t\t// consumer that keys off it. The 0x173 replay-assert risk that motivates per-instance\n\t\t// clientIds applies only to the writable variant, where the runtime accumulates dirty\n\t\t// pending ops across reconnects; the read-only variant does not.\n\t\tsuper(clientIdFrozenDeltaStream, readOnlyClaims);\n\t\tthis.storageOnlyReason = options?.storageOnlyReason;\n\t\tthis.readonlyConnectionReason = options?.readonlyConnectionReason;\n\t}\n}\n\n/**\n * Variant of {@link FrozenDeltaStreamBase} that appears to support writing but remains\n * \"frozen\" — no messages are actually sent or received. The stream itself does not enforce\n * the no-send guarantee; that lives in `ConnectionManager.sendMessages`, which recognizes\n * any `WritableFrozenDeltaStream` (via {@link isWritableFrozenDeltaStreamConnection}) and\n * short-circuits before its read-mode upgrade branch. Submitted ops are dropped at the\n * connection-manager layer, so the container stays `Connected` and the runtime accumulates\n * them in `pendingStateManager`.\n *\n * \"Appears writable\" mechanics: claims include `DocWrite` so the container surfaces as\n * writable; not matched by {@link isFrozenDeltaStreamConnection}, so `readOnlyInfo` reports\n * `readonly: false`. Connection mode stays `\"read\"` (advertising `\"write\"` would imply quorum\n * membership we cannot honor).\n *\n * Each instance mints a fresh `frozen-delta-stream/<uuid>` `clientId` to avoid\n * `pendingStateManager` `0x173` (`replayPendingStates called twice for same clientId!`) on\n * reconnect with dirty pending ops. Sibling (not subclass) of `FrozenDeltaStream` so\n * `instanceof` cleanly distinguishes the two for `ConnectionManager`'s short-circuits.\n */\nexport class WritableFrozenDeltaStream extends FrozenDeltaStreamBase {\n\tconstructor() {\n\t\tsuper(`frozen-delta-stream/${uuid()}`, writableClaims);\n\t}\n}\n\n/**\n * Recognizes the read-only variant of {@link FrozenDeltaStreamBase}. Drives the storage-only\n * forcing in `ConnectionManager.readOnlyInfo`: only the read-only variant should make the\n * container surface as read-only. {@link WritableFrozenDeltaStream} is a sibling class, not\n * a subclass, so `instanceof FrozenDeltaStream` already excludes it.\n */\nexport function isFrozenDeltaStreamConnection(\n\tconnection: unknown,\n): connection is FrozenDeltaStream {\n\treturn connection instanceof FrozenDeltaStream;\n}\n\n/**\n * Recognizes the writable variant of {@link FrozenDeltaStreamBase}. Drives the\n * `ConnectionManager.sendMessages` short-circuit: writable-frozen submits must be dropped at\n * the network layer instead of triggering a read→write reconnect. Sibling (not subclass) of\n * {@link FrozenDeltaStream}, so `instanceof WritableFrozenDeltaStream` excludes the read-only\n * variant.\n */\nexport function isWritableFrozenDeltaStreamConnection(\n\tconnection: unknown,\n): connection is WritableFrozenDeltaStream {\n\treturn connection instanceof WritableFrozenDeltaStream;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
export { ConnectionState } from "./connectionState.js";
|
|
6
6
|
export { type ContainerAlpha, waitContainerToCatchUp, asLegacyAlpha } from "./container.js";
|
|
7
7
|
export { createFrozenDocumentServiceFactory } from "./frozenServices.js";
|
|
8
|
-
export { createDetachedContainer, loadExistingContainer, rehydrateDetachedContainer, loadFrozenContainerFromPendingState, loadSummarizerContainerAndMakeSummary, type ICreateAndLoadContainerProps, type ICreateDetachedContainerProps, type ILoadExistingContainerProps, type ILoadSummarizerContainerProps, type IRehydrateDetachedContainerProps, type ILoadFrozenContainerFromPendingStateProps, } from "./createAndLoadContainerUtils.js";
|
|
8
|
+
export { captureFullContainerState, createDetachedContainer, loadExistingContainer, rehydrateDetachedContainer, loadFrozenContainerFromPendingState, loadSummarizerContainerAndMakeSummary, type ICaptureFullContainerStateProps, type ICreateAndLoadContainerProps, type ICreateDetachedContainerProps, type ILoadExistingContainerProps, type ILoadSummarizerContainerProps, type IRehydrateDetachedContainerProps, type ILoadFrozenContainerFromPendingStateProps, } from "./createAndLoadContainerUtils.js";
|
|
9
9
|
export type { LoadSummarizerSummaryResult, OnDemandSummaryResults, SummaryStage, } from "./summarizerResultTypes.js";
|
|
10
10
|
export { type ICodeDetailsLoader, type IFluidModuleWithDetails, type ILoaderProps, type ILoaderServices, Loader, } from "./loader.js";
|
|
11
11
|
export { driverSupportRequirementsForLoader, loaderCoreCompatDetails, runtimeSupportRequirementsForLoader, loaderCompatDetailsForRuntime, } from "./loaderLayerCompatState.js";
|
|
@@ -15,4 +15,5 @@ export type { IProtocolHandler, ProtocolHandlerBuilder } from "./protocol.js";
|
|
|
15
15
|
export { tryParseCompatibleResolvedUrl, type IParsedUrl, } from "./utils.js";
|
|
16
16
|
export type { IBaseProtocolHandler, IScribeProtocolState, IQuorumSnapshot, QuorumClientsSnapshot, QuorumProposalsSnapshot, } from "./protocol/index.js";
|
|
17
17
|
export { PendingLocalStateStore } from "./pendingLocalStateStore.js";
|
|
18
|
+
export { extractBlobAttachReferences, wireFormatConstants, type IBlobAttachReference, } from "./captureReferencedContents.js";
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACN,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,mCAAmC,EACnC,qCAAqC,EACrC,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EACrC,KAAK,yCAAyC,GAC9C,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACX,2BAA2B,EAC3B,sBAAsB,EACtB,YAAY,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,kCAAkC,EAClC,uBAAuB,EACvB,mCAAmC,EACnC,6BAA6B,GAC7B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EACN,0BAA0B,EAC1B,sCAAsC,GACtC,MAAM,2CAA2C,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EACN,6BAA6B,EAC7B,KAAK,UAAU,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACN,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,mCAAmC,EACnC,qCAAqC,EACrC,KAAK,+BAA+B,EACpC,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EACrC,KAAK,yCAAyC,GAC9C,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACX,2BAA2B,EAC3B,sBAAsB,EACtB,YAAY,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,kCAAkC,EAClC,uBAAuB,EACvB,mCAAmC,EACnC,6BAA6B,GAC7B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EACN,0BAA0B,EAC1B,sCAAsC,GACtC,MAAM,2CAA2C,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EACN,6BAA6B,EAC7B,KAAK,UAAU,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACN,2BAA2B,EAC3B,mBAAmB,EACnB,KAAK,oBAAoB,GACzB,MAAM,gCAAgC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.PendingLocalStateStore = exports.tryParseCompatibleResolvedUrl = exports.resolveWithLocationRedirectionHandling = exports.isLocationRedirectionError = exports.loadContainerPaused = exports.loaderCompatDetailsForRuntime = exports.runtimeSupportRequirementsForLoader = exports.loaderCoreCompatDetails = exports.driverSupportRequirementsForLoader = exports.Loader = exports.loadSummarizerContainerAndMakeSummary = exports.loadFrozenContainerFromPendingState = exports.rehydrateDetachedContainer = exports.loadExistingContainer = exports.createDetachedContainer = exports.createFrozenDocumentServiceFactory = exports.asLegacyAlpha = exports.waitContainerToCatchUp = exports.ConnectionState = void 0;
|
|
7
|
+
exports.wireFormatConstants = exports.extractBlobAttachReferences = exports.PendingLocalStateStore = exports.tryParseCompatibleResolvedUrl = exports.resolveWithLocationRedirectionHandling = exports.isLocationRedirectionError = exports.loadContainerPaused = exports.loaderCompatDetailsForRuntime = exports.runtimeSupportRequirementsForLoader = exports.loaderCoreCompatDetails = exports.driverSupportRequirementsForLoader = exports.Loader = exports.loadSummarizerContainerAndMakeSummary = exports.loadFrozenContainerFromPendingState = exports.rehydrateDetachedContainer = exports.loadExistingContainer = exports.createDetachedContainer = exports.captureFullContainerState = exports.createFrozenDocumentServiceFactory = exports.asLegacyAlpha = exports.waitContainerToCatchUp = exports.ConnectionState = void 0;
|
|
8
8
|
var connectionState_js_1 = require("./connectionState.js");
|
|
9
9
|
Object.defineProperty(exports, "ConnectionState", { enumerable: true, get: function () { return connectionState_js_1.ConnectionState; } });
|
|
10
10
|
var container_js_1 = require("./container.js");
|
|
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "asLegacyAlpha", { enumerable: true, get: functio
|
|
|
13
13
|
var frozenServices_js_1 = require("./frozenServices.js");
|
|
14
14
|
Object.defineProperty(exports, "createFrozenDocumentServiceFactory", { enumerable: true, get: function () { return frozenServices_js_1.createFrozenDocumentServiceFactory; } });
|
|
15
15
|
var createAndLoadContainerUtils_js_1 = require("./createAndLoadContainerUtils.js");
|
|
16
|
+
Object.defineProperty(exports, "captureFullContainerState", { enumerable: true, get: function () { return createAndLoadContainerUtils_js_1.captureFullContainerState; } });
|
|
16
17
|
Object.defineProperty(exports, "createDetachedContainer", { enumerable: true, get: function () { return createAndLoadContainerUtils_js_1.createDetachedContainer; } });
|
|
17
18
|
Object.defineProperty(exports, "loadExistingContainer", { enumerable: true, get: function () { return createAndLoadContainerUtils_js_1.loadExistingContainer; } });
|
|
18
19
|
Object.defineProperty(exports, "rehydrateDetachedContainer", { enumerable: true, get: function () { return createAndLoadContainerUtils_js_1.rehydrateDetachedContainer; } });
|
|
@@ -34,4 +35,7 @@ var utils_js_1 = require("./utils.js");
|
|
|
34
35
|
Object.defineProperty(exports, "tryParseCompatibleResolvedUrl", { enumerable: true, get: function () { return utils_js_1.tryParseCompatibleResolvedUrl; } });
|
|
35
36
|
var pendingLocalStateStore_js_1 = require("./pendingLocalStateStore.js");
|
|
36
37
|
Object.defineProperty(exports, "PendingLocalStateStore", { enumerable: true, get: function () { return pendingLocalStateStore_js_1.PendingLocalStateStore; } });
|
|
38
|
+
var captureReferencedContents_js_1 = require("./captureReferencedContents.js");
|
|
39
|
+
Object.defineProperty(exports, "extractBlobAttachReferences", { enumerable: true, get: function () { return captureReferencedContents_js_1.extractBlobAttachReferences; } });
|
|
40
|
+
Object.defineProperty(exports, "wireFormatConstants", { enumerable: true, get: function () { return captureReferencedContents_js_1.wireFormatConstants; } });
|
|
37
41
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,+CAA4F;AAA9D,sHAAA,sBAAsB,OAAA;AAAE,6GAAA,aAAa,OAAA;AACnE,yDAAyE;AAAhE,uIAAA,kCAAkC,OAAA;AAC3C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,+CAA4F;AAA9D,sHAAA,sBAAsB,OAAA;AAAE,6GAAA,aAAa,OAAA;AACnE,yDAAyE;AAAhE,uIAAA,kCAAkC,OAAA;AAC3C,mFAc0C;AAbzC,2IAAA,yBAAyB,OAAA;AACzB,yIAAA,uBAAuB,OAAA;AACvB,uIAAA,qBAAqB,OAAA;AACrB,4IAAA,0BAA0B,OAAA;AAC1B,qJAAA,mCAAmC,OAAA;AACnC,uJAAA,qCAAqC,OAAA;AActC,yCAMqB;AADpB,mGAAA,MAAM,OAAA;AAEP,yEAKqC;AAJpC,+IAAA,kCAAkC,OAAA;AAClC,oIAAA,uBAAuB,OAAA;AACvB,gJAAA,mCAAmC,OAAA;AACnC,0IAAA,6BAA6B,OAAA;AAE9B,iDAAsD;AAA7C,oHAAA,mBAAmB,OAAA;AAC5B,sEAGmD;AAFlD,sHAAA,0BAA0B,OAAA;AAC1B,kIAAA,sCAAsC,OAAA;AAGvC,uCAGoB;AAFnB,yHAAA,6BAA6B,OAAA;AAU9B,yEAAqE;AAA5D,mIAAA,sBAAsB,OAAA;AAC/B,+EAIwC;AAHvC,2IAAA,2BAA2B,OAAA;AAC3B,mIAAA,mBAAmB,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { ConnectionState } from \"./connectionState.js\";\nexport { type ContainerAlpha, waitContainerToCatchUp, asLegacyAlpha } from \"./container.js\";\nexport { createFrozenDocumentServiceFactory } from \"./frozenServices.js\";\nexport {\n\tcaptureFullContainerState,\n\tcreateDetachedContainer,\n\tloadExistingContainer,\n\trehydrateDetachedContainer,\n\tloadFrozenContainerFromPendingState,\n\tloadSummarizerContainerAndMakeSummary,\n\ttype ICaptureFullContainerStateProps,\n\ttype ICreateAndLoadContainerProps,\n\ttype ICreateDetachedContainerProps,\n\ttype ILoadExistingContainerProps,\n\ttype ILoadSummarizerContainerProps,\n\ttype IRehydrateDetachedContainerProps,\n\ttype ILoadFrozenContainerFromPendingStateProps,\n} from \"./createAndLoadContainerUtils.js\";\nexport type {\n\tLoadSummarizerSummaryResult,\n\tOnDemandSummaryResults,\n\tSummaryStage,\n} from \"./summarizerResultTypes.js\";\nexport {\n\ttype ICodeDetailsLoader,\n\ttype IFluidModuleWithDetails,\n\ttype ILoaderProps,\n\ttype ILoaderServices,\n\tLoader,\n} from \"./loader.js\";\nexport {\n\tdriverSupportRequirementsForLoader,\n\tloaderCoreCompatDetails,\n\truntimeSupportRequirementsForLoader,\n\tloaderCompatDetailsForRuntime,\n} from \"./loaderLayerCompatState.js\";\nexport { loadContainerPaused } from \"./loadPaused.js\";\nexport {\n\tisLocationRedirectionError,\n\tresolveWithLocationRedirectionHandling,\n} from \"./location-redirection-utilities/index.js\";\nexport type { IProtocolHandler, ProtocolHandlerBuilder } from \"./protocol.js\";\nexport {\n\ttryParseCompatibleResolvedUrl,\n\ttype IParsedUrl,\n} from \"./utils.js\";\nexport type {\n\tIBaseProtocolHandler,\n\tIScribeProtocolState,\n\tIQuorumSnapshot,\n\tQuorumClientsSnapshot,\n\tQuorumProposalsSnapshot,\n} from \"./protocol/index.js\";\nexport { PendingLocalStateStore } from \"./pendingLocalStateStore.js\";\nexport {\n\textractBlobAttachReferences,\n\twireFormatConstants,\n\ttype IBlobAttachReference,\n} from \"./captureReferencedContents.js\";\n"]}
|
package/dist/legacyAlpha.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export {
|
|
|
41
41
|
|
|
42
42
|
// #region @legacyAlpha APIs
|
|
43
43
|
ContainerAlpha,
|
|
44
|
+
ICaptureFullContainerStateProps,
|
|
44
45
|
ILoadFrozenContainerFromPendingStateProps,
|
|
45
46
|
ILoadSummarizerContainerProps,
|
|
46
47
|
LoadSummarizerSummaryResult,
|
|
@@ -48,6 +49,7 @@ export {
|
|
|
48
49
|
PendingLocalStateStore,
|
|
49
50
|
SummaryStage,
|
|
50
51
|
asLegacyAlpha,
|
|
52
|
+
captureFullContainerState,
|
|
51
53
|
createFrozenDocumentServiceFactory,
|
|
52
54
|
loadFrozenContainerFromPendingState,
|
|
53
55
|
loadSummarizerContainerAndMakeSummary
|
package/dist/loader.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { type IContainer, type IFluidCodeDetails, type IFluidModule, type IHostL
|
|
|
6
6
|
import type { FluidObject, IConfigProviderBase, IRequest, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
7
7
|
import type { IClientDetails } from "@fluidframework/driver-definitions";
|
|
8
8
|
import type { IDocumentServiceFactory, IUrlResolver } from "@fluidframework/driver-definitions/internal";
|
|
9
|
-
import {
|
|
9
|
+
import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/legacy";
|
|
10
10
|
import { Container } from "./container.js";
|
|
11
11
|
import type { ProtocolHandlerBuilder } from "./protocol.js";
|
|
12
12
|
/**
|
package/dist/loader.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,gCAAgC,EAErC,MAAM,gDAAgD,CAAC;AACxD,OAAO,KAAK,EACX,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,oBAAoB,EACpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EACX,uBAAuB,EAEvB,YAAY,EACZ,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,gCAAgC,EAErC,MAAM,gDAAgD,CAAC;AACxD,OAAO,KAAK,EACX,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,oBAAoB,EACpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EACX,uBAAuB,EAEvB,YAAY,EACZ,MAAM,6CAA6C,CAAC;AAUrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAGlF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAc5D;;GAEG;AACH,qBAAa,cAAe,YAAW,OAAO;IAE5C,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,OAAO,GAAG,SAAS;IAGhC,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;CA0B5D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACvC;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;;;OAIG;IACH,OAAO,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,gCAAgC,CAAC;IACpF;;;;;OAKG;IACH,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;IACzD;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAElC;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,mBAAmB,CAAC;IAE9C;;;OAGG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACzD;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;IACzD;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACzD;AAED;;;;;GAKG;AACH,qBAAa,MAAO,YAAW,WAAW;IACzC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;gBAE3B,WAAW,EAAE,YAAY;IAyCxB,uBAAuB,CACnC,WAAW,EAAE,iBAAiB,EAC9B,mBAAmB,CAAC,EAAE;QACrB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,qBAAqB,CAAC,EAAE,cAAc,CAAC;KACvC,GACC,OAAO,CAAC,UAAU,CAAC;IAUT,sCAAsC,CAClD,QAAQ,EAAE,MAAM,EAChB,mBAAmB,CAAC,EAAE;QACrB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,qBAAqB,CAAC,EAAE,cAAc,CAAC;KACvC,GACC,OAAO,CAAC,UAAU,CAAC;IAUT,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;YAU1E,WAAW;YAiCX,aAAa;CAuB3B"}
|
package/dist/loader.js
CHANGED
|
@@ -72,7 +72,7 @@ class Loader {
|
|
|
72
72
|
options: options ?? {},
|
|
73
73
|
scope: options?.provideScopeLoader === false ? { ...scope } : { ...scope, ILoader: this },
|
|
74
74
|
protocolHandlerBuilder,
|
|
75
|
-
subLogger: subMc.logger,
|
|
75
|
+
subLogger: (0, internal_2.toITelemetryLoggerExt)(subMc.logger),
|
|
76
76
|
};
|
|
77
77
|
this.mc = (0, internal_2.createChildMonitoringContext)({
|
|
78
78
|
logger: this.services.subLogger,
|