@fluid-experimental/attributor 2.0.0-rc.1.0.4 → 2.0.0-rc.2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +6 -2
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +4 -0
  4. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  5. package/api-extractor-lint.json +1 -1
  6. package/api-extractor.json +1 -1
  7. package/api-report/attributor.api.md +1 -1
  8. package/dist/attributor-untrimmed.d.ts +6 -3
  9. package/dist/attributor.d.ts +3 -3
  10. package/dist/attributor.d.ts.map +1 -1
  11. package/dist/attributor.js +0 -1
  12. package/dist/attributor.js.map +1 -1
  13. package/dist/encoders.d.ts +10 -4
  14. package/dist/encoders.d.ts.map +1 -1
  15. package/dist/encoders.js +13 -7
  16. package/dist/encoders.js.map +1 -1
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +8 -8
  20. package/dist/index.js.map +1 -1
  21. package/dist/lz4Encoder.d.ts +2 -2
  22. package/dist/lz4Encoder.d.ts.map +1 -1
  23. package/dist/lz4Encoder.js +4 -0
  24. package/dist/lz4Encoder.js.map +1 -1
  25. package/dist/mixinAttributor.d.ts +7 -4
  26. package/dist/mixinAttributor.d.ts.map +1 -1
  27. package/dist/mixinAttributor.js +20 -15
  28. package/dist/mixinAttributor.js.map +1 -1
  29. package/dist/package.json +3 -0
  30. package/dist/stringInterner.d.ts +9 -6
  31. package/dist/stringInterner.d.ts.map +1 -1
  32. package/dist/stringInterner.js +9 -6
  33. package/dist/stringInterner.js.map +1 -1
  34. package/dist/tsdoc-metadata.json +1 -1
  35. package/lib/{attributor-untrimmed.d.mts → attributor-untrimmed.d.ts} +6 -3
  36. package/lib/{attributor.d.mts → attributor.d.ts} +4 -4
  37. package/lib/attributor.d.ts.map +1 -0
  38. package/lib/{attributor.mjs → attributor.js} +5 -2
  39. package/lib/attributor.js.map +1 -0
  40. package/lib/{encoders.d.mts → encoders.d.ts} +11 -5
  41. package/lib/encoders.d.ts.map +1 -0
  42. package/lib/{encoders.mjs → encoders.js} +16 -6
  43. package/lib/encoders.js.map +1 -0
  44. package/lib/index.d.ts +7 -0
  45. package/lib/index.d.ts.map +1 -0
  46. package/lib/index.js +7 -0
  47. package/lib/index.js.map +1 -0
  48. package/lib/lz4Encoder.d.ts +7 -0
  49. package/lib/lz4Encoder.d.ts.map +1 -0
  50. package/lib/{lz4Encoder.mjs → lz4Encoder.js} +9 -1
  51. package/lib/lz4Encoder.js.map +1 -0
  52. package/lib/{mixinAttributor.d.mts → mixinAttributor.d.ts} +8 -5
  53. package/lib/mixinAttributor.d.ts.map +1 -0
  54. package/lib/{mixinAttributor.mjs → mixinAttributor.js} +19 -14
  55. package/lib/mixinAttributor.js.map +1 -0
  56. package/lib/{stringInterner.d.mts → stringInterner.d.ts} +10 -7
  57. package/lib/stringInterner.d.ts.map +1 -0
  58. package/lib/{stringInterner.mjs → stringInterner.js} +10 -7
  59. package/lib/stringInterner.js.map +1 -0
  60. package/lib/test/attribution/dirname.cjs +16 -0
  61. package/lib/test/attribution/dirname.cjs.map +1 -0
  62. package/lib/test/attribution/sharedString.attribution.spec.js +398 -0
  63. package/lib/test/attribution/sharedString.attribution.spec.js.map +1 -0
  64. package/lib/test/attributor.spec.js +32 -0
  65. package/lib/test/attributor.spec.js.map +1 -0
  66. package/lib/test/attributorSerializer.spec.js +123 -0
  67. package/lib/test/attributorSerializer.spec.js.map +1 -0
  68. package/lib/test/deltaEncoder.spec.js +36 -0
  69. package/lib/test/deltaEncoder.spec.js.map +1 -0
  70. package/lib/test/lz4Encoder.spec.js +27 -0
  71. package/lib/test/lz4Encoder.spec.js.map +1 -0
  72. package/lib/test/mixinAttributor.spec.js +219 -0
  73. package/lib/test/mixinAttributor.spec.js.map +1 -0
  74. package/lib/test/opStreamAttributor.spec.js +43 -0
  75. package/lib/test/opStreamAttributor.spec.js.map +1 -0
  76. package/lib/test/stringInterner.spec.js +71 -0
  77. package/lib/test/stringInterner.spec.js.map +1 -0
  78. package/lib/test/utils.js +32 -0
  79. package/lib/test/utils.js.map +1 -0
  80. package/package.json +42 -59
  81. package/src/attributor.ts +8 -6
  82. package/src/encoders.ts +16 -11
  83. package/src/index.ts +3 -3
  84. package/src/lz4Encoder.ts +10 -6
  85. package/src/mixinAttributor.ts +41 -26
  86. package/src/stringInterner.ts +10 -7
  87. package/tsconfig.cjs.json +7 -0
  88. package/tsconfig.json +2 -5
  89. package/lib/attributor.d.mts.map +0 -1
  90. package/lib/attributor.mjs.map +0 -1
  91. package/lib/encoders.d.mts.map +0 -1
  92. package/lib/encoders.mjs.map +0 -1
  93. package/lib/index.d.mts +0 -3
  94. package/lib/index.d.mts.map +0 -1
  95. package/lib/index.mjs +0 -3
  96. package/lib/index.mjs.map +0 -1
  97. package/lib/lz4Encoder.d.mts +0 -7
  98. package/lib/lz4Encoder.d.mts.map +0 -1
  99. package/lib/lz4Encoder.mjs.map +0 -1
  100. package/lib/mixinAttributor.d.mts.map +0 -1
  101. package/lib/mixinAttributor.mjs.map +0 -1
  102. package/lib/stringInterner.d.mts.map +0 -1
  103. package/lib/stringInterner.mjs.map +0 -1
  104. /package/lib/{attributor-alpha.d.mts → attributor-alpha.d.ts} +0 -0
  105. /package/lib/{attributor-beta.d.mts → attributor-beta.d.ts} +0 -0
  106. /package/lib/{attributor-public.d.mts → attributor-public.d.ts} +0 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Creates a mock {@link @fluidframework/container-definitions#IAudience} for testing.
3
+ */
4
+ export function makeMockAudience(clientIds) {
5
+ const clients = new Map();
6
+ for (const [index, clientId] of clientIds.entries()) {
7
+ // eslint-disable-next-line unicorn/prefer-code-point
8
+ const stringId = String.fromCharCode(index + 65);
9
+ const name = stringId.repeat(10);
10
+ const userId = `${name}@microsoft.com`;
11
+ const email = userId;
12
+ const user = {
13
+ id: userId,
14
+ name,
15
+ email,
16
+ };
17
+ clients.set(clientId, {
18
+ mode: "write",
19
+ details: { capabilities: { interactive: true } },
20
+ permission: [],
21
+ user,
22
+ scopes: [],
23
+ });
24
+ }
25
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
26
+ return {
27
+ getMember: (clientId) => {
28
+ return clients.get(clientId);
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAOA;;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 */\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-experimental/attributor",
3
- "version": "2.0.0-rc.1.0.4",
3
+ "version": "2.0.0-rc.2.0.0",
4
4
  "description": "Operation attributor",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -11,60 +11,40 @@
11
11
  "license": "MIT",
12
12
  "author": "Microsoft and contributors",
13
13
  "sideEffects": false,
14
+ "type": "module",
14
15
  "exports": {
15
16
  ".": {
16
17
  "import": {
17
- "types": "./lib/index.d.mts",
18
- "default": "./lib/index.mjs"
18
+ "types": "./lib/index.d.ts",
19
+ "default": "./lib/index.js"
19
20
  },
20
21
  "require": {
21
22
  "types": "./dist/index.d.ts",
22
23
  "default": "./dist/index.js"
23
24
  }
24
25
  },
25
- "./alpha": {
26
- "import": {
27
- "types": "./lib/attributor-alpha.d.mts",
28
- "default": "./lib/index.mjs"
29
- },
30
- "require": {
31
- "types": "./dist/attributor-alpha.d.ts",
32
- "default": "./dist/index.js"
33
- }
34
- },
35
- "./beta": {
26
+ "./public": {
36
27
  "import": {
37
- "types": "./lib/attributor-beta.d.mts",
38
- "default": "./lib/index.mjs"
28
+ "types": "./lib/attributor-public.d.ts",
29
+ "default": "./lib/index.js"
39
30
  },
40
31
  "require": {
41
- "types": "./dist/attributor-beta.d.ts",
32
+ "types": "./dist/attributor-public.d.ts",
42
33
  "default": "./dist/index.js"
43
34
  }
44
35
  },
45
36
  "./internal": {
46
37
  "import": {
47
- "types": "./lib/index.d.mts",
48
- "default": "./lib/index.mjs"
38
+ "types": "./lib/index.d.ts",
39
+ "default": "./lib/index.js"
49
40
  },
50
41
  "require": {
51
42
  "types": "./dist/index.d.ts",
52
43
  "default": "./dist/index.js"
53
44
  }
54
- },
55
- "./public": {
56
- "import": {
57
- "types": "./lib/attributor-public.d.mts",
58
- "default": "./lib/index.mjs"
59
- },
60
- "require": {
61
- "types": "./dist/attributor-public.d.ts",
62
- "default": "./dist/index.js"
63
- }
64
45
  }
65
46
  },
66
47
  "main": "dist/index.js",
67
- "module": "lib/index.mjs",
68
48
  "types": "dist/index.d.ts",
69
49
  "c8": {
70
50
  "all": true,
@@ -87,45 +67,44 @@
87
67
  "temp-directory": "nyc/.nyc_output"
88
68
  },
89
69
  "dependencies": {
90
- "@fluid-internal/client-utils": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
91
- "@fluidframework/container-definitions": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
92
- "@fluidframework/container-runtime": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
93
- "@fluidframework/container-runtime-definitions": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
94
- "@fluidframework/core-interfaces": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
95
- "@fluidframework/core-utils": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
96
- "@fluidframework/datastore-definitions": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
97
- "@fluidframework/protocol-definitions": "^3.1.0",
98
- "@fluidframework/runtime-definitions": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
99
- "@fluidframework/runtime-utils": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
100
- "@fluidframework/telemetry-utils": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
70
+ "@fluid-internal/client-utils": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
71
+ "@fluidframework/container-definitions": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
72
+ "@fluidframework/container-runtime": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
73
+ "@fluidframework/container-runtime-definitions": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
74
+ "@fluidframework/core-interfaces": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
75
+ "@fluidframework/core-utils": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
76
+ "@fluidframework/datastore-definitions": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
77
+ "@fluidframework/protocol-definitions": "^3.2.0",
78
+ "@fluidframework/runtime-definitions": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
79
+ "@fluidframework/runtime-utils": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
80
+ "@fluidframework/telemetry-utils": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
101
81
  "lz4js": "^0.2.0"
102
82
  },
103
83
  "devDependencies": {
104
84
  "@arethetypeswrong/cli": "^0.13.3",
105
- "@fluid-private/stochastic-test-utils": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
106
- "@fluid-tools/build-cli": "^0.29.0",
85
+ "@fluid-internal/mocha-test-setup": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
86
+ "@fluid-private/stochastic-test-utils": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
87
+ "@fluid-tools/build-cli": "^0.34.0",
107
88
  "@fluidframework/build-common": "^2.0.3",
108
- "@fluidframework/build-tools": "^0.29.0",
109
- "@fluidframework/driver-definitions": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
110
- "@fluidframework/eslint-config-fluid": "^3.2.0",
111
- "@fluidframework/merge-tree": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
112
- "@fluidframework/mocha-test-setup": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
113
- "@fluidframework/sequence": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
114
- "@fluidframework/test-runtime-utils": ">=2.0.0-rc.1.0.4 <2.0.0-rc.1.1.0",
115
- "@microsoft/api-extractor": "^7.38.3",
89
+ "@fluidframework/build-tools": "^0.34.0",
90
+ "@fluidframework/driver-definitions": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
91
+ "@fluidframework/eslint-config-fluid": "^4.0.0",
92
+ "@fluidframework/merge-tree": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
93
+ "@fluidframework/sequence": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
94
+ "@fluidframework/test-runtime-utils": ">=2.0.0-rc.2.0.0 <2.0.0-rc.2.1.0",
95
+ "@microsoft/api-extractor": "^7.42.3",
116
96
  "@types/mocha": "^9.1.1",
117
97
  "@types/node": "^18.19.0",
118
98
  "c8": "^8.0.1",
119
99
  "copyfiles": "^2.4.1",
120
100
  "cross-env": "^7.0.3",
121
- "eslint": "~8.50.0",
101
+ "eslint": "~8.55.0",
122
102
  "mocha": "^10.2.0",
123
103
  "mocha-json-output-reporter": "^2.0.1",
124
104
  "mocha-multi-reporters": "^1.5.1",
125
105
  "moment": "^2.21.0",
126
106
  "prettier": "~3.0.3",
127
107
  "rimraf": "^4.4.0",
128
- "tsc-multi": "^1.1.0",
129
108
  "typescript": "~5.1.6"
130
109
  },
131
110
  "fluidBuild": {
@@ -146,14 +125,16 @@
146
125
  },
147
126
  "scripts": {
148
127
  "api": "fluid-build . --task api",
149
- "api-extractor:commonjs": "api-extractor run --local",
150
- "api-extractor:esnext": "api-extractor run --config ./api-extractor-esm.json",
128
+ "api-extractor:commonjs": "api-extractor run --config ./api-extractor-cjs.json",
129
+ "api-extractor:esnext": "api-extractor run --local",
151
130
  "build": "fluid-build . --task build",
152
131
  "build:commonjs": "fluid-build . --task commonjs",
153
132
  "build:compile": "fluid-build . --task compile",
154
133
  "build:docs": "fluid-build . --task api",
155
- "build:esnext": "tsc-multi --config ../../../common/build/build-common/tsc-multi.esm.json",
156
- "build:test": "tsc --project ./src/test/tsconfig.json",
134
+ "build:esnext": "tsc --project ./tsconfig.json",
135
+ "build:test": "npm run build:test:esm && npm run build:test:cjs",
136
+ "build:test:cjs": "fluid-tsc commonjs --project ./src/test/tsconfig.cjs.json",
137
+ "build:test:esm": "tsc --project ./src/test/tsconfig.json",
157
138
  "check:are-the-types-wrong": "attw --pack . --entrypoints .",
158
139
  "check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
159
140
  "ci:build:docs": "api-extractor run",
@@ -167,9 +148,11 @@
167
148
  "prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore",
168
149
  "test": "npm run test:mocha",
169
150
  "test:coverage": "c8 npm test",
170
- "test:mocha": "mocha --ignore \"dist/test/memory/**/*\" --recursive \"dist/test/**/*.spec.*js\" -r node_modules/@fluidframework/mocha-test-setup",
151
+ "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
152
+ "test:mocha:cjs": "mocha --recursive \"dist/test/**/*.spec.*js\" --exit",
153
+ "test:mocha:esm": "mocha --recursive \"lib/test/**/*.spec.*js\" --exit",
171
154
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
172
- "tsc": "tsc",
155
+ "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
173
156
  "typetests:gen": "fluid-type-test-generator",
174
157
  "typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
175
158
  }
package/src/attributor.ts CHANGED
@@ -3,10 +3,13 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { assert } from "@fluidframework/core-utils";
6
- import { IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
7
- import { AttributionInfo } from "@fluidframework/runtime-definitions";
6
+ import {
7
+ type IDocumentMessage,
8
+ type ISequencedDocumentMessage,
9
+ } from "@fluidframework/protocol-definitions";
10
+ import { type AttributionInfo } from "@fluidframework/runtime-definitions";
8
11
  import { UsageError } from "@fluidframework/telemetry-utils";
9
- import { IAudience, IDeltaManager } from "@fluidframework/container-definitions";
12
+ import { type IAudience, type IDeltaManager } from "@fluidframework/container-definitions";
10
13
 
11
14
  /**
12
15
  * Provides lookup between attribution keys and their associated attribution information.
@@ -45,7 +48,7 @@ export class Attributor implements IAttributor {
45
48
  /**
46
49
  * @param initialEntries - Any entries which should be populated on instantiation.
47
50
  */
48
- constructor(initialEntries?: Iterable<[number, AttributionInfo]>) {
51
+ public constructor(initialEntries?: Iterable<[number, AttributionInfo]>) {
49
52
  this.keyToInfo = new Map(initialEntries ?? []);
50
53
  }
51
54
 
@@ -81,7 +84,7 @@ export class Attributor implements IAttributor {
81
84
  * @internal
82
85
  */
83
86
  export class OpStreamAttributor extends Attributor implements IAttributor {
84
- constructor(
87
+ public constructor(
85
88
  deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
86
89
  audience: IAudience,
87
90
  initialEntries?: Iterable<[number, AttributionInfo]>,
@@ -89,7 +92,6 @@ export class OpStreamAttributor extends Attributor implements IAttributor {
89
92
  super(initialEntries);
90
93
  deltaManager.on("op", (message: ISequencedDocumentMessage) => {
91
94
  // TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
92
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
93
95
  const client = audience.getMember(message.clientId as string);
94
96
  if (message.type === "op") {
95
97
  // TODO: This case may be legitimate, and if so we need to figure out how to handle it.
package/src/encoders.ts CHANGED
@@ -3,14 +3,13 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { assert } from "@fluidframework/core-utils";
6
- import { IUser } from "@fluidframework/protocol-definitions";
7
- import { AttributionInfo } from "@fluidframework/runtime-definitions";
8
- import { IAttributor } from "./attributor";
9
- import { InternedStringId, MutableStringInterner } from "./stringInterner";
6
+ import { type IUser } from "@fluidframework/protocol-definitions";
7
+ import { type AttributionInfo } from "@fluidframework/runtime-definitions";
8
+ import { type IAttributor } from "./attributor.js";
9
+ import { type InternedStringId, MutableStringInterner } from "./stringInterner.js";
10
10
 
11
11
  export interface Encoder<TDecoded, TEncoded> {
12
12
  encode(decoded: TDecoded): TEncoded;
13
-
14
13
  decode(encoded: TEncoded): TDecoded;
15
14
  }
16
15
 
@@ -20,7 +19,7 @@ export type TimestampEncoder = Encoder<number[], number[]>;
20
19
 
21
20
  export const deltaEncoder: TimestampEncoder = {
22
21
  encode: (timestamps: number[]) => {
23
- const deltaTimestamps: number[] = new Array(timestamps.length);
22
+ const deltaTimestamps: number[] = Array.from({ length: timestamps.length });
24
23
  let prev = 0;
25
24
  for (let i = 0; i < timestamps.length; i++) {
26
25
  deltaTimestamps[i] = timestamps[i] - prev;
@@ -33,7 +32,7 @@ export const deltaEncoder: TimestampEncoder = {
33
32
  Array.isArray(encoded),
34
33
  0x4b0 /* Encoded timestamps should be an array of numbers */,
35
34
  );
36
- const timestamps: number[] = new Array(encoded.length);
35
+ const timestamps: number[] = Array.from({ length: encoded.length });
37
36
  let cumulativeSum = 0;
38
37
  for (let i = 0; i < encoded.length; i++) {
39
38
  cumulativeSum += encoded[i];
@@ -53,13 +52,16 @@ export interface SerializedAttributor {
53
52
  }
54
53
 
55
54
  export class AttributorSerializer implements IAttributorSerializer {
56
- constructor(
55
+ public constructor(
57
56
  private readonly makeAttributor: (
58
57
  entries: Iterable<[number, AttributionInfo]>,
59
58
  ) => IAttributor,
60
59
  private readonly timestampEncoder: TimestampEncoder,
61
60
  ) {}
62
61
 
62
+ /**
63
+ * {@inheritDoc Encoder.encode}
64
+ */
63
65
  public encode(attributor: IAttributor): SerializedAttributor {
64
66
  const interner = new MutableStringInterner();
65
67
  const seqs: number[] = [];
@@ -82,6 +84,9 @@ export class AttributorSerializer implements IAttributorSerializer {
82
84
  return serialized;
83
85
  }
84
86
 
87
+ /**
88
+ * {@inheritDoc Encoder.decode}
89
+ */
85
90
  public decode(encoded: SerializedAttributor): IAttributor {
86
91
  const interner = new MutableStringInterner(encoded.interner);
87
92
  const { seqs, timestamps: encodedTimestamps, attributionRefs } = encoded;
@@ -90,12 +95,12 @@ export class AttributorSerializer implements IAttributorSerializer {
90
95
  seqs.length === timestamps.length && timestamps.length === attributionRefs.length,
91
96
  0x4b1 /* serialized attribution columns should have the same length */,
92
97
  );
93
- const entries = new Array(seqs.length);
98
+ const entries: [number, AttributionInfo][] = Array.from({ length: seqs.length });
94
99
  for (let i = 0; i < seqs.length; i++) {
95
100
  const key = seqs[i];
96
101
  const timestamp = timestamps[i];
97
102
  const ref = attributionRefs[i];
98
- const user: IUser = JSON.parse(interner.getString(ref));
103
+ const user = JSON.parse(interner.getString(ref)) as IUser;
99
104
  entries[i] = [key, { user, timestamp }];
100
105
  }
101
106
  return this.makeAttributor(entries);
@@ -103,7 +108,7 @@ export class AttributorSerializer implements IAttributorSerializer {
103
108
  }
104
109
 
105
110
  /**
106
- * @returns an encoder which composes `a` and `b`.
111
+ * Creates an encoder which composes `a` and `b`.
107
112
  */
108
113
  export const chain = <T1, T2, T3>(a: Encoder<T1, T2>, b: Encoder<T2, T3>): Encoder<T1, T3> => ({
109
114
  encode: (content) => b.encode(a.encode(content)),
package/src/index.ts CHANGED
@@ -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
- export { Attributor, OpStreamAttributor, IAttributor } from "./attributor";
5
+ export { Attributor, type IAttributor, OpStreamAttributor } from "./attributor.js";
6
6
  export {
7
7
  createRuntimeAttributor,
8
8
  enableOnNewFileKey,
9
- IProvideRuntimeAttributor,
9
+ type IProvideRuntimeAttributor,
10
10
  IRuntimeAttributor,
11
11
  mixinAttributor,
12
- } from "./mixinAttributor";
12
+ } from "./mixinAttributor.js";
package/src/lz4Encoder.ts CHANGED
@@ -4,23 +4,27 @@
4
4
  */
5
5
  import { compress, decompress } from "lz4js";
6
6
  import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
7
- import { Jsonable } from "@fluidframework/datastore-definitions";
8
- import { Encoder } from "./encoders";
7
+ import { type Jsonable } from "@fluidframework/datastore-definitions";
8
+ import { type Encoder } from "./encoders.js";
9
9
 
10
+ // TODO: document this
11
+ // eslint-disable-next-line jsdoc/require-description
10
12
  /**
11
13
  * @alpha
12
14
  */
13
15
  export function makeLZ4Encoder<T>(): Encoder<Jsonable<T>, string> {
14
16
  return {
15
- encode: (decoded: Jsonable<T>) => {
17
+ encode: (decoded: Jsonable<T>): string => {
16
18
  const uncompressed = new TextEncoder().encode(JSON.stringify(decoded));
17
- const compressed = compress(uncompressed);
19
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
20
+ const compressed = compress(uncompressed) as ArrayBufferLike;
18
21
  return bufferToString(compressed, "base64");
19
22
  },
20
23
  decode: (serializedSummary: string): Jsonable<T> => {
21
24
  const compressed = new Uint8Array(stringToBuffer(serializedSummary, "base64"));
22
- const uncompressed = decompress(compressed);
23
- const decoded: Jsonable<T> = JSON.parse(new TextDecoder().decode(uncompressed));
25
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
26
+ const uncompressed = decompress(compressed) as BufferSource;
27
+ const decoded = JSON.parse(new TextDecoder().decode(uncompressed)) as Jsonable<T>;
24
28
  return decoded;
25
29
  },
26
30
  };
@@ -3,23 +3,27 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import {
6
- IDocumentMessage,
7
- ISequencedDocumentMessage,
8
- ISnapshotTree,
6
+ type IDocumentMessage,
7
+ type ISequencedDocumentMessage,
8
+ type ISnapshotTree,
9
9
  } from "@fluidframework/protocol-definitions";
10
- import { IAudience, IContainerContext, IDeltaManager } from "@fluidframework/container-definitions";
10
+ import {
11
+ type IAudience,
12
+ type IContainerContext,
13
+ type IDeltaManager,
14
+ } from "@fluidframework/container-definitions";
11
15
  import { ContainerRuntime } from "@fluidframework/container-runtime";
12
16
  import type { IContainerRuntimeOptions } from "@fluidframework/container-runtime";
13
17
  import {
14
- AttributionInfo,
15
- AttributionKey,
16
- ISummaryTreeWithStats,
17
- ITelemetryContext,
18
- NamedFluidDataStoreRegistryEntries,
18
+ type AttributionInfo,
19
+ type AttributionKey,
20
+ type ISummaryTreeWithStats,
21
+ type ITelemetryContext,
22
+ type NamedFluidDataStoreRegistryEntries,
19
23
  } from "@fluidframework/runtime-definitions";
20
24
  import { addSummarizeResultToSummary, SummaryTreeBuilder } from "@fluidframework/runtime-utils";
21
- import { IContainerRuntime } from "@fluidframework/container-runtime-definitions";
22
- import { IRequest, IResponse, FluidObject } from "@fluidframework/core-interfaces";
25
+ import { type IContainerRuntime } from "@fluidframework/container-runtime-definitions";
26
+ import { type IRequest, type IResponse, type FluidObject } from "@fluidframework/core-interfaces";
23
27
  import { bufferToString } from "@fluid-internal/client-utils";
24
28
  import { assert, unreachableCase } from "@fluidframework/core-utils";
25
29
  import {
@@ -28,9 +32,9 @@ import {
28
32
  PerformanceEvent,
29
33
  UsageError,
30
34
  } from "@fluidframework/telemetry-utils";
31
- import { Attributor, IAttributor, OpStreamAttributor } from "./attributor";
32
- import { AttributorSerializer, chain, deltaEncoder, Encoder } from "./encoders";
33
- import { makeLZ4Encoder } from "./lz4Encoder";
35
+ import { Attributor, type IAttributor, OpStreamAttributor } from "./attributor.js";
36
+ import { AttributorSerializer, chain, deltaEncoder, type Encoder } from "./encoders.js";
37
+ import { makeLZ4Encoder } from "./lz4Encoder.js";
34
38
 
35
39
  // Summary tree keys
36
40
  const attributorTreeName = ".attributor";
@@ -56,7 +60,8 @@ export interface IProvideRuntimeAttributor {
56
60
  /**
57
61
  * Provides access to attribution information stored on the container runtime.
58
62
  *
59
- * Attributors are only populated after the container runtime they are injected into has initialized.
63
+ * @remarks Attributors are only populated after the container runtime into which they are being injected has initialized.
64
+ *
60
65
  * @sealed
61
66
  * @internal
62
67
  */
@@ -79,8 +84,10 @@ export interface IRuntimeAttributor extends IProvideRuntimeAttributor {
79
84
  }
80
85
 
81
86
  /**
82
- * @returns an IRuntimeAttributor for usage with `mixinAttributor`. The attributor will only be populated with data
83
- * once it's passed via scope to a container runtime load flow. See {@link mixinAttributor}.
87
+ * Creates an `IRuntimeAttributor` for usage with {@link mixinAttributor}.
88
+ *
89
+ * @remarks The attributor will only be populated with data once it's passed via scope to a container runtime load flow.
90
+ *
84
91
  * @internal
85
92
  */
86
93
  export function createRuntimeAttributor(): IRuntimeAttributor {
@@ -98,7 +105,9 @@ export function createRuntimeAttributor(): IRuntimeAttributor {
98
105
  * @param Base - base class, inherits from FluidAttributorRuntime
99
106
  * @internal
100
107
  */
101
- export const mixinAttributor = (Base: typeof ContainerRuntime = ContainerRuntime) =>
108
+ export const mixinAttributor = (
109
+ Base: typeof ContainerRuntime = ContainerRuntime,
110
+ ): typeof ContainerRuntime =>
102
111
  class ContainerRuntimeWithAttributor extends Base {
103
112
  public static async loadRuntime(params: {
104
113
  context: IContainerContext;
@@ -107,7 +116,9 @@ export const mixinAttributor = (Base: typeof ContainerRuntime = ContainerRuntime
107
116
  runtimeOptions?: IContainerRuntimeOptions;
108
117
  containerScope?: FluidObject;
109
118
  containerRuntimeCtor?: typeof ContainerRuntime;
110
- /** @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 */
119
+ /**
120
+ * @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
121
+ */
111
122
  requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;
112
123
  provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;
113
124
  }): Promise<ContainerRuntime> {
@@ -137,19 +148,22 @@ export const mixinAttributor = (Base: typeof ContainerRuntime = ContainerRuntime
137
148
  const baseSnapshot: ISnapshotTree | undefined =
138
149
  pendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;
139
150
 
140
- const { audience, deltaManager } = context;
151
+ const { audience, deltaManager, taggedLogger } = context;
141
152
  assert(
142
153
  audience !== undefined,
143
154
  0x508 /* Audience must exist when instantiating attribution-providing runtime */,
144
155
  );
145
156
 
146
- const mc = loggerToMonitoringContext(context.taggedLogger);
157
+ const mc = loggerToMonitoringContext(taggedLogger);
147
158
 
148
159
  const shouldTrackAttribution = mc.config.getBoolean(enableOnNewFileKey) ?? false;
149
160
  if (shouldTrackAttribution) {
150
- (context.options.attribution ??= {}).track = true;
161
+ const { options } = context;
162
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
163
+ (options.attribution ??= {}).track = true;
151
164
  }
152
165
 
166
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
153
167
  const runtime = (await Base.loadRuntime({
154
168
  context,
155
169
  registryEntries,
@@ -161,6 +175,7 @@ export const mixinAttributor = (Base: typeof ContainerRuntime = ContainerRuntime
161
175
  containerScope,
162
176
  existing,
163
177
  containerRuntimeCtor,
178
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
164
179
  } as any)) as ContainerRuntimeWithAttributor;
165
180
  runtime.runtimeAttributor = runtimeAttributor as RuntimeAttributor;
166
181
 
@@ -202,7 +217,7 @@ export const mixinAttributor = (Base: typeof ContainerRuntime = ContainerRuntime
202
217
  fullTree: boolean,
203
218
  trackState: boolean,
204
219
  telemetryContext?: ITelemetryContext,
205
- ) {
220
+ ): void {
206
221
  super.addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext);
207
222
  const attributorSummary = this.runtimeAttributor?.summarize();
208
223
  if (attributorSummary) {
@@ -286,7 +301,9 @@ class RuntimeAttributor implements IRuntimeAttributor {
286
301
  makeLZ4Encoder(),
287
302
  );
288
303
 
289
- if (attributorTree !== undefined) {
304
+ if (attributorTree === undefined) {
305
+ this.opAttributor = new OpStreamAttributor(deltaManager, audience);
306
+ } else {
290
307
  const id = attributorTree.blobs[opBlobName];
291
308
  assert(
292
309
  id !== undefined,
@@ -295,8 +312,6 @@ class RuntimeAttributor implements IRuntimeAttributor {
295
312
  const blobContents = await readBlob(id);
296
313
  const attributorSnapshot = bufferToString(blobContents, "utf8");
297
314
  this.opAttributor = this.encoder.decode(attributorSnapshot);
298
- } else {
299
- this.opAttributor = new OpStreamAttributor(deltaManager, audience);
300
315
  }
301
316
  }
302
317
 
@@ -36,15 +36,15 @@ export class MutableStringInterner implements StringInterner {
36
36
  * @param inputStrings - A list of strings to intern in the order given. Can be used to rehydrate from a previous
37
37
  * `StringInterner`'s {@link StringInterner.getSerializable} return value.
38
38
  */
39
- constructor(inputStrings: readonly string[] = []) {
39
+ public constructor(inputStrings: readonly string[] = []) {
40
40
  for (const value of inputStrings) {
41
41
  this.getOrCreateInternedId(value);
42
42
  }
43
43
  }
44
44
 
45
45
  /**
46
- * @param input - The string to get the associated intern ID for
47
- * @returns an intern ID that is uniquely associated with the input string
46
+ * Creates an intern ID that is uniquely associated with the input string.
47
+ * @param input - The string to get the associated intern ID for.
48
48
  */
49
49
  public getOrCreateInternedId(input: string): InternedStringId {
50
50
  return this.getInternedId(input) ?? this.createNewId(input);
@@ -55,10 +55,9 @@ export class MutableStringInterner implements StringInterner {
55
55
  }
56
56
 
57
57
  /**
58
- *
58
+ * Creates a string that is uniquely associated with the given intern ID.
59
59
  * @param internId - The intern ID to get the associated string for. Can only retrieve strings that have been
60
60
  * used as inputs to calls of `getInternId`.
61
- * @returns a string that is uniquely associated with the given intern ID
62
61
  */
63
62
  public getString(internId: number): string {
64
63
  const result = this.internedStrings[internId];
@@ -69,14 +68,18 @@ export class MutableStringInterner implements StringInterner {
69
68
  }
70
69
 
71
70
  /**
72
- * @returns The list of strings interned where the indices map to the associated {@link InternedStringId} of
71
+ * Gets the list of strings interned where the indices map to the associated {@link InternedStringId} of
73
72
  * each string.
74
73
  */
75
74
  public getSerializable(): readonly string[] {
76
75
  return this.internedStrings;
77
76
  }
78
77
 
79
- /** Create a new interned id. Assumes without validation that the input doesn't already have an interned id. */
78
+ /**
79
+ * Create a new interned id.
80
+ *
81
+ * @remarks Assumes (without validation) that the input doesn't already have an interned id.
82
+ */
80
83
  private createNewId(input: string): InternedStringId {
81
84
  const internedId = this.stringToInternedIdMap.size as InternedStringId;
82
85
  this.stringToInternedIdMap.set(input, internedId);
@@ -0,0 +1,7 @@
1
+ {
2
+ // This config must be used in a "type": "commonjs" environment. (Use fluid-tsc commonjs.)
3
+ "extends": "./tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "./dist",
6
+ },
7
+ }
package/tsconfig.json CHANGED
@@ -1,12 +1,9 @@
1
1
  {
2
- "extends": [
3
- "../../../common/build/build-common/tsconfig.base.json",
4
- "../../../common/build/build-common/tsconfig.cjs.json",
5
- ],
2
+ "extends": "../../../common/build/build-common/tsconfig.node16.json",
6
3
  "include": ["src/**/*"],
7
4
  "exclude": ["src/test/**/*"],
8
5
  "compilerOptions": {
9
6
  "rootDir": "./src",
10
- "outDir": "./dist",
7
+ "outDir": "./lib",
11
8
  },
12
9
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"attributor.d.mts","sourceRoot":"","sources":["../src/attributor.ts"],"names":[],"mappings":"OAKO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,sCAAsC;OAC3F,EAAE,eAAe,EAAE,MAAM,qCAAqC;OAE9D,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,uCAAuC;AAEhF;;;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;gBACS,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAIhE;;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;CAoBrD"}