@fluidframework/container-loader 0.58.2001 → 0.59.2000-61729
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/dist/connectionManager.d.ts +0 -2
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +14 -11
- package/dist/connectionManager.js.map +1 -1
- package/dist/container.d.ts +22 -10
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +81 -39
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +5 -7
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +6 -4
- package/dist/containerContext.js.map +1 -1
- package/dist/contracts.d.ts +8 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +21 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deltaManager.d.ts +2 -1
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +1 -1
- package/dist/deltaManager.js.map +1 -1
- package/dist/loader.d.ts +4 -4
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.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/retriableDocumentStorageService.js +1 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +0 -1
- package/dist/utils.js.map +1 -1
- package/lib/connectionManager.d.ts +0 -2
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +14 -11
- package/lib/connectionManager.js.map +1 -1
- package/lib/container.d.ts +22 -10
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +81 -39
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +5 -7
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +6 -4
- package/lib/containerContext.js.map +1 -1
- package/lib/contracts.d.ts +8 -1
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +19 -0
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts +2 -1
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +1 -1
- package/lib/deltaManager.js.map +1 -1
- package/lib/loader.d.ts +4 -4
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.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/retriableDocumentStorageService.js +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +0 -1
- package/lib/utils.js.map +1 -1
- package/package.json +25 -13
- package/src/connectionManager.ts +16 -12
- package/src/container.ts +98 -39
- package/src/containerContext.ts +11 -13
- package/src/contracts.ts +20 -0
- package/src/deltaManager.ts +3 -2
- package/src/loader.ts +5 -6
- package/src/packageVersion.ts +1 -1
- package/src/retriableDocumentStorageService.ts +1 -1
- package/src/utils.ts +0 -1
package/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC;AAC5B,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EACH,MAAM,EACN,cAAc,EACd,uBAAuB,EACvB,eAAe,GAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAA+B,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAqBhG,MAAM,UAAU,QAAQ,CAAC,GAAW;;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE;QACrC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;KAC/C;IACD,MAAM,KAAK,SAAG,MAAM,CAAC,MAAM,mCAAI,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,2BAA2B,CAAC;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,MAAK,CAAC,CAAC;QACxB,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAiB,EAAE;QAClF,CAAC,CAAC,SAAS,CAAC;AACpB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,gDAAgD,CACrD,OAAqB;IAErB,MAAM,QAAQ,GAAkC;QAC5C,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,EAAE;QACjB,KAAK,EAAE,EAAE;QACT,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.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 { parse } from \"url\";\nimport { v4 as uuid } from \"uuid\";\nimport {\n assert,\n stringToBuffer,\n Uint8ArrayToArrayBuffer,\n unreachableCase,\n} from \"@fluidframework/common-utils\";\nimport { ISummaryTree, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\n\n// This is used when we rehydrate a container from the snapshot. Here we put the blob contents\n// in separate property: blobContents.\nexport interface ISnapshotTreeWithBlobContents extends ISnapshotTree {\n blobsContents: {[path: string]: ArrayBufferLike},\n trees: {[path: string]: ISnapshotTreeWithBlobContents},\n}\n\nexport interface IParsedUrl {\n id: string;\n path: string;\n query: string;\n /**\n * Null means do not use snapshots, undefined means load latest snapshot\n * otherwise it's version ID passed to IDocumentStorageService.getVersions() to figure out what snapshot to use.\n * If needed, can add undefined which is treated by Container.load() as load latest snapshot.\n */\n version: string | null | undefined;\n}\n\nexport function parseUrl(url: string): IParsedUrl | undefined {\n const parsed = parse(url, true);\n if (typeof parsed.pathname !== \"string\") {\n throw new Error(\"Failed to parse pathname\");\n }\n const query = parsed.search ?? \"\";\n const regex = /^\\/([^/]*\\/[^/]*)(\\/?.*)$/;\n const match = regex.exec(parsed.pathname);\n return (match?.length === 3)\n ? { id: match[1], path: match[2], query, version: parsed.query.version as string }\n : undefined;\n}\n\n/**\n * Converts summary tree (for upload) to snapshot tree (for download).\n * Summary tree blobs contain contents, but snapshot tree blobs normally\n * contain IDs pointing to storage. This will create 2 blob entries in the\n * snapshot tree for each blob in the summary tree. One will be the regular\n * path pointing to a uniquely generated ID. Then there will be another\n * entry with the path as that uniquely generated ID, and value as the\n * blob contents as a base-64 string.\n * @param summary - summary to convert\n */\nfunction convertSummaryToSnapshotWithEmbeddedBlobContents(\n summary: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n const treeNode: ISnapshotTreeWithBlobContents = {\n blobs: {},\n blobsContents: {},\n trees: {},\n id: uuid(),\n unreferenced: summary.unreferenced,\n };\n const keys = Object.keys(summary.tree);\n for (const key of keys) {\n const summaryObject = summary.tree[key];\n\n switch (summaryObject.type) {\n case SummaryType.Tree: {\n treeNode.trees[key] = convertSummaryToSnapshotWithEmbeddedBlobContents(summaryObject);\n break;\n }\n case SummaryType.Attachment:\n treeNode.blobs[key] = summaryObject.id;\n break;\n case SummaryType.Blob: {\n const blobId = uuid();\n treeNode.blobs[key] = blobId;\n const contentBuffer = typeof summaryObject.content === \"string\" ?\n stringToBuffer(summaryObject.content, \"utf8\") : Uint8ArrayToArrayBuffer(summaryObject.content);\n treeNode.blobsContents[blobId] = contentBuffer;\n break;\n }\n case SummaryType.Handle:\n throw new Error(\"No handles should be there in summary in detached container!!\");\n break;\n default: {\n unreachableCase(summaryObject, `Unknown tree type ${(summaryObject as any).type}`);\n }\n }\n }\n return treeNode;\n}\n\n/**\n * Combine and convert protocol and app summary tree to format which is readable by container while rehydrating.\n * @param protocolSummaryTree - Protocol Summary Tree\n * @param appSummaryTree - App Summary Tree\n */\nexport function convertProtocolAndAppSummaryToSnapshotTree(\n protocolSummaryTree: ISummaryTree,\n appSummaryTree: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n // Shallow copy is fine, since we are doing a deep clone below.\n const combinedSummary: ISummaryTree = {\n type: SummaryType.Tree,\n tree: { ...appSummaryTree.tree },\n };\n\n combinedSummary.tree[\".protocol\"] = protocolSummaryTree;\n const snapshotTreeWithBlobContents =\n convertSummaryToSnapshotWithEmbeddedBlobContents(combinedSummary);\n return snapshotTreeWithBlobContents;\n}\n\n// This function converts the snapshot taken in detached container(by serialize api) to snapshotTree with which\n// a detached container can be rehydrated.\nexport const getSnapshotTreeFromSerializedContainer = (detachedContainerSnapshot: ISummaryTree) => {\n const protocolSummaryTree = detachedContainerSnapshot.tree[\".protocol\"] as ISummaryTree;\n const appSummaryTree = detachedContainerSnapshot.tree[\".app\"] as ISummaryTree;\n assert(protocolSummaryTree !== undefined && appSummaryTree !== undefined,\n 0x1e0 /* \"Protocol and App summary trees should be present\" */);\n const snapshotTreeWithBlobContents = convertProtocolAndAppSummaryToSnapshotTree(\n protocolSummaryTree,\n appSummaryTree,\n );\n return snapshotTreeWithBlobContents;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-loader",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.2000-61729",
|
|
4
4
|
"description": "Fluid container loader",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"lint:fix": "npm run eslint:fix",
|
|
33
33
|
"test": "npm run test:mocha",
|
|
34
34
|
"test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
|
|
35
|
-
"test:mocha": "mocha --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
|
|
35
|
+
"test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
|
|
36
36
|
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
37
37
|
"tsc": "tsc",
|
|
38
38
|
"tsc:watch": "tsc --watch",
|
|
@@ -62,14 +62,14 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
64
64
|
"@fluidframework/common-utils": "^0.32.1",
|
|
65
|
-
"@fluidframework/container-definitions": "^0.
|
|
66
|
-
"@fluidframework/container-utils": "
|
|
67
|
-
"@fluidframework/core-interfaces": "^0.
|
|
68
|
-
"@fluidframework/driver-definitions": "^0.
|
|
69
|
-
"@fluidframework/driver-utils": "
|
|
70
|
-
"@fluidframework/protocol-base": "^0.
|
|
71
|
-
"@fluidframework/protocol-definitions": "^0.
|
|
72
|
-
"@fluidframework/telemetry-utils": "
|
|
65
|
+
"@fluidframework/container-definitions": "^0.48.1000-0",
|
|
66
|
+
"@fluidframework/container-utils": "0.59.2000-61729",
|
|
67
|
+
"@fluidframework/core-interfaces": "^0.43.1000-0",
|
|
68
|
+
"@fluidframework/driver-definitions": "^0.46.1000-0",
|
|
69
|
+
"@fluidframework/driver-utils": "0.59.2000-61729",
|
|
70
|
+
"@fluidframework/protocol-base": "^0.1036.1000-0",
|
|
71
|
+
"@fluidframework/protocol-definitions": "^0.1028.1000-0",
|
|
72
|
+
"@fluidframework/telemetry-utils": "0.59.2000-61729",
|
|
73
73
|
"abort-controller": "^3.0.0",
|
|
74
74
|
"double-ended-queue": "^2.1.0-0",
|
|
75
75
|
"lodash": "^4.17.21",
|
|
@@ -77,9 +77,10 @@
|
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@fluidframework/build-common": "^0.23.0",
|
|
80
|
-
"@fluidframework/
|
|
81
|
-
"@fluidframework/
|
|
82
|
-
"@fluidframework/test-
|
|
80
|
+
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@^0.58.0",
|
|
81
|
+
"@fluidframework/eslint-config-fluid": "^0.28.1000-61189",
|
|
82
|
+
"@fluidframework/mocha-test-setup": "0.59.2000-61729",
|
|
83
|
+
"@fluidframework/test-loader-utils": "0.59.2000-61729",
|
|
83
84
|
"@microsoft/api-extractor": "^7.16.1",
|
|
84
85
|
"@rushstack/eslint-config": "^2.5.1",
|
|
85
86
|
"@types/double-ended-queue": "^2.1.0",
|
|
@@ -105,5 +106,16 @@
|
|
|
105
106
|
"sinon": "^7.4.2",
|
|
106
107
|
"typescript": "~4.1.3",
|
|
107
108
|
"typescript-formatter": "7.1.0"
|
|
109
|
+
},
|
|
110
|
+
"typeValidation": {
|
|
111
|
+
"version": "0.59.1000",
|
|
112
|
+
"broken": {
|
|
113
|
+
"0.58.2002": {
|
|
114
|
+
"ClassDeclaration_Container": {
|
|
115
|
+
"forwardCompat": false,
|
|
116
|
+
"backCompat": false
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
108
120
|
}
|
|
109
121
|
}
|
package/src/connectionManager.ts
CHANGED
|
@@ -147,9 +147,6 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
147
147
|
/** True if there is pending (async) reconnection from "read" to "write" */
|
|
148
148
|
private pendingReconnect = false;
|
|
149
149
|
|
|
150
|
-
/** downgrade "write" connection to "read" */
|
|
151
|
-
private downgradedConnection = false;
|
|
152
|
-
|
|
153
150
|
private clientSequenceNumber = 0;
|
|
154
151
|
private clientSequenceNumberObserved = 0;
|
|
155
152
|
/** Counts the number of noops sent by the client which may not be acked. */
|
|
@@ -176,12 +173,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
176
173
|
* The current connection mode, initially read.
|
|
177
174
|
*/
|
|
178
175
|
public get connectionMode(): ConnectionMode {
|
|
179
|
-
|
|
180
|
-
0x277 /* "Did we forget to reset downgradedConnection on new connection?" */);
|
|
181
|
-
if (this.connection === undefined) {
|
|
182
|
-
return "read";
|
|
183
|
-
}
|
|
184
|
-
return this.connection.mode;
|
|
176
|
+
return this.connection?.mode ?? "read";
|
|
185
177
|
}
|
|
186
178
|
|
|
187
179
|
public get connected() { return this.connection !== undefined; }
|
|
@@ -490,6 +482,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
490
482
|
throw error;
|
|
491
483
|
}
|
|
492
484
|
|
|
485
|
+
// Since the error is retryable this will not log to the error table
|
|
493
486
|
logNetworkFailure(
|
|
494
487
|
this.logger,
|
|
495
488
|
{
|
|
@@ -547,7 +540,6 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
547
540
|
*/
|
|
548
541
|
private disconnectFromDeltaStream(reason: string): boolean {
|
|
549
542
|
this.pendingReconnect = false;
|
|
550
|
-
this.downgradedConnection = false;
|
|
551
543
|
|
|
552
544
|
if (this.connection === undefined) {
|
|
553
545
|
return false;
|
|
@@ -798,7 +790,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
798
790
|
// Note that we also want nacks to be rare and be treated as catastrophic failures.
|
|
799
791
|
// Be careful with reentrancy though - disconnected event should not be be raised in the
|
|
800
792
|
// middle of the current workflow, but rather on clean stack!
|
|
801
|
-
if (this.connectionMode === "read"
|
|
793
|
+
if (this.connectionMode === "read") {
|
|
802
794
|
if (!this.pendingReconnect) {
|
|
803
795
|
this.pendingReconnect = true;
|
|
804
796
|
Promise.resolve().then(async () => {
|
|
@@ -841,7 +833,19 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
841
833
|
if (clientId === this.clientId) {
|
|
842
834
|
// We have been kicked out from quorum
|
|
843
835
|
this.logger.sendPerformanceEvent({ eventName: "ReadConnectionTransition" });
|
|
844
|
-
|
|
836
|
+
|
|
837
|
+
// Please see #8483 for more details on why maintaining connection further as is would not work.
|
|
838
|
+
// Short story - connection properties are immutable, and many processes (consensus DDSs, summarizer)
|
|
839
|
+
// assume that connection stays "write" connection until disconnect, and act accordingly, which may
|
|
840
|
+
// not work well with de-facto "read" connection we are in after receiving own leave op on timeout.
|
|
841
|
+
// Clients need to be able to transition to "read" state after some time of inactivity!
|
|
842
|
+
// Note - this may close container!
|
|
843
|
+
this.reconnect(
|
|
844
|
+
"read", // connectionMode
|
|
845
|
+
"Switch to read", // message
|
|
846
|
+
).catch((error) => {
|
|
847
|
+
this.logger.sendErrorEvent({ eventName: "SwitchToReadConnection"}, error);
|
|
848
|
+
});
|
|
845
849
|
}
|
|
846
850
|
}
|
|
847
851
|
}
|
package/src/container.ts
CHANGED
|
@@ -14,8 +14,6 @@ import {
|
|
|
14
14
|
IRequest,
|
|
15
15
|
IResponse,
|
|
16
16
|
IFluidRouter,
|
|
17
|
-
IFluidCodeDetails,
|
|
18
|
-
isFluidCodeDetails,
|
|
19
17
|
} from "@fluidframework/core-interfaces";
|
|
20
18
|
import {
|
|
21
19
|
IAudience,
|
|
@@ -30,6 +28,8 @@ import {
|
|
|
30
28
|
IPendingLocalState,
|
|
31
29
|
ReadOnlyInfo,
|
|
32
30
|
IContainerLoadMode,
|
|
31
|
+
IFluidCodeDetails,
|
|
32
|
+
isFluidCodeDetails,
|
|
33
33
|
} from "@fluidframework/container-definitions";
|
|
34
34
|
import {
|
|
35
35
|
DataCorruptionError,
|
|
@@ -92,7 +92,7 @@ import {
|
|
|
92
92
|
} from "@fluidframework/telemetry-utils";
|
|
93
93
|
import { Audience } from "./audience";
|
|
94
94
|
import { ContainerContext } from "./containerContext";
|
|
95
|
-
import { ReconnectMode, IConnectionManagerFactoryArgs } from "./contracts";
|
|
95
|
+
import { ReconnectMode, IConnectionManagerFactoryArgs, getPackageName } from "./contracts";
|
|
96
96
|
import { DeltaManager, IConnectionArgs } from "./deltaManager";
|
|
97
97
|
import { DeltaManagerProxy } from "./deltaManagerProxy";
|
|
98
98
|
import { ILoaderOptions, Loader, RelativeLoader } from "./loader";
|
|
@@ -224,6 +224,8 @@ const getCodeProposal =
|
|
|
224
224
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
225
225
|
(quorum: IQuorumProposals) => quorum.get("code") ?? quorum.get("code2");
|
|
226
226
|
|
|
227
|
+
const summarizerClientType = "summarizer";
|
|
228
|
+
|
|
227
229
|
export class Container extends EventEmitterWithErrorHandling<IContainerEvents> implements IContainer {
|
|
228
230
|
public static version = "^0.1.0";
|
|
229
231
|
|
|
@@ -381,7 +383,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
381
383
|
private _context: ContainerContext | undefined;
|
|
382
384
|
private get context() {
|
|
383
385
|
if (this._context === undefined) {
|
|
384
|
-
throw new
|
|
386
|
+
throw new GenericError("Attempted to access context before it was defined");
|
|
385
387
|
}
|
|
386
388
|
return this._context;
|
|
387
389
|
}
|
|
@@ -395,7 +397,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
395
397
|
|
|
396
398
|
private resumedOpProcessingAfterLoad = false;
|
|
397
399
|
private firstConnection = true;
|
|
398
|
-
private manualReconnectInProgress = false;
|
|
399
400
|
private readonly connectionTransitionTimes: number[] = [];
|
|
400
401
|
private messageCountAfterDisconnection: number = 0;
|
|
401
402
|
private _loadedFromVersion: IVersion | undefined;
|
|
@@ -432,6 +433,10 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
432
433
|
return this._deltaManager.readOnlyInfo;
|
|
433
434
|
}
|
|
434
435
|
|
|
436
|
+
public get closeSignal(): AbortSignal {
|
|
437
|
+
return this._deltaManager.closeAbortController.signal;
|
|
438
|
+
}
|
|
439
|
+
|
|
435
440
|
/**
|
|
436
441
|
* Tracks host requiring read-only mode.
|
|
437
442
|
*/
|
|
@@ -818,15 +823,20 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
818
823
|
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
819
824
|
ensureFluidResolvedUrl(createNewResolvedUrl);
|
|
820
825
|
if (this.service === undefined) {
|
|
826
|
+
assert(this.client.details.type !== summarizerClientType,
|
|
827
|
+
0x2c4 /* "client should not be summarizer before container is created" */);
|
|
821
828
|
this.service = await runWithRetry(
|
|
822
829
|
async () => this.serviceFactory.createContainer(
|
|
823
830
|
summary,
|
|
824
831
|
createNewResolvedUrl,
|
|
825
832
|
this.subLogger,
|
|
833
|
+
false, // clientIsSummarizer
|
|
826
834
|
),
|
|
827
835
|
"containerAttach",
|
|
828
836
|
this.mc.logger,
|
|
829
|
-
{
|
|
837
|
+
{
|
|
838
|
+
cancel: this.closeSignal,
|
|
839
|
+
}, // progress
|
|
830
840
|
);
|
|
831
841
|
}
|
|
832
842
|
const resolvedUrl = this.service.resolvedUrl;
|
|
@@ -898,11 +908,31 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
898
908
|
);
|
|
899
909
|
}
|
|
900
910
|
|
|
911
|
+
/**
|
|
912
|
+
* Dictates whether or not the current container will automatically attempt to reconnect to the delta stream
|
|
913
|
+
* after receiving a disconnect event
|
|
914
|
+
* @param reconnect - Boolean indicating if reconnect should automatically occur
|
|
915
|
+
* @deprecated - 0.58, This API will be removed in 1.0
|
|
916
|
+
* Use `connect()` and `disconnect()` instead of `setAutoReconnect(true)` and `setAutoReconnect(false)` respectively
|
|
917
|
+
* See https://github.com/microsoft/FluidFramework/issues/9167 for context
|
|
918
|
+
*/
|
|
901
919
|
public setAutoReconnect(reconnect: boolean) {
|
|
902
920
|
if (this.closed) {
|
|
903
921
|
throw new Error("Attempting to setAutoReconnect() a closed Container");
|
|
904
922
|
}
|
|
923
|
+
|
|
905
924
|
const mode = reconnect ? ReconnectMode.Enabled : ReconnectMode.Disabled;
|
|
925
|
+
this.setAutoReconnectInternal(mode);
|
|
926
|
+
|
|
927
|
+
// If container state is not attached and resumed, then don't connect to delta stream. Also don't set the
|
|
928
|
+
// manual reconnection flag to true as we haven't made the initial connection yet.
|
|
929
|
+
if (reconnect && this._attachState === AttachState.Attached && this.resumedOpProcessingAfterLoad) {
|
|
930
|
+
// Ensure connection to web socket
|
|
931
|
+
this.connectToDeltaStream({ reason: "autoReconnect" });
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
private setAutoReconnectInternal(mode: ReconnectMode) {
|
|
906
936
|
const currentMode = this._deltaManager.connectionManager.reconnectMode;
|
|
907
937
|
|
|
908
938
|
if (currentMode === mode) {
|
|
@@ -914,27 +944,66 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
914
944
|
this.setAutoReconnectTime = now;
|
|
915
945
|
|
|
916
946
|
this.mc.logger.sendTelemetryEvent({
|
|
917
|
-
eventName:
|
|
947
|
+
eventName: mode === ReconnectMode.Enabled ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
|
|
918
948
|
connectionMode: this.connectionMode,
|
|
919
949
|
connectionState: ConnectionState[this.connectionState],
|
|
920
950
|
duration,
|
|
921
951
|
});
|
|
922
952
|
|
|
923
953
|
this._deltaManager.connectionManager.setAutoReconnect(mode);
|
|
954
|
+
}
|
|
924
955
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
956
|
+
public connect() {
|
|
957
|
+
if (this.closed) {
|
|
958
|
+
throw new UsageError(`The Container is closed and cannot be connected`);
|
|
959
|
+
}
|
|
960
|
+
else if (this._attachState !== AttachState.Attached) {
|
|
961
|
+
throw new UsageError(`The Container is not attached and cannot be connected`);
|
|
962
|
+
}
|
|
963
|
+
else if (!this.connected) {
|
|
964
|
+
// Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
|
|
965
|
+
// If there is gap, we will learn about it once connected, but the gap should be small (if any),
|
|
966
|
+
// assuming that connect() is called quickly after initial container boot.
|
|
967
|
+
this.connectInternal({ reason: "DocumentConnect", fetchOpsFromStorage: false });
|
|
968
|
+
}
|
|
969
|
+
}
|
|
932
970
|
|
|
933
|
-
|
|
934
|
-
|
|
971
|
+
private connectInternal(args: IConnectionArgs) {
|
|
972
|
+
assert(!this.closed, 0x2c5 /* "Attempting to connect() a closed Container" */);
|
|
973
|
+
assert(this._attachState === AttachState.Attached,
|
|
974
|
+
0x2c6 /* "Attempting to connect() a container that is not attached" */);
|
|
975
|
+
|
|
976
|
+
// Resume processing ops and connect to delta stream
|
|
977
|
+
this.resumeInternal(args);
|
|
978
|
+
|
|
979
|
+
// Set Auto Reconnect Mode
|
|
980
|
+
const mode = ReconnectMode.Enabled;
|
|
981
|
+
this.setAutoReconnectInternal(mode);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
public disconnect() {
|
|
985
|
+
if (this.closed) {
|
|
986
|
+
throw new UsageError(`The Container is closed and cannot be disconnected`);
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
this.disconnectInternal();
|
|
935
990
|
}
|
|
936
991
|
}
|
|
937
992
|
|
|
993
|
+
private disconnectInternal() {
|
|
994
|
+
assert(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
|
|
995
|
+
|
|
996
|
+
// Set Auto Reconnect Mode
|
|
997
|
+
const mode = ReconnectMode.Disabled;
|
|
998
|
+
this.setAutoReconnectInternal(mode);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* Have the container attempt to resume processing ops
|
|
1003
|
+
* @deprecated - 0.58, This API will be removed in 1.0
|
|
1004
|
+
* Use `connect()` instead
|
|
1005
|
+
* See https://github.com/microsoft/FluidFramework/issues/9167 for context
|
|
1006
|
+
*/
|
|
938
1007
|
public resume() {
|
|
939
1008
|
if (!this.closed) {
|
|
940
1009
|
// Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
|
|
@@ -958,21 +1027,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
958
1027
|
this.connectToDeltaStream(args);
|
|
959
1028
|
}
|
|
960
1029
|
|
|
961
|
-
/**
|
|
962
|
-
* @deprecated 0.56, will be removed in next release from IContainerContext
|
|
963
|
-
* Raise non-critical error to host. Calling this API will not close container.
|
|
964
|
-
* For critical errors, please call Container.close(error).
|
|
965
|
-
* @param error - an error to raise
|
|
966
|
-
*/
|
|
967
|
-
public raiseContainerWarning(warning: ContainerWarning) {
|
|
968
|
-
// Some "warning" events come from outside the container and are logged
|
|
969
|
-
// elsewhere (e.g. summarizing container). We shouldn't log these here.
|
|
970
|
-
if (warning.logged !== true) {
|
|
971
|
-
this.logContainerError(warning);
|
|
972
|
-
}
|
|
973
|
-
this.emit("warning", warning);
|
|
974
|
-
}
|
|
975
|
-
|
|
976
1030
|
public async getAbsoluteUrl(relativeUrl: string): Promise<string | undefined> {
|
|
977
1031
|
if (this.resolvedUrl === undefined) {
|
|
978
1032
|
return undefined;
|
|
@@ -981,7 +1035,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
981
1035
|
return this.urlResolver.getAbsoluteUrl(
|
|
982
1036
|
this.resolvedUrl,
|
|
983
1037
|
relativeUrl,
|
|
984
|
-
this._context?.codeDetails);
|
|
1038
|
+
getPackageName(this._context?.codeDetails));
|
|
985
1039
|
}
|
|
986
1040
|
|
|
987
1041
|
public async proposeCodeDetails(codeDetails: IFluidCodeDetails) {
|
|
@@ -1057,7 +1111,11 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
1057
1111
|
if (this._resolvedUrl === undefined) {
|
|
1058
1112
|
throw new Error("Attempting to load without a resolved url");
|
|
1059
1113
|
}
|
|
1060
|
-
this.service = await this.serviceFactory.createDocumentService(
|
|
1114
|
+
this.service = await this.serviceFactory.createDocumentService(
|
|
1115
|
+
this._resolvedUrl,
|
|
1116
|
+
this.subLogger,
|
|
1117
|
+
this.client.details.type === summarizerClientType,
|
|
1118
|
+
);
|
|
1061
1119
|
|
|
1062
1120
|
// Ideally we always connect as "read" by default.
|
|
1063
1121
|
// Currently that works with SPO & r11s, because we get "write" connection when connecting to non-existing file.
|
|
@@ -1476,13 +1534,18 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
1476
1534
|
});
|
|
1477
1535
|
|
|
1478
1536
|
deltaManager.on("disconnect", (reason: string) => {
|
|
1479
|
-
this.manualReconnectInProgress = false;
|
|
1480
1537
|
this.collabWindowTracker.stopSequenceNumberUpdate();
|
|
1481
1538
|
this.connectionStateHandler.receivedDisconnectEvent(reason);
|
|
1482
1539
|
});
|
|
1483
1540
|
|
|
1484
1541
|
deltaManager.on("throttled", (warning: IThrottlingWarning) => {
|
|
1485
|
-
|
|
1542
|
+
const warn = warning as ContainerWarning;
|
|
1543
|
+
// Some "warning" events come from outside the container and are logged
|
|
1544
|
+
// elsewhere (e.g. summarizing container). We shouldn't log these here.
|
|
1545
|
+
if (warn.logged !== true) {
|
|
1546
|
+
this.logContainerError(warn);
|
|
1547
|
+
}
|
|
1548
|
+
this.emit("warning", warn);
|
|
1486
1549
|
});
|
|
1487
1550
|
|
|
1488
1551
|
deltaManager.on("readonly", (readonly) => {
|
|
@@ -1543,8 +1606,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
1543
1606
|
}
|
|
1544
1607
|
if (this.firstConnection) {
|
|
1545
1608
|
connectionInitiationReason = "InitialConnect";
|
|
1546
|
-
} else if (this.manualReconnectInProgress) {
|
|
1547
|
-
connectionInitiationReason = "ManualReconnect";
|
|
1548
1609
|
} else {
|
|
1549
1610
|
connectionInitiationReason = "AutoReconnect";
|
|
1550
1611
|
}
|
|
@@ -1569,7 +1630,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
1569
1630
|
|
|
1570
1631
|
if (value === ConnectionState.Connected) {
|
|
1571
1632
|
this.firstConnection = false;
|
|
1572
|
-
this.manualReconnectInProgress = false;
|
|
1573
1633
|
}
|
|
1574
1634
|
}
|
|
1575
1635
|
|
|
@@ -1755,7 +1815,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
|
|
|
1755
1815
|
new DeltaManagerProxy(this._deltaManager),
|
|
1756
1816
|
new QuorumProxy(this.protocolHandler.quorum),
|
|
1757
1817
|
loader,
|
|
1758
|
-
(warning: ContainerWarning) => this.raiseContainerWarning(warning),
|
|
1759
1818
|
(type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata),
|
|
1760
1819
|
(message) => this.submitSignal(message),
|
|
1761
1820
|
(error?: ICriticalContainerError) => this.close(error),
|
package/src/containerContext.ts
CHANGED
|
@@ -12,20 +12,19 @@ import {
|
|
|
12
12
|
ILoader,
|
|
13
13
|
IRuntime,
|
|
14
14
|
ICriticalContainerError,
|
|
15
|
-
ContainerWarning,
|
|
16
15
|
AttachState,
|
|
17
16
|
ILoaderOptions,
|
|
18
17
|
IRuntimeFactory,
|
|
19
|
-
ICodeLoader,
|
|
20
18
|
IProvideRuntimeFactory,
|
|
19
|
+
IFluidCodeDetails,
|
|
20
|
+
IFluidCodeDetailsComparer,
|
|
21
|
+
IProvideFluidCodeDetailsComparer,
|
|
22
|
+
ICodeDetailsLoader,
|
|
23
|
+
IFluidModuleWithDetails,
|
|
21
24
|
} from "@fluidframework/container-definitions";
|
|
22
25
|
import {
|
|
23
|
-
IFluidObject,
|
|
24
26
|
IRequest,
|
|
25
27
|
IResponse,
|
|
26
|
-
IFluidCodeDetails,
|
|
27
|
-
IFluidCodeDetailsComparer,
|
|
28
|
-
IProvideFluidCodeDetailsComparer,
|
|
29
28
|
FluidObject,
|
|
30
29
|
} from "@fluidframework/core-interfaces";
|
|
31
30
|
import { IDocumentStorageService } from "@fluidframework/driver-definitions";
|
|
@@ -45,7 +44,6 @@ import {
|
|
|
45
44
|
} from "@fluidframework/protocol-definitions";
|
|
46
45
|
import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
47
46
|
import { Container } from "./container";
|
|
48
|
-
import { ICodeDetailsLoader, IFluidModuleWithDetails } from "./loader";
|
|
49
47
|
|
|
50
48
|
const PackageNotFactoryError = "Code package does not implement IRuntimeFactory";
|
|
51
49
|
|
|
@@ -53,13 +51,12 @@ export class ContainerContext implements IContainerContext {
|
|
|
53
51
|
public static async createOrLoad(
|
|
54
52
|
container: Container,
|
|
55
53
|
scope: FluidObject,
|
|
56
|
-
codeLoader: ICodeDetailsLoader
|
|
54
|
+
codeLoader: ICodeDetailsLoader,
|
|
57
55
|
codeDetails: IFluidCodeDetails,
|
|
58
56
|
baseSnapshot: ISnapshotTree | undefined,
|
|
59
57
|
deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
60
58
|
quorum: IQuorum,
|
|
61
59
|
loader: ILoader,
|
|
62
|
-
raiseContainerWarning: (warning: ContainerWarning) => void,
|
|
63
60
|
submitFn: (type: MessageType, contents: any, batch: boolean, appData: any) => number,
|
|
64
61
|
submitSignalFn: (contents: any) => void,
|
|
65
62
|
closeFn: (error?: ICriticalContainerError) => void,
|
|
@@ -77,7 +74,6 @@ export class ContainerContext implements IContainerContext {
|
|
|
77
74
|
deltaManager,
|
|
78
75
|
quorum,
|
|
79
76
|
loader,
|
|
80
|
-
raiseContainerWarning,
|
|
81
77
|
submitFn,
|
|
82
78
|
submitSignalFn,
|
|
83
79
|
closeFn,
|
|
@@ -159,14 +155,13 @@ export class ContainerContext implements IContainerContext {
|
|
|
159
155
|
|
|
160
156
|
constructor(
|
|
161
157
|
private readonly container: Container,
|
|
162
|
-
public readonly scope:
|
|
163
|
-
private readonly codeLoader: ICodeDetailsLoader
|
|
158
|
+
public readonly scope: FluidObject,
|
|
159
|
+
private readonly codeLoader: ICodeDetailsLoader,
|
|
164
160
|
private readonly _codeDetails: IFluidCodeDetails,
|
|
165
161
|
private readonly _baseSnapshot: ISnapshotTree | undefined,
|
|
166
162
|
public readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
167
163
|
quorum: IQuorum,
|
|
168
164
|
public readonly loader: ILoader,
|
|
169
|
-
public readonly raiseContainerWarning: (warning: ContainerWarning) => void,
|
|
170
165
|
public readonly submitFn: (type: MessageType, contents: any, batch: boolean, appData: any) => number,
|
|
171
166
|
public readonly submitSignalFn: (contents: any) => void,
|
|
172
167
|
public readonly closeFn: (error?: ICriticalContainerError) => void,
|
|
@@ -333,6 +328,9 @@ export class ContainerContext implements IContainerContext {
|
|
|
333
328
|
details: details ?? codeDetails,
|
|
334
329
|
};
|
|
335
330
|
} else {
|
|
331
|
+
// If "module" is not in the result, we are using a legacy ICodeLoader. Fix the result up with details.
|
|
332
|
+
// Once usage drops to 0 we can remove this compat path.
|
|
333
|
+
this.taggedLogger.sendTelemetryEvent({ eventName: "LegacyCodeLoader" });
|
|
336
334
|
return { module: loadCodeResult, details: codeDetails };
|
|
337
335
|
}
|
|
338
336
|
}
|
package/src/contracts.ts
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
ReadOnlyInfo,
|
|
12
12
|
IConnectionDetails,
|
|
13
13
|
ICriticalContainerError,
|
|
14
|
+
IFluidCodeDetails,
|
|
15
|
+
isFluidPackage,
|
|
14
16
|
} from "@fluidframework/container-definitions";
|
|
15
17
|
import {
|
|
16
18
|
ConnectionMode,
|
|
@@ -20,6 +22,7 @@ import {
|
|
|
20
22
|
IClientDetails,
|
|
21
23
|
ISignalMessage,
|
|
22
24
|
} from "@fluidframework/protocol-definitions";
|
|
25
|
+
import { IContainerPackageInfo } from "@fluidframework/driver-definitions";
|
|
23
26
|
|
|
24
27
|
export enum ReconnectMode {
|
|
25
28
|
Never = "Never",
|
|
@@ -155,3 +158,20 @@ export interface IConnectionManagerFactoryArgs {
|
|
|
155
158
|
*/
|
|
156
159
|
readonly readonlyChangeHandler: (readonly?: boolean) => void,
|
|
157
160
|
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
*
|
|
164
|
+
* @param codeDetails- Data structure used to describe the code to load on the Fluid document
|
|
165
|
+
* @returns The name of the Fluid package
|
|
166
|
+
*/
|
|
167
|
+
export const getPackageName = (codeDetails: IFluidCodeDetails | undefined): IContainerPackageInfo => {
|
|
168
|
+
let containerPackageName;
|
|
169
|
+
if (codeDetails && "name" in codeDetails) {
|
|
170
|
+
containerPackageName = codeDetails;
|
|
171
|
+
} else if (isFluidPackage(codeDetails?.package)) {
|
|
172
|
+
containerPackageName = codeDetails?.package.name;
|
|
173
|
+
} else {
|
|
174
|
+
containerPackageName = codeDetails?.package;
|
|
175
|
+
}
|
|
176
|
+
return { name: containerPackageName };
|
|
177
|
+
};
|
package/src/deltaManager.ts
CHANGED
|
@@ -123,7 +123,7 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
123
123
|
private readonly throttlingIdSet = new Set<string>();
|
|
124
124
|
private timeTillThrottling: number = 0;
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
public readonly closeAbortController = new AbortController();
|
|
127
127
|
|
|
128
128
|
private readonly deltaStorageDelayId = uuid();
|
|
129
129
|
private readonly deltaStreamDelayId = uuid();
|
|
@@ -201,11 +201,12 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
201
201
|
|
|
202
202
|
this.messageBuffer.push(message);
|
|
203
203
|
|
|
204
|
+
this.emit("submitOp", message);
|
|
205
|
+
|
|
204
206
|
if (!batch) {
|
|
205
207
|
this.flush();
|
|
206
208
|
}
|
|
207
209
|
|
|
208
|
-
this.emit("submitOp", message);
|
|
209
210
|
return message.clientSequenceNumber;
|
|
210
211
|
}
|
|
211
212
|
|
package/src/loader.ts
CHANGED
|
@@ -7,15 +7,12 @@ import { v4 as uuid } from "uuid";
|
|
|
7
7
|
import { ITelemetryBaseLogger, ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
8
8
|
import {
|
|
9
9
|
FluidObject,
|
|
10
|
-
IFluidCodeDetails,
|
|
11
10
|
IFluidRouter,
|
|
12
|
-
IProvideFluidCodeDetailsComparer,
|
|
13
11
|
IRequest,
|
|
14
12
|
IRequestHeader,
|
|
15
13
|
IResponse,
|
|
16
14
|
} from "@fluidframework/core-interfaces";
|
|
17
15
|
import {
|
|
18
|
-
ICodeLoader,
|
|
19
16
|
IContainer,
|
|
20
17
|
IFluidModule,
|
|
21
18
|
IHostLoader,
|
|
@@ -24,6 +21,8 @@ import {
|
|
|
24
21
|
ILoaderOptions as ILoaderOptions1,
|
|
25
22
|
IProxyLoaderFactory,
|
|
26
23
|
LoaderHeader,
|
|
24
|
+
IProvideFluidCodeDetailsComparer,
|
|
25
|
+
IFluidCodeDetails,
|
|
27
26
|
} from "@fluidframework/container-definitions";
|
|
28
27
|
import {
|
|
29
28
|
ChildLogger,
|
|
@@ -187,7 +186,7 @@ export interface ILoaderProps {
|
|
|
187
186
|
* The code loader handles loading the necessary code
|
|
188
187
|
* for running a container once it is loaded.
|
|
189
188
|
*/
|
|
190
|
-
readonly codeLoader: ICodeDetailsLoader
|
|
189
|
+
readonly codeLoader: ICodeDetailsLoader;
|
|
191
190
|
|
|
192
191
|
/**
|
|
193
192
|
* A property bag of options used by various layers
|
|
@@ -243,7 +242,7 @@ export interface ILoaderServices {
|
|
|
243
242
|
* The code loader handles loading the necessary code
|
|
244
243
|
* for running a container once it is loaded.
|
|
245
244
|
*/
|
|
246
|
-
readonly codeLoader: ICodeDetailsLoader
|
|
245
|
+
readonly codeLoader: ICodeDetailsLoader;
|
|
247
246
|
|
|
248
247
|
/**
|
|
249
248
|
* A property bag of options used by various layers
|
|
@@ -295,7 +294,7 @@ export class Loader implements IHostLoader {
|
|
|
295
294
|
private readonly mc: MonitoringContext;
|
|
296
295
|
|
|
297
296
|
constructor(loaderProps: ILoaderProps) {
|
|
298
|
-
const scope = { ...loaderProps.scope
|
|
297
|
+
const scope: FluidObject<ILoader> = { ...loaderProps.scope };
|
|
299
298
|
if (loaderProps.options?.provideScopeLoader !== false) {
|
|
300
299
|
scope.ILoader = this;
|
|
301
300
|
}
|
package/src/packageVersion.ts
CHANGED