@fluidframework/container-loader 2.4.0 → 2.5.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.
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/container-loader";
8
- export declare const pkgVersion = "2.4.0";
8
+ export declare const pkgVersion = "2.5.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/container-loader";
8
- export const pkgVersion = "2.4.0";
8
+ export const pkgVersion = "2.5.0";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-loader\";\nexport const pkgVersion = \"2.4.0\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-loader\";\nexport const pkgVersion = \"2.5.0\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAChF,OAAO,EACN,mBAAmB,EACnB,qBAAqB,EAGrB,yBAAyB,EACzB,cAAc,EACd,MAAM,6CAA6C,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG/F,oBAAY,UAAU;IACrB,UAAU,SAAS,CAAE,wCAAwC;IAC7D,WAAW,UAAU,CAAE,yCAAyC;IAChE,KAAK,UAAU;CACf;AAED;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,CACpC,UAAU,EAAE,mBAAmB,EAC/B,QAAQ,EAAE,eAAe,EAGzB,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,KAC7C,gBAAgB,CAAC;AAEtB;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB;IAC7D,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,aAAa,CAAC,OAAO,EAAE,cAAc,OAAE;CACvC;AAED,qBAAa,eAAgB,SAAQ,iBAAkB,YAAW,gBAAgB;aAOhE,QAAQ,EAAE,cAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBANrC,UAAU,EAAE,mBAAmB,EAC/B,cAAc,EAAE,eAAe,EAG/B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,EACjC,QAAQ,EAAE,cAAc,EACvB,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO;IAyB9D,cAAc,CACpB,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,GACZ,qBAAqB;IAwBjB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;CAiCnD;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAWnF"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAChF,OAAO,EACN,mBAAmB,EACnB,qBAAqB,EAGrB,yBAAyB,EACzB,cAAc,EACd,MAAM,6CAA6C,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG/F,oBAAY,UAAU;IACrB,UAAU,SAAS,CAAE,wCAAwC;IAC7D,WAAW,UAAU,CAAE,yCAAyC;IAChE,KAAK,UAAU;CACf;AAED;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,CACpC,UAAU,EAAE,mBAAmB,EAC/B,QAAQ,EAAE,eAAe,EAGzB,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,KAC7C,gBAAgB,CAAC;AAEtB;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB;IAC7D,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,aAAa,CAAC,OAAO,EAAE,cAAc,OAAE;CACvC;AAED,qBAAa,eAAgB,SAAQ,iBAAkB,YAAW,gBAAgB;aAOhE,QAAQ,EAAE,cAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBANrC,UAAU,EAAE,mBAAmB,EAC/B,cAAc,EAAE,eAAe,EAG/B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,EACjC,QAAQ,EAAE,cAAc,EACvB,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO;IAsB9D,cAAc,CACpB,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,GACZ,qBAAqB;IAwBjB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;CAiCnD;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAWnF"}
package/lib/protocol.js CHANGED
@@ -26,9 +26,6 @@ export class ProtocolHandler extends ProtocolOpHandler {
26
26
  // Join / leave signals are ignored for "write" clients in favor of join / leave ops
27
27
  this.quorum.on("addMember", (clientId, details) => audience.addMember(clientId, details.client));
28
28
  this.quorum.on("removeMember", (clientId) => audience.removeMember(clientId));
29
- for (const [clientId, details] of this.quorum.getMembers()) {
30
- this.audience.addMember(clientId, details.client);
31
- }
32
29
  }
