@adobe/helix-onedrive-support 5.2.1 → 6.1.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/.mocha-multi.json +6 -0
- package/.nycrc.json +10 -0
- package/CHANGELOG.md +33 -0
- package/package.json +23 -16
- package/src/OneDrive.d.ts +46 -1
- package/src/OneDrive.js +57 -7
- package/src/Range.d.ts +2 -1
- package/src/Range.js +10 -3
- package/src/SharePointSite.js +139 -0
- package/src/StatusCodeError.js +1 -1
- package/src/Table.d.ts +10 -3
- package/src/Table.js +10 -3
- package/src/utils.js +18 -0
package/.nycrc.json
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
# [6.1.0](https://github.com/adobe/helix-onedrive-support/compare/v6.0.1...v6.1.0) (2022-01-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add API for SP API ([#227](https://github.com/adobe/helix-onedrive-support/issues/227)) ([6ce5938](https://github.com/adobe/helix-onedrive-support/commit/6ce59387a777d4549964a8fb90b2e0ca2a4fd86e))
|
|
7
|
+
|
|
8
|
+
## [6.0.1](https://github.com/adobe/helix-onedrive-support/compare/v6.0.0...v6.0.1) (2021-10-18)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **deps:** update dependency @adobe/helix-fetch to v3 ([#202](https://github.com/adobe/helix-onedrive-support/issues/202)) ([1b0b586](https://github.com/adobe/helix-onedrive-support/commit/1b0b58661458550a3d6b782ada364f2f48d69fb0))
|
|
14
|
+
|
|
15
|
+
# [6.0.0](https://github.com/adobe/helix-onedrive-support/compare/v5.2.2...v6.0.0) (2021-10-08)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
* Support conflict behaviour (#197) ([b4a5c72](https://github.com/adobe/helix-onedrive-support/commit/b4a5c72ed76062c558ea175aaedff3475e892c34)), closes [#197](https://github.com/adobe/helix-onedrive-support/issues/197)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### BREAKING CHANGES
|
|
22
|
+
|
|
23
|
+
* uploadDriveItem return value changed
|
|
24
|
+
|
|
25
|
+
* fix: test behaviour values
|
|
26
|
+
|
|
27
|
+
## [5.2.2](https://github.com/adobe/helix-onedrive-support/compare/v5.2.1...v5.2.2) (2021-10-08)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* trim object names and values ([#196](https://github.com/adobe/helix-onedrive-support/issues/196)) ([f117175](https://github.com/adobe/helix-onedrive-support/commit/f117175f63316ed8a3b60f4e74870114134b9ef7))
|
|
33
|
+
|
|
1
34
|
## [5.2.1](https://github.com/adobe/helix-onedrive-support/compare/v5.2.0...v5.2.1) (2021-10-07)
|
|
2
35
|
|
|
3
36
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-onedrive-support",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Helix OneDrive Support",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "
|
|
9
|
-
"test-ci": "nyc
|
|
8
|
+
"test": "nyc mocha",
|
|
9
|
+
"test-ci": "nyc mocha && codecov",
|
|
10
10
|
"lint": "./node_modules/.bin/eslint .",
|
|
11
11
|
"semantic-release": "semantic-release",
|
|
12
12
|
"docs": "npx jsdoc2md -c .jsdoc.json --files 'src/*.js' > docs/API.md",
|
|
@@ -23,28 +23,29 @@
|
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://github.com/adobe/helix-onedrive-support#readme",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@adobe/helix-fetch": "
|
|
26
|
+
"@adobe/helix-fetch": "3.0.0",
|
|
27
27
|
"adal-node": "https://github.com/adobe-rnd/azure-activedirectory-library-for-nodejs.git#adobe"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@adobe/eslint-config-helix": "1.2
|
|
31
|
-
"@semantic-release/changelog": "6.0.
|
|
32
|
-
"@semantic-release/git": "10.0.
|
|
33
|
-
"ajv": "8.
|
|
30
|
+
"@adobe/eslint-config-helix": "1.3.2",
|
|
31
|
+
"@semantic-release/changelog": "6.0.1",
|
|
32
|
+
"@semantic-release/git": "10.0.1",
|
|
33
|
+
"ajv": "8.9.0",
|
|
34
34
|
"codecov": "3.8.3",
|
|
35
35
|
"commitizen": "4.2.4",
|
|
36
36
|
"cz-conventional-changelog": "3.3.0",
|
|
37
|
-
"dotenv": "
|
|
38
|
-
"eslint": "7.
|
|
37
|
+
"dotenv": "14.2.0",
|
|
38
|
+
"eslint": "8.7.0",
|
|
39
39
|
"eslint-plugin-header": "3.1.1",
|
|
40
|
-
"eslint-plugin-import": "2.
|
|
41
|
-
"jsdoc-to-markdown": "7.0
|
|
40
|
+
"eslint-plugin-import": "2.25.4",
|
|
41
|
+
"jsdoc-to-markdown": "7.1.0",
|
|
42
42
|
"junit-report-builder": "3.0.0",
|
|
43
|
-
"lint-staged": "
|
|
44
|
-
"mocha": "9.1.
|
|
45
|
-
"
|
|
43
|
+
"lint-staged": "12.3.1",
|
|
44
|
+
"mocha": "9.1.4",
|
|
45
|
+
"mocha-multi-reporters": "1.5.1",
|
|
46
|
+
"nock": "13.2.2",
|
|
46
47
|
"nyc": "15.1.0",
|
|
47
|
-
"semantic-release": "
|
|
48
|
+
"semantic-release": "19.0.2"
|
|
48
49
|
},
|
|
49
50
|
"lint-staged": {
|
|
50
51
|
"*.js": "eslint"
|
|
@@ -56,5 +57,11 @@
|
|
|
56
57
|
"ghooks": {
|
|
57
58
|
"pre-commit": "npx lint-staged"
|
|
58
59
|
}
|
|
60
|
+
},
|
|
61
|
+
"mocha": {
|
|
62
|
+
"spec": "test/**/*.test.js",
|
|
63
|
+
"require": "test/setup-env.js",
|
|
64
|
+
"reporter": "mocha-multi-reporters",
|
|
65
|
+
"reporter-options": "configFile=.mocha-multi.json"
|
|
59
66
|
}
|
|
60
67
|
}
|
package/src/OneDrive.d.ts
CHANGED
|
@@ -60,6 +60,36 @@ export declare interface SubscriptionOptions {
|
|
|
60
60
|
expiresIn?: number;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
export declare interface SharePointSite {
|
|
64
|
+
/**
|
|
65
|
+
* Return a file's properties.
|
|
66
|
+
* @param file file name
|
|
67
|
+
* @returns file properties
|
|
68
|
+
*/
|
|
69
|
+
getFile(file: string): Promise<GraphResult>;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Return a folder's properties.
|
|
73
|
+
* @param folder folder name
|
|
74
|
+
* @returns folder properties
|
|
75
|
+
*/
|
|
76
|
+
getFolder(folder: string): Promise<GraphResult>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Return a file's contents, as a binary buffer.
|
|
80
|
+
* @param file file name
|
|
81
|
+
* @returns file contents
|
|
82
|
+
*/
|
|
83
|
+
getFileContents(file: string): Promise<Buffer>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns a list of children items in a folder
|
|
87
|
+
* @param folder folder name
|
|
88
|
+
* @returns list of files and folders
|
|
89
|
+
*/
|
|
90
|
+
getFilesAndFolders(folder: string): Promise<GraphResult>;
|
|
91
|
+
}
|
|
92
|
+
|
|
63
93
|
/**
|
|
64
94
|
* Helper class that facilitates accessing one drive.
|
|
65
95
|
*/
|
|
@@ -203,7 +233,15 @@ export declare class OneDrive extends EventEmitter {
|
|
|
203
233
|
|
|
204
234
|
deleteSubscription(id: string): Promise<GraphResult>;
|
|
205
235
|
|
|
206
|
-
|
|
236
|
+
/**
|
|
237
|
+
* Uploads a drive item.
|
|
238
|
+
*
|
|
239
|
+
* @param buffer contents of file
|
|
240
|
+
* @param driveItem parent item in combination with relPath or item itself
|
|
241
|
+
* @param relPath relative path
|
|
242
|
+
* @param conflictBehaviour replace, rename or fail, default is replace
|
|
243
|
+
*/
|
|
244
|
+
uploadDriveItem(buffer: Buffer, driveItem: string, relPath?: string, conflictBehaviour?: string);
|
|
207
245
|
|
|
208
246
|
/**
|
|
209
247
|
* Returns the root item for a drive given its id.
|
|
@@ -220,4 +258,11 @@ export declare class OneDrive extends EventEmitter {
|
|
|
220
258
|
* @returns {Promise<Array>} A return object with the values and a `@odata.deltaLink`.
|
|
221
259
|
*/
|
|
222
260
|
fetchChanges(resource: string, token?: string);
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Returns a site object exposing the SharePoint API (now called Graph API V1).
|
|
264
|
+
* @param siteURL site URL, in the format https://<tenant>.sharepoint.com/sites/<site>
|
|
265
|
+
* @return {Promise<SharePointSite} site object
|
|
266
|
+
*/
|
|
267
|
+
getSite(siteURL: string): Promise<SharePointSite>;
|
|
223
268
|
}
|
package/src/OneDrive.js
CHANGED
|
@@ -20,6 +20,7 @@ const Workbook = require('./Workbook.js');
|
|
|
20
20
|
const StatusCodeError = require('./StatusCodeError.js');
|
|
21
21
|
const { driveItemFromURL, driveItemToURL } = require('./utils.js');
|
|
22
22
|
const { splitByExtension, sanitize, editDistance } = require('./fuzzy-helper.js');
|
|
23
|
+
const SharePointSite = require('./SharePointSite.js');
|
|
23
24
|
|
|
24
25
|
const { fetch, reset } = process.env.HELIX_FETCH_FORCE_HTTP1
|
|
25
26
|
? fetchAPI.context({
|
|
@@ -204,18 +205,26 @@ class OneDrive extends EventEmitter {
|
|
|
204
205
|
if (this.refreshToken) {
|
|
205
206
|
log.debug('acquire token with refresh token.');
|
|
206
207
|
const resp = await context.acquireTokenWithRefreshToken(
|
|
207
|
-
this.refreshToken,
|
|
208
|
+
this.refreshToken,
|
|
209
|
+
this.clientId,
|
|
210
|
+
this.clientSecret,
|
|
211
|
+
AZ_RESOURCE,
|
|
208
212
|
);
|
|
209
213
|
return await this.augmentAndCacheResponse(resp);
|
|
210
214
|
} else if (this.username && this.password) {
|
|
211
215
|
log.debug('acquire token with ROPC.');
|
|
212
216
|
return await context.acquireTokenWithUsernamePassword(
|
|
213
|
-
AZ_RESOURCE,
|
|
217
|
+
AZ_RESOURCE,
|
|
218
|
+
this.username,
|
|
219
|
+
this.password,
|
|
220
|
+
this.clientId,
|
|
214
221
|
);
|
|
215
222
|
} else if (this.clientSecret) {
|
|
216
223
|
log.debug('acquire token with client credentials.');
|
|
217
224
|
return await context.acquireTokenWithClientCredentials(
|
|
218
|
-
AZ_RESOURCE,
|
|
225
|
+
AZ_RESOURCE,
|
|
226
|
+
this.clientId,
|
|
227
|
+
this.clientSecret,
|
|
219
228
|
);
|
|
220
229
|
} else {
|
|
221
230
|
const err = new StatusCodeError('No valid authentication credentials supplied.');
|
|
@@ -259,7 +268,11 @@ class OneDrive extends EventEmitter {
|
|
|
259
268
|
const { log, authContext: context } = this;
|
|
260
269
|
try {
|
|
261
270
|
const resp = await context.acquireTokenWithAuthorizationCode(
|
|
262
|
-
code,
|
|
271
|
+
code,
|
|
272
|
+
redirectUri,
|
|
273
|
+
AZ_RESOURCE,
|
|
274
|
+
this.clientId,
|
|
275
|
+
this.clientSecret,
|
|
263
276
|
);
|
|
264
277
|
return await this.augmentAndCacheResponse(resp);
|
|
265
278
|
} catch (e) {
|
|
@@ -489,7 +502,15 @@ class OneDrive extends EventEmitter {
|
|
|
489
502
|
/**
|
|
490
503
|
* @see https://docs.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=http
|
|
491
504
|
*/
|
|
492
|
-
async uploadDriveItem(buffer, driveItem, relPath = '') {
|
|
505
|
+
async uploadDriveItem(buffer, driveItem, relPath = '', conflictBehaviour = 'replace') {
|
|
506
|
+
const validConflictBehaviours = [
|
|
507
|
+
'replace',
|
|
508
|
+
'rename',
|
|
509
|
+
'fail',
|
|
510
|
+
];
|
|
511
|
+
if (!validConflictBehaviours.includes(conflictBehaviour)) {
|
|
512
|
+
throw new Error(`Bad confict behaviour: ${conflictBehaviour}, must be one of: ${validConflictBehaviours.join('/')}`);
|
|
513
|
+
}
|
|
493
514
|
// eslint-disable-next-line no-param-reassign
|
|
494
515
|
relPath = relPath.replace(/\/+$/, '');
|
|
495
516
|
if (relPath) {
|
|
@@ -498,7 +519,7 @@ class OneDrive extends EventEmitter {
|
|
|
498
519
|
}
|
|
499
520
|
|
|
500
521
|
// PUT /drives/{drive-id}/items/{parent-id}:/{filename}:/content
|
|
501
|
-
const uri = `/drives/${driveItem.parentReference.driveId}/items/${driveItem.id}${relPath}/content`;
|
|
522
|
+
const uri = `/drives/${driveItem.parentReference.driveId}/items/${driveItem.id}${relPath}/content?@microsoft.graph.conflictBehavior=${conflictBehaviour}`;
|
|
502
523
|
const opts = {
|
|
503
524
|
method: 'PUT',
|
|
504
525
|
body: buffer,
|
|
@@ -506,7 +527,7 @@ class OneDrive extends EventEmitter {
|
|
|
506
527
|
'Content-Type': 'application/octet-stream',
|
|
507
528
|
},
|
|
508
529
|
};
|
|
509
|
-
return this.doFetch(uri,
|
|
530
|
+
return this.doFetch(uri, false, opts);
|
|
510
531
|
}
|
|
511
532
|
|
|
512
533
|
/**
|
|
@@ -603,6 +624,35 @@ class OneDrive extends EventEmitter {
|
|
|
603
624
|
}
|
|
604
625
|
}
|
|
605
626
|
}
|
|
627
|
+
|
|
628
|
+
async getSite(siteURL) {
|
|
629
|
+
this.log.debug(`getting site: (${siteURL})`);
|
|
630
|
+
|
|
631
|
+
const match = siteURL.match(/^https:\/\/(\S+).sharepoint.com\/sites\/([^/]+)\/(\S+)$/);
|
|
632
|
+
if (!match) {
|
|
633
|
+
throw new Error(`Site URL does not match (*.sharepoint.com/sites/.*): ${match}`);
|
|
634
|
+
}
|
|
635
|
+
const [, owner, site, root] = match;
|
|
636
|
+
|
|
637
|
+
try {
|
|
638
|
+
const accessToken = await this.getAccessToken();
|
|
639
|
+
return new SharePointSite({
|
|
640
|
+
owner,
|
|
641
|
+
site,
|
|
642
|
+
root,
|
|
643
|
+
clientId: this.clientId,
|
|
644
|
+
tenantId: accessToken.tenantId,
|
|
645
|
+
refreshToken: accessToken.refreshToken,
|
|
646
|
+
log: this.log,
|
|
647
|
+
});
|
|
648
|
+
} catch (e) {
|
|
649
|
+
if (e.statusCode === 401) {
|
|
650
|
+
// an inexistant share returns 401, we prefer to just say it wasn't found
|
|
651
|
+
throw new StatusCodeError(e.message, 404, e.details);
|
|
652
|
+
}
|
|
653
|
+
throw e;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
606
656
|
}
|
|
607
657
|
|
|
608
658
|
module.exports = Object.assign(OneDrive, {
|
package/src/Range.d.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { GraphResult, Logger } from './OneDrive'
|
|
14
|
+
import { FormatOptions } from "./Table";
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Excel Range
|
|
@@ -45,7 +46,7 @@ export declare interface Range {
|
|
|
45
46
|
* Returns the rows as a list of objects. the rows have the columns names as property names
|
|
46
47
|
* and the row values as value.
|
|
47
48
|
*/
|
|
48
|
-
getRowsAsObjects(): Promise<Array<object>>;
|
|
49
|
+
getRowsAsObjects(opts?:FormatOptions): Promise<Array<object>>;
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Returns the values of the range.
|
package/src/Range.js
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
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 { superTrim } = require('./utils.js');
|
|
13
|
+
|
|
12
14
|
class Range {
|
|
13
15
|
constructor(oneDrive, uri, log) {
|
|
14
16
|
this._oneDrive = oneDrive;
|
|
@@ -44,13 +46,18 @@ class Range {
|
|
|
44
46
|
return (await this.getData()).values[0];
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
async getRowsAsObjects() {
|
|
49
|
+
async getRowsAsObjects({ trim = false } = {}) {
|
|
48
50
|
const values = await this.getValues();
|
|
49
51
|
|
|
50
52
|
const columnNames = values[0];
|
|
51
53
|
const rows = values.map((row) => columnNames.reduce((obj, name, index) => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
if (trim) {
|
|
55
|
+
// eslint-disable-next-line no-param-reassign
|
|
56
|
+
obj[superTrim(name)] = superTrim(row[index]);
|
|
57
|
+
} else {
|
|
58
|
+
// eslint-disable-next-line no-param-reassign
|
|
59
|
+
obj[name] = row[index];
|
|
60
|
+
}
|
|
54
61
|
return obj;
|
|
55
62
|
}, {}));
|
|
56
63
|
// discard first row
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2021 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
|
+
const fetchAPI = require('@adobe/helix-fetch');
|
|
14
|
+
const StatusCodeError = require('./StatusCodeError.js');
|
|
15
|
+
|
|
16
|
+
/* istanbul ignore next */
|
|
17
|
+
const { fetch } = process.env.HELIX_FETCH_FORCE_HTTP1
|
|
18
|
+
? fetchAPI.context({
|
|
19
|
+
alpnProtocols: [fetchAPI.ALPN_HTTP1_1],
|
|
20
|
+
userAgent: 'helix-fetch', // static user agent for test recordings
|
|
21
|
+
})
|
|
22
|
+
/* istanbul ignore next */
|
|
23
|
+
: fetchAPI;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Helper class accessing folders and files using the SharePoint V1 API.
|
|
27
|
+
*/
|
|
28
|
+
class SharePointSite {
|
|
29
|
+
constructor(opts) {
|
|
30
|
+
this._owner = opts.owner;
|
|
31
|
+
this._site = opts.site;
|
|
32
|
+
this._clientId = opts.clientId;
|
|
33
|
+
this._tenantId = opts.tenantId;
|
|
34
|
+
this._refreshToken = opts.refreshToken;
|
|
35
|
+
this._root = opts.root || '';
|
|
36
|
+
this._log = opts.log || console;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async getAccessToken() {
|
|
40
|
+
const { log } = this;
|
|
41
|
+
if (!this._accessToken || Date.now() >= this._expires) {
|
|
42
|
+
const url = `https://login.microsoftonline.com/${this._tenantId}/oauth2/v2.0/token`;
|
|
43
|
+
const resp = await fetch(url, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
body: new URLSearchParams({
|
|
46
|
+
client_id: this._clientId,
|
|
47
|
+
refresh_token: this._refreshToken,
|
|
48
|
+
grant_type: 'refresh_token',
|
|
49
|
+
scope: `https://${this._owner}.sharepoint.com/Sites.ReadWrite.All`,
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
if (!resp.ok) {
|
|
53
|
+
const text = await resp.text();
|
|
54
|
+
log.error(`Error while getting a SharePoint API token: ${text}}`);
|
|
55
|
+
throw new StatusCodeError(text, resp.status);
|
|
56
|
+
}
|
|
57
|
+
const json = await resp.json();
|
|
58
|
+
this._accessToken = json.access_token;
|
|
59
|
+
this._expires = Date.now() + json.expires_in * 1000;
|
|
60
|
+
}
|
|
61
|
+
return this._accessToken;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_splitDirAndBase(file) {
|
|
65
|
+
const idx = file.lastIndexOf('/');
|
|
66
|
+
const [dir, base] = (idx < 0)
|
|
67
|
+
? ['', file]
|
|
68
|
+
: [file.substring(0, idx), file.substring(idx + 1)];
|
|
69
|
+
return dir ? [`${this._root}/${dir}`, base] : [this._root, base];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
_getRelativePath(folder) {
|
|
73
|
+
return folder ? `${this._root}/${folder}` : this._root;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async getFile(file) {
|
|
77
|
+
const [dir, base] = this._splitDirAndBase(file);
|
|
78
|
+
return this.doFetch(`/GetFolderByServerRelativeUrl('${dir}')/Files('${base}')?$expand=ModifiedBy`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async getFolder(folder) {
|
|
82
|
+
const dir = this._getRelativePath(folder);
|
|
83
|
+
return this.doFetch(`/GetFolderByServerRelativeUrl('${dir}')`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async getFileContents(file) {
|
|
87
|
+
const [dir, base] = this._splitDirAndBase(file);
|
|
88
|
+
return this.doFetch(`/GetFolderByServerRelativeUrl('${dir}')/Files('${base}')/$value`, true);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async getFilesAndFolders(folder) {
|
|
92
|
+
const dir = this._getRelativePath(folder);
|
|
93
|
+
return this.doFetch(`/GetFolderByServerRelativeUrl('${dir}')?$expand=Files/ModifiedBy,Folders`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async doFetch(relUrl, rawResponseBody = false) {
|
|
97
|
+
const opts = { headers: {} };
|
|
98
|
+
const accessToken = await this.getAccessToken();
|
|
99
|
+
opts.headers.authorization = `Bearer ${accessToken}`;
|
|
100
|
+
if (!rawResponseBody) {
|
|
101
|
+
opts.headers.accept = 'application/json;odata=verbose';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const url = `https://${this._owner}.sharepoint.com/sites/${this._site}/_api/web${relUrl}`;
|
|
105
|
+
try {
|
|
106
|
+
const resp = await fetch(url, opts);
|
|
107
|
+
if (!resp.ok) {
|
|
108
|
+
const text = await resp.text();
|
|
109
|
+
let err;
|
|
110
|
+
try {
|
|
111
|
+
// try to parse json
|
|
112
|
+
err = StatusCodeError.fromErrorResponse(JSON.parse(text), resp.status);
|
|
113
|
+
} catch {
|
|
114
|
+
err = new StatusCodeError(text, resp.status);
|
|
115
|
+
}
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
// check content type before trying to parse a response body as JSON
|
|
119
|
+
const contentType = resp.headers.get('content-type');
|
|
120
|
+
const json = contentType && contentType.startsWith('application/json');
|
|
121
|
+
|
|
122
|
+
// await result in order to be able to catch any error
|
|
123
|
+
return await (rawResponseBody || !json ? resp.buffer() : resp.json());
|
|
124
|
+
} catch (e) {
|
|
125
|
+
/* istanbul ignore else */
|
|
126
|
+
if (e instanceof StatusCodeError) {
|
|
127
|
+
throw e;
|
|
128
|
+
}
|
|
129
|
+
/* istanbul ignore next */
|
|
130
|
+
throw StatusCodeError.fromError(e);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
get log() {
|
|
135
|
+
return this._log;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = SharePointSite;
|
package/src/StatusCodeError.js
CHANGED
package/src/Table.d.ts
CHANGED
|
@@ -9,7 +9,14 @@
|
|
|
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 { GraphResult
|
|
12
|
+
import {DriveItem, GraphResult} from './OneDrive';
|
|
13
|
+
|
|
14
|
+
export declare interface FormatOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Trims the object names and values and strips zero-width unicode characters.
|
|
17
|
+
*/
|
|
18
|
+
trim?:boolean;
|
|
19
|
+
}
|
|
13
20
|
|
|
14
21
|
/**
|
|
15
22
|
* Excel Table
|
|
@@ -37,7 +44,7 @@ export declare interface Table {
|
|
|
37
44
|
* Returns the rows as a list of objects. the rows have the columns names as property names
|
|
38
45
|
* and the row values as value.
|
|
39
46
|
*/
|
|
40
|
-
getRowsAsObjects(): Promise<Array<object>>;
|
|
47
|
+
getRowsAsObjects(opts?:FormatOptions): Promise<Array<object>>;
|
|
41
48
|
|
|
42
49
|
/**
|
|
43
50
|
* Return a row given its index
|
|
@@ -85,5 +92,5 @@ export declare interface Table {
|
|
|
85
92
|
* @param index zero-based index or missing to add at end
|
|
86
93
|
* @returns new column
|
|
87
94
|
*/
|
|
88
|
-
addColumn(name, index
|
|
95
|
+
addColumn(name:string, index?:number): Promise<DriveItem>;
|
|
89
96
|
}
|
package/src/Table.js
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
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 { superTrim } = require('./utils.js');
|
|
13
|
+
|
|
12
14
|
class Table {
|
|
13
15
|
constructor(oneDrive, prefix, name, log) {
|
|
14
16
|
this._oneDrive = oneDrive;
|
|
@@ -39,7 +41,7 @@ class Table {
|
|
|
39
41
|
return result.value.map((v) => v.values[0]);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
async getRowsAsObjects() {
|
|
44
|
+
async getRowsAsObjects({ trim = false } = {}) {
|
|
43
45
|
const { log } = this;
|
|
44
46
|
this.log.debug(`get columns from ${this.uri}/columns`);
|
|
45
47
|
const result = await this._oneDrive.doFetch(`${this.uri}/columns`);
|
|
@@ -49,8 +51,13 @@ class Table {
|
|
|
49
51
|
const rowValues = result.value[0].values
|
|
50
52
|
.map((_, rownum) => columnNames.reduce((row, name, column) => {
|
|
51
53
|
const [value] = result.value[column].values[rownum];
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
if (trim) {
|
|
55
|
+
// eslint-disable-next-line no-param-reassign
|
|
56
|
+
row[superTrim(name)] = superTrim(value);
|
|
57
|
+
} else {
|
|
58
|
+
// eslint-disable-next-line no-param-reassign
|
|
59
|
+
row[name] = value;
|
|
60
|
+
}
|
|
54
61
|
return row;
|
|
55
62
|
}, {}));
|
|
56
63
|
|
package/src/utils.js
CHANGED
|
@@ -10,6 +10,23 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Trims the string at both ends and removes the zero width unicode chars:
|
|
15
|
+
*
|
|
16
|
+
* - U+200B zero width space
|
|
17
|
+
* - U+200C zero width non-joiner Unicode code point
|
|
18
|
+
* - U+200D zero width joiner Unicode code point
|
|
19
|
+
* - U+FEFF zero width no-break space Unicode code point
|
|
20
|
+
*
|
|
21
|
+
* @param {string} str input string
|
|
22
|
+
* @return {string} trimmed and stripped string
|
|
23
|
+
*/
|
|
24
|
+
function superTrim(str) {
|
|
25
|
+
return String(str)
|
|
26
|
+
.replace(/[\u200B-\u200D\uFEFF]/g, '')
|
|
27
|
+
.trim();
|
|
28
|
+
}
|
|
29
|
+
|
|
13
30
|
/**
|
|
14
31
|
* Returns a onedrive uri for the given drive item. the uri has the format:
|
|
15
32
|
* `onedrive:/drives/<driveId>/items/<itemId>`
|
|
@@ -55,4 +72,5 @@ function driveItemFromURL(url) {
|
|
|
55
72
|
module.exports = {
|
|
56
73
|
driveItemFromURL,
|
|
57
74
|
driveItemToURL,
|
|
75
|
+
superTrim,
|
|
58
76
|
};
|