@openfn/language-msgraph 0.1.1 → 0.3.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/ast.json +275 -0
- package/dist/index.cjs +141 -19
- package/dist/index.js +139 -23
- package/package.json +4 -4
- package/types/Adaptor.d.ts +45 -1
- package/types/Utils.d.ts +4 -3
package/ast.json
CHANGED
|
@@ -125,6 +125,207 @@
|
|
|
125
125
|
]
|
|
126
126
|
},
|
|
127
127
|
"valid": true
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"name": "getDrive",
|
|
131
|
+
"params": [
|
|
132
|
+
"specifier",
|
|
133
|
+
"name",
|
|
134
|
+
"callback"
|
|
135
|
+
],
|
|
136
|
+
"docs": {
|
|
137
|
+
"description": "Get a Drive or SharePoint document library. The drive metadata will be written\nto state.drives, where it can be used by other adaptor functions.\nPass { id } to get a drive by id or { id, owner } to get default drive for\nsome parent resource, like a group",
|
|
138
|
+
"tags": [
|
|
139
|
+
{
|
|
140
|
+
"title": "public",
|
|
141
|
+
"description": null,
|
|
142
|
+
"type": null
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"title": "example",
|
|
146
|
+
"description": "getDrive({ id: \"YXzpkoLwR06bxC8tNdg71m\" })",
|
|
147
|
+
"caption": "Get a drive by ID"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"title": "example",
|
|
151
|
+
"description": "getDrive({ id: \"openfn.sharepoint.com\", owner: \"sites\" })",
|
|
152
|
+
"caption": "Get the default drive for a site"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"title": "param",
|
|
156
|
+
"description": "{Object} - A definition of the drive to retrieve\n - id {string} - The ID of the resource or owner.\n - owner {string} - The type of drive owner (e.g. sites, groups).",
|
|
157
|
+
"type": null,
|
|
158
|
+
"name": "specifier"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"title": "param",
|
|
162
|
+
"description": "The local name of the drive used to write to state.drives, ie, state.drives[name]",
|
|
163
|
+
"type": {
|
|
164
|
+
"type": "NameExpression",
|
|
165
|
+
"name": "string"
|
|
166
|
+
},
|
|
167
|
+
"name": "name"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"title": "param",
|
|
171
|
+
"description": "(Optional) Callback function",
|
|
172
|
+
"type": {
|
|
173
|
+
"type": "OptionalType",
|
|
174
|
+
"expression": {
|
|
175
|
+
"type": "NameExpression",
|
|
176
|
+
"name": "function"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"name": "callback",
|
|
180
|
+
"default": "s=>s"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"title": "return",
|
|
184
|
+
"description": null,
|
|
185
|
+
"type": {
|
|
186
|
+
"type": "NameExpression",
|
|
187
|
+
"name": "Operation"
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
"valid": true
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"name": "getFolder",
|
|
196
|
+
"params": [
|
|
197
|
+
"pathOrId",
|
|
198
|
+
"options",
|
|
199
|
+
"callback"
|
|
200
|
+
],
|
|
201
|
+
"docs": {
|
|
202
|
+
"description": "Get the contents or metadata of a folder.",
|
|
203
|
+
"tags": [
|
|
204
|
+
{
|
|
205
|
+
"title": "public",
|
|
206
|
+
"description": null,
|
|
207
|
+
"type": null
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"title": "example",
|
|
211
|
+
"description": "getFolder('01LUM6XOCKDTZKQC7AVZF2VMHE2I3O6OY3')",
|
|
212
|
+
"caption": "Get a folder by ID"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"title": "example",
|
|
216
|
+
"description": "getFolder(\"01LUM6XOCKDTZKQC7AVZF2VMHE2I3O6OY3\",{ driveName: \"mydrive\"})",
|
|
217
|
+
"caption": "Get a folder for a named drive by id"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"title": "param",
|
|
221
|
+
"description": "A path to a folder or folder id",
|
|
222
|
+
"type": {
|
|
223
|
+
"type": "NameExpression",
|
|
224
|
+
"name": "string"
|
|
225
|
+
},
|
|
226
|
+
"name": "pathOrId"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"title": "param",
|
|
230
|
+
"description": "(Optional) Query parameters",
|
|
231
|
+
"type": {
|
|
232
|
+
"type": "NameExpression",
|
|
233
|
+
"name": "object"
|
|
234
|
+
},
|
|
235
|
+
"name": "options"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"title": "param",
|
|
239
|
+
"description": "(Optional) Callback function",
|
|
240
|
+
"type": {
|
|
241
|
+
"type": "OptionalType",
|
|
242
|
+
"expression": {
|
|
243
|
+
"type": "NameExpression",
|
|
244
|
+
"name": "function"
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
"name": "callback",
|
|
248
|
+
"default": "s=>s"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"title": "return",
|
|
252
|
+
"description": null,
|
|
253
|
+
"type": {
|
|
254
|
+
"type": "NameExpression",
|
|
255
|
+
"name": "Operation"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
"valid": true
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"name": "getFile",
|
|
264
|
+
"params": [
|
|
265
|
+
"pathOrId",
|
|
266
|
+
"options",
|
|
267
|
+
"callback"
|
|
268
|
+
],
|
|
269
|
+
"docs": {
|
|
270
|
+
"description": "Get file metadata or file content.",
|
|
271
|
+
"tags": [
|
|
272
|
+
{
|
|
273
|
+
"title": "public",
|
|
274
|
+
"description": null,
|
|
275
|
+
"type": null
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"title": "example",
|
|
279
|
+
"description": "getFile('01LUM6XOGRONYNTZ26DBBJPTN5IFTQPBIW')",
|
|
280
|
+
"caption": "Get a file by ID"
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"title": "example",
|
|
284
|
+
"description": "getFile(\"01LUM6XOGRONYNTZ26DBBJPTN5IFTQPBIW\",{ driveName: \"mydrive\"})",
|
|
285
|
+
"caption": "Get a file for a named drive by id"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"title": "param",
|
|
289
|
+
"description": "A path to a file or file id",
|
|
290
|
+
"type": {
|
|
291
|
+
"type": "NameExpression",
|
|
292
|
+
"name": "string"
|
|
293
|
+
},
|
|
294
|
+
"name": "pathOrId"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"title": "param",
|
|
298
|
+
"description": "(Optional) Query parameters",
|
|
299
|
+
"type": {
|
|
300
|
+
"type": "NameExpression",
|
|
301
|
+
"name": "object"
|
|
302
|
+
},
|
|
303
|
+
"name": "options"
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"title": "param",
|
|
307
|
+
"description": "(Optional) Callback function",
|
|
308
|
+
"type": {
|
|
309
|
+
"type": "OptionalType",
|
|
310
|
+
"expression": {
|
|
311
|
+
"type": "NameExpression",
|
|
312
|
+
"name": "function"
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
"name": "callback",
|
|
316
|
+
"default": "s=>s"
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"title": "return",
|
|
320
|
+
"description": null,
|
|
321
|
+
"type": {
|
|
322
|
+
"type": "NameExpression",
|
|
323
|
+
"name": "Operation"
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
]
|
|
327
|
+
},
|
|
328
|
+
"valid": true
|
|
128
329
|
}
|
|
129
330
|
],
|
|
130
331
|
"exports": [],
|
|
@@ -545,6 +746,80 @@
|
|
|
545
746
|
]
|
|
546
747
|
},
|
|
547
748
|
"valid": true
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
"name": "parseCsv",
|
|
752
|
+
"params": [
|
|
753
|
+
"csvData",
|
|
754
|
+
"parsingOptions",
|
|
755
|
+
"callback"
|
|
756
|
+
],
|
|
757
|
+
"docs": {
|
|
758
|
+
"description": "Takes a CSV file string or stream and parsing options as input, and returns a promise that\nresolves to the parsed CSV data as an array of objects.\nOptions for `parsingOptions` include:\n- `delimiter` {string/Buffer/[string/Buffer]} - Defines the character(s) used to delineate the fields inside a record. Default: `','`\n- `quote` {string/Buffer/[string/Buffer]} - Defines the characters used to surround a field. Default: `'\"'`\n- `escape` {Buffer/string/null/boolean} - Set the escape character as one character/byte only. Default: `\"`\n- `columns` {boolean / array / function} - Generates record in the form of object literals. Default: `true`\n- `bom` {boolean} - Strips the {@link https://en.wikipedia.org/wiki/Byte_order_mark byte order mark (BOM)} from the input string or buffer. Default: `true`\n- `trim` {boolean} - Ignore whitespace characters immediately around the `delimiter`. Default: `true`\n- `ltrim` {boolean} - Ignore whitespace characters from the left side of a CSV field. Default: `true`\n- `rtrim` {boolean} - Ignore whitespace characters from the right side of a CSV field. Default: `true`\n- `chunkSize` {number} - The size of each chunk of CSV data. Default: `Infinity`\n- `skip_empty_lines` {boolean} - Ignore empty lines in the CSV file. Default: `true`",
|
|
759
|
+
"tags": [
|
|
760
|
+
{
|
|
761
|
+
"title": "public",
|
|
762
|
+
"description": null,
|
|
763
|
+
"type": null
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
"title": "function",
|
|
767
|
+
"description": null,
|
|
768
|
+
"name": null
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
"title": "param",
|
|
772
|
+
"description": "A CSV string or a readable stream",
|
|
773
|
+
"type": {
|
|
774
|
+
"type": "UnionType",
|
|
775
|
+
"elements": [
|
|
776
|
+
{
|
|
777
|
+
"type": "NameExpression",
|
|
778
|
+
"name": "String"
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
"type": "NameExpression",
|
|
782
|
+
"name": "Stream"
|
|
783
|
+
}
|
|
784
|
+
]
|
|
785
|
+
},
|
|
786
|
+
"name": "csvData"
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
"title": "param",
|
|
790
|
+
"description": "Optional. Parsing options for converting CSV to JSON.",
|
|
791
|
+
"type": {
|
|
792
|
+
"type": "OptionalType",
|
|
793
|
+
"expression": {
|
|
794
|
+
"type": "NameExpression",
|
|
795
|
+
"name": "Object"
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
"name": "parsingOptions"
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
"title": "param",
|
|
802
|
+
"description": "(Optional) callback function. If used it will be called state and an array of rows.",
|
|
803
|
+
"type": {
|
|
804
|
+
"type": "OptionalType",
|
|
805
|
+
"expression": {
|
|
806
|
+
"type": "NameExpression",
|
|
807
|
+
"name": "function"
|
|
808
|
+
}
|
|
809
|
+
},
|
|
810
|
+
"name": "callback"
|
|
811
|
+
},
|
|
812
|
+
{
|
|
813
|
+
"title": "returns",
|
|
814
|
+
"description": "The function returns a Promise that resolves to the result of parsing a CSV `stringOrStream`.",
|
|
815
|
+
"type": {
|
|
816
|
+
"type": "NameExpression",
|
|
817
|
+
"name": "Operation"
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
]
|
|
821
|
+
},
|
|
822
|
+
"valid": true
|
|
548
823
|
}
|
|
549
824
|
]
|
|
550
825
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -30,8 +30,12 @@ __export(src_exports, {
|
|
|
30
30
|
fields: () => import_language_common3.fields,
|
|
31
31
|
fn: () => import_language_common3.fn,
|
|
32
32
|
get: () => get,
|
|
33
|
+
getDrive: () => getDrive,
|
|
34
|
+
getFile: () => getFile,
|
|
35
|
+
getFolder: () => getFolder,
|
|
33
36
|
lastReferenceValue: () => import_language_common3.lastReferenceValue,
|
|
34
37
|
merge: () => import_language_common3.merge,
|
|
38
|
+
parseCsv: () => import_language_common3.parseCsv,
|
|
35
39
|
request: () => request,
|
|
36
40
|
sourceValue: () => import_language_common3.sourceValue
|
|
37
41
|
});
|
|
@@ -50,20 +54,35 @@ __export(Adaptor_exports, {
|
|
|
50
54
|
fields: () => import_language_common3.fields,
|
|
51
55
|
fn: () => import_language_common3.fn,
|
|
52
56
|
get: () => get,
|
|
57
|
+
getDrive: () => getDrive,
|
|
58
|
+
getFile: () => getFile,
|
|
59
|
+
getFolder: () => getFolder,
|
|
53
60
|
lastReferenceValue: () => import_language_common3.lastReferenceValue,
|
|
54
61
|
merge: () => import_language_common3.merge,
|
|
62
|
+
parseCsv: () => import_language_common3.parseCsv,
|
|
55
63
|
request: () => request,
|
|
56
64
|
sourceValue: () => import_language_common3.sourceValue
|
|
57
65
|
});
|
|
58
66
|
var import_language_common2 = require("@openfn/language-common");
|
|
67
|
+
var import_util = require("@openfn/language-common/util");
|
|
59
68
|
|
|
60
69
|
// src/Utils.js
|
|
70
|
+
var import_undici = require("undici");
|
|
61
71
|
var import_language_common = require("@openfn/language-common");
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
function assertDrive(state, driveName) {
|
|
73
|
+
if (!state.drives[driveName]) {
|
|
74
|
+
const errorString = [
|
|
75
|
+
`Drive is not defined.`,
|
|
76
|
+
`At the top of your job you should define all the drives you want to use.`,
|
|
77
|
+
`eg: getDrive({ id: "openfn.sharepoint.com", owner: "sites"})`
|
|
78
|
+
].join("\n \u221F ");
|
|
79
|
+
throw new Error(errorString);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function getUrl(resource, apiVersion) {
|
|
83
|
+
if (isValidHttpUrl(resource))
|
|
84
|
+
return resource;
|
|
85
|
+
const pathSuffix = apiVersion ? `${apiVersion}/${resource}` : `v1.0/${resource}`;
|
|
67
86
|
return `https://graph.microsoft.com/${pathSuffix}`;
|
|
68
87
|
}
|
|
69
88
|
function isValidHttpUrl(string) {
|
|
@@ -75,7 +94,7 @@ function isValidHttpUrl(string) {
|
|
|
75
94
|
}
|
|
76
95
|
return url.protocol === "http:" || url.protocol === "https:";
|
|
77
96
|
}
|
|
78
|
-
function
|
|
97
|
+
function getAuth(token) {
|
|
79
98
|
return token ? { headers: { Authorization: `Bearer ${token}` } } : null;
|
|
80
99
|
}
|
|
81
100
|
function handleResponse(response, state, callback) {
|
|
@@ -114,7 +133,7 @@ var request = async (urlString, params = {}, method = "GET") => {
|
|
|
114
133
|
} else {
|
|
115
134
|
options.body = JSON.stringify(params);
|
|
116
135
|
}
|
|
117
|
-
const response = await fetch(url, options);
|
|
136
|
+
const response = await (0, import_undici.fetch)(url, options);
|
|
118
137
|
const contentType = response.headers.get("Content-Type");
|
|
119
138
|
const data = (contentType == null ? void 0 : contentType.includes("application/json")) ? await response.json() : await response.text();
|
|
120
139
|
handleResponseError(response, data, method);
|
|
@@ -126,25 +145,33 @@ var import_language_common3 = require("@openfn/language-common");
|
|
|
126
145
|
function execute(...operations) {
|
|
127
146
|
const initialState = {
|
|
128
147
|
references: [],
|
|
129
|
-
data: null
|
|
148
|
+
data: null,
|
|
149
|
+
drives: {}
|
|
150
|
+
};
|
|
151
|
+
const cleanup = (finalState) => {
|
|
152
|
+
const { drives, ...rest } = finalState;
|
|
153
|
+
return rest;
|
|
130
154
|
};
|
|
131
155
|
return (state) => {
|
|
132
156
|
return (0, import_language_common2.execute)(...operations)({
|
|
133
157
|
...initialState,
|
|
134
158
|
...state
|
|
135
|
-
});
|
|
159
|
+
}).then(cleanup).catch(cleanup);
|
|
136
160
|
};
|
|
137
161
|
}
|
|
138
162
|
function create(resource, data, callback) {
|
|
139
163
|
return (state) => {
|
|
140
|
-
const
|
|
141
|
-
|
|
164
|
+
const [resolvedResource, resolvedData] = (0, import_util.expandReferences)(
|
|
165
|
+
state,
|
|
166
|
+
resource,
|
|
167
|
+
data
|
|
168
|
+
);
|
|
142
169
|
const { accessToken, apiVersion } = state.configuration;
|
|
143
|
-
const url =
|
|
144
|
-
const auth =
|
|
170
|
+
const url = getUrl({ apiVersion, resolvedResource });
|
|
171
|
+
const auth = getAuth(accessToken);
|
|
145
172
|
const options = {
|
|
146
173
|
auth,
|
|
147
|
-
...
|
|
174
|
+
...resolvedData
|
|
148
175
|
};
|
|
149
176
|
return request(url, options, "POST").then(
|
|
150
177
|
(response) => handleResponse(response, state, callback)
|
|
@@ -153,12 +180,103 @@ function create(resource, data, callback) {
|
|
|
153
180
|
}
|
|
154
181
|
function get(path, query, callback = false) {
|
|
155
182
|
return (state) => {
|
|
156
|
-
const resolvePath = (0, import_language_common2.expandReferences)(path)(state);
|
|
157
|
-
const resolveQuery = (0, import_language_common2.expandReferences)(query)(state);
|
|
158
183
|
const { accessToken, apiVersion } = state.configuration;
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
|
|
184
|
+
const [resolvedPath, resolvedQuery] = (0, import_util.expandReferences)(state, path, query);
|
|
185
|
+
const url = getUrl(resolvedPath, apiVersion);
|
|
186
|
+
const auth = getAuth(accessToken);
|
|
187
|
+
return request(url, { ...resolvedQuery, ...auth }).then(
|
|
188
|
+
(response) => handleResponse(response, state, callback)
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function getDrive(specifier, name = "default", callback = (s) => s) {
|
|
193
|
+
return (state) => {
|
|
194
|
+
const { accessToken, apiVersion } = state.configuration;
|
|
195
|
+
const [resolvedSpecifier, resolvedName] = (0, import_util.expandReferences)(
|
|
196
|
+
state,
|
|
197
|
+
specifier,
|
|
198
|
+
name
|
|
199
|
+
);
|
|
200
|
+
const { id, owner = "drive" } = resolvedSpecifier;
|
|
201
|
+
let resource;
|
|
202
|
+
if (owner === "drive") {
|
|
203
|
+
resource = `drives/${id}`;
|
|
204
|
+
} else {
|
|
205
|
+
resource = `${owner}/${id}/drive`;
|
|
206
|
+
}
|
|
207
|
+
const url = getUrl(resource, apiVersion);
|
|
208
|
+
const auth = getAuth(accessToken);
|
|
209
|
+
return request(url, { ...auth }).then((response) => {
|
|
210
|
+
state.drives[resolvedName] = response;
|
|
211
|
+
return callback(state);
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function getFolder(pathOrId, options, callback = (s) => s) {
|
|
216
|
+
return async (state) => {
|
|
217
|
+
const defaultOptions = {
|
|
218
|
+
driveName: "default",
|
|
219
|
+
metadata: false
|
|
220
|
+
};
|
|
221
|
+
const { accessToken, apiVersion } = state.configuration;
|
|
222
|
+
const [resolvedPathOrId, resolvedOptions] = (0, import_util.expandReferences)(
|
|
223
|
+
state,
|
|
224
|
+
pathOrId,
|
|
225
|
+
options
|
|
226
|
+
);
|
|
227
|
+
const { driveName, metadata } = { ...defaultOptions, ...resolvedOptions };
|
|
228
|
+
assertDrive(state, driveName);
|
|
229
|
+
const { id: driveId } = state.drives[driveName];
|
|
230
|
+
let resource;
|
|
231
|
+
if (resolvedPathOrId.startsWith("/")) {
|
|
232
|
+
resource = `drives/${driveId}/root:/${encodeURIComponent(
|
|
233
|
+
resolvedPathOrId
|
|
234
|
+
)}`;
|
|
235
|
+
} else {
|
|
236
|
+
resource = `drives/${driveId}/items/${resolvedPathOrId}`;
|
|
237
|
+
}
|
|
238
|
+
if (!metadata) {
|
|
239
|
+
resource += resolvedPathOrId.startsWith("/") ? ":/children" : "/children";
|
|
240
|
+
}
|
|
241
|
+
const url = getUrl(resource, apiVersion);
|
|
242
|
+
const auth = getAuth(accessToken);
|
|
243
|
+
return request(url, { ...auth }).then(
|
|
244
|
+
(response) => handleResponse(response, state, callback)
|
|
245
|
+
);
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function getFile(pathOrId, options, callback = (s) => s) {
|
|
249
|
+
return async (state) => {
|
|
250
|
+
const defaultOptions = {
|
|
251
|
+
driveName: "default",
|
|
252
|
+
metadata: false
|
|
253
|
+
};
|
|
254
|
+
const { accessToken, apiVersion } = state.configuration;
|
|
255
|
+
const [resolvedPathOrId, resolvedOptions] = (0, import_util.expandReferences)(
|
|
256
|
+
state,
|
|
257
|
+
pathOrId,
|
|
258
|
+
options
|
|
259
|
+
);
|
|
260
|
+
const { driveName, metadata } = {
|
|
261
|
+
...defaultOptions,
|
|
262
|
+
...resolvedOptions
|
|
263
|
+
};
|
|
264
|
+
assertDrive(state, driveName);
|
|
265
|
+
const { id: driveId } = state.drives[driveName];
|
|
266
|
+
let resource;
|
|
267
|
+
if (resolvedPathOrId.startsWith("/")) {
|
|
268
|
+
resource = `drives/${driveId}/root:/${encodeURIComponent(
|
|
269
|
+
resolvedPathOrId
|
|
270
|
+
)}`;
|
|
271
|
+
} else {
|
|
272
|
+
resource = `drives/${driveId}/items/${resolvedPathOrId}`;
|
|
273
|
+
}
|
|
274
|
+
if (!metadata) {
|
|
275
|
+
resource += resolvedPathOrId.startsWith("/") ? ":/content" : "/content";
|
|
276
|
+
}
|
|
277
|
+
const url = getUrl(resource, apiVersion);
|
|
278
|
+
const auth = getAuth(accessToken);
|
|
279
|
+
return request(url, { ...auth }).then(
|
|
162
280
|
(response) => handleResponse(response, state, callback)
|
|
163
281
|
);
|
|
164
282
|
};
|
|
@@ -178,8 +296,12 @@ var src_default = Adaptor_exports;
|
|
|
178
296
|
fields,
|
|
179
297
|
fn,
|
|
180
298
|
get,
|
|
299
|
+
getDrive,
|
|
300
|
+
getFile,
|
|
301
|
+
getFolder,
|
|
181
302
|
lastReferenceValue,
|
|
182
303
|
merge,
|
|
304
|
+
parseCsv,
|
|
183
305
|
request,
|
|
184
306
|
sourceValue
|
|
185
307
|
});
|
package/dist/index.js
CHANGED
|
@@ -17,23 +17,35 @@ __export(Adaptor_exports, {
|
|
|
17
17
|
fields: () => fields,
|
|
18
18
|
fn: () => fn,
|
|
19
19
|
get: () => get,
|
|
20
|
+
getDrive: () => getDrive,
|
|
21
|
+
getFile: () => getFile,
|
|
22
|
+
getFolder: () => getFolder,
|
|
20
23
|
lastReferenceValue: () => lastReferenceValue,
|
|
21
24
|
merge: () => merge,
|
|
25
|
+
parseCsv: () => parseCsv,
|
|
22
26
|
request: () => request,
|
|
23
27
|
sourceValue: () => sourceValue
|
|
24
28
|
});
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
expandReferences
|
|
28
|
-
} from "@openfn/language-common";
|
|
29
|
+
import { execute as commonExecute } from "@openfn/language-common";
|
|
30
|
+
import { expandReferences } from "@openfn/language-common/util";
|
|
29
31
|
|
|
30
32
|
// src/Utils.js
|
|
33
|
+
import { fetch } from "undici";
|
|
31
34
|
import { composeNextState } from "@openfn/language-common";
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
function assertDrive(state, driveName) {
|
|
36
|
+
if (!state.drives[driveName]) {
|
|
37
|
+
const errorString = [
|
|
38
|
+
`Drive is not defined.`,
|
|
39
|
+
`At the top of your job you should define all the drives you want to use.`,
|
|
40
|
+
`eg: getDrive({ id: "openfn.sharepoint.com", owner: "sites"})`
|
|
41
|
+
].join("\n \u221F ");
|
|
42
|
+
throw new Error(errorString);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function getUrl(resource, apiVersion) {
|
|
46
|
+
if (isValidHttpUrl(resource))
|
|
47
|
+
return resource;
|
|
48
|
+
const pathSuffix = apiVersion ? `${apiVersion}/${resource}` : `v1.0/${resource}`;
|
|
37
49
|
return `https://graph.microsoft.com/${pathSuffix}`;
|
|
38
50
|
}
|
|
39
51
|
function isValidHttpUrl(string) {
|
|
@@ -45,7 +57,7 @@ function isValidHttpUrl(string) {
|
|
|
45
57
|
}
|
|
46
58
|
return url.protocol === "http:" || url.protocol === "https:";
|
|
47
59
|
}
|
|
48
|
-
function
|
|
60
|
+
function getAuth(token) {
|
|
49
61
|
return token ? { headers: { Authorization: `Bearer ${token}` } } : null;
|
|
50
62
|
}
|
|
51
63
|
function handleResponse(response, state, callback) {
|
|
@@ -102,30 +114,39 @@ import {
|
|
|
102
114
|
fn,
|
|
103
115
|
lastReferenceValue,
|
|
104
116
|
merge,
|
|
105
|
-
sourceValue
|
|
117
|
+
sourceValue,
|
|
118
|
+
parseCsv
|
|
106
119
|
} from "@openfn/language-common";
|
|
107
120
|
function execute(...operations) {
|
|
108
121
|
const initialState = {
|
|
109
122
|
references: [],
|
|
110
|
-
data: null
|
|
123
|
+
data: null,
|
|
124
|
+
drives: {}
|
|
125
|
+
};
|
|
126
|
+
const cleanup = (finalState) => {
|
|
127
|
+
const { drives, ...rest } = finalState;
|
|
128
|
+
return rest;
|
|
111
129
|
};
|
|
112
130
|
return (state) => {
|
|
113
131
|
return commonExecute(...operations)({
|
|
114
132
|
...initialState,
|
|
115
133
|
...state
|
|
116
|
-
});
|
|
134
|
+
}).then(cleanup).catch(cleanup);
|
|
117
135
|
};
|
|
118
136
|
}
|
|
119
137
|
function create(resource, data, callback) {
|
|
120
138
|
return (state) => {
|
|
121
|
-
const
|
|
122
|
-
|
|
139
|
+
const [resolvedResource, resolvedData] = expandReferences(
|
|
140
|
+
state,
|
|
141
|
+
resource,
|
|
142
|
+
data
|
|
143
|
+
);
|
|
123
144
|
const { accessToken, apiVersion } = state.configuration;
|
|
124
|
-
const url =
|
|
125
|
-
const auth =
|
|
145
|
+
const url = getUrl({ apiVersion, resolvedResource });
|
|
146
|
+
const auth = getAuth(accessToken);
|
|
126
147
|
const options = {
|
|
127
148
|
auth,
|
|
128
|
-
...
|
|
149
|
+
...resolvedData
|
|
129
150
|
};
|
|
130
151
|
return request(url, options, "POST").then(
|
|
131
152
|
(response) => handleResponse(response, state, callback)
|
|
@@ -134,12 +155,103 @@ function create(resource, data, callback) {
|
|
|
134
155
|
}
|
|
135
156
|
function get(path, query, callback = false) {
|
|
136
157
|
return (state) => {
|
|
137
|
-
const resolvePath = expandReferences(path)(state);
|
|
138
|
-
const resolveQuery = expandReferences(query)(state);
|
|
139
158
|
const { accessToken, apiVersion } = state.configuration;
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
|
|
159
|
+
const [resolvedPath, resolvedQuery] = expandReferences(state, path, query);
|
|
160
|
+
const url = getUrl(resolvedPath, apiVersion);
|
|
161
|
+
const auth = getAuth(accessToken);
|
|
162
|
+
return request(url, { ...resolvedQuery, ...auth }).then(
|
|
163
|
+
(response) => handleResponse(response, state, callback)
|
|
164
|
+
);
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function getDrive(specifier, name = "default", callback = (s) => s) {
|
|
168
|
+
return (state) => {
|
|
169
|
+
const { accessToken, apiVersion } = state.configuration;
|
|
170
|
+
const [resolvedSpecifier, resolvedName] = expandReferences(
|
|
171
|
+
state,
|
|
172
|
+
specifier,
|
|
173
|
+
name
|
|
174
|
+
);
|
|
175
|
+
const { id, owner = "drive" } = resolvedSpecifier;
|
|
176
|
+
let resource;
|
|
177
|
+
if (owner === "drive") {
|
|
178
|
+
resource = `drives/${id}`;
|
|
179
|
+
} else {
|
|
180
|
+
resource = `${owner}/${id}/drive`;
|
|
181
|
+
}
|
|
182
|
+
const url = getUrl(resource, apiVersion);
|
|
183
|
+
const auth = getAuth(accessToken);
|
|
184
|
+
return request(url, { ...auth }).then((response) => {
|
|
185
|
+
state.drives[resolvedName] = response;
|
|
186
|
+
return callback(state);
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function getFolder(pathOrId, options, callback = (s) => s) {
|
|
191
|
+
return async (state) => {
|
|
192
|
+
const defaultOptions = {
|
|
193
|
+
driveName: "default",
|
|
194
|
+
metadata: false
|
|
195
|
+
};
|
|
196
|
+
const { accessToken, apiVersion } = state.configuration;
|
|
197
|
+
const [resolvedPathOrId, resolvedOptions] = expandReferences(
|
|
198
|
+
state,
|
|
199
|
+
pathOrId,
|
|
200
|
+
options
|
|
201
|
+
);
|
|
202
|
+
const { driveName, metadata } = { ...defaultOptions, ...resolvedOptions };
|
|
203
|
+
assertDrive(state, driveName);
|
|
204
|
+
const { id: driveId } = state.drives[driveName];
|
|
205
|
+
let resource;
|
|
206
|
+
if (resolvedPathOrId.startsWith("/")) {
|
|
207
|
+
resource = `drives/${driveId}/root:/${encodeURIComponent(
|
|
208
|
+
resolvedPathOrId
|
|
209
|
+
)}`;
|
|
210
|
+
} else {
|
|
211
|
+
resource = `drives/${driveId}/items/${resolvedPathOrId}`;
|
|
212
|
+
}
|
|
213
|
+
if (!metadata) {
|
|
214
|
+
resource += resolvedPathOrId.startsWith("/") ? ":/children" : "/children";
|
|
215
|
+
}
|
|
216
|
+
const url = getUrl(resource, apiVersion);
|
|
217
|
+
const auth = getAuth(accessToken);
|
|
218
|
+
return request(url, { ...auth }).then(
|
|
219
|
+
(response) => handleResponse(response, state, callback)
|
|
220
|
+
);
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function getFile(pathOrId, options, callback = (s) => s) {
|
|
224
|
+
return async (state) => {
|
|
225
|
+
const defaultOptions = {
|
|
226
|
+
driveName: "default",
|
|
227
|
+
metadata: false
|
|
228
|
+
};
|
|
229
|
+
const { accessToken, apiVersion } = state.configuration;
|
|
230
|
+
const [resolvedPathOrId, resolvedOptions] = expandReferences(
|
|
231
|
+
state,
|
|
232
|
+
pathOrId,
|
|
233
|
+
options
|
|
234
|
+
);
|
|
235
|
+
const { driveName, metadata } = {
|
|
236
|
+
...defaultOptions,
|
|
237
|
+
...resolvedOptions
|
|
238
|
+
};
|
|
239
|
+
assertDrive(state, driveName);
|
|
240
|
+
const { id: driveId } = state.drives[driveName];
|
|
241
|
+
let resource;
|
|
242
|
+
if (resolvedPathOrId.startsWith("/")) {
|
|
243
|
+
resource = `drives/${driveId}/root:/${encodeURIComponent(
|
|
244
|
+
resolvedPathOrId
|
|
245
|
+
)}`;
|
|
246
|
+
} else {
|
|
247
|
+
resource = `drives/${driveId}/items/${resolvedPathOrId}`;
|
|
248
|
+
}
|
|
249
|
+
if (!metadata) {
|
|
250
|
+
resource += resolvedPathOrId.startsWith("/") ? ":/content" : "/content";
|
|
251
|
+
}
|
|
252
|
+
const url = getUrl(resource, apiVersion);
|
|
253
|
+
const auth = getAuth(accessToken);
|
|
254
|
+
return request(url, { ...auth }).then(
|
|
143
255
|
(response) => handleResponse(response, state, callback)
|
|
144
256
|
);
|
|
145
257
|
};
|
|
@@ -159,8 +271,12 @@ export {
|
|
|
159
271
|
fields,
|
|
160
272
|
fn,
|
|
161
273
|
get,
|
|
274
|
+
getDrive,
|
|
275
|
+
getFile,
|
|
276
|
+
getFolder,
|
|
162
277
|
lastReferenceValue,
|
|
163
278
|
merge,
|
|
279
|
+
parseCsv,
|
|
164
280
|
request,
|
|
165
281
|
sourceValue
|
|
166
282
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/language-msgraph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Microsoft Graph Language Pack for OpenFn",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"configuration-schema.json"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@openfn/language-common": "^1.10.
|
|
22
|
+
"@openfn/language-common": "^1.10.1",
|
|
23
|
+
"undici": "^5.22.1"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@openfn/buildtools": "^1.0.2",
|
|
@@ -29,8 +30,7 @@
|
|
|
29
30
|
"deep-eql": "4.1.1",
|
|
30
31
|
"esno": "^0.16.3",
|
|
31
32
|
"mocha": "9.2.2",
|
|
32
|
-
"rimraf": "3.0.2"
|
|
33
|
-
"undici": "^5.22.1"
|
|
33
|
+
"rimraf": "3.0.2"
|
|
34
34
|
},
|
|
35
35
|
"repository": {
|
|
36
36
|
"type": "git",
|
package/types/Adaptor.d.ts
CHANGED
|
@@ -35,5 +35,49 @@ export function create(resource: string, data: object, callback: Function): Oper
|
|
|
35
35
|
* @returns {Operation}
|
|
36
36
|
*/
|
|
37
37
|
export function get(path: string, query: object, callback?: Function): Operation;
|
|
38
|
+
/**
|
|
39
|
+
* Get a Drive or SharePoint document library. The drive metadata will be written
|
|
40
|
+
* to state.drives, where it can be used by other adaptor functions.
|
|
41
|
+
* Pass { id } to get a drive by id or { id, owner } to get default drive for
|
|
42
|
+
* some parent resource, like a group
|
|
43
|
+
* @public
|
|
44
|
+
* @example <caption>Get a drive by ID</caption>
|
|
45
|
+
* getDrive({ id: "YXzpkoLwR06bxC8tNdg71m" })
|
|
46
|
+
* @example <caption>Get the default drive for a site</caption>
|
|
47
|
+
* getDrive({ id: "openfn.sharepoint.com", owner: "sites" })
|
|
48
|
+
* @param specifier {Object} - A definition of the drive to retrieve
|
|
49
|
+
* - id {string} - The ID of the resource or owner.
|
|
50
|
+
* - owner {string} - The type of drive owner (e.g. sites, groups).
|
|
51
|
+
* @param {string} name - The local name of the drive used to write to state.drives, ie, state.drives[name]
|
|
52
|
+
* @param {function} [callback = s => s] (Optional) Callback function
|
|
53
|
+
* @return {Operation}
|
|
54
|
+
*/
|
|
55
|
+
export function getDrive(specifier: any, name?: string, callback?: Function): Operation;
|
|
56
|
+
/**
|
|
57
|
+
* Get the contents or metadata of a folder.
|
|
58
|
+
* @public
|
|
59
|
+
* @example <caption>Get a folder by ID</caption>
|
|
60
|
+
* getFolder('01LUM6XOCKDTZKQC7AVZF2VMHE2I3O6OY3')
|
|
61
|
+
* @example <caption>Get a folder for a named drive by id</caption>
|
|
62
|
+
* getFolder("01LUM6XOCKDTZKQC7AVZF2VMHE2I3O6OY3",{ driveName: "mydrive"})
|
|
63
|
+
* @param {string} pathOrId - A path to a folder or folder id
|
|
64
|
+
* @param {object} options - (Optional) Query parameters
|
|
65
|
+
* @param {function} [callback = s => s] (Optional) Callback function
|
|
66
|
+
* @return {Operation}
|
|
67
|
+
*/
|
|
68
|
+
export function getFolder(pathOrId: string, options: object, callback?: Function): Operation;
|
|
69
|
+
/**
|
|
70
|
+
* Get file metadata or file content.
|
|
71
|
+
* @public
|
|
72
|
+
* @example <caption>Get a file by ID</caption>
|
|
73
|
+
* getFile('01LUM6XOGRONYNTZ26DBBJPTN5IFTQPBIW')
|
|
74
|
+
* @example <caption>Get a file for a named drive by id</caption>
|
|
75
|
+
* getFile("01LUM6XOGRONYNTZ26DBBJPTN5IFTQPBIW",{ driveName: "mydrive"})
|
|
76
|
+
* @param {string} pathOrId - A path to a file or file id
|
|
77
|
+
* @param {object} options - (Optional) Query parameters
|
|
78
|
+
* @param {function} [callback = s => s] (Optional) Callback function
|
|
79
|
+
* @return {Operation}
|
|
80
|
+
*/
|
|
81
|
+
export function getFile(pathOrId: string, options: object, callback?: Function): Operation;
|
|
38
82
|
export { request } from "./Utils";
|
|
39
|
-
export { dataPath, dataValue, dateFns, each, field, fields, fn, lastReferenceValue, merge, sourceValue } from "@openfn/language-common";
|
|
83
|
+
export { dataPath, dataValue, dateFns, each, field, fields, fn, lastReferenceValue, merge, sourceValue, parseCsv } from "@openfn/language-common";
|
package/types/Utils.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export function
|
|
2
|
-
export function
|
|
1
|
+
export function assertDrive(state: any, driveName: any): void;
|
|
2
|
+
export function getUrl(resource: any, apiVersion: any): any;
|
|
3
|
+
export function getAuth(token: any): {
|
|
3
4
|
headers: {
|
|
4
5
|
Authorization: string;
|
|
5
6
|
};
|
|
6
7
|
};
|
|
7
8
|
export function handleResponse(response: any, state: any, callback: any): any;
|
|
8
9
|
export function handleResponseError(response: any, data: any, method: any): void;
|
|
9
|
-
export function request(urlString: any, params?: object, method?: string): Promise<
|
|
10
|
+
export function request(urlString: any, params?: object, method?: string): Promise<unknown>;
|