33
30
  processMessage(message, local) {
34
31
  // Check and report if we're getting messages from a clientId that we previously
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.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 { IAudienceOwner } from \"@fluidframework/container-definitions/internal\";\nimport {\n\tIDocumentAttributes,\n\tIProcessMessageResult,\n\tISignalClient,\n\tMessageType,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { canBeCoalescedByService } from \"@fluidframework/driver-utils/internal\";\n\nimport { IBaseProtocolHandler, IQuorumSnapshot, ProtocolOpHandler } from \"./protocol/index.js\";\n\n// ADO: #1986: Start using enum from protocol-base.\nexport enum SignalType {\n\tClientJoin = \"join\", // same value as MessageType.ClientJoin,\n\tClientLeave = \"leave\", // same value as MessageType.ClientLeave,\n\tClear = \"clear\", // used only by client for synthetic signals\n}\n\n/**\n * Function to be used for creating a protocol handler.\n * @legacy\n * @alpha\n */\nexport type ProtocolHandlerBuilder = (\n\tattributes: IDocumentAttributes,\n\tsnapshot: IQuorumSnapshot,\n\t// TODO: use a real type (breaking change)\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tsendProposal: (key: string, value: any) => number,\n) => IProtocolHandler;\n\n/**\n * @legacy\n * @alpha\n */\nexport interface IProtocolHandler extends IBaseProtocolHandler {\n\treadonly audience: IAudienceOwner;\n\tprocessSignal(message: ISignalMessage);\n}\n\nexport class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandler {\n\tconstructor(\n\t\tattributes: IDocumentAttributes,\n\t\tquorumSnapshot: IQuorumSnapshot,\n\t\t// TODO: use a real type (breaking change)\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\tsendProposal: (key: string, value: any) => number,\n\t\tpublic readonly audience: IAudienceOwner,\n\t\tprivate readonly shouldClientHaveLeft: (clientId: string) => boolean,\n\t) {\n\t\tsuper(\n\t\t\tattributes.minimumSequenceNumber,\n\t\t\tattributes.sequenceNumber,\n\t\t\tquorumSnapshot.members,\n\t\t\tquorumSnapshot.proposals,\n\t\t\tquorumSnapshot.values,\n\t\t\tsendProposal,\n\t\t);\n\n\t\tfor (const [clientId, member] of this.quorum.getMembers()) {\n\t\t\taudience.addMember(clientId, member.client);\n\t\t}\n\n\t\t// Join / leave signals are ignored for \"write\" clients in favor of join / leave ops\n\t\tthis.quorum.on(\"addMember\", (clientId, details) =>\n\t\t\taudience.addMember(clientId, details.client),\n\t\t);\n\t\tthis.quorum.on(\"removeMember\", (clientId) => audience.removeMember(clientId));\n\t\tfor (const [clientId, details] of this.quorum.getMembers()) {\n\t\t\tthis.audience.addMember(clientId, details.client);\n\t\t}\n\t}\n\n\tpublic processMessage(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t): IProcessMessageResult {\n\t\t// Check and report if we're getting messages from a clientId that we previously\n\t\t// flagged as shouldHaveLeft, or from a client that's not in the quorum but should be\n\t\t// eslint-disable-next-line unicorn/no-null\n\t\tif (message.clientId != null) {\n\t\t\tconst client = this.quorum.getMember(message.clientId);\n\n\t\t\tif (client === undefined && message.type !== MessageType.ClientJoin) {\n\t\t\t\t// pre-0.58 error message: messageClientIdMissingFromQuorum\n\t\t\t\tthrow new Error(\"Remote message's clientId is missing from the quorum\");\n\t\t\t}\n\n\t\t\t// Here checking canBeCoalescedByService is used as an approximation of \"is benign to process despite being unexpected\".\n\t\t\t// It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the\n\t\t\t// document we don't need to blow up aggressively.\n\t\t\tif (this.shouldClientHaveLeft(message.clientId) && !canBeCoalescedByService(message)) {\n\t\t\t\t// pre-0.58 error message: messageClientIdShouldHaveLeft\n\t\t\t\tthrow new Error(\"Remote message's clientId already should have left\");\n\t\t\t}\n\t\t}\n\n\t\treturn super.processMessage(message, local);\n\t}\n\n\tpublic processSignal(message: ISignalMessage): void {\n\t\tconst innerContent = message.content as { content: unknown; type: string };\n\t\tswitch (innerContent.type) {\n\t\t\tcase SignalType.Clear: {\n\t\t\t\tconst members = this.audience.getMembers();\n\t\t\t\tfor (const [clientId, client] of members) {\n\t\t\t\t\tif (client.mode === \"read\") {\n\t\t\t\t\t\tthis.audience.removeMember(clientId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SignalType.ClientJoin: {\n\t\t\t\tconst newClient = innerContent.content as ISignalClient;\n\t\t\t\t// Ignore write clients - quorum will control such clients.\n\t\t\t\tif (newClient.client.mode === \"read\") {\n\t\t\t\t\tthis.audience.addMember(newClient.clientId, newClient.client);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SignalType.ClientLeave: {\n\t\t\t\tconst leftClientId = innerContent.content as string;\n\t\t\t\t// Ignore write clients - quorum will control such clients.\n\t\t\t\tif (this.audience.getMember(leftClientId)?.mode === \"read\") {\n\t\t\t\t\tthis.audience.removeMember(leftClientId);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Function to check whether the protocol handler should process the Signal.\n * The protocol handler should strictly handle only ClientJoin, ClientLeave\n * and Clear signal types.\n */\nexport function protocolHandlerShouldProcessSignal(message: ISignalMessage): boolean {\n\t// Signal originates from server\n\tif (message.clientId === null) {\n\t\tconst innerContent = message.content as { content: unknown; type: string };\n\t\treturn (\n\t\t\tinnerContent.type === SignalType.Clear ||\n\t\t\tinnerContent.type === SignalType.ClientJoin ||\n\t\t\tinnerContent.type === SignalType.ClientLeave\n\t\t);\n\t}\n\treturn false;\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.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 { IAudienceOwner } from \"@fluidframework/container-definitions/internal\";\nimport {\n\tIDocumentAttributes,\n\tIProcessMessageResult,\n\tISignalClient,\n\tMessageType,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { canBeCoalescedByService } from \"@fluidframework/driver-utils/internal\";\n\nimport { IBaseProtocolHandler, IQuorumSnapshot, ProtocolOpHandler } from \"./protocol/index.js\";\n\n// ADO: #1986: Start using enum from protocol-base.\nexport enum SignalType {\n\tClientJoin = \"join\", // same value as MessageType.ClientJoin,\n\tClientLeave = \"leave\", // same value as MessageType.ClientLeave,\n\tClear = \"clear\", // used only by client for synthetic signals\n}\n\n/**\n * Function to be used for creating a protocol handler.\n * @legacy\n * @alpha\n */\nexport type ProtocolHandlerBuilder = (\n\tattributes: IDocumentAttributes,\n\tsnapshot: IQuorumSnapshot,\n\t// TODO: use a real type (breaking change)\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tsendProposal: (key: string, value: any) => number,\n) => IProtocolHandler;\n\n/**\n * @legacy\n * @alpha\n */\nexport interface IProtocolHandler extends IBaseProtocolHandler {\n\treadonly audience: IAudienceOwner;\n\tprocessSignal(message: ISignalMessage);\n}\n\nexport class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandler {\n\tconstructor(\n\t\tattributes: IDocumentAttributes,\n\t\tquorumSnapshot: IQuorumSnapshot,\n\t\t// TODO: use a real type (breaking change)\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\tsendProposal: (key: string, value: any) => number,\n\t\tpublic readonly audience: IAudienceOwner,\n\t\tprivate readonly shouldClientHaveLeft: (clientId: string) => boolean,\n\t) {\n\t\tsuper(\n\t\t\tattributes.minimumSequenceNumber,\n\t\t\tattributes.sequenceNumber,\n\t\t\tquorumSnapshot.members,\n\t\t\tquorumSnapshot.proposals,\n\t\t\tquorumSnapshot.values,\n\t\t\tsendProposal,\n\t\t);\n\n\t\tfor (const [clientId, member] of this.quorum.getMembers()) {\n\t\t\taudience.addMember(clientId, member.client);\n\t\t}\n\n\t\t// Join / leave signals are ignored for \"write\" clients in favor of join / leave ops\n\t\tthis.quorum.on(\"addMember\", (clientId, details) =>\n\t\t\taudience.addMember(clientId, details.client),\n\t\t);\n\t\tthis.quorum.on(\"removeMember\", (clientId) => audience.removeMember(clientId));\n\t}\n\n\tpublic processMessage(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t): IProcessMessageResult {\n\t\t// Check and report if we're getting messages from a clientId that we previously\n\t\t// flagged as shouldHaveLeft, or from a client that's not in the quorum but should be\n\t\t// eslint-disable-next-line unicorn/no-null\n\t\tif (message.clientId != null) {\n\t\t\tconst client = this.quorum.getMember(message.clientId);\n\n\t\t\tif (client === undefined && message.type !== MessageType.ClientJoin) {\n\t\t\t\t// pre-0.58 error message: messageClientIdMissingFromQuorum\n\t\t\t\tthrow new Error(\"Remote message's clientId is missing from the quorum\");\n\t\t\t}\n\n\t\t\t// Here checking canBeCoalescedByService is used as an approximation of \"is benign to process despite being unexpected\".\n\t\t\t// It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the\n\t\t\t// document we don't need to blow up aggressively.\n\t\t\tif (this.shouldClientHaveLeft(message.clientId) && !canBeCoalescedByService(message)) {\n\t\t\t\t// pre-0.58 error message: messageClientIdShouldHaveLeft\n\t\t\t\tthrow new Error(\"Remote message's clientId already should have left\");\n\t\t\t}\n\t\t}\n\n\t\treturn super.processMessage(message, local);\n\t}\n\n\tpublic processSignal(message: ISignalMessage): void {\n\t\tconst innerContent = message.content as { content: unknown; type: string };\n\t\tswitch (innerContent.type) {\n\t\t\tcase SignalType.Clear: {\n\t\t\t\tconst members = this.audience.getMembers();\n\t\t\t\tfor (const [clientId, client] of members) {\n\t\t\t\t\tif (client.mode === \"read\") {\n\t\t\t\t\t\tthis.audience.removeMember(clientId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SignalType.ClientJoin: {\n\t\t\t\tconst newClient = innerContent.content as ISignalClient;\n\t\t\t\t// Ignore write clients - quorum will control such clients.\n\t\t\t\tif (newClient.client.mode === \"read\") {\n\t\t\t\t\tthis.audience.addMember(newClient.clientId, newClient.client);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SignalType.ClientLeave: {\n\t\t\t\tconst leftClientId = innerContent.content as string;\n\t\t\t\t// Ignore write clients - quorum will control such clients.\n\t\t\t\tif (this.audience.getMember(leftClientId)?.mode === \"read\") {\n\t\t\t\t\tthis.audience.removeMember(leftClientId);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Function to check whether the protocol handler should process the Signal.\n * The protocol handler should strictly handle only ClientJoin, ClientLeave\n * and Clear signal types.\n */\nexport function protocolHandlerShouldProcessSignal(message: ISignalMessage): boolean {\n\t// Signal originates from server\n\tif (message.clientId === null) {\n\t\tconst innerContent = message.content as { content: unknown; type: string };\n\t\treturn (\n\t\t\tinnerContent.type === SignalType.Clear ||\n\t\t\tinnerContent.type === SignalType.ClientJoin ||\n\t\t\tinnerContent.type === SignalType.ClientLeave\n\t\t);\n\t}\n\treturn false;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-loader",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Fluid container loader",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -119,13 +119,13 @@
119
119
  "temp-directory": "nyc/.nyc_output"
120
120
  },
