@fluidframework/file-driver 2.118.0 → 3.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.
package/CHANGELOG.md CHANGED
@@ -1,12 +1,42 @@
1
1
  # @fluidframework/file-driver
2
2
 
3
- ## 2.118.0
3
+ ## 3.0.0
4
4
 
5
- Dependency updates only.
5
+ ### Minor Changes
6
6
 
7
- ## 2.117.0
7
+ - Removal of direct CommonJS support ([#28124](https://github.com/microsoft/FluidFramework/pull/28124)) [0f84e3b8878](https://github.com/microsoft/FluidFramework/commit/0f84e3b8878a5e75b2253976d98fd963bbd9db88)
8
8
 
9
- Dependency updates only.
9
+ Direct `require()` import is no longer directly supported.
10
+ Package is transpiled as ECMAScript Module.
11
+
12
+ See [Removal of direct CommonJS support in v3.0](https://github.com/microsoft/FluidFramework/issues/27444) for more information.
13
+
14
+ - Require modern TypeScript module resolution ([#27970](https://github.com/microsoft/FluidFramework/pull/27970)) [325e2016ca9](https://github.com/microsoft/FluidFramework/commit/325e2016ca9978d4a1f7552c97ba34feac9df41f)
15
+
16
+ Fluid Framework Client packages no longer include type declaration compatibility entrypoints for TypeScript's legacy Node10 resolution mode (`"moduleResolution": "node"` or `"node10"`).
17
+ Applications upgrading to Fluid Framework 3.0 must use one of the following supported configurations:
18
+ - `"module": "Node16"` with `"moduleResolution": "Node16"`
19
+ - `"module": "NodeNext"` with `"moduleResolution": "NodeNext"`
20
+ - `"module": "ESNext"` with `"moduleResolution": "Bundler"`
21
+
22
+ Existing public package entrypoints exposed through `package.json` exports, including `/alpha`, `/beta`, and `/legacy`, remain available under supported module resolution modes.
23
+
24
+ See [Removal of Node10 resolutions in v3.0](https://github.com/microsoft/FluidFramework/issues/27457) for more information.
25
+
26
+ - Client packages now target ES2022 ([#27846](https://github.com/microsoft/FluidFramework/pull/27846)) [91c78541bdd](https://github.com/microsoft/FluidFramework/commit/91c78541bddcbca5d6c5f357b023eeaee617d885)
27
+
28
+ The TypeScript compilation `target` and `lib` for the Fluid Framework client packages have been raised from ES2021/ES2020 to **ES2022**.
29
+ The published JavaScript now uses ES2022 language features (with correspondingly less down-leveling), so consuming these packages requires a runtime that supports ES2022.
30
+ All actively supported Node.js versions and evergreen browsers already meet this requirement.
31
+
32
+ Note that Fluid Framework has not officially supported targets older than ES2022 since before 2.0: this is documented in [ClientRequirements.md](https://github.com/microsoft/FluidFramework/blob/main/ClientRequirements.md) as well as the README for every client package.
33
+
34
+ It is possible this change could impact users of less up to date JavaScript runtimes.
35
+ Impacted users can use a tool like [babel](https://babeljs.io/) to transpile out unsupported language features.
36
+
37
+ - Build with TypeScript 6 ([#28052](https://github.com/microsoft/FluidFramework/pull/28052)) [7ab015c49de](https://github.com/microsoft/FluidFramework/commit/7ab015c49deec84833cdfe1fb5e1606b901f6e81)
38
+
39
+ FluidFramework Client SDK is now built using TypeScript 6. Consumers should build with TypeScript v6 or v7 or compatible tooling.
10
40
 
11
41
  ## 2.116.0
12
42
 
package/README.md CHANGED
@@ -9,15 +9,15 @@ This is an implementation of a driver which provides a DocumentService which use
9
9
 
10
10
  ## Using Fluid Framework libraries
11
11
 
12
- When taking a dependency on a Fluid Framework library's public APIs, we recommend using a `^` (caret) version range, such as `^1.3.4`.
13
- While Fluid Framework libraries may use different ranges with interdependencies between other Fluid Framework libraries,
14
- library consumers should always prefer `^`.
12
+ For a dependency on a Fluid Framework library's public APIs, we recommend a `^` (caret) version range.
13
+ For example, use `^1.3.4`.
15
14
 
16
- If using any of Fluid Framework's unstable APIs (for example, its `beta` APIs), we recommend using a more constrained version range, such as `~`.
15
+ For a dependency on an unstable API, such as a `beta` API, we recommend a more restrictive version range.
16
+ For example, use a `~` version range.
17
17
 
18
18
  ## Installation
19
19
 
20
- To get started, install the package by running the following command:
20
+ Run this command to install the package:
21
21
 
22
22
  ```bash
23
23
  npm i @fluidframework/file-driver
@@ -25,7 +25,7 @@ npm i @fluidframework/file-driver
25
25
 
26
26
  ## API Documentation
27
27
 
28
- API documentation for **@fluidframework/file-driver** is available at <https://fluidframework.com/docs/apis/file-driver>.
28
+ Read the **@fluidframework/file-driver** API documentation at <https://fluidframework.com/docs/apis/file-driver>.
29
29
 
30
30
  <!-- prettier-ignore-end -->
31
31
 
@@ -38,62 +38,69 @@ API documentation for **@fluidframework/file-driver** is available at <https://f
38
38
 
39
39
  ## Minimum Client Requirements
40
40
 
41
- These are the platform requirements for the current version of Fluid Framework Client Packages.
42
- These requirements err on the side of being too strict since within a major version they can be relaxed over time, but not made stricter.
43
- For Long Term Support (LTS) versions this can require supporting these platforms for several years.
41
+ Fluid Framework client libraries support the platforms in this document.
42
+ These requirements are intentionally restrictive.
43
+ Within a major version series, we can relax these requirements, but we cannot make them stricter.
44
+ For a Long Term Support (LTS) version, we might need to support these platforms for several years.
44
45
 
45
- It is likely that other configurations will work, but they are not supported: if they stop working, we do not consider that a bug.
46
- If you would benefit from support for something not listed here, file an issue and the product team will evaluate your request.
47
- When making such a request please include if the configuration already works (and thus the request is just that it becomes officially supported), or if changes are required to get it working.
46
+ Other configurations can work, but Fluid Framework does not support them.
47
+ If an unsupported configuration stops working, we do not classify this as a bug.
48
+ To request support for a configuration that is not listed, file an issue.
49
+ The product team will evaluate your request.
50
+ In the issue, specify the current status of the configuration:
51
+
52
+ - The configuration works but needs official support.
53
+ - The configuration does not work and requires changes.
48
54
 
49
55
  ### Supported Runtimes
50
56
 
51
- - NodeJs ^22.22.2 except that we will drop support for it [when NodeJs 22 loses its upstream support on 2027-04-30](https://github.com/nodejs/release#release-schedule), and will support a newer LTS version of NodeJS at least 1 year before 22 is end-of-life.
52
- - Running Fluid in a Node.js environment with the `--no-experimental-fetch` flag is not supported.
53
- - Modern browsers supporting the es2022 standard library: in response to asks we can add explicit support for using babel to polyfill to target specific standards or runtimes (meaning we can avoid/remove use of things that don't polyfill robustly, but otherwise target modern standards).
57
+ - Fluid Framework supports Node.js versions 22 and 24 while they receive [upstream support](https://nodejs.org/en/about/previous-releases).
58
+ - Fluid Framework will stop support for version 22 [when upstream support ends on 2027-04-30](https://github.com/nodejs/release#release-schedule).
59
+ - Fluid Framework does not support Node.js with the `--no-experimental-fetch` flag.
60
+ - Fluid Framework supports modern browsers that support the ES2022 standard library.
54
61
 
55
62
  ### Supported Tools
56
63
 
57
- - TypeScript 5.4:
58
- - All [`strict`](https://www.typescriptlang.org/tsconfig) options are supported.
59
- - [`strictNullChecks`](https://www.typescriptlang.org/tsconfig) is required.
60
- - [Configuration options deprecated in 5.0](https://github.com/microsoft/TypeScript/issues/51909) are not supported.
61
- - `exactOptionalPropertyTypes` is currently not fully supported.
62
- If used, narrowing members of Fluid Framework types types using `in`, `Reflect.has`, `Object.hasOwn` or `Object.prototype.hasOwnProperty` should be avoided as they may incorrectly exclude `undefined` from the possible values in some cases.
64
+ - [TypeScript 6.0](https://typescriptdocs.com/release-notes/TypeScript%206.0):
65
+ - Fluid Framework supports all [`strict`](https://www.typescriptlang.org/tsconfig) options.
66
+ - Set the build targets (`lib`, `target`) to `ES2022` or later.
67
+ - Enable [`strictNullChecks`](https://www.typescriptlang.org/tsconfig).
68
+ - Fluid Framework does not support [configuration options deprecated in TypeScript 6.0](https://typescriptdocs.com/release-notes/TypeScript%206.0#breaking-changes-and-deprecations-in-typescript-6-0).
69
+ - Fluid Framework does not fully support `exactOptionalPropertyTypes`.
70
+ If you enable this option, do not use `in`, `Reflect.has`, `Object.hasOwn`, or `Object.prototype.hasOwnProperty` to narrow members of Fluid Framework types.
71
+ These methods can incorrectly exclude `undefined` from the possible values.
63
72
  - [webpack](https://webpack.js.org/) 5
64
- - We are not intending to be prescriptive about what bundler to use.
65
- Other bundlers which can handle ES Modules should work, but webpack is the only one we actively test.
73
+ - We do not require a specific bundler.
74
+ Other bundlers that handle ES Modules can work, but we actively test only webpack.
66
75
 
67
76
  ### Module Resolution
68
77
 
69
- [`Node16`, `NodeNext`, or `Bundler`](https://www.typescriptlang.org/tsconfig#moduleResolution) resolution should be used with TypeScript compilerOptions to follow the [Node.js v12+ ESM Resolution and Loading algorithm](https://nodejs.github.io/nodejs.dev/en/api/v20/esm/#resolution-and-loading-algorithm).
70
- Node10 resolution is not supported as it does not support Fluid Framework's API structuring pattern that is used to distinguish stable APIs from those that are in development.
78
+ In TypeScript `compilerOptions`, use [`Node16`, `Node20`, `NodeNext`, or `Bundler`](https://www.typescriptlang.org/tsconfig#moduleResolution) module resolution.
79
+ These settings follow the [Node.js v12+ ESM Resolution and Loading algorithm](https://nodejs.github.io/nodejs.dev/en/api/v20/esm/#resolution-and-loading-algorithm).
80
+
81
+ Do not use `Node10` module resolution.
71
82
 
72
83
  ### Module Formats
73
84
 
74
85
  - ES Modules:
75
- ES Modules are the preferred way to consume our client packages (including in NodeJs) and consuming our client packages from ES Modules is fully supported.
76
- - CommonJs:
77
- Consuming our client packages as CommonJs is supported only in NodeJS and only for the cases listed below.
78
- This is done to accommodate some workflows without good ES Module support.
79
- If you have a workflow you would like included in this list, file an issue.
80
- Once this list of workflows motivating CommonJS support is empty, we may drop support for CommonJS one year after notice of the change is posted here.
81
-
82
- - Testing with Jest (which lacks [stable ESM support](https://jestjs.io/docs/ecmascript-modules) due to [unstable APIs in NodeJs](https://github.com/nodejs/node/issues/37648))
86
+ Use ES Modules to consume Fluid Framework client packages, including in Node.js.
87
+ - CommonJS:
88
+ Fluid Framework does not officially support CommonJS in version 3.0 or later.
83
89
 
84
90
  ## Contribution Guidelines
85
91
 
86
- There are many ways to [contribute](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md) to Fluid.
92
+ You can [contribute](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md) to Fluid Framework in these ways:
87
93
 
88
- - Participate in Q&A in our [GitHub Discussions](https://github.com/microsoft/FluidFramework/discussions).
89
- - [Submit bugs](https://github.com/microsoft/FluidFramework/issues) and help us verify fixes as they are checked in.
90
- - Review the [source code changes](https://github.com/microsoft/FluidFramework/pulls).
94
+ - Answer questions in [GitHub Discussions](https://github.com/microsoft/FluidFramework/discussions).
95
+ - [Submit bug reports](https://github.com/microsoft/FluidFramework/issues) and help verify fixes.
96
+ - Review [source code changes](https://github.com/microsoft/FluidFramework/pulls).
91
97
  - [Contribute bug fixes](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md).
92
98
 
93
- Detailed instructions for working in the repo can be found in the [Wiki](https://github.com/microsoft/FluidFramework/blob/main/docs/content/Home.md).
99
+ For detailed instructions, read the [repo documentation](https://github.com/microsoft/FluidFramework/blob/main/docs/content/Home.md).
94
100
 
95
- This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
96
- For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
101
+ This project follows the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
102
+ For more information, read the [Code of Conduct frequently asked questions](https://opensource.microsoft.com/codeofconduct/faq/).
103
+ For questions or comments, contact [opencode@microsoft.com](mailto:opencode@microsoft.com).
97
104
 
98
105
  This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services.
99
106
  Use of these trademarks or logos must follow Microsoft’s [Trademark & Brand Guidelines](https://www.microsoft.com/trademarks).
@@ -101,13 +108,9 @@ Use of Microsoft trademarks or logos in modified versions of this project must n
101
108
 
102
109
  ## Help
103
110
 
104
- Not finding what you're looking for in this README?
105
- Check out [fluidframework.com](https://fluidframework.com/docs/).
106
-
107
- Still not finding what you're looking for?
108
- Please [file an issue](https://github.com/microsoft/FluidFramework/blob/main/docs/content/Contributing/Submitting-Bugs-and-Feature-Requests.md).
111
+ Read the [Fluid Framework documentation](https://fluidframework.com/docs/) for information about Fluid Framework concepts and APIs.
109
112
 
110
- Thank you!
113
+ To request information that the documentation does not contain, [create an issue](https://github.com/microsoft/FluidFramework/blob/main/docs/content/Contributing/Submitting-Bugs-and-Feature-Requests.md).
111
114
 
112
115
  ## Trademark
113
116
 
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3
- "extends": "../../../common/build/build-common/api-extractor-base.esm.no-legacy.json"
3
+ "extends": "<projectFolder>/../../../common/build/build-common/api-extractor-model.esm.json"
4
4
  }
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3
+ "extends": "<projectFolder>/../../../common/build/build-common/api-extractor-report-base.esm.json",
4
+ "mainEntryPointFilePath": "<projectFolder>/lib/public.d.ts"
5
+ }
@@ -16,9 +16,11 @@ const internal_2 = require("@fluidframework/driver-utils/internal");
16
16
  * @internal
17
17
  */
18
18
  class FileDeltaStorageService {
19
+ path;
20
+ messages;
21
+ lastOps = [];
19
22
  constructor(path) {
20
23
  this.path = path;
21
- this.lastOps = [];
22
24
  this.messages = [];
23
25
  let counter = 0;
24
26
  while (true) {
@@ -1 +1 @@
1
- {"version":3,"file":"fileDeltaStorageService.js","sourceRoot":"","sources":["../src/fileDeltaStorageService.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,4CAAoB;AAEpB,kEAA6D;AAM7D,oEAA2E;AAE3E;;;GAGG;AACH,MAAa,uBAAuB;IAInC,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAFjC,YAAO,GAAgC,EAAE,CAAC;QAGjD,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,aAAa,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC;YAC9E,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,YAAY,CAAC,CAAC;gBAC/C,CAAC;gBACD,MAAM;YACP,CAAC;YACD,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACzE,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IAEM,aAAa,CACnB,IAAY,EACZ,EAAsB,EACtB,WAAyB,EACzB,UAAoB;QAEpB,OAAO,6BAAkB,CAAC;IAC3B,CAAC;IAED,IAAW,GAAG;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACI,gBAAgB,CAAC,IAAY,EAAE,EAAU;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;QAE/D,IAAI,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,MAAM,IAAI,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;YAC3E,OAAO,EAAE,CAAC;QACX,CAAC;QAED,mDAAmD;QACnD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC,OAAO,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrD,IAAA,iBAAM,EACL,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAC/C,KAAK,CAAC,kEAAkE,CACxE,CAAC;QACF,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;CACD;AA3DD,0DA2DC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport fs from \"fs\";\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type {\n\tIDocumentDeltaStorageService,\n\tIStream,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { emptyMessageStream } from \"@fluidframework/driver-utils/internal\";\n\n/**\n * Provides access to the underlying delta storage on the local file storage for file driver.\n * @internal\n */\nexport class FileDeltaStorageService implements IDocumentDeltaStorageService {\n\tprivate readonly messages: ISequencedDocumentMessage[];\n\tprivate lastOps: ISequencedDocumentMessage[] = [];\n\n\tconstructor(private readonly path: string) {\n\t\tthis.messages = [];\n\t\tlet counter = 0;\n\t\twhile (true) {\n\t\t\tconst filename = `${this.path}//messages${counter === 0 ? \"\" : counter}.json`;\n\t\t\tif (!fs.existsSync(filename)) {\n\t\t\t\tif (counter === 0) {\n\t\t\t\t\tthrow new Error(`file ${filename} not found`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst data = fs.readFileSync(filename);\n\t\t\tthis.messages = this.messages.concat(JSON.parse(data.toString(\"utf-8\")));\n\t\t\tcounter++;\n\t\t}\n\t}\n\n\tpublic fetchMessages(\n\t\tfrom: number,\n\t\tto: number | undefined,\n\t\tabortSignal?: AbortSignal,\n\t\tcachedOnly?: boolean,\n\t): IStream<ISequencedDocumentMessage[]> {\n\t\treturn emptyMessageStream;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.messages;\n\t}\n\n\t/**\n\t * Retrieve ops within the exclusive sequence number range.\n\t *\n\t * @param from - First op to be fetched.\n\t * @param to - Last op to be fetched. This is exclusive.\n\t */\n\tpublic getFromWebSocket(from: number, to: number): ISequencedDocumentMessage[] {\n\t\tconst readFrom = Math.max(from, 0); // Inclusive\n\t\tconst readTo = Math.min(to, this.messages.length); // Exclusive\n\n\t\tif (readFrom >= this.messages.length || readTo <= 0 || readFrom >= readTo) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Optimizations for multiple readers (replay tool)\n\t\tif (this.lastOps.length > 0 && this.lastOps[0].sequenceNumber === readFrom + 1) {\n\t\t\treturn this.lastOps;\n\t\t}\n\t\tthis.lastOps = this.messages.slice(readFrom, readTo);\n\t\tassert(\n\t\t\tthis.lastOps[0].sequenceNumber === readFrom + 1,\n\t\t\t0x091 /* \"Retrieved ops' first sequence number has unexpected value!\" */,\n\t\t);\n\t\treturn this.lastOps;\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDeltaStorageService.js","sourceRoot":"","sources":["../src/fileDeltaStorageService.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,4CAAoB;AAEpB,kEAA6D;AAM7D,oEAA2E;AAE3E;;;GAGG;AACH,MAAa,uBAAuB;IAIN;IAHZ,QAAQ,CAA8B;IAC/C,OAAO,GAAgC,EAAE,CAAC;IAElD,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QACxC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,aAAa,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC;YAC9E,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,YAAY,CAAC,CAAC;gBAC/C,CAAC;gBACD,MAAM;YACP,CAAC;YACD,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACzE,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IAEM,aAAa,CACnB,IAAY,EACZ,EAAsB,EACtB,WAAyB,EACzB,UAAoB;QAEpB,OAAO,6BAAkB,CAAC;IAC3B,CAAC;IAED,IAAW,GAAG;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACI,gBAAgB,CAAC,IAAY,EAAE,EAAU;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;QAE/D,IAAI,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,MAAM,IAAI,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;YAC3E,OAAO,EAAE,CAAC;QACX,CAAC;QAED,mDAAmD;QACnD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC,OAAO,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrD,IAAA,iBAAM,EACL,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAC/C,KAAK,CAAC,kEAAkE,CACxE,CAAC;QACF,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;CACD;AA3DD,0DA2DC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport fs from \"fs\";\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type {\n\tIDocumentDeltaStorageService,\n\tIStream,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { emptyMessageStream } from \"@fluidframework/driver-utils/internal\";\n\n/**\n * Provides access to the underlying delta storage on the local file storage for file driver.\n * @internal\n */\nexport class FileDeltaStorageService implements IDocumentDeltaStorageService {\n\tprivate readonly messages: ISequencedDocumentMessage[];\n\tprivate lastOps: ISequencedDocumentMessage[] = [];\n\n\tconstructor(private readonly path: string) {\n\t\tthis.messages = [];\n\t\tlet counter = 0;\n\t\twhile (true) {\n\t\t\tconst filename = `${this.path}//messages${counter === 0 ? \"\" : counter}.json`;\n\t\t\tif (!fs.existsSync(filename)) {\n\t\t\t\tif (counter === 0) {\n\t\t\t\t\tthrow new Error(`file ${filename} not found`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst data = fs.readFileSync(filename);\n\t\t\tthis.messages = this.messages.concat(JSON.parse(data.toString(\"utf-8\")));\n\t\t\tcounter++;\n\t\t}\n\t}\n\n\tpublic fetchMessages(\n\t\tfrom: number,\n\t\tto: number | undefined,\n\t\tabortSignal?: AbortSignal,\n\t\tcachedOnly?: boolean,\n\t): IStream<ISequencedDocumentMessage[]> {\n\t\treturn emptyMessageStream;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.messages;\n\t}\n\n\t/**\n\t * Retrieve ops within the exclusive sequence number range.\n\t *\n\t * @param from - First op to be fetched.\n\t * @param to - Last op to be fetched. This is exclusive.\n\t */\n\tpublic getFromWebSocket(from: number, to: number): ISequencedDocumentMessage[] {\n\t\tconst readFrom = Math.max(from, 0); // Inclusive\n\t\tconst readTo = Math.min(to, this.messages.length); // Exclusive\n\n\t\tif (readFrom >= this.messages.length || readTo <= 0 || readFrom >= readTo) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Optimizations for multiple readers (replay tool)\n\t\tif (this.lastOps.length > 0 && this.lastOps[0].sequenceNumber === readFrom + 1) {\n\t\t\treturn this.lastOps;\n\t\t}\n\t\tthis.lastOps = this.messages.slice(readFrom, readTo);\n\t\tassert(\n\t\t\tthis.lastOps[0].sequenceNumber === readFrom + 1,\n\t\t\t0x091 /* \"Retrieved ops' first sequence number has unexpected value!\" */,\n\t\t);\n\t\treturn this.lastOps;\n\t}\n}\n"]}
@@ -28,10 +28,12 @@ const Claims = {
28
28
  * @internal
29
29
  */
30
30
  class Replayer {
31
+ deltaConnection;
32
+ documentStorageService;
33
+ currentReplayOp = 0;
31
34
  constructor(deltaConnection, documentStorageService) {
32
35
  this.deltaConnection = deltaConnection;
33
36
  this.documentStorageService = documentStorageService;
34
- this.currentReplayOp = 0;
35
37
  }
36
38
  get currentReplayedOp() {
37
39
  return this.currentReplayOp;
@@ -84,6 +86,7 @@ exports.Replayer = Replayer;
84
86
  * @internal
85
87
  */
86
88
  class ReplayFileDeltaConnection extends client_utils_1.TypedEventEmitter {
89
+ details;
87
90
  /**
88
91
  * Mimic the delta connection to replay ops on it.
89
92
  *
@@ -112,11 +115,11 @@ class ReplayFileDeltaConnection extends client_utils_1.TypedEventEmitter {
112
115
  const deltaConnection = new ReplayFileDeltaConnection(connection, documentDeltaStorageService);
113
116
  return deltaConnection;
114
117
  }
118
+ maxMessageSize = ReplayMaxMessageSize;
119
+ replayer;
115
120
  constructor(details, documentDeltaStorageService) {
116
121
  super();
117
122
  this.details = details;
118
- this.maxMessageSize = ReplayMaxMessageSize;
119
- this._disposed = false;
120
123
  this.replayer = new Replayer(this, documentDeltaStorageService);
121
124
  }
122
125
  getReplayer() {
@@ -156,6 +159,7 @@ class ReplayFileDeltaConnection extends client_utils_1.TypedEventEmitter {
156
159
  }
157
160
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
158
161
  async submitSignal(message) { }
162
+ _disposed = false;
159
163
  get disposed() {
160
164
  return this._disposed;
161
165
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/fileDocumentDeltaConnection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport type { ConnectionMode } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaConnectionEvents,\n\tIClientConfiguration,\n\tIConnected,\n\tIDocumentMessage,\n\tISignalClient,\n\tITokenClaims,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { ScopeType } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\nconst MaxBatchDeltas = 2000;\n\n// Since the replay service never actually sends messages the size below is arbitrary\nconst ReplayMaxMessageSize = 16 * 1024;\n\nconst fileProtocolVersion = \"^0.1.0\";\n\nconst replayDocumentId = \"replayDocId\";\n\nconst Claims: ITokenClaims = {\n\tdocumentId: replayDocumentId,\n\tscopes: [ScopeType.DocRead],\n\ttenantId: \"\",\n\tuser: {\n\t\tid: \"\",\n\t},\n\tiat: Math.round(Date.now() / 1000),\n\texp: Math.round(Date.now() / 1000) + 60 * 60, // 1 hour expiration\n\tver: \"1.0\",\n};\n\n/**\n * Replay service used to play ops using the delta connection.\n * @internal\n */\nexport class Replayer {\n\tprivate currentReplayOp = 0;\n\n\tconstructor(\n\t\tprivate readonly deltaConnection: ReplayFileDeltaConnection,\n\t\tprivate readonly documentStorageService: FileDeltaStorageService,\n\t) {}\n\n\tpublic get currentReplayedOp(): number {\n\t\treturn this.currentReplayOp;\n\t}\n\n\tpublic set currentReplayedOp(op: number) {\n\t\tthis.currentReplayOp = op;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.documentStorageService.ops;\n\t}\n\n\t/**\n\t * Replay the ops upto a certain number.\n\t * @param replayTo - The last op number to be replayed.\n\t */\n\tpublic replay(replayTo: number): number {\n\t\tlet totalReplayedOps = 0;\n\t\tlet done: boolean;\n\t\tdo {\n\t\t\tconst fetchToBatch = this.currentReplayOp + MaxBatchDeltas;\n\t\t\tconst fetchTo = Math.min(fetchToBatch, replayTo);\n\n\t\t\tconst fetchedOps = this.documentStorageService.getFromWebSocket(\n\t\t\t\tthis.currentReplayOp,\n\t\t\t\tfetchTo,\n\t\t\t);\n\n\t\t\tif (fetchedOps.length <= 0) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tthis.emit(fetchedOps);\n\t\t\t\ttotalReplayedOps += fetchedOps.length;\n\t\t\t\tthis.currentReplayOp += fetchedOps.length;\n\t\t\t\tdone = this.isDoneFetch(replayTo);\n\t\t\t}\n\t\t} while (!done);\n\t\treturn totalReplayedOps;\n\t}\n\n\tprivate isDoneFetch(replayTo: number): boolean {\n\t\tif (replayTo >= 0) {\n\t\t\treturn this.currentReplayOp >= replayTo;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate emit(ops: ISequencedDocumentMessage[]): void {\n\t\t// Note: do not clone messages here!\n\t\t// If Replay Tool fails due to one container patching message in-place,\n\t\t// then same thing can happen in shipping product due to\n\t\t// socket reuse in ODSP between main and summarizer containers.\n\t\tthis.deltaConnection.emit(\"op\", replayDocumentId, ops);\n\t}\n}\n\n/**\n * @internal\n */\nexport class ReplayFileDeltaConnection\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\t/**\n\t * Mimic the delta connection to replay ops on it.\n\t *\n\t * @param documentDeltaStorageService - The delta storage service to get ops from.\n\t * @returns Document delta connection.\n\t */\n\tpublic static async create(\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t): Promise<ReplayFileDeltaConnection> {\n\t\tconst mode: ConnectionMode = \"read\";\n\t\tconst connection = {\n\t\t\tclaims: Claims,\n\t\t\tclientId: \"PseudoClientId\",\n\t\t\texisting: true,\n\t\t\tinitialMessages: [],\n\t\t\tinitialSignals: [],\n\t\t\tinitialClients: [],\n\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\tmode,\n\t\t\tserviceConfiguration: {\n\t\t\t\tblockSize: 64436,\n\t\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\t},\n\t\t\tsupportedVersions: [fileProtocolVersion],\n\t\t\tuser: null,\n\t\t\tversion: fileProtocolVersion,\n\t\t};\n\t\tconst deltaConnection = new ReplayFileDeltaConnection(\n\t\t\tconnection,\n\t\t\tdocumentDeltaStorageService,\n\t\t);\n\t\treturn deltaConnection;\n\t}\n\n\tpublic readonly maxMessageSize = ReplayMaxMessageSize;\n\tprivate readonly replayer: Replayer;\n\n\tpublic constructor(\n\t\tpublic details: IConnected,\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t) {\n\t\tsuper();\n\t\tthis.replayer = new Replayer(this, documentDeltaStorageService);\n\t}\n\n\tpublic getReplayer(): Replayer {\n\t\treturn this.replayer;\n\t}\n\n\tpublic get clientId(): string {\n\t\treturn this.details.clientId;\n\t}\n\n\tpublic get mode(): ConnectionMode {\n\t\treturn this.details.mode;\n\t}\n\n\tpublic get claims(): ITokenClaims {\n\t\treturn this.details.claims;\n\t}\n\n\tpublic get existing(): boolean {\n\t\treturn this.details.existing;\n\t}\n\n\tpublic get version(): string {\n\t\treturn this.details.version;\n\t}\n\n\tpublic get initialMessages(): ISequencedDocumentMessage[] {\n\t\treturn this.details.initialMessages;\n\t}\n\n\tpublic get initialSignals(): ISignalMessage[] {\n\t\treturn this.details.initialSignals;\n\t}\n\n\tpublic get initialClients(): ISignalClient[] {\n\t\treturn this.details.initialClients;\n\t}\n\n\tpublic get serviceConfiguration(): IClientConfiguration {\n\t\treturn this.details.serviceConfiguration;\n\t}\n\n\tpublic submit(documentMessages: IDocumentMessage[]): void {\n\t\t// ReplayFileDeltaConnection.submit() can't be called - client never sees its own join on,\n\t\t// and thus can never move to sending ops.\n\t\tthrow new Error(\"ReplayFileDeltaConnection.submit() can't be called\");\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\tpublic async submitSignal(message: any): Promise<void> {}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/fileDocumentDeltaConnection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport type { ConnectionMode } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaConnectionEvents,\n\tIClientConfiguration,\n\tIConnected,\n\tIDocumentMessage,\n\tISignalClient,\n\tITokenClaims,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { ScopeType } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\nconst MaxBatchDeltas = 2000;\n\n// Since the replay service never actually sends messages the size below is arbitrary\nconst ReplayMaxMessageSize = 16 * 1024;\n\nconst fileProtocolVersion = \"^0.1.0\";\n\nconst replayDocumentId = \"replayDocId\";\n\nconst Claims: ITokenClaims = {\n\tdocumentId: replayDocumentId,\n\tscopes: [ScopeType.DocRead],\n\ttenantId: \"\",\n\tuser: {\n\t\tid: \"\",\n\t},\n\tiat: Math.round(Date.now() / 1000),\n\texp: Math.round(Date.now() / 1000) + 60 * 60, // 1 hour expiration\n\tver: \"1.0\",\n};\n\n/**\n * Replay service used to play ops using the delta connection.\n * @internal\n */\nexport class Replayer {\n\tprivate currentReplayOp = 0;\n\n\tconstructor(\n\t\tprivate readonly deltaConnection: ReplayFileDeltaConnection,\n\t\tprivate readonly documentStorageService: FileDeltaStorageService,\n\t) {}\n\n\tpublic get currentReplayedOp(): number {\n\t\treturn this.currentReplayOp;\n\t}\n\n\tpublic set currentReplayedOp(op: number) {\n\t\tthis.currentReplayOp = op;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.documentStorageService.ops;\n\t}\n\n\t/**\n\t * Replay the ops upto a certain number.\n\t * @param replayTo - The last op number to be replayed.\n\t */\n\tpublic replay(replayTo: number): number {\n\t\tlet totalReplayedOps = 0;\n\t\tlet done: boolean;\n\t\tdo {\n\t\t\tconst fetchToBatch = this.currentReplayOp + MaxBatchDeltas;\n\t\t\tconst fetchTo = Math.min(fetchToBatch, replayTo);\n\n\t\t\tconst fetchedOps = this.documentStorageService.getFromWebSocket(\n\t\t\t\tthis.currentReplayOp,\n\t\t\t\tfetchTo,\n\t\t\t);\n\n\t\t\tif (fetchedOps.length <= 0) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tthis.emit(fetchedOps);\n\t\t\t\ttotalReplayedOps += fetchedOps.length;\n\t\t\t\tthis.currentReplayOp += fetchedOps.length;\n\t\t\t\tdone = this.isDoneFetch(replayTo);\n\t\t\t}\n\t\t} while (!done);\n\t\treturn totalReplayedOps;\n\t}\n\n\tprivate isDoneFetch(replayTo: number): boolean {\n\t\tif (replayTo >= 0) {\n\t\t\treturn this.currentReplayOp >= replayTo;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate emit(ops: ISequencedDocumentMessage[]): void {\n\t\t// Note: do not clone messages here!\n\t\t// If Replay Tool fails due to one container patching message in-place,\n\t\t// then same thing can happen in shipping product due to\n\t\t// socket reuse in ODSP between main and summarizer containers.\n\t\tthis.deltaConnection.emit(\"op\", replayDocumentId, ops);\n\t}\n}\n\n/**\n * @internal\n */\nexport class ReplayFileDeltaConnection\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\t/**\n\t * Mimic the delta connection to replay ops on it.\n\t *\n\t * @param documentDeltaStorageService - The delta storage service to get ops from.\n\t * @returns Document delta connection.\n\t */\n\tpublic static async create(\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t): Promise<ReplayFileDeltaConnection> {\n\t\tconst mode: ConnectionMode = \"read\";\n\t\tconst connection = {\n\t\t\tclaims: Claims,\n\t\t\tclientId: \"PseudoClientId\",\n\t\t\texisting: true,\n\t\t\tinitialMessages: [],\n\t\t\tinitialSignals: [],\n\t\t\tinitialClients: [],\n\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\tmode,\n\t\t\tserviceConfiguration: {\n\t\t\t\tblockSize: 64436,\n\t\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\t},\n\t\t\tsupportedVersions: [fileProtocolVersion],\n\t\t\tuser: null,\n\t\t\tversion: fileProtocolVersion,\n\t\t};\n\t\tconst deltaConnection = new ReplayFileDeltaConnection(\n\t\t\tconnection,\n\t\t\tdocumentDeltaStorageService,\n\t\t);\n\t\treturn deltaConnection;\n\t}\n\n\tpublic readonly maxMessageSize = ReplayMaxMessageSize;\n\tprivate readonly replayer: Replayer;\n\n\tpublic constructor(\n\t\tpublic details: IConnected,\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t) {\n\t\tsuper();\n\t\tthis.replayer = new Replayer(this, documentDeltaStorageService);\n\t}\n\n\tpublic getReplayer(): Replayer {\n\t\treturn this.replayer;\n\t}\n\n\tpublic get clientId(): string {\n\t\treturn this.details.clientId;\n\t}\n\n\tpublic get mode(): ConnectionMode {\n\t\treturn this.details.mode;\n\t}\n\n\tpublic get claims(): ITokenClaims {\n\t\treturn this.details.claims;\n\t}\n\n\tpublic get existing(): boolean {\n\t\treturn this.details.existing;\n\t}\n\n\tpublic get version(): string {\n\t\treturn this.details.version;\n\t}\n\n\tpublic get initialMessages(): ISequencedDocumentMessage[] {\n\t\treturn this.details.initialMessages;\n\t}\n\n\tpublic get initialSignals(): ISignalMessage[] {\n\t\treturn this.details.initialSignals;\n\t}\n\n\tpublic get initialClients(): ISignalClient[] {\n\t\treturn this.details.initialClients;\n\t}\n\n\tpublic get serviceConfiguration(): IClientConfiguration {\n\t\treturn this.details.serviceConfiguration;\n\t}\n\n\tpublic submit(documentMessages: IDocumentMessage[]): void {\n\t\t// ReplayFileDeltaConnection.submit() can't be called - client never sees its own join on,\n\t\t// and thus can never move to sending ops.\n\t\tthrow new Error(\"ReplayFileDeltaConnection.submit() can't be called\");\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\tpublic async submitSignal(message: any): Promise<void> {}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\n"]}
@@ -11,6 +11,10 @@ const client_utils_1 = require("@fluid-internal/client-utils");
11
11
  * underlying storage for file document service.
12
12
  */
13
13
  class FileDocumentService extends client_utils_1.TypedEventEmitter {
14
+ resolvedUrl;
15
+ storage;
16
+ deltaStorage;
17
+ deltaConnection;
14
18
  constructor(resolvedUrl, storage, deltaStorage, deltaConnection) {
15
19
  super();
16
20
  this.resolvedUrl = resolvedUrl;
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentService.js","sourceRoot":"","sources":["../src/fileDocumentService.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAajE;;;GAGG;AACH,MAAa,mBACZ,SAAQ,gCAAyC;IAGjD,YACiB,WAAyB,EACxB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAE1D,KAAK,EAAE,CAAC;QALQ,gBAAW,GAAX,WAAW,CAAc;QACxB,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IAG3D,CAAC;IAEM,OAAO,KAAU,CAAC;IAElB,KAAK,CAAC,gBAAgB;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,qBAAqB;QACjC,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,oBAAoB,CAAC,MAAe;QAChD,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;CACD;AAjCD,kDAiCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IClient } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentServiceEvents,\n\tIDocumentService,\n\tIResolvedUrl,\n\tIDocumentStorageService,\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaStorageService,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\n/**\n * The DocumentService manages the different endpoints for connecting to\n * underlying storage for file document service.\n */\nexport class FileDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {\n\t\tsuper();\n\t}\n\n\tpublic dispose(): void {}\n\n\tpublic async connectToStorage(): Promise<IDocumentStorageService> {\n\t\treturn this.storage;\n\t}\n\n\tpublic async connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn this.deltaStorage;\n\t}\n\n\t/**\n\t * Connects to a delta storage endpoint of provided documentService to get ops and then replaying\n\t * them so as to mimic a delta stream endpoint.\n\t *\n\t * @param client - Client that connects to socket.\n\t * @returns returns the delta stream service.\n\t */\n\tpublic async connectToDeltaStream(client: IClient): Promise<IDocumentDeltaConnection> {\n\t\treturn this.deltaConnection;\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDocumentService.js","sourceRoot":"","sources":["../src/fileDocumentService.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAajE;;;GAGG;AACH,MAAa,mBACZ,SAAQ,gCAAyC;IAIhC;IACC;IACA;IACA;IAJlB,YACiB,WAAyB,EACxB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAE1D,KAAK,EAAE,CAAC;QALQ,gBAAW,GAAX,WAAW,CAAc;QACxB,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IAG3D,CAAC;IAEM,OAAO,KAAU,CAAC;IAElB,KAAK,CAAC,gBAAgB;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,qBAAqB;QACjC,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,oBAAoB,CAAC,MAAe;QAChD,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;CACD;AAjCD,kDAiCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IClient } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentServiceEvents,\n\tIDocumentService,\n\tIResolvedUrl,\n\tIDocumentStorageService,\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaStorageService,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\n/**\n * The DocumentService manages the different endpoints for connecting to\n * underlying storage for file document service.\n */\nexport class FileDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {\n\t\tsuper();\n\t}\n\n\tpublic dispose(): void {}\n\n\tpublic async connectToStorage(): Promise<IDocumentStorageService> {\n\t\treturn this.storage;\n\t}\n\n\tpublic async connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn this.deltaStorage;\n\t}\n\n\t/**\n\t * Connects to a delta storage endpoint of provided documentService to get ops and then replaying\n\t * them so as to mimic a delta stream endpoint.\n\t *\n\t * @param client - Client that connects to socket.\n\t * @returns returns the delta stream service.\n\t */\n\tpublic async connectToDeltaStream(client: IClient): Promise<IDocumentDeltaConnection> {\n\t\treturn this.deltaConnection;\n\t}\n}\n"]}
@@ -12,6 +12,9 @@ const fileDocumentService_js_1 = require("./fileDocumentService.js");
12
12
  * @internal
13
13
  */
14
14
  class FileDocumentServiceFactory {
15
+ storage;
16
+ deltaStorage;
17
+ deltaConnection;
15
18
  constructor(storage, deltaStorage, deltaConnection) {
16
19
  this.storage = storage;
17
20
  this.deltaStorage = deltaStorage;
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentServiceFactory.js","sourceRoot":"","sources":["../src/fileDocumentServiceFactory.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAaH,qEAA+D;AAE/D;;;;GAIG;AACH,MAAa,0BAA0B;IACtC,YACkB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAFzC,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IACxD,CAAC;IAEJ;;;;;OAKG;IACI,KAAK,CAAC,qBAAqB,CACjC,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,OAAO,IAAI,4CAAmB,CAC7B,WAAW,EACX,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,eAAe,CACpB,CAAC;IACH,CAAC;IAED,8EAA8E;IACvE,KAAK,CAAC,eAAe,CAC3B,gBAA8B,EAC9B,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;CACD;AAnCD,gEAmCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentService,\n\tIDocumentServiceFactory,\n\tIDocumentStorageService,\n\tIResolvedUrl,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\nimport { FileDocumentService } from \"./fileDocumentService.js\";\n\n/**\n * Factory for creating the file document service. Use this if you want to\n * use the local file storage as underlying storage.\n * @internal\n */\nexport class FileDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {}\n\n\t/**\n\t * Creates the file document service if the path exists.\n\t *\n\t * @param fileURL - Path of directory containing ops/snapshots.\n\t * @returns file document service.\n\t */\n\tpublic async createDocumentService(\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\treturn new FileDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tthis.storage,\n\t\t\tthis.deltaStorage,\n\t\t\tthis.deltaConnection,\n\t\t);\n\t}\n\n\t// TODO: Issue-2109 Implement detach container api or put appropriate comment.\n\tpublic async createContainer(\n\t\tcreateNewSummary: ISummaryTree,\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\tthrow new Error(\"Not implemented\");\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDocumentServiceFactory.js","sourceRoot":"","sources":["../src/fileDocumentServiceFactory.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAaH,qEAA+D;AAE/D;;;;GAIG;AACH,MAAa,0BAA0B;IAEpB;IACA;IACA;IAHlB,YACkB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAFzC,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IACxD,CAAC;IAEJ;;;;;OAKG;IACI,KAAK,CAAC,qBAAqB,CACjC,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,OAAO,IAAI,4CAAmB,CAC7B,WAAW,EACX,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,eAAe,CACpB,CAAC;IACH,CAAC;IAED,8EAA8E;IACvE,KAAK,CAAC,eAAe,CAC3B,gBAA8B,EAC9B,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;CACD;AAnCD,gEAmCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentService,\n\tIDocumentServiceFactory,\n\tIDocumentStorageService,\n\tIResolvedUrl,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\nimport { FileDocumentService } from \"./fileDocumentService.js\";\n\n/**\n * Factory for creating the file document service. Use this if you want to\n * use the local file storage as underlying storage.\n * @internal\n */\nexport class FileDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {}\n\n\t/**\n\t * Creates the file document service if the path exists.\n\t *\n\t * @param fileURL - Path of directory containing ops/snapshots.\n\t * @returns file document service.\n\t */\n\tpublic async createDocumentService(\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\treturn new FileDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tthis.storage,\n\t\t\tthis.deltaStorage,\n\t\t\tthis.deltaConnection,\n\t\t);\n\t}\n\n\t// TODO: Issue-2109 Implement detach container api or put appropriate comment.\n\tpublic async createContainer(\n\t\tcreateNewSummary: ISummaryTree,\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\tthrow new Error(\"Not implemented\");\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/fileDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EACX,uBAAuB,EAEvB,aAAa,EACb,QAAQ,EAGR,MAAM,6CAA6C,CAAC;AAMrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AAIxF;;GAEG;AACH,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAK1D;;;GAGG;AACH,qBAAa,gBACZ,SAAQ,8BACR,YAAW,uBAAuB;IAKjC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAJ9B,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAQ;gBAG7B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,oBAAQ;IAKtC;;;OAGG;IAEU,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAkC/E;;;;OAIG;IAEU,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAmBzE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAU5D;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACtE,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACjD,KAAK,IAAI,IAAI,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,uBAAuB,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,8BAA8B,0CACpC,KAAK,KACT,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,sBAAsB,CAkGxD,CAAC;AAcH;;GAEG;AACH,eAAO,MAAM,kCAAkC,2CAnHrB,GAAG,EAAE,KAAK,sBAAsB,CAoHT,CAAC"}
1
+ {"version":3,"file":"fileDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/fileDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EACX,uBAAuB,EAEvB,aAAa,EACb,QAAQ,EAGR,MAAM,6CAA6C,CAAC;AAMrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AAIxF;;GAEG;AACH,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAK1D;;;GAGG;AACH,qBAAa,gBACZ,SAAQ,8BACR,YAAW,uBAAuB;IAKjC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAJ9B,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAQ;gBAG7B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,YAAA;IAKtC;;;OAGG;IAEU,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAkC/E;;;;OAIG;IAEU,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAmBzE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAU5D;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACtE,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACjD,KAAK,IAAI,IAAI,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,uBAAuB,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,8BAA8B,GAAI,KAAK,SAAS,iBAAiB,EAC7E,MAAM,KAAK,KACT,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,sBAAsB,CAkGxD,CAAC;AAcH;;GAEG;AACH,eAAO,MAAM,kCAAkC,2CAnHrB,GAAG,EAAE,KAAK,sBAAsB,CAoHT,CAAC"}
@@ -27,11 +27,13 @@ const FileStorageVersionTreeId = "FileStorageTreeId";
27
27
  * @internal
28
28
  */
29
29
  class FluidFetchReader extends internal_4.ReadDocumentStorageServiceBase {
30
+ path;
31
+ versionName;
32
+ docTree = null;
30
33
  constructor(path, versionName) {
31
34
  super();
32
35
  this.path = path;
33
36
  this.versionName = versionName;
34
- this.docTree = null;
35
37
  }
36
38
  /**
37
39
  * Read the file and returns the snapshot tree.
@@ -97,7 +99,7 @@ class FluidFetchReader extends internal_4.ReadDocumentStorageServiceBase {
97
99
  const fileName = `${this.path}/${this.versionName}/${sha}`;
98
100
  if (fs_1.default.existsSync(fileName)) {
99
101
  const data = fs_1.default.readFileSync(fileName);
100
- return data;
102
+ return (0, client_utils_1.Uint8ArrayToArrayBufferLike)(data);
101
103
  }
102
104
  }
103
105
  throw new Error(`Can't find blob ${sha}`);
@@ -108,11 +110,10 @@ exports.FluidFetchReader = FluidFetchReader;
108
110
  * @internal
109
111
  */
110
112
  const FileSnapshotWriterClassFactory = (Base) => class extends Base {
111
- constructor() {
112
- super(...arguments);
113
- // Note: if variable name has same name as in base class, it overrides it!
114
- this.blobsWriter = new Map();
115
- }
113
+ // Note: if variable name has same name as in base class, it overrides it!
114
+ blobsWriter = new Map();
115
+ latestWriterTree;
116
+ docId;
116
117
  reset() {
117
118
  this.blobsWriter = new Map();
118
119
  delete this.latestWriterTree;
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentStorageService.js","sourceRoot":"","sources":["../src/fileDocumentStorageService.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 fs from \"fs\";\n\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentStorageService,\n\tISummaryContext,\n\tISnapshotTree,\n\tIVersion,\n\tITree,\n\tIBlob,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { FileMode, TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tbuildSnapshotTree,\n\tconvertSummaryTreeToSnapshotITree,\n} from \"@fluidframework/driver-utils/internal\";\nimport type { IFileSnapshot } from \"@fluidframework/replay-driver/internal\";\nimport { ReadDocumentStorageServiceBase } from \"@fluidframework/replay-driver/internal\";\n\n// This ID is used by replay tool as Document Id.\n// We leverage it to figure out when container is asking for root document tree.\n/**\n * @internal\n */\nexport const FileStorageDocumentName = \"FileStorageDocId\"; // Some unique document name\n\n// Tree ID use to communicate between getVersions() & getSnapshotTree() that IVersion is ours.\nconst FileStorageVersionTreeId = \"FileStorageTreeId\";\n\n/**\n * Document storage service for the file driver.\n * @internal\n */\nexport class FluidFetchReader\n\textends ReadDocumentStorageServiceBase\n\timplements IDocumentStorageService\n{\n\tprotected docTree: ISnapshotTree | null = null;\n\n\tconstructor(\n\t\tprivate readonly path: string,\n\t\tprivate readonly versionName?: string,\n\t) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Read the file and returns the snapshot tree.\n\t * @param version - The version contains the path of the file which contains the snapshot tree.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\tassert(version !== null, 0x092 /* \"version input for reading snapshot tree is null!\" */);\n\t\tassert(\n\t\t\t!version || version.treeId === FileStorageVersionTreeId,\n\t\t\t0x093 /* \"invalid version input for reading snapshot tree!\" */,\n\t\t);\n\n\t\tlet filename: string;\n\t\tlet rootTree = false;\n\t\tif (!version || version.id === \"latest\") {\n\t\t\tif (this.docTree) {\n\t\t\t\treturn this.docTree;\n\t\t\t}\n\t\t\tif (this.versionName === undefined) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\trootTree = true;\n\t\t\tfilename = `${this.path}/${this.versionName}/tree.json`;\n\t\t} else {\n\t\t\tfilename = `${this.path}/${this.versionName}/${version.id}.json`;\n\t\t}\n\n\t\tif (!fs.existsSync(filename)) {\n\t\t\tthrow new Error(`Can't find file ${filename}`);\n\t\t}\n\t\tconst data = fs.readFileSync(filename);\n\t\tconst tree = JSON.parse(data.toString(\"utf-8\"));\n\t\tif (rootTree) {\n\t\t\tthis.docTree = tree;\n\t\t}\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn tree;\n\t}\n\n\t/**\n\t * Gets the path of the snapshot tree to be read.\n\t * @param versionId - version ID.\n\t * @param count - Number of versions to be returned.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\tif (versionId === FileStorageDocumentName || versionId === null) {\n\t\t\tif (this.docTree !== null || this.versionName !== undefined) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\t\t\t// Started with ops - return empty set.\n\t\t\treturn [];\n\t\t} else if (this.versionName !== undefined) {\n\t\t\tassert(!!this.docTree, 0x094 /* \"Missing snapshot tree!\" */);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: versionId,\n\t\t\t\t\ttreeId: FileStorageVersionTreeId,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\tthrow new Error(`Unknown version: ${versionId}`);\n\t}\n\n\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\tif (this.versionName !== undefined) {\n\t\t\tconst fileName = `${this.path}/${this.versionName}/${sha}`;\n\t\t\tif (fs.existsSync(fileName)) {\n\t\t\t\tconst data = fs.readFileSync(fileName);\n\t\t\t\treturn data;\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`Can't find blob ${sha}`);\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ISnapshotWriterStorage extends IDocumentStorageService {\n\tonSnapshotHandler(snapshot: IFileSnapshot): void;\n\treset(): void;\n}\n\n/**\n * Constructor type for creating {@link @fluidframework/driver-definitions#IDocumentStorageService} instances.\n *\n * @internal\n */\nexport type ReaderConstructor = new (...args: any[]) => IDocumentStorageService;\n\n/**\n * @internal\n */\nexport const FileSnapshotWriterClassFactory = <TBase extends ReaderConstructor>(\n\tBase: TBase,\n): TBase & (new (...args: any[]) => ISnapshotWriterStorage) =>\n\tclass extends Base implements ISnapshotWriterStorage {\n\t\t// Note: if variable name has same name as in base class, it overrides it!\n\t\tpublic blobsWriter = new Map<string, ArrayBufferLike>();\n\t\tpublic latestWriterTree?: ISnapshotTree;\n\t\tpublic docId?: string;\n\n\t\tpublic reset(): void {\n\t\t\tthis.blobsWriter = new Map<string, ArrayBufferLike>();\n\t\t\tdelete this.latestWriterTree;\n\t\t\tdelete this.docId;\n\t\t}\n\n\t\tpublic onSnapshotHandler(snapshot: IFileSnapshot): void {\n\t\t\tthrow new Error(\"onSnapshotHandler is not setup! Please provide your handler!\");\n\t\t}\n\n\t\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\t\tconst blob = this.blobsWriter.get(sha);\n\t\t\tif (blob !== undefined) {\n\t\t\t\treturn blob;\n\t\t\t}\n\t\t\treturn super.readBlob(sha);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\t\t// If we already saved document, that means we are getting here because of snapshot generation.\n\t\t\t// Not returning tree ensures that IContainerRuntime.snapshot() would regenerate subtrees for\n\t\t\t// each unchanged data store.\n\t\t\t// If we want to change that, we would need to capture docId on first call and return this.latestWriterTree\n\t\t\t// when latest is requested.\n\t\t\tif (this.latestWriterTree && (this.docId === versionId || versionId === null)) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\n\t\t\tif (this.docId === undefined && versionId !== null) {\n\t\t\t\tthis.docId = versionId;\n\t\t\t}\n\n\t\t\treturn super.getVersions(versionId, count);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\t\tif (this.latestWriterTree && (!version || version.id === \"latest\")) {\n\t\t\t\treturn this.latestWriterTree;\n\t\t\t}\n\t\t\treturn super.getSnapshotTree(version);\n\t\t}\n\n\t\tpublic async uploadSummaryWithContext(\n\t\t\tsummary: ISummaryTree,\n\t\t\tcontext: ISummaryContext,\n\t\t): Promise<string> {\n\t\t\tconst tree = convertSummaryTreeToSnapshotITree(summary);\n\n\t\t\t// Remove tree IDs for easier comparison of snapshots\n\t\t\tdelete tree.id;\n\t\t\tremoveNullTreeIds(tree);\n\n\t\t\tthis.latestWriterTree = buildSnapshotTree(tree.entries, this.blobsWriter);\n\n\t\t\tconst fileSnapshot: IFileSnapshot = { tree, commits: {} };\n\t\t\tthis.onSnapshotHandler(fileSnapshot);\n\t\t\treturn \"testHandleId\";\n\t\t}\n\n\t\tpublic async buildTree(snapshotTree: ISnapshotTree): Promise<ITree> {\n\t\t\tconst tree: ITree = { entries: [] };\n\n\t\t\tfor (const [subTreeId, subTreeValue] of Object.entries(snapshotTree.trees)) {\n\t\t\t\tconst subTree = await this.buildTree(subTreeValue);\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.Directory,\n\t\t\t\t\tpath: subTreeId,\n\t\t\t\t\ttype: TreeEntry.Tree,\n\t\t\t\t\tvalue: subTree,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (const [blobName, blobValue] of Object.keys(snapshotTree.blobs)) {\n\t\t\t\tconst buffer = await this.readBlob(blobValue);\n\t\t\t\tconst contents = bufferToString(buffer, \"utf8\");\n\t\t\t\tconst blob: IBlob = {\n\t\t\t\t\tcontents,\n\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t};\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.File,\n\t\t\t\t\tpath: blobName,\n\t\t\t\t\ttype: TreeEntry.Blob,\n\t\t\t\t\tvalue: blob,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn tree;\n\t\t}\n\t};\n\nfunction removeNullTreeIds(tree: ITree): void {\n\tfor (const node of tree.entries) {\n\t\tif (node.type === TreeEntry.Tree) {\n\t\t\tremoveNullTreeIds(node.value);\n\t\t}\n\t}\n\tassert(\n\t\ttree.id === undefined || tree.id === null,\n\t\t0x096 /* \"Trying to remove valid tree IDs in removeNullTreeIds()!\" */,\n\t);\n\tdelete tree.id;\n}\n/**\n * @internal\n */\nexport const FluidFetchReaderFileSnapshotWriter =\n\tFileSnapshotWriterClassFactory(FluidFetchReader);\n"]}
1
+ {"version":3,"file":"fileDocumentStorageService.js","sourceRoot":"","sources":["../src/fileDocumentStorageService.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 fs from \"fs\";\n\nimport { bufferToString, Uint8ArrayToArrayBufferLike } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentStorageService,\n\tISummaryContext,\n\tISnapshotTree,\n\tIVersion,\n\tITree,\n\tIBlob,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { FileMode, TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tbuildSnapshotTree,\n\tconvertSummaryTreeToSnapshotITree,\n} from \"@fluidframework/driver-utils/internal\";\nimport type { IFileSnapshot } from \"@fluidframework/replay-driver/internal\";\nimport { ReadDocumentStorageServiceBase } from \"@fluidframework/replay-driver/internal\";\n\n// This ID is used by replay tool as Document Id.\n// We leverage it to figure out when container is asking for root document tree.\n/**\n * @internal\n */\nexport const FileStorageDocumentName = \"FileStorageDocId\"; // Some unique document name\n\n// Tree ID use to communicate between getVersions() & getSnapshotTree() that IVersion is ours.\nconst FileStorageVersionTreeId = \"FileStorageTreeId\";\n\n/**\n * Document storage service for the file driver.\n * @internal\n */\nexport class FluidFetchReader\n\textends ReadDocumentStorageServiceBase\n\timplements IDocumentStorageService\n{\n\tprotected docTree: ISnapshotTree | null = null;\n\n\tconstructor(\n\t\tprivate readonly path: string,\n\t\tprivate readonly versionName?: string,\n\t) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Read the file and returns the snapshot tree.\n\t * @param version - The version contains the path of the file which contains the snapshot tree.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\tassert(version !== null, 0x092 /* \"version input for reading snapshot tree is null!\" */);\n\t\tassert(\n\t\t\t!version || version.treeId === FileStorageVersionTreeId,\n\t\t\t0x093 /* \"invalid version input for reading snapshot tree!\" */,\n\t\t);\n\n\t\tlet filename: string;\n\t\tlet rootTree = false;\n\t\tif (!version || version.id === \"latest\") {\n\t\t\tif (this.docTree) {\n\t\t\t\treturn this.docTree;\n\t\t\t}\n\t\t\tif (this.versionName === undefined) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\trootTree = true;\n\t\t\tfilename = `${this.path}/${this.versionName}/tree.json`;\n\t\t} else {\n\t\t\tfilename = `${this.path}/${this.versionName}/${version.id}.json`;\n\t\t}\n\n\t\tif (!fs.existsSync(filename)) {\n\t\t\tthrow new Error(`Can't find file ${filename}`);\n\t\t}\n\t\tconst data = fs.readFileSync(filename);\n\t\tconst tree = JSON.parse(data.toString(\"utf-8\"));\n\t\tif (rootTree) {\n\t\t\tthis.docTree = tree;\n\t\t}\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn tree;\n\t}\n\n\t/**\n\t * Gets the path of the snapshot tree to be read.\n\t * @param versionId - version ID.\n\t * @param count - Number of versions to be returned.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\tif (versionId === FileStorageDocumentName || versionId === null) {\n\t\t\tif (this.docTree !== null || this.versionName !== undefined) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\t\t\t// Started with ops - return empty set.\n\t\t\treturn [];\n\t\t} else if (this.versionName !== undefined) {\n\t\t\tassert(!!this.docTree, 0x094 /* \"Missing snapshot tree!\" */);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: versionId,\n\t\t\t\t\ttreeId: FileStorageVersionTreeId,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\tthrow new Error(`Unknown version: ${versionId}`);\n\t}\n\n\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\tif (this.versionName !== undefined) {\n\t\t\tconst fileName = `${this.path}/${this.versionName}/${sha}`;\n\t\t\tif (fs.existsSync(fileName)) {\n\t\t\t\tconst data = fs.readFileSync(fileName);\n\t\t\t\treturn Uint8ArrayToArrayBufferLike(data);\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`Can't find blob ${sha}`);\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ISnapshotWriterStorage extends IDocumentStorageService {\n\tonSnapshotHandler(snapshot: IFileSnapshot): void;\n\treset(): void;\n}\n\n/**\n * Constructor type for creating {@link @fluidframework/driver-definitions#IDocumentStorageService} instances.\n *\n * @internal\n */\nexport type ReaderConstructor = new (...args: any[]) => IDocumentStorageService;\n\n/**\n * @internal\n */\nexport const FileSnapshotWriterClassFactory = <TBase extends ReaderConstructor>(\n\tBase: TBase,\n): TBase & (new (...args: any[]) => ISnapshotWriterStorage) =>\n\tclass extends Base implements ISnapshotWriterStorage {\n\t\t// Note: if variable name has same name as in base class, it overrides it!\n\t\tpublic blobsWriter = new Map<string, ArrayBufferLike>();\n\t\tpublic latestWriterTree?: ISnapshotTree;\n\t\tpublic docId?: string;\n\n\t\tpublic reset(): void {\n\t\t\tthis.blobsWriter = new Map<string, ArrayBufferLike>();\n\t\t\tdelete this.latestWriterTree;\n\t\t\tdelete this.docId;\n\t\t}\n\n\t\tpublic onSnapshotHandler(snapshot: IFileSnapshot): void {\n\t\t\tthrow new Error(\"onSnapshotHandler is not setup! Please provide your handler!\");\n\t\t}\n\n\t\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\t\tconst blob = this.blobsWriter.get(sha);\n\t\t\tif (blob !== undefined) {\n\t\t\t\treturn blob;\n\t\t\t}\n\t\t\treturn super.readBlob(sha);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\t\t// If we already saved document, that means we are getting here because of snapshot generation.\n\t\t\t// Not returning tree ensures that IContainerRuntime.snapshot() would regenerate subtrees for\n\t\t\t// each unchanged data store.\n\t\t\t// If we want to change that, we would need to capture docId on first call and return this.latestWriterTree\n\t\t\t// when latest is requested.\n\t\t\tif (this.latestWriterTree && (this.docId === versionId || versionId === null)) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\n\t\t\tif (this.docId === undefined && versionId !== null) {\n\t\t\t\tthis.docId = versionId;\n\t\t\t}\n\n\t\t\treturn super.getVersions(versionId, count);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\t\tif (this.latestWriterTree && (!version || version.id === \"latest\")) {\n\t\t\t\treturn this.latestWriterTree;\n\t\t\t}\n\t\t\treturn super.getSnapshotTree(version);\n\t\t}\n\n\t\tpublic async uploadSummaryWithContext(\n\t\t\tsummary: ISummaryTree,\n\t\t\tcontext: ISummaryContext,\n\t\t): Promise<string> {\n\t\t\tconst tree = convertSummaryTreeToSnapshotITree(summary);\n\n\t\t\t// Remove tree IDs for easier comparison of snapshots\n\t\t\tdelete tree.id;\n\t\t\tremoveNullTreeIds(tree);\n\n\t\t\tthis.latestWriterTree = buildSnapshotTree(tree.entries, this.blobsWriter);\n\n\t\t\tconst fileSnapshot: IFileSnapshot = { tree, commits: {} };\n\t\t\tthis.onSnapshotHandler(fileSnapshot);\n\t\t\treturn \"testHandleId\";\n\t\t}\n\n\t\tpublic async buildTree(snapshotTree: ISnapshotTree): Promise<ITree> {\n\t\t\tconst tree: ITree = { entries: [] };\n\n\t\t\tfor (const [subTreeId, subTreeValue] of Object.entries(snapshotTree.trees)) {\n\t\t\t\tconst subTree = await this.buildTree(subTreeValue);\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.Directory,\n\t\t\t\t\tpath: subTreeId,\n\t\t\t\t\ttype: TreeEntry.Tree,\n\t\t\t\t\tvalue: subTree,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (const [blobName, blobValue] of Object.keys(snapshotTree.blobs)) {\n\t\t\t\tconst buffer = await this.readBlob(blobValue);\n\t\t\t\tconst contents = bufferToString(buffer, \"utf8\");\n\t\t\t\tconst blob: IBlob = {\n\t\t\t\t\tcontents,\n\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t};\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.File,\n\t\t\t\t\tpath: blobName,\n\t\t\t\t\ttype: TreeEntry.Blob,\n\t\t\t\t\tvalue: blob,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn tree;\n\t\t}\n\t};\n\nfunction removeNullTreeIds(tree: ITree): void {\n\tfor (const node of tree.entries) {\n\t\tif (node.type === TreeEntry.Tree) {\n\t\t\tremoveNullTreeIds(node.value);\n\t\t}\n\t}\n\tassert(\n\t\ttree.id === undefined || tree.id === null,\n\t\t0x096 /* \"Trying to remove valid tree IDs in removeNullTreeIds()!\" */,\n\t);\n\tdelete tree.id;\n}\n/**\n * @internal\n */\nexport const FluidFetchReaderFileSnapshotWriter =\n\tFileSnapshotWriterClassFactory(FluidFetchReader);\n"]}
@@ -10,9 +10,11 @@ import { emptyMessageStream } from "@fluidframework/driver-utils/internal";
10
10
  * @internal
11
11
  */
12
12
  export class FileDeltaStorageService {
13
+ path;
14
+ messages;
15
+ lastOps = [];
13
16
  constructor(path) {
14
17
  this.path = path;
15
- this.lastOps = [];
16
18
  this.messages = [];
17
19
  let counter = 0;
18
20
  while (true) {
@@ -1 +1 @@
1
- {"version":3,"file":"fileDeltaStorageService.js","sourceRoot":"","sources":["../src/fileDeltaStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAM7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IAInC,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAFjC,YAAO,GAAgC,EAAE,CAAC;QAGjD,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,aAAa,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC;YAC9E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,YAAY,CAAC,CAAC;gBAC/C,CAAC;gBACD,MAAM;YACP,CAAC;YACD,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACzE,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IAEM,aAAa,CACnB,IAAY,EACZ,EAAsB,EACtB,WAAyB,EACzB,UAAoB;QAEpB,OAAO,kBAAkB,CAAC;IAC3B,CAAC;IAED,IAAW,GAAG;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACI,gBAAgB,CAAC,IAAY,EAAE,EAAU;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;QAE/D,IAAI,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,MAAM,IAAI,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;YAC3E,OAAO,EAAE,CAAC;QACX,CAAC;QAED,mDAAmD;QACnD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC,OAAO,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,CACL,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAC/C,KAAK,CAAC,kEAAkE,CACxE,CAAC;QACF,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport fs from \"fs\";\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type {\n\tIDocumentDeltaStorageService,\n\tIStream,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { emptyMessageStream } from \"@fluidframework/driver-utils/internal\";\n\n/**\n * Provides access to the underlying delta storage on the local file storage for file driver.\n * @internal\n */\nexport class FileDeltaStorageService implements IDocumentDeltaStorageService {\n\tprivate readonly messages: ISequencedDocumentMessage[];\n\tprivate lastOps: ISequencedDocumentMessage[] = [];\n\n\tconstructor(private readonly path: string) {\n\t\tthis.messages = [];\n\t\tlet counter = 0;\n\t\twhile (true) {\n\t\t\tconst filename = `${this.path}//messages${counter === 0 ? \"\" : counter}.json`;\n\t\t\tif (!fs.existsSync(filename)) {\n\t\t\t\tif (counter === 0) {\n\t\t\t\t\tthrow new Error(`file ${filename} not found`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst data = fs.readFileSync(filename);\n\t\t\tthis.messages = this.messages.concat(JSON.parse(data.toString(\"utf-8\")));\n\t\t\tcounter++;\n\t\t}\n\t}\n\n\tpublic fetchMessages(\n\t\tfrom: number,\n\t\tto: number | undefined,\n\t\tabortSignal?: AbortSignal,\n\t\tcachedOnly?: boolean,\n\t): IStream<ISequencedDocumentMessage[]> {\n\t\treturn emptyMessageStream;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.messages;\n\t}\n\n\t/**\n\t * Retrieve ops within the exclusive sequence number range.\n\t *\n\t * @param from - First op to be fetched.\n\t * @param to - Last op to be fetched. This is exclusive.\n\t */\n\tpublic getFromWebSocket(from: number, to: number): ISequencedDocumentMessage[] {\n\t\tconst readFrom = Math.max(from, 0); // Inclusive\n\t\tconst readTo = Math.min(to, this.messages.length); // Exclusive\n\n\t\tif (readFrom >= this.messages.length || readTo <= 0 || readFrom >= readTo) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Optimizations for multiple readers (replay tool)\n\t\tif (this.lastOps.length > 0 && this.lastOps[0].sequenceNumber === readFrom + 1) {\n\t\t\treturn this.lastOps;\n\t\t}\n\t\tthis.lastOps = this.messages.slice(readFrom, readTo);\n\t\tassert(\n\t\t\tthis.lastOps[0].sequenceNumber === readFrom + 1,\n\t\t\t0x091 /* \"Retrieved ops' first sequence number has unexpected value!\" */,\n\t\t);\n\t\treturn this.lastOps;\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDeltaStorageService.js","sourceRoot":"","sources":["../src/fileDeltaStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAM7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IAIN;IAHZ,QAAQ,CAA8B;IAC/C,OAAO,GAAgC,EAAE,CAAC;IAElD,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QACxC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,aAAa,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC;YAC9E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,YAAY,CAAC,CAAC;gBAC/C,CAAC;gBACD,MAAM;YACP,CAAC;YACD,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACzE,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IAEM,aAAa,CACnB,IAAY,EACZ,EAAsB,EACtB,WAAyB,EACzB,UAAoB;QAEpB,OAAO,kBAAkB,CAAC;IAC3B,CAAC;IAED,IAAW,GAAG;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACI,gBAAgB,CAAC,IAAY,EAAE,EAAU;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;QAE/D,IAAI,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,MAAM,IAAI,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;YAC3E,OAAO,EAAE,CAAC;QACX,CAAC;QAED,mDAAmD;QACnD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC,OAAO,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,CACL,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,GAAG,CAAC,EAC/C,KAAK,CAAC,kEAAkE,CACxE,CAAC;QACF,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport fs from \"fs\";\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type {\n\tIDocumentDeltaStorageService,\n\tIStream,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { emptyMessageStream } from \"@fluidframework/driver-utils/internal\";\n\n/**\n * Provides access to the underlying delta storage on the local file storage for file driver.\n * @internal\n */\nexport class FileDeltaStorageService implements IDocumentDeltaStorageService {\n\tprivate readonly messages: ISequencedDocumentMessage[];\n\tprivate lastOps: ISequencedDocumentMessage[] = [];\n\n\tconstructor(private readonly path: string) {\n\t\tthis.messages = [];\n\t\tlet counter = 0;\n\t\twhile (true) {\n\t\t\tconst filename = `${this.path}//messages${counter === 0 ? \"\" : counter}.json`;\n\t\t\tif (!fs.existsSync(filename)) {\n\t\t\t\tif (counter === 0) {\n\t\t\t\t\tthrow new Error(`file ${filename} not found`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst data = fs.readFileSync(filename);\n\t\t\tthis.messages = this.messages.concat(JSON.parse(data.toString(\"utf-8\")));\n\t\t\tcounter++;\n\t\t}\n\t}\n\n\tpublic fetchMessages(\n\t\tfrom: number,\n\t\tto: number | undefined,\n\t\tabortSignal?: AbortSignal,\n\t\tcachedOnly?: boolean,\n\t): IStream<ISequencedDocumentMessage[]> {\n\t\treturn emptyMessageStream;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.messages;\n\t}\n\n\t/**\n\t * Retrieve ops within the exclusive sequence number range.\n\t *\n\t * @param from - First op to be fetched.\n\t * @param to - Last op to be fetched. This is exclusive.\n\t */\n\tpublic getFromWebSocket(from: number, to: number): ISequencedDocumentMessage[] {\n\t\tconst readFrom = Math.max(from, 0); // Inclusive\n\t\tconst readTo = Math.min(to, this.messages.length); // Exclusive\n\n\t\tif (readFrom >= this.messages.length || readTo <= 0 || readFrom >= readTo) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Optimizations for multiple readers (replay tool)\n\t\tif (this.lastOps.length > 0 && this.lastOps[0].sequenceNumber === readFrom + 1) {\n\t\t\treturn this.lastOps;\n\t\t}\n\t\tthis.lastOps = this.messages.slice(readFrom, readTo);\n\t\tassert(\n\t\t\tthis.lastOps[0].sequenceNumber === readFrom + 1,\n\t\t\t0x091 /* \"Retrieved ops' first sequence number has unexpected value!\" */,\n\t\t);\n\t\treturn this.lastOps;\n\t}\n}\n"]}
@@ -25,10 +25,12 @@ const Claims = {
25
25
  * @internal
26
26
  */
27
27
  export class Replayer {
28
+ deltaConnection;
29
+ documentStorageService;
30
+ currentReplayOp = 0;
28
31
  constructor(deltaConnection, documentStorageService) {
29
32
  this.deltaConnection = deltaConnection;
30
33
  this.documentStorageService = documentStorageService;
31
- this.currentReplayOp = 0;
32
34
  }
33
35
  get currentReplayedOp() {
34
36
  return this.currentReplayOp;
@@ -80,6 +82,7 @@ export class Replayer {
80
82
  * @internal
81
83
  */
82
84
  export class ReplayFileDeltaConnection extends TypedEventEmitter {
85
+ details;
83
86
  /**
84
87
  * Mimic the delta connection to replay ops on it.
85
88
  *
@@ -108,11 +111,11 @@ export class ReplayFileDeltaConnection extends TypedEventEmitter {
108
111
  const deltaConnection = new ReplayFileDeltaConnection(connection, documentDeltaStorageService);
109
112
  return deltaConnection;
110
113
  }
114
+ maxMessageSize = ReplayMaxMessageSize;
115
+ replayer;
111
116
  constructor(details, documentDeltaStorageService) {
112
117
  super();
113
118
  this.details = details;
114
- this.maxMessageSize = ReplayMaxMessageSize;
115
- this._disposed = false;
116
119
  this.replayer = new Replayer(this, documentDeltaStorageService);
117
120
  }
118
121
  getReplayer() {
@@ -152,6 +155,7 @@ export class ReplayFileDeltaConnection extends TypedEventEmitter {
152
155
  }
153
156
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
154
157
  async submitSignal(message) { }
158
+ _disposed = false;
155
159
  get disposed() {
156
160
  return this._disposed;
157
161
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/fileDocumentDeltaConnection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport type { ConnectionMode } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaConnectionEvents,\n\tIClientConfiguration,\n\tIConnected,\n\tIDocumentMessage,\n\tISignalClient,\n\tITokenClaims,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { ScopeType } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\nconst MaxBatchDeltas = 2000;\n\n// Since the replay service never actually sends messages the size below is arbitrary\nconst ReplayMaxMessageSize = 16 * 1024;\n\nconst fileProtocolVersion = \"^0.1.0\";\n\nconst replayDocumentId = \"replayDocId\";\n\nconst Claims: ITokenClaims = {\n\tdocumentId: replayDocumentId,\n\tscopes: [ScopeType.DocRead],\n\ttenantId: \"\",\n\tuser: {\n\t\tid: \"\",\n\t},\n\tiat: Math.round(Date.now() / 1000),\n\texp: Math.round(Date.now() / 1000) + 60 * 60, // 1 hour expiration\n\tver: \"1.0\",\n};\n\n/**\n * Replay service used to play ops using the delta connection.\n * @internal\n */\nexport class Replayer {\n\tprivate currentReplayOp = 0;\n\n\tconstructor(\n\t\tprivate readonly deltaConnection: ReplayFileDeltaConnection,\n\t\tprivate readonly documentStorageService: FileDeltaStorageService,\n\t) {}\n\n\tpublic get currentReplayedOp(): number {\n\t\treturn this.currentReplayOp;\n\t}\n\n\tpublic set currentReplayedOp(op: number) {\n\t\tthis.currentReplayOp = op;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.documentStorageService.ops;\n\t}\n\n\t/**\n\t * Replay the ops upto a certain number.\n\t * @param replayTo - The last op number to be replayed.\n\t */\n\tpublic replay(replayTo: number): number {\n\t\tlet totalReplayedOps = 0;\n\t\tlet done: boolean;\n\t\tdo {\n\t\t\tconst fetchToBatch = this.currentReplayOp + MaxBatchDeltas;\n\t\t\tconst fetchTo = Math.min(fetchToBatch, replayTo);\n\n\t\t\tconst fetchedOps = this.documentStorageService.getFromWebSocket(\n\t\t\t\tthis.currentReplayOp,\n\t\t\t\tfetchTo,\n\t\t\t);\n\n\t\t\tif (fetchedOps.length <= 0) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tthis.emit(fetchedOps);\n\t\t\t\ttotalReplayedOps += fetchedOps.length;\n\t\t\t\tthis.currentReplayOp += fetchedOps.length;\n\t\t\t\tdone = this.isDoneFetch(replayTo);\n\t\t\t}\n\t\t} while (!done);\n\t\treturn totalReplayedOps;\n\t}\n\n\tprivate isDoneFetch(replayTo: number): boolean {\n\t\tif (replayTo >= 0) {\n\t\t\treturn this.currentReplayOp >= replayTo;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate emit(ops: ISequencedDocumentMessage[]): void {\n\t\t// Note: do not clone messages here!\n\t\t// If Replay Tool fails due to one container patching message in-place,\n\t\t// then same thing can happen in shipping product due to\n\t\t// socket reuse in ODSP between main and summarizer containers.\n\t\tthis.deltaConnection.emit(\"op\", replayDocumentId, ops);\n\t}\n}\n\n/**\n * @internal\n */\nexport class ReplayFileDeltaConnection\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\t/**\n\t * Mimic the delta connection to replay ops on it.\n\t *\n\t * @param documentDeltaStorageService - The delta storage service to get ops from.\n\t * @returns Document delta connection.\n\t */\n\tpublic static async create(\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t): Promise<ReplayFileDeltaConnection> {\n\t\tconst mode: ConnectionMode = \"read\";\n\t\tconst connection = {\n\t\t\tclaims: Claims,\n\t\t\tclientId: \"PseudoClientId\",\n\t\t\texisting: true,\n\t\t\tinitialMessages: [],\n\t\t\tinitialSignals: [],\n\t\t\tinitialClients: [],\n\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\tmode,\n\t\t\tserviceConfiguration: {\n\t\t\t\tblockSize: 64436,\n\t\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\t},\n\t\t\tsupportedVersions: [fileProtocolVersion],\n\t\t\tuser: null,\n\t\t\tversion: fileProtocolVersion,\n\t\t};\n\t\tconst deltaConnection = new ReplayFileDeltaConnection(\n\t\t\tconnection,\n\t\t\tdocumentDeltaStorageService,\n\t\t);\n\t\treturn deltaConnection;\n\t}\n\n\tpublic readonly maxMessageSize = ReplayMaxMessageSize;\n\tprivate readonly replayer: Replayer;\n\n\tpublic constructor(\n\t\tpublic details: IConnected,\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t) {\n\t\tsuper();\n\t\tthis.replayer = new Replayer(this, documentDeltaStorageService);\n\t}\n\n\tpublic getReplayer(): Replayer {\n\t\treturn this.replayer;\n\t}\n\n\tpublic get clientId(): string {\n\t\treturn this.details.clientId;\n\t}\n\n\tpublic get mode(): ConnectionMode {\n\t\treturn this.details.mode;\n\t}\n\n\tpublic get claims(): ITokenClaims {\n\t\treturn this.details.claims;\n\t}\n\n\tpublic get existing(): boolean {\n\t\treturn this.details.existing;\n\t}\n\n\tpublic get version(): string {\n\t\treturn this.details.version;\n\t}\n\n\tpublic get initialMessages(): ISequencedDocumentMessage[] {\n\t\treturn this.details.initialMessages;\n\t}\n\n\tpublic get initialSignals(): ISignalMessage[] {\n\t\treturn this.details.initialSignals;\n\t}\n\n\tpublic get initialClients(): ISignalClient[] {\n\t\treturn this.details.initialClients;\n\t}\n\n\tpublic get serviceConfiguration(): IClientConfiguration {\n\t\treturn this.details.serviceConfiguration;\n\t}\n\n\tpublic submit(documentMessages: IDocumentMessage[]): void {\n\t\t// ReplayFileDeltaConnection.submit() can't be called - client never sees its own join on,\n\t\t// and thus can never move to sending ops.\n\t\tthrow new Error(\"ReplayFileDeltaConnection.submit() can't be called\");\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\tpublic async submitSignal(message: any): Promise<void> {}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/fileDocumentDeltaConnection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport type { ConnectionMode } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaConnectionEvents,\n\tIClientConfiguration,\n\tIConnected,\n\tIDocumentMessage,\n\tISignalClient,\n\tITokenClaims,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { ScopeType } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\nconst MaxBatchDeltas = 2000;\n\n// Since the replay service never actually sends messages the size below is arbitrary\nconst ReplayMaxMessageSize = 16 * 1024;\n\nconst fileProtocolVersion = \"^0.1.0\";\n\nconst replayDocumentId = \"replayDocId\";\n\nconst Claims: ITokenClaims = {\n\tdocumentId: replayDocumentId,\n\tscopes: [ScopeType.DocRead],\n\ttenantId: \"\",\n\tuser: {\n\t\tid: \"\",\n\t},\n\tiat: Math.round(Date.now() / 1000),\n\texp: Math.round(Date.now() / 1000) + 60 * 60, // 1 hour expiration\n\tver: \"1.0\",\n};\n\n/**\n * Replay service used to play ops using the delta connection.\n * @internal\n */\nexport class Replayer {\n\tprivate currentReplayOp = 0;\n\n\tconstructor(\n\t\tprivate readonly deltaConnection: ReplayFileDeltaConnection,\n\t\tprivate readonly documentStorageService: FileDeltaStorageService,\n\t) {}\n\n\tpublic get currentReplayedOp(): number {\n\t\treturn this.currentReplayOp;\n\t}\n\n\tpublic set currentReplayedOp(op: number) {\n\t\tthis.currentReplayOp = op;\n\t}\n\n\tpublic get ops(): readonly Readonly<ISequencedDocumentMessage>[] {\n\t\treturn this.documentStorageService.ops;\n\t}\n\n\t/**\n\t * Replay the ops upto a certain number.\n\t * @param replayTo - The last op number to be replayed.\n\t */\n\tpublic replay(replayTo: number): number {\n\t\tlet totalReplayedOps = 0;\n\t\tlet done: boolean;\n\t\tdo {\n\t\t\tconst fetchToBatch = this.currentReplayOp + MaxBatchDeltas;\n\t\t\tconst fetchTo = Math.min(fetchToBatch, replayTo);\n\n\t\t\tconst fetchedOps = this.documentStorageService.getFromWebSocket(\n\t\t\t\tthis.currentReplayOp,\n\t\t\t\tfetchTo,\n\t\t\t);\n\n\t\t\tif (fetchedOps.length <= 0) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tthis.emit(fetchedOps);\n\t\t\t\ttotalReplayedOps += fetchedOps.length;\n\t\t\t\tthis.currentReplayOp += fetchedOps.length;\n\t\t\t\tdone = this.isDoneFetch(replayTo);\n\t\t\t}\n\t\t} while (!done);\n\t\treturn totalReplayedOps;\n\t}\n\n\tprivate isDoneFetch(replayTo: number): boolean {\n\t\tif (replayTo >= 0) {\n\t\t\treturn this.currentReplayOp >= replayTo;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate emit(ops: ISequencedDocumentMessage[]): void {\n\t\t// Note: do not clone messages here!\n\t\t// If Replay Tool fails due to one container patching message in-place,\n\t\t// then same thing can happen in shipping product due to\n\t\t// socket reuse in ODSP between main and summarizer containers.\n\t\tthis.deltaConnection.emit(\"op\", replayDocumentId, ops);\n\t}\n}\n\n/**\n * @internal\n */\nexport class ReplayFileDeltaConnection\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\t/**\n\t * Mimic the delta connection to replay ops on it.\n\t *\n\t * @param documentDeltaStorageService - The delta storage service to get ops from.\n\t * @returns Document delta connection.\n\t */\n\tpublic static async create(\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t): Promise<ReplayFileDeltaConnection> {\n\t\tconst mode: ConnectionMode = \"read\";\n\t\tconst connection = {\n\t\t\tclaims: Claims,\n\t\t\tclientId: \"PseudoClientId\",\n\t\t\texisting: true,\n\t\t\tinitialMessages: [],\n\t\t\tinitialSignals: [],\n\t\t\tinitialClients: [],\n\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\tmode,\n\t\t\tserviceConfiguration: {\n\t\t\t\tblockSize: 64436,\n\t\t\t\tmaxMessageSize: ReplayMaxMessageSize,\n\t\t\t},\n\t\t\tsupportedVersions: [fileProtocolVersion],\n\t\t\tuser: null,\n\t\t\tversion: fileProtocolVersion,\n\t\t};\n\t\tconst deltaConnection = new ReplayFileDeltaConnection(\n\t\t\tconnection,\n\t\t\tdocumentDeltaStorageService,\n\t\t);\n\t\treturn deltaConnection;\n\t}\n\n\tpublic readonly maxMessageSize = ReplayMaxMessageSize;\n\tprivate readonly replayer: Replayer;\n\n\tpublic constructor(\n\t\tpublic details: IConnected,\n\t\tdocumentDeltaStorageService: FileDeltaStorageService,\n\t) {\n\t\tsuper();\n\t\tthis.replayer = new Replayer(this, documentDeltaStorageService);\n\t}\n\n\tpublic getReplayer(): Replayer {\n\t\treturn this.replayer;\n\t}\n\n\tpublic get clientId(): string {\n\t\treturn this.details.clientId;\n\t}\n\n\tpublic get mode(): ConnectionMode {\n\t\treturn this.details.mode;\n\t}\n\n\tpublic get claims(): ITokenClaims {\n\t\treturn this.details.claims;\n\t}\n\n\tpublic get existing(): boolean {\n\t\treturn this.details.existing;\n\t}\n\n\tpublic get version(): string {\n\t\treturn this.details.version;\n\t}\n\n\tpublic get initialMessages(): ISequencedDocumentMessage[] {\n\t\treturn this.details.initialMessages;\n\t}\n\n\tpublic get initialSignals(): ISignalMessage[] {\n\t\treturn this.details.initialSignals;\n\t}\n\n\tpublic get initialClients(): ISignalClient[] {\n\t\treturn this.details.initialClients;\n\t}\n\n\tpublic get serviceConfiguration(): IClientConfiguration {\n\t\treturn this.details.serviceConfiguration;\n\t}\n\n\tpublic submit(documentMessages: IDocumentMessage[]): void {\n\t\t// ReplayFileDeltaConnection.submit() can't be called - client never sees its own join on,\n\t\t// and thus can never move to sending ops.\n\t\tthrow new Error(\"ReplayFileDeltaConnection.submit() can't be called\");\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\tpublic async submitSignal(message: any): Promise<void> {}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\n"]}
@@ -8,6 +8,10 @@ import { TypedEventEmitter } from "@fluid-internal/client-utils";
8
8
  * underlying storage for file document service.
9
9
  */
10
10
  export class FileDocumentService extends TypedEventEmitter {
11
+ resolvedUrl;
12
+ storage;
13
+ deltaStorage;
14
+ deltaConnection;
11
15
  constructor(resolvedUrl, storage, deltaStorage, deltaConnection) {
12
16
  super();
13
17
  this.resolvedUrl = resolvedUrl;
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentService.js","sourceRoot":"","sources":["../src/fileDocumentService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAajE;;;GAGG;AACH,MAAM,OAAO,mBACZ,SAAQ,iBAAyC;IAGjD,YACiB,WAAyB,EACxB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAE1D,KAAK,EAAE,CAAC;QALQ,gBAAW,GAAX,WAAW,CAAc;QACxB,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IAG3D,CAAC;IAEM,OAAO,KAAU,CAAC;IAElB,KAAK,CAAC,gBAAgB;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,qBAAqB;QACjC,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,oBAAoB,CAAC,MAAe;QAChD,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IClient } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentServiceEvents,\n\tIDocumentService,\n\tIResolvedUrl,\n\tIDocumentStorageService,\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaStorageService,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\n/**\n * The DocumentService manages the different endpoints for connecting to\n * underlying storage for file document service.\n */\nexport class FileDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {\n\t\tsuper();\n\t}\n\n\tpublic dispose(): void {}\n\n\tpublic async connectToStorage(): Promise<IDocumentStorageService> {\n\t\treturn this.storage;\n\t}\n\n\tpublic async connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn this.deltaStorage;\n\t}\n\n\t/**\n\t * Connects to a delta storage endpoint of provided documentService to get ops and then replaying\n\t * them so as to mimic a delta stream endpoint.\n\t *\n\t * @param client - Client that connects to socket.\n\t * @returns returns the delta stream service.\n\t */\n\tpublic async connectToDeltaStream(client: IClient): Promise<IDocumentDeltaConnection> {\n\t\treturn this.deltaConnection;\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDocumentService.js","sourceRoot":"","sources":["../src/fileDocumentService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAajE;;;GAGG;AACH,MAAM,OAAO,mBACZ,SAAQ,iBAAyC;IAIhC;IACC;IACA;IACA;IAJlB,YACiB,WAAyB,EACxB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAE1D,KAAK,EAAE,CAAC;QALQ,gBAAW,GAAX,WAAW,CAAc;QACxB,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IAG3D,CAAC;IAEM,OAAO,KAAU,CAAC;IAElB,KAAK,CAAC,gBAAgB;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,qBAAqB;QACjC,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,oBAAoB,CAAC,MAAe;QAChD,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IClient } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentServiceEvents,\n\tIDocumentService,\n\tIResolvedUrl,\n\tIDocumentStorageService,\n\tIDocumentDeltaConnection,\n\tIDocumentDeltaStorageService,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\n\n/**\n * The DocumentService manages the different endpoints for connecting to\n * underlying storage for file document service.\n */\nexport class FileDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {\n\t\tsuper();\n\t}\n\n\tpublic dispose(): void {}\n\n\tpublic async connectToStorage(): Promise<IDocumentStorageService> {\n\t\treturn this.storage;\n\t}\n\n\tpublic async connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn this.deltaStorage;\n\t}\n\n\t/**\n\t * Connects to a delta storage endpoint of provided documentService to get ops and then replaying\n\t * them so as to mimic a delta stream endpoint.\n\t *\n\t * @param client - Client that connects to socket.\n\t * @returns returns the delta stream service.\n\t */\n\tpublic async connectToDeltaStream(client: IClient): Promise<IDocumentDeltaConnection> {\n\t\treturn this.deltaConnection;\n\t}\n}\n"]}
@@ -9,6 +9,9 @@ import { FileDocumentService } from "./fileDocumentService.js";
9
9
  * @internal
10
10
  */
11
11
  export class FileDocumentServiceFactory {
12
+ storage;
13
+ deltaStorage;
14
+ deltaConnection;
12
15
  constructor(storage, deltaStorage, deltaConnection) {
13
16
  this.storage = storage;
14
17
  this.deltaStorage = deltaStorage;
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentServiceFactory.js","sourceRoot":"","sources":["../src/fileDocumentServiceFactory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D;;;;GAIG;AACH,MAAM,OAAO,0BAA0B;IACtC,YACkB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAFzC,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IACxD,CAAC;IAEJ;;;;;OAKG;IACI,KAAK,CAAC,qBAAqB,CACjC,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,OAAO,IAAI,mBAAmB,CAC7B,WAAW,EACX,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,eAAe,CACpB,CAAC;IACH,CAAC;IAED,8EAA8E;IACvE,KAAK,CAAC,eAAe,CAC3B,gBAA8B,EAC9B,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentService,\n\tIDocumentServiceFactory,\n\tIDocumentStorageService,\n\tIResolvedUrl,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\nimport { FileDocumentService } from \"./fileDocumentService.js\";\n\n/**\n * Factory for creating the file document service. Use this if you want to\n * use the local file storage as underlying storage.\n * @internal\n */\nexport class FileDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {}\n\n\t/**\n\t * Creates the file document service if the path exists.\n\t *\n\t * @param fileURL - Path of directory containing ops/snapshots.\n\t * @returns file document service.\n\t */\n\tpublic async createDocumentService(\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\treturn new FileDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tthis.storage,\n\t\t\tthis.deltaStorage,\n\t\t\tthis.deltaConnection,\n\t\t);\n\t}\n\n\t// TODO: Issue-2109 Implement detach container api or put appropriate comment.\n\tpublic async createContainer(\n\t\tcreateNewSummary: ISummaryTree,\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\tthrow new Error(\"Not implemented\");\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileDocumentServiceFactory.js","sourceRoot":"","sources":["../src/fileDocumentServiceFactory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D;;;;GAIG;AACH,MAAM,OAAO,0BAA0B;IAEpB;IACA;IACA;IAHlB,YACkB,OAAgC,EAChC,YAAqC,EACrC,eAAyC;QAFzC,YAAO,GAAP,OAAO,CAAyB;QAChC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,oBAAe,GAAf,eAAe,CAA0B;IACxD,CAAC;IAEJ;;;;;OAKG;IACI,KAAK,CAAC,qBAAqB,CACjC,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,OAAO,IAAI,mBAAmB,CAC7B,WAAW,EACX,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,eAAe,CACpB,CAAC;IACH,CAAC;IAED,8EAA8E;IACvE,KAAK,CAAC,eAAe,CAC3B,gBAA8B,EAC9B,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B;QAE5B,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentDeltaConnection,\n\tIDocumentService,\n\tIDocumentServiceFactory,\n\tIDocumentStorageService,\n\tIResolvedUrl,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport type { FileDeltaStorageService } from \"./fileDeltaStorageService.js\";\nimport { FileDocumentService } from \"./fileDocumentService.js\";\n\n/**\n * Factory for creating the file document service. Use this if you want to\n * use the local file storage as underlying storage.\n * @internal\n */\nexport class FileDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tprivate readonly storage: IDocumentStorageService,\n\t\tprivate readonly deltaStorage: FileDeltaStorageService,\n\t\tprivate readonly deltaConnection: IDocumentDeltaConnection,\n\t) {}\n\n\t/**\n\t * Creates the file document service if the path exists.\n\t *\n\t * @param fileURL - Path of directory containing ops/snapshots.\n\t * @returns file document service.\n\t */\n\tpublic async createDocumentService(\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\treturn new FileDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tthis.storage,\n\t\t\tthis.deltaStorage,\n\t\t\tthis.deltaConnection,\n\t\t);\n\t}\n\n\t// TODO: Issue-2109 Implement detach container api or put appropriate comment.\n\tpublic async createContainer(\n\t\tcreateNewSummary: ISummaryTree,\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\tthrow new Error(\"Not implemented\");\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/fileDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EACX,uBAAuB,EAEvB,aAAa,EACb,QAAQ,EAGR,MAAM,6CAA6C,CAAC;AAMrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AAIxF;;GAEG;AACH,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAK1D;;;GAGG;AACH,qBAAa,gBACZ,SAAQ,8BACR,YAAW,uBAAuB;IAKjC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAJ9B,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAQ;gBAG7B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,oBAAQ;IAKtC;;;OAGG;IAEU,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAkC/E;;;;OAIG;IAEU,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAmBzE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAU5D;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACtE,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACjD,KAAK,IAAI,IAAI,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,uBAAuB,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,8BAA8B,0CACpC,KAAK,KACT,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,sBAAsB,CAkGxD,CAAC;AAcH;;GAEG;AACH,eAAO,MAAM,kCAAkC,2CAnHrB,GAAG,EAAE,KAAK,sBAAsB,CAoHT,CAAC"}
1
+ {"version":3,"file":"fileDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/fileDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EACX,uBAAuB,EAEvB,aAAa,EACb,QAAQ,EAGR,MAAM,6CAA6C,CAAC;AAMrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AAIxF;;GAEG;AACH,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAK1D;;;GAGG;AACH,qBAAa,gBACZ,SAAQ,8BACR,YAAW,uBAAuB;IAKjC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAJ9B,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAQ;gBAG7B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,YAAA;IAKtC;;;OAGG;IAEU,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAkC/E;;;;OAIG;IAEU,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAmBzE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAU5D;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACtE,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACjD,KAAK,IAAI,IAAI,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,uBAAuB,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,8BAA8B,GAAI,KAAK,SAAS,iBAAiB,EAC7E,MAAM,KAAK,KACT,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,sBAAsB,CAkGxD,CAAC;AAcH;;GAEG;AACH,eAAO,MAAM,kCAAkC,2CAnHrB,GAAG,EAAE,KAAK,sBAAsB,CAoHT,CAAC"}
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import fs from "fs";
6
- import { bufferToString } from "@fluid-internal/client-utils";
6
+ import { bufferToString, Uint8ArrayToArrayBufferLike } from "@fluid-internal/client-utils";
7
7
  import { assert } from "@fluidframework/core-utils/internal";
8
8
  import { FileMode, TreeEntry } from "@fluidframework/driver-definitions/internal";
9
9
  import { buildSnapshotTree, convertSummaryTreeToSnapshotITree, } from "@fluidframework/driver-utils/internal";
@@ -21,11 +21,13 @@ const FileStorageVersionTreeId = "FileStorageTreeId";
21
21
  * @internal
22
22
  */
23
23
  export class FluidFetchReader extends ReadDocumentStorageServiceBase {
24
+ path;
25
+ versionName;
26
+ docTree = null;
24
27
  constructor(path, versionName) {
25
28
  super();
26
29
  this.path = path;
27
30
  this.versionName = versionName;
28
- this.docTree = null;
29
31
  }
30
32
  /**
31
33
  * Read the file and returns the snapshot tree.
@@ -91,7 +93,7 @@ export class FluidFetchReader extends ReadDocumentStorageServiceBase {
91
93
  const fileName = `${this.path}/${this.versionName}/${sha}`;
92
94
  if (fs.existsSync(fileName)) {
93
95
  const data = fs.readFileSync(fileName);
94
- return data;
96
+ return Uint8ArrayToArrayBufferLike(data);
95
97
  }
96
98
  }
97
99
  throw new Error(`Can't find blob ${sha}`);
@@ -101,11 +103,10 @@ export class FluidFetchReader extends ReadDocumentStorageServiceBase {
101
103
  * @internal
102
104
  */
103
105
  export const FileSnapshotWriterClassFactory = (Base) => class extends Base {
104
- constructor() {
105
- super(...arguments);
106
- // Note: if variable name has same name as in base class, it overrides it!
107
- this.blobsWriter = new Map();
108
- }
106
+ // Note: if variable name has same name as in base class, it overrides it!
107
+ blobsWriter = new Map();
108
+ latestWriterTree;
109
+ docId;
109
110
  reset() {
110
111
  this.blobsWriter = new Map();
111
112
  delete this.latestWriterTree;
@@ -1 +1 @@
1
- {"version":3,"file":"fileDocumentStorageService.js","sourceRoot":"","sources":["../src/fileDocumentStorageService.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 fs from \"fs\";\n\nimport { bufferToString } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentStorageService,\n\tISummaryContext,\n\tISnapshotTree,\n\tIVersion,\n\tITree,\n\tIBlob,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { FileMode, TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tbuildSnapshotTree,\n\tconvertSummaryTreeToSnapshotITree,\n} from \"@fluidframework/driver-utils/internal\";\nimport type { IFileSnapshot } from \"@fluidframework/replay-driver/internal\";\nimport { ReadDocumentStorageServiceBase } from \"@fluidframework/replay-driver/internal\";\n\n// This ID is used by replay tool as Document Id.\n// We leverage it to figure out when container is asking for root document tree.\n/**\n * @internal\n */\nexport const FileStorageDocumentName = \"FileStorageDocId\"; // Some unique document name\n\n// Tree ID use to communicate between getVersions() & getSnapshotTree() that IVersion is ours.\nconst FileStorageVersionTreeId = \"FileStorageTreeId\";\n\n/**\n * Document storage service for the file driver.\n * @internal\n */\nexport class FluidFetchReader\n\textends ReadDocumentStorageServiceBase\n\timplements IDocumentStorageService\n{\n\tprotected docTree: ISnapshotTree | null = null;\n\n\tconstructor(\n\t\tprivate readonly path: string,\n\t\tprivate readonly versionName?: string,\n\t) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Read the file and returns the snapshot tree.\n\t * @param version - The version contains the path of the file which contains the snapshot tree.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\tassert(version !== null, 0x092 /* \"version input for reading snapshot tree is null!\" */);\n\t\tassert(\n\t\t\t!version || version.treeId === FileStorageVersionTreeId,\n\t\t\t0x093 /* \"invalid version input for reading snapshot tree!\" */,\n\t\t);\n\n\t\tlet filename: string;\n\t\tlet rootTree = false;\n\t\tif (!version || version.id === \"latest\") {\n\t\t\tif (this.docTree) {\n\t\t\t\treturn this.docTree;\n\t\t\t}\n\t\t\tif (this.versionName === undefined) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\trootTree = true;\n\t\t\tfilename = `${this.path}/${this.versionName}/tree.json`;\n\t\t} else {\n\t\t\tfilename = `${this.path}/${this.versionName}/${version.id}.json`;\n\t\t}\n\n\t\tif (!fs.existsSync(filename)) {\n\t\t\tthrow new Error(`Can't find file ${filename}`);\n\t\t}\n\t\tconst data = fs.readFileSync(filename);\n\t\tconst tree = JSON.parse(data.toString(\"utf-8\"));\n\t\tif (rootTree) {\n\t\t\tthis.docTree = tree;\n\t\t}\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn tree;\n\t}\n\n\t/**\n\t * Gets the path of the snapshot tree to be read.\n\t * @param versionId - version ID.\n\t * @param count - Number of versions to be returned.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\tif (versionId === FileStorageDocumentName || versionId === null) {\n\t\t\tif (this.docTree !== null || this.versionName !== undefined) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\t\t\t// Started with ops - return empty set.\n\t\t\treturn [];\n\t\t} else if (this.versionName !== undefined) {\n\t\t\tassert(!!this.docTree, 0x094 /* \"Missing snapshot tree!\" */);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: versionId,\n\t\t\t\t\ttreeId: FileStorageVersionTreeId,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\tthrow new Error(`Unknown version: ${versionId}`);\n\t}\n\n\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\tif (this.versionName !== undefined) {\n\t\t\tconst fileName = `${this.path}/${this.versionName}/${sha}`;\n\t\t\tif (fs.existsSync(fileName)) {\n\t\t\t\tconst data = fs.readFileSync(fileName);\n\t\t\t\treturn data;\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`Can't find blob ${sha}`);\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ISnapshotWriterStorage extends IDocumentStorageService {\n\tonSnapshotHandler(snapshot: IFileSnapshot): void;\n\treset(): void;\n}\n\n/**\n * Constructor type for creating {@link @fluidframework/driver-definitions#IDocumentStorageService} instances.\n *\n * @internal\n */\nexport type ReaderConstructor = new (...args: any[]) => IDocumentStorageService;\n\n/**\n * @internal\n */\nexport const FileSnapshotWriterClassFactory = <TBase extends ReaderConstructor>(\n\tBase: TBase,\n): TBase & (new (...args: any[]) => ISnapshotWriterStorage) =>\n\tclass extends Base implements ISnapshotWriterStorage {\n\t\t// Note: if variable name has same name as in base class, it overrides it!\n\t\tpublic blobsWriter = new Map<string, ArrayBufferLike>();\n\t\tpublic latestWriterTree?: ISnapshotTree;\n\t\tpublic docId?: string;\n\n\t\tpublic reset(): void {\n\t\t\tthis.blobsWriter = new Map<string, ArrayBufferLike>();\n\t\t\tdelete this.latestWriterTree;\n\t\t\tdelete this.docId;\n\t\t}\n\n\t\tpublic onSnapshotHandler(snapshot: IFileSnapshot): void {\n\t\t\tthrow new Error(\"onSnapshotHandler is not setup! Please provide your handler!\");\n\t\t}\n\n\t\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\t\tconst blob = this.blobsWriter.get(sha);\n\t\t\tif (blob !== undefined) {\n\t\t\t\treturn blob;\n\t\t\t}\n\t\t\treturn super.readBlob(sha);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\t\t// If we already saved document, that means we are getting here because of snapshot generation.\n\t\t\t// Not returning tree ensures that IContainerRuntime.snapshot() would regenerate subtrees for\n\t\t\t// each unchanged data store.\n\t\t\t// If we want to change that, we would need to capture docId on first call and return this.latestWriterTree\n\t\t\t// when latest is requested.\n\t\t\tif (this.latestWriterTree && (this.docId === versionId || versionId === null)) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\n\t\t\tif (this.docId === undefined && versionId !== null) {\n\t\t\t\tthis.docId = versionId;\n\t\t\t}\n\n\t\t\treturn super.getVersions(versionId, count);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\t\tif (this.latestWriterTree && (!version || version.id === \"latest\")) {\n\t\t\t\treturn this.latestWriterTree;\n\t\t\t}\n\t\t\treturn super.getSnapshotTree(version);\n\t\t}\n\n\t\tpublic async uploadSummaryWithContext(\n\t\t\tsummary: ISummaryTree,\n\t\t\tcontext: ISummaryContext,\n\t\t): Promise<string> {\n\t\t\tconst tree = convertSummaryTreeToSnapshotITree(summary);\n\n\t\t\t// Remove tree IDs for easier comparison of snapshots\n\t\t\tdelete tree.id;\n\t\t\tremoveNullTreeIds(tree);\n\n\t\t\tthis.latestWriterTree = buildSnapshotTree(tree.entries, this.blobsWriter);\n\n\t\t\tconst fileSnapshot: IFileSnapshot = { tree, commits: {} };\n\t\t\tthis.onSnapshotHandler(fileSnapshot);\n\t\t\treturn \"testHandleId\";\n\t\t}\n\n\t\tpublic async buildTree(snapshotTree: ISnapshotTree): Promise<ITree> {\n\t\t\tconst tree: ITree = { entries: [] };\n\n\t\t\tfor (const [subTreeId, subTreeValue] of Object.entries(snapshotTree.trees)) {\n\t\t\t\tconst subTree = await this.buildTree(subTreeValue);\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.Directory,\n\t\t\t\t\tpath: subTreeId,\n\t\t\t\t\ttype: TreeEntry.Tree,\n\t\t\t\t\tvalue: subTree,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (const [blobName, blobValue] of Object.keys(snapshotTree.blobs)) {\n\t\t\t\tconst buffer = await this.readBlob(blobValue);\n\t\t\t\tconst contents = bufferToString(buffer, \"utf8\");\n\t\t\t\tconst blob: IBlob = {\n\t\t\t\t\tcontents,\n\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t};\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.File,\n\t\t\t\t\tpath: blobName,\n\t\t\t\t\ttype: TreeEntry.Blob,\n\t\t\t\t\tvalue: blob,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn tree;\n\t\t}\n\t};\n\nfunction removeNullTreeIds(tree: ITree): void {\n\tfor (const node of tree.entries) {\n\t\tif (node.type === TreeEntry.Tree) {\n\t\t\tremoveNullTreeIds(node.value);\n\t\t}\n\t}\n\tassert(\n\t\ttree.id === undefined || tree.id === null,\n\t\t0x096 /* \"Trying to remove valid tree IDs in removeNullTreeIds()!\" */,\n\t);\n\tdelete tree.id;\n}\n/**\n * @internal\n */\nexport const FluidFetchReaderFileSnapshotWriter =\n\tFileSnapshotWriterClassFactory(FluidFetchReader);\n"]}
1
+ {"version":3,"file":"fileDocumentStorageService.js","sourceRoot":"","sources":["../src/fileDocumentStorageService.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 fs from \"fs\";\n\nimport { bufferToString, Uint8ArrayToArrayBufferLike } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentStorageService,\n\tISummaryContext,\n\tISnapshotTree,\n\tIVersion,\n\tITree,\n\tIBlob,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { FileMode, TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tbuildSnapshotTree,\n\tconvertSummaryTreeToSnapshotITree,\n} from \"@fluidframework/driver-utils/internal\";\nimport type { IFileSnapshot } from \"@fluidframework/replay-driver/internal\";\nimport { ReadDocumentStorageServiceBase } from \"@fluidframework/replay-driver/internal\";\n\n// This ID is used by replay tool as Document Id.\n// We leverage it to figure out when container is asking for root document tree.\n/**\n * @internal\n */\nexport const FileStorageDocumentName = \"FileStorageDocId\"; // Some unique document name\n\n// Tree ID use to communicate between getVersions() & getSnapshotTree() that IVersion is ours.\nconst FileStorageVersionTreeId = \"FileStorageTreeId\";\n\n/**\n * Document storage service for the file driver.\n * @internal\n */\nexport class FluidFetchReader\n\textends ReadDocumentStorageServiceBase\n\timplements IDocumentStorageService\n{\n\tprotected docTree: ISnapshotTree | null = null;\n\n\tconstructor(\n\t\tprivate readonly path: string,\n\t\tprivate readonly versionName?: string,\n\t) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Read the file and returns the snapshot tree.\n\t * @param version - The version contains the path of the file which contains the snapshot tree.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\tassert(version !== null, 0x092 /* \"version input for reading snapshot tree is null!\" */);\n\t\tassert(\n\t\t\t!version || version.treeId === FileStorageVersionTreeId,\n\t\t\t0x093 /* \"invalid version input for reading snapshot tree!\" */,\n\t\t);\n\n\t\tlet filename: string;\n\t\tlet rootTree = false;\n\t\tif (!version || version.id === \"latest\") {\n\t\t\tif (this.docTree) {\n\t\t\t\treturn this.docTree;\n\t\t\t}\n\t\t\tif (this.versionName === undefined) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\trootTree = true;\n\t\t\tfilename = `${this.path}/${this.versionName}/tree.json`;\n\t\t} else {\n\t\t\tfilename = `${this.path}/${this.versionName}/${version.id}.json`;\n\t\t}\n\n\t\tif (!fs.existsSync(filename)) {\n\t\t\tthrow new Error(`Can't find file ${filename}`);\n\t\t}\n\t\tconst data = fs.readFileSync(filename);\n\t\tconst tree = JSON.parse(data.toString(\"utf-8\"));\n\t\tif (rootTree) {\n\t\t\tthis.docTree = tree;\n\t\t}\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn tree;\n\t}\n\n\t/**\n\t * Gets the path of the snapshot tree to be read.\n\t * @param versionId - version ID.\n\t * @param count - Number of versions to be returned.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\tif (versionId === FileStorageDocumentName || versionId === null) {\n\t\t\tif (this.docTree !== null || this.versionName !== undefined) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\t\t\t// Started with ops - return empty set.\n\t\t\treturn [];\n\t\t} else if (this.versionName !== undefined) {\n\t\t\tassert(!!this.docTree, 0x094 /* \"Missing snapshot tree!\" */);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: versionId,\n\t\t\t\t\ttreeId: FileStorageVersionTreeId,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\tthrow new Error(`Unknown version: ${versionId}`);\n\t}\n\n\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\tif (this.versionName !== undefined) {\n\t\t\tconst fileName = `${this.path}/${this.versionName}/${sha}`;\n\t\t\tif (fs.existsSync(fileName)) {\n\t\t\t\tconst data = fs.readFileSync(fileName);\n\t\t\t\treturn Uint8ArrayToArrayBufferLike(data);\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`Can't find blob ${sha}`);\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ISnapshotWriterStorage extends IDocumentStorageService {\n\tonSnapshotHandler(snapshot: IFileSnapshot): void;\n\treset(): void;\n}\n\n/**\n * Constructor type for creating {@link @fluidframework/driver-definitions#IDocumentStorageService} instances.\n *\n * @internal\n */\nexport type ReaderConstructor = new (...args: any[]) => IDocumentStorageService;\n\n/**\n * @internal\n */\nexport const FileSnapshotWriterClassFactory = <TBase extends ReaderConstructor>(\n\tBase: TBase,\n): TBase & (new (...args: any[]) => ISnapshotWriterStorage) =>\n\tclass extends Base implements ISnapshotWriterStorage {\n\t\t// Note: if variable name has same name as in base class, it overrides it!\n\t\tpublic blobsWriter = new Map<string, ArrayBufferLike>();\n\t\tpublic latestWriterTree?: ISnapshotTree;\n\t\tpublic docId?: string;\n\n\t\tpublic reset(): void {\n\t\t\tthis.blobsWriter = new Map<string, ArrayBufferLike>();\n\t\t\tdelete this.latestWriterTree;\n\t\t\tdelete this.docId;\n\t\t}\n\n\t\tpublic onSnapshotHandler(snapshot: IFileSnapshot): void {\n\t\t\tthrow new Error(\"onSnapshotHandler is not setup! Please provide your handler!\");\n\t\t}\n\n\t\tpublic async readBlob(sha: string): Promise<ArrayBufferLike> {\n\t\t\tconst blob = this.blobsWriter.get(sha);\n\t\t\tif (blob !== undefined) {\n\t\t\t\treturn blob;\n\t\t\t}\n\t\t\treturn super.readBlob(sha);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\t\t// If we already saved document, that means we are getting here because of snapshot generation.\n\t\t\t// Not returning tree ensures that IContainerRuntime.snapshot() would regenerate subtrees for\n\t\t\t// each unchanged data store.\n\t\t\t// If we want to change that, we would need to capture docId on first call and return this.latestWriterTree\n\t\t\t// when latest is requested.\n\t\t\tif (this.latestWriterTree && (this.docId === versionId || versionId === null)) {\n\t\t\t\treturn [{ id: \"latest\", treeId: FileStorageVersionTreeId }];\n\t\t\t}\n\n\t\t\tif (this.docId === undefined && versionId !== null) {\n\t\t\t\tthis.docId = versionId;\n\t\t\t}\n\n\t\t\treturn super.getVersions(versionId, count);\n\t\t}\n\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\t\tif (this.latestWriterTree && (!version || version.id === \"latest\")) {\n\t\t\t\treturn this.latestWriterTree;\n\t\t\t}\n\t\t\treturn super.getSnapshotTree(version);\n\t\t}\n\n\t\tpublic async uploadSummaryWithContext(\n\t\t\tsummary: ISummaryTree,\n\t\t\tcontext: ISummaryContext,\n\t\t): Promise<string> {\n\t\t\tconst tree = convertSummaryTreeToSnapshotITree(summary);\n\n\t\t\t// Remove tree IDs for easier comparison of snapshots\n\t\t\tdelete tree.id;\n\t\t\tremoveNullTreeIds(tree);\n\n\t\t\tthis.latestWriterTree = buildSnapshotTree(tree.entries, this.blobsWriter);\n\n\t\t\tconst fileSnapshot: IFileSnapshot = { tree, commits: {} };\n\t\t\tthis.onSnapshotHandler(fileSnapshot);\n\t\t\treturn \"testHandleId\";\n\t\t}\n\n\t\tpublic async buildTree(snapshotTree: ISnapshotTree): Promise<ITree> {\n\t\t\tconst tree: ITree = { entries: [] };\n\n\t\t\tfor (const [subTreeId, subTreeValue] of Object.entries(snapshotTree.trees)) {\n\t\t\t\tconst subTree = await this.buildTree(subTreeValue);\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.Directory,\n\t\t\t\t\tpath: subTreeId,\n\t\t\t\t\ttype: TreeEntry.Tree,\n\t\t\t\t\tvalue: subTree,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (const [blobName, blobValue] of Object.keys(snapshotTree.blobs)) {\n\t\t\t\tconst buffer = await this.readBlob(blobValue);\n\t\t\t\tconst contents = bufferToString(buffer, \"utf8\");\n\t\t\t\tconst blob: IBlob = {\n\t\t\t\t\tcontents,\n\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t};\n\t\t\t\ttree.entries.push({\n\t\t\t\t\tmode: FileMode.File,\n\t\t\t\t\tpath: blobName,\n\t\t\t\t\ttype: TreeEntry.Blob,\n\t\t\t\t\tvalue: blob,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn tree;\n\t\t}\n\t};\n\nfunction removeNullTreeIds(tree: ITree): void {\n\tfor (const node of tree.entries) {\n\t\tif (node.type === TreeEntry.Tree) {\n\t\t\tremoveNullTreeIds(node.value);\n\t\t}\n\t}\n\tassert(\n\t\ttree.id === undefined || tree.id === null,\n\t\t0x096 /* \"Trying to remove valid tree IDs in removeNullTreeIds()!\" */,\n\t);\n\tdelete tree.id;\n}\n/**\n * @internal\n */\nexport const FluidFetchReaderFileSnapshotWriter =\n\tFileSnapshotWriterClassFactory(FluidFetchReader);\n"]}
package/lib/public.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  /*
7
7
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
- * Generated by "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib --node10TypeCompat" in @fluid-tools/build-cli.
8
+ * Generated by "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib" in @fluid-tools/build-cli.
9
9
  */
10
10
 
11
11
  export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/file-driver",
3
- "version": "2.118.0",
3
+ "version": "3.0.0",
4
4
  "description": "A driver that reads/write from/to local file storage.",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -14,35 +14,24 @@
14
14
  "type": "module",
15
15
  "exports": {
16
16
  ".": {
17
- "import": {
18
- "types": "./lib/public.d.ts",
19
- "default": "./lib/index.js"
20
- },
21
- "require": {
22
- "types": "./dist/public.d.ts",
23
- "default": "./dist/index.js"
17
+ "types": "./lib/public.d.ts",
18
+ "default": "./lib/index.js",
19
+ "internal-entrypoint-generation": {
20
+ "types": "./dist/public.d.ts"
24
21
  }
25
22
  },
26
23
  "./internal": {
27
- "import": {
28
- "types": "./lib/index.d.ts",
29
- "default": "./lib/index.js"
30
- },
31
- "require": {
32
- "types": "./dist/index.d.ts",
33
- "default": "./dist/index.js"
34
- }
24
+ "types": "./lib/index.d.ts",
25
+ "default": "./lib/index.js"
35
26
  }
36
27
  },
37
- "main": "lib/index.js",
38
- "types": "lib/public.d.ts",
39
28
  "dependencies": {
40
- "@fluid-internal/client-utils": "~2.118.0",
41
- "@fluidframework/core-interfaces": "~2.118.0",
42
- "@fluidframework/core-utils": "~2.118.0",
43
- "@fluidframework/driver-definitions": "~2.118.0",
44
- "@fluidframework/driver-utils": "~2.118.0",
45
- "@fluidframework/replay-driver": "~2.118.0"
29
+ "@fluid-internal/client-utils": "~3.0.0",
30
+ "@fluidframework/core-interfaces": "~3.0.0",
31
+ "@fluidframework/core-utils": "~3.0.0",
32
+ "@fluidframework/driver-definitions": "~3.0.0",
33
+ "@fluidframework/driver-utils": "~3.0.0",
34
+ "@fluidframework/replay-driver": "~3.0.0"
46
35
  },
47
36
  "devDependencies": {
48
37
  "@arethetypeswrong/cli": "^0.18.5",
@@ -59,7 +48,7 @@
59
48
  "eslint": "~9.39.1",
60
49
  "jiti": "^2.6.1",
61
50
  "rimraf": "^6.1.3",
62
- "typescript": "~5.4.5"
51
+ "typescript": "~6.0.3"
63
52
  },
64
53
  "typeValidation": {
65
54
  "broken": {},
@@ -67,23 +56,27 @@
67
56
  },
68
57
  "scripts": {
69
58
  "build": "fluid-build . --task build",
59
+ "build:api-reports": "api-extractor run --local --config api-extractor/api-extractor-report.json",
60
+ "build:cjs": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
70
61
  "build:compile": "fluid-build . --task compile",
71
- "build:docs": "api-extractor run --local",
62
+ "build:docs": "api-extractor run --local --config api-extractor/api-extractor-model.json",
72
63
  "build:entrypoints": "fluid-build . --task build:entrypoints",
73
64
  "build:entrypoints:cjs": "flub generate entrypoints --resolutionConditions require --outFileLegacyBeta legacy --outDir ./dist",
74
- "build:entrypoints:esm": "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib --node10TypeCompat",
75
- "build:esnext": "tsc --project ./tsconfig.json",
65
+ "build:entrypoints:esm": "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib",
66
+ "build:esm": "tsc --project ./tsconfig.json",
76
67
  "build:test": "concurrently npm:build:test:esm npm:build:test:cjs",
77
68
  "build:test:cjs": "fluid-tsc commonjs --project ./src/test/tsconfig.cjs.json",
78
69
  "build:test:esm": "tsc --project ./src/test/tsconfig.json",
79
- "check:are-the-types-wrong": "attw --pack .",
70
+ "check:are-the-types-wrong": "attw --pack . --profile esm-only",
80
71
  "check:biome": "biome check .",
81
72
  "check:exports": "concurrently \"npm:check:exports:*\"",
82
73
  "check:exports:bundle-release-tags": "api-extractor run --config api-extractor/api-extractor-lint-bundle.json",
83
74
  "check:exports:cjs:public": "api-extractor run --config api-extractor/api-extractor-lint-public.cjs.json",
84
75
  "check:exports:esm:public": "api-extractor run --config api-extractor/api-extractor-lint-public.esm.json",
85
76
  "check:format": "npm run check:biome",
86
- "ci:build:docs": "api-extractor run",
77
+ "check:types:inexactOptionalPropertyTypes": "tsc --project ./tsconfig.json --noEmit --exactOptionalPropertyTypes false --skipLibCheck --emitDeclarationOnly false --tsBuildInfoFile ./tsconfig.inexactOptionalPropertyTypes.tsbuildinfo",
78
+ "ci:build:api-reports": "api-extractor run --config api-extractor/api-extractor-report.json",
79
+ "ci:build:docs": "api-extractor run --config api-extractor/api-extractor-model.json",
87
80
  "clean": "rimraf --glob dist lib {alpha,beta,internal,legacy}.d.ts \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp",
88
81
  "eslint": "eslint --quiet --format stylish src",
89
82
  "eslint:fix": "eslint --quiet --format stylish src --fix --fix-type problem,suggestion,layout",
@@ -91,7 +84,6 @@
91
84
  "format:biome": "biome check . --write",
92
85
  "lint": "fluid-build . --task lint",
93
86
  "lint:fix": "fluid-build . --task eslint:fix --task format",
94
- "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
95
87
  "typetests:gen": "flub generate typetests --dir . -v"
96
88
  }
97
89
  }
@@ -5,7 +5,7 @@
5
5
 
6
6
  import fs from "fs";
7
7
 
8
- import { bufferToString } from "@fluid-internal/client-utils";
8
+ import { bufferToString, Uint8ArrayToArrayBufferLike } from "@fluid-internal/client-utils";
9
9
  import { assert } from "@fluidframework/core-utils/internal";
10
10
  import type { ISummaryTree } from "@fluidframework/driver-definitions";
11
11
  import type {
@@ -120,7 +120,7 @@ export class FluidFetchReader
120
120
  const fileName = `${this.path}/${this.versionName}/${sha}`;
121
121
  if (fs.existsSync(fileName)) {
122
122
  const data = fs.readFileSync(fileName);
123
- return data;
123
+ return Uint8ArrayToArrayBufferLike(data);
124
124
  }
125
125
  }
126
126
  throw new Error(`Can't find blob ${sha}`);
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "../../../common/build/build-common/tsconfig.node16.json",
2
+ "extends": "../../../common/build/build-common/tsconfig.node20.json",
3
3
  "include": ["src/**/*"],
4
4
  "exclude": ["src/test/**/*"],
5
5
  "compilerOptions": {
package/internal.d.ts DELETED
@@ -1,11 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
-
6
- /*
7
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
- * Generated by "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib --node10TypeCompat" in @fluid-tools/build-cli.
9
- */
10
-
11
- export * from "./lib/index.js";