@adobe/helix-onedrive-support 7.1.2 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.eslintrc.cjs +33 -0
  2. package/.husky/pre-commit +4 -0
  3. package/.jsdoc.json +4 -2
  4. package/.nycrc.json +4 -3
  5. package/.releaserc.cjs +16 -0
  6. package/CHANGELOG.md +35 -0
  7. package/docs/API.md +106 -341
  8. package/package.json +20 -20
  9. package/src/OneDrive.d.ts +4 -72
  10. package/src/OneDrive.js +62 -326
  11. package/src/OneDriveAuth.d.ts +98 -0
  12. package/src/OneDriveAuth.js +310 -0
  13. package/src/OneDriveMock.js +19 -12
  14. package/src/SharePointSite.js +5 -7
  15. package/src/StatusCodeError.js +2 -4
  16. package/src/cache/FSCacheManager.d.ts +28 -0
  17. package/src/cache/FSCacheManager.js +77 -0
  18. package/src/cache/FSCachePlugin.d.ts +29 -0
  19. package/src/cache/FSCachePlugin.js +70 -0
  20. package/src/cache/MemCachePlugin.d.ts +34 -0
  21. package/src/cache/MemCachePlugin.js +88 -0
  22. package/src/cache/S3CacheManager.d.ts +40 -0
  23. package/src/cache/S3CacheManager.js +107 -0
  24. package/src/cache/S3CachePlugin.d.ts +49 -0
  25. package/src/cache/S3CachePlugin.js +116 -0
  26. package/src/cache/encrypt.js +70 -0
  27. package/src/{NamedItem.d.ts → excel/NamedItem.d.ts} +0 -0
  28. package/src/{NamedItemContainer.js → excel/NamedItemContainer.js} +3 -5
  29. package/src/{Range.d.ts → excel/Range.d.ts} +2 -2
  30. package/src/{Range.js → excel/Range.js} +3 -5
  31. package/src/{Table.d.ts → excel/Table.d.ts} +2 -2
  32. package/src/{Table.js → excel/Table.js} +3 -5
  33. package/src/{Workbook.d.ts → excel/Workbook.d.ts} +2 -2
  34. package/src/{Workbook.js → excel/Workbook.js} +5 -10
  35. package/src/{Worksheet.d.ts → excel/Worksheet.d.ts} +4 -4
  36. package/src/{Worksheet.js → excel/Worksheet.js} +5 -10
  37. package/src/index.d.ts +14 -5
  38. package/src/index.js +9 -7
  39. package/src/package.cjs +12 -0
  40. package/src/utils.js +95 -45
  41. package/src/fuzzy-helper.js +0 -89
