@fluidframework/routerlicious-driver 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.2.0.153917
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 +5 -0
- package/README.md +38 -0
- package/dist/cache.js +2 -2
- package/dist/cache.js.map +1 -1
- package/dist/deltaStorageService.d.ts +1 -1
- package/dist/deltaStorageService.d.ts.map +1 -1
- package/dist/deltaStorageService.js +7 -4
- package/dist/deltaStorageService.js.map +1 -1
- package/dist/documentService.d.ts +4 -2
- package/dist/documentService.d.ts.map +1 -1
- package/dist/documentService.js +20 -12
- package/dist/documentService.js.map +1 -1
- package/dist/documentServiceFactory.d.ts +2 -2
- package/dist/documentServiceFactory.d.ts.map +1 -1
- package/dist/documentServiceFactory.js +21 -12
- package/dist/documentServiceFactory.js.map +1 -1
- package/dist/documentStorageService.d.ts +3 -2
- package/dist/documentStorageService.d.ts.map +1 -1
- package/dist/documentStorageService.js +4 -4
- package/dist/documentStorageService.js.map +1 -1
- package/dist/errorUtils.d.ts +9 -2
- package/dist/errorUtils.d.ts.map +1 -1
- package/dist/errorUtils.js +15 -8
- package/dist/errorUtils.js.map +1 -1
- package/dist/gitManager.d.ts +30 -0
- package/dist/gitManager.d.ts.map +1 -0
- package/dist/gitManager.js +89 -0
- package/dist/gitManager.js.map +1 -0
- package/dist/historian.d.ts +33 -0
- package/dist/historian.d.ts.map +1 -0
- package/dist/historian.js +65 -0
- package/dist/historian.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/mapWithExpiration.d.ts +34 -0
- package/dist/mapWithExpiration.d.ts.map +1 -0
- package/dist/mapWithExpiration.js +105 -0
- package/dist/mapWithExpiration.js.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/restWrapper.d.ts +21 -8
- package/dist/restWrapper.d.ts.map +1 -1
- package/dist/restWrapper.js +93 -25
- package/dist/restWrapper.js.map +1 -1
- package/dist/restWrapperBase.d.ts +26 -0
- package/dist/restWrapperBase.d.ts.map +1 -0
- package/dist/restWrapperBase.js +55 -0
- package/dist/restWrapperBase.js.map +1 -0
- package/dist/retriableGitManager.d.ts +10 -21
- package/dist/retriableGitManager.d.ts.map +1 -1
- package/dist/retriableGitManager.js +0 -36
- package/dist/retriableGitManager.js.map +1 -1
- package/dist/shreddedSummaryDocumentStorageService.d.ts +1 -1
- package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/shreddedSummaryDocumentStorageService.js +6 -6
- package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/dist/storageContracts.d.ts +44 -0
- package/dist/storageContracts.d.ts.map +1 -0
- package/dist/storageContracts.js +7 -0
- package/dist/storageContracts.js.map +1 -0
- package/dist/summaryTreeUploadManager.d.ts +23 -0
- package/dist/summaryTreeUploadManager.d.ts.map +1 -0
- package/dist/summaryTreeUploadManager.js +110 -0
- package/dist/summaryTreeUploadManager.js.map +1 -0
- package/dist/tokens.d.ts +24 -7
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js.map +1 -1
- package/dist/treeUtils.d.ts +58 -0
- package/dist/treeUtils.d.ts.map +1 -0
- package/dist/treeUtils.js +107 -0
- package/dist/treeUtils.js.map +1 -0
- package/dist/wholeSummaryDocumentStorageService.d.ts +5 -4
- package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.js +70 -38
- package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
- package/dist/wholeSummaryUploadManager.d.ts +16 -0
- package/dist/wholeSummaryUploadManager.d.ts.map +1 -0
- package/dist/wholeSummaryUploadManager.js +38 -0
- package/dist/wholeSummaryUploadManager.js.map +1 -0
- package/lib/cache.js +1 -1
- package/lib/cache.js.map +1 -1
- package/lib/deltaStorageService.d.ts +1 -1
- package/lib/deltaStorageService.d.ts.map +1 -1
- package/lib/deltaStorageService.js +7 -4
- package/lib/deltaStorageService.js.map +1 -1
- package/lib/documentService.d.ts +4 -2
- package/lib/documentService.d.ts.map +1 -1
- package/lib/documentService.js +20 -12
- package/lib/documentService.js.map +1 -1
- package/lib/documentServiceFactory.d.ts +2 -2
- package/lib/documentServiceFactory.d.ts.map +1 -1
- package/lib/documentServiceFactory.js +22 -13
- package/lib/documentServiceFactory.js.map +1 -1
- package/lib/documentStorageService.d.ts +3 -2
- package/lib/documentStorageService.d.ts.map +1 -1
- package/lib/documentStorageService.js +4 -4
- package/lib/documentStorageService.js.map +1 -1
- package/lib/errorUtils.d.ts +9 -2
- package/lib/errorUtils.d.ts.map +1 -1
- package/lib/errorUtils.js +14 -7
- package/lib/errorUtils.js.map +1 -1
- package/lib/gitManager.d.ts +30 -0
- package/lib/gitManager.d.ts.map +1 -0
- package/lib/gitManager.js +85 -0
- package/lib/gitManager.js.map +1 -0
- package/lib/historian.d.ts +33 -0
- package/lib/historian.d.ts.map +1 -0
- package/lib/historian.js +60 -0
- package/lib/historian.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/mapWithExpiration.d.ts +34 -0
- package/lib/mapWithExpiration.d.ts.map +1 -0
- package/lib/mapWithExpiration.js +101 -0
- package/lib/mapWithExpiration.js.map +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/restWrapper.d.ts +21 -8
- package/lib/restWrapper.d.ts.map +1 -1
- package/lib/restWrapper.js +92 -26
- package/lib/restWrapper.js.map +1 -1
- package/lib/restWrapperBase.d.ts +26 -0
- package/lib/restWrapperBase.d.ts.map +1 -0
- package/lib/restWrapperBase.js +50 -0
- package/lib/restWrapperBase.js.map +1 -0
- package/lib/retriableGitManager.d.ts +10 -21
- package/lib/retriableGitManager.d.ts.map +1 -1
- package/lib/retriableGitManager.js +0 -36
- package/lib/retriableGitManager.js.map +1 -1
- package/lib/shreddedSummaryDocumentStorageService.d.ts +1 -1
- package/lib/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
- package/lib/shreddedSummaryDocumentStorageService.js +5 -5
- package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/lib/storageContracts.d.ts +44 -0
- package/lib/storageContracts.d.ts.map +1 -0
- package/lib/storageContracts.js +6 -0
- package/lib/storageContracts.js.map +1 -0
- package/lib/summaryTreeUploadManager.d.ts +23 -0
- package/lib/summaryTreeUploadManager.d.ts.map +1 -0
- package/lib/summaryTreeUploadManager.js +106 -0
- package/lib/summaryTreeUploadManager.js.map +1 -0
- package/lib/tokens.d.ts +24 -7
- package/lib/tokens.d.ts.map +1 -1
- package/lib/tokens.js.map +1 -1
- package/lib/treeUtils.d.ts +58 -0
- package/lib/treeUtils.d.ts.map +1 -0
- package/lib/treeUtils.js +100 -0
- package/lib/treeUtils.js.map +1 -0
- package/lib/wholeSummaryDocumentStorageService.d.ts +5 -4
- package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/lib/wholeSummaryDocumentStorageService.js +70 -38
- package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
- package/lib/wholeSummaryUploadManager.d.ts +16 -0
- package/lib/wholeSummaryUploadManager.d.ts.map +1 -0
- package/lib/wholeSummaryUploadManager.js +34 -0
- package/lib/wholeSummaryUploadManager.js.map +1 -0
- package/package.json +52 -54
- package/src/cache.ts +1 -1
- package/src/deltaStorageService.ts +11 -3
- package/src/documentService.ts +37 -22
- package/src/documentServiceFactory.ts +40 -21
- package/src/documentStorageService.ts +8 -4
- package/src/errorUtils.ts +16 -4
- package/src/gitManager.ts +116 -0
- package/src/historian.ts +121 -0
- package/src/index.ts +3 -0
- package/src/mapWithExpiration.ts +124 -0
- package/src/packageVersion.ts +1 -1
- package/src/restWrapper.ts +114 -38
- package/src/restWrapperBase.ts +146 -0
- package/src/retriableGitManager.ts +17 -95
- package/src/shreddedSummaryDocumentStorageService.ts +7 -9
- package/src/storageContracts.ts +63 -0
- package/src/summaryTreeUploadManager.ts +160 -0
- package/src/tokens.ts +24 -7
- package/src/treeUtils.ts +137 -0
- package/src/wholeSummaryDocumentStorageService.ts +118 -46
- package/src/wholeSummaryUploadManager.ts +64 -0
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type * as git from "@fluidframework/gitresources";
|
|
7
|
-
import type * as protocol from "@fluidframework/protocol-definitions";
|
|
8
7
|
import {
|
|
9
|
-
IGitManager,
|
|
10
8
|
IWholeFlatSummary,
|
|
11
9
|
IWholeSummaryPayload,
|
|
12
10
|
IWriteSummaryResponse,
|
|
13
11
|
} from "@fluidframework/server-services-client";
|
|
14
12
|
import { runWithRetry } from "@fluidframework/driver-utils";
|
|
15
13
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
14
|
+
import { IGitManager } from "./storageContracts";
|
|
15
|
+
import { IR11sResponse } from "./restWrapper";
|
|
16
16
|
|
|
17
17
|
export class RetriableGitManager implements IGitManager {
|
|
18
18
|
constructor(
|
|
@@ -20,135 +20,57 @@ export class RetriableGitManager implements IGitManager {
|
|
|
20
20
|
private readonly logger: ITelemetryLogger,
|
|
21
21
|
) {}
|
|
22
22
|
|
|
23
|
-
public async
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public async getFullTree(sha: string): Promise<any> {
|
|
31
|
-
return this.runWithRetry(
|
|
32
|
-
async () => this.internalGitManager.getFullTree(sha),
|
|
33
|
-
"gitManager_getFullTree",
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
public async getCommit(sha: string): Promise<git.ICommit> {
|
|
38
|
-
return this.runWithRetry(
|
|
39
|
-
async () => this.internalGitManager.getCommit(sha),
|
|
40
|
-
"gitManager_getCommit",
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
public async getCommits(sha: string, count: number): Promise<git.ICommitDetails[]> {
|
|
23
|
+
public async getCommits(
|
|
24
|
+
sha: string,
|
|
25
|
+
count: number,
|
|
26
|
+
): Promise<IR11sResponse<git.ICommitDetails[]>> {
|
|
45
27
|
return this.runWithRetry(
|
|
46
28
|
async () => this.internalGitManager.getCommits(sha, count),
|
|
47
29
|
"gitManager_getCommits",
|
|
48
30
|
);
|
|
49
31
|
}
|
|
50
32
|
|
|
51
|
-
public async getTree(root: string, recursive: boolean): Promise<git.ITree
|
|
33
|
+
public async getTree(root: string, recursive: boolean): Promise<IR11sResponse<git.ITree>> {
|
|
52
34
|
return this.runWithRetry(
|
|
53
35
|
async () => this.internalGitManager.getTree(root, recursive),
|
|
54
36
|
"gitManager_getTree",
|
|
55
37
|
);
|
|
56
38
|
}
|
|
57
39
|
|
|
58
|
-
public async getBlob(sha: string): Promise<git.IBlob
|
|
40
|
+
public async getBlob(sha: string): Promise<IR11sResponse<git.IBlob>> {
|
|
59
41
|
return this.runWithRetry(
|
|
60
42
|
async () => this.internalGitManager.getBlob(sha),
|
|
61
43
|
"gitManager_getBlob",
|
|
62
44
|
);
|
|
63
45
|
}
|
|
64
46
|
|
|
65
|
-
public
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
public async getContent(commit: string, path: string): Promise<git.IBlob> {
|
|
70
|
-
return this.runWithRetry(
|
|
71
|
-
async () => this.internalGitManager.getContent(commit, path),
|
|
72
|
-
"gitManager_getContent",
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public async createBlob(content: string, encoding: string): Promise<git.ICreateBlobResponse> {
|
|
47
|
+
public async createBlob(
|
|
48
|
+
content: string,
|
|
49
|
+
encoding: string,
|
|
50
|
+
): Promise<IR11sResponse<git.ICreateBlobResponse>> {
|
|
77
51
|
return this.runWithRetry(
|
|
78
52
|
async () => this.internalGitManager.createBlob(content, encoding),
|
|
79
53
|
"gitManager_createBlob",
|
|
80
54
|
);
|
|
81
55
|
}
|
|
82
56
|
|
|
83
|
-
public async createGitTree(params: git.ICreateTreeParams): Promise<git.ITree
|
|
57
|
+
public async createGitTree(params: git.ICreateTreeParams): Promise<IR11sResponse<git.ITree>> {
|
|
84
58
|
return this.runWithRetry(
|
|
85
59
|
async () => this.internalGitManager.createGitTree(params),
|
|
86
60
|
"gitManager_createGitTree",
|
|
87
61
|
);
|
|
88
62
|
}
|
|
89
63
|
|
|
90
|
-
public async
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"gitManager_createTree",
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public async createCommit(commit: git.ICreateCommitParams): Promise<git.ICommit> {
|
|
98
|
-
return this.runWithRetry(
|
|
99
|
-
async () => this.internalGitManager.createCommit(commit),
|
|
100
|
-
"gitManager_createCommit",
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
public async getRef(ref: string): Promise<git.IRef> {
|
|
105
|
-
return this.runWithRetry(
|
|
106
|
-
async () => this.internalGitManager.getRef(ref),
|
|
107
|
-
"gitManager_getRef",
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
public async createRef(branch: string, sha: string): Promise<git.IRef> {
|
|
112
|
-
return this.runWithRetry(
|
|
113
|
-
async () => this.internalGitManager.createRef(branch, sha),
|
|
114
|
-
"gitManager_createRef",
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
public async upsertRef(branch: string, commitSha: string): Promise<git.IRef> {
|
|
119
|
-
return this.runWithRetry(
|
|
120
|
-
async () => this.internalGitManager.upsertRef(branch, commitSha),
|
|
121
|
-
"gitManager_upsertRef",
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public async write(
|
|
126
|
-
branch: string,
|
|
127
|
-
inputTree: protocol.ITree,
|
|
128
|
-
parents: string[],
|
|
129
|
-
message: string,
|
|
130
|
-
): Promise<git.ICommit> {
|
|
131
|
-
return this.runWithRetry(
|
|
132
|
-
async () => this.internalGitManager.write(branch, inputTree, parents, message),
|
|
133
|
-
"gitManager_write",
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public async createSummary(summary: IWholeSummaryPayload): Promise<IWriteSummaryResponse> {
|
|
64
|
+
public async createSummary(
|
|
65
|
+
summary: IWholeSummaryPayload,
|
|
66
|
+
): Promise<IR11sResponse<IWriteSummaryResponse>> {
|
|
138
67
|
return this.runWithRetry(
|
|
139
68
|
async () => this.internalGitManager.createSummary(summary),
|
|
140
69
|
"gitManager_createSummary",
|
|
141
70
|
);
|
|
142
71
|
}
|
|
143
72
|
|
|
144
|
-
public async
|
|
145
|
-
return this.runWithRetry(
|
|
146
|
-
async () => this.internalGitManager.deleteSummary(softDelete),
|
|
147
|
-
"gitManager_deleteSummary",
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
public async getSummary(sha: string): Promise<IWholeFlatSummary> {
|
|
73
|
+
public async getSummary(sha: string): Promise<IR11sResponse<IWholeFlatSummary>> {
|
|
152
74
|
return this.runWithRetry(
|
|
153
75
|
async () => this.internalGitManager.getSummary(sha),
|
|
154
76
|
"gitManager_getSummary",
|
|
@@ -18,16 +18,14 @@ import {
|
|
|
18
18
|
ISummaryTree,
|
|
19
19
|
IVersion,
|
|
20
20
|
} from "@fluidframework/protocol-definitions";
|
|
21
|
-
import {
|
|
22
|
-
GitManager,
|
|
23
|
-
ISummaryUploadManager,
|
|
24
|
-
SummaryTreeUploadManager,
|
|
25
|
-
} from "@fluidframework/server-services-client";
|
|
26
21
|
import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
27
22
|
import { IRouterliciousDriverPolicies } from "./policies";
|
|
28
23
|
import { ICache, InMemoryCache } from "./cache";
|
|
29
24
|
import { RetriableGitManager } from "./retriableGitManager";
|
|
30
25
|
import { ISnapshotTreeVersion } from "./definitions";
|
|
26
|
+
import { GitManager } from "./gitManager";
|
|
27
|
+
import { ISummaryUploadManager } from "./storageContracts";
|
|
28
|
+
import { SummaryTreeUploadManager } from "./summaryTreeUploadManager";
|
|
31
29
|
|
|
32
30
|
const isNode = typeof window === "undefined";
|
|
33
31
|
|
|
@@ -85,7 +83,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
|
|
|
85
83
|
},
|
|
86
84
|
async () => {
|
|
87
85
|
const manager = await this.getStorageManager();
|
|
88
|
-
return manager.getCommits(id, count);
|
|
86
|
+
return (await manager.getCommits(id, count)).content;
|
|
89
87
|
},
|
|
90
88
|
);
|
|
91
89
|
return commits.map((commit) => ({
|
|
@@ -121,7 +119,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
|
|
|
121
119
|
},
|
|
122
120
|
async (event) => {
|
|
123
121
|
const manager = await this.getStorageManager();
|
|
124
|
-
const response = await manager.getTree(requestVersion!.treeId);
|
|
122
|
+
const response = (await manager.getTree(requestVersion!.treeId)).content;
|
|
125
123
|
event.end({
|
|
126
124
|
size: response.tree.length,
|
|
127
125
|
});
|
|
@@ -150,7 +148,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
|
|
|
150
148
|
},
|
|
151
149
|
async (event) => {
|
|
152
150
|
const manager = await this.getStorageManager();
|
|
153
|
-
const response = await manager.getBlob(blobId);
|
|
151
|
+
const response = (await manager.getBlob(blobId)).content;
|
|
154
152
|
event.end({
|
|
155
153
|
size: response.size,
|
|
156
154
|
});
|
|
@@ -203,7 +201,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
|
|
|
203
201
|
const manager = await this.getStorageManager();
|
|
204
202
|
const response = await manager
|
|
205
203
|
.createBlob(Uint8ArrayToString(uint8ArrayFile, "base64"), "base64")
|
|
206
|
-
.then((r) => ({ id: r.sha, url: r.url }));
|
|
204
|
+
.then((r) => ({ id: r.content.sha, url: r.content.url }));
|
|
207
205
|
event.end({
|
|
208
206
|
blobId: response.id,
|
|
209
207
|
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as git from "@fluidframework/gitresources";
|
|
7
|
+
import * as api from "@fluidframework/protocol-definitions";
|
|
8
|
+
import {
|
|
9
|
+
IWholeFlatSummary,
|
|
10
|
+
IWholeSummaryPayload,
|
|
11
|
+
IWholeSummaryPayloadType,
|
|
12
|
+
IWriteSummaryResponse,
|
|
13
|
+
} from "@fluidframework/server-services-client";
|
|
14
|
+
import { IR11sResponse } from "./restWrapper";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Interface to a generic Git provider
|
|
18
|
+
*/
|
|
19
|
+
export interface IHistorian {
|
|
20
|
+
getBlob(sha: string): Promise<IR11sResponse<git.IBlob>>;
|
|
21
|
+
createBlob(blob: git.ICreateBlobParams): Promise<IR11sResponse<git.ICreateBlobResponse>>;
|
|
22
|
+
getCommits(sha: string, count: number): Promise<IR11sResponse<git.ICommitDetails[]>>;
|
|
23
|
+
createTree(tree: git.ICreateTreeParams): Promise<IR11sResponse<git.ITree>>;
|
|
24
|
+
getTree(sha: string, recursive: boolean): Promise<IR11sResponse<git.ITree>>;
|
|
25
|
+
createSummary(
|
|
26
|
+
summary: IWholeSummaryPayload,
|
|
27
|
+
initial?: boolean,
|
|
28
|
+
): Promise<IR11sResponse<IWriteSummaryResponse>>;
|
|
29
|
+
getSummary(sha: string): Promise<IR11sResponse<IWholeFlatSummary>>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface IGitManager {
|
|
33
|
+
getCommits(sha: string, count: number): Promise<IR11sResponse<git.ICommitDetails[]>>;
|
|
34
|
+
getTree(root: string, recursive: boolean): Promise<IR11sResponse<git.ITree>>;
|
|
35
|
+
getBlob(sha: string): Promise<IR11sResponse<git.IBlob>>;
|
|
36
|
+
createBlob(content: string, encoding: string): Promise<IR11sResponse<git.ICreateBlobResponse>>;
|
|
37
|
+
createGitTree(params: git.ICreateTreeParams): Promise<IR11sResponse<git.ITree>>;
|
|
38
|
+
createSummary(
|
|
39
|
+
summary: IWholeSummaryPayload,
|
|
40
|
+
initial?: boolean,
|
|
41
|
+
): Promise<IR11sResponse<IWriteSummaryResponse>>;
|
|
42
|
+
getSummary(sha: string): Promise<IR11sResponse<IWholeFlatSummary>>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Uploads a summary to storage.
|
|
47
|
+
*/
|
|
48
|
+
export interface ISummaryUploadManager {
|
|
49
|
+
/**
|
|
50
|
+
* Writes summary tree to storage.
|
|
51
|
+
* @param summaryTree - Summary tree to write to storage
|
|
52
|
+
* @param parentHandle - Parent summary acked handle (if available from summary ack)
|
|
53
|
+
* @param summaryType - type of summary being uploaded
|
|
54
|
+
* @param sequenceNumber - optional reference sequence number of the summary
|
|
55
|
+
* @returns Id of created tree as a string.
|
|
56
|
+
*/
|
|
57
|
+
writeSummaryTree(
|
|
58
|
+
summaryTree: api.ISummaryTree,
|
|
59
|
+
parentHandle: string,
|
|
60
|
+
summaryType: IWholeSummaryPayloadType,
|
|
61
|
+
sequenceNumber?: number,
|
|
62
|
+
): Promise<string>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
assert,
|
|
8
|
+
gitHashFile,
|
|
9
|
+
IsoBuffer,
|
|
10
|
+
Uint8ArrayToString,
|
|
11
|
+
unreachableCase,
|
|
12
|
+
} from "@fluidframework/common-utils";
|
|
13
|
+
import { ICreateTreeEntry } from "@fluidframework/gitresources";
|
|
14
|
+
import { getGitMode, getGitType } from "@fluidframework/protocol-base";
|
|
15
|
+
import {
|
|
16
|
+
ISnapshotTreeEx,
|
|
17
|
+
ISummaryTree,
|
|
18
|
+
SummaryObject,
|
|
19
|
+
SummaryType,
|
|
20
|
+
} from "@fluidframework/protocol-definitions";
|
|
21
|
+
import { IWholeSummaryPayloadType } from "@fluidframework/server-services-client";
|
|
22
|
+
import { IGitManager, ISummaryUploadManager } from "./storageContracts";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Recursively writes summary tree as individual summary blobs.
|
|
26
|
+
*/
|
|
27
|
+
export class SummaryTreeUploadManager implements ISummaryUploadManager {
|
|
28
|
+
constructor(
|
|
29
|
+
private readonly manager: IGitManager,
|
|
30
|
+
private readonly blobsShaCache: Map<string, string>,
|
|
31
|
+
private readonly getPreviousFullSnapshot: (
|
|
32
|
+
parentHandle: string,
|
|
33
|
+
) => Promise<ISnapshotTreeEx | null | undefined>,
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
public async writeSummaryTree(
|
|
37
|
+
summaryTree: ISummaryTree,
|
|
38
|
+
parentHandle: string,
|
|
39
|
+
summaryType: IWholeSummaryPayloadType,
|
|
40
|
+
sequenceNumber?: number,
|
|
41
|
+
initial?: boolean,
|
|
42
|
+
): Promise<string> {
|
|
43
|
+
const previousFullSnapshot = await this.getPreviousFullSnapshot(parentHandle);
|
|
44
|
+
return this.writeSummaryTreeCore(summaryTree, previousFullSnapshot ?? undefined);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private async writeSummaryTreeCore(
|
|
48
|
+
summaryTree: ISummaryTree,
|
|
49
|
+
previousFullSnapshot: ISnapshotTreeEx | undefined,
|
|
50
|
+
): Promise<string> {
|
|
51
|
+
const entries = await Promise.all(
|
|
52
|
+
Object.keys(summaryTree.tree).map(async (key) => {
|
|
53
|
+
const entry = summaryTree.tree[key];
|
|
54
|
+
const pathHandle = await this.writeSummaryTreeObject(entry, previousFullSnapshot);
|
|
55
|
+
const treeEntry: ICreateTreeEntry = {
|
|
56
|
+
mode: getGitMode(entry),
|
|
57
|
+
path: encodeURIComponent(key),
|
|
58
|
+
sha: pathHandle,
|
|
59
|
+
type: getGitType(entry),
|
|
60
|
+
};
|
|
61
|
+
return treeEntry;
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const treeHandle = (await this.manager.createGitTree({ tree: entries })).content;
|
|
66
|
+
return treeHandle.sha;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private async writeSummaryTreeObject(
|
|
70
|
+
object: SummaryObject,
|
|
71
|
+
previousFullSnapshot: ISnapshotTreeEx | undefined,
|
|
72
|
+
): Promise<string> {
|
|
73
|
+
switch (object.type) {
|
|
74
|
+
case SummaryType.Blob: {
|
|
75
|
+
return this.writeSummaryBlob(object.content);
|
|
76
|
+
}
|
|
77
|
+
case SummaryType.Handle: {
|
|
78
|
+
if (previousFullSnapshot === undefined) {
|
|
79
|
+
throw Error("Parent summary does not exist to reference by handle.");
|
|
80
|
+
}
|
|
81
|
+
return this.getIdFromPath(object.handleType, object.handle, previousFullSnapshot);
|
|
82
|
+
}
|
|
83
|
+
case SummaryType.Tree: {
|
|
84
|
+
return this.writeSummaryTreeCore(object, previousFullSnapshot);
|
|
85
|
+
}
|
|
86
|
+
case SummaryType.Attachment: {
|
|
87
|
+
return object.id;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
default:
|
|
91
|
+
unreachableCase(object, `Unknown type: ${(object as any).type}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private async writeSummaryBlob(content: string | Uint8Array): Promise<string> {
|
|
96
|
+
const { parsedContent, encoding } =
|
|
97
|
+
typeof content === "string"
|
|
98
|
+
? { parsedContent: content, encoding: "utf-8" }
|
|
99
|
+
: { parsedContent: Uint8ArrayToString(content, "base64"), encoding: "base64" };
|
|
100
|
+
|
|
101
|
+
// The gitHashFile would return the same hash as returned by the server as blob.sha
|
|
102
|
+
const hash = await gitHashFile(IsoBuffer.from(parsedContent, encoding));
|
|
103
|
+
if (!this.blobsShaCache.has(hash)) {
|
|
104
|
+
this.blobsShaCache.set(hash, "");
|
|
105
|
+
const blob = (await this.manager.createBlob(parsedContent, encoding)).content;
|
|
106
|
+
assert(hash === blob.sha, 0x0b6 /* "Blob.sha and hash do not match!!" */);
|
|
107
|
+
}
|
|
108
|
+
return hash;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private getIdFromPath(
|
|
112
|
+
handleType: SummaryType,
|
|
113
|
+
handlePath: string,
|
|
114
|
+
previousFullSnapshot: ISnapshotTreeEx,
|
|
115
|
+
): string {
|
|
116
|
+
const path = handlePath.split("/").map((part) => decodeURIComponent(part));
|
|
117
|
+
if (path[0] === "") {
|
|
118
|
+
// root of tree should be unnamed
|
|
119
|
+
path.shift();
|
|
120
|
+
}
|
|
121
|
+
if (path.length === 0) {
|
|
122
|
+
return previousFullSnapshot.id;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return this.getIdFromPathCore(handleType, path, previousFullSnapshot);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private getIdFromPathCore(
|
|
129
|
+
handleType: SummaryType,
|
|
130
|
+
path: string[],
|
|
131
|
+
/** Previous snapshot, subtree relative to this path part */
|
|
132
|
+
previousSnapshot: ISnapshotTreeEx,
|
|
133
|
+
): string {
|
|
134
|
+
assert(path.length > 0, 0x0b3 /* "Expected at least 1 path part" */);
|
|
135
|
+
const key = path[0];
|
|
136
|
+
if (path.length === 1) {
|
|
137
|
+
switch (handleType) {
|
|
138
|
+
case SummaryType.Blob: {
|
|
139
|
+
const tryId = previousSnapshot.blobs[key];
|
|
140
|
+
assert(
|
|
141
|
+
!!tryId,
|
|
142
|
+
0x0b4 /* "Parent summary does not have blob handle for specified path." */,
|
|
143
|
+
);
|
|
144
|
+
return tryId;
|
|
145
|
+
}
|
|
146
|
+
case SummaryType.Tree: {
|
|
147
|
+
const tryId = previousSnapshot.trees[key]?.id;
|
|
148
|
+
assert(
|
|
149
|
+
!!tryId,
|
|
150
|
+
0x0b5 /* "Parent summary does not have tree handle for specified path." */,
|
|
151
|
+
);
|
|
152
|
+
return tryId;
|
|
153
|
+
}
|
|
154
|
+
default:
|
|
155
|
+
throw Error(`Unexpected handle summary object type: "${handleType}".`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return this.getIdFromPathCore(handleType, path.slice(1), previousSnapshot.trees[key]);
|
|
159
|
+
}
|
|
160
|
+
}
|
package/src/tokens.ts
CHANGED
|
@@ -6,9 +6,13 @@
|
|
|
6
6
|
import { ITokenClaims } from "@fluidframework/protocol-definitions";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Abstracts the discovery of claims contained within a token.
|
|
10
10
|
*/
|
|
11
11
|
export interface ITokenService {
|
|
12
|
+
/**
|
|
13
|
+
* Extracts the {@link @fluidframework/protocol-definitions#ITokenClaims | token claims} from the provided
|
|
14
|
+
* {@link https://jwt.io/introduction/ | JSON Web Token (JWT)} string representation.
|
|
15
|
+
*/
|
|
12
16
|
extractClaims(token: string): ITokenClaims;
|
|
13
17
|
}
|
|
14
18
|
|
|
@@ -19,8 +23,9 @@ export interface ITokenResponse {
|
|
|
19
23
|
jwt: string;
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
26
|
+
* A flag indicating whether token was obtained from local cache.
|
|
27
|
+
*
|
|
28
|
+
* @remarks `undefined` indicates that the source of the token could not be determined.
|
|
24
29
|
*/
|
|
25
30
|
fromCache?: boolean;
|
|
26
31
|
}
|
|
@@ -32,11 +37,16 @@ export interface ITokenResponse {
|
|
|
32
37
|
export interface ITokenProvider {
|
|
33
38
|
/**
|
|
34
39
|
* Fetches the orderer token from host.
|
|
40
|
+
*
|
|
35
41
|
* @param tenantId - Tenant ID.
|
|
36
42
|
* @param documentId - Optional. Document ID is only required for document-scoped requests.
|
|
37
43
|
* @param refresh - Optional flag indicating whether token fetch must bypass local cache.
|
|
38
|
-
*
|
|
39
|
-
*
|
|
44
|
+
* This likely indicates that some previous request failed authorization due to an expired token,
|
|
45
|
+
* and so a fresh token is required.
|
|
46
|
+
*
|
|
47
|
+
* Default: `false`.
|
|
48
|
+
*
|
|
49
|
+
* NOTE: This parameter will be made required in the future.
|
|
40
50
|
*/
|
|
41
51
|
fetchOrdererToken(
|
|
42
52
|
tenantId: string,
|
|
@@ -46,11 +56,16 @@ export interface ITokenProvider {
|
|
|
46
56
|
|
|
47
57
|
/**
|
|
48
58
|
* Fetches the storage token from host.
|
|
59
|
+
*
|
|
49
60
|
* @param tenantId - Tenant ID.
|
|
50
61
|
* @param documentId - Document ID.
|
|
51
62
|
* @param refresh - Optional flag indicating whether token fetch must bypass local cache.
|
|
52
|
-
*
|
|
53
|
-
*
|
|
63
|
+
* This likely indicates that some previous request failed authorization due to an expired token,
|
|
64
|
+
* and so a fresh token is required.
|
|
65
|
+
*
|
|
66
|
+
* Default: `false`.
|
|
67
|
+
*
|
|
68
|
+
* NOTE: This parameter will be made required in the future.
|
|
54
69
|
*/
|
|
55
70
|
fetchStorageToken(
|
|
56
71
|
tenantId: string,
|
|
@@ -64,7 +79,9 @@ export interface ITokenProvider {
|
|
|
64
79
|
* created it.
|
|
65
80
|
*
|
|
66
81
|
* @remarks Notes:
|
|
82
|
+
*
|
|
67
83
|
* * Using the callback may have performance impact on the document creation process.
|
|
84
|
+
*
|
|
68
85
|
* * Any exceptions thrown in the callback would fail the creation workflow
|
|
69
86
|
* (see {@link RouterliciousDocumentServiceFactory.createContainer} for more details).
|
|
70
87
|
*
|
package/src/treeUtils.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { assert, IsoBuffer } from "@fluidframework/common-utils";
|
|
7
|
+
import {
|
|
8
|
+
SummaryType,
|
|
9
|
+
ISnapshotTree,
|
|
10
|
+
ISummaryTree,
|
|
11
|
+
SummaryObject,
|
|
12
|
+
} from "@fluidframework/protocol-definitions";
|
|
13
|
+
import { INormalizedWholeSummary } from "@fluidframework/server-services-client";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Summary tree assembler props
|
|
17
|
+
*/
|
|
18
|
+
export interface ISummaryTreeAssemblerProps {
|
|
19
|
+
/**
|
|
20
|
+
* Indicates that this tree is unreferenced. If this is not present, the tree is considered referenced.
|
|
21
|
+
*/
|
|
22
|
+
unreferenced?: true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Summary tree assembler (without stats collection).
|
|
27
|
+
*/
|
|
28
|
+
export class SummaryTreeAssembler {
|
|
29
|
+
private attachmentCounter: number = 0;
|
|
30
|
+
private readonly summaryTree: { [path: string]: SummaryObject } = {};
|
|
31
|
+
|
|
32
|
+
constructor(private readonly props?: ISummaryTreeAssemblerProps) {}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get final summary
|
|
36
|
+
*/
|
|
37
|
+
public get summary(): ISummaryTree {
|
|
38
|
+
return {
|
|
39
|
+
type: SummaryType.Tree,
|
|
40
|
+
tree: { ...this.summaryTree },
|
|
41
|
+
unreferenced: this.props?.unreferenced,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Add blob to summary
|
|
47
|
+
*/
|
|
48
|
+
public addBlob(key: string, content: string | Uint8Array): void {
|
|
49
|
+
this.summaryTree[key] = {
|
|
50
|
+
type: SummaryType.Blob,
|
|
51
|
+
content,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Add handle to summary
|
|
57
|
+
*/
|
|
58
|
+
public addHandle(
|
|
59
|
+
key: string,
|
|
60
|
+
handleType: SummaryType.Tree | SummaryType.Blob | SummaryType.Attachment,
|
|
61
|
+
handle: string,
|
|
62
|
+
): void {
|
|
63
|
+
this.summaryTree[key] = {
|
|
64
|
+
type: SummaryType.Handle,
|
|
65
|
+
handleType,
|
|
66
|
+
handle,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Add tree to summary
|
|
72
|
+
*/
|
|
73
|
+
public addTree(key: string, summary: ISummaryTree): void {
|
|
74
|
+
this.summaryTree[key] = summary;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Add attachment to summary
|
|
79
|
+
*/
|
|
80
|
+
public addAttachment(id: string) {
|
|
81
|
+
this.summaryTree[this.attachmentCounter++] = { id, type: SummaryType.Attachment };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Helper function that converts ISnapshotTree and blobs to ISummaryTree
|
|
87
|
+
* @param snapshot - Source snapshot tree
|
|
88
|
+
* @param blobs - Blobs cache
|
|
89
|
+
* @returns Converted snapshot in ISummaryTree format
|
|
90
|
+
*/
|
|
91
|
+
export function convertSnapshotAndBlobsToSummaryTree(
|
|
92
|
+
snapshot: ISnapshotTree,
|
|
93
|
+
blobs: Map<string, ArrayBuffer>,
|
|
94
|
+
): ISummaryTree {
|
|
95
|
+
const assembler = new SummaryTreeAssembler({
|
|
96
|
+
unreferenced: snapshot.unreferenced,
|
|
97
|
+
});
|
|
98
|
+
for (const [path, id] of Object.entries(snapshot.blobs)) {
|
|
99
|
+
const blob = blobs.get(id);
|
|
100
|
+
assert(blob !== undefined, 0x2dd /* "Cannot find blob for a given id" */);
|
|
101
|
+
assembler.addBlob(path, IsoBuffer.from(blob).toString("utf-8"));
|
|
102
|
+
}
|
|
103
|
+
for (const [key, tree] of Object.entries(snapshot.trees)) {
|
|
104
|
+
const subtree = convertSnapshotAndBlobsToSummaryTree(tree, blobs);
|
|
105
|
+
assembler.addTree(key, subtree);
|
|
106
|
+
}
|
|
107
|
+
return assembler.summary;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function evalBlobsAndTrees(snapshot: INormalizedWholeSummary) {
|
|
111
|
+
const trees = countTreesInSnapshotTree(snapshot.snapshotTree);
|
|
112
|
+
const numBlobs = snapshot.blobs.size;
|
|
113
|
+
let encodedBlobsSize = 0;
|
|
114
|
+
for (const [_, blobContent] of snapshot.blobs) {
|
|
115
|
+
encodedBlobsSize += blobContent.byteLength;
|
|
116
|
+
}
|
|
117
|
+
return { trees, numBlobs, encodedBlobsSize };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function validateBlobsAndTrees(snapshot: ISnapshotTree) {
|
|
121
|
+
assert(
|
|
122
|
+
snapshot.trees !== undefined,
|
|
123
|
+
0x5d0 /* Returned r11s snapshot is malformed. No trees! */,
|
|
124
|
+
);
|
|
125
|
+
assert(
|
|
126
|
+
snapshot.blobs !== undefined,
|
|
127
|
+
0x5d1 /* Returned r11s snapshot is malformed. No blobs! */,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {
|
|
132
|
+
let numTrees = 0;
|
|
133
|
+
for (const [_, tree] of Object.entries(snapshotTree.trees)) {
|
|
134
|
+
numTrees += 1 + countTreesInSnapshotTree(tree);
|
|
135
|
+
}
|
|
136
|
+
return numTrees;
|
|
137
|
+
}
|