121
121
  "dependencies": {
122
- "@fluid-internal/client-utils": "~2.4.0",
123
- "@fluidframework/container-definitions": "~2.4.0",
124
- "@fluidframework/core-interfaces": "~2.4.0",
125
- "@fluidframework/core-utils": "~2.4.0",
126
- "@fluidframework/driver-definitions": "~2.4.0",
127
- "@fluidframework/driver-utils": "~2.4.0",
128
- "@fluidframework/telemetry-utils": "~2.4.0",
122
+ "@fluid-internal/client-utils": "~2.5.0",
123
+ "@fluidframework/container-definitions": "~2.5.0",
124
+ "@fluidframework/core-interfaces": "~2.5.0",
125
+ "@fluidframework/core-utils": "~2.5.0",
126
+ "@fluidframework/driver-definitions": "~2.5.0",
127
+ "@fluidframework/driver-utils": "~2.5.0",
128
+ "@fluidframework/telemetry-utils": "~2.5.0",
129
129
  "@types/events_pkg": "npm:@types/events@^3.0.0",
130
130
  "@ungap/structured-clone": "^1.2.0",
131
131
  "debug": "^4.3.4",
@@ -135,14 +135,14 @@
135
135
  },
136
136
  "devDependencies": {
137
137
  "@arethetypeswrong/cli": "^0.16.4",
138
- "@biomejs/biome": "~1.8.3",
139
- "@fluid-internal/client-utils": "~2.4.0",
140
- "@fluid-internal/mocha-test-setup": "~2.4.0",
141
- "@fluid-private/test-loader-utils": "~2.4.0",
142
- "@fluid-tools/build-cli": "^0.48.0",
138
+ "@biomejs/biome": "~1.9.3",
139
+ "@fluid-internal/client-utils": "~2.5.0",
140
+ "@fluid-internal/mocha-test-setup": "~2.5.0",
141
+ "@fluid-private/test-loader-utils": "~2.5.0",
142
+ "@fluid-tools/build-cli": "^0.49.0",
143
143
  "@fluidframework/build-common": "^2.0.3",
144
- "@fluidframework/build-tools": "^0.48.0",
145
- "@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@~2.3.0",
144
+ "@fluidframework/build-tools": "^0.49.0",
145
+ "@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@~2.4.0",
146
146
  "@fluidframework/eslint-config-fluid": "^5.4.0",
147
147
  "@microsoft/api-extractor": "7.47.8",
148
148
  "@types/debug": "^4.1.5",
@@ -162,7 +162,7 @@
162
162
  "moment": "^2.21.0",
163
163
  "prettier": "~3.0.3",
164
164
  "rimraf": "^4.4.0",
165
- "sinon": "^17.0.1",
165
+ "sinon": "^18.0.1",
166
166
  "typescript": "~5.4.5"
167
167
  },
