@openfn/language-kobotoolbox 2.4.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 get the list of forms",
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({}, state => {\n console.log(state.data);\n return state;\n});"
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": "param",
28
- "description": "Query, Headers and Authentication parameters",
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
- "params",
60
- "callback"
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({formId: 'aXecHjmbATuF6iGFmvBLBX'}, state => {\n console.log(state.data);\n return state;\n});"
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 and data to make the fetch or filter",
70
+ "description": "Form Id to get the specific submissions",
82
71
  "type": {
83
72
  "type": "NameExpression",
84
- "name": "object"
73
+ "name": "string"
85
74
  },
86
- "name": "params"
75
+ "name": "formId"
87
76
  },
88
77
  {
89
78
  "title": "param",
90
- "description": "(Optional) Callback function to execute after fetching form submissions",
79
+ "description": "Optional query params for the request",
91
80
  "type": {
92
- "type": "NameExpression",
93
- "name": "function"
81
+ "type": "OptionalType",
82
+ "expression": {
83
+ "type": "NameExpression",
84
+ "name": "object"
85
+ }
94
86
  },
95
- "name": "callback"
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
- "params",
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({formId: 'aXecHjmbATuF6iGFmvBLBX'}, state => {\n console.log(state.data);\n return state;\n});"
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 and data to make the fetch or filter",
130
+ "description": "Form Id to get the deployment information",
135
131
  "type": {
136
132
  "type": "NameExpression",
137
- "name": "object"
133
+ "name": "string"
138
134
  },
139
- "name": "params"
135
+ "name": "formId"
140
136
  },
