@openfn/language-kobotoolbox 2.4.3 → 3.0.1
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 +51 -49
- package/configuration-schema.json +3 -3
- package/dist/index.cjs +203 -83
- package/dist/index.js +181 -59
- package/package.json +2 -4
- package/types/Adaptor.d.ts +42 -25
- package/types/Utils.d.ts +2 -0
- package/types/http.d.ts +100 -0
- package/types/index.d.ts +1 -0
package/ast.json
CHANGED
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
"operations": [
|
|
3
3
|
{
|
|
4
4
|
"name": "getForms",
|
|
5
|
-
"params": [
|
|
6
|
-
"params",
|
|
7
|
-
"callback"
|
|
8
|
-
],
|
|
5
|
+
"params": [],
|
|
9
6
|
"docs": {
|
|
10
|
-
"description": "Make a request to
|
|
7
|
+
"description": "Make a request to fetch all survey forms accessible to the authorized user. Calls `/api/v2/assets/?asset_type=survey`.",
|
|
11
8
|
"tags": [
|
|
12
9
|
{
|
|
13
10
|
"title": "public",
|
|
@@ -16,7 +13,7 @@
|
|
|
16
13
|
},
|
|
17
14
|
{
|
|
18
15
|
"title": "example",
|
|
19
|
-
"description": "getForms(
|
|
16
|
+
"description": "getForms();"
|
|
20
17
|
},
|
|
21
18
|
{
|
|
22
19
|
"title": "function",
|
|
@@ -24,22 +21,8 @@
|
|
|
24
21
|
"name": null
|
|
25
22
|
},
|
|
26
23
|
{
|
|
27
|
-
"title": "
|
|
28
|
-
"description": "
|
|
29
|
-
"type": {
|
|
30
|
-
"type": "NameExpression",
|
|
31
|
-
"name": "object"
|
|
32
|
-
},
|
|
33
|
-
"name": "params"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"title": "param",
|
|
37
|
-
"description": "(Optional) Callback function to execute after fetching form list",
|
|
38
|
-
"type": {
|
|
39
|
-
"type": "NameExpression",
|
|
40
|
-
"name": "function"
|
|
41
|
-
},
|
|
42
|
-
"name": "callback"
|
|
24
|
+
"title": "state",
|
|
25
|
+
"description": "data - an array of form objects"
|
|
43
26
|
},
|
|
44
27
|
{
|
|
45
28
|
"title": "returns",
|
|
@@ -56,15 +39,21 @@
|
|
|
56
39
|
{
|
|
57
40
|
"name": "getSubmissions",
|
|
58
41
|
"params": [
|
|
59
|
-
"
|
|
60
|
-
"
|
|
42
|
+
"formId",
|
|
43
|
+
"options"
|
|
61
44
|
],
|
|
62
45
|
"docs": {
|
|
63
|
-
"description": "Get submissions for a specific form",
|
|
46
|
+
"description": "Get submissions for a specific form. Calls `/api/v2/assets/<formId>/data/`.",
|
|
64
47
|
"tags": [
|
|
65
48
|
{
|
|
66
49
|
"title": "example",
|
|
67
|
-
"description": "getSubmissions(
|
|
50
|
+
"description": "getSubmissions('aXecHjmbATuF6iGFmvBLBX');",
|
|
51
|
+
"caption": "Get all submissions for a specific form"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"title": "example",
|
|
55
|
+
"description": "getSubmissions('aXecHjmbATuF6iGFmvBLBX', { query: { _submission_time:{ $gte: \"2022-06-12T21:54:20\" } } });",
|
|
56
|
+
"caption": "Get form submissions with a query"
|
|
68
57
|
},
|
|
69
58
|
{
|
|
70
59
|
"title": "function",
|
|
@@ -78,21 +67,29 @@
|
|
|
78
67
|
},
|
|
79
68
|
{
|
|
80
69
|
"title": "param",
|
|
81
|
-
"description": "Form Id
|
|
70
|
+
"description": "Form Id to get the specific submissions",
|
|
82
71
|
"type": {
|
|
83
72
|
"type": "NameExpression",
|
|
84
|
-
"name": "
|
|
73
|
+
"name": "string"
|
|
85
74
|
},
|
|
86
|
-
"name": "
|
|
75
|
+
"name": "formId"
|
|
87
76
|
},
|
|
88
77
|
{
|
|
89
78
|
"title": "param",
|
|
90
|
-
"description": "
|
|
79
|
+
"description": "Optional query params for the request",
|
|
91
80
|
"type": {
|
|
92
|
-
"type": "
|
|
93
|
-
"
|
|
81
|
+
"type": "OptionalType",
|
|
82
|
+
"expression": {
|
|
83
|
+
"type": "NameExpression",
|
|
84
|
+
"name": "object"
|
|
85
|
+
}
|
|
94
86
|
},
|
|
95
|
-
"name": "
|
|
87
|
+
"name": "options",
|
|
88
|
+
"default": "{}"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"title": "state",
|
|
92
|
+
"description": "data - an array of submission objects"
|
|
96
93
|
},
|
|
97
94
|
{
|
|
98
95
|
"title": "returns",
|
|
@@ -109,15 +106,14 @@
|
|
|
109
106
|
{
|
|
110
107
|
"name": "getDeploymentInfo",
|
|
111
108
|
"params": [
|
|
112
|
-
"
|
|
113
|
-
"callback"
|
|
109
|
+
"formId"
|
|
114
110
|
],
|
|
115
111
|
"docs": {
|
|
116
|
-
"description": "Get deployment information for a specific form",
|
|
112
|
+
"description": "Get deployment information for a specific form. Calls `/api/v2/assets/<id>/deployment/`.",
|
|
117
113
|
"tags": [
|
|
118
114
|
{
|
|
119
115
|
"title": "example",
|
|
120
|
-
"description": "getDeploymentInfo(
|
|
116
|
+
"description": "getDeploymentInfo('aXecHjmbATuF6iGFmvBLBX');"
|
|
121
117
|
},
|
|
122
118
|
{
|
|
123
119
|
"title": "function",
|
|
@@ -131,21 +127,16 @@
|
|
|
131
127
|
},
|
|
132
128
|
{
|
|
133
129
|
"title": "param",
|
|
134
|
-
"description": "Form Id
|
|
130
|
+
"description": "Form Id to get the deployment information",
|
|
135
131
|
"type": {
|
|
136
132
|
"type": "NameExpression",
|
|
137
|
-
"name": "
|
|
133
|
+
"name": "string"
|
|
138
134
|
},
|
|
139
|
-
"name": "
|
|
135
|
+
"name": "formId"
|
|
140
136
|
},
|
|
141
137
|
{
|
|
142
|
-
"title": "
|
|
143
|
-
"description": "
|
|
144
|
-
"type": {
|
|
145
|
-
"type": "NameExpression",
|
|
146
|
-
"name": "function"
|
|
147
|
-
},
|
|
148
|
-
"name": "callback"
|
|
138
|
+
"title": "state",
|
|
139
|
+
"description": "data - an object containing deployment information"
|
|
149
140
|
},
|
|
150
141
|
{
|
|
151
142
|
"title": "returns",
|
|
@@ -437,7 +428,7 @@
|
|
|
437
428
|
"operation"
|
|
438
429
|
],
|
|
439
430
|
"docs": {
|
|
440
|
-
"description": "
|
|
431
|
+
"description": "Iterates over an array of items and invokes an operation upon each one, where the state\nobject is _scoped_ so that state.data is the item under iteration.\nThe rest of the state object is untouched and can be referenced as usual.\nYou can pass an array directly, or use lazy state or a JSONPath string to\nreference a slice of state.",
|
|
441
432
|
"tags": [
|
|
442
433
|
{
|
|
443
434
|
"title": "public",
|
|
@@ -451,7 +442,18 @@
|
|
|
451
442
|
},
|
|
452
443
|
{
|
|
453
444
|
"title": "example",
|
|
454
|
-
"description": "each(\
|
|
445
|
+
"description": "each(\n $.data,\n // Inside the callback operation, `$.data` is scoped to the item under iteration\n insert(\"patient\", {\n patient_name: $.data.properties.case_name,\n patient_id: $.data.case_id,\n })\n);",
|
|
446
|
+
"caption": "Using lazy state ($) to iterate over items in state.data and pass each into an \"insert\" operation"
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
"title": "example",
|
|
450
|
+
"description": "each(\n $.data,\n insert(\"patient\", (state) => ({\n patient_id: state.data.case_id,\n ...state.data\n }))\n);",
|
|
451
|
+
"caption": "Iterate over items in state.data and pass each one into an \"insert\" operation"
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"title": "example",
|
|
455
|
+
"description": "each(\n \"$.data[*]\",\n insert(\"patient\", (state) => ({\n patient_name: state.data.properties.case_name,\n patient_id: state.data.case_id,\n }))\n);",
|
|
456
|
+
"caption": "Using JSON path to iterate over items in state.data and pass each one into an \"insert\" operation"
|
|
455
457
|
},
|
|
456
458
|
{
|
|
457
459
|
"title": "param",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"properties": {
|
|
4
|
-
"
|
|
5
|
-
"title": "Base
|
|
4
|
+
"baseUrl": {
|
|
5
|
+
"title": "Base Url",
|
|
6
6
|
"type": "string",
|
|
7
7
|
"default": "https://kf.kobotoolbox.org",
|
|
8
8
|
"description": "Kobotoolbox URL",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"additionalProperties": true,
|
|
47
47
|
"required": [
|
|
48
48
|
"username",
|
|
49
|
-
"
|
|
49
|
+
"baseUrl",
|
|
50
50
|
"password",
|
|
51
51
|
"apiVersion"
|
|
52
52
|
]
|
package/dist/index.cjs
CHANGED
|
@@ -19,124 +19,244 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
// src/index.js
|
|
20
20
|
var src_exports = {};
|
|
21
21
|
__export(src_exports, {
|
|
22
|
-
alterState: () =>
|
|
23
|
-
cursor: () =>
|
|
24
|
-
dataPath: () =>
|
|
25
|
-
dataValue: () =>
|
|
22
|
+
alterState: () => import_language_common3.alterState,
|
|
23
|
+
cursor: () => import_language_common3.cursor,
|
|
24
|
+
dataPath: () => import_language_common3.dataPath,
|
|
25
|
+
dataValue: () => import_language_common3.dataValue,
|
|
26
26
|
default: () => src_default,
|
|
27
|
-
each: () =>
|
|
27
|
+
each: () => import_language_common3.each,
|
|
28
28
|
execute: () => execute,
|
|
29
|
-
field: () =>
|
|
30
|
-
fields: () =>
|
|
31
|
-
fn: () =>
|
|
32
|
-
fnIf: () =>
|
|
29
|
+
field: () => import_language_common3.field,
|
|
30
|
+
fields: () => import_language_common3.fields,
|
|
31
|
+
fn: () => import_language_common3.fn,
|
|
32
|
+
fnIf: () => import_language_common3.fnIf,
|
|
33
33
|
getDeploymentInfo: () => getDeploymentInfo,
|
|
34
34
|
getForms: () => getForms,
|
|
35
35
|
getSubmissions: () => getSubmissions,
|
|
36
|
-
group: () =>
|
|
37
|
-
http: () =>
|
|
38
|
-
lastReferenceValue: () =>
|
|
39
|
-
merge: () =>
|
|
40
|
-
sourceValue: () =>
|
|
36
|
+
group: () => import_language_common3.group,
|
|
37
|
+
http: () => http_exports,
|
|
38
|
+
lastReferenceValue: () => import_language_common3.lastReferenceValue,
|
|
39
|
+
merge: () => import_language_common3.merge,
|
|
40
|
+
sourceValue: () => import_language_common3.sourceValue
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(src_exports);
|
|
43
43
|
|
|
44
44
|
// src/Adaptor.js
|
|
45
45
|
var Adaptor_exports = {};
|
|
46
46
|
__export(Adaptor_exports, {
|
|
47
|
-
alterState: () =>
|
|
48
|
-
cursor: () =>
|
|
49
|
-
dataPath: () =>
|
|
50
|
-
dataValue: () =>
|
|
51
|
-
each: () =>
|
|
47
|
+
alterState: () => import_language_common3.alterState,
|
|
48
|
+
cursor: () => import_language_common3.cursor,
|
|
49
|
+
dataPath: () => import_language_common3.dataPath,
|
|
50
|
+
dataValue: () => import_language_common3.dataValue,
|
|
51
|
+
each: () => import_language_common3.each,
|
|
52
52
|
execute: () => execute,
|
|
53
|
-
field: () =>
|
|
54
|
-
fields: () =>
|
|
55
|
-
fn: () =>
|
|
56
|
-
fnIf: () =>
|
|
53
|
+
field: () => import_language_common3.field,
|
|
54
|
+
fields: () => import_language_common3.fields,
|
|
55
|
+
fn: () => import_language_common3.fn,
|
|
56
|
+
fnIf: () => import_language_common3.fnIf,
|
|
57
57
|
getDeploymentInfo: () => getDeploymentInfo,
|
|
58
58
|
getForms: () => getForms,
|
|
59
59
|
getSubmissions: () => getSubmissions,
|
|
60
|
-
group: () =>
|
|
61
|
-
http: () =>
|
|
62
|
-
lastReferenceValue: () =>
|
|
63
|
-
merge: () =>
|
|
64
|
-
sourceValue: () =>
|
|
60
|
+
group: () => import_language_common3.group,
|
|
61
|
+
http: () => import_language_common3.http,
|
|
62
|
+
lastReferenceValue: () => import_language_common3.lastReferenceValue,
|
|
63
|
+
merge: () => import_language_common3.merge,
|
|
64
|
+
sourceValue: () => import_language_common3.sourceValue
|
|
65
65
|
});
|
|
66
|
-
var import_language_common = require("@openfn/language-common");
|
|
67
66
|
var import_language_common2 = require("@openfn/language-common");
|
|
67
|
+
var import_util2 = require("@openfn/language-common/util");
|
|
68
|
+
|
|
69
|
+
// src/Utils.js
|
|
70
|
+
var import_language_common = require("@openfn/language-common");
|
|
71
|
+
var import_util = require("@openfn/language-common/util");
|
|
72
|
+
var prepareNextState = (state, response) => {
|
|
73
|
+
const { body, ...responseWithoutBody } = response;
|
|
74
|
+
return {
|
|
75
|
+
...(0, import_language_common.composeNextState)(state, response.body),
|
|
76
|
+
response: responseWithoutBody
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
async function request(state, method, path, opts) {
|
|
80
|
+
const { baseURL, apiVersion, username, password } = state.configuration;
|
|
81
|
+
let baseUrl;
|
|
82
|
+
if (!state.configuration.baseUrl && baseURL) {
|
|
83
|
+
baseUrl = baseURL;
|
|
84
|
+
console.warn(
|
|
85
|
+
"No baseUrl found in state.configuration. baseURL will be used instead, but this will be deprecated in the future."
|
|
86
|
+
);
|
|
87
|
+
} else {
|
|
88
|
+
baseUrl = state.configuration.baseUrl;
|
|
89
|
+
}
|
|
90
|
+
const {
|
|
91
|
+
data = {},
|
|
92
|
+
query = {},
|
|
93
|
+
headers = {},
|
|
94
|
+
parseAs = "json",
|
|
95
|
+
paginate = false
|
|
96
|
+
} = opts;
|
|
97
|
+
const authHeaders = (0, import_util.makeBasicAuthHeader)(username, password);
|
|
98
|
+
let start, limit;
|
|
99
|
+
const options = {
|
|
100
|
+
body: data,
|
|
101
|
+
headers: {
|
|
102
|
+
"Content-Type": "application/json",
|
|
103
|
+
...authHeaders,
|
|
104
|
+
...headers
|
|
105
|
+
},
|
|
106
|
+
query: {
|
|
107
|
+
format: "json",
|
|
108
|
+
...query
|
|
109
|
+
},
|
|
110
|
+
parseAs,
|
|
111
|
+
baseUrl: `${baseUrl}/api/${apiVersion}`
|
|
112
|
+
};
|
|
113
|
+
if (paginate) {
|
|
114
|
+
const results = [];
|
|
115
|
+
do {
|
|
116
|
+
const response = await (0, import_util.request)(method, path, options).then(
|
|
117
|
+
import_util.logResponse
|
|
118
|
+
);
|
|
119
|
+
results.push(...response.body.results);
|
|
120
|
+
if (response.body.next) {
|
|
121
|
+
const nextUrl = new URL(response.body.next);
|
|
122
|
+
const startDigit = nextUrl.searchParams.get("start") !== null ? nextUrl.searchParams.get("start") : 0;
|
|
123
|
+
start = Number(startDigit);
|
|
124
|
+
limit = nextUrl.searchParams.get("limit");
|
|
125
|
+
options.query = {
|
|
126
|
+
...options.query,
|
|
127
|
+
start,
|
|
128
|
+
limit
|
|
129
|
+
};
|
|
130
|
+
} else {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
} while (true);
|
|
134
|
+
return { results };
|
|
135
|
+
} else {
|
|
136
|
+
return (0, import_util.request)(method, path, options).then(import_util.logResponse);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/Adaptor.js
|
|
141
|
+
var import_language_common3 = require("@openfn/language-common");
|
|
68
142
|
function execute(...operations) {
|
|
69
143
|
const initialState = {
|
|
70
144
|
references: [],
|
|
71
145
|
data: null
|
|
72
146
|
};
|
|
73
147
|
return (state) => {
|
|
74
|
-
return (0,
|
|
148
|
+
return (0, import_language_common2.execute)(...operations)({
|
|
75
149
|
...initialState,
|
|
76
150
|
...state
|
|
77
151
|
});
|
|
78
152
|
};
|
|
79
153
|
}
|
|
80
|
-
function getForms(
|
|
81
|
-
return (state) => {
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
154
|
+
function getForms() {
|
|
155
|
+
return async (state) => {
|
|
156
|
+
const url = `/assets/?asset_type=survey`;
|
|
157
|
+
const response = await request(state, "GET", url, {});
|
|
158
|
+
console.log("\u2713", response.body.results.length, "forms fetched.");
|
|
159
|
+
return prepareNextState(state, response);
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function getSubmissions(formId, options = {}) {
|
|
163
|
+
return async (state) => {
|
|
164
|
+
const [resolvedFormId, resolvedOptions] = (0, import_util2.expandReferences)(
|
|
165
|
+
state,
|
|
166
|
+
formId,
|
|
167
|
+
options
|
|
168
|
+
);
|
|
169
|
+
const url = `/assets/${resolvedFormId}/data/`;
|
|
170
|
+
const query = {};
|
|
171
|
+
if (resolvedOptions.query) {
|
|
172
|
+
if (typeof resolvedOptions.query == "string") {
|
|
173
|
+
query.query = resolvedOptions.query;
|
|
174
|
+
} else {
|
|
175
|
+
query.query = JSON.stringify(resolvedOptions.query);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const { results } = await request(state, "GET", url, {
|
|
179
|
+
paginate: true,
|
|
180
|
+
query
|
|
97
181
|
});
|
|
182
|
+
console.log("\u2713", results.length, "submissions fetched.");
|
|
183
|
+
return (0, import_language_common2.composeNextState)(state, results);
|
|
98
184
|
};
|
|
99
185
|
}
|
|
100
|
-
function
|
|
101
|
-
return (state) => {
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
186
|
+
function getDeploymentInfo(formId) {
|
|
187
|
+
return async (state) => {
|
|
188
|
+
const [resolvedFormId] = (0, import_util2.expandReferences)(state, formId);
|
|
189
|
+
const url = `/assets/${resolvedFormId}/deployment/`;
|
|
190
|
+
const response = await request(state, "GET", url, {});
|
|
191
|
+
console.log("\u2713", "deployment information fetched.");
|
|
192
|
+
return prepareNextState(state, response);
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/http.js
|
|
197
|
+
var http_exports = {};
|
|
198
|
+
__export(http_exports, {
|
|
199
|
+
get: () => get,
|
|
200
|
+
post: () => post,
|
|
201
|
+
put: () => put
|
|
202
|
+
});
|
|
203
|
+
var import_util3 = require("@openfn/language-common/util");
|
|
204
|
+
function get(path, options = {}) {
|
|
205
|
+
return async (state) => {
|
|
206
|
+
const [resolvedPath, resolvedOptions] = (0, import_util3.expandReferences)(
|
|
207
|
+
state,
|
|
208
|
+
path,
|
|
209
|
+
options
|
|
210
|
+
);
|
|
211
|
+
const response = await request(
|
|
212
|
+
state,
|
|
213
|
+
"GET",
|
|
214
|
+
resolvedPath,
|
|
215
|
+
resolvedOptions
|
|
216
|
+
);
|
|
217
|
+
return prepareNextState(state, response);
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function post(path, data, options = {}) {
|
|
221
|
+
return async (state) => {
|
|
222
|
+
const [resolvedPath, resolvedData, resolvedOptions] = (0, import_util3.expandReferences)(
|
|
223
|
+
state,
|
|
224
|
+
path,
|
|
225
|
+
data,
|
|
226
|
+
options
|
|
227
|
+
);
|
|
228
|
+
const optionsObject = {
|
|
229
|
+
data: resolvedData,
|
|
230
|
+
...resolvedOptions
|
|
111
231
|
};
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
232
|
+
const response = await request(
|
|
233
|
+
state,
|
|
234
|
+
"POST",
|
|
235
|
+
resolvedPath,
|
|
236
|
+
optionsObject
|
|
237
|
+
);
|
|
238
|
+
return prepareNextState(state, response);
|
|
119
239
|
};
|
|
120
240
|
}
|
|
121
|
-
function
|
|
122
|
-
return (state) => {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
241
|
+
function put(path, data, options = {}) {
|
|
242
|
+
return async (state) => {
|
|
243
|
+
const [resolvedPath, resolvedData, resolvedOptions] = (0, import_util3.expandReferences)(
|
|
244
|
+
state,
|
|
245
|
+
path,
|
|
246
|
+
data,
|
|
247
|
+
options
|
|
248
|
+
);
|
|
249
|
+
const optionsObject = {
|
|
250
|
+
data: resolvedData,
|
|
251
|
+
...resolvedOptions
|
|
132
252
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
253
|
+
const response = await request(
|
|
254
|
+
state,
|
|
255
|
+
"PUT",
|
|
256
|
+
resolvedPath,
|
|
257
|
+
optionsObject
|
|
258
|
+
);
|
|
259
|
+
return prepareNextState(state, response);
|
|
140
260
|
};
|
|
141
261
|
}
|
|
142
262
|
|
package/dist/index.js
CHANGED
|
@@ -21,17 +21,93 @@ __export(Adaptor_exports, {
|
|
|
21
21
|
getForms: () => getForms,
|
|
22
22
|
getSubmissions: () => getSubmissions,
|
|
23
23
|
group: () => group,
|
|
24
|
-
http: () =>
|
|
24
|
+
http: () => http,
|
|
25
25
|
lastReferenceValue: () => lastReferenceValue,
|
|
26
26
|
merge: () => merge,
|
|
27
27
|
sourceValue: () => sourceValue
|
|
28
28
|
});
|
|
29
29
|
import {
|
|
30
30
|
execute as commonExecute,
|
|
31
|
-
composeNextState
|
|
32
|
-
expandReferences,
|
|
33
|
-
http
|
|
31
|
+
composeNextState as composeNextState2
|
|
34
32
|
} from "@openfn/language-common";
|
|
33
|
+
import { expandReferences } from "@openfn/language-common/util";
|
|
34
|
+
|
|
35
|
+
// src/Utils.js
|
|
36
|
+
import { composeNextState } from "@openfn/language-common";
|
|
37
|
+
import {
|
|
38
|
+
request as commonRequest,
|
|
39
|
+
makeBasicAuthHeader,
|
|
40
|
+
logResponse
|
|
41
|
+
} from "@openfn/language-common/util";
|
|
42
|
+
var prepareNextState = (state, response) => {
|
|
43
|
+
const { body, ...responseWithoutBody } = response;
|
|
44
|
+
return {
|
|
45
|
+
...composeNextState(state, response.body),
|
|
46
|
+
response: responseWithoutBody
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
async function request(state, method, path, opts) {
|
|
50
|
+
const { baseURL, apiVersion, username, password } = state.configuration;
|
|
51
|
+
let baseUrl;
|
|
52
|
+
if (!state.configuration.baseUrl && baseURL) {
|
|
53
|
+
baseUrl = baseURL;
|
|
54
|
+
console.warn(
|
|
55
|
+
"No baseUrl found in state.configuration. baseURL will be used instead, but this will be deprecated in the future."
|
|
56
|
+
);
|
|
57
|
+
} else {
|
|
58
|
+
baseUrl = state.configuration.baseUrl;
|
|
59
|
+
}
|
|
60
|
+
const {
|
|
61
|
+
data = {},
|
|
62
|
+
query = {},
|
|
63
|
+
headers = {},
|
|
64
|
+
parseAs = "json",
|
|
65
|
+
paginate = false
|
|
66
|
+
} = opts;
|
|
67
|
+
const authHeaders = makeBasicAuthHeader(username, password);
|
|
68
|
+
let start, limit;
|
|
69
|
+
const options = {
|
|
70
|
+
body: data,
|
|
71
|
+
headers: {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
...authHeaders,
|
|
74
|
+
...headers
|
|
75
|
+
},
|
|
76
|
+
query: {
|
|
77
|
+
format: "json",
|
|
78
|
+
...query
|
|
79
|
+
},
|
|
80
|
+
parseAs,
|
|
81
|
+
baseUrl: `${baseUrl}/api/${apiVersion}`
|
|
82
|
+
};
|
|
83
|
+
if (paginate) {
|
|
84
|
+
const results = [];
|
|
85
|
+
do {
|
|
86
|
+
const response = await commonRequest(method, path, options).then(
|
|
87
|
+
logResponse
|
|
88
|
+
);
|
|
89
|
+
results.push(...response.body.results);
|
|
90
|
+
if (response.body.next) {
|
|
91
|
+
const nextUrl = new URL(response.body.next);
|
|
92
|
+
const startDigit = nextUrl.searchParams.get("start") !== null ? nextUrl.searchParams.get("start") : 0;
|
|
93
|
+
start = Number(startDigit);
|
|
94
|
+
limit = nextUrl.searchParams.get("limit");
|
|
95
|
+
options.query = {
|
|
96
|
+
...options.query,
|
|
97
|
+
start,
|
|
98
|
+
limit
|
|
99
|
+
};
|
|
100
|
+
} else {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
} while (true);
|
|
104
|
+
return { results };
|
|
105
|
+
} else {
|
|
106
|
+
return commonRequest(method, path, options).then(logResponse);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/Adaptor.js
|
|
35
111
|
import {
|
|
36
112
|
alterState,
|
|
37
113
|
cursor,
|
|
@@ -42,7 +118,7 @@ import {
|
|
|
42
118
|
fields,
|
|
43
119
|
fn,
|
|
44
120
|
fnIf,
|
|
45
|
-
http
|
|
121
|
+
http,
|
|
46
122
|
group,
|
|
47
123
|
lastReferenceValue,
|
|
48
124
|
merge,
|
|
@@ -60,66 +136,112 @@ function execute(...operations) {
|
|
|
60
136
|
});
|
|
61
137
|
};
|
|
62
138
|
}
|
|
63
|
-
function getForms(
|
|
64
|
-
return (state) => {
|
|
65
|
-
const
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
139
|
+
function getForms() {
|
|
140
|
+
return async (state) => {
|
|
141
|
+
const url = `/assets/?asset_type=survey`;
|
|
142
|
+
const response = await request(state, "GET", url, {});
|
|
143
|
+
console.log("\u2713", response.body.results.length, "forms fetched.");
|
|
144
|
+
return prepareNextState(state, response);
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function getSubmissions(formId, options = {}) {
|
|
148
|
+
return async (state) => {
|
|
149
|
+
const [resolvedFormId, resolvedOptions] = expandReferences(
|
|
150
|
+
state,
|
|
151
|
+
formId,
|
|
152
|
+
options
|
|
153
|
+
);
|
|
154
|
+
const url = `/assets/${resolvedFormId}/data/`;
|
|
155
|
+
const query = {};
|
|
156
|
+
if (resolvedOptions.query) {
|
|
157
|
+
if (typeof resolvedOptions.query == "string") {
|
|
158
|
+
query.query = resolvedOptions.query;
|
|
159
|
+
} else {
|
|
160
|
+
query.query = JSON.stringify(resolvedOptions.query);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const { results } = await request(state, "GET", url, {
|
|
164
|
+
paginate: true,
|
|
165
|
+
query
|
|
80
166
|
});
|
|
167
|
+
console.log("\u2713", results.length, "submissions fetched.");
|
|
168
|
+
return composeNextState2(state, results);
|
|
81
169
|
};
|
|
82
170
|
}
|
|
83
|
-
function
|
|
84
|
-
return (state) => {
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
171
|
+
function getDeploymentInfo(formId) {
|
|
172
|
+
return async (state) => {
|
|
173
|
+
const [resolvedFormId] = expandReferences(state, formId);
|
|
174
|
+
const url = `/assets/${resolvedFormId}/deployment/`;
|
|
175
|
+
const response = await request(state, "GET", url, {});
|
|
176
|
+
console.log("\u2713", "deployment information fetched.");
|
|
177
|
+
return prepareNextState(state, response);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/http.js
|
|
182
|
+
var http_exports = {};
|
|
183
|
+
__export(http_exports, {
|
|
184
|
+
get: () => get,
|
|
185
|
+
post: () => post,
|
|
186
|
+
put: () => put
|
|
187
|
+
});
|
|
188
|
+
import { expandReferences as expandReferences2 } from "@openfn/language-common/util";
|
|
189
|
+
function get(path, options = {}) {
|
|
190
|
+
return async (state) => {
|
|
191
|
+
const [resolvedPath, resolvedOptions] = expandReferences2(
|
|
192
|
+
state,
|
|
193
|
+
path,
|
|
194
|
+
options
|
|
195
|
+
);
|
|
196
|
+
const response = await request(
|
|
197
|
+
state,
|
|
198
|
+
"GET",
|
|
199
|
+
resolvedPath,
|
|
200
|
+
resolvedOptions
|
|
201
|
+
);
|
|
202
|
+
return prepareNextState(state, response);
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function post(path, data, options = {}) {
|
|
206
|
+
return async (state) => {
|
|
207
|
+
const [resolvedPath, resolvedData, resolvedOptions] = expandReferences2(
|
|
208
|
+
state,
|
|
209
|
+
path,
|
|
210
|
+
data,
|
|
211
|
+
options
|
|
212
|
+
);
|
|
213
|
+
const optionsObject = {
|
|
214
|
+
data: resolvedData,
|
|
215
|
+
...resolvedOptions
|
|
94
216
|
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
217
|
+
const response = await request(
|
|
218
|
+
state,
|
|
219
|
+
"POST",
|
|
220
|
+
resolvedPath,
|
|
221
|
+
optionsObject
|
|
222
|
+
);
|
|
223
|
+
return prepareNextState(state, response);
|
|
102
224
|
};
|
|
103
225
|
}
|
|
104
|
-
function
|
|
105
|
-
return (state) => {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
226
|
+
function put(path, data, options = {}) {
|
|
227
|
+
return async (state) => {
|
|
228
|
+
const [resolvedPath, resolvedData, resolvedOptions] = expandReferences2(
|
|
229
|
+
state,
|
|
230
|
+
path,
|
|
231
|
+
data,
|
|
232
|
+
options
|
|
233
|
+
);
|
|
234
|
+
const optionsObject = {
|
|
235
|
+
data: resolvedData,
|
|
236
|
+
...resolvedOptions
|
|
115
237
|
};
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
238
|
+
const response = await request(
|
|
239
|
+
state,
|
|
240
|
+
"PUT",
|
|
241
|
+
resolvedPath,
|
|
242
|
+
optionsObject
|
|
243
|
+
);
|
|
244
|
+
return prepareNextState(state, response);
|
|
123
245
|
};
|
|
124
246
|
}
|
|
125
247
|
|
|
@@ -141,7 +263,7 @@ export {
|
|
|
141
263
|
getForms,
|
|
142
264
|
getSubmissions,
|
|
143
265
|
group,
|
|
144
|
-
|
|
266
|
+
http_exports as http,
|
|
145
267
|
lastReferenceValue,
|
|
146
268
|
merge,
|
|
147
269
|
sourceValue
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/language-kobotoolbox",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "A Kobo Toolbox Language Pack for OpenFn",
|
|
5
5
|
"homepage": "https://docs.openfn.org",
|
|
6
6
|
"repository": {
|
|
@@ -17,15 +17,13 @@
|
|
|
17
17
|
"configuration-schema.json"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@openfn/language-common": "
|
|
20
|
+
"@openfn/language-common": "2.3.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@openfn/simple-ast": "0.4.1",
|
|
24
23
|
"assertion-error": "^1.0.1",
|
|
25
24
|
"chai": "^3.4.0",
|
|
26
25
|
"deep-eql": "^0.1.3",
|
|
27
26
|
"esno": "^0.16.3",
|
|
28
|
-
"nock": "^12.0.3",
|
|
29
27
|
"rimraf": "^3.0.2"
|
|
30
28
|
},
|
|
31
29
|
"type": "module",
|
package/types/Adaptor.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options object
|
|
3
|
+
* @typedef {Object} RequestOptions
|
|
4
|
+
* @property {object} query - An object of query parameters to be encoded into the URL
|
|
5
|
+
* @property {object} headers - An object of all request headers
|
|
6
|
+
* @property {string} [parseAs='json'] - The response format to parse (e.g., 'json', 'text', or 'stream')
|
|
7
|
+
*/
|
|
1
8
|
/**
|
|
2
9
|
* Execute a sequence of operations.
|
|
3
10
|
* Wraps `language-common/execute`, and prepends initial state for http.
|
|
@@ -12,45 +19,55 @@
|
|
|
12
19
|
*/
|
|
13
20
|
export function execute(...operations: Operations): Operation;
|
|
14
21
|
/**
|
|
15
|
-
* Make a request to
|
|
22
|
+
* Make a request to fetch all survey forms accessible to the authorized user. Calls `/api/v2/assets/?asset_type=survey`.
|
|
16
23
|
* @public
|
|
17
24
|
* @example
|
|
18
|
-
* getForms(
|
|
19
|
-
* console.log(state.data);
|
|
20
|
-
* return state;
|
|
21
|
-
* });
|
|
25
|
+
* getForms();
|
|
22
26
|
* @function
|
|
23
|
-
* @
|
|
24
|
-
* @param {function} callback - (Optional) Callback function to execute after fetching form list
|
|
27
|
+
* @state data - an array of form objects
|
|
25
28
|
* @returns {Operation}
|
|
26
29
|
*/
|
|
27
|
-
export function getForms(
|
|
30
|
+
export function getForms(): Operation;
|
|
28
31
|
/**
|
|
29
|
-
* Get submissions for a specific form
|
|
30
|
-
* @example
|
|
31
|
-
* getSubmissions(
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* });
|
|
32
|
+
* Get submissions for a specific form. Calls `/api/v2/assets/<formId>/data/`.
|
|
33
|
+
* @example <caption>Get all submissions for a specific form</caption>
|
|
34
|
+
* getSubmissions('aXecHjmbATuF6iGFmvBLBX');
|
|
35
|
+
* @example <caption>Get form submissions with a query</caption>
|
|
36
|
+
* getSubmissions('aXecHjmbATuF6iGFmvBLBX', { query: { _submission_time:{ $gte: "2022-06-12T21:54:20" } } });
|
|
35
37
|
* @function
|
|
36
38
|
* @public
|
|
37
|
-
* @param {
|
|
38
|
-
* @param {
|
|
39
|
+
* @param {string} formId - Form Id to get the specific submissions
|
|
40
|
+
* @param {object} [options={}] - Optional query params for the request
|
|
41
|
+
* @state data - an array of submission objects
|
|
39
42
|
* @returns {Operation}
|
|
40
43
|
*/
|
|
41
|
-
export function getSubmissions(
|
|
44
|
+
export function getSubmissions(formId: string, options?: object): Operation;
|
|
42
45
|
/**
|
|
43
|
-
* Get deployment information for a specific form
|
|
46
|
+
* Get deployment information for a specific form. Calls `/api/v2/assets/<id>/deployment/`.
|
|
44
47
|
* @example
|
|
45
|
-
* getDeploymentInfo(
|
|
46
|
-
* console.log(state.data);
|
|
47
|
-
* return state;
|
|
48
|
-
* });
|
|
48
|
+
* getDeploymentInfo('aXecHjmbATuF6iGFmvBLBX');
|
|
49
49
|
* @function
|
|
50
50
|
* @public
|
|
51
|
-
* @param {
|
|
52
|
-
* @
|
|
51
|
+
* @param {string} formId - Form Id to get the deployment information
|
|
52
|
+
* @state data - an object containing deployment information
|
|
53
53
|
* @returns {Operation}
|
|
54
54
|
*/
|
|
55
|
-
export function getDeploymentInfo(
|
|
55
|
+
export function getDeploymentInfo(formId: string): Operation;
|
|
56
|
+
/**
|
|
57
|
+
* Options object
|
|
58
|
+
*/
|
|
59
|
+
export type RequestOptions = {
|
|
60
|
+
/**
|
|
61
|
+
* - An object of query parameters to be encoded into the URL
|
|
62
|
+
*/
|
|
63
|
+
query: object;
|
|
64
|
+
/**
|
|
65
|
+
* - An object of all request headers
|
|
66
|
+
*/
|
|
67
|
+
headers: object;
|
|
68
|
+
/**
|
|
69
|
+
* - The response format to parse (e.g., 'json', 'text', or 'stream')
|
|
70
|
+
*/
|
|
71
|
+
parseAs?: string;
|
|
72
|
+
};
|
|
56
73
|
export { alterState, cursor, dataPath, dataValue, each, field, fields, fn, fnIf, http, group, lastReferenceValue, merge, sourceValue } from "@openfn/language-common";
|
package/types/Utils.d.ts
ADDED
package/types/http.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State object
|
|
3
|
+
* @typedef {Object} KoboToolboxHttpState
|
|
4
|
+
* @property data - The response body (as JSON)
|
|
5
|
+
* @property response - The HTTP response from the KoboToolbox server (excluding the body). Responses will be returned in JSON format
|
|
6
|
+
* @property references - An array of all previous data objects used in the Job
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Options object
|
|
10
|
+
* @typedef {Object} RequestOptions
|
|
11
|
+
* @property {object} query - An object of query parameters to be encoded into the URL
|
|
12
|
+
* @property {object} headers - An object of all request headers
|
|
13
|
+
* @property {string} [parseAs='json'] - The response format to parse (e.g., 'json', 'text', or 'stream')
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Make a GET request to any KoboToolbox endpoint.
|
|
17
|
+
* @public
|
|
18
|
+
* @function
|
|
19
|
+
* @example <caption>GET assets resource</caption>
|
|
20
|
+
* http.get(
|
|
21
|
+
* "/assets/",
|
|
22
|
+
* )
|
|
23
|
+
* @param {string} path - path to resource
|
|
24
|
+
* @param {RequestOptions} [options={}] - An object containing query params and headers for the request
|
|
25
|
+
* @state {KoboToolboxHttpState}
|
|
26
|
+
* @returns {operation}
|
|
27
|
+
*/
|
|
28
|
+
export function get(path: string, options?: RequestOptions): operation;
|
|
29
|
+
/**
|
|
30
|
+
* Make a POST request to a KoboToolbox endpoint
|
|
31
|
+
* @public
|
|
32
|
+
* @function
|
|
33
|
+
* @example <caption>Create an asset resource</caption>
|
|
34
|
+
* http.post(
|
|
35
|
+
* '/assets/',
|
|
36
|
+
* {
|
|
37
|
+
* name: 'Feedback Survey Test',
|
|
38
|
+
* asset_type: 'survey',
|
|
39
|
+
* },
|
|
40
|
+
* );
|
|
41
|
+
* @param {string} path - path to resource
|
|
42
|
+
* @param {any} data - the body data in JSON format
|
|
43
|
+
* @param {RequestOptions} [options={}] - An object containing query params and headers for the request
|
|
44
|
+
* @state {KoboToolboxHttpState}
|
|
45
|
+
* @returns {operation}
|
|
46
|
+
*/
|
|
47
|
+
export function post(path: string, data: any, options?: RequestOptions): operation;
|
|
48
|
+
/**
|
|
49
|
+
* Make a PUT request to a KoboToolbox endpoint
|
|
50
|
+
* @public
|
|
51
|
+
* @function
|
|
52
|
+
* @example <caption>Update an asset resource</caption>
|
|
53
|
+
* http.put(
|
|
54
|
+
* 'assets/a4jAWzoa8SZWzZGhx84sB5/deployment/',
|
|
55
|
+
* {
|
|
56
|
+
* name: 'Feedback Survey Test',
|
|
57
|
+
* asset_type: 'survey',
|
|
58
|
+
* },
|
|
59
|
+
* );
|
|
60
|
+
* @param {string} path - path to resource
|
|
61
|
+
* @param {any} data - the body data in JSON format
|
|
62
|
+
* @param {RequestOptions} [options={}] - An object containing query params and headers for the request
|
|
63
|
+
* @state {KoboToolboxHttpState}
|
|
64
|
+
* @returns {operation}
|
|
65
|
+
*/
|
|
66
|
+
export function put(path: string, data: any, options?: RequestOptions): operation;
|
|
67
|
+
/**
|
|
68
|
+
* State object
|
|
69
|
+
*/
|
|
70
|
+
export type KoboToolboxHttpState = {
|
|
71
|
+
/**
|
|
72
|
+
* - The response body (as JSON)
|
|
73
|
+
*/
|
|
74
|
+
data: any;
|
|
75
|
+
/**
|
|
76
|
+
* - The HTTP response from the KoboToolbox server (excluding the body). Responses will be returned in JSON format
|
|
77
|
+
*/
|
|
78
|
+
response: any;
|
|
79
|
+
/**
|
|
80
|
+
* - An array of all previous data objects used in the Job
|
|
81
|
+
*/
|
|
82
|
+
references: any;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Options object
|
|
86
|
+
*/
|
|
87
|
+
export type RequestOptions = {
|
|
88
|
+
/**
|
|
89
|
+
* - An object of query parameters to be encoded into the URL
|
|
90
|
+
*/
|
|
91
|
+
query: object;
|
|
92
|
+
/**
|
|
93
|
+
* - An object of all request headers
|
|
94
|
+
*/
|
|
95
|
+
headers: object;
|
|
96
|
+
/**
|
|
97
|
+
* - The response format to parse (e.g., 'json', 'text', or 'stream')
|
|
98
|
+
*/
|
|
99
|
+
parseAs?: string;
|
|
100
|
+
};
|
package/types/index.d.ts
CHANGED