168
168
  "typeValidation": {
package/src/container.ts CHANGED
@@ -394,7 +394,7 @@ export class Container
394
394
  // to return container, so ignore this value and use undefined for opsBeforeReturn
395
395
  const mode: IContainerLoadMode = pendingLocalState
396
396
  ? { ...(loadMode ?? defaultMode), opsBeforeReturn: undefined }
397
- : loadMode ?? defaultMode;
397
+ : (loadMode ?? defaultMode);
398
398
 
399
399
  const onClosed = (err?: ICriticalContainerError): void => {
400
400
  // pre-0.58 error message: containerClosedWithoutErrorDuringLoad
@@ -602,7 +602,7 @@ export class Container
602
602
  * During initialization we pause the inbound queues. We track this state to ensure we only call resume once
603
603
  */
604
604
  private inboundQueuePausedFromInit = true;
605
- private firstConnection = true;
605
+ private connectionCount = 0;
606
606
  private readonly connectionTransitionTimes: number[] = [];
607
607
  private _loadedFromVersion: IVersion | undefined;
608
608
  private _dirtyContainer = false;
@@ -1719,7 +1719,7 @@ export class Container
1719
1719
  codeDetails,
1720
1720
  baseSnapshotTree,
1721
1721
  // give runtime a dummy value so it knows we're loading from a stash blob
1722
- pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined,
1722
+ pendingLocalState ? (pendingLocalState?.pendingRuntimeState ?? {}) : undefined,
1723
1723
  isInstanceOfISnapshot(baseSnapshot) ? baseSnapshot : undefined,
1724
1724
  );
1725
1725
 
@@ -2148,7 +2148,6 @@ export class Container
2148
2148
  const duration = time - this.connectionTransitionTimes[oldState];
2149
2149
 
2150
2150
  let durationFromDisconnected: number | undefined;
2151
- let connectionInitiationReason: string | undefined;
2152
2151
  let autoReconnect: ReconnectMode | undefined;
2153
2152
  let checkpointSequenceNumber: number | undefined;
2154
2153
  let opsBehind: number | undefined;
@@ -2167,7 +2166,6 @@ export class Container
2167
2166
  opsBehind = checkpointSequenceNumber - this.deltaManager.lastSequenceNumber;
2168
2167
  }
