@fluid-tools/fetch-tool 2.1.0-276326 → 2.1.0-276985
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/README.md +2 -2
- package/dist/fluidFetchArgs.d.ts +1 -1
- package/dist/fluidFetchArgs.d.ts.map +1 -1
- package/dist/fluidFetchArgs.js +5 -13
- package/dist/fluidFetchArgs.js.map +1 -1
- package/dist/fluidFetchInit.d.ts.map +1 -1
- package/dist/fluidFetchInit.js +1 -1
- package/dist/fluidFetchInit.js.map +1 -1
- package/dist/fluidFetchMessages.d.ts.map +1 -1
- package/dist/fluidFetchMessages.js +21 -10
- package/dist/fluidFetchMessages.js.map +1 -1
- package/dist/fluidFetchSharePoint.d.ts +1 -1
- package/dist/fluidFetchSharePoint.d.ts.map +1 -1
- package/dist/fluidFetchSharePoint.js +35 -35
- package/dist/fluidFetchSharePoint.js.map +1 -1
- package/lib/fluidFetchArgs.d.ts +1 -1
- package/lib/fluidFetchArgs.d.ts.map +1 -1
- package/lib/fluidFetchArgs.js +5 -11
- package/lib/fluidFetchArgs.js.map +1 -1
- package/lib/fluidFetchInit.d.ts.map +1 -1
- package/lib/fluidFetchInit.js +1 -1
- package/lib/fluidFetchInit.js.map +1 -1
- package/lib/fluidFetchMessages.d.ts.map +1 -1
- package/lib/fluidFetchMessages.js +21 -10
- package/lib/fluidFetchMessages.js.map +1 -1
- package/lib/fluidFetchSharePoint.d.ts +1 -1
- package/lib/fluidFetchSharePoint.d.ts.map +1 -1
- package/lib/fluidFetchSharePoint.js +37 -34
- package/lib/fluidFetchSharePoint.js.map +1 -1
- package/package.json +17 -15
- package/src/fluidFetchArgs.ts +5 -13
- package/src/fluidFetchInit.ts +0 -2
- package/src/fluidFetchMessages.ts +27 -11
- package/src/fluidFetchSharePoint.ts +40 -47
|
@@ -96,28 +96,44 @@ async function* loadAllSequencedMessages(
|
|
|
96
96
|
let requests = 0;
|
|
97
97
|
let opsStorage = 0;
|
|
98
98
|
|
|
99
|
+
console.log("fetching cached messages");
|
|
99
100
|
// reading only 1 op to test if there is mismatch
|
|
100
101
|
const teststream = deltaStorage.fetchMessages(lastSeq + 1, lastSeq + 2);
|
|
101
102
|
|
|
102
|
-
let statusCode;
|
|
103
|
-
let innerMostErrorCode;
|
|
104
|
-
let response;
|
|
105
|
-
|
|
106
103
|
try {
|
|
107
104
|
await teststream.read();
|
|
108
105
|
} catch (error: any) {
|
|
109
|
-
statusCode = error.getTelemetryProperties().statusCode;
|
|
110
|
-
innerMostErrorCode = error.getTelemetryProperties().innerMostErrorCode;
|
|
111
|
-
// if there is gap between ops, catch the error and check it is the error we need
|
|
106
|
+
const statusCode = error.getTelemetryProperties().statusCode;
|
|
107
|
+
const innerMostErrorCode = error.getTelemetryProperties().innerMostErrorCode;
|
|
112
108
|
if (statusCode !== 410 || innerMostErrorCode !== "fluidDeltaDataNotAvailable") {
|
|
113
109
|
throw error;
|
|
114
110
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
|
|
112
|
+
// This indicates we tried to fetch ops from storage that have been deleted (because they are past some retention policy).
|
|
113
|
+
// In that case, the error message should indicate the first sequence number that is available.
|
|
114
|
+
// We make a best-effort attempt for the original query (fetch all ops) by starting from that sequence number.
|
|
115
|
+
const props = error.getTelemetryProperties();
|
|
116
|
+
const { responseMessage } = props;
|
|
117
|
+
const [_, seq] =
|
|
118
|
+
typeof responseMessage === "string"
|
|
119
|
+
? responseMessage.match(/GenesisSequenceNumber '(\d+)'/) ?? []
|
|
120
|
+
: [];
|
|
121
|
+
if (seq !== undefined) {
|
|
122
|
+
lastSeq = parseInt(seq, 10);
|
|
123
|
+
firstAvailableDelta = lastSeq + 1;
|
|
124
|
+
console.log(
|
|
125
|
+
`Not all ops are available (older ops may have been deleted from storage). Starting from sequenceNumber: ${firstAvailableDelta}.`,
|
|
126
|
+
);
|
|
127
|
+
} else {
|
|
128
|
+
console.log(props);
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Unexpected structure for 410 error: ${error.message}. Further error properties were logged above. This indicates a problem with fetch-tool.`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
119
133
|
}
|
|
120
134
|
|
|
135
|
+
console.log("fetching remaining messages from delta storage");
|
|
136
|
+
|
|
121
137
|
// continue reading rest of the ops
|
|
122
138
|
const stream = deltaStorage.fetchMessages(
|
|
123
139
|
lastSeq + 1, // inclusive left
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
|
|
6
|
+
import { InteractiveBrowserCredential, useIdentityPlugin } from "@azure/identity";
|
|
7
|
+
import { cachePersistencePlugin } from "@azure/identity-cache-persistence";
|
|
8
8
|
import { DriverErrorTypes } from "@fluidframework/driver-definitions/internal";
|
|
9
9
|
import {
|
|
10
10
|
IPublicClientConfig,
|
|
@@ -13,16 +13,16 @@ import {
|
|
|
13
13
|
getChildrenByDriveItem,
|
|
14
14
|
getDriveItemByServerRelativePath,
|
|
15
15
|
getDriveItemFromDriveAndItem,
|
|
16
|
-
|
|
16
|
+
getAadTenant,
|
|
17
|
+
getOdspScope,
|
|
17
18
|
} from "@fluidframework/odsp-doclib-utils/internal";
|
|
18
|
-
import {
|
|
19
|
-
IOdspTokenManagerCacheKey,
|
|
20
|
-
OdspTokenConfig,
|
|
21
|
-
OdspTokenManager,
|
|
22
|
-
odspTokensCache,
|
|
23
|
-
} from "@fluidframework/tool-utils/internal";
|
|
24
19
|
|
|
25
|
-
import {
|
|
20
|
+
import { loginHint } from "./fluidFetchArgs.js";
|
|
21
|
+
|
|
22
|
+
// Note: the following page may be helpful for debugging auth issues:
|
|
23
|
+
// https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/identity/identity/TROUBLESHOOTING.md
|
|
24
|
+
// See e.g. the section on setting 'AZURE_LOG_LEVEL'.
|
|
25
|
+
useIdentityPlugin(cachePersistencePlugin);
|
|
26
26
|
|
|
27
27
|
export const fetchToolClientConfig: IPublicClientConfig = {
|
|
28
28
|
get clientId(): string {
|
|
@@ -41,40 +41,43 @@ export async function resolveWrapper<T>(
|
|
|
41
41
|
server: string,
|
|
42
42
|
clientConfig: IPublicClientConfig,
|
|
43
43
|
forceTokenReauth = false,
|
|
44
|
-
forToken = false,
|
|
45
44
|
): Promise<T> {
|
|
46
45
|
try {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
const credential = new InteractiveBrowserCredential({
|
|
47
|
+
clientId: fetchToolClientConfig.clientId,
|
|
48
|
+
tenantId: getAadTenant(server),
|
|
49
|
+
// NOTE: fetch-tool flows using multiple sets of user credentials haven't been well-tested.
|
|
50
|
+
// Some of the @azure/identity docs suggest we may need to manage authentication records and choose
|
|
51
|
+
// which one to use explicitly here if we have such scenarios.
|
|
52
|
+
// If we start doing this, it may be worth considering using disableAutomaticAuthentication here so we
|
|
53
|
+
// have better control over when interactive auth may be triggered.
|
|
54
|
+
// For now, fetch-tool doesn't work against personal accounts anyway so the only flow that might necessitate this
|
|
55
|
+
// would be grabbing documents using several identities (e.g. test accounts we use for stress testing).
|
|
56
|
+
// In that case, a simple workaround is to delete the cache that @azure/identity uses before running the tool.
|
|
57
|
+
// See docs on `tokenCachePersistenceOptions.name` for information on where this cache is stored.
|
|
58
|
+
loginHint,
|
|
59
|
+
tokenCachePersistenceOptions: {
|
|
60
|
+
enabled: true,
|
|
61
|
+
name: "fetch-tool",
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const scope = getOdspScope(server);
|
|
59
66
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
const { token } = await credential.getToken(scope);
|
|
68
|
+
|
|
69
|
+
return await callback({
|
|
70
|
+
accessToken: token,
|
|
71
|
+
refreshTokenFn: async () => {
|
|
72
|
+
await credential.authenticate(scope);
|
|
73
|
+
const result = await credential.getToken(scope);
|
|
74
|
+
return result.token;
|
|
75
|
+
},
|
|
63
76
|
});
|
|
64
|
-
// If this is used for getting a token, then refresh the cache with new token.
|
|
65
|
-
if (forToken) {
|
|
66
|
-
const key: IOdspTokenManagerCacheKey = { isPush: false, userOrServer: server };
|
|
67
|
-
await odspTokenManager.updateTokensCache(key, {
|
|
68
|
-
accessToken: result as any as string,
|
|
69
|
-
refreshToken: tokens.refreshToken,
|
|
70
|
-
});
|
|
71
|
-
return result;
|
|
72
|
-
}
|
|
73
|
-
return result;
|
|
74
77
|
} catch (e: any) {
|
|
75
78
|
if (e.errorType === DriverErrorTypes.authorizationError && !forceTokenReauth) {
|
|
76
79
|
// Re-auth
|
|
77
|
-
return resolveWrapper<T>(callback, server, clientConfig, true
|
|
80
|
+
return resolveWrapper<T>(callback, server, clientConfig, true);
|
|
78
81
|
}
|
|
79
82
|
throw e;
|
|
80
83
|
}
|
|
@@ -156,13 +159,3 @@ export async function getSingleSharePointFile(server: string, drive: string, ite
|
|
|
156
159
|
fetchToolClientConfig,
|
|
157
160
|
);
|
|
158
161
|
}
|
|
159
|
-
|
|
160
|
-
const fluidFetchWebNavigator = (url: string) => {
|
|
161
|
-
let message = "Please open browser and navigate to this URL:";
|
|
162
|
-
if (process.platform === "win32") {
|
|
163
|
-
child_process.exec(`start "fluid-fetch" /B "${url}"`);
|
|
164
|
-
message =
|
|
165
|
-
"Opening browser to get authorization code. If that doesn't open, please go to this URL manually";
|
|
166
|
-
}
|
|
167
|
-
console.log(`${message}\n ${url}`);
|
|
168
|
-
};
|