@@ -0,0 +1,98 @@
1
+ /*
2
+ * Copyright 2022 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import {AuthenticationResult, ClientApplication, ICachePlugin} from "@azure/msal-node";
13
+
14
+ export declare interface OneDriveAuthOptions {
15
+ clientId: string;
16
+ clientSecret?: string;
17
+ refreshToken?: string;
18
+ log?: Console;
19
+ tenant?: string;
20
+ scopes?: string[];
21
+ localAuthCache?:boolean;
22
+
23
+ /**
24
+ * use cache plugin instead for default (global) token cache.
25
+ */
26
+ cachePlugin?: ICachePlugin,
27
+
28
+ /**
29
+ * Disables the cache for the tenant lookup.
30
+ * @default process.env.HELIX_ONEDRIVE_NO_TENANT_CACHE
31
+ */
32
+ noTenantCache?: boolean;
33
+
34
+ /**
35
+ * Map to use for the tenant lookup cache. If empty, a module-global cache will be used.
36
+ * Note that the cache is only used, if the `noTenantCache` flag is `falsy`
37
+ */
38
+ tenantCache?: Map<string, string>;
39
+ }
40
+
41
+ /**
42
+ * Helper class that facilitates authentication for one drive.
43
+ */
44
+ export declare class OneDriveAuth {
45
+ /**
46
+ * Creates a new OneDriveAuth helper.
47
+ * @param {OneDriveAuthOptions} opts Options.
48
+ */
49
+ constructor(opts: OneDriveAuthOptions);
50
+
51
+ /**
52
+ * {@code true} if this client is initialized.
53
+ */
54
+ isAuthenticated(): boolean;
55
+
56
+ /**
57
+ * the logger of this client
58
+ */
59
+ log: Console;
60
+
61
+ /**
62
+ * the MSAL client application
63
+ */
64
+ app: ClientApplication;
65
+
66
+ /**
67
+ * the authority url for login.
68
+ */
69
+ getAuthorityUrl(): string;
70
+
71
+ /**
72
+ * Performs a login using an interactive flow which prompts the user to open a browser window and
73
+ * enter the authorization code.
74
+ * @params {function} [onCode] - optional function that gets invoked after code was retrieved.
75
+ * @returns {Promise<AuthenticationResult>}
76
+ */
77
+ acquireTokenByDeviceCode(onCode: Function): Promise<AuthenticationResult>;
78
+
79
+ /**
80
+ * Sets the access token to use for all requests. if the token is a valid JWT token,
81
+ * its `tid` claim is used a tenant (if no tenant is already set).
82
+ *
83
+ * @param {string} bearerToken
84
+ * @returns {OneDriveAuth} this
85
+ */
86
+ setAccessToken(bearerToken): OneDriveAuth;
87
+
88
+ /**
89
+ * Acquires the access token either from the cache or from MS.
90
+ * @param {boolean} silentOnly
91
+ * @returns {Promise<AuthenticationResult>}
92
+ */
93
+ authenticate(silentOnly: boolean): Promise<AuthenticationResult>;
94
+
95
+ dispose() : Promise<void>;
96
+
97
+ initTenantFromUrl(sharingUrl: string|URL): Promise<void>;
98
+ }
@@ -0,0 +1,310 @@
1
+ /*
2
+ * Copyright 2019 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ // eslint-disable-next-line max-classes-per-file
14
+ import { keepAliveNoCache } from '@adobe/helix-fetch';
15
+ import { ConfidentialClientApplication, LogLevel } from '@azure/msal-node';
16
+ import { decodeJwt } from 'jose';
17
+ import { MemCachePlugin } from './cache/MemCachePlugin.js';
18
+ import { StatusCodeError } from './StatusCodeError.js';
19
+
20
+ const { fetch, reset } = keepAliveNoCache({ userAgent: 'helix-fetch' });
21
+
22
+ const AZ_AUTHORITY_HOST_URL = 'https://login.windows.net';
23
+ const AZ_COMMON_TENANT = 'common';
24
+
25
+ const DEFAULT_SCOPES = ['https://graph.microsoft.com/.default', 'openid', 'profile', 'offline_access'];
26
+
27
+ const MSAL_LOG_LEVELS = [
28
+ 'error',
29
+ 'warn',
30
+ 'info',
31
+ 'debug',
32
+ 'trace',
33
+ ];
34
+
35
+ /**
36
+ * aliases
37
+ * @typedef {import('@azure/msal-node').AuthenticationResult} AuthenticationResult
38
+ */
39
+
40
+ /**
41
+ * map that caches the tenant ids
42
+ * @type {Map<string, string>}
43
+ */
44
+ const globalTenantCache = new Map();
45
+
46
+ /**
47
+ * Helper class that facilitates accessing one drive.
48
+ *
49
+ * @class
50
+ * @field {ConfidentialClientApplication|PublicClientApplication} app
51
+ */
52
+ export class OneDriveAuth {
53
+ /**
54
+ * @param {OneDriveAuthOptions} opts Options
55
+ */
56
+ constructor(opts) {
57
+ if (!opts.clientId) {
58
+ throw new Error('Missing clientId.');
59
+ }
60
+ if (opts.username || opts.password) {
61
+ throw new Error('Username/password authentication no longer supported.');
62
+ }
63
+
64
+ this.clientId = opts.clientId;
65
+ this.clientSecret = opts.clientSecret || '';
66
+ this.refreshToken = opts.refreshToken || '';
67
+ this._log = opts.log || console;
68
+ this.tenant = opts.tenant;
69
+ this.cachePlugin = opts.cachePlugin;
70
+ this.scopes = opts.scopes || DEFAULT_SCOPES;
71
+
72
+ if (!opts.noTenantCache && !process.env.HELIX_ONEDRIVE_NO_TENANT_CACHE) {
73
+ /** @type {Map<string, string>} */
74
+ this.tenantCache = opts.tenantCache || globalTenantCache;
75
+ }
76
+
77
+ if ((opts.localAuthCache || process.env.HELIX_ONEDRIVE_LOCAL_AUTH_CACHE) && !this.cachePlugin) {
78
+ this.cachePlugin = new MemCachePlugin({
79
+ log: this._log,
80
+ key: 'default',
81
+ caches: new Map(),
82
+ });
83
+ }
84
+ }
85
+
86
+ get app() {
87
+ if (!this._app) {
88
+ const {
89
+ log,
90
+ cachePlugin,
91
+ } = this;
92
+ const msalConfig = {
93
+ auth: {
94
+ clientId: this.clientId,
95
+ clientSecret: this.clientSecret,
96
+ authority: this.getAuthorityUrl(),
97
+ },
98
+ system: {
99
+ loggerOptions: {
100
+ loggerCallback(loglevel, message) {
101
+ log[MSAL_LOG_LEVELS[loglevel]](message);
102
+ },
103
+ piiLoggingEnabled: false,
104
+ logLevel: LogLevel.Verbose,
105
+ },
106
+ },
107
+ };
108
+
109
+ if (cachePlugin) {
110
+ msalConfig.cache = {
111
+ cachePlugin,
112
+ };
113
+ }
114
+ this._app = new ConfidentialClientApplication(msalConfig);
115
+ }
116
+ return this._app;
117
+ }
118
+
119
+ async resolveTenant(tenantHostName) {
120
+ const { log } = this;
121
+ const configUrl = `https://login.windows.net/${tenantHostName}.onmicrosoft.com/.well-known/openid-configuration`;
122
+ const res = await fetch(configUrl);
123
+ if (!res.ok) {
124
+ log.info(`error fetching openid-configuration for ${tenantHostName}: ${res.status}. Fallback to 'common'`);
125
+ return AZ_COMMON_TENANT;
126
+ }
127
+
128
+ const { issuer } = await res.json();
129
+ if (!issuer) {
130
+ log.info(`unable to extract tenant from openid-configuration for ${tenantHostName}: no 'issuer'. Fallback to 'common'`);
131
+ return AZ_COMMON_TENANT;
132
+ }
133
+
134
+ // eslint-disable-next-line prefer-destructuring
135
+ const tenant = new URL(issuer).pathname.split('/')[1];
136
+ log.info(`fetched tenant information from for ${tenantHostName}: ${tenant}`);
137
+ return tenant;
138
+ }
139
+
140
+ static getTenantHostFromUrl(sharingUrl) {
141
+ const url = sharingUrl instanceof URL
142
+ ? sharingUrl
143
+ : new URL(sharingUrl);
144
+ let [tenantHost] = url.hostname.split('.');
145
+ // special case: `xxxx-my.sharepoint.com`
146
+ if (url.hostname.endsWith('-my.sharepoint.com')) {
147
+ tenantHost = tenantHost.substring(0, tenantHost.length - 3);
148
+ }
149
+ return tenantHost;
150
+ }
151
+
152
+ async initTenantFromUrl(sharingUrl) {
153
+ if (this.tenant) {
154
+ return;
155
+ }
156
+ const { log } = this;
157
+ const tenantHost = OneDriveAuth.getTenantHostFromUrl(sharingUrl);
158
+
159
+ if (this.tenantCache) {
160
+ this.tenant = this.tenantCache.get(tenantHost);
161
+ }
162
+ if (!this.tenant) {
163
+ this.tenant = await this.resolveTenant(tenantHost);
164
+ if (this.tenantCache) {
165
+ this.tenantCache.set(tenantHost, this.tenant);
166
+ }
167
+ }
168
+ log.info(`using tenant ${this.tenant} for ${tenantHost} from ${sharingUrl}`);
169
+ }
170
+
171
+ /**
172
+ */
173
+ // eslint-disable-next-line class-methods-use-this
174
+ async dispose() {
175
+ // TODO: clear other state?
176
+ return reset();
177
+ }
178
+
179
+ /**
180
+ */
181
+ get log() {
182
+ return this._log;
183
+ }
184
+
185
+ getAuthorityUrl() {
186
+ if (!this.tenant) {
187
+ throw new Error('unable to compute authority url. no tenant.');
188
+ }
189
+ return `${AZ_AUTHORITY_HOST_URL}/${this.tenant}`;
190
+ }
191
+
192
+ /**
193
+ * @returns {boolean}
194
+ */
195
+ async isAuthenticated() {
196
+ const accounts = await this.app.getTokenCache().getAllAccounts();
197
+ return accounts.length > 0;
198
+ }
199
+
200
+ /**
201
+ * Performs a login using an interactive flow which prompts the user to open a browser window and
202
+ * enter the authorization code.
203
+ * @params {function} [onCode] - optional function that gets invoked after code was retrieved.
204
+ * @returns {Promise<AuthenticationResult>}
205
+ */
206
+ async acquireTokenByDeviceCode(onCode) {
207
+ const { log, app } = this;
208
+ try {
209
+ return await app.acquireTokenByDeviceCode({
210
+ deviceCodeCallback: async (code) => {
211
+ log.info(code.message);
212
+ if (typeof onCode === 'function') {
213
+ await onCode(code);
214
+ }
215
+ },
216
+ scopes: this.scopes,
217
+ });
218
+ } catch (e) {
219
+ log.error('Error while requesting access token with device code', e);
220
+ throw e;
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Sets the access token to use for all requests. if the token is a valid JWT token,
226
+ * its `tid` claim is used a tenant (if no tenant is already set).
227
+ *
228
+ * @param {string} bearerToken
229
+ * @returns {OneDriveAuth} this
230
+ */
231
+ setAccessToken(bearerToken) {
232
+ const { log } = this;
233
+ /** @type AuthenticationResult */
234
+ this.authResult = {
235
+ accessToken: bearerToken,
236
+ };
237
+ if (!this.tenant) {
238
+ try {
239
+ const { tid } = decodeJwt(bearerToken);
240
+ if (tid) {
241
+ log.info(`using tenant from access token: ${tid}`);
242
+ this.tenant = tid;
243
+ }
244
+ } catch (e) {
245
+ log.warn(`unable to decode access token: ${e.message}`);
246
+ }
247
+ }
248
+ this.authResult.tenantId = this.tenant;
249
+ return this;
250
+ }
251
+
252
+ /**
253
+ * Authenticates against MS
254
+ * @param {boolean} silentOnly
255
+ * @returns {Promise<null|AuthenticationResult>}
256
+ */
257
+ async doAuthenticate(silentOnly) {
258
+ const { log, app } = this;
259
+ const accounts = await app.getTokenCache().getAllAccounts();
260
+ if (accounts.length > 0) {
261
+ try {
262
+ return await app.acquireTokenSilent({
263
+ account: accounts[0],
264
+ });
265
+ } catch (e) {
266
+ if (e.message !== 'Entry not found in cache.') {
267
+ log.warn(`Unable to acquire token from cache: ${e}`);
268
+ } else {
269
+ log.debug(`Unable to acquire token from cache: ${e}`);
270
+ }
271
+ }
272
+ }
273
+ if (silentOnly) {
274
+ return null;
275
+ }
276
+
277
+ try {
278
+ if (this.refreshToken) {
279
+ log.debug('acquire token with refresh token.');
280
+ return await app.acquireTokenByRefreshToken({
281
+ refreshToken: this.refreshToken,
282
+ });
283
+ } else if (this.clientSecret) {
284
+ log.debug('acquire token with client credentials.');
285
+ return await app.acquireTokenByClientCredential({
286
+ scopes: this.scopes,
287
+ });
288
+ } else {
289
+ const err = new StatusCodeError('No valid authentication credentials supplied.');
290
+ err.statusCode = 401;
291
+ throw err;
292
+ }
293
+ } catch (e) {
294
+ log.error(`Error while acquiring access token ${e}`);
295
+ throw e;
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Authenticates by either using the cached result or talking to MS
301
+ * @param {boolean} silentOnly
302
+ * @returns {Promise<AuthenticationResult>}
303
+ */
304
+ async authenticate(silentOnly) {
305
+ if (!this.authResult) {
306
+ this.authResult = await this.doAuthenticate(silentOnly);
307
+ }
308
+ return this.authResult;
309
+ }
310
+ }
@@ -9,10 +9,10 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
- const OneDrive = require('./OneDrive.js');
13
- const Workbook = require('./Workbook.js');
14
- const StatusCodeError = require('./StatusCodeError.js');
15
- const { driveItemFromURL, driveItemToURL } = require('./utils.js');
12
+ import { OneDrive } from './OneDrive.js';
13
+ import { OneDriveAuth } from './OneDriveAuth.js';
14
+ import { Workbook } from './excel/Workbook.js';
15
+ import { StatusCodeError } from './StatusCodeError.js';
16
16
 
17
17
  /**
18
18
  * Handle the `namedItems` operation on a workbook / worksheet
@@ -139,10 +139,22 @@ function handleTable(sheet, segs, method, body) {
139
139
  /**
140
140
  * Mock OneDrive client that supports some of the operations the `OneDrive` class does.
141
141
  */
142
- class OneDriveMock extends OneDrive {
143
- constructor() {
142
+ export class OneDriveMock extends OneDrive {
143
+ constructor({ auth } = {}) {
144
+ if (!auth) {
145
+ // eslint-disable-next-line no-param-reassign
146
+ auth = new OneDriveAuth({
147
+ clientId: 'mock-id',
148
+ tenant: 'test-tenant',
149
+ });
150
+ // eslint-disable-next-line no-param-reassign
151
+ auth.accessToken = {
152
+ accessToken: 'dummy-token',
153
+ tenantId: 'test-tenant',
154
+ };
155
+ }
144
156
  super({
145
- clientId: 'mock-id',
157
+ auth,
146
158
  });
147
159
  this.workbooks = [];
148
160
  this.sharelinks = {};
@@ -310,8 +322,3 @@ class OneDriveMock extends OneDrive {
310
322
  }
311
323
  }
312
324
  }
313
-
314
- module.exports = Object.assign(OneDriveMock, {
315
- driveItemToURL,
316
- driveItemFromURL,
317
- });
@@ -9,14 +9,15 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
+ import { keepAliveNoCache } from '@adobe/helix-fetch';
13
+ import { StatusCodeError } from './StatusCodeError.js';
12
14
 
13
- const { fetch } = require('@adobe/helix-fetch').keepAliveNoCache({ userAgent: 'helix-fetch' });
14
- const StatusCodeError = require('./StatusCodeError.js');
15
+ const { fetch } = keepAliveNoCache({ userAgent: 'helix-fetch' });
15
16
 
16
17
  /**
17
18
  * Helper class accessing folders and files using the SharePoint V1 API.
18
19
  */
19
- class SharePointSite {
20
+ export class SharePointSite {
20
21
  constructor(opts) {
21
22
  this._owner = opts.owner;
22
23
  this._site = opts.site;
@@ -113,11 +114,10 @@ class SharePointSite {
113
114
  // await result in order to be able to catch any error
114
115
  return await (rawResponseBody || !json ? resp.buffer() : resp.json());
115
116
  } catch (e) {
116
- /* istanbul ignore else */
117
+ /* c8 ignore next 4 */
117
118
  if (e instanceof StatusCodeError) {
118
119
  throw e;
119
120
  }
120
- /* istanbul ignore next */
121
121
  throw StatusCodeError.fromError(e);
122
122
  }
123
123
  }
@@ -126,5 +126,3 @@ class SharePointSite {
126
126
  return this._log;
127
127
  }
128
128
  }
129
-
130
- module.exports = SharePointSite;
@@ -10,13 +10,13 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- const { AbortError, FetchError } = require('@adobe/helix-fetch');
13
+ import { AbortError, FetchError } from '@adobe/helix-fetch';
14
14
 
15
15
  /**
16
16
  * Internal error class
17
17
  * @private
18
18
  */
19
- class StatusCodeError extends Error {
19
+ export class StatusCodeError extends Error {
20
20
  /**
21
21
  * Converts a fetch error to a status code error.
22
22
  * @param {Error} err The original error
@@ -63,5 +63,3 @@ class StatusCodeError extends Error {
63
63
  this.details = details;
64
64
  }
65
65
  }
66
-
67
- module.exports = StatusCodeError;
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Copyright 2022 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import { FSCachePlugin } from "./FSCachePlugin";
13
+
14
+ export declare interface FSCacheManagerOptions {
15
+ log: Console;
16
+ dirPath: string;
17
+ type: string;
18
+ }
19
+
20
+ export declare class FSCacheManager {
21
+ constructor(opts: FSCacheManagerOptions);
22
+
23
+ listCacheKeys():Promise<string[]>;
24
+
25
+ hasCache(key:string):Promise<boolean>;
26
+
27
+ getCache(key:string):Promise<FSCachePlugin>;
28
+ }
@@ -0,0 +1,77 @@
1
+ /*
2
+ * Copyright 2022 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import fs from 'fs/promises';
13
+ import path from 'path';
14
+ import { FSCachePlugin } from './FSCachePlugin.js';
15
+
16
+ /**
17
+ * aliases
18
+ * @typedef {import("@azure/msal-node").ICachePlugin} ICachePlugin
19
+ * @typedef {import("@azure/msal-node").TokenCacheContext} TokenCacheContext
20
+ */
21
+
22
+ export class FSCacheManager {
23
+ constructor(opts) {
24
+ this.dirPath = opts.dirPath;
25
+ this.log = opts.log || console;
26
+ this.type = opts.type;
27
+ }
28
+
29
+ getCacheFilePath(key) {
30
+ return path.resolve(this.dirPath, `auth-${this.type}-${key}.json`);
31
+ }
32
+
33
+ async listCacheKeys() {
34
+ try {
35
+ const files = await fs.readdir(this.dirPath);
36
+ return files
37
+ .filter((name) => (name.startsWith('auth-') && name.endsWith('.json')))
38
+ .map((name) => name.replace(/auth-([a-z0-9]+)-([a-z0-9]+).json/i, '$2'));
39
+ } catch (e) {
40
+ if (e.code === 'ENOENT') {
41
+ return [];
42
+ }
43
+ throw e;
44
+ }
45
+ }
46
+
47
+ async hasCache(key) {
48
+ try {
49
+ await fs.lstat(this.getCacheFilePath(key));
50
+ return true;
51
+ } catch (e) {
52
+ if (e.code !== 'ENOENT') {
53
+ throw e;
54
+ }
55
+ return false;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * @param key
61
+ * @returns {FSCachePlugin}
62
+ */
63
+ async getCache(key) {
64
+ try {
65
+ await fs.lstat(this.dirPath);
66
+ } catch (e) {
67
+ if (e.code !== 'ENOENT') {
68
+ throw e;
69
+ }
70
+ await fs.mkdir(this.dirPath);
71
+ }
72
+ return new FSCachePlugin({
73
+ log: this.log,
74
+ filePath: this.getCacheFilePath(key),
75
+ });
76
+ }
77
+ }
@@ -0,0 +1,29 @@
1
+ /*
2
+ * Copyright 2022 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import { ICachePlugin, TokenCacheContext } from '@azure/msal-node';
13
+
14
+ import { Logger } from "../OneDrive";
15
+
16
+ export declare interface FSCachePluginOptions {
17
+ log: Console;
18
+ filePath: string;
19
+ }
20
+
21
+ export declare class FSCachePlugin implements ICachePlugin {
22
+ constructor(opts: FSCachePluginOptions);
23
+
24
+ deleteCache(): Promise<void>;
25
+
26
+ afterCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
27
+
28
+ beforeCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
29
+ }