2169
2168
  }
2170
- connectionInitiationReason = this.firstConnection ? "InitialConnect" : "AutoReconnect";
2171
2169
  }
2172
2170
 
2173
2171
  this.mc.logger.sendPerformanceEvent(
@@ -2177,7 +2175,7 @@ export class Container
2177
2175
  duration,
2178
2176
  durationFromDisconnected,
2179
2177
  reason: reason?.text,
2180
- connectionInitiationReason,
2178
+ connectionCount: this.connectionCount,
2181
2179
  pendingClientId: this.connectionStateHandler.pendingClientId,
2182
2180
  clientId: this.connectionStateHandler.clientId,
2183
2181
  autoReconnect,
@@ -2187,6 +2185,7 @@ export class Container
2187
2185
  this.lastVisible === undefined ? undefined : performance.now() - this.lastVisible,
2188
2186
  checkpointSequenceNumber,
2189
2187
  quorumSize: this._protocolHandler?.quorum.getMembers().size,
2188
+ audienceSize: this._protocolHandler?.audience.getMembers().size,
2190
2189
  isDirty: this.isDirty,
2191
2190
  ...this._deltaManager.connectionProps,
2192
2191
  },
@@ -2194,7 +2193,7 @@ export class Container
2194
2193
  );
2195
2194
 
2196
2195
  if (value === ConnectionState.Connected) {
2197
- this.firstConnection = false;
2196
+ this.connectionCount++;
2198
2197
  }
2199
2198
  }
2200
2199
 
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-loader";
9
- export const pkgVersion = "2.4.0";
9
+ export const pkgVersion = "2.5.0";
package/src/protocol.ts CHANGED
@@ -73,9 +73,6 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
73
73
  audience.addMember(clientId, details.client),
74
74
  );
75
75
  this.quorum.on("removeMember", (clientId) => audience.removeMember(clientId));
76
- for (const [clientId, details] of this.quorum.getMembers()) {
77
- this.audience.addMember(clientId, details.client);
78
- }
79
76
  }
80
77
 
81
78
  public processMessage(