141
137
  {
142
- "title": "param",
143
- "description": "(Optional) Callback function to execute after fetching form deployment information",
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": "Scopes an array of data based on a JSONPath.\nUseful when the source data has `n` items you would like to map to\nan operation.\nThe operation will receive a slice of the data based of each item\nof the JSONPath provided.\n\nIt also ensures the results of an operation make their way back into\nthe state's references.",
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(\"$.[*]\",\n create(\"SObject\",\n field(\"FirstName\", sourceValue(\"$.firstName\"))\n )\n)"
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
- "baseURL": {
5
- "title": "Base URL",
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
- "baseURL",
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: () => import_language_common2.alterState,
23
- cursor: () => import_language_common2.cursor,
24
- dataPath: () => import_language_common2.dataPath,
25
- dataValue: () => import_language_common2.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: () => import_language_common2.each,
27
+ each: () => import_language_common3.each,
28
28
  execute: () => execute,
29
- field: () => import_language_common2.field,
30
- fields: () => import_language_common2.fields,
31
- fn: () => import_language_common2.fn,
32
- fnIf: () => import_language_common2.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: () => import_language_common2.group,
37
- http: () => import_language_common2.http,
38
- lastReferenceValue: () => import_language_common2.lastReferenceValue,
39
- merge: () => import_language_common2.merge,
40
- sourceValue: () => import_language_common2.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: () => import_language_common2.alterState,
48
- cursor: () => import_language_common2.cursor,
49
- dataPath: () => import_language_common2.dataPath,
50
- dataValue: () => import_language_common2.dataValue,
51
- each: () => import_language_common2.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: () => import_language_common2.field,
54
- fields: () => import_language_common2.fields,
55
- fn: () => import_language_common2.fn,
56
- fnIf: () => import_language_common2.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: () => import_language_common2.group,
61
- http: () => import_language_common2.http,
62
- lastReferenceValue: () => import_language_common2.lastReferenceValue,
63
- merge: () => import_language_common2.merge,
64
- sourceValue: () => import_language_common2.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, import_language_common.execute)(...operations)({
148
+ return (0, import_language_common2.execute)(...operations)({
75
149
  ...initialState,
76
150
  ...state
77
151
  });
78
152
  };
79
153
  }
80
- function getForms(params, callback) {
81
- return (state) => {
82
- const resolvedParams = (0, import_language_common.expandReferences)(params)(state);
83
- const { baseURL, apiVersion, username, password } = state.configuration;
84
- const url = `${baseURL}/api/${apiVersion}/assets/?format=json`;
85
- const auth = { username, password };
86
- const config = {
87
- url,
88
- params: resolvedParams,
89
- auth
90
- };
91
- return import_language_common.http.get(config)(state).then((response) => {
92
- console.log("\u2713", response.data.count, "forms fetched.");
93
- const nextState = (0, import_language_common.composeNextState)(state, response.data);
94
- if (callback)
95
- return callback(nextState);
96
- return nextState;
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 response = await request(state, "GET", url, {
179
+ paginate: true,
180
+ query
97
181
  });
182
+ console.log("\u2713", response.results.length, "submissions fetched.");
183
+ return prepareNextState(state, response);
98
184
  };
99
185
  }
100
- function getSubmissions(params, callback) {
101
- return (state) => {
102
- const resolvedParams = (0, import_language_common.expandReferences)(params)(state);
103
- const { baseURL, apiVersion, username, password } = state.configuration;
104
- const { formId } = resolvedParams;
105
- const url = `${baseURL}/api/${apiVersion}/assets/${formId}/data/?format=json`;
106
- const auth = { username, password };
107
- const config = {
108
- url,
109
- params: resolvedParams.query,
110
- auth
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
- return import_language_common.http.get(config)(state).then((response) => {
113
- console.log("\u2713", response.data.count, "submissions fetched.");
114
- const nextState = (0, import_language_common.composeNextState)(state, response.data);
115
- if (callback)
116
- return callback(nextState);
117
- return nextState;
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 getDeploymentInfo(params, callback) {
122
- return (state) => {
123
- const resolvedParams = (0, import_language_common.expandReferences)(params)(state);
124
- const { baseURL, apiVersion, username, password } = state.configuration;
125
- const { formId } = resolvedParams;
126
- const url = `${baseURL}/api/${apiVersion}/assets/${formId}/deployment/?format=json`;
127
- const auth = { username, password };
128
- const config = {
129
- url,
130
- params: resolvedParams.query,
131
- auth
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
- return import_language_common.http.get(config)(state).then((response) => {
134
- console.log("\u2713", "deployment information fetched.");
135
- const nextState = (0, import_language_common.composeNextState)(state, response.data);
136
- if (callback)
137
- return callback(nextState);
138
- return nextState;
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,90 @@ __export(Adaptor_exports, {
21
21
  getForms: () => getForms,
22
22
  getSubmissions: () => getSubmissions,
23
23
  group: () => group,
24
- http: () => http2,
24
+ http: () => http,
25
25
  lastReferenceValue: () => lastReferenceValue,
26
26
  merge: () => merge,
27
27
  sourceValue: () => sourceValue
28
28
  });
29
+ import { execute as commonExecute } from "@openfn/language-common";
30
+ import { expandReferences } from "@openfn/language-common/util";
31
+
32
+ // src/Utils.js
33
+ import { composeNextState } from "@openfn/language-common";
29
34
  import {
30
- execute as commonExecute,
31
- composeNextState,
32
- expandReferences,
33
- http
34
- } from "@openfn/language-common";
35
+ request as commonRequest,
36
+ makeBasicAuthHeader,
37
+ logResponse
38
+ } from "@openfn/language-common/util";
39
+ var prepareNextState = (state, response) => {
40
+ const { body, ...responseWithoutBody } = response;
41
+ return {
42
+ ...composeNextState(state, response.body),
43
+ response: responseWithoutBody
44
+ };
45
+ };
46
+ async function request(state, method, path, opts) {
47
+ const { baseURL, apiVersion, username, password } = state.configuration;
48
+ let baseUrl;
49
+ if (!state.configuration.baseUrl && baseURL) {
50
+ baseUrl = baseURL;
51
+ console.warn(
52
+ "No baseUrl found in state.configuration. baseURL will be used instead, but this will be deprecated in the future."
53
+ );
54
+ } else {
55
+ baseUrl = state.configuration.baseUrl;
56
+ }
57
+ const {
58
+ data = {},
59
+ query = {},
60
+ headers = {},
61
+ parseAs = "json",
62
+ paginate = false
63
+ } = opts;
64
+ const authHeaders = makeBasicAuthHeader(username, password);
65
+ let start, limit;
66
+ const options = {
67
+ body: data,
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ ...authHeaders,
71
+ ...headers
72
+ },
73
+ query: {
74
+ format: "json",
75
+ ...query
76
+ },
77
+ parseAs,
78
+ baseUrl: `${baseUrl}/api/${apiVersion}`
79
+ };
80
+ if (paginate) {
81
+ const results = [];
82
+ do {
83
+ const response = await commonRequest(method, path, options).then(
84
+ logResponse
85
+ );
86
+ results.push(...response.body.results);
87
+ if (response.body.next) {
88
+ const nextUrl = new URL(response.body.next);
89
+ const startDigit = nextUrl.searchParams.get("start") !== null ? nextUrl.searchParams.get("start") : 0;
90
+ start = Number(startDigit);
91
+ limit = nextUrl.searchParams.get("limit");
92
+ options.query = {
93
+ ...options.query,
94
+ start,
95
+ limit
96
+ };
97
+ } else {
98
+ break;
99
+ }
100
+ } while (true);
101
+ return { results };
102
+ } else {
103
+ return commonRequest(method, path, options).then(logResponse);
104
+ }
105
+ }
106
+
107
+ // src/Adaptor.js
35
108
  import {
36
109
  alterState,
37
110
  cursor,
@@ -42,7 +115,7 @@ import {
42
115
  fields,
43
116
  fn,
44
117
  fnIf,
45
- http as http2,
118
+ http,
46
119
  group,
47
120
  lastReferenceValue,
48
121
  merge,
@@ -60,66 +133,112 @@ function execute(...operations) {
60
133
  });
61
134
  };
62
135
  }
63
- function getForms(params, callback) {
64
- return (state) => {
65
- const resolvedParams = expandReferences(params)(state);
66
- const { baseURL, apiVersion, username, password } = state.configuration;
67
- const url = `${baseURL}/api/${apiVersion}/assets/?format=json`;
68
- const auth = { username, password };
69
- const config = {
70
- url,
71
- params: resolvedParams,
72
- auth
73
- };
74
- return http.get(config)(state).then((response) => {
75
- console.log("\u2713", response.data.count, "forms fetched.");
76
- const nextState = composeNextState(state, response.data);
77
- if (callback)
78
- return callback(nextState);
79
- return nextState;
136
+ function getForms() {
137
+ return async (state) => {
138
+ const url = `/assets/?asset_type=survey`;
139
+ const response = await request(state, "GET", url, {});
140
+ console.log("\u2713", response.body.results.length, "forms fetched.");
141
+ return prepareNextState(state, response);
142
+ };
143
+ }
144
+ function getSubmissions(formId, options = {}) {
145
+ return async (state) => {
146
+ const [resolvedFormId, resolvedOptions] = expandReferences(
147
+ state,
148
+ formId,
149
+ options
150
+ );
151
+ const url = `/assets/${resolvedFormId}/data/`;
152
+ const query = {};
153
+ if (resolvedOptions.query) {
154
+ if (typeof resolvedOptions.query == "string") {
155
+ query.query = resolvedOptions.query;
156
+ } else {
157
+ query.query = JSON.stringify(resolvedOptions.query);
158
+ }
159
+ }
160
+ const response = await request(state, "GET", url, {
161
+ paginate: true,
162
+ query
80
163
  });
164
+ console.log("\u2713", response.results.length, "submissions fetched.");
165
+ return prepareNextState(state, response);
81
166
  };
82
167
  }
83
- function getSubmissions(params, callback) {
84
- return (state) => {
85
- const resolvedParams = expandReferences(params)(state);
86
- const { baseURL, apiVersion, username, password } = state.configuration;
87
- const { formId } = resolvedParams;
88
- const url = `${baseURL}/api/${apiVersion}/assets/${formId}/data/?format=json`;
89
- const auth = { username, password };
90
- const config = {
91
- url,
92
- params: resolvedParams.query,
93
- auth
168
+ function getDeploymentInfo(formId) {
169
+ return async (state) => {
170
+ const [resolvedFormId] = expandReferences(state, formId);
171
+ const url = `/assets/${resolvedFormId}/deployment/`;
172
+ const response = await request(state, "GET", url, {});
173
+ console.log("\u2713", "deployment information fetched.");
174
+ return prepareNextState(state, response);
175
+ };
176
+ }
177
+
178
+ // src/http.js
179
+ var http_exports = {};
180
+ __export(http_exports, {
181
+ get: () => get,
182
+ post: () => post,
183
+ put: () => put
184
+ });
185
+ import { expandReferences as expandReferences2 } from "@openfn/language-common/util";
186
+ function get(path, options = {}) {
187
+ return async (state) => {
188
+ const [resolvedPath, resolvedOptions] = expandReferences2(
189
+ state,
190
+ path,
191
+ options
192
+ );
193
+ const response = await request(
194
+ state,
195
+ "GET",
196
+ resolvedPath,
197
+ resolvedOptions
198
+ );
199
+ return prepareNextState(state, response);
200
+ };
201
+ }
202
+ function post(path, data, options = {}) {
203
+ return async (state) => {
204
+ const [resolvedPath, resolvedData, resolvedOptions] = expandReferences2(
205
+ state,
206
+ path,
207
+ data,
208
+ options
209
+ );
210
+ const optionsObject = {
211
+ data: resolvedData,
212
+ ...resolvedOptions
94
213
  };
95
- return http.get(config)(state).then((response) => {
96
- console.log("\u2713", response.data.count, "submissions fetched.");
97
- const nextState = composeNextState(state, response.data);
98
- if (callback)
99
- return callback(nextState);
100
- return nextState;
101
- });
214
+ const response = await request(
215
+ state,
216
+ "POST",
217
+ resolvedPath,
218
+ optionsObject
219
+ );
220
+ return prepareNextState(state, response);
102
221
  };
103
222
  }
104
- function getDeploymentInfo(params, callback) {
105
- return (state) => {
106
- const resolvedParams = expandReferences(params)(state);
107
- const { baseURL, apiVersion, username, password } = state.configuration;
108
- const { formId } = resolvedParams;
109
- const url = `${baseURL}/api/${apiVersion}/assets/${formId}/deployment/?format=json`;
110
- const auth = { username, password };
111
- const config = {
112
- url,
113
- params: resolvedParams.query,
114
- auth
223
+ function put(path, data, options = {}) {
224
+ return async (state) => {
225
+ const [resolvedPath, resolvedData, resolvedOptions] = expandReferences2(
226
+ state,
227
+ path,
228
+ data,
229
+ options
230
+ );
231
+ const optionsObject = {
232
+ data: resolvedData,
233
+ ...resolvedOptions
115
234
  };
116
- return http.get(config)(state).then((response) => {
117
- console.log("\u2713", "deployment information fetched.");
118
- const nextState = composeNextState(state, response.data);
119
- if (callback)
120
- return callback(nextState);
121
- return nextState;
122
- });
235
+ const response = await request(
236
+ state,
237
+ "PUT",
238
+ resolvedPath,
239
+ optionsObject
240
+ );
241
+ return prepareNextState(state, response);
123
242
  };
124
243
  }
125
244
 
@@ -141,7 +260,7 @@ export {
141
260
  getForms,
142
261
  getSubmissions,
143
262
  group,
144
- http2 as http,
263
+ http_exports as http,
145
264
  lastReferenceValue,
146
265
  merge,
147
266
  sourceValue
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfn/language-kobotoolbox",
3
- "version": "2.4.3",
3
+ "version": "3.0.0",
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": "1.15.2"
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",
@@ -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 get the list of forms
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({}, state => {
19
- * console.log(state.data);
20
- * return state;
21
- * });
25
+ * getForms();
22
26
  * @function
23
- * @param {object} params - Query, Headers and Authentication parameters
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(params: object, callback: Function): Operation;
30
+ export function getForms(): Operation;
28
31
  /**
29
- * Get submissions for a specific form
30
- * @example
31
- * getSubmissions({formId: 'aXecHjmbATuF6iGFmvBLBX'}, state => {
32
- * console.log(state.data);
33
- * return state;
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 {object} params - Form Id and data to make the fetch or filter
38
- * @param {function} callback - (Optional) Callback function to execute after fetching form submissions
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(params: object, callback: Function): Operation;
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({formId: 'aXecHjmbATuF6iGFmvBLBX'}, state => {
46
- * console.log(state.data);
47
- * return state;
48
- * });
48
+ * getDeploymentInfo('aXecHjmbATuF6iGFmvBLBX');
49
49
  * @function
50
50
  * @public
51
- * @param {object} params - Form Id and data to make the fetch or filter
52
- * @param {function} callback - (Optional) Callback function to execute after fetching form deployment information
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(params: object, callback: Function): Operation;
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";
@@ -0,0 +1,2 @@
1
+ export function request(state: any, method: any, path: any, opts: any): Promise<any>;
2
+ export function prepareNextState(state: any, response: any): any;
@@ -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
@@ -1,3 +1,4 @@
1
1
  export default Adaptor;
2
2
  export * from "./Adaptor";
3
+ export * as http from "./http";
3
4
  import * as Adaptor from "./Adaptor";