@fluidframework/file-driver 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.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/.eslintrc.js +6 -9
- package/README.md +1 -1
- package/api-extractor.json +2 -2
- package/dist/fileDeltaStorageService.d.ts.map +1 -1
- package/dist/fileDeltaStorageService.js.map +1 -1
- package/dist/fileDocumentDeltaConnection.d.ts.map +1 -1
- package/dist/fileDocumentDeltaConnection.js +6 -3
- package/dist/fileDocumentDeltaConnection.js.map +1 -1
- package/dist/fileDocumentService.d.ts.map +1 -1
- package/dist/fileDocumentService.js.map +1 -1
- package/dist/fileDocumentServiceFactory.d.ts.map +1 -1
- package/dist/fileDocumentServiceFactory.js.map +1 -1
- package/dist/fileDocumentStorageService.d.ts.map +1 -1
- package/dist/fileDocumentStorageService.js +4 -2
- package/dist/fileDocumentStorageService.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/package.json +33 -32
- package/prettier.config.cjs +1 -1
- package/src/fileDeltaStorageService.ts +53 -50
- package/src/fileDocumentDeltaConnection.ts +186 -171
- package/src/fileDocumentService.ts +26 -27
- package/src/fileDocumentServiceFactory.ts +33 -33
- package/src/fileDocumentStorageService.ts +190 -178
- package/src/packageVersion.ts +1 -1
- package/tsconfig.json +9 -14
|
@@ -20,192 +20,204 @@ const FileStorageVersionTreeId = "FileStorageTreeId";
|
|
|
20
20
|
/**
|
|
21
21
|
* Document storage service for the file driver.
|
|
22
22
|
*/
|
|
23
|
-
export class FluidFetchReader
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
23
|
+
export class FluidFetchReader
|
|
24
|
+
extends ReadDocumentStorageServiceBase
|
|
25
|
+
implements IDocumentStorageService
|
|
26
|
+
{
|
|
27
|
+
protected docTree: api.ISnapshotTree | null = null;
|
|
28
|
+
|
|
29
|
+
constructor(private readonly path: string, private readonly versionName?: string) {
|
|
30
|
+
super();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Read the file and returns the snapshot tree.
|
|
35
|
+
* @param version - The version contains the path of the file which contains the snapshot tree.
|
|
36
|
+
*/
|
|
37
|
+
public async getSnapshotTree(version?: api.IVersion): Promise<api.ISnapshotTree | null> {
|
|
38
|
+
assert(version !== null, 0x092 /* "version input for reading snapshot tree is null!" */);
|
|
39
|
+
assert(
|
|
40
|
+
!version || version.treeId === FileStorageVersionTreeId,
|
|
41
|
+
0x093 /* "invalid version input for reading snapshot tree!" */,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
let filename: string;
|
|
45
|
+
let rootTree = false;
|
|
46
|
+
if (!version || version.id === "latest") {
|
|
47
|
+
if (this.docTree) {
|
|
48
|
+
return this.docTree;
|
|
49
|
+
}
|
|
50
|
+
if (this.versionName === undefined) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
rootTree = true;
|
|
54
|
+
filename = `${this.path}/${this.versionName}/tree.json`;
|
|
55
|
+
} else {
|
|
56
|
+
filename = `${this.path}/${this.versionName}/${version.id}.json`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!fs.existsSync(filename)) {
|
|
60
|
+
throw new Error(`Can't find file ${filename}`);
|
|
61
|
+
}
|
|
62
|
+
const data = fs.readFileSync(filename);
|
|
63
|
+
const tree = JSON.parse(data.toString("utf-8"));
|
|
64
|
+
if (rootTree) {
|
|
65
|
+
this.docTree = tree;
|
|
66
|
+
}
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
68
|
+
return tree;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Gets the path of the snapshot tree to be read.
|
|
73
|
+
* @param versionId - version ID.
|
|
74
|
+
* @param count - Number of versions to be returned.
|
|
75
|
+
*/
|
|
76
|
+
public async getVersions(versionId: string | null, count: number): Promise<api.IVersion[]> {
|
|
77
|
+
if (versionId === FileStorageDocumentName || versionId === null) {
|
|
78
|
+
if (this.docTree || this.versionName !== undefined) {
|
|
79
|
+
return [{ id: "latest", treeId: FileStorageVersionTreeId }];
|
|
80
|
+
}
|
|
81
|
+
// Started with ops - return empty set.
|
|
82
|
+
return [];
|
|
83
|
+
} else if (this.versionName !== undefined) {
|
|
84
|
+
assert(!!this.docTree, 0x094 /* "Missing snapshot tree!" */);
|
|
85
|
+
return [
|
|
86
|
+
{
|
|
87
|
+
id: versionId,
|
|
88
|
+
treeId: FileStorageVersionTreeId,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
throw new Error(`Unknown version: ${versionId}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public async readBlob(sha: string): Promise<ArrayBufferLike> {
|
|
96
|
+
if (this.versionName !== undefined) {
|
|
97
|
+
const fileName = `${this.path}/${this.versionName}/${sha}`;
|
|
98
|
+
if (fs.existsSync(fileName)) {
|
|
99
|
+
const data = fs.readFileSync(fileName);
|
|
100
|
+
return data;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`Can't find blob ${sha}`);
|
|
104
|
+
}
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
export interface ISnapshotWriterStorage extends IDocumentStorageService {
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
onSnapshotHandler(snapshot: IFileSnapshot): void;
|
|
109
|
+
reset(): void;
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
export type ReaderConstructor = new (...args: any[]) => IDocumentStorageService;
|
|
106
113
|
export const FileSnapshotWriterClassFactory = <TBase extends ReaderConstructor>(Base: TBase) =>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
114
|
+
class extends Base implements ISnapshotWriterStorage {
|
|
115
|
+
// Note: if variable name has same name as in base class, it overrides it!
|
|
116
|
+
public blobsWriter = new Map<string, ArrayBufferLike>();
|
|
117
|
+
public latestWriterTree?: api.ISnapshotTree;
|
|
118
|
+
public docId?: string;
|
|
119
|
+
|
|
120
|
+
public reset() {
|
|
121
|
+
this.blobsWriter = new Map<string, ArrayBufferLike>();
|
|
122
|
+
this.latestWriterTree = undefined;
|
|
123
|
+
this.docId = undefined;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public onSnapshotHandler(snapshot: IFileSnapshot): void {
|
|
127
|
+
throw new Error("onSnapshotHandler is not setup! Please provide your handler!");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public async readBlob(sha: string): Promise<ArrayBufferLike> {
|
|
131
|
+
const blob = this.blobsWriter.get(sha);
|
|
132
|
+
if (blob !== undefined) {
|
|
133
|
+
return blob;
|
|
134
|
+
}
|
|
135
|
+
return super.readBlob(sha);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public async getVersions(versionId: string | null, count: number): Promise<api.IVersion[]> {
|
|
139
|
+
// If we already saved document, that means we are getting here because of snapshot generation.
|
|
140
|
+
// Not returning tree ensures that ContainerRuntime.snapshot() would regenerate subtrees for
|
|
141
|
+
// each unchanged data store.
|
|
142
|
+
// If we want to change that, we would need to capture docId on first call and return this.latestWriterTree
|
|
143
|
+
// when latest is requested.
|
|
144
|
+
if (this.latestWriterTree && (this.docId === versionId || versionId === null)) {
|
|
145
|
+
return [{ id: "latest", treeId: FileStorageVersionTreeId }];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (this.docId === undefined && versionId !== null) {
|
|
149
|
+
this.docId = versionId;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return super.getVersions(versionId, count);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public async getSnapshotTree(version?: api.IVersion): Promise<api.ISnapshotTree | null> {
|
|
156
|
+
if (this.latestWriterTree && (!version || version.id === "latest")) {
|
|
157
|
+
return this.latestWriterTree;
|
|
158
|
+
}
|
|
159
|
+
return super.getSnapshotTree(version);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public async uploadSummaryWithContext(
|
|
163
|
+
summary: api.ISummaryTree,
|
|
164
|
+
context: ISummaryContext,
|
|
165
|
+
): Promise<string> {
|
|
166
|
+
const tree = convertSummaryTreeToSnapshotITree(summary);
|
|
167
|
+
|
|
168
|
+
// Remove tree IDs for easier comparison of snapshots
|
|
169
|
+
delete tree.id;
|
|
170
|
+
removeNullTreeIds(tree);
|
|
171
|
+
|
|
172
|
+
this.latestWriterTree = buildSnapshotTree(tree.entries, this.blobsWriter);
|
|
173
|
+
|
|
174
|
+
const fileSnapshot: IFileSnapshot = { tree, commits: {} };
|
|
175
|
+
this.onSnapshotHandler(fileSnapshot);
|
|
176
|
+
return "testHandleId";
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public async buildTree(snapshotTree: api.ISnapshotTree): Promise<api.ITree> {
|
|
180
|
+
const tree: api.ITree = { entries: [] };
|
|
181
|
+
|
|
182
|
+
for (const subTreeId of Object.keys(snapshotTree.trees)) {
|
|
183
|
+
const subTree = await this.buildTree(snapshotTree.trees[subTreeId]);
|
|
184
|
+
tree.entries.push({
|
|
185
|
+
mode: api.FileMode.Directory,
|
|
186
|
+
path: subTreeId,
|
|
187
|
+
type: api.TreeEntry.Tree,
|
|
188
|
+
value: subTree,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
for (const blobName of Object.keys(snapshotTree.blobs)) {
|
|
193
|
+
const buffer = await this.readBlob(snapshotTree.blobs[blobName]);
|
|
194
|
+
const contents = bufferToString(buffer, "utf8");
|
|
195
|
+
const blob: api.IBlob = {
|
|
196
|
+
contents,
|
|
197
|
+
encoding: "utf-8",
|
|
198
|
+
};
|
|
199
|
+
tree.entries.push({
|
|
200
|
+
mode: api.FileMode.File,
|
|
201
|
+
path: blobName,
|
|
202
|
+
type: api.TreeEntry.Blob,
|
|
203
|
+
value: blob,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return tree;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
200
210
|
|
|
201
211
|
function removeNullTreeIds(tree: api.ITree) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
212
|
+
for (const node of tree.entries) {
|
|
213
|
+
if (node.type === api.TreeEntry.Tree) {
|
|
214
|
+
removeNullTreeIds(node.value);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
assert(
|
|
218
|
+
tree.id === undefined || tree.id === null,
|
|
219
|
+
0x096 /* "Trying to remove valid tree IDs in removeNullTreeIds()!" */,
|
|
220
|
+
);
|
|
221
|
+
delete tree.id;
|
|
210
222
|
}
|
|
211
223
|
export const FluidFetchReaderFileSnapshotWriter = FileSnapshotWriterClassFactory(FluidFetchReader);
|
package/src/packageVersion.ts
CHANGED
package/tsconfig.json
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"noUnusedLocals": false
|
|
12
|
-
},
|
|
13
|
-
"include": [
|
|
14
|
-
"src/**/*"
|
|
15
|
-
]
|
|
2
|
+
"extends": "@fluidframework/build-common/ts-common-config.json",
|
|
3
|
+
"exclude": ["dist", "node_modules"],
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"noUnusedLocals": false,
|
|
9
|
+
},
|
|
10
|
+
"include": ["src/**/*"],
|
|
16
11
|
}
|