@fluid-experimental/attributor 2.0.0-dev-rc.2.0.0.246488 → 2.0.0-dev-rc.3.0.0.250606

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.
@@ -2,9 +2,9 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import { type IAudience, type IDeltaManager } from "@fluidframework/container-definitions";
5
6
  import { type IDocumentMessage, type ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
6
7
  import { type AttributionInfo } from "@fluidframework/runtime-definitions";
7
- import { type IAudience, type IDeltaManager } from "@fluidframework/container-definitions";
8
8
  /**
9
9
  * Provides lookup between attribution keys and their associated attribution information.
10
10
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"attributor.d.ts","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAE3F;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IAEjD;;;OAGG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAEhE;;OAEG;IACH,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CAIvD;AAED;;;GAGG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC7C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAE3D;;OAEG;gBACgB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAIvE;;OAEG;IACI,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAQvD;;OAEG;IACI,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAItE;;OAEG;IACI,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAG7D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,UAAW,YAAW,WAAW;gBAEvE,YAAY,EAAE,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,EACxE,QAAQ,EAAE,SAAS,EACnB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAmBrD"}
1
+ {"version":3,"file":"attributor.d.ts","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAE3F,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAG3E;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IAEjD;;;OAGG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAEhE;;OAEG;IACH,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CAIvD;AAED;;;GAGG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC7C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAE3D;;OAEG;gBACgB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAIvE;;OAEG;IACI,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAQvD;;OAEG;IACI,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAItE;;OAEG;IACI,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAG7D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,UAAW,YAAW,WAAW;gBAEvE,YAAY,EAAE,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,EACxE,QAAQ,EAAE,SAAS,EACnB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAmBrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"attributor.js","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,2DAAoD;AAMpD,qEAA6D;AA8B7D;;;GAGG;AACH,MAAa,UAAU;IAGtB;;OAEG;IACH,YAAmB,cAAoD;QACtE,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAW;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,EAAE;YACZ,MAAM,IAAI,4BAAU,CAAC,uDAAuD,GAAG,GAAG,CAAC,CAAC;SACpF;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,GAAW;QACvC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACI,OAAO;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;CACD;AAlCD,gCAkCC;AAED;;;;GAIG;AACH,MAAa,kBAAmB,SAAQ,UAAU;IACjD,YACC,YAAwE,EACxE,QAAmB,EACnB,cAAoD;QAEpD,KAAK,CAAC,cAAc,CAAC,CAAC;QACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,OAAkC,EAAE,EAAE;YAC5D,+FAA+F;YAC/F,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,QAAkB,CAAC,CAAC;YAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE;gBAC1B,uFAAuF;gBACvF,IAAA,mBAAM,EACL,MAAM,KAAK,SAAS,EACpB,KAAK,CAAC,oDAAoD,CAC1D,CAAC;gBACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE;oBAC1C,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,SAAS,EAAE,OAAO,CAAC,SAAS;iBAC5B,CAAC,CAAC;aACH;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;CACD;AAvBD,gDAuBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { type AttributionInfo } from \"@fluidframework/runtime-definitions\";\nimport { UsageError } from \"@fluidframework/telemetry-utils\";\nimport { type IAudience, type IDeltaManager } from \"@fluidframework/container-definitions\";\n\n/**\n * Provides lookup between attribution keys and their associated attribution information.\n * @internal\n */\nexport interface IAttributor {\n\t/**\n\t * Retrieves attribution information associated with a particular key.\n\t * @param key - Attribution key to look up.\n\t * @throws If no attribution information is recorded for that key.\n\t */\n\tgetAttributionInfo(key: number): AttributionInfo;\n\n\t/**\n\t * @param key - Attribution key to look up.\n\t * @returns the attribution information associated with the provided key, or undefined if no information exists.\n\t */\n\ttryGetAttributionInfo(key: number): AttributionInfo | undefined;\n\n\t/**\n\t * @returns an iterable of (attribution key, attribution info) pairs for each stored key.\n\t */\n\tentries(): IterableIterator<[number, AttributionInfo]>;\n\n\t// TODO:\n\t// - GC\n}\n\n/**\n * {@inheritdoc IAttributor}\n * @internal\n */\nexport class Attributor implements IAttributor {\n\tprotected readonly keyToInfo: Map<number, AttributionInfo>;\n\n\t/**\n\t * @param initialEntries - Any entries which should be populated on instantiation.\n\t */\n\tpublic constructor(initialEntries?: Iterable<[number, AttributionInfo]>) {\n\t\tthis.keyToInfo = new Map(initialEntries ?? []);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.getAttributionInfo}\n\t */\n\tpublic getAttributionInfo(key: number): AttributionInfo {\n\t\tconst result = this.tryGetAttributionInfo(key);\n\t\tif (!result) {\n\t\t\tthrow new UsageError(`Requested attribution information for unstored key: ${key}.`);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.tryGetAttributionInfo}\n\t */\n\tpublic tryGetAttributionInfo(key: number): AttributionInfo | undefined {\n\t\treturn this.keyToInfo.get(key);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.entries}\n\t */\n\tpublic entries(): IterableIterator<[number, AttributionInfo]> {\n\t\treturn this.keyToInfo.entries();\n\t}\n}\n\n/**\n * Attributor which listens to an op stream and records entries for each op.\n * Sequence numbers are used as attribution keys.\n * @internal\n */\nexport class OpStreamAttributor extends Attributor implements IAttributor {\n\tpublic constructor(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tinitialEntries?: Iterable<[number, AttributionInfo]>,\n\t) {\n\t\tsuper(initialEntries);\n\t\tdeltaManager.on(\"op\", (message: ISequencedDocumentMessage) => {\n\t\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t\tconst client = audience.getMember(message.clientId as string);\n\t\t\tif (message.type === \"op\") {\n\t\t\t\t// TODO: This case may be legitimate, and if so we need to figure out how to handle it.\n\t\t\t\tassert(\n\t\t\t\t\tclient !== undefined,\n\t\t\t\t\t0x4af /* Received message from user not in the audience */,\n\t\t\t\t);\n\t\t\t\tthis.keyToInfo.set(message.sequenceNumber, {\n\t\t\t\t\tuser: client.user,\n\t\t\t\t\ttimestamp: message.timestamp,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"attributor.js","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,2DAAoD;AAMpD,qEAA6D;AA6B7D;;;GAGG;AACH,MAAa,UAAU;IAGtB;;OAEG;IACH,YAAmB,cAAoD;QACtE,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAW;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,EAAE;YACZ,MAAM,IAAI,4BAAU,CAAC,uDAAuD,GAAG,GAAG,CAAC,CAAC;SACpF;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,GAAW;QACvC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACI,OAAO;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;CACD;AAlCD,gCAkCC;AAED;;;;GAIG;AACH,MAAa,kBAAmB,SAAQ,UAAU;IACjD,YACC,YAAwE,EACxE,QAAmB,EACnB,cAAoD;QAEpD,KAAK,CAAC,cAAc,CAAC,CAAC;QACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,OAAkC,EAAE,EAAE;YAC5D,+FAA+F;YAC/F,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,QAAkB,CAAC,CAAC;YAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE;gBAC1B,uFAAuF;gBACvF,IAAA,mBAAM,EACL,MAAM,KAAK,SAAS,EACpB,KAAK,CAAC,oDAAoD,CAC1D,CAAC;gBACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE;oBAC1C,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,SAAS,EAAE,OAAO,CAAC,SAAS;iBAC5B,CAAC,CAAC;aACH;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;CACD;AAvBD,gDAuBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { type IAudience, type IDeltaManager } from \"@fluidframework/container-definitions\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { type AttributionInfo } from \"@fluidframework/runtime-definitions\";\nimport { UsageError } from \"@fluidframework/telemetry-utils\";\n\n/**\n * Provides lookup between attribution keys and their associated attribution information.\n * @internal\n */\nexport interface IAttributor {\n\t/**\n\t * Retrieves attribution information associated with a particular key.\n\t * @param key - Attribution key to look up.\n\t * @throws If no attribution information is recorded for that key.\n\t */\n\tgetAttributionInfo(key: number): AttributionInfo;\n\n\t/**\n\t * @param key - Attribution key to look up.\n\t * @returns the attribution information associated with the provided key, or undefined if no information exists.\n\t */\n\ttryGetAttributionInfo(key: number): AttributionInfo | undefined;\n\n\t/**\n\t * @returns an iterable of (attribution key, attribution info) pairs for each stored key.\n\t */\n\tentries(): IterableIterator<[number, AttributionInfo]>;\n\n\t// TODO:\n\t// - GC\n}\n\n/**\n * {@inheritdoc IAttributor}\n * @internal\n */\nexport class Attributor implements IAttributor {\n\tprotected readonly keyToInfo: Map<number, AttributionInfo>;\n\n\t/**\n\t * @param initialEntries - Any entries which should be populated on instantiation.\n\t */\n\tpublic constructor(initialEntries?: Iterable<[number, AttributionInfo]>) {\n\t\tthis.keyToInfo = new Map(initialEntries ?? []);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.getAttributionInfo}\n\t */\n\tpublic getAttributionInfo(key: number): AttributionInfo {\n\t\tconst result = this.tryGetAttributionInfo(key);\n\t\tif (!result) {\n\t\t\tthrow new UsageError(`Requested attribution information for unstored key: ${key}.`);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.tryGetAttributionInfo}\n\t */\n\tpublic tryGetAttributionInfo(key: number): AttributionInfo | undefined {\n\t\treturn this.keyToInfo.get(key);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.entries}\n\t */\n\tpublic entries(): IterableIterator<[number, AttributionInfo]> {\n\t\treturn this.keyToInfo.entries();\n\t}\n}\n\n/**\n * Attributor which listens to an op stream and records entries for each op.\n * Sequence numbers are used as attribution keys.\n * @internal\n */\nexport class OpStreamAttributor extends Attributor implements IAttributor {\n\tpublic constructor(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tinitialEntries?: Iterable<[number, AttributionInfo]>,\n\t) {\n\t\tsuper(initialEntries);\n\t\tdeltaManager.on(\"op\", (message: ISequencedDocumentMessage) => {\n\t\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t\tconst client = audience.getMember(message.clientId as string);\n\t\t\tif (message.type === \"op\") {\n\t\t\t\t// TODO: This case may be legitimate, and if so we need to figure out how to handle it.\n\t\t\t\tassert(\n\t\t\t\t\tclient !== undefined,\n\t\t\t\t\t0x4af /* Received message from user not in the audience */,\n\t\t\t\t);\n\t\t\t\tthis.keyToInfo.set(message.sequenceNumber, {\n\t\t\t\t\tuser: client.user,\n\t\t\t\t\ttimestamp: message.timestamp,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lz4Encoder.d.ts","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAgBhE"}
1
+ {"version":3,"file":"lz4Encoder.d.ts","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AAEtE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAgBhE"}
@@ -5,8 +5,8 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.makeLZ4Encoder = void 0;
8
- const lz4js_1 = require("lz4js");
9
8
  const client_utils_1 = require("@fluid-internal/client-utils");
9
+ const lz4js_1 = require("lz4js");
10
10
  // TODO: document this
11
11
  // eslint-disable-next-line jsdoc/require-description
12
12
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lz4Encoder.js","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAA6C;AAC7C,+DAA8E;AAI9E,sBAAsB;AACtB,qDAAqD;AACrD;;GAEG;AACH,SAAgB,cAAc;IAC7B,OAAO;QACN,MAAM,EAAE,CAAC,OAAoB,EAAU,EAAE;YACxC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,6DAA6D;YAC7D,MAAM,UAAU,GAAG,IAAA,gBAAQ,EAAC,YAAY,CAAoB,CAAC;YAC7D,OAAO,IAAA,6BAAc,EAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,EAAE,CAAC,iBAAyB,EAAe,EAAE;YAClD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,IAAA,6BAAc,EAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC/E,6DAA6D;YAC7D,MAAM,YAAY,GAAG,IAAA,kBAAU,EAAC,UAAU,CAAiB,CAAC;YAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAgB,CAAC;YAClF,OAAO,OAAO,CAAC;QAChB,CAAC;KACD,CAAC;AACH,CAAC;AAhBD,wCAgBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { compress, decompress } from \"lz4js\";\nimport { bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { type Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { type Encoder } from \"./encoders.js\";\n\n// TODO: document this\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @alpha\n */\nexport function makeLZ4Encoder<T>(): Encoder<Jsonable<T>, string> {\n\treturn {\n\t\tencode: (decoded: Jsonable<T>): string => {\n\t\t\tconst uncompressed = new TextEncoder().encode(JSON.stringify(decoded));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst compressed = compress(uncompressed) as ArrayBufferLike;\n\t\t\treturn bufferToString(compressed, \"base64\");\n\t\t},\n\t\tdecode: (serializedSummary: string): Jsonable<T> => {\n\t\t\tconst compressed = new Uint8Array(stringToBuffer(serializedSummary, \"base64\"));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst uncompressed = decompress(compressed) as BufferSource;\n\t\t\tconst decoded = JSON.parse(new TextDecoder().decode(uncompressed)) as Jsonable<T>;\n\t\t\treturn decoded;\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"lz4Encoder.js","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAA8E;AAE9E,iCAA6C;AAG7C,sBAAsB;AACtB,qDAAqD;AACrD;;GAEG;AACH,SAAgB,cAAc;IAC7B,OAAO;QACN,MAAM,EAAE,CAAC,OAAoB,EAAU,EAAE;YACxC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,6DAA6D;YAC7D,MAAM,UAAU,GAAG,IAAA,gBAAQ,EAAC,YAAY,CAAoB,CAAC;YAC7D,OAAO,IAAA,6BAAc,EAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,EAAE,CAAC,iBAAyB,EAAe,EAAE;YAClD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,IAAA,6BAAc,EAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC/E,6DAA6D;YAC7D,MAAM,YAAY,GAAG,IAAA,kBAAU,EAAC,UAAU,CAAiB,CAAC;YAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAgB,CAAC;YAClF,OAAO,OAAO,CAAC;QAChB,CAAC;KACD,CAAC;AACH,CAAC;AAhBD,wCAgBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { type Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { compress, decompress } from \"lz4js\";\nimport { type Encoder } from \"./encoders.js\";\n\n// TODO: document this\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @alpha\n */\nexport function makeLZ4Encoder<T>(): Encoder<Jsonable<T>, string> {\n\treturn {\n\t\tencode: (decoded: Jsonable<T>): string => {\n\t\t\tconst uncompressed = new TextEncoder().encode(JSON.stringify(decoded));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst compressed = compress(uncompressed) as ArrayBufferLike;\n\t\t\treturn bufferToString(compressed, \"base64\");\n\t\t},\n\t\tdecode: (serializedSummary: string): Jsonable<T> => {\n\t\t\tconst compressed = new Uint8Array(stringToBuffer(serializedSummary, \"base64\"));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst uncompressed = decompress(compressed) as BufferSource;\n\t\t\tconst decoded = JSON.parse(new TextDecoder().decode(uncompressed)) as Jsonable<T>;\n\t\t\treturn decoded;\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mixinAttributor.d.ts","sourceRoot":"","sources":["../src/mixinAttributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,cAAc,EAInB,MAAM,qCAAqC,CAAC;AAoB7C;;GAEG;AACH,eAAO,MAAM,kBAAkB,sCAAsC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,yBAAgD,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACpE;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,CAAC;IAE1C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IAElC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,kBAAkB,CAE5D;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,UACrB,uBAAuB,KAC3B,uBAqHqC,CAAC"}
1
+ {"version":3,"file":"mixinAttributor.d.ts","sourceRoot":"","sources":["../src/mixinAttributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAUrE,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,cAAc,EAInB,MAAM,qCAAqC,CAAC;AAgB7C;;GAEG;AACH,eAAO,MAAM,kBAAkB,sCAAsC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,yBAAgD,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACpE;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,CAAC;IAE1C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IAElC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,kBAAkB,CAE5D;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,UACrB,uBAAuB,KAC3B,uBAqHqC,CAAC"}
@@ -5,10 +5,10 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.mixinAttributor = exports.createRuntimeAttributor = exports.IRuntimeAttributor = exports.enableOnNewFileKey = void 0;
8
- const container_runtime_1 = require("@fluidframework/container-runtime");
9
- const runtime_utils_1 = require("@fluidframework/runtime-utils");
10
8
  const client_utils_1 = require("@fluid-internal/client-utils");
9
+ const container_runtime_1 = require("@fluidframework/container-runtime");
11
10
  const core_utils_1 = require("@fluidframework/core-utils");
11
+ const runtime_utils_1 = require("@fluidframework/runtime-utils");
12
12
  const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
13
13
  const attributor_js_1 = require("./attributor.js");
14
14
  const encoders_js_1 = require("./encoders.js");
@@ -1 +1 @@
1
- {"version":3,"file":"mixinAttributor.js","sourceRoot":"","sources":["../src/mixinAttributor.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 {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n\ttype ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n\ttype IAudience,\n\ttype IContainerContext,\n\ttype IDeltaManager,\n} from \"@fluidframework/container-definitions\";\nimport { ContainerRuntime } from \"@fluidframework/container-runtime\";\nimport type { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport {\n\ttype AttributionInfo,\n\ttype AttributionKey,\n\ttype ISummaryTreeWithStats,\n\ttype ITelemetryContext,\n\ttype NamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions\";\nimport { addSummarizeResultToSummary, SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { type IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport { type IRequest, type IResponse, type FluidObject } from \"@fluidframework/core-interfaces\";\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport {\n\tcreateChildLogger,\n\tloggerToMonitoringContext,\n\tPerformanceEvent,\n\tUsageError,\n} from \"@fluidframework/telemetry-utils\";\nimport { Attributor, type IAttributor, OpStreamAttributor } from \"./attributor.js\";\nimport { AttributorSerializer, chain, deltaEncoder, type Encoder } from \"./encoders.js\";\nimport { makeLZ4Encoder } from \"./lz4Encoder.js\";\n\n// Summary tree keys\nconst attributorTreeName = \".attributor\";\nconst opBlobName = \"op\";\n\n/**\n * @internal\n */\nexport const enableOnNewFileKey = \"Fluid.Attribution.EnableOnNewFile\";\n\n/**\n * @internal\n */\nexport const IRuntimeAttributor: keyof IProvideRuntimeAttributor = \"IRuntimeAttributor\";\n\n/**\n * @internal\n */\nexport interface IProvideRuntimeAttributor {\n\treadonly IRuntimeAttributor: IRuntimeAttributor;\n}\n\n/**\n * Provides access to attribution information stored on the container runtime.\n *\n * @remarks Attributors are only populated after the container runtime into which they are being injected has initialized.\n *\n * @sealed\n * @internal\n */\nexport interface IRuntimeAttributor extends IProvideRuntimeAttributor {\n\t/**\n\t * @throws - If no AttributionInfo exists for this key.\n\t */\n\tget(key: AttributionKey): AttributionInfo;\n\n\t/**\n\t * @returns Whether any AttributionInfo exists for the provided key.\n\t */\n\thas(key: AttributionKey): boolean;\n\n\t/**\n\t * @returns Whether the runtime is currently tracking attribution information for the loaded container.\n\t * See {@link mixinAttributor} for more details on when this happens.\n\t */\n\treadonly isEnabled: boolean;\n}\n\n/**\n * Creates an `IRuntimeAttributor` for usage with {@link mixinAttributor}.\n *\n * @remarks The attributor will only be populated with data once it's passed via scope to a container runtime load flow.\n *\n * @internal\n */\nexport function createRuntimeAttributor(): IRuntimeAttributor {\n\treturn new RuntimeAttributor();\n}\n\n/**\n * Mixes in logic to load and store runtime-based attribution functionality.\n *\n * The `scope` passed to `load` should implement `IProvideRuntimeAttributor`.\n *\n * Existing documents without stored attributors will not start storing attribution information: if an\n * IRuntimeAttributor is passed via scope to load a document that never previously had attribution information,\n * that attributor's `has` method will always return `false`.\n * @param Base - base class, inherits from FluidAttributorRuntime\n * @internal\n */\nexport const mixinAttributor = (\n\tBase: typeof ContainerRuntime = ContainerRuntime,\n): typeof ContainerRuntime =>\n\tclass ContainerRuntimeWithAttributor extends Base {\n\t\tpublic static async loadRuntime(params: {\n\t\t\tcontext: IContainerContext;\n\t\t\tregistryEntries: NamedFluidDataStoreRegistryEntries;\n\t\t\texisting: boolean;\n\t\t\truntimeOptions?: IContainerRuntimeOptions;\n\t\t\tcontainerScope?: FluidObject;\n\t\t\tcontainerRuntimeCtor?: typeof ContainerRuntime;\n\t\t\t/**\n\t\t\t * @deprecated Will be removed once Loader LTS version is \"2.0.0-internal.7.0.0\". Migrate all usage of IFluidRouter to the \"entryPoint\" pattern. Refer to Removing-IFluidRouter.md\n\t\t\t */\n\t\t\trequestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;\n\t\t\tprovideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;\n\t\t}): Promise<ContainerRuntime> {\n\t\t\tconst {\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\texisting,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\tcontainerRuntimeCtor = ContainerRuntimeWithAttributor as unknown as typeof ContainerRuntime,\n\t\t\t} = params;\n\n\t\t\tconst runtimeAttributor = (\n\t\t\t\tcontainerScope as FluidObject<IProvideRuntimeAttributor> | undefined\n\t\t\t)?.IRuntimeAttributor;\n\t\t\tif (!runtimeAttributor) {\n\t\t\t\tthrow new UsageError(\n\t\t\t\t\t\"ContainerRuntimeWithAttributor must be passed a scope implementing IProvideRuntimeAttributor\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst pendingRuntimeState = context.pendingLocalState as {\n\t\t\t\tbaseSnapshot?: ISnapshotTree;\n\t\t\t};\n\t\t\tconst baseSnapshot: ISnapshotTree | undefined =\n\t\t\t\tpendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;\n\n\t\t\tconst { audience, deltaManager, taggedLogger } = context;\n\t\t\tassert(\n\t\t\t\taudience !== undefined,\n\t\t\t\t0x508 /* Audience must exist when instantiating attribution-providing runtime */,\n\t\t\t);\n\n\t\t\tconst mc = loggerToMonitoringContext(taggedLogger);\n\n\t\t\tconst shouldTrackAttribution = mc.config.getBoolean(enableOnNewFileKey) ?? false;\n\t\t\tif (shouldTrackAttribution) {\n\t\t\t\tconst { options } = context;\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t(options.attribution ??= {}).track = true;\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\tconst runtime = (await Base.loadRuntime({\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\t// ! This prop is needed for back-compat. Can be removed in 2.0.0-internal.8.0.0\n\t\t\t\tinitializeEntryPoint: provideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\texisting,\n\t\t\t\tcontainerRuntimeCtor,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t} as any)) as ContainerRuntimeWithAttributor;\n\t\t\truntime.runtimeAttributor = runtimeAttributor as RuntimeAttributor;\n\n\t\t\tconst logger = createChildLogger({ logger: runtime.logger, namespace: \"Attributor\" });\n\n\t\t\t// Note: this fetches attribution blobs relatively eagerly in the load flow; we may want to optimize\n\t\t\t// this to avoid blocking on such information until application actually requests some op-based attribution\n\t\t\t// info or we need to summarize. All that really needs to happen immediately is to start recording\n\t\t\t// op seq# -> attributionInfo for new ops.\n\t\t\tawait PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"initialize\",\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tawait runtime.runtimeAttributor?.initialize(\n\t\t\t\t\t\tdeltaManager,\n\t\t\t\t\t\taudience,\n\t\t\t\t\t\tbaseSnapshot,\n\t\t\t\t\t\tasync (id) => runtime.storage.readBlob(id),\n\t\t\t\t\t\tshouldTrackAttribution,\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tattributionEnabledInConfig: shouldTrackAttribution,\n\t\t\t\t\t\tattributionEnabledInDoc: runtime.runtimeAttributor\n\t\t\t\t\t\t\t? runtime.runtimeAttributor.isEnabled\n\t\t\t\t\t\t\t: false,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn runtime;\n\t\t}\n\n\t\tprivate runtimeAttributor: RuntimeAttributor | undefined;\n\n\t\tprotected addContainerStateToSummary(\n\t\t\tsummaryTree: ISummaryTreeWithStats,\n\t\t\tfullTree: boolean,\n\t\t\ttrackState: boolean,\n\t\t\ttelemetryContext?: ITelemetryContext,\n\t\t): void {\n\t\t\tsuper.addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext);\n\t\t\tconst attributorSummary = this.runtimeAttributor?.summarize();\n\t\t\tif (attributorSummary) {\n\t\t\t\taddSummarizeResultToSummary(summaryTree, attributorTreeName, attributorSummary);\n\t\t\t}\n\t\t}\n\t} as unknown as typeof ContainerRuntime;\n\nclass RuntimeAttributor implements IRuntimeAttributor {\n\tpublic get IRuntimeAttributor(): IRuntimeAttributor {\n\t\treturn this;\n\t}\n\n\tpublic get(key: AttributionKey): AttributionInfo {\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x509 /* RuntimeAttributor must be initialized before getAttributionInfo can be called */,\n\t\t);\n\n\t\tif (key.type === \"detached\") {\n\t\t\tthrow new Error(\"Attribution of detached keys is not yet supported.\");\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\t// Note: we can *almost* orchestrate this correctly with internal-only changes by looking up the current\n\t\t\t// client id in the audience. However, for read->write client transition, the container might have not yet\n\t\t\t// received a client id. This is left as a TODO as it might be more easily solved once the detached case\n\t\t\t// is settled (e.g. if it's reasonable for the host to know the current user information at container\n\t\t\t// creation time, we could just use that here as well).\n\t\t\tthrow new Error(\"Attribution of local keys is not yet supported.\");\n\t\t}\n\n\t\treturn this.opAttributor.getAttributionInfo(key.seq);\n\t}\n\n\tpublic has(key: AttributionKey): boolean {\n\t\tif (key.type === \"detached\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.opAttributor?.tryGetAttributionInfo(key.seq) !== undefined;\n\t}\n\n\tprivate encoder: Encoder<IAttributor, string> = {\n\t\tencode: unreachableCase,\n\t\tdecode: unreachableCase,\n\t};\n\n\tprivate opAttributor: IAttributor | undefined;\n\tpublic isEnabled = false;\n\n\tpublic async initialize(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tbaseSnapshot: ISnapshotTree | undefined,\n\t\treadBlob: (id: string) => Promise<ArrayBufferLike>,\n\t\tshouldAddAttributorOnNewFile: boolean,\n\t): Promise<void> {\n\t\tconst attributorTree = baseSnapshot?.trees[attributorTreeName];\n\t\t// Existing documents that don't already have a snapshot containing runtime attribution info shouldn't\n\t\t// inject any for now--this causes some back-compat integration problems that aren't fully worked out.\n\t\tconst shouldExcludeAttributor =\n\t\t\t(baseSnapshot !== undefined && attributorTree === undefined) ||\n\t\t\t(baseSnapshot === undefined && !shouldAddAttributorOnNewFile);\n\t\tif (shouldExcludeAttributor) {\n\t\t\t// This gives a consistent error for calls to `get` on keys that don't exist.\n\t\t\tthis.opAttributor = new Attributor();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isEnabled = true;\n\t\tthis.encoder = chain(\n\t\t\tnew AttributorSerializer(\n\t\t\t\t(entries) => new OpStreamAttributor(deltaManager, audience, entries),\n\t\t\t\tdeltaEncoder,\n\t\t\t),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\n\t\tif (attributorTree === undefined) {\n\t\t\tthis.opAttributor = new OpStreamAttributor(deltaManager, audience);\n\t\t} else {\n\t\t\tconst id = attributorTree.blobs[opBlobName];\n\t\t\tassert(\n\t\t\t\tid !== undefined,\n\t\t\t\t0x50a /* Attributor tree should have op attributor summary blob. */,\n\t\t\t);\n\t\t\tconst blobContents = await readBlob(id);\n\t\t\tconst attributorSnapshot = bufferToString(blobContents, \"utf8\");\n\t\t\tthis.opAttributor = this.encoder.decode(attributorSnapshot);\n\t\t}\n\t}\n\n\tpublic summarize(): ISummaryTreeWithStats | undefined {\n\t\tif (!this.isEnabled) {\n\t\t\t// Loaded existing document without attributor data: avoid injecting any data.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x50b /* RuntimeAttributor should be initialized before summarization */,\n\t\t);\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(opBlobName, this.encoder.encode(this.opAttributor));\n\t\treturn builder.getSummaryTree();\n\t}\n}\n"]}
1
+ {"version":3,"file":"mixinAttributor.js","sourceRoot":"","sources":["../src/mixinAttributor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport {\n\ttype IAudience,\n\ttype IContainerContext,\n\ttype IDeltaManager,\n} from \"@fluidframework/container-definitions\";\nimport { ContainerRuntime } from \"@fluidframework/container-runtime\";\nimport type { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport { type IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport { type FluidObject, type IRequest, type IResponse } from \"@fluidframework/core-interfaces\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n\ttype ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n\ttype AttributionInfo,\n\ttype AttributionKey,\n\ttype ISummaryTreeWithStats,\n\ttype ITelemetryContext,\n\ttype NamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions\";\nimport { SummaryTreeBuilder, addSummarizeResultToSummary } from \"@fluidframework/runtime-utils\";\nimport {\n\tPerformanceEvent,\n\tUsageError,\n\tcreateChildLogger,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { Attributor, type IAttributor, OpStreamAttributor } from \"./attributor.js\";\nimport { AttributorSerializer, type Encoder, chain, deltaEncoder } from \"./encoders.js\";\nimport { makeLZ4Encoder } from \"./lz4Encoder.js\";\n\n// Summary tree keys\nconst attributorTreeName = \".attributor\";\nconst opBlobName = \"op\";\n\n/**\n * @internal\n */\nexport const enableOnNewFileKey = \"Fluid.Attribution.EnableOnNewFile\";\n\n/**\n * @internal\n */\nexport const IRuntimeAttributor: keyof IProvideRuntimeAttributor = \"IRuntimeAttributor\";\n\n/**\n * @internal\n */\nexport interface IProvideRuntimeAttributor {\n\treadonly IRuntimeAttributor: IRuntimeAttributor;\n}\n\n/**\n * Provides access to attribution information stored on the container runtime.\n *\n * @remarks Attributors are only populated after the container runtime into which they are being injected has initialized.\n *\n * @sealed\n * @internal\n */\nexport interface IRuntimeAttributor extends IProvideRuntimeAttributor {\n\t/**\n\t * @throws - If no AttributionInfo exists for this key.\n\t */\n\tget(key: AttributionKey): AttributionInfo;\n\n\t/**\n\t * @returns Whether any AttributionInfo exists for the provided key.\n\t */\n\thas(key: AttributionKey): boolean;\n\n\t/**\n\t * @returns Whether the runtime is currently tracking attribution information for the loaded container.\n\t * See {@link mixinAttributor} for more details on when this happens.\n\t */\n\treadonly isEnabled: boolean;\n}\n\n/**\n * Creates an `IRuntimeAttributor` for usage with {@link mixinAttributor}.\n *\n * @remarks The attributor will only be populated with data once it's passed via scope to a container runtime load flow.\n *\n * @internal\n */\nexport function createRuntimeAttributor(): IRuntimeAttributor {\n\treturn new RuntimeAttributor();\n}\n\n/**\n * Mixes in logic to load and store runtime-based attribution functionality.\n *\n * The `scope` passed to `load` should implement `IProvideRuntimeAttributor`.\n *\n * Existing documents without stored attributors will not start storing attribution information: if an\n * IRuntimeAttributor is passed via scope to load a document that never previously had attribution information,\n * that attributor's `has` method will always return `false`.\n * @param Base - base class, inherits from FluidAttributorRuntime\n * @internal\n */\nexport const mixinAttributor = (\n\tBase: typeof ContainerRuntime = ContainerRuntime,\n): typeof ContainerRuntime =>\n\tclass ContainerRuntimeWithAttributor extends Base {\n\t\tpublic static async loadRuntime(params: {\n\t\t\tcontext: IContainerContext;\n\t\t\tregistryEntries: NamedFluidDataStoreRegistryEntries;\n\t\t\texisting: boolean;\n\t\t\truntimeOptions?: IContainerRuntimeOptions;\n\t\t\tcontainerScope?: FluidObject;\n\t\t\tcontainerRuntimeCtor?: typeof ContainerRuntime;\n\t\t\t/**\n\t\t\t * @deprecated Will be removed once Loader LTS version is \"2.0.0-internal.7.0.0\". Migrate all usage of IFluidRouter to the \"entryPoint\" pattern. Refer to Removing-IFluidRouter.md\n\t\t\t */\n\t\t\trequestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;\n\t\t\tprovideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;\n\t\t}): Promise<ContainerRuntime> {\n\t\t\tconst {\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\texisting,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\tcontainerRuntimeCtor = ContainerRuntimeWithAttributor as unknown as typeof ContainerRuntime,\n\t\t\t} = params;\n\n\t\t\tconst runtimeAttributor = (\n\t\t\t\tcontainerScope as FluidObject<IProvideRuntimeAttributor> | undefined\n\t\t\t)?.IRuntimeAttributor;\n\t\t\tif (!runtimeAttributor) {\n\t\t\t\tthrow new UsageError(\n\t\t\t\t\t\"ContainerRuntimeWithAttributor must be passed a scope implementing IProvideRuntimeAttributor\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst pendingRuntimeState = context.pendingLocalState as {\n\t\t\t\tbaseSnapshot?: ISnapshotTree;\n\t\t\t};\n\t\t\tconst baseSnapshot: ISnapshotTree | undefined =\n\t\t\t\tpendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;\n\n\t\t\tconst { audience, deltaManager, taggedLogger } = context;\n\t\t\tassert(\n\t\t\t\taudience !== undefined,\n\t\t\t\t0x508 /* Audience must exist when instantiating attribution-providing runtime */,\n\t\t\t);\n\n\t\t\tconst mc = loggerToMonitoringContext(taggedLogger);\n\n\t\t\tconst shouldTrackAttribution = mc.config.getBoolean(enableOnNewFileKey) ?? false;\n\t\t\tif (shouldTrackAttribution) {\n\t\t\t\tconst { options } = context;\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t(options.attribution ??= {}).track = true;\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\tconst runtime = (await Base.loadRuntime({\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\t// ! This prop is needed for back-compat. Can be removed in 2.0.0-internal.8.0.0\n\t\t\t\tinitializeEntryPoint: provideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\texisting,\n\t\t\t\tcontainerRuntimeCtor,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t} as any)) as ContainerRuntimeWithAttributor;\n\t\t\truntime.runtimeAttributor = runtimeAttributor as RuntimeAttributor;\n\n\t\t\tconst logger = createChildLogger({ logger: runtime.logger, namespace: \"Attributor\" });\n\n\t\t\t// Note: this fetches attribution blobs relatively eagerly in the load flow; we may want to optimize\n\t\t\t// this to avoid blocking on such information until application actually requests some op-based attribution\n\t\t\t// info or we need to summarize. All that really needs to happen immediately is to start recording\n\t\t\t// op seq# -> attributionInfo for new ops.\n\t\t\tawait PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"initialize\",\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tawait runtime.runtimeAttributor?.initialize(\n\t\t\t\t\t\tdeltaManager,\n\t\t\t\t\t\taudience,\n\t\t\t\t\t\tbaseSnapshot,\n\t\t\t\t\t\tasync (id) => runtime.storage.readBlob(id),\n\t\t\t\t\t\tshouldTrackAttribution,\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tattributionEnabledInConfig: shouldTrackAttribution,\n\t\t\t\t\t\tattributionEnabledInDoc: runtime.runtimeAttributor\n\t\t\t\t\t\t\t? runtime.runtimeAttributor.isEnabled\n\t\t\t\t\t\t\t: false,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn runtime;\n\t\t}\n\n\t\tprivate runtimeAttributor: RuntimeAttributor | undefined;\n\n\t\tprotected addContainerStateToSummary(\n\t\t\tsummaryTree: ISummaryTreeWithStats,\n\t\t\tfullTree: boolean,\n\t\t\ttrackState: boolean,\n\t\t\ttelemetryContext?: ITelemetryContext,\n\t\t): void {\n\t\t\tsuper.addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext);\n\t\t\tconst attributorSummary = this.runtimeAttributor?.summarize();\n\t\t\tif (attributorSummary) {\n\t\t\t\taddSummarizeResultToSummary(summaryTree, attributorTreeName, attributorSummary);\n\t\t\t}\n\t\t}\n\t} as unknown as typeof ContainerRuntime;\n\nclass RuntimeAttributor implements IRuntimeAttributor {\n\tpublic get IRuntimeAttributor(): IRuntimeAttributor {\n\t\treturn this;\n\t}\n\n\tpublic get(key: AttributionKey): AttributionInfo {\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x509 /* RuntimeAttributor must be initialized before getAttributionInfo can be called */,\n\t\t);\n\n\t\tif (key.type === \"detached\") {\n\t\t\tthrow new Error(\"Attribution of detached keys is not yet supported.\");\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\t// Note: we can *almost* orchestrate this correctly with internal-only changes by looking up the current\n\t\t\t// client id in the audience. However, for read->write client transition, the container might have not yet\n\t\t\t// received a client id. This is left as a TODO as it might be more easily solved once the detached case\n\t\t\t// is settled (e.g. if it's reasonable for the host to know the current user information at container\n\t\t\t// creation time, we could just use that here as well).\n\t\t\tthrow new Error(\"Attribution of local keys is not yet supported.\");\n\t\t}\n\n\t\treturn this.opAttributor.getAttributionInfo(key.seq);\n\t}\n\n\tpublic has(key: AttributionKey): boolean {\n\t\tif (key.type === \"detached\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.opAttributor?.tryGetAttributionInfo(key.seq) !== undefined;\n\t}\n\n\tprivate encoder: Encoder<IAttributor, string> = {\n\t\tencode: unreachableCase,\n\t\tdecode: unreachableCase,\n\t};\n\n\tprivate opAttributor: IAttributor | undefined;\n\tpublic isEnabled = false;\n\n\tpublic async initialize(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tbaseSnapshot: ISnapshotTree | undefined,\n\t\treadBlob: (id: string) => Promise<ArrayBufferLike>,\n\t\tshouldAddAttributorOnNewFile: boolean,\n\t): Promise<void> {\n\t\tconst attributorTree = baseSnapshot?.trees[attributorTreeName];\n\t\t// Existing documents that don't already have a snapshot containing runtime attribution info shouldn't\n\t\t// inject any for now--this causes some back-compat integration problems that aren't fully worked out.\n\t\tconst shouldExcludeAttributor =\n\t\t\t(baseSnapshot !== undefined && attributorTree === undefined) ||\n\t\t\t(baseSnapshot === undefined && !shouldAddAttributorOnNewFile);\n\t\tif (shouldExcludeAttributor) {\n\t\t\t// This gives a consistent error for calls to `get` on keys that don't exist.\n\t\t\tthis.opAttributor = new Attributor();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isEnabled = true;\n\t\tthis.encoder = chain(\n\t\t\tnew AttributorSerializer(\n\t\t\t\t(entries) => new OpStreamAttributor(deltaManager, audience, entries),\n\t\t\t\tdeltaEncoder,\n\t\t\t),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\n\t\tif (attributorTree === undefined) {\n\t\t\tthis.opAttributor = new OpStreamAttributor(deltaManager, audience);\n\t\t} else {\n\t\t\tconst id = attributorTree.blobs[opBlobName];\n\t\t\tassert(\n\t\t\t\tid !== undefined,\n\t\t\t\t0x50a /* Attributor tree should have op attributor summary blob. */,\n\t\t\t);\n\t\t\tconst blobContents = await readBlob(id);\n\t\t\tconst attributorSnapshot = bufferToString(blobContents, \"utf8\");\n\t\t\tthis.opAttributor = this.encoder.decode(attributorSnapshot);\n\t\t}\n\t}\n\n\tpublic summarize(): ISummaryTreeWithStats | undefined {\n\t\tif (!this.isEnabled) {\n\t\t\t// Loaded existing document without attributor data: avoid injecting any data.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x50b /* RuntimeAttributor should be initialized before summarization */,\n\t\t);\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(opBlobName, this.encoder.encode(this.opAttributor));\n\t\treturn builder.getSummaryTree();\n\t}\n}\n"]}
@@ -2,9 +2,9 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import { type IAudience, type IDeltaManager } from "@fluidframework/container-definitions";
5
6
  import { type IDocumentMessage, type ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
6
7
  import { type AttributionInfo } from "@fluidframework/runtime-definitions";
7
- import { type IAudience, type IDeltaManager } from "@fluidframework/container-definitions";
8
8
  /**
9
9
  * Provides lookup between attribution keys and their associated attribution information.
10
10
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"attributor.d.ts","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAE3F;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IAEjD;;;OAGG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAEhE;;OAEG;IACH,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CAIvD;AAED;;;GAGG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC7C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAE3D;;OAEG;gBACgB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAIvE;;OAEG;IACI,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAQvD;;OAEG;IACI,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAItE;;OAEG;IACI,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAG7D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,UAAW,YAAW,WAAW;gBAEvE,YAAY,EAAE,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,EACxE,QAAQ,EAAE,SAAS,EACnB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAmBrD"}
1
+ {"version":3,"file":"attributor.d.ts","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAE3F,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAG3E;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IAEjD;;;OAGG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAEhE;;OAEG;IACH,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CAIvD;AAED;;;GAGG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC7C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAE3D;;OAEG;gBACgB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAIvE;;OAEG;IACI,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAQvD;;OAEG;IACI,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAItE;;OAEG;IACI,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAG7D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,UAAW,YAAW,WAAW;gBAEvE,YAAY,EAAE,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,EACxE,QAAQ,EAAE,SAAS,EACnB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAmBrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"attributor.js","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAMpD,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AA8B7D;;;GAGG;AACH,MAAM,OAAO,UAAU;IAGtB;;OAEG;IACH,YAAmB,cAAoD;QACtE,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAW;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,EAAE;YACZ,MAAM,IAAI,UAAU,CAAC,uDAAuD,GAAG,GAAG,CAAC,CAAC;SACpF;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,GAAW;QACvC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACI,OAAO;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IACjD,YACC,YAAwE,EACxE,QAAmB,EACnB,cAAoD;QAEpD,KAAK,CAAC,cAAc,CAAC,CAAC;QACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,OAAkC,EAAE,EAAE;YAC5D,+FAA+F;YAC/F,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,QAAkB,CAAC,CAAC;YAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE;gBAC1B,uFAAuF;gBACvF,MAAM,CACL,MAAM,KAAK,SAAS,EACpB,KAAK,CAAC,oDAAoD,CAC1D,CAAC;gBACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE;oBAC1C,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,SAAS,EAAE,OAAO,CAAC,SAAS;iBAC5B,CAAC,CAAC;aACH;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { type AttributionInfo } from \"@fluidframework/runtime-definitions\";\nimport { UsageError } from \"@fluidframework/telemetry-utils\";\nimport { type IAudience, type IDeltaManager } from \"@fluidframework/container-definitions\";\n\n/**\n * Provides lookup between attribution keys and their associated attribution information.\n * @internal\n */\nexport interface IAttributor {\n\t/**\n\t * Retrieves attribution information associated with a particular key.\n\t * @param key - Attribution key to look up.\n\t * @throws If no attribution information is recorded for that key.\n\t */\n\tgetAttributionInfo(key: number): AttributionInfo;\n\n\t/**\n\t * @param key - Attribution key to look up.\n\t * @returns the attribution information associated with the provided key, or undefined if no information exists.\n\t */\n\ttryGetAttributionInfo(key: number): AttributionInfo | undefined;\n\n\t/**\n\t * @returns an iterable of (attribution key, attribution info) pairs for each stored key.\n\t */\n\tentries(): IterableIterator<[number, AttributionInfo]>;\n\n\t// TODO:\n\t// - GC\n}\n\n/**\n * {@inheritdoc IAttributor}\n * @internal\n */\nexport class Attributor implements IAttributor {\n\tprotected readonly keyToInfo: Map<number, AttributionInfo>;\n\n\t/**\n\t * @param initialEntries - Any entries which should be populated on instantiation.\n\t */\n\tpublic constructor(initialEntries?: Iterable<[number, AttributionInfo]>) {\n\t\tthis.keyToInfo = new Map(initialEntries ?? []);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.getAttributionInfo}\n\t */\n\tpublic getAttributionInfo(key: number): AttributionInfo {\n\t\tconst result = this.tryGetAttributionInfo(key);\n\t\tif (!result) {\n\t\t\tthrow new UsageError(`Requested attribution information for unstored key: ${key}.`);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.tryGetAttributionInfo}\n\t */\n\tpublic tryGetAttributionInfo(key: number): AttributionInfo | undefined {\n\t\treturn this.keyToInfo.get(key);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.entries}\n\t */\n\tpublic entries(): IterableIterator<[number, AttributionInfo]> {\n\t\treturn this.keyToInfo.entries();\n\t}\n}\n\n/**\n * Attributor which listens to an op stream and records entries for each op.\n * Sequence numbers are used as attribution keys.\n * @internal\n */\nexport class OpStreamAttributor extends Attributor implements IAttributor {\n\tpublic constructor(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tinitialEntries?: Iterable<[number, AttributionInfo]>,\n\t) {\n\t\tsuper(initialEntries);\n\t\tdeltaManager.on(\"op\", (message: ISequencedDocumentMessage) => {\n\t\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t\tconst client = audience.getMember(message.clientId as string);\n\t\t\tif (message.type === \"op\") {\n\t\t\t\t// TODO: This case may be legitimate, and if so we need to figure out how to handle it.\n\t\t\t\tassert(\n\t\t\t\t\tclient !== undefined,\n\t\t\t\t\t0x4af /* Received message from user not in the audience */,\n\t\t\t\t);\n\t\t\t\tthis.keyToInfo.set(message.sequenceNumber, {\n\t\t\t\t\tuser: client.user,\n\t\t\t\t\ttimestamp: message.timestamp,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"attributor.js","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAMpD,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AA6B7D;;;GAGG;AACH,MAAM,OAAO,UAAU;IAGtB;;OAEG;IACH,YAAmB,cAAoD;QACtE,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAW;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,EAAE;YACZ,MAAM,IAAI,UAAU,CAAC,uDAAuD,GAAG,GAAG,CAAC,CAAC;SACpF;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,GAAW;QACvC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACI,OAAO;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IACjD,YACC,YAAwE,EACxE,QAAmB,EACnB,cAAoD;QAEpD,KAAK,CAAC,cAAc,CAAC,CAAC;QACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,OAAkC,EAAE,EAAE;YAC5D,+FAA+F;YAC/F,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,QAAkB,CAAC,CAAC;YAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE;gBAC1B,uFAAuF;gBACvF,MAAM,CACL,MAAM,KAAK,SAAS,EACpB,KAAK,CAAC,oDAAoD,CAC1D,CAAC;gBACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE;oBAC1C,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,SAAS,EAAE,OAAO,CAAC,SAAS;iBAC5B,CAAC,CAAC;aACH;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { type IAudience, type IDeltaManager } from \"@fluidframework/container-definitions\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { type AttributionInfo } from \"@fluidframework/runtime-definitions\";\nimport { UsageError } from \"@fluidframework/telemetry-utils\";\n\n/**\n * Provides lookup between attribution keys and their associated attribution information.\n * @internal\n */\nexport interface IAttributor {\n\t/**\n\t * Retrieves attribution information associated with a particular key.\n\t * @param key - Attribution key to look up.\n\t * @throws If no attribution information is recorded for that key.\n\t */\n\tgetAttributionInfo(key: number): AttributionInfo;\n\n\t/**\n\t * @param key - Attribution key to look up.\n\t * @returns the attribution information associated with the provided key, or undefined if no information exists.\n\t */\n\ttryGetAttributionInfo(key: number): AttributionInfo | undefined;\n\n\t/**\n\t * @returns an iterable of (attribution key, attribution info) pairs for each stored key.\n\t */\n\tentries(): IterableIterator<[number, AttributionInfo]>;\n\n\t// TODO:\n\t// - GC\n}\n\n/**\n * {@inheritdoc IAttributor}\n * @internal\n */\nexport class Attributor implements IAttributor {\n\tprotected readonly keyToInfo: Map<number, AttributionInfo>;\n\n\t/**\n\t * @param initialEntries - Any entries which should be populated on instantiation.\n\t */\n\tpublic constructor(initialEntries?: Iterable<[number, AttributionInfo]>) {\n\t\tthis.keyToInfo = new Map(initialEntries ?? []);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.getAttributionInfo}\n\t */\n\tpublic getAttributionInfo(key: number): AttributionInfo {\n\t\tconst result = this.tryGetAttributionInfo(key);\n\t\tif (!result) {\n\t\t\tthrow new UsageError(`Requested attribution information for unstored key: ${key}.`);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.tryGetAttributionInfo}\n\t */\n\tpublic tryGetAttributionInfo(key: number): AttributionInfo | undefined {\n\t\treturn this.keyToInfo.get(key);\n\t}\n\n\t/**\n\t * {@inheritdoc IAttributor.entries}\n\t */\n\tpublic entries(): IterableIterator<[number, AttributionInfo]> {\n\t\treturn this.keyToInfo.entries();\n\t}\n}\n\n/**\n * Attributor which listens to an op stream and records entries for each op.\n * Sequence numbers are used as attribution keys.\n * @internal\n */\nexport class OpStreamAttributor extends Attributor implements IAttributor {\n\tpublic constructor(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tinitialEntries?: Iterable<[number, AttributionInfo]>,\n\t) {\n\t\tsuper(initialEntries);\n\t\tdeltaManager.on(\"op\", (message: ISequencedDocumentMessage) => {\n\t\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t\tconst client = audience.getMember(message.clientId as string);\n\t\t\tif (message.type === \"op\") {\n\t\t\t\t// TODO: This case may be legitimate, and if so we need to figure out how to handle it.\n\t\t\t\tassert(\n\t\t\t\t\tclient !== undefined,\n\t\t\t\t\t0x4af /* Received message from user not in the audience */,\n\t\t\t\t);\n\t\t\t\tthis.keyToInfo.set(message.sequenceNumber, {\n\t\t\t\t\tuser: client.user,\n\t\t\t\t\ttimestamp: message.timestamp,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lz4Encoder.d.ts","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAgBhE"}
1
+ {"version":3,"file":"lz4Encoder.d.ts","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AAEtE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAgBhE"}
package/lib/lz4Encoder.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { compress, decompress } from "lz4js";
6
5
  import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
6
+ import { compress, decompress } from "lz4js";
7
7
  // TODO: document this
8
8
  // eslint-disable-next-line jsdoc/require-description
9
9
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lz4Encoder.js","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI9E,sBAAsB;AACtB,qDAAqD;AACrD;;GAEG;AACH,MAAM,UAAU,cAAc;IAC7B,OAAO;QACN,MAAM,EAAE,CAAC,OAAoB,EAAU,EAAE;YACxC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,6DAA6D;YAC7D,MAAM,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAoB,CAAC;YAC7D,OAAO,cAAc,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,EAAE,CAAC,iBAAyB,EAAe,EAAE;YAClD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,cAAc,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC/E,6DAA6D;YAC7D,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAiB,CAAC;YAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAgB,CAAC;YAClF,OAAO,OAAO,CAAC;QAChB,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { compress, decompress } from \"lz4js\";\nimport { bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { type Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { type Encoder } from \"./encoders.js\";\n\n// TODO: document this\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @alpha\n */\nexport function makeLZ4Encoder<T>(): Encoder<Jsonable<T>, string> {\n\treturn {\n\t\tencode: (decoded: Jsonable<T>): string => {\n\t\t\tconst uncompressed = new TextEncoder().encode(JSON.stringify(decoded));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst compressed = compress(uncompressed) as ArrayBufferLike;\n\t\t\treturn bufferToString(compressed, \"base64\");\n\t\t},\n\t\tdecode: (serializedSummary: string): Jsonable<T> => {\n\t\t\tconst compressed = new Uint8Array(stringToBuffer(serializedSummary, \"base64\"));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst uncompressed = decompress(compressed) as BufferSource;\n\t\t\tconst decoded = JSON.parse(new TextDecoder().decode(uncompressed)) as Jsonable<T>;\n\t\t\treturn decoded;\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"lz4Encoder.js","sourceRoot":"","sources":["../src/lz4Encoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9E,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAG7C,sBAAsB;AACtB,qDAAqD;AACrD;;GAEG;AACH,MAAM,UAAU,cAAc;IAC7B,OAAO;QACN,MAAM,EAAE,CAAC,OAAoB,EAAU,EAAE;YACxC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,6DAA6D;YAC7D,MAAM,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAoB,CAAC;YAC7D,OAAO,cAAc,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,EAAE,CAAC,iBAAyB,EAAe,EAAE;YAClD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,cAAc,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC/E,6DAA6D;YAC7D,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAiB,CAAC;YAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAgB,CAAC;YAClF,OAAO,OAAO,CAAC;QAChB,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { type Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { compress, decompress } from \"lz4js\";\nimport { type Encoder } from \"./encoders.js\";\n\n// TODO: document this\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @alpha\n */\nexport function makeLZ4Encoder<T>(): Encoder<Jsonable<T>, string> {\n\treturn {\n\t\tencode: (decoded: Jsonable<T>): string => {\n\t\t\tconst uncompressed = new TextEncoder().encode(JSON.stringify(decoded));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst compressed = compress(uncompressed) as ArrayBufferLike;\n\t\t\treturn bufferToString(compressed, \"base64\");\n\t\t},\n\t\tdecode: (serializedSummary: string): Jsonable<T> => {\n\t\t\tconst compressed = new Uint8Array(stringToBuffer(serializedSummary, \"base64\"));\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\tconst uncompressed = decompress(compressed) as BufferSource;\n\t\t\tconst decoded = JSON.parse(new TextDecoder().decode(uncompressed)) as Jsonable<T>;\n\t\t\treturn decoded;\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mixinAttributor.d.ts","sourceRoot":"","sources":["../src/mixinAttributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,cAAc,EAInB,MAAM,qCAAqC,CAAC;AAoB7C;;GAEG;AACH,eAAO,MAAM,kBAAkB,sCAAsC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,yBAAgD,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACpE;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,CAAC;IAE1C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IAElC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,kBAAkB,CAE5D;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,UACrB,uBAAuB,KAC3B,uBAqHqC,CAAC"}
1
+ {"version":3,"file":"mixinAttributor.d.ts","sourceRoot":"","sources":["../src/mixinAttributor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAUrE,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,cAAc,EAInB,MAAM,qCAAqC,CAAC;AAgB7C;;GAEG;AACH,eAAO,MAAM,kBAAkB,sCAAsC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,yBAAgD,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACpE;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,CAAC;IAE1C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IAElC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,kBAAkB,CAE5D;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,UACrB,uBAAuB,KAC3B,uBAqHqC,CAAC"}
@@ -2,11 +2,11 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ContainerRuntime } from "@fluidframework/container-runtime";
6
- import { addSummarizeResultToSummary, SummaryTreeBuilder } from "@fluidframework/runtime-utils";
7
5
  import { bufferToString } from "@fluid-internal/client-utils";
6
+ import { ContainerRuntime } from "@fluidframework/container-runtime";
8
7
  import { assert, unreachableCase } from "@fluidframework/core-utils";
9
- import { createChildLogger, loggerToMonitoringContext, PerformanceEvent, UsageError, } from "@fluidframework/telemetry-utils";
8
+ import { SummaryTreeBuilder, addSummarizeResultToSummary } from "@fluidframework/runtime-utils";
9
+ import { PerformanceEvent, UsageError, createChildLogger, loggerToMonitoringContext, } from "@fluidframework/telemetry-utils";
10
10
  import { Attributor, OpStreamAttributor } from "./attributor.js";
11
11
  import { AttributorSerializer, chain, deltaEncoder } from "./encoders.js";
12
12
  import { makeLZ4Encoder } from "./lz4Encoder.js";
@@ -1 +1 @@
1
- {"version":3,"file":"mixinAttributor.js","sourceRoot":"","sources":["../src/mixinAttributor.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 {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n\ttype ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n\ttype IAudience,\n\ttype IContainerContext,\n\ttype IDeltaManager,\n} from \"@fluidframework/container-definitions\";\nimport { ContainerRuntime } from \"@fluidframework/container-runtime\";\nimport type { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport {\n\ttype AttributionInfo,\n\ttype AttributionKey,\n\ttype ISummaryTreeWithStats,\n\ttype ITelemetryContext,\n\ttype NamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions\";\nimport { addSummarizeResultToSummary, SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { type IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport { type IRequest, type IResponse, type FluidObject } from \"@fluidframework/core-interfaces\";\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport {\n\tcreateChildLogger,\n\tloggerToMonitoringContext,\n\tPerformanceEvent,\n\tUsageError,\n} from \"@fluidframework/telemetry-utils\";\nimport { Attributor, type IAttributor, OpStreamAttributor } from \"./attributor.js\";\nimport { AttributorSerializer, chain, deltaEncoder, type Encoder } from \"./encoders.js\";\nimport { makeLZ4Encoder } from \"./lz4Encoder.js\";\n\n// Summary tree keys\nconst attributorTreeName = \".attributor\";\nconst opBlobName = \"op\";\n\n/**\n * @internal\n */\nexport const enableOnNewFileKey = \"Fluid.Attribution.EnableOnNewFile\";\n\n/**\n * @internal\n */\nexport const IRuntimeAttributor: keyof IProvideRuntimeAttributor = \"IRuntimeAttributor\";\n\n/**\n * @internal\n */\nexport interface IProvideRuntimeAttributor {\n\treadonly IRuntimeAttributor: IRuntimeAttributor;\n}\n\n/**\n * Provides access to attribution information stored on the container runtime.\n *\n * @remarks Attributors are only populated after the container runtime into which they are being injected has initialized.\n *\n * @sealed\n * @internal\n */\nexport interface IRuntimeAttributor extends IProvideRuntimeAttributor {\n\t/**\n\t * @throws - If no AttributionInfo exists for this key.\n\t */\n\tget(key: AttributionKey): AttributionInfo;\n\n\t/**\n\t * @returns Whether any AttributionInfo exists for the provided key.\n\t */\n\thas(key: AttributionKey): boolean;\n\n\t/**\n\t * @returns Whether the runtime is currently tracking attribution information for the loaded container.\n\t * See {@link mixinAttributor} for more details on when this happens.\n\t */\n\treadonly isEnabled: boolean;\n}\n\n/**\n * Creates an `IRuntimeAttributor` for usage with {@link mixinAttributor}.\n *\n * @remarks The attributor will only be populated with data once it's passed via scope to a container runtime load flow.\n *\n * @internal\n */\nexport function createRuntimeAttributor(): IRuntimeAttributor {\n\treturn new RuntimeAttributor();\n}\n\n/**\n * Mixes in logic to load and store runtime-based attribution functionality.\n *\n * The `scope` passed to `load` should implement `IProvideRuntimeAttributor`.\n *\n * Existing documents without stored attributors will not start storing attribution information: if an\n * IRuntimeAttributor is passed via scope to load a document that never previously had attribution information,\n * that attributor's `has` method will always return `false`.\n * @param Base - base class, inherits from FluidAttributorRuntime\n * @internal\n */\nexport const mixinAttributor = (\n\tBase: typeof ContainerRuntime = ContainerRuntime,\n): typeof ContainerRuntime =>\n\tclass ContainerRuntimeWithAttributor extends Base {\n\t\tpublic static async loadRuntime(params: {\n\t\t\tcontext: IContainerContext;\n\t\t\tregistryEntries: NamedFluidDataStoreRegistryEntries;\n\t\t\texisting: boolean;\n\t\t\truntimeOptions?: IContainerRuntimeOptions;\n\t\t\tcontainerScope?: FluidObject;\n\t\t\tcontainerRuntimeCtor?: typeof ContainerRuntime;\n\t\t\t/**\n\t\t\t * @deprecated Will be removed once Loader LTS version is \"2.0.0-internal.7.0.0\". Migrate all usage of IFluidRouter to the \"entryPoint\" pattern. Refer to Removing-IFluidRouter.md\n\t\t\t */\n\t\t\trequestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;\n\t\t\tprovideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;\n\t\t}): Promise<ContainerRuntime> {\n\t\t\tconst {\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\texisting,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\tcontainerRuntimeCtor = ContainerRuntimeWithAttributor as unknown as typeof ContainerRuntime,\n\t\t\t} = params;\n\n\t\t\tconst runtimeAttributor = (\n\t\t\t\tcontainerScope as FluidObject<IProvideRuntimeAttributor> | undefined\n\t\t\t)?.IRuntimeAttributor;\n\t\t\tif (!runtimeAttributor) {\n\t\t\t\tthrow new UsageError(\n\t\t\t\t\t\"ContainerRuntimeWithAttributor must be passed a scope implementing IProvideRuntimeAttributor\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst pendingRuntimeState = context.pendingLocalState as {\n\t\t\t\tbaseSnapshot?: ISnapshotTree;\n\t\t\t};\n\t\t\tconst baseSnapshot: ISnapshotTree | undefined =\n\t\t\t\tpendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;\n\n\t\t\tconst { audience, deltaManager, taggedLogger } = context;\n\t\t\tassert(\n\t\t\t\taudience !== undefined,\n\t\t\t\t0x508 /* Audience must exist when instantiating attribution-providing runtime */,\n\t\t\t);\n\n\t\t\tconst mc = loggerToMonitoringContext(taggedLogger);\n\n\t\t\tconst shouldTrackAttribution = mc.config.getBoolean(enableOnNewFileKey) ?? false;\n\t\t\tif (shouldTrackAttribution) {\n\t\t\t\tconst { options } = context;\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t(options.attribution ??= {}).track = true;\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\tconst runtime = (await Base.loadRuntime({\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\t// ! This prop is needed for back-compat. Can be removed in 2.0.0-internal.8.0.0\n\t\t\t\tinitializeEntryPoint: provideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\texisting,\n\t\t\t\tcontainerRuntimeCtor,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t} as any)) as ContainerRuntimeWithAttributor;\n\t\t\truntime.runtimeAttributor = runtimeAttributor as RuntimeAttributor;\n\n\t\t\tconst logger = createChildLogger({ logger: runtime.logger, namespace: \"Attributor\" });\n\n\t\t\t// Note: this fetches attribution blobs relatively eagerly in the load flow; we may want to optimize\n\t\t\t// this to avoid blocking on such information until application actually requests some op-based attribution\n\t\t\t// info or we need to summarize. All that really needs to happen immediately is to start recording\n\t\t\t// op seq# -> attributionInfo for new ops.\n\t\t\tawait PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"initialize\",\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tawait runtime.runtimeAttributor?.initialize(\n\t\t\t\t\t\tdeltaManager,\n\t\t\t\t\t\taudience,\n\t\t\t\t\t\tbaseSnapshot,\n\t\t\t\t\t\tasync (id) => runtime.storage.readBlob(id),\n\t\t\t\t\t\tshouldTrackAttribution,\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tattributionEnabledInConfig: shouldTrackAttribution,\n\t\t\t\t\t\tattributionEnabledInDoc: runtime.runtimeAttributor\n\t\t\t\t\t\t\t? runtime.runtimeAttributor.isEnabled\n\t\t\t\t\t\t\t: false,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn runtime;\n\t\t}\n\n\t\tprivate runtimeAttributor: RuntimeAttributor | undefined;\n\n\t\tprotected addContainerStateToSummary(\n\t\t\tsummaryTree: ISummaryTreeWithStats,\n\t\t\tfullTree: boolean,\n\t\t\ttrackState: boolean,\n\t\t\ttelemetryContext?: ITelemetryContext,\n\t\t): void {\n\t\t\tsuper.addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext);\n\t\t\tconst attributorSummary = this.runtimeAttributor?.summarize();\n\t\t\tif (attributorSummary) {\n\t\t\t\taddSummarizeResultToSummary(summaryTree, attributorTreeName, attributorSummary);\n\t\t\t}\n\t\t}\n\t} as unknown as typeof ContainerRuntime;\n\nclass RuntimeAttributor implements IRuntimeAttributor {\n\tpublic get IRuntimeAttributor(): IRuntimeAttributor {\n\t\treturn this;\n\t}\n\n\tpublic get(key: AttributionKey): AttributionInfo {\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x509 /* RuntimeAttributor must be initialized before getAttributionInfo can be called */,\n\t\t);\n\n\t\tif (key.type === \"detached\") {\n\t\t\tthrow new Error(\"Attribution of detached keys is not yet supported.\");\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\t// Note: we can *almost* orchestrate this correctly with internal-only changes by looking up the current\n\t\t\t// client id in the audience. However, for read->write client transition, the container might have not yet\n\t\t\t// received a client id. This is left as a TODO as it might be more easily solved once the detached case\n\t\t\t// is settled (e.g. if it's reasonable for the host to know the current user information at container\n\t\t\t// creation time, we could just use that here as well).\n\t\t\tthrow new Error(\"Attribution of local keys is not yet supported.\");\n\t\t}\n\n\t\treturn this.opAttributor.getAttributionInfo(key.seq);\n\t}\n\n\tpublic has(key: AttributionKey): boolean {\n\t\tif (key.type === \"detached\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.opAttributor?.tryGetAttributionInfo(key.seq) !== undefined;\n\t}\n\n\tprivate encoder: Encoder<IAttributor, string> = {\n\t\tencode: unreachableCase,\n\t\tdecode: unreachableCase,\n\t};\n\n\tprivate opAttributor: IAttributor | undefined;\n\tpublic isEnabled = false;\n\n\tpublic async initialize(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tbaseSnapshot: ISnapshotTree | undefined,\n\t\treadBlob: (id: string) => Promise<ArrayBufferLike>,\n\t\tshouldAddAttributorOnNewFile: boolean,\n\t): Promise<void> {\n\t\tconst attributorTree = baseSnapshot?.trees[attributorTreeName];\n\t\t// Existing documents that don't already have a snapshot containing runtime attribution info shouldn't\n\t\t// inject any for now--this causes some back-compat integration problems that aren't fully worked out.\n\t\tconst shouldExcludeAttributor =\n\t\t\t(baseSnapshot !== undefined && attributorTree === undefined) ||\n\t\t\t(baseSnapshot === undefined && !shouldAddAttributorOnNewFile);\n\t\tif (shouldExcludeAttributor) {\n\t\t\t// This gives a consistent error for calls to `get` on keys that don't exist.\n\t\t\tthis.opAttributor = new Attributor();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isEnabled = true;\n\t\tthis.encoder = chain(\n\t\t\tnew AttributorSerializer(\n\t\t\t\t(entries) => new OpStreamAttributor(deltaManager, audience, entries),\n\t\t\t\tdeltaEncoder,\n\t\t\t),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\n\t\tif (attributorTree === undefined) {\n\t\t\tthis.opAttributor = new OpStreamAttributor(deltaManager, audience);\n\t\t} else {\n\t\t\tconst id = attributorTree.blobs[opBlobName];\n\t\t\tassert(\n\t\t\t\tid !== undefined,\n\t\t\t\t0x50a /* Attributor tree should have op attributor summary blob. */,\n\t\t\t);\n\t\t\tconst blobContents = await readBlob(id);\n\t\t\tconst attributorSnapshot = bufferToString(blobContents, \"utf8\");\n\t\t\tthis.opAttributor = this.encoder.decode(attributorSnapshot);\n\t\t}\n\t}\n\n\tpublic summarize(): ISummaryTreeWithStats | undefined {\n\t\tif (!this.isEnabled) {\n\t\t\t// Loaded existing document without attributor data: avoid injecting any data.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x50b /* RuntimeAttributor should be initialized before summarization */,\n\t\t);\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(opBlobName, this.encoder.encode(this.opAttributor));\n\t\treturn builder.getSummaryTree();\n\t}\n}\n"]}
1
+ {"version":3,"file":"mixinAttributor.js","sourceRoot":"","sources":["../src/mixinAttributor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport {\n\ttype IAudience,\n\ttype IContainerContext,\n\ttype IDeltaManager,\n} from \"@fluidframework/container-definitions\";\nimport { ContainerRuntime } from \"@fluidframework/container-runtime\";\nimport type { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport { type IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport { type FluidObject, type IRequest, type IResponse } from \"@fluidframework/core-interfaces\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport {\n\ttype IDocumentMessage,\n\ttype ISequencedDocumentMessage,\n\ttype ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n\ttype AttributionInfo,\n\ttype AttributionKey,\n\ttype ISummaryTreeWithStats,\n\ttype ITelemetryContext,\n\ttype NamedFluidDataStoreRegistryEntries,\n} from \"@fluidframework/runtime-definitions\";\nimport { SummaryTreeBuilder, addSummarizeResultToSummary } from \"@fluidframework/runtime-utils\";\nimport {\n\tPerformanceEvent,\n\tUsageError,\n\tcreateChildLogger,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { Attributor, type IAttributor, OpStreamAttributor } from \"./attributor.js\";\nimport { AttributorSerializer, type Encoder, chain, deltaEncoder } from \"./encoders.js\";\nimport { makeLZ4Encoder } from \"./lz4Encoder.js\";\n\n// Summary tree keys\nconst attributorTreeName = \".attributor\";\nconst opBlobName = \"op\";\n\n/**\n * @internal\n */\nexport const enableOnNewFileKey = \"Fluid.Attribution.EnableOnNewFile\";\n\n/**\n * @internal\n */\nexport const IRuntimeAttributor: keyof IProvideRuntimeAttributor = \"IRuntimeAttributor\";\n\n/**\n * @internal\n */\nexport interface IProvideRuntimeAttributor {\n\treadonly IRuntimeAttributor: IRuntimeAttributor;\n}\n\n/**\n * Provides access to attribution information stored on the container runtime.\n *\n * @remarks Attributors are only populated after the container runtime into which they are being injected has initialized.\n *\n * @sealed\n * @internal\n */\nexport interface IRuntimeAttributor extends IProvideRuntimeAttributor {\n\t/**\n\t * @throws - If no AttributionInfo exists for this key.\n\t */\n\tget(key: AttributionKey): AttributionInfo;\n\n\t/**\n\t * @returns Whether any AttributionInfo exists for the provided key.\n\t */\n\thas(key: AttributionKey): boolean;\n\n\t/**\n\t * @returns Whether the runtime is currently tracking attribution information for the loaded container.\n\t * See {@link mixinAttributor} for more details on when this happens.\n\t */\n\treadonly isEnabled: boolean;\n}\n\n/**\n * Creates an `IRuntimeAttributor` for usage with {@link mixinAttributor}.\n *\n * @remarks The attributor will only be populated with data once it's passed via scope to a container runtime load flow.\n *\n * @internal\n */\nexport function createRuntimeAttributor(): IRuntimeAttributor {\n\treturn new RuntimeAttributor();\n}\n\n/**\n * Mixes in logic to load and store runtime-based attribution functionality.\n *\n * The `scope` passed to `load` should implement `IProvideRuntimeAttributor`.\n *\n * Existing documents without stored attributors will not start storing attribution information: if an\n * IRuntimeAttributor is passed via scope to load a document that never previously had attribution information,\n * that attributor's `has` method will always return `false`.\n * @param Base - base class, inherits from FluidAttributorRuntime\n * @internal\n */\nexport const mixinAttributor = (\n\tBase: typeof ContainerRuntime = ContainerRuntime,\n): typeof ContainerRuntime =>\n\tclass ContainerRuntimeWithAttributor extends Base {\n\t\tpublic static async loadRuntime(params: {\n\t\t\tcontext: IContainerContext;\n\t\t\tregistryEntries: NamedFluidDataStoreRegistryEntries;\n\t\t\texisting: boolean;\n\t\t\truntimeOptions?: IContainerRuntimeOptions;\n\t\t\tcontainerScope?: FluidObject;\n\t\t\tcontainerRuntimeCtor?: typeof ContainerRuntime;\n\t\t\t/**\n\t\t\t * @deprecated Will be removed once Loader LTS version is \"2.0.0-internal.7.0.0\". Migrate all usage of IFluidRouter to the \"entryPoint\" pattern. Refer to Removing-IFluidRouter.md\n\t\t\t */\n\t\t\trequestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;\n\t\t\tprovideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;\n\t\t}): Promise<ContainerRuntime> {\n\t\t\tconst {\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\texisting,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\tcontainerRuntimeCtor = ContainerRuntimeWithAttributor as unknown as typeof ContainerRuntime,\n\t\t\t} = params;\n\n\t\t\tconst runtimeAttributor = (\n\t\t\t\tcontainerScope as FluidObject<IProvideRuntimeAttributor> | undefined\n\t\t\t)?.IRuntimeAttributor;\n\t\t\tif (!runtimeAttributor) {\n\t\t\t\tthrow new UsageError(\n\t\t\t\t\t\"ContainerRuntimeWithAttributor must be passed a scope implementing IProvideRuntimeAttributor\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst pendingRuntimeState = context.pendingLocalState as {\n\t\t\t\tbaseSnapshot?: ISnapshotTree;\n\t\t\t};\n\t\t\tconst baseSnapshot: ISnapshotTree | undefined =\n\t\t\t\tpendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;\n\n\t\t\tconst { audience, deltaManager, taggedLogger } = context;\n\t\t\tassert(\n\t\t\t\taudience !== undefined,\n\t\t\t\t0x508 /* Audience must exist when instantiating attribution-providing runtime */,\n\t\t\t);\n\n\t\t\tconst mc = loggerToMonitoringContext(taggedLogger);\n\n\t\t\tconst shouldTrackAttribution = mc.config.getBoolean(enableOnNewFileKey) ?? false;\n\t\t\tif (shouldTrackAttribution) {\n\t\t\t\tconst { options } = context;\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t(options.attribution ??= {}).track = true;\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\tconst runtime = (await Base.loadRuntime({\n\t\t\t\tcontext,\n\t\t\t\tregistryEntries,\n\t\t\t\trequestHandler,\n\t\t\t\tprovideEntryPoint,\n\t\t\t\t// ! This prop is needed for back-compat. Can be removed in 2.0.0-internal.8.0.0\n\t\t\t\tinitializeEntryPoint: provideEntryPoint,\n\t\t\t\truntimeOptions,\n\t\t\t\tcontainerScope,\n\t\t\t\texisting,\n\t\t\t\tcontainerRuntimeCtor,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t} as any)) as ContainerRuntimeWithAttributor;\n\t\t\truntime.runtimeAttributor = runtimeAttributor as RuntimeAttributor;\n\n\t\t\tconst logger = createChildLogger({ logger: runtime.logger, namespace: \"Attributor\" });\n\n\t\t\t// Note: this fetches attribution blobs relatively eagerly in the load flow; we may want to optimize\n\t\t\t// this to avoid blocking on such information until application actually requests some op-based attribution\n\t\t\t// info or we need to summarize. All that really needs to happen immediately is to start recording\n\t\t\t// op seq# -> attributionInfo for new ops.\n\t\t\tawait PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"initialize\",\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tawait runtime.runtimeAttributor?.initialize(\n\t\t\t\t\t\tdeltaManager,\n\t\t\t\t\t\taudience,\n\t\t\t\t\t\tbaseSnapshot,\n\t\t\t\t\t\tasync (id) => runtime.storage.readBlob(id),\n\t\t\t\t\t\tshouldTrackAttribution,\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tattributionEnabledInConfig: shouldTrackAttribution,\n\t\t\t\t\t\tattributionEnabledInDoc: runtime.runtimeAttributor\n\t\t\t\t\t\t\t? runtime.runtimeAttributor.isEnabled\n\t\t\t\t\t\t\t: false,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn runtime;\n\t\t}\n\n\t\tprivate runtimeAttributor: RuntimeAttributor | undefined;\n\n\t\tprotected addContainerStateToSummary(\n\t\t\tsummaryTree: ISummaryTreeWithStats,\n\t\t\tfullTree: boolean,\n\t\t\ttrackState: boolean,\n\t\t\ttelemetryContext?: ITelemetryContext,\n\t\t): void {\n\t\t\tsuper.addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext);\n\t\t\tconst attributorSummary = this.runtimeAttributor?.summarize();\n\t\t\tif (attributorSummary) {\n\t\t\t\taddSummarizeResultToSummary(summaryTree, attributorTreeName, attributorSummary);\n\t\t\t}\n\t\t}\n\t} as unknown as typeof ContainerRuntime;\n\nclass RuntimeAttributor implements IRuntimeAttributor {\n\tpublic get IRuntimeAttributor(): IRuntimeAttributor {\n\t\treturn this;\n\t}\n\n\tpublic get(key: AttributionKey): AttributionInfo {\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x509 /* RuntimeAttributor must be initialized before getAttributionInfo can be called */,\n\t\t);\n\n\t\tif (key.type === \"detached\") {\n\t\t\tthrow new Error(\"Attribution of detached keys is not yet supported.\");\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\t// Note: we can *almost* orchestrate this correctly with internal-only changes by looking up the current\n\t\t\t// client id in the audience. However, for read->write client transition, the container might have not yet\n\t\t\t// received a client id. This is left as a TODO as it might be more easily solved once the detached case\n\t\t\t// is settled (e.g. if it's reasonable for the host to know the current user information at container\n\t\t\t// creation time, we could just use that here as well).\n\t\t\tthrow new Error(\"Attribution of local keys is not yet supported.\");\n\t\t}\n\n\t\treturn this.opAttributor.getAttributionInfo(key.seq);\n\t}\n\n\tpublic has(key: AttributionKey): boolean {\n\t\tif (key.type === \"detached\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (key.type === \"local\") {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.opAttributor?.tryGetAttributionInfo(key.seq) !== undefined;\n\t}\n\n\tprivate encoder: Encoder<IAttributor, string> = {\n\t\tencode: unreachableCase,\n\t\tdecode: unreachableCase,\n\t};\n\n\tprivate opAttributor: IAttributor | undefined;\n\tpublic isEnabled = false;\n\n\tpublic async initialize(\n\t\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\taudience: IAudience,\n\t\tbaseSnapshot: ISnapshotTree | undefined,\n\t\treadBlob: (id: string) => Promise<ArrayBufferLike>,\n\t\tshouldAddAttributorOnNewFile: boolean,\n\t): Promise<void> {\n\t\tconst attributorTree = baseSnapshot?.trees[attributorTreeName];\n\t\t// Existing documents that don't already have a snapshot containing runtime attribution info shouldn't\n\t\t// inject any for now--this causes some back-compat integration problems that aren't fully worked out.\n\t\tconst shouldExcludeAttributor =\n\t\t\t(baseSnapshot !== undefined && attributorTree === undefined) ||\n\t\t\t(baseSnapshot === undefined && !shouldAddAttributorOnNewFile);\n\t\tif (shouldExcludeAttributor) {\n\t\t\t// This gives a consistent error for calls to `get` on keys that don't exist.\n\t\t\tthis.opAttributor = new Attributor();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isEnabled = true;\n\t\tthis.encoder = chain(\n\t\t\tnew AttributorSerializer(\n\t\t\t\t(entries) => new OpStreamAttributor(deltaManager, audience, entries),\n\t\t\t\tdeltaEncoder,\n\t\t\t),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\n\t\tif (attributorTree === undefined) {\n\t\t\tthis.opAttributor = new OpStreamAttributor(deltaManager, audience);\n\t\t} else {\n\t\t\tconst id = attributorTree.blobs[opBlobName];\n\t\t\tassert(\n\t\t\t\tid !== undefined,\n\t\t\t\t0x50a /* Attributor tree should have op attributor summary blob. */,\n\t\t\t);\n\t\t\tconst blobContents = await readBlob(id);\n\t\t\tconst attributorSnapshot = bufferToString(blobContents, \"utf8\");\n\t\t\tthis.opAttributor = this.encoder.decode(attributorSnapshot);\n\t\t}\n\t}\n\n\tpublic summarize(): ISummaryTreeWithStats | undefined {\n\t\tif (!this.isEnabled) {\n\t\t\t// Loaded existing document without attributor data: avoid injecting any data.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tassert(\n\t\t\tthis.opAttributor !== undefined,\n\t\t\t0x50b /* RuntimeAttributor should be initialized before summarization */,\n\t\t);\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(opBlobName, this.encoder.encode(this.opAttributor));\n\t\treturn builder.getSummaryTree();\n\t}\n}\n"]}
@@ -2,14 +2,14 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import * as path from "node:path";
6
- import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
7
5
  import { strict as assert } from "node:assert";
6
+ import { mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
7
+ import * as path from "node:path";
8
8
  import { chain, createWeightedGenerator, done, generatorFromArray, interleave, makeRandom, performFuzzActions, take, } from "@fluid-private/stochastic-test-utils";
9
- import { MockFluidDataStoreRuntime, MockStorage, MockContainerRuntimeFactoryForReconnection, } from "@fluidframework/test-runtime-utils";
9
+ import { createInsertOnlyAttributionPolicy } from "@fluidframework/merge-tree";
10
10
  import { SummaryType } from "@fluidframework/protocol-definitions";
11
11
  import { SharedString, SharedStringFactory } from "@fluidframework/sequence";
12
- import { createInsertOnlyAttributionPolicy } from "@fluidframework/merge-tree";
12
+ import { MockContainerRuntimeFactoryForReconnection, MockFluidDataStoreRuntime, MockStorage, } from "@fluidframework/test-runtime-utils";
13
13
  import { OpStreamAttributor } from "../../attributor.js";
14
14
  import { AttributorSerializer, chain as chainEncoders, deltaEncoder, } from "../../encoders.js";
15
15
  import { makeLZ4Encoder } from "../../lz4Encoder.js";
@@ -1 +1 @@
1
- {"version":3,"file":"sharedString.attribution.spec.js","sourceRoot":"","sources":["../../../src/test/attribution/sharedString.attribution.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport * as path from \"node:path\";\nimport { mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { strict as assert } from \"node:assert\";\nimport {\n\ttype AcceptanceCondition,\n\ttype BaseFuzzTestState,\n\tchain,\n\tcreateWeightedGenerator,\n\tdone,\n\ttype Generator,\n\tgeneratorFromArray,\n\tinterleave,\n\ttype IRandom,\n\tmakeRandom,\n\tperformFuzzActions,\n\ttype Reducer,\n\ttake,\n} from \"@fluid-private/stochastic-test-utils\";\nimport {\n\tMockFluidDataStoreRuntime,\n\tMockStorage,\n\tMockContainerRuntimeFactoryForReconnection,\n\ttype MockContainerRuntimeForReconnection,\n} from \"@fluidframework/test-runtime-utils\";\nimport {\n\ttype IChannelServices,\n\ttype IFluidDataStoreRuntime,\n\ttype Jsonable,\n} from \"@fluidframework/datastore-definitions\";\nimport { type IClient, type ISummaryTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { type IAudience } from \"@fluidframework/container-definitions\";\nimport { SharedString, SharedStringFactory } from \"@fluidframework/sequence\";\nimport { createInsertOnlyAttributionPolicy } from \"@fluidframework/merge-tree\";\nimport { type IAttributor, OpStreamAttributor } from \"../../attributor.js\";\nimport {\n\tAttributorSerializer,\n\tchain as chainEncoders,\n\tdeltaEncoder,\n\ttype Encoder,\n} from \"../../encoders.js\";\nimport { makeLZ4Encoder } from \"../../lz4Encoder.js\";\nimport { _dirname } from \"./dirname.cjs\";\n\nfunction makeMockAudience(clientIds: string[]): IAudience {\n\tconst clients = new Map<string, IClient>();\n\tfor (const [index, clientId] of clientIds.entries()) {\n\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\tconst stringId = String.fromCharCode(index + 65);\n\t\tconst name = stringId.repeat(10);\n\t\tconst userId = `${name}@microsoft.com`;\n\t\tconst email = userId;\n\t\tconst user = {\n\t\t\tid: userId,\n\t\t\tname,\n\t\t\temail,\n\t\t};\n\t\tclients.set(clientId, {\n\t\t\tmode: \"write\",\n\t\t\tdetails: { capabilities: { interactive: true } },\n\t\t\tpermission: [],\n\t\t\tuser,\n\t\t\tscopes: [],\n\t\t});\n\t}\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\treturn {\n\t\tgetMember: (clientId: string): IClient | undefined => {\n\t\t\treturn clients.get(clientId);\n\t\t},\n\t} as IAudience;\n}\n\ntype PropertySet = Record<string, unknown>;\n\ninterface Client {\n\tsharedString: SharedString;\n\tcontainerRuntime: MockContainerRuntimeForReconnection;\n}\n\ninterface FuzzTestState extends BaseFuzzTestState {\n\tcontainerRuntimeFactory: MockContainerRuntimeFactoryForReconnection;\n\tclients: Client[];\n\t// Note: eventually each client will have an Attributor. While design/implementation is in flux, this test suite\n\t// just stores a singleton attributor for the purposes of assessing its size.\n\tattributor?: IAttributor;\n\tserializer?: Encoder<IAttributor, string>;\n}\n\ninterface ClientSpec {\n\tstringId: string;\n}\n\ninterface RangeSpec {\n\tstart: number;\n\tend: number;\n}\n\ninterface AddText extends ClientSpec {\n\ttype: \"addText\";\n\tindex: number;\n\tcontent: string;\n\tprops?: PropertySet;\n}\n\ninterface RemoveRange extends ClientSpec, RangeSpec {\n\ttype: \"removeRange\";\n}\n\ninterface AnnotateRange extends ClientSpec, RangeSpec {\n\ttype: \"annotateRange\";\n\tproperties: PropertySet;\n}\n\ninterface Synchronize {\n\ttype: \"synchronize\";\n}\n\ntype TextOperation = AddText | RemoveRange | AnnotateRange;\n\ntype Operation = TextOperation | Synchronize;\n\ninterface OperationGenerationConfig {\n\t/**\n\t * Maximum length of the SharedString (locally) before no further AddText operations are generated.\n\t * Note due to concurrency, during test execution the actual length of the string may exceed this.\n\t */\n\tmaxStringLength?: number;\n\t/**\n\t * Maximum number of intervals (locally) before no further AddInterval operations are generated.\n\t * Note due to concurrency, during test execution the actual number of intervals may exceed this.\n\t */\n\tmaxIntervals?: number;\n\tmaxInsertLength?: number;\n\tpropertyNamePool?: string[];\n\tvalidateInterval?: number;\n}\n\nconst defaultOptions: Required<OperationGenerationConfig> = {\n\tmaxStringLength: 1000,\n\tmaxIntervals: 100,\n\tmaxInsertLength: 10,\n\tpropertyNamePool: [\"prop1\", \"prop2\", \"prop3\"],\n\tvalidateInterval: 100,\n};\n\nfunction makeOperationGenerator(\n\toptionsParam?: OperationGenerationConfig,\n): Generator<Operation, FuzzTestState> {\n\tconst options = { ...defaultOptions, ...optionsParam };\n\ttype ClientOpState = FuzzTestState & { sharedString: SharedString };\n\n\t// All subsequent helper functions are generators; note that they don't actually apply any operations.\n\tfunction startPosition({ random, sharedString }: ClientOpState): number {\n\t\treturn random.integer(0, Math.max(0, sharedString.getLength() - 1));\n\t}\n\n\tfunction exclusiveRange(state: ClientOpState): RangeSpec {\n\t\tconst start = startPosition(state);\n\t\tconst end = state.random.integer(start + 1, state.sharedString.getLength());\n\t\treturn { start, end };\n\t}\n\n\tfunction propertySet(state: ClientOpState): PropertySet {\n\t\tconst propNamesShuffled = [...options.propertyNamePool];\n\t\tstate.random.shuffle(propNamesShuffled);\n\t\tconst propsToChange = propNamesShuffled.slice(\n\t\t\t0,\n\t\t\tstate.random.integer(1, propNamesShuffled.length),\n\t\t);\n\t\tconst propSet: PropertySet = {};\n\t\tfor (const name of propsToChange) {\n\t\t\tpropSet[name] = state.random.string(5);\n\t\t}\n\t\treturn propSet;\n\t}\n\n\tfunction addText(state: ClientOpState): AddText {\n\t\tconst { random, sharedString } = state;\n\t\treturn {\n\t\t\ttype: \"addText\",\n\t\t\tindex: random.integer(0, sharedString.getLength()),\n\t\t\tcontent: random.string(random.integer(0, options.maxInsertLength)),\n\t\t\tstringId: sharedString.id,\n\t\t\tprops: random.bool(0.1) ? propertySet(state) : undefined,\n\t\t};\n\t}\n\n\tfunction removeRange(state: ClientOpState): RemoveRange {\n\t\treturn { type: \"removeRange\", ...exclusiveRange(state), stringId: state.sharedString.id };\n\t}\n\n\tfunction annotateRange(state: ClientOpState): AnnotateRange {\n\t\treturn {\n\t\t\ttype: \"annotateRange\",\n\t\t\t...exclusiveRange(state),\n\t\t\tproperties: propertySet(state),\n\t\t\tstringId: state.sharedString.id,\n\t\t};\n\t}\n\n\tconst lengthSatisfies =\n\t\t(criteria: (length: number) => boolean): AcceptanceCondition<ClientOpState> =>\n\t\t({ sharedString }) =>\n\t\t\tcriteria(sharedString.getLength());\n\tconst hasNonzeroLength = lengthSatisfies((length) => length > 0);\n\tconst isShorterThanMaxLength = lengthSatisfies((length) => length < options.maxStringLength);\n\n\tconst clientBaseOperationGenerator = createWeightedGenerator<Operation, ClientOpState>([\n\t\t[addText, 6, isShorterThanMaxLength],\n\t\t[removeRange, 2, hasNonzeroLength],\n\t\t[annotateRange, 1, hasNonzeroLength],\n\t]);\n\n\tconst clientOperationGenerator = (state: FuzzTestState): Operation | typeof done =>\n\t\tclientBaseOperationGenerator({\n\t\t\t...state,\n\t\t\tsharedString: state.random.pick(state.clients).sharedString,\n\t\t});\n\n\treturn interleave(\n\t\tclientOperationGenerator,\n\t\t() => ({ type: \"synchronize\" }),\n\t\toptions.validateInterval,\n\t);\n}\n\nfunction createSharedString(\n\trandom: IRandom,\n\tgenerator: Generator<Operation, FuzzTestState>,\n\tmakeSerializer?: (runtime: IFluidDataStoreRuntime) => Encoder<IAttributor, string>,\n): FuzzTestState {\n\tconst numClients = 3;\n\tconst clientIds = Array.from({ length: numClients }, () => random.uuid4());\n\tconst audience = makeMockAudience(clientIds);\n\tconst containerRuntimeFactory = new MockContainerRuntimeFactoryForReconnection();\n\tlet attributor: IAttributor | undefined;\n\tlet serializer: Encoder<IAttributor, string> | undefined;\n\tconst initialState: FuzzTestState = {\n\t\tclients: clientIds.map((clientId, index) => {\n\t\t\tconst dataStoreRuntime = new MockFluidDataStoreRuntime({ clientId });\n\t\t\tdataStoreRuntime.options = {\n\t\t\t\tattribution: {\n\t\t\t\t\ttrack: makeSerializer !== undefined,\n\t\t\t\t\tpolicyFactory: createInsertOnlyAttributionPolicy,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst { deltaManager } = dataStoreRuntime;\n\t\t\tconst sharedString = new SharedString(\n\t\t\t\tdataStoreRuntime,\n\t\t\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\t\t\tString.fromCharCode(index + 65),\n\t\t\t\tSharedStringFactory.Attributes,\n\t\t\t);\n\n\t\t\tif (index === 0 && makeSerializer !== undefined) {\n\t\t\t\tattributor = new OpStreamAttributor(deltaManager, audience);\n\t\t\t\tserializer = makeSerializer(dataStoreRuntime);\n\t\t\t\t// DeltaManager mock doesn't have high fidelity but attribution requires DataStoreRuntime implements\n\t\t\t\t// audience / op emission.\n\t\t\t\tlet opIndex = 0;\n\t\t\t\tsharedString.on(\"op\", (message) => {\n\t\t\t\t\topIndex++;\n\t\t\t\t\tmessage.timestamp = getTimestamp(opIndex);\n\t\t\t\t\tdeltaManager.emit(\"op\", message);\n\t\t\t\t});\n\t\t\t\tdataStoreRuntime.getAudience = (): IAudience => audience;\n\t\t\t}\n\n\t\t\tconst containerRuntime =\n\t\t\t\tcontainerRuntimeFactory.createContainerRuntime(dataStoreRuntime);\n\t\t\tconst services: IChannelServices = {\n\t\t\t\tdeltaConnection: dataStoreRuntime.createDeltaConnection(),\n\t\t\t\tobjectStorage: new MockStorage(),\n\t\t\t};\n\n\t\t\tsharedString.initializeLocal();\n\t\t\tsharedString.connect(services);\n\t\t\treturn { containerRuntime, sharedString };\n\t\t}),\n\t\tcontainerRuntimeFactory,\n\t\trandom,\n\t};\n\tinitialState.attributor = attributor;\n\tinitialState.serializer = serializer;\n\n\t// Small wrapper to avoid having to return the same state repeatedly; all operations in this suite mutate.\n\t// Also a reasonable point to inject logging of incremental state.\n\tconst statefully =\n\t\t<T>(\n\t\t\tstatefulReducer: (state: FuzzTestState, operation: T) => void,\n\t\t): Reducer<T, FuzzTestState> =>\n\t\t(state, operation) => {\n\t\t\tstatefulReducer(state, operation);\n\t\t\treturn state;\n\t\t};\n\n\treturn performFuzzActions(\n\t\tgenerator,\n\t\t{\n\t\t\taddText: statefully(({ clients }, { stringId, index, content, props }) => {\n\t\t\t\tconst { sharedString } = clients.find((c) => c.sharedString.id === stringId) ?? {};\n\t\t\t\tassert(sharedString);\n\t\t\t\tsharedString.insertText(index, content, props);\n\t\t\t}),\n\t\t\tremoveRange: statefully(({ clients }, { stringId, start, end }) => {\n\t\t\t\tconst { sharedString } = clients.find((c) => c.sharedString.id === stringId) ?? {};\n\t\t\t\tassert(sharedString);\n\t\t\t\tsharedString.removeRange(start, end);\n\t\t\t}),\n\t\t\tannotateRange: statefully(({ clients }, { stringId, properties, start, end }) => {\n\t\t\t\tconst { sharedString } = clients.find((c) => c.sharedString.id === stringId) ?? {};\n\t\t\t\tassert(sharedString);\n\t\t\t\tsharedString.annotateRange(start, end, properties);\n\t\t\t}),\n\t\t\tsynchronize: statefully((state) => {\n\t\t\t\tstate.containerRuntimeFactory.processAllMessages();\n\t\t\t}),\n\t\t},\n\t\tinitialState,\n\t);\n}\n\nconst directory = path.join(_dirname, \"../../../src/test/attribution/documents\");\n\ninterface TestPaths {\n\tdirectory: string;\n\toperations: string;\n}\n\nfunction getDocumentPaths(docName: string): TestPaths {\n\tmkdirSync(path.join(directory, docName), { recursive: true });\n\treturn {\n\t\tdirectory: path.join(directory, docName),\n\t\toperations: path.join(directory, docName, \"operations.json\"),\n\t};\n}\n\nfunction getDocuments(): string[] {\n\treturn readdirSync(directory).filter((name) => name !== \"README.md\");\n}\n\n// Format a number separating 3 digits by comma\nconst formatNumber = (num: number): string => num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n\nfunction spyOnOperations(baseGenerator: Generator<Operation, FuzzTestState>): {\n\tgenerator: Generator<Operation, FuzzTestState>;\n\toperations: Operation[];\n} {\n\tconst operations: Operation[] = [];\n\tconst generator = (state: FuzzTestState): Operation | typeof done => {\n\t\tconst operation = baseGenerator(state);\n\t\tif (operation !== done) {\n\t\t\toperations.push(operation);\n\t\t}\n\t\treturn operation;\n\t};\n\treturn { operations, generator };\n}\n\n/**\n * Type constraint for types that are likely deserializable from JSON or have a custom\n * alternate type.\n */\ntype JsonDeserializedTypeWith<T> =\n\t// eslint-disable-next-line @rushstack/no-new-null\n\t| null\n\t| boolean\n\t| number\n\t| string\n\t| T\n\t| { [P in string]: JsonDeserializedTypeWith<T> }\n\t| JsonDeserializedTypeWith<T>[];\n\ntype NonSymbolWithDefinedNonFunctionPropertyOf<T extends object> = Exclude<\n\t{\n\t\t// eslint-disable-next-line @typescript-eslint/ban-types\n\t\t[K in keyof T]: undefined extends T[K] ? never : T[K] extends Function ? never : K;\n\t}[keyof T],\n\tundefined | symbol\n>;\ntype NonSymbolWithUndefinedNonFunctionPropertyOf<T extends object> = Exclude<\n\t{\n\t\t// eslint-disable-next-line @typescript-eslint/ban-types\n\t\t[K in keyof T]: undefined extends T[K] ? (T[K] extends Function ? never : K) : never;\n\t}[keyof T],\n\tundefined | symbol\n>;\n\n/**\n * Used to constrain a type `T` to types that are deserializable from JSON.\n *\n * When used as a filter to inferred generic `T`, a compile-time error can be\n * produced trying to assign `JsonDeserialized<T>` to `T`.\n *\n * Deserialized JSON never contains `undefined` values, so properties with\n * `undefined` values become optional. If the original property was not already\n * optional, then compilation of assignment will fail.\n *\n * Similarly, function valued properties are removed.\n */\ntype JsonDeserialized<T, TReplaced = never> = /* test for 'any' */ boolean extends (\n\tT extends never ? true : false\n)\n\t? /* 'any' => */ JsonDeserializedTypeWith<TReplaced>\n\t: /* test for 'unknown' */ unknown extends T\n\t? /* 'unknown' => */ JsonDeserializedTypeWith<TReplaced>\n\t: // eslint-disable-next-line @rushstack/no-new-null\n\t/* test for Jsonable primitive types */ T extends null | boolean | number | string | TReplaced\n\t? /* primitive types => */ T\n\t: // eslint-disable-next-line @typescript-eslint/ban-types\n\t/* test for not a function */ Extract<T, Function> extends never\n\t? /* not a function => test for object */ T extends object\n\t\t? /* object => test for array */ T extends (infer E)[]\n\t\t\t? /* array => */ JsonDeserialized<E, TReplaced>[]\n\t\t\t: /* property bag => */\n\t\t\t /* properties with symbol keys or function values are removed */\n\t\t\t {\n\t\t\t\t\t/* properties with defined values are recursed */\n\t\t\t\t\t[K in NonSymbolWithDefinedNonFunctionPropertyOf<T>]: JsonDeserialized<\n\t\t\t\t\t\tT[K],\n\t\t\t\t\t\tTReplaced\n\t\t\t\t\t>;\n\t\t\t } & {\n\t\t\t\t\t/* properties that may have undefined values are optional */\n\t\t\t\t\t[K in NonSymbolWithUndefinedNonFunctionPropertyOf<T>]?: JsonDeserialized<\n\t\t\t\t\t\tT[K],\n\t\t\t\t\t\tTReplaced\n\t\t\t\t\t>;\n\t\t\t }\n\t\t: /* not an object => */ never\n\t: /* function => */ never;\n\nfunction readJson<T>(filepath: string): JsonDeserialized<T> {\n\treturn JSON.parse(readFileSync(filepath, { encoding: \"utf8\" })) as JsonDeserialized<T>;\n}\n\nfunction writeJson<T>(filepath: string, content: Jsonable<T>): void {\n\twriteFileSync(filepath, JSON.stringify(content, undefined, 4), { encoding: \"utf8\" });\n}\n\nconst validateInterval = 10;\n\nfunction getTimestamp(opIndex: number): number {\n\t// This is an arbitrary start point of the same magnitude as current data.\n\t// Wed Oct 12 2022 11:40:00 GMT-0700\n\tconst baseDate = 1665600000000;\n\treturn baseDate + Math.floor(opIndex / 10) * 5000;\n}\n\nfunction embedAttributionInProps(operations: Operation[]): Operation[] {\n\treturn operations.map((operation, index) => {\n\t\tif (operation.type === \"addText\") {\n\t\t\tconst name = operation.stringId.repeat(10);\n\t\t\tconst id = `${name}@contoso.com`;\n\t\t\tconst email = id;\n\t\t\tconst props = {\n\t\t\t\tattribution: {\n\t\t\t\t\tid,\n\t\t\t\t\tname,\n\t\t\t\t\temail,\n\t\t\t\t\ttimestamp: getTimestamp(index),\n\t\t\t\t},\n\t\t\t};\n\t\t\treturn {\n\t\t\t\t...operation,\n\t\t\t\tprops,\n\t\t\t};\n\t\t} else {\n\t\t\treturn operation;\n\t\t}\n\t});\n}\n\n// ISummaryTree is not serializable due to Uint8Array content in ISummaryBlob.\n// SerializableISummaryTree is a version of ISummaryTree with Uint8Array content removed.\ntype SerializableISummaryTree = ExcludeDeeply<ISummaryTree, Uint8Array>;\n\ntype ExcludeDeeply<T, Exclusion, TBase = Exclude<T, Exclusion>> = TBase extends object\n\t? { [K in keyof TBase]: ExcludeDeeply<TBase[K], Exclusion> }\n\t: TBase;\n\n/**\n * Validates that summary tree does not have a blob with a Uint8Array as content.\n *\n * @param summary - Summary tree to validate\n */\nfunction assertSerializableSummary(\n\tsummary: ISummaryTree,\n): asserts summary is SerializableISummaryTree {\n\tfor (const value of Object.values(summary.tree)) {\n\t\tswitch (value.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\tassertSerializableSummary(value);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tassert(typeof value.content === \"string\");\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\nconst summaryFromState = async (state: FuzzTestState): Promise<SerializableISummaryTree> => {\n\tstate.containerRuntimeFactory.processAllMessages();\n\tconst { sharedString } = state.clients[0];\n\tconst { summary } = await sharedString.summarize();\n\t// KLUDGE: For now, since attribution info isn't embedded at a proper location in the summary tree, just\n\t// add a property to the root so that its size is reported\n\tif (state.attributor && state.serializer) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\t(summary as any).attribution = state.serializer.encode(state.attributor);\n\t}\n\tassertSerializableSummary(summary);\n\treturn summary;\n};\n\nconst noopEncoder = {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tencode: (x: any): any => x,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tdecode: (x: any): any => x,\n};\n\nclass DataTable<T> {\n\tprivate readonly rows = new Map<string, T[]>();\n\tpublic constructor(private readonly columnNames: string[]) {}\n\n\tpublic addRow(name: string, data: T[]): void {\n\t\tthis.rows.set(name, data);\n\t}\n\n\tpublic log(dataToString: (t: T) => string = (t): string => `${t}`): void {\n\t\tconst namePaddingLength =\n\t\t\t1 + Math.max(...Array.from(this.rows.keys(), (docName) => docName.length));\n\t\tconst rowStrings = new Map<string, string[]>();\n\t\tconst paddingByColumn = this.columnNames.map((name) => name.length);\n\t\tfor (const [name, data] of this.rows.entries()) {\n\t\t\tconst dataStrings = data.map((entry: T) => dataToString(entry));\n\t\t\trowStrings.set(name, dataStrings);\n\t\t\tfor (const [i, s] of dataStrings.entries()) {\n\t\t\t\tpaddingByColumn[i] = Math.max(paddingByColumn[i], s.length);\n\t\t\t}\n\t\t}\n\t\tfor (const [i, _] of paddingByColumn.entries()) {\n\t\t\tpaddingByColumn[i]++;\n\t\t}\n\n\t\tconsole.log(\n\t\t\t[\n\t\t\t\t`${\"Name\".padEnd(namePaddingLength)}`,\n\t\t\t\t...this.columnNames.map((name, i) => `${name.padStart(paddingByColumn[i])} `),\n\t\t\t].join(\"|\"),\n\t\t);\n\n\t\tfor (const [name, result] of rowStrings.entries()) {\n\t\t\tconsole.log(\n\t\t\t\t`${name.padEnd(namePaddingLength)}|${result\n\t\t\t\t\t.map((s, i) => `${s.padStart(paddingByColumn[i])} `)\n\t\t\t\t\t.join(\"|\")}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nconst getSummaryLength = (summary: ISummaryTree): string =>\n\tformatNumber(JSON.stringify(summary).length);\n\ndescribe(\"SharedString Attribution\", () => {\n\t/**\n\t * This test suite is aimed at assessing the overhead of storing attribution information in a document.\n\t * See 'documents/README.md' for more details.\n\t */\n\n\tdescribe(\"using randomly generated documents\", () => {\n\t\t// Entries of this list produce documents which should contain the same attribution information but\n\t\t// stored in different formats. The \"None\" factory is an exception in that it contains no attribution\n\t\t// information, and is useful as a baseline for comparison.\n\t\tconst dataGenerators: {\n\t\t\tname: string;\n\t\t\tfactory: (operations: Operation[]) => FuzzTestState;\n\t\t\tfilename: string;\n\t\t}[] = [\n\t\t\t{\n\t\t\t\tname: \"None\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations)),\n\t\t\t\tfilename: \"no-attribution-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Prop\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(\n\t\t\t\t\t\tmakeRandom(0),\n\t\t\t\t\t\tgeneratorFromArray(embedAttributionInProps(operations)),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"prop-attribution-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"OpStreamAttributor without any compression\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations), (runtime) =>\n\t\t\t\t\t\tchainEncoders(\n\t\t\t\t\t\t\tnew AttributorSerializer(\n\t\t\t\t\t\t\t\t(entries) =>\n\t\t\t\t\t\t\t\t\tnew OpStreamAttributor(\n\t\t\t\t\t\t\t\t\t\truntime.deltaManager,\n\t\t\t\t\t\t\t\t\t\truntime.getAudience(),\n\t\t\t\t\t\t\t\t\t\tentries,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tnoopEncoder,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tnoopEncoder,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"attributor-no-compression-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"OpStreamAttributor without delta encoding\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations), (runtime) =>\n\t\t\t\t\t\tchainEncoders(\n\t\t\t\t\t\t\tnew AttributorSerializer(\n\t\t\t\t\t\t\t\t(entries) =>\n\t\t\t\t\t\t\t\t\tnew OpStreamAttributor(\n\t\t\t\t\t\t\t\t\t\truntime.deltaManager,\n\t\t\t\t\t\t\t\t\t\truntime.getAudience(),\n\t\t\t\t\t\t\t\t\t\tentries,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tnoopEncoder,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tmakeLZ4Encoder(),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"attributor-lz4-compression-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"OpStreamAttributor\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations), (runtime) =>\n\t\t\t\t\t\tchainEncoders(\n\t\t\t\t\t\t\tnew AttributorSerializer(\n\t\t\t\t\t\t\t\t(entries) =>\n\t\t\t\t\t\t\t\t\tnew OpStreamAttributor(\n\t\t\t\t\t\t\t\t\t\truntime.deltaManager,\n\t\t\t\t\t\t\t\t\t\truntime.getAudience(),\n\t\t\t\t\t\t\t\t\t\tentries,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tdeltaEncoder,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tmakeLZ4Encoder(),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"attributor-lz4-and-delta-snap.json\",\n\t\t\t},\n\t\t];\n\n\t\tit.skip(\"Generate a new document\", async () => {\n\t\t\tconst paths = getDocumentPaths(\"default\");\n\t\t\tconst attributionlessGenerator = chain(\n\t\t\t\ttake(100, makeOperationGenerator({ validateInterval })),\n\t\t\t\tgeneratorFromArray<Operation, FuzzTestState>([{ type: \"synchronize\" }]),\n\t\t\t);\n\n\t\t\tconst { generator, operations } = spyOnOperations(attributionlessGenerator);\n\t\t\tcreateSharedString(makeRandom(0), generator);\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any\n\t\t\twriteJson(paths.operations, operations as any);\n\n\t\t\tawait Promise.all(\n\t\t\t\tdataGenerators.map(async ({ filename, factory }) => {\n\t\t\t\t\tconst summary = await summaryFromState(factory(operations));\n\t\t\t\t\twriteJson(path.join(paths.directory, filename), summary);\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\n\t\tconst documents = getDocuments();\n\t\tfor (const document of documents) {\n\t\t\tdescribe(`document name: ${document} has an up-to-date`, () => {\n\t\t\t\tlet paths: TestPaths;\n\t\t\t\tlet operations: Operation[];\n\t\t\t\tbefore(() => {\n\t\t\t\t\tpaths = getDocumentPaths(document);\n\t\t\t\t\toperations = readJson<Operation[]>(paths.operations);\n\t\t\t\t});\n\n\t\t\t\tfor (const { filename, factory } of dataGenerators) {\n\t\t\t\t\tit(`snapshot at ${filename}`, async () => {\n\t\t\t\t\t\tconst expected = readJson(path.join(paths.directory, filename));\n\t\t\t\t\t\tconst actual = await summaryFromState(factory(operations));\n\t\t\t\t\t\tassert.deepEqual(actual, expected);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// Note: to see output, FLUID_TEST_VERBOSE needs to be enabled. Using the `test:mocha:verbose` script is\n\t\t// sufficient to do so.\n\t\tit(\"generate snapshot size impact report\", async () => {\n\t\t\tconst table = new DataTable<ISummaryTree>(dataGenerators.map(({ name }) => name));\n\t\t\tfor (const docName of documents) {\n\t\t\t\tconst paths = getDocumentPaths(docName);\n\t\t\t\tconst operations: Operation[] = readJson(paths.operations);\n\t\t\t\tconst data = await Promise.all(\n\t\t\t\t\tdataGenerators.map(async ({ factory }) =>\n\t\t\t\t\t\tsummaryFromState(factory(operations)),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\ttable.addRow(docName, data);\n\t\t\t}\n\n\t\t\ttable.log(getSummaryLength);\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"sharedString.attribution.spec.js","sourceRoot":"","sources":["../../../src/test/attribution/sharedString.attribution.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\nimport { mkdirSync, readFileSync, readdirSync, writeFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n\ttype AcceptanceCondition,\n\ttype BaseFuzzTestState,\n\ttype Generator,\n\ttype IRandom,\n\ttype Reducer,\n\tchain,\n\tcreateWeightedGenerator,\n\tdone,\n\tgeneratorFromArray,\n\tinterleave,\n\tmakeRandom,\n\tperformFuzzActions,\n\ttake,\n} from \"@fluid-private/stochastic-test-utils\";\nimport { type IAudience } from \"@fluidframework/container-definitions\";\nimport {\n\ttype IChannelServices,\n\ttype IFluidDataStoreRuntime,\n\ttype Jsonable,\n} from \"@fluidframework/datastore-definitions\";\nimport { createInsertOnlyAttributionPolicy } from \"@fluidframework/merge-tree\";\nimport { type IClient, type ISummaryTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { SharedString, SharedStringFactory } from \"@fluidframework/sequence\";\nimport {\n\tMockContainerRuntimeFactoryForReconnection,\n\ttype MockContainerRuntimeForReconnection,\n\tMockFluidDataStoreRuntime,\n\tMockStorage,\n} from \"@fluidframework/test-runtime-utils\";\nimport { type IAttributor, OpStreamAttributor } from \"../../attributor.js\";\nimport {\n\tAttributorSerializer,\n\ttype Encoder,\n\tchain as chainEncoders,\n\tdeltaEncoder,\n} from \"../../encoders.js\";\nimport { makeLZ4Encoder } from \"../../lz4Encoder.js\";\nimport { _dirname } from \"./dirname.cjs\";\n\nfunction makeMockAudience(clientIds: string[]): IAudience {\n\tconst clients = new Map<string, IClient>();\n\tfor (const [index, clientId] of clientIds.entries()) {\n\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\tconst stringId = String.fromCharCode(index + 65);\n\t\tconst name = stringId.repeat(10);\n\t\tconst userId = `${name}@microsoft.com`;\n\t\tconst email = userId;\n\t\tconst user = {\n\t\t\tid: userId,\n\t\t\tname,\n\t\t\temail,\n\t\t};\n\t\tclients.set(clientId, {\n\t\t\tmode: \"write\",\n\t\t\tdetails: { capabilities: { interactive: true } },\n\t\t\tpermission: [],\n\t\t\tuser,\n\t\t\tscopes: [],\n\t\t});\n\t}\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\treturn {\n\t\tgetMember: (clientId: string): IClient | undefined => {\n\t\t\treturn clients.get(clientId);\n\t\t},\n\t} as IAudience;\n}\n\ntype PropertySet = Record<string, unknown>;\n\ninterface Client {\n\tsharedString: SharedString;\n\tcontainerRuntime: MockContainerRuntimeForReconnection;\n}\n\ninterface FuzzTestState extends BaseFuzzTestState {\n\tcontainerRuntimeFactory: MockContainerRuntimeFactoryForReconnection;\n\tclients: Client[];\n\t// Note: eventually each client will have an Attributor. While design/implementation is in flux, this test suite\n\t// just stores a singleton attributor for the purposes of assessing its size.\n\tattributor?: IAttributor;\n\tserializer?: Encoder<IAttributor, string>;\n}\n\ninterface ClientSpec {\n\tstringId: string;\n}\n\ninterface RangeSpec {\n\tstart: number;\n\tend: number;\n}\n\ninterface AddText extends ClientSpec {\n\ttype: \"addText\";\n\tindex: number;\n\tcontent: string;\n\tprops?: PropertySet;\n}\n\ninterface RemoveRange extends ClientSpec, RangeSpec {\n\ttype: \"removeRange\";\n}\n\ninterface AnnotateRange extends ClientSpec, RangeSpec {\n\ttype: \"annotateRange\";\n\tproperties: PropertySet;\n}\n\ninterface Synchronize {\n\ttype: \"synchronize\";\n}\n\ntype TextOperation = AddText | RemoveRange | AnnotateRange;\n\ntype Operation = TextOperation | Synchronize;\n\ninterface OperationGenerationConfig {\n\t/**\n\t * Maximum length of the SharedString (locally) before no further AddText operations are generated.\n\t * Note due to concurrency, during test execution the actual length of the string may exceed this.\n\t */\n\tmaxStringLength?: number;\n\t/**\n\t * Maximum number of intervals (locally) before no further AddInterval operations are generated.\n\t * Note due to concurrency, during test execution the actual number of intervals may exceed this.\n\t */\n\tmaxIntervals?: number;\n\tmaxInsertLength?: number;\n\tpropertyNamePool?: string[];\n\tvalidateInterval?: number;\n}\n\nconst defaultOptions: Required<OperationGenerationConfig> = {\n\tmaxStringLength: 1000,\n\tmaxIntervals: 100,\n\tmaxInsertLength: 10,\n\tpropertyNamePool: [\"prop1\", \"prop2\", \"prop3\"],\n\tvalidateInterval: 100,\n};\n\nfunction makeOperationGenerator(\n\toptionsParam?: OperationGenerationConfig,\n): Generator<Operation, FuzzTestState> {\n\tconst options = { ...defaultOptions, ...optionsParam };\n\ttype ClientOpState = FuzzTestState & { sharedString: SharedString };\n\n\t// All subsequent helper functions are generators; note that they don't actually apply any operations.\n\tfunction startPosition({ random, sharedString }: ClientOpState): number {\n\t\treturn random.integer(0, Math.max(0, sharedString.getLength() - 1));\n\t}\n\n\tfunction exclusiveRange(state: ClientOpState): RangeSpec {\n\t\tconst start = startPosition(state);\n\t\tconst end = state.random.integer(start + 1, state.sharedString.getLength());\n\t\treturn { start, end };\n\t}\n\n\tfunction propertySet(state: ClientOpState): PropertySet {\n\t\tconst propNamesShuffled = [...options.propertyNamePool];\n\t\tstate.random.shuffle(propNamesShuffled);\n\t\tconst propsToChange = propNamesShuffled.slice(\n\t\t\t0,\n\t\t\tstate.random.integer(1, propNamesShuffled.length),\n\t\t);\n\t\tconst propSet: PropertySet = {};\n\t\tfor (const name of propsToChange) {\n\t\t\tpropSet[name] = state.random.string(5);\n\t\t}\n\t\treturn propSet;\n\t}\n\n\tfunction addText(state: ClientOpState): AddText {\n\t\tconst { random, sharedString } = state;\n\t\treturn {\n\t\t\ttype: \"addText\",\n\t\t\tindex: random.integer(0, sharedString.getLength()),\n\t\t\tcontent: random.string(random.integer(0, options.maxInsertLength)),\n\t\t\tstringId: sharedString.id,\n\t\t\tprops: random.bool(0.1) ? propertySet(state) : undefined,\n\t\t};\n\t}\n\n\tfunction removeRange(state: ClientOpState): RemoveRange {\n\t\treturn { type: \"removeRange\", ...exclusiveRange(state), stringId: state.sharedString.id };\n\t}\n\n\tfunction annotateRange(state: ClientOpState): AnnotateRange {\n\t\treturn {\n\t\t\ttype: \"annotateRange\",\n\t\t\t...exclusiveRange(state),\n\t\t\tproperties: propertySet(state),\n\t\t\tstringId: state.sharedString.id,\n\t\t};\n\t}\n\n\tconst lengthSatisfies =\n\t\t(criteria: (length: number) => boolean): AcceptanceCondition<ClientOpState> =>\n\t\t({ sharedString }) =>\n\t\t\tcriteria(sharedString.getLength());\n\tconst hasNonzeroLength = lengthSatisfies((length) => length > 0);\n\tconst isShorterThanMaxLength = lengthSatisfies((length) => length < options.maxStringLength);\n\n\tconst clientBaseOperationGenerator = createWeightedGenerator<Operation, ClientOpState>([\n\t\t[addText, 6, isShorterThanMaxLength],\n\t\t[removeRange, 2, hasNonzeroLength],\n\t\t[annotateRange, 1, hasNonzeroLength],\n\t]);\n\n\tconst clientOperationGenerator = (state: FuzzTestState): Operation | typeof done =>\n\t\tclientBaseOperationGenerator({\n\t\t\t...state,\n\t\t\tsharedString: state.random.pick(state.clients).sharedString,\n\t\t});\n\n\treturn interleave(\n\t\tclientOperationGenerator,\n\t\t() => ({ type: \"synchronize\" }),\n\t\toptions.validateInterval,\n\t);\n}\n\nfunction createSharedString(\n\trandom: IRandom,\n\tgenerator: Generator<Operation, FuzzTestState>,\n\tmakeSerializer?: (runtime: IFluidDataStoreRuntime) => Encoder<IAttributor, string>,\n): FuzzTestState {\n\tconst numClients = 3;\n\tconst clientIds = Array.from({ length: numClients }, () => random.uuid4());\n\tconst audience = makeMockAudience(clientIds);\n\tconst containerRuntimeFactory = new MockContainerRuntimeFactoryForReconnection();\n\tlet attributor: IAttributor | undefined;\n\tlet serializer: Encoder<IAttributor, string> | undefined;\n\tconst initialState: FuzzTestState = {\n\t\tclients: clientIds.map((clientId, index) => {\n\t\t\tconst dataStoreRuntime = new MockFluidDataStoreRuntime({ clientId });\n\t\t\tdataStoreRuntime.options = {\n\t\t\t\tattribution: {\n\t\t\t\t\ttrack: makeSerializer !== undefined,\n\t\t\t\t\tpolicyFactory: createInsertOnlyAttributionPolicy,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst { deltaManager } = dataStoreRuntime;\n\t\t\tconst sharedString = new SharedString(\n\t\t\t\tdataStoreRuntime,\n\t\t\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\t\t\tString.fromCharCode(index + 65),\n\t\t\t\tSharedStringFactory.Attributes,\n\t\t\t);\n\n\t\t\tif (index === 0 && makeSerializer !== undefined) {\n\t\t\t\tattributor = new OpStreamAttributor(deltaManager, audience);\n\t\t\t\tserializer = makeSerializer(dataStoreRuntime);\n\t\t\t\t// DeltaManager mock doesn't have high fidelity but attribution requires DataStoreRuntime implements\n\t\t\t\t// audience / op emission.\n\t\t\t\tlet opIndex = 0;\n\t\t\t\tsharedString.on(\"op\", (message) => {\n\t\t\t\t\topIndex++;\n\t\t\t\t\tmessage.timestamp = getTimestamp(opIndex);\n\t\t\t\t\tdeltaManager.emit(\"op\", message);\n\t\t\t\t});\n\t\t\t\tdataStoreRuntime.getAudience = (): IAudience => audience;\n\t\t\t}\n\n\t\t\tconst containerRuntime =\n\t\t\t\tcontainerRuntimeFactory.createContainerRuntime(dataStoreRuntime);\n\t\t\tconst services: IChannelServices = {\n\t\t\t\tdeltaConnection: dataStoreRuntime.createDeltaConnection(),\n\t\t\t\tobjectStorage: new MockStorage(),\n\t\t\t};\n\n\t\t\tsharedString.initializeLocal();\n\t\t\tsharedString.connect(services);\n\t\t\treturn { containerRuntime, sharedString };\n\t\t}),\n\t\tcontainerRuntimeFactory,\n\t\trandom,\n\t};\n\tinitialState.attributor = attributor;\n\tinitialState.serializer = serializer;\n\n\t// Small wrapper to avoid having to return the same state repeatedly; all operations in this suite mutate.\n\t// Also a reasonable point to inject logging of incremental state.\n\tconst statefully =\n\t\t<T>(\n\t\t\tstatefulReducer: (state: FuzzTestState, operation: T) => void,\n\t\t): Reducer<T, FuzzTestState> =>\n\t\t(state, operation) => {\n\t\t\tstatefulReducer(state, operation);\n\t\t\treturn state;\n\t\t};\n\n\treturn performFuzzActions(\n\t\tgenerator,\n\t\t{\n\t\t\taddText: statefully(({ clients }, { stringId, index, content, props }) => {\n\t\t\t\tconst { sharedString } = clients.find((c) => c.sharedString.id === stringId) ?? {};\n\t\t\t\tassert(sharedString);\n\t\t\t\tsharedString.insertText(index, content, props);\n\t\t\t}),\n\t\t\tremoveRange: statefully(({ clients }, { stringId, start, end }) => {\n\t\t\t\tconst { sharedString } = clients.find((c) => c.sharedString.id === stringId) ?? {};\n\t\t\t\tassert(sharedString);\n\t\t\t\tsharedString.removeRange(start, end);\n\t\t\t}),\n\t\t\tannotateRange: statefully(({ clients }, { stringId, properties, start, end }) => {\n\t\t\t\tconst { sharedString } = clients.find((c) => c.sharedString.id === stringId) ?? {};\n\t\t\t\tassert(sharedString);\n\t\t\t\tsharedString.annotateRange(start, end, properties);\n\t\t\t}),\n\t\t\tsynchronize: statefully((state) => {\n\t\t\t\tstate.containerRuntimeFactory.processAllMessages();\n\t\t\t}),\n\t\t},\n\t\tinitialState,\n\t);\n}\n\nconst directory = path.join(_dirname, \"../../../src/test/attribution/documents\");\n\ninterface TestPaths {\n\tdirectory: string;\n\toperations: string;\n}\n\nfunction getDocumentPaths(docName: string): TestPaths {\n\tmkdirSync(path.join(directory, docName), { recursive: true });\n\treturn {\n\t\tdirectory: path.join(directory, docName),\n\t\toperations: path.join(directory, docName, \"operations.json\"),\n\t};\n}\n\nfunction getDocuments(): string[] {\n\treturn readdirSync(directory).filter((name) => name !== \"README.md\");\n}\n\n// Format a number separating 3 digits by comma\nconst formatNumber = (num: number): string => num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n\nfunction spyOnOperations(baseGenerator: Generator<Operation, FuzzTestState>): {\n\tgenerator: Generator<Operation, FuzzTestState>;\n\toperations: Operation[];\n} {\n\tconst operations: Operation[] = [];\n\tconst generator = (state: FuzzTestState): Operation | typeof done => {\n\t\tconst operation = baseGenerator(state);\n\t\tif (operation !== done) {\n\t\t\toperations.push(operation);\n\t\t}\n\t\treturn operation;\n\t};\n\treturn { operations, generator };\n}\n\n/**\n * Type constraint for types that are likely deserializable from JSON or have a custom\n * alternate type.\n */\ntype JsonDeserializedTypeWith<T> =\n\t// eslint-disable-next-line @rushstack/no-new-null\n\t| null\n\t| boolean\n\t| number\n\t| string\n\t| T\n\t| { [P in string]: JsonDeserializedTypeWith<T> }\n\t| JsonDeserializedTypeWith<T>[];\n\ntype NonSymbolWithDefinedNonFunctionPropertyOf<T extends object> = Exclude<\n\t{\n\t\t// eslint-disable-next-line @typescript-eslint/ban-types\n\t\t[K in keyof T]: undefined extends T[K] ? never : T[K] extends Function ? never : K;\n\t}[keyof T],\n\tundefined | symbol\n>;\ntype NonSymbolWithUndefinedNonFunctionPropertyOf<T extends object> = Exclude<\n\t{\n\t\t// eslint-disable-next-line @typescript-eslint/ban-types\n\t\t[K in keyof T]: undefined extends T[K] ? (T[K] extends Function ? never : K) : never;\n\t}[keyof T],\n\tundefined | symbol\n>;\n\n/**\n * Used to constrain a type `T` to types that are deserializable from JSON.\n *\n * When used as a filter to inferred generic `T`, a compile-time error can be\n * produced trying to assign `JsonDeserialized<T>` to `T`.\n *\n * Deserialized JSON never contains `undefined` values, so properties with\n * `undefined` values become optional. If the original property was not already\n * optional, then compilation of assignment will fail.\n *\n * Similarly, function valued properties are removed.\n */\ntype JsonDeserialized<T, TReplaced = never> = /* test for 'any' */ boolean extends (\n\tT extends never ? true : false\n)\n\t? /* 'any' => */ JsonDeserializedTypeWith<TReplaced>\n\t: /* test for 'unknown' */ unknown extends T\n\t? /* 'unknown' => */ JsonDeserializedTypeWith<TReplaced>\n\t: // eslint-disable-next-line @rushstack/no-new-null\n\t/* test for Jsonable primitive types */ T extends null | boolean | number | string | TReplaced\n\t? /* primitive types => */ T\n\t: // eslint-disable-next-line @typescript-eslint/ban-types\n\t/* test for not a function */ Extract<T, Function> extends never\n\t? /* not a function => test for object */ T extends object\n\t\t? /* object => test for array */ T extends (infer E)[]\n\t\t\t? /* array => */ JsonDeserialized<E, TReplaced>[]\n\t\t\t: /* property bag => */\n\t\t\t /* properties with symbol keys or function values are removed */\n\t\t\t {\n\t\t\t\t\t/* properties with defined values are recursed */\n\t\t\t\t\t[K in NonSymbolWithDefinedNonFunctionPropertyOf<T>]: JsonDeserialized<\n\t\t\t\t\t\tT[K],\n\t\t\t\t\t\tTReplaced\n\t\t\t\t\t>;\n\t\t\t } & {\n\t\t\t\t\t/* properties that may have undefined values are optional */\n\t\t\t\t\t[K in NonSymbolWithUndefinedNonFunctionPropertyOf<T>]?: JsonDeserialized<\n\t\t\t\t\t\tT[K],\n\t\t\t\t\t\tTReplaced\n\t\t\t\t\t>;\n\t\t\t }\n\t\t: /* not an object => */ never\n\t: /* function => */ never;\n\nfunction readJson<T>(filepath: string): JsonDeserialized<T> {\n\treturn JSON.parse(readFileSync(filepath, { encoding: \"utf8\" })) as JsonDeserialized<T>;\n}\n\nfunction writeJson<T>(filepath: string, content: Jsonable<T>): void {\n\twriteFileSync(filepath, JSON.stringify(content, undefined, 4), { encoding: \"utf8\" });\n}\n\nconst validateInterval = 10;\n\nfunction getTimestamp(opIndex: number): number {\n\t// This is an arbitrary start point of the same magnitude as current data.\n\t// Wed Oct 12 2022 11:40:00 GMT-0700\n\tconst baseDate = 1665600000000;\n\treturn baseDate + Math.floor(opIndex / 10) * 5000;\n}\n\nfunction embedAttributionInProps(operations: Operation[]): Operation[] {\n\treturn operations.map((operation, index) => {\n\t\tif (operation.type === \"addText\") {\n\t\t\tconst name = operation.stringId.repeat(10);\n\t\t\tconst id = `${name}@contoso.com`;\n\t\t\tconst email = id;\n\t\t\tconst props = {\n\t\t\t\tattribution: {\n\t\t\t\t\tid,\n\t\t\t\t\tname,\n\t\t\t\t\temail,\n\t\t\t\t\ttimestamp: getTimestamp(index),\n\t\t\t\t},\n\t\t\t};\n\t\t\treturn {\n\t\t\t\t...operation,\n\t\t\t\tprops,\n\t\t\t};\n\t\t} else {\n\t\t\treturn operation;\n\t\t}\n\t});\n}\n\n// ISummaryTree is not serializable due to Uint8Array content in ISummaryBlob.\n// SerializableISummaryTree is a version of ISummaryTree with Uint8Array content removed.\ntype SerializableISummaryTree = ExcludeDeeply<ISummaryTree, Uint8Array>;\n\ntype ExcludeDeeply<T, Exclusion, TBase = Exclude<T, Exclusion>> = TBase extends object\n\t? { [K in keyof TBase]: ExcludeDeeply<TBase[K], Exclusion> }\n\t: TBase;\n\n/**\n * Validates that summary tree does not have a blob with a Uint8Array as content.\n *\n * @param summary - Summary tree to validate\n */\nfunction assertSerializableSummary(\n\tsummary: ISummaryTree,\n): asserts summary is SerializableISummaryTree {\n\tfor (const value of Object.values(summary.tree)) {\n\t\tswitch (value.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\tassertSerializableSummary(value);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tassert(typeof value.content === \"string\");\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\nconst summaryFromState = async (state: FuzzTestState): Promise<SerializableISummaryTree> => {\n\tstate.containerRuntimeFactory.processAllMessages();\n\tconst { sharedString } = state.clients[0];\n\tconst { summary } = await sharedString.summarize();\n\t// KLUDGE: For now, since attribution info isn't embedded at a proper location in the summary tree, just\n\t// add a property to the root so that its size is reported\n\tif (state.attributor && state.serializer) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\t(summary as any).attribution = state.serializer.encode(state.attributor);\n\t}\n\tassertSerializableSummary(summary);\n\treturn summary;\n};\n\nconst noopEncoder = {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tencode: (x: any): any => x,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tdecode: (x: any): any => x,\n};\n\nclass DataTable<T> {\n\tprivate readonly rows = new Map<string, T[]>();\n\tpublic constructor(private readonly columnNames: string[]) {}\n\n\tpublic addRow(name: string, data: T[]): void {\n\t\tthis.rows.set(name, data);\n\t}\n\n\tpublic log(dataToString: (t: T) => string = (t): string => `${t}`): void {\n\t\tconst namePaddingLength =\n\t\t\t1 + Math.max(...Array.from(this.rows.keys(), (docName) => docName.length));\n\t\tconst rowStrings = new Map<string, string[]>();\n\t\tconst paddingByColumn = this.columnNames.map((name) => name.length);\n\t\tfor (const [name, data] of this.rows.entries()) {\n\t\t\tconst dataStrings = data.map((entry: T) => dataToString(entry));\n\t\t\trowStrings.set(name, dataStrings);\n\t\t\tfor (const [i, s] of dataStrings.entries()) {\n\t\t\t\tpaddingByColumn[i] = Math.max(paddingByColumn[i], s.length);\n\t\t\t}\n\t\t}\n\t\tfor (const [i, _] of paddingByColumn.entries()) {\n\t\t\tpaddingByColumn[i]++;\n\t\t}\n\n\t\tconsole.log(\n\t\t\t[\n\t\t\t\t`${\"Name\".padEnd(namePaddingLength)}`,\n\t\t\t\t...this.columnNames.map((name, i) => `${name.padStart(paddingByColumn[i])} `),\n\t\t\t].join(\"|\"),\n\t\t);\n\n\t\tfor (const [name, result] of rowStrings.entries()) {\n\t\t\tconsole.log(\n\t\t\t\t`${name.padEnd(namePaddingLength)}|${result\n\t\t\t\t\t.map((s, i) => `${s.padStart(paddingByColumn[i])} `)\n\t\t\t\t\t.join(\"|\")}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nconst getSummaryLength = (summary: ISummaryTree): string =>\n\tformatNumber(JSON.stringify(summary).length);\n\ndescribe(\"SharedString Attribution\", () => {\n\t/**\n\t * This test suite is aimed at assessing the overhead of storing attribution information in a document.\n\t * See 'documents/README.md' for more details.\n\t */\n\n\tdescribe(\"using randomly generated documents\", () => {\n\t\t// Entries of this list produce documents which should contain the same attribution information but\n\t\t// stored in different formats. The \"None\" factory is an exception in that it contains no attribution\n\t\t// information, and is useful as a baseline for comparison.\n\t\tconst dataGenerators: {\n\t\t\tname: string;\n\t\t\tfactory: (operations: Operation[]) => FuzzTestState;\n\t\t\tfilename: string;\n\t\t}[] = [\n\t\t\t{\n\t\t\t\tname: \"None\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations)),\n\t\t\t\tfilename: \"no-attribution-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Prop\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(\n\t\t\t\t\t\tmakeRandom(0),\n\t\t\t\t\t\tgeneratorFromArray(embedAttributionInProps(operations)),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"prop-attribution-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"OpStreamAttributor without any compression\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations), (runtime) =>\n\t\t\t\t\t\tchainEncoders(\n\t\t\t\t\t\t\tnew AttributorSerializer(\n\t\t\t\t\t\t\t\t(entries) =>\n\t\t\t\t\t\t\t\t\tnew OpStreamAttributor(\n\t\t\t\t\t\t\t\t\t\truntime.deltaManager,\n\t\t\t\t\t\t\t\t\t\truntime.getAudience(),\n\t\t\t\t\t\t\t\t\t\tentries,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tnoopEncoder,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tnoopEncoder,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"attributor-no-compression-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"OpStreamAttributor without delta encoding\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations), (runtime) =>\n\t\t\t\t\t\tchainEncoders(\n\t\t\t\t\t\t\tnew AttributorSerializer(\n\t\t\t\t\t\t\t\t(entries) =>\n\t\t\t\t\t\t\t\t\tnew OpStreamAttributor(\n\t\t\t\t\t\t\t\t\t\truntime.deltaManager,\n\t\t\t\t\t\t\t\t\t\truntime.getAudience(),\n\t\t\t\t\t\t\t\t\t\tentries,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tnoopEncoder,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tmakeLZ4Encoder(),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"attributor-lz4-compression-snap.json\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"OpStreamAttributor\",\n\t\t\t\tfactory: (operations: Operation[]) =>\n\t\t\t\t\tcreateSharedString(makeRandom(0), generatorFromArray(operations), (runtime) =>\n\t\t\t\t\t\tchainEncoders(\n\t\t\t\t\t\t\tnew AttributorSerializer(\n\t\t\t\t\t\t\t\t(entries) =>\n\t\t\t\t\t\t\t\t\tnew OpStreamAttributor(\n\t\t\t\t\t\t\t\t\t\truntime.deltaManager,\n\t\t\t\t\t\t\t\t\t\truntime.getAudience(),\n\t\t\t\t\t\t\t\t\t\tentries,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tdeltaEncoder,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tmakeLZ4Encoder(),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\tfilename: \"attributor-lz4-and-delta-snap.json\",\n\t\t\t},\n\t\t];\n\n\t\tit.skip(\"Generate a new document\", async () => {\n\t\t\tconst paths = getDocumentPaths(\"default\");\n\t\t\tconst attributionlessGenerator = chain(\n\t\t\t\ttake(100, makeOperationGenerator({ validateInterval })),\n\t\t\t\tgeneratorFromArray<Operation, FuzzTestState>([{ type: \"synchronize\" }]),\n\t\t\t);\n\n\t\t\tconst { generator, operations } = spyOnOperations(attributionlessGenerator);\n\t\t\tcreateSharedString(makeRandom(0), generator);\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any\n\t\t\twriteJson(paths.operations, operations as any);\n\n\t\t\tawait Promise.all(\n\t\t\t\tdataGenerators.map(async ({ filename, factory }) => {\n\t\t\t\t\tconst summary = await summaryFromState(factory(operations));\n\t\t\t\t\twriteJson(path.join(paths.directory, filename), summary);\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\n\t\tconst documents = getDocuments();\n\t\tfor (const document of documents) {\n\t\t\tdescribe(`document name: ${document} has an up-to-date`, () => {\n\t\t\t\tlet paths: TestPaths;\n\t\t\t\tlet operations: Operation[];\n\t\t\t\tbefore(() => {\n\t\t\t\t\tpaths = getDocumentPaths(document);\n\t\t\t\t\toperations = readJson<Operation[]>(paths.operations);\n\t\t\t\t});\n\n\t\t\t\tfor (const { filename, factory } of dataGenerators) {\n\t\t\t\t\tit(`snapshot at ${filename}`, async () => {\n\t\t\t\t\t\tconst expected = readJson(path.join(paths.directory, filename));\n\t\t\t\t\t\tconst actual = await summaryFromState(factory(operations));\n\t\t\t\t\t\tassert.deepEqual(actual, expected);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// Note: to see output, FLUID_TEST_VERBOSE needs to be enabled. Using the `test:mocha:verbose` script is\n\t\t// sufficient to do so.\n\t\tit(\"generate snapshot size impact report\", async () => {\n\t\t\tconst table = new DataTable<ISummaryTree>(dataGenerators.map(({ name }) => name));\n\t\t\tfor (const docName of documents) {\n\t\t\t\tconst paths = getDocumentPaths(docName);\n\t\t\t\tconst operations: Operation[] = readJson(paths.operations);\n\t\t\t\tconst data = await Promise.all(\n\t\t\t\t\tdataGenerators.map(async ({ factory }) =>\n\t\t\t\t\t\tsummaryFromState(factory(operations)),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\ttable.addRow(docName, data);\n\t\t\t}\n\n\t\t\ttable.log(getSummaryLength);\n\t\t});\n\t});\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"attributorSerializer.spec.js","sourceRoot":"","sources":["../../src/test/attributorSerializer.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\nimport { type AttributionInfo } from \"@fluidframework/runtime-definitions\";\n\nimport { Attributor, type IAttributor } from \"../attributor.js\";\nimport {\n\tAttributorSerializer,\n\tchain,\n\ttype Encoder,\n\ttype SerializedAttributor,\n} from \"../encoders.js\";\nimport { type InternedStringId } from \"../stringInterner.js\";\n\nfunction makeNoopEncoder<T>(): Encoder<T, T> {\n\treturn {\n\t\tencode: (x) => x,\n\t\tdecode: (x) => x,\n\t};\n}\n\ndescribe(\"AttributorSerializer\", () => {\n\tit(\"uses its timestamp encoder\", () => {\n\t\tit(\"on encode\", () => {\n\t\t\tconst attributor = new Attributor([\n\t\t\t\t[1, { user: { id: \"a\" }, timestamp: 500 }],\n\t\t\t\t[2, { user: { id: \"a\" }, timestamp: 6001 }],\n\t\t\t]);\n\t\t\tconst calls: unknown[] = [];\n\t\t\tconst serializer = new AttributorSerializer((entries) => new Attributor(entries), {\n\t\t\t\tencode: (x): number[] => {\n\t\t\t\t\tcalls.push(x);\n\t\t\t\t\treturn x;\n\t\t\t\t},\n\t\t\t\tdecode: (x): number[] => x,\n\t\t\t});\n\t\t\tassert.equal(calls.length, 0);\n\t\t\tserializer.encode(attributor);\n\t\t\tassert.equal(calls.length, 1);\n\t\t\tassert.deepEqual(calls[0], [500, 6001]);\n\t\t});\n\n\t\tit(\"on decode\", () => {\n\t\t\tconst calls: unknown[] = [];\n\t\t\tconst serializer = new AttributorSerializer((entries) => new Attributor(entries), {\n\t\t\t\tencode: (x): number[] => x,\n\t\t\t\tdecode: (x): number[] => {\n\t\t\t\t\tcalls.push(x);\n\t\t\t\t\treturn x;\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst encoded: SerializedAttributor = {\n\t\t\t\tinterner: [\"a\"],\n\t\t\t\tseqs: [1, 2],\n\t\t\t\ttimestamps: [501, 604],\n\t\t\t\tattributionRefs: [0 as InternedStringId, 0 as InternedStringId],\n\t\t\t};\n\n\t\t\tassert.equal(calls.length, 0);\n\t\t\tserializer.decode(encoded);\n\t\t\tassert.equal(calls.length, 1);\n\t\t\tassert.deepEqual(calls[0], [501, 604]);\n\t\t});\n\t});\n\n\tdescribe(\"correctly round-trips\", () => {\n\t\tconst testCases: { name: string; entries: Iterable<[number, AttributionInfo]> }[] = [\n\t\t\t{\n\t\t\t\tname: \"empty attribution information\",\n\t\t\t\tentries: [],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"one attribution\",\n\t\t\t\tentries: [[5, { user: { id: \"only user\" }, timestamp: 6000 }]],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"multiple keys associated with the same user\",\n\t\t\t\tentries: [\n\t\t\t\t\t[1, { user: { id: \"user foo\" }, timestamp: 500 }],\n\t\t\t\t\t[2, { user: { id: \"user foo\" }, timestamp: 7000 }],\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"multiple keys associated with different users\",\n\t\t\t\tentries: [\n\t\t\t\t\t[1, { user: { id: \"user foo\" }, timestamp: 500 }],\n\t\t\t\t\t[2, { user: { id: \"user bar\" }, timestamp: 7000 }],\n\t\t\t\t],\n\t\t\t},\n\t\t];\n\n\t\tfor (const { name, entries } of testCases) {\n\t\t\tit(name, () => {\n\t\t\t\tconst calls: unknown[] = [];\n\t\t\t\tlet retVal: IAttributor | undefined;\n\t\t\t\tconst serializer = new AttributorSerializer((providedEntries) => {\n\t\t\t\t\tcalls.push(providedEntries);\n\t\t\t\t\tretVal = new Attributor(providedEntries);\n\t\t\t\t\treturn retVal;\n\t\t\t\t}, makeNoopEncoder());\n\t\t\t\tconst attributor = new Attributor(entries);\n\t\t\t\tconst roundTrippedAttributor = serializer.decode(serializer.encode(attributor));\n\t\t\t\tassert.equal(calls.length, 1);\n\t\t\t\tassert.deepEqual(calls[0], entries);\n\t\t\t\tassert.equal(retVal, roundTrippedAttributor);\n\t\t\t});\n\t\t}\n\t});\n});\n\ndescribe(\"chain\", () => {\n\tit(\"correctly chains encoders\", () => {\n\t\tconst encodeCalls: string[] = [];\n\t\tconst decodeCalls: string[] = [];\n\t\tconst makeLoggingChain = <T>(tag: string): Encoder<T, T> => ({\n\t\t\tencode: (s: T): T => {\n\t\t\t\tencodeCalls.push(tag);\n\t\t\t\treturn s;\n\t\t\t},\n\t\t\tdecode: (s: T): T => {\n\t\t\t\tdecodeCalls.push(tag);\n\t\t\t\treturn s;\n\t\t\t},\n\t\t});\n\t\tconst encoder = chain(makeLoggingChain(\"A\"), makeLoggingChain(\"B\"));\n\t\tassert.deepEqual(encodeCalls, []);\n\t\tassert.deepEqual(decodeCalls, []);\n\t\tassert.equal(encoder.encode(\"foo\"), \"foo\");\n\t\tassert.deepEqual(encodeCalls, [\"A\", \"B\"]);\n\t\tassert.deepEqual(decodeCalls, []);\n\t\tassert.equal(encoder.decode(\"bar\"), \"bar\");\n\t\tassert.deepEqual(encodeCalls, [\"A\", \"B\"]);\n\t\tassert.deepEqual(decodeCalls, [\"B\", \"A\"]);\n\t});\n});\n"]}
1
+ {"version":3,"file":"attributorSerializer.spec.js","sourceRoot":"","sources":["../../src/test/attributorSerializer.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\nimport { type AttributionInfo } from \"@fluidframework/runtime-definitions\";\n\nimport { Attributor, type IAttributor } from \"../attributor.js\";\nimport {\n\tAttributorSerializer,\n\ttype Encoder,\n\ttype SerializedAttributor,\n\tchain,\n} from \"../encoders.js\";\nimport { type InternedStringId } from \"../stringInterner.js\";\n\nfunction makeNoopEncoder<T>(): Encoder<T, T> {\n\treturn {\n\t\tencode: (x) => x,\n\t\tdecode: (x) => x,\n\t};\n}\n\ndescribe(\"AttributorSerializer\", () => {\n\tit(\"uses its timestamp encoder\", () => {\n\t\tit(\"on encode\", () => {\n\t\t\tconst attributor = new Attributor([\n\t\t\t\t[1, { user: { id: \"a\" }, timestamp: 500 }],\n\t\t\t\t[2, { user: { id: \"a\" }, timestamp: 6001 }],\n\t\t\t]);\n\t\t\tconst calls: unknown[] = [];\n\t\t\tconst serializer = new AttributorSerializer((entries) => new Attributor(entries), {\n\t\t\t\tencode: (x): number[] => {\n\t\t\t\t\tcalls.push(x);\n\t\t\t\t\treturn x;\n\t\t\t\t},\n\t\t\t\tdecode: (x): number[] => x,\n\t\t\t});\n\t\t\tassert.equal(calls.length, 0);\n\t\t\tserializer.encode(attributor);\n\t\t\tassert.equal(calls.length, 1);\n\t\t\tassert.deepEqual(calls[0], [500, 6001]);\n\t\t});\n\n\t\tit(\"on decode\", () => {\n\t\t\tconst calls: unknown[] = [];\n\t\t\tconst serializer = new AttributorSerializer((entries) => new Attributor(entries), {\n\t\t\t\tencode: (x): number[] => x,\n\t\t\t\tdecode: (x): number[] => {\n\t\t\t\t\tcalls.push(x);\n\t\t\t\t\treturn x;\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst encoded: SerializedAttributor = {\n\t\t\t\tinterner: [\"a\"],\n\t\t\t\tseqs: [1, 2],\n\t\t\t\ttimestamps: [501, 604],\n\t\t\t\tattributionRefs: [0 as InternedStringId, 0 as InternedStringId],\n\t\t\t};\n\n\t\t\tassert.equal(calls.length, 0);\n\t\t\tserializer.decode(encoded);\n\t\t\tassert.equal(calls.length, 1);\n\t\t\tassert.deepEqual(calls[0], [501, 604]);\n\t\t});\n\t});\n\n\tdescribe(\"correctly round-trips\", () => {\n\t\tconst testCases: { name: string; entries: Iterable<[number, AttributionInfo]> }[] = [\n\t\t\t{\n\t\t\t\tname: \"empty attribution information\",\n\t\t\t\tentries: [],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"one attribution\",\n\t\t\t\tentries: [[5, { user: { id: \"only user\" }, timestamp: 6000 }]],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"multiple keys associated with the same user\",\n\t\t\t\tentries: [\n\t\t\t\t\t[1, { user: { id: \"user foo\" }, timestamp: 500 }],\n\t\t\t\t\t[2, { user: { id: \"user foo\" }, timestamp: 7000 }],\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"multiple keys associated with different users\",\n\t\t\t\tentries: [\n\t\t\t\t\t[1, { user: { id: \"user foo\" }, timestamp: 500 }],\n\t\t\t\t\t[2, { user: { id: \"user bar\" }, timestamp: 7000 }],\n\t\t\t\t],\n\t\t\t},\n\t\t];\n\n\t\tfor (const { name, entries } of testCases) {\n\t\t\tit(name, () => {\n\t\t\t\tconst calls: unknown[] = [];\n\t\t\t\tlet retVal: IAttributor | undefined;\n\t\t\t\tconst serializer = new AttributorSerializer((providedEntries) => {\n\t\t\t\t\tcalls.push(providedEntries);\n\t\t\t\t\tretVal = new Attributor(providedEntries);\n\t\t\t\t\treturn retVal;\n\t\t\t\t}, makeNoopEncoder());\n\t\t\t\tconst attributor = new Attributor(entries);\n\t\t\t\tconst roundTrippedAttributor = serializer.decode(serializer.encode(attributor));\n\t\t\t\tassert.equal(calls.length, 1);\n\t\t\t\tassert.deepEqual(calls[0], entries);\n\t\t\t\tassert.equal(retVal, roundTrippedAttributor);\n\t\t\t});\n\t\t}\n\t});\n});\n\ndescribe(\"chain\", () => {\n\tit(\"correctly chains encoders\", () => {\n\t\tconst encodeCalls: string[] = [];\n\t\tconst decodeCalls: string[] = [];\n\t\tconst makeLoggingChain = <T>(tag: string): Encoder<T, T> => ({\n\t\t\tencode: (s: T): T => {\n\t\t\t\tencodeCalls.push(tag);\n\t\t\t\treturn s;\n\t\t\t},\n\t\t\tdecode: (s: T): T => {\n\t\t\t\tdecodeCalls.push(tag);\n\t\t\t\treturn s;\n\t\t\t},\n\t\t});\n\t\tconst encoder = chain(makeLoggingChain(\"A\"), makeLoggingChain(\"B\"));\n\t\tassert.deepEqual(encodeCalls, []);\n\t\tassert.deepEqual(decodeCalls, []);\n\t\tassert.equal(encoder.encode(\"foo\"), \"foo\");\n\t\tassert.deepEqual(encodeCalls, [\"A\", \"B\"]);\n\t\tassert.deepEqual(decodeCalls, []);\n\t\tassert.equal(encoder.decode(\"bar\"), \"bar\");\n\t\tassert.deepEqual(encodeCalls, [\"A\", \"B\"]);\n\t\tassert.deepEqual(decodeCalls, [\"B\", \"A\"]);\n\t});\n});\n"]}
@@ -5,13 +5,13 @@
5
5
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
6
6
  import { strict as assert } from "node:assert";
7
7
  import { AttachState, } from "@fluidframework/container-definitions";
8
+ import { SummaryType, } from "@fluidframework/protocol-definitions";
8
9
  import { MockLogger, sessionStorageConfigProvider } from "@fluidframework/telemetry-utils";
9
10
  import { MockDeltaManager, MockQuorumClients } from "@fluidframework/test-runtime-utils";
10
- import { SummaryType, } from "@fluidframework/protocol-definitions";
11
- import { createRuntimeAttributor, enableOnNewFileKey, mixinAttributor, } from "../mixinAttributor.js";
12
11
  import { Attributor } from "../attributor.js";
13
- import { makeLZ4Encoder } from "../lz4Encoder.js";
14
12
  import { AttributorSerializer, chain, deltaEncoder } from "../encoders.js";
13
+ import { makeLZ4Encoder } from "../lz4Encoder.js";
14
+ import { createRuntimeAttributor, enableOnNewFileKey, mixinAttributor, } from "../mixinAttributor.js";
15
15
  import { makeMockAudience } from "./utils.js";
16
16
  describe("mixinAttributor", () => {
17
17
  const clientId = "mock client id";
@@ -1 +1 @@
1
- {"version":3,"file":"mixinAttributor.spec.js","sourceRoot":"","sources":["../../src/test/mixinAttributor.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport { strict as assert } from \"node:assert\";\nimport {\n\tAttachState,\n\ttype IContainerContext,\n\ttype ICriticalContainerError,\n} from \"@fluidframework/container-definitions\";\nimport { MockLogger, sessionStorageConfigProvider } from \"@fluidframework/telemetry-utils\";\nimport { type IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { MockDeltaManager, MockQuorumClients } from \"@fluidframework/test-runtime-utils\";\nimport { type ConfigTypes, type FluidObject } from \"@fluidframework/core-interfaces\";\nimport {\n\ttype ISequencedDocumentMessage,\n\ttype ISnapshotTree,\n\tSummaryType,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n\tcreateRuntimeAttributor,\n\tenableOnNewFileKey,\n\ttype IProvideRuntimeAttributor,\n\tmixinAttributor,\n} from \"../mixinAttributor.js\";\nimport { Attributor } from \"../attributor.js\";\nimport { makeLZ4Encoder } from \"../lz4Encoder.js\";\nimport { AttributorSerializer, chain, deltaEncoder } from \"../encoders.js\";\nimport { makeMockAudience } from \"./utils.js\";\n\ntype Mutable<T> = {\n\t-readonly [P in keyof T]: T[P];\n};\n\ndescribe(\"mixinAttributor\", () => {\n\tconst clientId = \"mock client id\";\n\tconst getMockContext = (): Partial<IContainerContext> => {\n\t\treturn {\n\t\t\taudience: makeMockAudience([clientId]),\n\t\t\tattachState: AttachState.Attached,\n\t\t\tdeltaManager: new MockDeltaManager(),\n\t\t\tquorum: new MockQuorumClients(),\n\t\t\ttaggedLogger: new MockLogger(),\n\t\t\tclientDetails: { capabilities: { interactive: true } },\n\t\t\tcloseFn: (error?: ICriticalContainerError): void => {\n\t\t\t\tif (error) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-throw-literal\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t\toptions: {},\n\t\t\tupdateDirtyContainerState: (_dirty: boolean): void => {},\n\t\t\tgetLoadedFromVersion: () => undefined,\n\t\t};\n\t};\n\n\tconst getScope = (): FluidObject<IProvideRuntimeAttributor> => ({\n\t\tIRuntimeAttributor: createRuntimeAttributor(),\n\t});\n\n\tconst oldRawConfig = sessionStorageConfigProvider.value.getRawConfig;\n\tlet injectedSettings: Record<string, ConfigTypes> = {};\n\n\tbefore(() => {\n\t\tsessionStorageConfigProvider.value.getRawConfig = (name): ConfigTypes =>\n\t\t\tinjectedSettings[name];\n\t});\n\n\tafterEach(() => {\n\t\tinjectedSettings = {};\n\t});\n\n\tafter(() => {\n\t\tsessionStorageConfigProvider.value.getRawConfig = oldRawConfig;\n\t});\n\n\tconst setEnableOnNew = (val: boolean): void => {\n\t\tinjectedSettings[enableOnNewFileKey] = val;\n\t};\n\n\tconst AttributingContainerRuntime = mixinAttributor();\n\n\tit(\"Attributes ops\", async () => {\n\t\tsetEnableOnNew(true);\n\t\tconst context = getMockContext() as IContainerContext;\n\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\tcontext,\n\t\t\tregistryEntries: [],\n\t\t\tcontainerScope: getScope(),\n\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\texisting: false,\n\t\t});\n\n\t\tconst maybeProvidesAttributor: FluidObject<IProvideRuntimeAttributor> =\n\t\t\tcontainerRuntime.scope;\n\t\tassert(maybeProvidesAttributor.IRuntimeAttributor !== undefined);\n\t\tconst runtimeAttribution = maybeProvidesAttributor.IRuntimeAttributor;\n\n\t\tconst op: Partial<ISequencedDocumentMessage> = {\n\t\t\ttype: \"op\",\n\t\t\tsequenceNumber: 7,\n\t\t\tclientId,\n\t\t\ttimestamp: 1006,\n\t\t};\n\n\t\t(context.deltaManager as MockDeltaManager).emit(\"op\", op);\n\n\t\tassert.deepEqual(runtimeAttribution.get({ type: \"op\", seq: op.sequenceNumber! }), {\n\t\t\ttimestamp: op.timestamp,\n\t\t\tuser: context.audience?.getMember(op.clientId!)?.user,\n\t\t});\n\t});\n\n\tit(\"includes attribution association data in the summary tree\", async () => {\n\t\tsetEnableOnNew(true);\n\t\tconst context = getMockContext() as IContainerContext;\n\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\tcontext,\n\t\t\tregistryEntries: [],\n\t\t\tcontainerScope: getScope(),\n\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\texisting: false,\n\t\t});\n\n\t\tconst op: Partial<ISequencedDocumentMessage> = {\n\t\t\ttype: \"op\",\n\t\t\tsequenceNumber: 7,\n\t\t\tclientId,\n\t\t\ttimestamp: 1006,\n\t\t};\n\n\t\t(context.deltaManager as MockDeltaManager).emit(\"op\", op);\n\t\tconst { summary } = await containerRuntime.summarize({\n\t\t\tfullTree: true,\n\t\t\ttrackState: false,\n\t\t\trunGC: false,\n\t\t});\n\n\t\tconst { \".attributor\": attributor } = summary.tree;\n\t\tassert(\n\t\t\tattributor !== undefined && attributor.type === SummaryType.Tree,\n\t\t\t\"summary should contain attributor data\",\n\t\t);\n\t\tconst opAttributorBlob = attributor.tree.op;\n\t\tassert(\n\t\t\topAttributorBlob.type === SummaryType.Blob &&\n\t\t\t\ttypeof opAttributorBlob.content === \"string\",\n\t\t);\n\t\tconst decoder = chain(\n\t\t\tnew AttributorSerializer((entries) => new Attributor(entries), deltaEncoder),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\t\tconst decoded = decoder.decode(opAttributorBlob.content);\n\t\tassert.deepEqual(decoded.getAttributionInfo(op.sequenceNumber!), {\n\t\t\ttimestamp: op.timestamp,\n\t\t\tuser: context.audience?.getMember(op.clientId!)?.user,\n\t\t});\n\t});\n\n\tit(\"repopulates attribution association data using the summary tree\", async () => {\n\t\tconst op: Partial<ISequencedDocumentMessage> = {\n\t\t\tsequenceNumber: 7,\n\t\t\tclientId,\n\t\t\ttimestamp: 1006,\n\t\t};\n\n\t\tconst encoder = chain(\n\t\t\tnew AttributorSerializer((entries) => new Attributor(entries), deltaEncoder),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\t\tconst context = getMockContext() as Mutable<IContainerContext>;\n\t\tconst sampleAttributor = new Attributor([\n\t\t\t[\n\t\t\t\top.sequenceNumber!,\n\t\t\t\t{ timestamp: op.timestamp!, user: context.audience!.getMember(op.clientId!)!.user },\n\t\t\t],\n\t\t]);\n\n\t\tconst opAttributorBlobId = \"mock attributor blob id\";\n\t\tconst mockStorage: IDocumentStorageService = {\n\t\t\treadBlob: async (blobId: string) => {\n\t\t\t\tassert(blobId === opAttributorBlobId);\n\t\t\t\treturn encoder.encode(sampleAttributor);\n\t\t\t},\n\t\t} as unknown as IDocumentStorageService;\n\t\tconst snapshot: ISnapshotTree = {\n\t\t\tblobs: {},\n\t\t\ttrees: {\n\t\t\t\t\".attributor\": {\n\t\t\t\t\tblobs: { op: opAttributorBlobId },\n\t\t\t\t\ttrees: {},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tcontext.baseSnapshot = snapshot;\n\t\tcontext.storage = mockStorage;\n\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\tcontext,\n\t\t\tregistryEntries: [],\n\t\t\tcontainerScope: getScope(),\n\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\texisting: false,\n\t\t});\n\n\t\tconst maybeProvidesAttributor: FluidObject<IProvideRuntimeAttributor> =\n\t\t\tcontainerRuntime.scope;\n\t\tassert(maybeProvidesAttributor.IRuntimeAttributor !== undefined);\n\t\tconst runtimeAttribution = maybeProvidesAttributor.IRuntimeAttributor;\n\n\t\tassert.deepEqual(runtimeAttribution.get({ type: \"op\", seq: op.sequenceNumber! }), {\n\t\t\ttimestamp: op.timestamp,\n\t\t\tuser: context.audience?.getMember(op.clientId!)?.user,\n\t\t});\n\t});\n\n\tdescribe(\"Doesn't summarize attributor\", () => {\n\t\tconst testCases: { getContext: () => IContainerContext; testName: string }[] = [\n\t\t\t{\n\t\t\t\ttestName: \"for existing documents that had no attributor\",\n\t\t\t\tgetContext: (): IContainerContext => {\n\t\t\t\t\tsetEnableOnNew(true);\n\t\t\t\t\tconst context = getMockContext() as Mutable<IContainerContext>;\n\t\t\t\t\tconst snapshot: ISnapshotTree = {\n\t\t\t\t\t\tblobs: {},\n\t\t\t\t\t\ttrees: {},\n\t\t\t\t\t};\n\t\t\t\t\tcontext.baseSnapshot = snapshot;\n\t\t\t\t\treturn context;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttestName: `for new documents with ${enableOnNewFileKey} unset`,\n\t\t\t\tgetContext: (): IContainerContext => {\n\t\t\t\t\treturn getMockContext() as IContainerContext;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttestName: `for new documents with ${enableOnNewFileKey} set to false`,\n\t\t\t\tgetContext: (): IContainerContext => {\n\t\t\t\t\tsetEnableOnNew(false);\n\t\t\t\t\tconst context = getMockContext() as Mutable<IContainerContext>;\n\t\t\t\t\tconst snapshot: ISnapshotTree = {\n\t\t\t\t\t\tblobs: {},\n\t\t\t\t\t\ttrees: {},\n\t\t\t\t\t};\n\t\t\t\t\tcontext.baseSnapshot = snapshot;\n\t\t\t\t\treturn context;\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tfor (const { getContext, testName } of testCases) {\n\t\t\tit(testName, async () => {\n\t\t\t\tconst context = getContext();\n\t\t\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\t\t\tcontext,\n\t\t\t\t\tregistryEntries: [],\n\t\t\t\t\tcontainerScope: getScope(),\n\t\t\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\t\t\texisting: false,\n\t\t\t\t});\n\n\t\t\t\tconst maybeProvidesAttributor: FluidObject<IProvideRuntimeAttributor> =\n\t\t\t\t\tcontainerRuntime.scope;\n\t\t\t\tassert(maybeProvidesAttributor.IRuntimeAttributor !== undefined);\n\n\t\t\t\tconst { summary } = await containerRuntime.summarize({\n\t\t\t\t\tfullTree: true,\n\t\t\t\t\ttrackState: false,\n\t\t\t\t\trunGC: false,\n\t\t\t\t});\n\t\t\t\tassert(summary.tree[\".attributor\"] === undefined);\n\t\t\t});\n\t\t}\n\t});\n});\n\n/* eslint-enable @typescript-eslint/no-non-null-assertion */\n"]}
1
+ {"version":3,"file":"mixinAttributor.spec.js","sourceRoot":"","sources":["../../src/test/mixinAttributor.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport { strict as assert } from \"node:assert\";\nimport {\n\tAttachState,\n\ttype IContainerContext,\n\ttype ICriticalContainerError,\n} from \"@fluidframework/container-definitions\";\nimport { type ConfigTypes, type FluidObject } from \"@fluidframework/core-interfaces\";\nimport { type IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport {\n\ttype ISequencedDocumentMessage,\n\ttype ISnapshotTree,\n\tSummaryType,\n} from \"@fluidframework/protocol-definitions\";\nimport { MockLogger, sessionStorageConfigProvider } from \"@fluidframework/telemetry-utils\";\nimport { MockDeltaManager, MockQuorumClients } from \"@fluidframework/test-runtime-utils\";\nimport { Attributor } from \"../attributor.js\";\nimport { AttributorSerializer, chain, deltaEncoder } from \"../encoders.js\";\nimport { makeLZ4Encoder } from \"../lz4Encoder.js\";\nimport {\n\ttype IProvideRuntimeAttributor,\n\tcreateRuntimeAttributor,\n\tenableOnNewFileKey,\n\tmixinAttributor,\n} from \"../mixinAttributor.js\";\nimport { makeMockAudience } from \"./utils.js\";\n\ntype Mutable<T> = {\n\t-readonly [P in keyof T]: T[P];\n};\n\ndescribe(\"mixinAttributor\", () => {\n\tconst clientId = \"mock client id\";\n\tconst getMockContext = (): Partial<IContainerContext> => {\n\t\treturn {\n\t\t\taudience: makeMockAudience([clientId]),\n\t\t\tattachState: AttachState.Attached,\n\t\t\tdeltaManager: new MockDeltaManager(),\n\t\t\tquorum: new MockQuorumClients(),\n\t\t\ttaggedLogger: new MockLogger(),\n\t\t\tclientDetails: { capabilities: { interactive: true } },\n\t\t\tcloseFn: (error?: ICriticalContainerError): void => {\n\t\t\t\tif (error) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-throw-literal\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t\toptions: {},\n\t\t\tupdateDirtyContainerState: (_dirty: boolean): void => {},\n\t\t\tgetLoadedFromVersion: () => undefined,\n\t\t};\n\t};\n\n\tconst getScope = (): FluidObject<IProvideRuntimeAttributor> => ({\n\t\tIRuntimeAttributor: createRuntimeAttributor(),\n\t});\n\n\tconst oldRawConfig = sessionStorageConfigProvider.value.getRawConfig;\n\tlet injectedSettings: Record<string, ConfigTypes> = {};\n\n\tbefore(() => {\n\t\tsessionStorageConfigProvider.value.getRawConfig = (name): ConfigTypes =>\n\t\t\tinjectedSettings[name];\n\t});\n\n\tafterEach(() => {\n\t\tinjectedSettings = {};\n\t});\n\n\tafter(() => {\n\t\tsessionStorageConfigProvider.value.getRawConfig = oldRawConfig;\n\t});\n\n\tconst setEnableOnNew = (val: boolean): void => {\n\t\tinjectedSettings[enableOnNewFileKey] = val;\n\t};\n\n\tconst AttributingContainerRuntime = mixinAttributor();\n\n\tit(\"Attributes ops\", async () => {\n\t\tsetEnableOnNew(true);\n\t\tconst context = getMockContext() as IContainerContext;\n\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\tcontext,\n\t\t\tregistryEntries: [],\n\t\t\tcontainerScope: getScope(),\n\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\texisting: false,\n\t\t});\n\n\t\tconst maybeProvidesAttributor: FluidObject<IProvideRuntimeAttributor> =\n\t\t\tcontainerRuntime.scope;\n\t\tassert(maybeProvidesAttributor.IRuntimeAttributor !== undefined);\n\t\tconst runtimeAttribution = maybeProvidesAttributor.IRuntimeAttributor;\n\n\t\tconst op: Partial<ISequencedDocumentMessage> = {\n\t\t\ttype: \"op\",\n\t\t\tsequenceNumber: 7,\n\t\t\tclientId,\n\t\t\ttimestamp: 1006,\n\t\t};\n\n\t\t(context.deltaManager as MockDeltaManager).emit(\"op\", op);\n\n\t\tassert.deepEqual(runtimeAttribution.get({ type: \"op\", seq: op.sequenceNumber! }), {\n\t\t\ttimestamp: op.timestamp,\n\t\t\tuser: context.audience?.getMember(op.clientId!)?.user,\n\t\t});\n\t});\n\n\tit(\"includes attribution association data in the summary tree\", async () => {\n\t\tsetEnableOnNew(true);\n\t\tconst context = getMockContext() as IContainerContext;\n\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\tcontext,\n\t\t\tregistryEntries: [],\n\t\t\tcontainerScope: getScope(),\n\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\texisting: false,\n\t\t});\n\n\t\tconst op: Partial<ISequencedDocumentMessage> = {\n\t\t\ttype: \"op\",\n\t\t\tsequenceNumber: 7,\n\t\t\tclientId,\n\t\t\ttimestamp: 1006,\n\t\t};\n\n\t\t(context.deltaManager as MockDeltaManager).emit(\"op\", op);\n\t\tconst { summary } = await containerRuntime.summarize({\n\t\t\tfullTree: true,\n\t\t\ttrackState: false,\n\t\t\trunGC: false,\n\t\t});\n\n\t\tconst { \".attributor\": attributor } = summary.tree;\n\t\tassert(\n\t\t\tattributor !== undefined && attributor.type === SummaryType.Tree,\n\t\t\t\"summary should contain attributor data\",\n\t\t);\n\t\tconst opAttributorBlob = attributor.tree.op;\n\t\tassert(\n\t\t\topAttributorBlob.type === SummaryType.Blob &&\n\t\t\t\ttypeof opAttributorBlob.content === \"string\",\n\t\t);\n\t\tconst decoder = chain(\n\t\t\tnew AttributorSerializer((entries) => new Attributor(entries), deltaEncoder),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\t\tconst decoded = decoder.decode(opAttributorBlob.content);\n\t\tassert.deepEqual(decoded.getAttributionInfo(op.sequenceNumber!), {\n\t\t\ttimestamp: op.timestamp,\n\t\t\tuser: context.audience?.getMember(op.clientId!)?.user,\n\t\t});\n\t});\n\n\tit(\"repopulates attribution association data using the summary tree\", async () => {\n\t\tconst op: Partial<ISequencedDocumentMessage> = {\n\t\t\tsequenceNumber: 7,\n\t\t\tclientId,\n\t\t\ttimestamp: 1006,\n\t\t};\n\n\t\tconst encoder = chain(\n\t\t\tnew AttributorSerializer((entries) => new Attributor(entries), deltaEncoder),\n\t\t\tmakeLZ4Encoder(),\n\t\t);\n\t\tconst context = getMockContext() as Mutable<IContainerContext>;\n\t\tconst sampleAttributor = new Attributor([\n\t\t\t[\n\t\t\t\top.sequenceNumber!,\n\t\t\t\t{ timestamp: op.timestamp!, user: context.audience!.getMember(op.clientId!)!.user },\n\t\t\t],\n\t\t]);\n\n\t\tconst opAttributorBlobId = \"mock attributor blob id\";\n\t\tconst mockStorage: IDocumentStorageService = {\n\t\t\treadBlob: async (blobId: string) => {\n\t\t\t\tassert(blobId === opAttributorBlobId);\n\t\t\t\treturn encoder.encode(sampleAttributor);\n\t\t\t},\n\t\t} as unknown as IDocumentStorageService;\n\t\tconst snapshot: ISnapshotTree = {\n\t\t\tblobs: {},\n\t\t\ttrees: {\n\t\t\t\t\".attributor\": {\n\t\t\t\t\tblobs: { op: opAttributorBlobId },\n\t\t\t\t\ttrees: {},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tcontext.baseSnapshot = snapshot;\n\t\tcontext.storage = mockStorage;\n\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\tcontext,\n\t\t\tregistryEntries: [],\n\t\t\tcontainerScope: getScope(),\n\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\texisting: false,\n\t\t});\n\n\t\tconst maybeProvidesAttributor: FluidObject<IProvideRuntimeAttributor> =\n\t\t\tcontainerRuntime.scope;\n\t\tassert(maybeProvidesAttributor.IRuntimeAttributor !== undefined);\n\t\tconst runtimeAttribution = maybeProvidesAttributor.IRuntimeAttributor;\n\n\t\tassert.deepEqual(runtimeAttribution.get({ type: \"op\", seq: op.sequenceNumber! }), {\n\t\t\ttimestamp: op.timestamp,\n\t\t\tuser: context.audience?.getMember(op.clientId!)?.user,\n\t\t});\n\t});\n\n\tdescribe(\"Doesn't summarize attributor\", () => {\n\t\tconst testCases: { getContext: () => IContainerContext; testName: string }[] = [\n\t\t\t{\n\t\t\t\ttestName: \"for existing documents that had no attributor\",\n\t\t\t\tgetContext: (): IContainerContext => {\n\t\t\t\t\tsetEnableOnNew(true);\n\t\t\t\t\tconst context = getMockContext() as Mutable<IContainerContext>;\n\t\t\t\t\tconst snapshot: ISnapshotTree = {\n\t\t\t\t\t\tblobs: {},\n\t\t\t\t\t\ttrees: {},\n\t\t\t\t\t};\n\t\t\t\t\tcontext.baseSnapshot = snapshot;\n\t\t\t\t\treturn context;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttestName: `for new documents with ${enableOnNewFileKey} unset`,\n\t\t\t\tgetContext: (): IContainerContext => {\n\t\t\t\t\treturn getMockContext() as IContainerContext;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttestName: `for new documents with ${enableOnNewFileKey} set to false`,\n\t\t\t\tgetContext: (): IContainerContext => {\n\t\t\t\t\tsetEnableOnNew(false);\n\t\t\t\t\tconst context = getMockContext() as Mutable<IContainerContext>;\n\t\t\t\t\tconst snapshot: ISnapshotTree = {\n\t\t\t\t\t\tblobs: {},\n\t\t\t\t\t\ttrees: {},\n\t\t\t\t\t};\n\t\t\t\t\tcontext.baseSnapshot = snapshot;\n\t\t\t\t\treturn context;\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tfor (const { getContext, testName } of testCases) {\n\t\t\tit(testName, async () => {\n\t\t\t\tconst context = getContext();\n\t\t\t\tconst containerRuntime = await AttributingContainerRuntime.loadRuntime({\n\t\t\t\t\tcontext,\n\t\t\t\t\tregistryEntries: [],\n\t\t\t\t\tcontainerScope: getScope(),\n\t\t\t\t\tprovideEntryPoint: async () => ({}),\n\t\t\t\t\texisting: false,\n\t\t\t\t});\n\n\t\t\t\tconst maybeProvidesAttributor: FluidObject<IProvideRuntimeAttributor> =\n\t\t\t\t\tcontainerRuntime.scope;\n\t\t\t\tassert(maybeProvidesAttributor.IRuntimeAttributor !== undefined);\n\n\t\t\t\tconst { summary } = await containerRuntime.summarize({\n\t\t\t\t\tfullTree: true,\n\t\t\t\t\ttrackState: false,\n\t\t\t\t\trunGC: false,\n\t\t\t\t});\n\t\t\t\tassert(summary.tree[\".attributor\"] === undefined);\n\t\t\t});\n\t\t}\n\t});\n});\n\n/* eslint-enable @typescript-eslint/no-non-null-assertion */\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAmB;IACnD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC3C,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE;QACpD,qDAAqD;QACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,GAAG,IAAI,gBAAgB,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC;QACrB,MAAM,IAAI,GAAG;YACZ,EAAE,EAAE,MAAM;YACV,IAAI;YACJ,KAAK;SACL,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;YACrB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;YAChD,UAAU,EAAE,EAAE;YACd,IAAI;YACJ,MAAM,EAAE,EAAE;SACV,CAAC,CAAC;KACH;IACD,yEAAyE;IACzE,OAAO;QACN,SAAS,EAAE,CAAC,QAAgB,EAAuB,EAAE;YACpD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;KACY,CAAC;AAChB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { type IClient } from \"@fluidframework/protocol-definitions\";\nimport { type IAudience } from \"@fluidframework/container-definitions\";\n\n/**\n * Creates a mock {@link @fluidframework/container-definitions#IAudience} for testing.\n */\nexport function makeMockAudience(clientIds: string[]): IAudience {\n\tconst clients = new Map<string, IClient>();\n\tfor (const [index, clientId] of clientIds.entries()) {\n\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\tconst stringId = String.fromCharCode(index + 65);\n\t\tconst name = stringId.repeat(10);\n\t\tconst userId = `${name}@microsoft.com`;\n\t\tconst email = userId;\n\t\tconst user = {\n\t\t\tid: userId,\n\t\t\tname,\n\t\t\temail,\n\t\t};\n\t\tclients.set(clientId, {\n\t\t\tmode: \"write\",\n\t\t\tdetails: { capabilities: { interactive: true } },\n\t\t\tpermission: [],\n\t\t\tuser,\n\t\t\tscopes: [],\n\t\t});\n\t}\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\treturn {\n\t\tgetMember: (clientId: string): IClient | undefined => {\n\t\t\treturn clients.get(clientId);\n\t\t},\n\t} as IAudience;\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAmB;IACnD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC3C,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE;QACpD,qDAAqD;QACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,GAAG,IAAI,gBAAgB,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC;QACrB,MAAM,IAAI,GAAG;YACZ,EAAE,EAAE,MAAM;YACV,IAAI;YACJ,KAAK;SACL,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;YACrB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;YAChD,UAAU,EAAE,EAAE;YACd,IAAI;YACJ,MAAM,EAAE,EAAE;SACV,CAAC,CAAC;KACH;IACD,yEAAyE;IACzE,OAAO;QACN,SAAS,EAAE,CAAC,QAAgB,EAAuB,EAAE;YACpD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;KACY,CAAC;AAChB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { type IAudience } from \"@fluidframework/container-definitions\";\nimport { type IClient } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Creates a mock {@link @fluidframework/container-definitions#IAudience} for testing.\n */\nexport function makeMockAudience(clientIds: string[]): IAudience {\n\tconst clients = new Map<string, IClient>();\n\tfor (const [index, clientId] of clientIds.entries()) {\n\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\tconst stringId = String.fromCharCode(index + 65);\n\t\tconst name = stringId.repeat(10);\n\t\tconst userId = `${name}@microsoft.com`;\n\t\tconst email = userId;\n\t\tconst user = {\n\t\t\tid: userId,\n\t\t\tname,\n\t\t\temail,\n\t\t};\n\t\tclients.set(clientId, {\n\t\t\tmode: \"write\",\n\t\t\tdetails: { capabilities: { interactive: true } },\n\t\t\tpermission: [],\n\t\t\tuser,\n\t\t\tscopes: [],\n\t\t});\n\t}\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\treturn {\n\t\tgetMember: (clientId: string): IClient | undefined => {\n\t\t\treturn clients.get(clientId);\n\t\t},\n\t} as IAudience;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-experimental/attributor",
3
- "version": "2.0.0-dev-rc.2.0.0.246488",
3
+ "version": "2.0.0-dev-rc.3.0.0.250606",
4
4
  "description": "Operation attributor",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -67,31 +67,32 @@
67
67
  "temp-directory": "nyc/.nyc_output"
68
68
  },
69
69
  "dependencies": {
70
- "@fluid-internal/client-utils": "2.0.0-dev-rc.2.0.0.246488",
71
- "@fluidframework/container-definitions": "2.0.0-dev-rc.2.0.0.246488",
72
- "@fluidframework/container-runtime": "2.0.0-dev-rc.2.0.0.246488",
73
- "@fluidframework/container-runtime-definitions": "2.0.0-dev-rc.2.0.0.246488",
74
- "@fluidframework/core-interfaces": "2.0.0-dev-rc.2.0.0.246488",
75
- "@fluidframework/core-utils": "2.0.0-dev-rc.2.0.0.246488",
76
- "@fluidframework/datastore-definitions": "2.0.0-dev-rc.2.0.0.246488",
70
+ "@fluid-internal/client-utils": "2.0.0-dev-rc.3.0.0.250606",
71
+ "@fluidframework/container-definitions": "2.0.0-dev-rc.3.0.0.250606",
72
+ "@fluidframework/container-runtime": "2.0.0-dev-rc.3.0.0.250606",
73
+ "@fluidframework/container-runtime-definitions": "2.0.0-dev-rc.3.0.0.250606",
74
+ "@fluidframework/core-interfaces": "2.0.0-dev-rc.3.0.0.250606",
75
+ "@fluidframework/core-utils": "2.0.0-dev-rc.3.0.0.250606",
76
+ "@fluidframework/datastore-definitions": "2.0.0-dev-rc.3.0.0.250606",
77
77
  "@fluidframework/protocol-definitions": "^3.2.0",
78
- "@fluidframework/runtime-definitions": "2.0.0-dev-rc.2.0.0.246488",
79
- "@fluidframework/runtime-utils": "2.0.0-dev-rc.2.0.0.246488",
80
- "@fluidframework/telemetry-utils": "2.0.0-dev-rc.2.0.0.246488",
78
+ "@fluidframework/runtime-definitions": "2.0.0-dev-rc.3.0.0.250606",
79
+ "@fluidframework/runtime-utils": "2.0.0-dev-rc.3.0.0.250606",
80
+ "@fluidframework/telemetry-utils": "2.0.0-dev-rc.3.0.0.250606",
81
81
  "lz4js": "^0.2.0"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@arethetypeswrong/cli": "^0.13.3",
85
- "@fluid-internal/mocha-test-setup": "2.0.0-dev-rc.2.0.0.246488",
86
- "@fluid-private/stochastic-test-utils": "2.0.0-dev-rc.2.0.0.246488",
85
+ "@biomejs/biome": "^1.6.2",
86
+ "@fluid-internal/mocha-test-setup": "2.0.0-dev-rc.3.0.0.250606",
87
+ "@fluid-private/stochastic-test-utils": "2.0.0-dev-rc.3.0.0.250606",
87
88
  "@fluid-tools/build-cli": "^0.34.0",
88
89
  "@fluidframework/build-common": "^2.0.3",
89
90
  "@fluidframework/build-tools": "^0.34.0",
90
- "@fluidframework/driver-definitions": "2.0.0-dev-rc.2.0.0.246488",
91
+ "@fluidframework/driver-definitions": "2.0.0-dev-rc.3.0.0.250606",
91
92
  "@fluidframework/eslint-config-fluid": "^5.1.0",
92
- "@fluidframework/merge-tree": "2.0.0-dev-rc.2.0.0.246488",
93
- "@fluidframework/sequence": "2.0.0-dev-rc.2.0.0.246488",
94
- "@fluidframework/test-runtime-utils": "2.0.0-dev-rc.2.0.0.246488",
93
+ "@fluidframework/merge-tree": "2.0.0-dev-rc.3.0.0.250606",
94
+ "@fluidframework/sequence": "2.0.0-dev-rc.3.0.0.250606",
95
+ "@fluidframework/test-runtime-utils": "2.0.0-dev-rc.3.0.0.250606",
95
96
  "@microsoft/api-extractor": "^7.42.3",
96
97
  "@types/mocha": "^9.1.1",
97
98
  "@types/node": "^18.19.0",
@@ -136,16 +137,18 @@
136
137
  "build:test:cjs": "fluid-tsc commonjs --project ./src/test/tsconfig.cjs.json",
137
138
  "build:test:esm": "tsc --project ./src/test/tsconfig.json",
138
139
  "check:are-the-types-wrong": "attw --pack . --entrypoints .",
140
+ "check:biome": "biome check .",
141
+ "check:prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
139
142
  "check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
140
143
  "ci:build:docs": "api-extractor run",
141
144
  "clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
142
145
  "eslint": "eslint --format stylish src",
143
146
  "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
144
- "format": "npm run prettier:fix",
145
- "lint": "npm run prettier && npm run check:release-tags && npm run eslint",
146
- "lint:fix": "npm run prettier:fix && npm run eslint:fix",
147
- "prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
148
- "prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore",
147
+ "format": "fluid-build --task format .",
148
+ "format:biome": "biome check --apply .",
149
+ "format:prettier": "prettier --write . --cache --ignore-path ../../../.prettierignore",
150
+ "lint": "fluid-build . --task lint",
151
+ "lint:fix": "fluid-build . --task eslint:fix --task format",
149
152
  "test": "npm run test:mocha",
150
153
  "test:coverage": "c8 npm test",
151
154
  "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
package/src/attributor.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ import { type IAudience, type IDeltaManager } from "@fluidframework/container-definitions";
6
7
  import { assert } from "@fluidframework/core-utils";
7
8
  import {
8
9
  type IDocumentMessage,
@@ -10,7 +11,6 @@ import {
10
11
  } from "@fluidframework/protocol-definitions";
11
12
  import { type AttributionInfo } from "@fluidframework/runtime-definitions";
12
13
  import { UsageError } from "@fluidframework/telemetry-utils";
13
- import { type IAudience, type IDeltaManager } from "@fluidframework/container-definitions";
14
14
 
15
15
  /**
16
16
  * Provides lookup between attribution keys and their associated attribution information.
package/src/lz4Encoder.ts CHANGED
@@ -3,9 +3,9 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { compress, decompress } from "lz4js";
7
6
  import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
8
7
  import { type Jsonable } from "@fluidframework/datastore-definitions";
8
+ import { compress, decompress } from "lz4js";
9
9
  import { type Encoder } from "./encoders.js";
10
10
 
11
11
  // TODO: document this
@@ -3,11 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import {
7
- type IDocumentMessage,
8
- type ISequencedDocumentMessage,
9
- type ISnapshotTree,
10
- } from "@fluidframework/protocol-definitions";
6
+ import { bufferToString } from "@fluid-internal/client-utils";
11
7
  import {
12
8
  type IAudience,
13
9
  type IContainerContext,
@@ -15,6 +11,14 @@ import {
15
11
  } from "@fluidframework/container-definitions";
16
12
  import { ContainerRuntime } from "@fluidframework/container-runtime";
17
13
  import type { IContainerRuntimeOptions } from "@fluidframework/container-runtime";
14
+ import { type IContainerRuntime } from "@fluidframework/container-runtime-definitions";
15
+ import { type FluidObject, type IRequest, type IResponse } from "@fluidframework/core-interfaces";
16
+ import { assert, unreachableCase } from "@fluidframework/core-utils";
17
+ import {
18
+ type IDocumentMessage,
19
+ type ISequencedDocumentMessage,
20
+ type ISnapshotTree,
21
+ } from "@fluidframework/protocol-definitions";
18
22
  import {
19
23
  type AttributionInfo,
20
24
  type AttributionKey,
@@ -22,19 +26,15 @@ import {
22
26
  type ITelemetryContext,
23
27
  type NamedFluidDataStoreRegistryEntries,
24
28
  } from "@fluidframework/runtime-definitions";
25
- import { addSummarizeResultToSummary, SummaryTreeBuilder } from "@fluidframework/runtime-utils";
26
- import { type IContainerRuntime } from "@fluidframework/container-runtime-definitions";
27
- import { type IRequest, type IResponse, type FluidObject } from "@fluidframework/core-interfaces";
28
- import { bufferToString } from "@fluid-internal/client-utils";
29
- import { assert, unreachableCase } from "@fluidframework/core-utils";
29
+ import { SummaryTreeBuilder, addSummarizeResultToSummary } from "@fluidframework/runtime-utils";
30
30
  import {
31
- createChildLogger,
32
- loggerToMonitoringContext,
33
31
  PerformanceEvent,
34
32
  UsageError,
33
+ createChildLogger,
34
+ loggerToMonitoringContext,
35
35
  } from "@fluidframework/telemetry-utils";
36
36
  import { Attributor, type IAttributor, OpStreamAttributor } from "./attributor.js";
37
- import { AttributorSerializer, chain, deltaEncoder, type Encoder } from "./encoders.js";
37
+ import { AttributorSerializer, type Encoder, chain, deltaEncoder } from "./encoders.js";
38
38
  import { makeLZ4Encoder } from "./lz4Encoder.js";
39
39
 
40
40
  // Summary tree keys