@openfn/language-asana 3.0.1 → 3.2.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/README.md CHANGED
@@ -16,6 +16,7 @@ definition.
16
16
  Using Asana's API requires having an API token. To generate that token, head to
17
17
  the [Asana developer console](https://app.asana.com/0/developer-console) and
18
18
  enter the **Personal access tokens** section.
19
+ [For API Reference docs](https://developers.asana.com/docs/api-explorer)
19
20
 
20
21
  There you can click on **+New access token**. A prompt will be opened allowing
21
22
  you to give the token a name and then create it.
package/ast.json CHANGED
@@ -17,7 +17,7 @@
17
17
  },
18
18
  {
19
19
  "title": "example",
20
- "description": "getTask(\"taskGid\",\n {\n opt_fields: \"name,notes,assignee\"\n })"
20
+ "description": "getTask(\"1206933955023739\", {\n opt_fields: \"name,notes,assignee\",\n});"
21
21
  },
22
22
  {
23
23
  "title": "function",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  {
82
82
  "title": "example",
83
- "description": "getTasks(\"projectGid\",\n {\n opt_fields: \"name,notes,assignee\"\n })"
83
+ "description": "getTasks(\"1206933955023739\", {\n opt_fields: \"name,notes,assignee\",\n});"
84
84
  },
85
85
  {
86
86
  "title": "function",
@@ -143,7 +143,7 @@
143
143
  },
144
144
  {
145
145
  "title": "example",
146
- "description": "updateTask(\"taskGid\",\n {\n name: 'test', \"approval_status\": \"pending\", \"assignee\": \"12345\"\n }\n)"
146
+ "description": "updateTask(\"1206933955023739\", {\n name: \"test\",\n approval_status: \"pending\",\n assignee: \"12345\",\n});"
147
147
  },
148
148
  {
149
149
  "title": "function",
@@ -205,7 +205,7 @@
205
205
  },
206
206
  {
207
207
  "title": "example",
208
- "description": "createTask(\n {\n name: 'test', \"approval_status\": \"pending\", \"assignee\": \"12345\"\n }\n)"
208
+ "description": "createTask({\n name: \"test\",\n approval_status: \"pending\",\n assignee: \"12345\",\n projects: [\"1206933955023739\"],\n});"
209
209
  },
210
210
  {
211
211
  "title": "function",
@@ -259,7 +259,7 @@
259
259
  },
260
260
  {
261
261
  "title": "example",
262
- "description": "upsertTask(\n \"1201382240880\",\n {\n \"externalId\": \"name\",\n \"data\": {\n name: 'test', \"approval_status\": \"pending\", \"assignee\": \"12345\"\n }\n\n }\n)"
262
+ "description": "upsertTask(\"1201382240880\", {\n externalId: \"name\",\n data: {\n name: \"test\",\n approval_status: \"pending\",\n projects: [\"1201382240880\"],\n assignee: \"12345\",\n },\n});"
263
263
  },
264
264
  {
265
265
  "title": "function",
@@ -724,6 +724,83 @@
724
724
  ]
725
725
  },
726
726
  "valid": true
727
+ },
728
+ {
729
+ "name": "cursor",
730
+ "params": [
731
+ "value",
732
+ "options"
733
+ ],
734
+ "docs": {
735
+ "description": "Sets a cursor property on state.\nSupports natural language dates like `now`, `today`, `yesterday`, `n hours ago`, `n days ago`, and `start`,\nwhich will be converted relative to the environment (ie, the Lightning or CLI locale). Custom timezones \nare not yet supported.\nSee the usage guide at @{link https://docs.openfn.org/documentation/jobs/job-writing-guide#using-cursors}",
736
+ "tags": [
737
+ {
738
+ "title": "public",
739
+ "description": null,
740
+ "type": null
741
+ },
742
+ {
743
+ "title": "example",
744
+ "description": "cursor($.cursor, { defaultValue: 'today' })",
745
+ "caption": "Use a cursor from state if present, or else use the default value"
746
+ },
747
+ {
748
+ "title": "example",
749
+ "description": "cursor(22)",
750
+ "caption": "Use a pagination cursor"
751
+ },
752
+ {
753
+ "title": "function",
754
+ "description": null,
755
+ "name": null
756
+ },
757
+ {
758
+ "title": "param",
759
+ "description": "the cursor value. Usually an ISO date, natural language date, or page number",
760
+ "type": {
761
+ "type": "NameExpression",
762
+ "name": "any"
763
+ },
764
+ "name": "value"
765
+ },
766
+ {
767
+ "title": "param",
768
+ "description": "options to control the cursor.",
769
+ "type": {
770
+ "type": "NameExpression",
771
+ "name": "object"
772
+ },
773
+ "name": "options"
774
+ },
775
+ {
776
+ "title": "param",
777
+ "description": "set the cursor key. Will persist through the whole run.",
778
+ "type": {
779
+ "type": "NameExpression",
780
+ "name": "string"
781
+ },
782
+ "name": "options.key"
783
+ },
784
+ {
785
+ "title": "param",
786
+ "description": "the value to use if value is falsy",
787
+ "type": {
788
+ "type": "NameExpression",
789
+ "name": "any"
790
+ },
791
+ "name": "options.defaultValue"
792
+ },
793
+ {
794
+ "title": "returns",
795
+ "description": null,
796
+ "type": {
797
+ "type": "NameExpression",
798
+ "name": "Operation"
799
+ }
800
+ }
801
+ ]
802
+ },
803
+ "valid": false
727
804
  }
728
805
  ]
729
806
  }
package/dist/index.cjs CHANGED
@@ -19,23 +19,26 @@ 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,
22
+ alterState: () => import_language_common3.alterState,
23
23
  createTask: () => createTask,
24
- dataPath: () => import_language_common2.dataPath,
25
- dataValue: () => import_language_common2.dataValue,
26
- dateFns: () => import_language_common2.dateFns,
24
+ createTaskStory: () => createTaskStory,
25
+ cursor: () => import_language_common3.cursor,
26
+ dataPath: () => import_language_common3.dataPath,
27
+ dataValue: () => import_language_common3.dataValue,
28
+ dateFns: () => import_language_common3.dateFns,
27
29
  default: () => src_default,
28
- each: () => import_language_common2.each,
30
+ each: () => import_language_common3.each,
29
31
  execute: () => execute,
30
- field: () => import_language_common2.field,
31
- fields: () => import_language_common2.fields,
32
- fn: () => import_language_common2.fn,
32
+ field: () => import_language_common3.field,
33
+ fields: () => import_language_common3.fields,
34
+ fn: () => import_language_common3.fn,
33
35
  getTask: () => getTask,
34
36
  getTasks: () => getTasks,
35
- http: () => import_language_common2.http,
36
- lastReferenceValue: () => import_language_common2.lastReferenceValue,
37
- merge: () => import_language_common2.merge,
38
- sourceValue: () => import_language_common2.sourceValue,
37
+ http: () => import_language_common3.http,
38
+ lastReferenceValue: () => import_language_common3.lastReferenceValue,
39
+ merge: () => import_language_common3.merge,
40
+ request: () => request2,
41
+ sourceValue: () => import_language_common3.sourceValue,
39
42
  updateTask: () => updateTask,
40
43
  upsertTask: () => upsertTask
41
44
  });
@@ -44,34 +47,74 @@ module.exports = __toCommonJS(src_exports);
44
47
  // src/Adaptor.js
45
48
  var Adaptor_exports = {};
46
49
  __export(Adaptor_exports, {
47
- alterState: () => import_language_common2.alterState,
50
+ alterState: () => import_language_common3.alterState,
48
51
  createTask: () => createTask,
49
- dataPath: () => import_language_common2.dataPath,
50
- dataValue: () => import_language_common2.dataValue,
51
- dateFns: () => import_language_common2.dateFns,
52
- each: () => import_language_common2.each,
52
+ createTaskStory: () => createTaskStory,
53
+ cursor: () => import_language_common3.cursor,
54
+ dataPath: () => import_language_common3.dataPath,
55
+ dataValue: () => import_language_common3.dataValue,
56
+ dateFns: () => import_language_common3.dateFns,
57
+ each: () => import_language_common3.each,
53
58
  execute: () => execute,
54
- field: () => import_language_common2.field,
55
- fields: () => import_language_common2.fields,
56
- fn: () => import_language_common2.fn,
59
+ field: () => import_language_common3.field,
60
+ fields: () => import_language_common3.fields,
61
+ fn: () => import_language_common3.fn,
57
62
  getTask: () => getTask,
58
63
  getTasks: () => getTasks,
59
- http: () => import_language_common2.http,
60
- lastReferenceValue: () => import_language_common2.lastReferenceValue,
61
- merge: () => import_language_common2.merge,
62
- sourceValue: () => import_language_common2.sourceValue,
64
+ http: () => import_language_common3.http,
65
+ lastReferenceValue: () => import_language_common3.lastReferenceValue,
66
+ merge: () => import_language_common3.merge,
67
+ request: () => request2,
68
+ sourceValue: () => import_language_common3.sourceValue,
63
69
  updateTask: () => updateTask,
64
70
  upsertTask: () => upsertTask
65
71
  });
66
- var import_language_common = require("@openfn/language-common");
67
72
  var import_language_common2 = require("@openfn/language-common");
73
+ var import_util2 = require("@openfn/language-common/util");
74
+
75
+ // src/Utils.js
76
+ var import_language_common = require("@openfn/language-common");
77
+ var import_util = require("@openfn/language-common/util");
78
+ function addAuth(headers, configuration = {}) {
79
+ const { token } = configuration;
80
+ if (token) {
81
+ Object.assign(headers, { Authorization: `Bearer ${token}` });
82
+ }
83
+ }
84
+ function request(state, path, params, callback = (s) => s) {
85
+ var _a;
86
+ let { body, headers = {}, method = "GET", ...rest } = params;
87
+ const baseUrl = `https://app.asana.com/api/${(_a = state.configuration) == null ? void 0 : _a.apiVersion}`;
88
+ addAuth(headers, state.configuration);
89
+ const options = {
90
+ ...rest,
91
+ headers,
92
+ baseUrl,
93
+ body
94
+ };
95
+ return (0, import_util.request)(method, path, options).then((response) => {
96
+ (0, import_util.logResponse)(response);
97
+ const { body: body2, ...responseWithoutBody } = response;
98
+ return {
99
+ ...(0, import_language_common.composeNextState)(state, body2 == null ? void 0 : body2.data),
100
+ response: responseWithoutBody
101
+ };
102
+ }).then(callback).catch((err) => {
103
+ console.log("Asana says:");
104
+ (0, import_util.logResponse)(err);
105
+ throw err;
106
+ });
107
+ }
108
+
109
+ // src/Adaptor.js
110
+ var import_language_common3 = require("@openfn/language-common");
68
111
  function execute(...operations) {
69
112
  const initialState = {
70
113
  references: [],
71
114
  data: null
72
115
  };
73
116
  return (state) => {
74
- return (0, import_language_common.execute)(...operations)({
117
+ return (0, import_language_common2.execute)(...operations)({
75
118
  ...initialState,
76
119
  ...state
77
120
  });
@@ -79,129 +122,123 @@ function execute(...operations) {
79
122
  }
80
123
  function getTask(taskGid, params, callback) {
81
124
  return (state) => {
82
- const resolvedTaskGid = (0, import_language_common.expandReferences)(taskGid)(state);
83
- const { opt_fields } = (0, import_language_common.expandReferences)(params)(state);
84
- const { apiVersion, token } = state.configuration;
85
- const url = `https://app.asana.com/api/${apiVersion}/tasks/${resolvedTaskGid}`;
86
- const config = {
87
- url,
88
- headers: { Authorization: `Bearer ${token}` },
89
- params: {
90
- opt_fields
91
- }
92
- };
93
- return import_language_common.http.get(config)(state).then((response) => {
94
- const nextState = {
95
- ...(0, import_language_common.composeNextState)(state, response.data),
96
- response
97
- };
98
- if (callback)
99
- return callback(nextState);
100
- return nextState;
101
- });
125
+ const [resolvedTaskGid, resolvedParams] = (0, import_util2.expandReferences)(
126
+ state,
127
+ taskGid,
128
+ params
129
+ );
130
+ return request(
131
+ state,
132
+ `tasks/${resolvedTaskGid}`,
133
+ { query: resolvedParams },
134
+ callback
135
+ );
102
136
  };
103
137
  }
104
138
  function getTasks(projectGid, params, callback) {
105
139
  return (state) => {
106
- const resolvedProjectGid = (0, import_language_common.expandReferences)(projectGid)(state);
107
- const { opt_fields } = (0, import_language_common.expandReferences)(params)(state);
108
- const { apiVersion, token } = state.configuration;
109
- const url = `https://app.asana.com/api/${apiVersion}/projects/${resolvedProjectGid}/tasks`;
110
- const config = {
111
- url,
112
- headers: { Authorization: `Bearer ${token}` },
113
- params: {
114
- opt_fields
115
- }
116
- };
117
- return import_language_common.http.get(config)(state).then((response) => {
118
- const nextState = {
119
- ...(0, import_language_common.composeNextState)(state, response.data),
120
- response
121
- };
122
- if (callback)
123
- return callback(nextState);
124
- return nextState;
125
- });
140
+ const [resolvedProjectGid, resolvedParams] = (0, import_util2.expandReferences)(
141
+ state,
142
+ projectGid,
143
+ params
144
+ );
145
+ return request(
146
+ state,
147
+ `projects/${resolvedProjectGid}/tasks`,
148
+ { query: resolvedParams },
149
+ callback
150
+ );
126
151
  };
127
152
  }
128
153
  function updateTask(taskGid, params, callback) {
129
154
  return (state) => {
130
- const resolvedTaskGid = (0, import_language_common.expandReferences)(taskGid)(state);
131
- const resolvedParams = (0, import_language_common.expandReferences)(params)(state);
132
- const { apiVersion, token } = state.configuration;
133
- const url = `https://app.asana.com/api/${apiVersion}/tasks/${resolvedTaskGid}/`;
134
- const config = {
135
- url,
136
- data: { data: resolvedParams },
137
- headers: { Authorization: `Bearer ${token}` }
138
- };
139
- return import_language_common.http.put(config)(state).then((response) => {
140
- const nextState = {
141
- ...(0, import_language_common.composeNextState)(state, response.data),
142
- response
143
- };
144
- if (callback)
145
- return callback(nextState);
146
- return nextState;
147
- }).catch((e) => {
148
- console.log("Asana says:", e.response.data);
149
- throw e;
150
- });
155
+ const [resolvedTaskGid, resolvedParams] = (0, import_util2.expandReferences)(
156
+ state,
157
+ taskGid,
158
+ params
159
+ );
160
+ return request(
161
+ state,
162
+ `tasks/${resolvedTaskGid}`,
163
+ { body: { data: resolvedParams }, method: "PUT" },
164
+ callback
165
+ );
151
166
  };
152
167
  }
153
168
  function createTask(params, callback) {
154
169
  return (state) => {
155
- const resolvedParams = (0, import_language_common.expandReferences)(params)(state);
156
- const { apiVersion, token } = state.configuration;
157
- const url = `https://app.asana.com/api/${apiVersion}/tasks/`;
158
- const config = {
159
- url,
160
- data: { data: resolvedParams },
161
- headers: { Authorization: `Bearer ${token}` }
162
- };
163
- return import_language_common.http.post(config)(state).then((response) => {
164
- const nextState = {
165
- ...(0, import_language_common.composeNextState)(state, response.data),
166
- response
167
- };
168
- if (callback)
169
- return callback(nextState);
170
- return nextState;
171
- }).catch((e) => {
172
- console.log("Asana says:", e.response.data);
173
- throw e;
174
- });
170
+ const [resolvedParams] = (0, import_util2.expandReferences)(state, params);
171
+ return request(
172
+ state,
173
+ "tasks",
174
+ { body: { data: resolvedParams }, method: "POST" },
175
+ callback
176
+ );
175
177
  };
176
178
  }
177
179
  function upsertTask(projectGid, params, callback) {
178
180
  return (state) => {
179
- const resolvedProjectGid = (0, import_language_common.expandReferences)(projectGid)(state);
180
- const { externalId, data } = (0, import_language_common.expandReferences)(params)(state);
181
- const { apiVersion, token } = state.configuration;
182
- const url = `https://app.asana.com/api/${apiVersion}/projects/${resolvedProjectGid}/tasks`;
183
- const config = {
184
- url,
185
- headers: { Authorization: `Bearer ${token}` },
186
- params: {
187
- opt_fields: `${externalId}`
181
+ const [resolvedProjectGid, { externalId, data }] = (0, import_util2.expandReferences)(
182
+ state,
183
+ projectGid,
184
+ params
185
+ );
186
+ return request(
187
+ state,
188
+ `projects/${resolvedProjectGid}/tasks`,
189
+ { query: { opt_fields: `${externalId}` } },
190
+ (next) => {
191
+ const matchingTask = next.data.find(
192
+ (task) => task[externalId] === data[externalId]
193
+ );
194
+ if (matchingTask) {
195
+ console.log("Matching task found. Performing update.");
196
+ console.log("Data to update", data);
197
+ const { projects, workspace, ...remainingData } = data;
198
+ return updateTask(matchingTask.gid, remainingData, callback)(state);
199
+ } else {
200
+ console.log("No matching task found. Performing create.");
201
+ return createTask(data, callback)(state);
202
+ }
188
203
  }
189
- };
190
- return import_language_common.http.get(config)(state).then((response) => {
191
- const matchingTask = response.data.data.find(
192
- (task) => task[externalId] === data[externalId]
193
- );
194
- if (matchingTask) {
195
- console.log("Matching task found. Performing update.");
196
- console.log("Data to update", data);
197
- delete data.projects;
198
- delete data.workspace;
199
- return updateTask(matchingTask.gid, data, callback)(state);
200
- } else {
201
- console.log("No matching task found. Performing create.");
202
- return createTask(data, callback)(state);
204
+ );
205
+ };
206
+ }
207
+ function createTaskStory(taskGid, params, callback) {
208
+ return (state) => {
209
+ const [
210
+ resolvedTaskGid,
211
+ {
212
+ text,
213
+ html_text,
214
+ sticker_name,
215
+ is_pinned = false,
216
+ opt_pretty = false,
217
+ opt_fields = []
203
218
  }
204
- });
219
+ ] = (0, import_util2.expandReferences)(state, taskGid, params);
220
+ const story = { text, html_text, is_pinned, sticker_name };
221
+ return request(
222
+ state,
223
+ `tasks/${resolvedTaskGid}/stories`,
224
+ {
225
+ body: { data: story },
226
+ query: { opt_fields, opt_pretty },
227
+ method: "POST"
228
+ },
229
+ callback
230
+ );
231
+ };
232
+ }
233
+ function request2(path, params, callback) {
234
+ return (state) => {
235
+ const [resolvedPath, { body = {}, query = {}, method = "GET" }] = (0, import_util2.expandReferences)(state, path, params);
236
+ return request(
237
+ state,
238
+ resolvedPath,
239
+ { method, body, query },
240
+ callback
241
+ );
205
242
  };
206
243
  }
207
244
 
@@ -211,6 +248,8 @@ var src_default = Adaptor_exports;
211
248
  0 && (module.exports = {
212
249
  alterState,
213
250
  createTask,
251
+ createTaskStory,
252
+ cursor,
214
253
  dataPath,
215
254
  dataValue,
216
255
  dateFns,
@@ -224,6 +263,7 @@ var src_default = Adaptor_exports;
224
263
  http,
225
264
  lastReferenceValue,
226
265
  merge,
266
+ request,
227
267
  sourceValue,
228
268
  updateTask,
229
269
  upsertTask
package/dist/index.js CHANGED
@@ -9,6 +9,8 @@ var Adaptor_exports = {};
9
9
  __export(Adaptor_exports, {
10
10
  alterState: () => alterState,
11
11
  createTask: () => createTask,
12
+ createTaskStory: () => createTaskStory,
13
+ cursor: () => cursor,
12
14
  dataPath: () => dataPath,
13
15
  dataValue: () => dataValue,
14
16
  dateFns: () => dateFns,
@@ -19,21 +21,58 @@ __export(Adaptor_exports, {
19
21
  fn: () => fn,
20
22
  getTask: () => getTask,
21
23
  getTasks: () => getTasks,
22
- http: () => http2,
24
+ http: () => http,
23
25
  lastReferenceValue: () => lastReferenceValue,
24
26
  merge: () => merge,
27
+ request: () => request2,
25
28
  sourceValue: () => sourceValue,
26
29
  updateTask: () => updateTask,
27
30
  upsertTask: () => upsertTask
28
31
  });
32
+ import { execute as commonExecute } from "@openfn/language-common";
33
+ import { expandReferences } from "@openfn/language-common/util";
34
+
35
+ // src/Utils.js
36
+ import { composeNextState } from "@openfn/language-common";
29
37
  import {
30
- execute as commonExecute,
31
- composeNextState,
32
- expandReferences,
33
- http
34
- } from "@openfn/language-common";
38
+ request as commonRequest,
39
+ logResponse
40
+ } from "@openfn/language-common/util";
41
+ function addAuth(headers, configuration = {}) {
42
+ const { token } = configuration;
43
+ if (token) {
44
+ Object.assign(headers, { Authorization: `Bearer ${token}` });
45
+ }
46
+ }
47
+ function request(state, path, params, callback = (s) => s) {
48
+ var _a;
49
+ let { body, headers = {}, method = "GET", ...rest } = params;
50
+ const baseUrl = `https://app.asana.com/api/${(_a = state.configuration) == null ? void 0 : _a.apiVersion}`;
51
+ addAuth(headers, state.configuration);
52
+ const options = {
53
+ ...rest,
54
+ headers,
55
+ baseUrl,
56
+ body
57
+ };
58
+ return commonRequest(method, path, options).then((response) => {
59
+ logResponse(response);
60
+ const { body: body2, ...responseWithoutBody } = response;
61
+ return {
62
+ ...composeNextState(state, body2 == null ? void 0 : body2.data),
63
+ response: responseWithoutBody
64
+ };
65
+ }).then(callback).catch((err) => {
66
+ console.log("Asana says:");
67
+ logResponse(err);
68
+ throw err;
69
+ });
70
+ }
71
+
72
+ // src/Adaptor.js
35
73
  import {
36
74
  alterState,
75
+ cursor,
37
76
  dataPath,
38
77
  dataValue,
39
78
  dateFns,
@@ -41,7 +80,7 @@ import {
41
80
  field,
42
81
  fields,
43
82
  fn,
44
- http as http2,
83
+ http,
45
84
  lastReferenceValue,
46
85
  merge,
47
86
  sourceValue
@@ -60,129 +99,123 @@ function execute(...operations) {
60
99
  }
61
100
  function getTask(taskGid, params, callback) {
62
101
  return (state) => {
63
- const resolvedTaskGid = expandReferences(taskGid)(state);
64
- const { opt_fields } = expandReferences(params)(state);
65
- const { apiVersion, token } = state.configuration;
66
- const url = `https://app.asana.com/api/${apiVersion}/tasks/${resolvedTaskGid}`;
67
- const config = {
68
- url,
69
- headers: { Authorization: `Bearer ${token}` },
70
- params: {
71
- opt_fields
72
- }
73
- };
74
- return http.get(config)(state).then((response) => {
75
- const nextState = {
76
- ...composeNextState(state, response.data),
77
- response
78
- };
79
- if (callback)
80
- return callback(nextState);
81
- return nextState;
82
- });
102
+ const [resolvedTaskGid, resolvedParams] = expandReferences(
103
+ state,
104
+ taskGid,
105
+ params
106
+ );
107
+ return request(
108
+ state,
109
+ `tasks/${resolvedTaskGid}`,
110
+ { query: resolvedParams },
111
+ callback
112
+ );
83
113
  };
84
114
  }
85
115
  function getTasks(projectGid, params, callback) {
86
116
  return (state) => {
87
- const resolvedProjectGid = expandReferences(projectGid)(state);
88
- const { opt_fields } = expandReferences(params)(state);
89
- const { apiVersion, token } = state.configuration;
90
- const url = `https://app.asana.com/api/${apiVersion}/projects/${resolvedProjectGid}/tasks`;
91
- const config = {
92
- url,
93
- headers: { Authorization: `Bearer ${token}` },
94
- params: {
95
- opt_fields
96
- }
97
- };
98
- return http.get(config)(state).then((response) => {
99
- const nextState = {
100
- ...composeNextState(state, response.data),
101
- response
102
- };
103
- if (callback)
104
- return callback(nextState);
105
- return nextState;
106
- });
117
+ const [resolvedProjectGid, resolvedParams] = expandReferences(
118
+ state,
119
+ projectGid,
120
+ params
121
+ );
122
+ return request(
123
+ state,
124
+ `projects/${resolvedProjectGid}/tasks`,
125
+ { query: resolvedParams },
126
+ callback
127
+ );
107
128
  };
108
129
  }
109
130
  function updateTask(taskGid, params, callback) {
110
131
  return (state) => {
111
- const resolvedTaskGid = expandReferences(taskGid)(state);
112
- const resolvedParams = expandReferences(params)(state);
113
- const { apiVersion, token } = state.configuration;
114
- const url = `https://app.asana.com/api/${apiVersion}/tasks/${resolvedTaskGid}/`;
115
- const config = {
116
- url,
117
- data: { data: resolvedParams },
118
- headers: { Authorization: `Bearer ${token}` }
119
- };
120
- return http.put(config)(state).then((response) => {
121
- const nextState = {
122
- ...composeNextState(state, response.data),
123
- response
124
- };
125
- if (callback)
126
- return callback(nextState);
127
- return nextState;
128
- }).catch((e) => {
129
- console.log("Asana says:", e.response.data);
130
- throw e;
131
- });
132
+ const [resolvedTaskGid, resolvedParams] = expandReferences(
133
+ state,
134
+ taskGid,
135
+ params
136
+ );
137
+ return request(
138
+ state,
139
+ `tasks/${resolvedTaskGid}`,
140
+ { body: { data: resolvedParams }, method: "PUT" },
141
+ callback
142
+ );
132
143
  };
133
144
  }
134
145
  function createTask(params, callback) {
135
146
  return (state) => {
136
- const resolvedParams = expandReferences(params)(state);
137
- const { apiVersion, token } = state.configuration;
138
- const url = `https://app.asana.com/api/${apiVersion}/tasks/`;
139
- const config = {
140
- url,
141
- data: { data: resolvedParams },
142
- headers: { Authorization: `Bearer ${token}` }
143
- };
144
- return http.post(config)(state).then((response) => {
145
- const nextState = {
146
- ...composeNextState(state, response.data),
147
- response
148
- };
149
- if (callback)
150
- return callback(nextState);
151
- return nextState;
152
- }).catch((e) => {
153
- console.log("Asana says:", e.response.data);
154
- throw e;
155
- });
147
+ const [resolvedParams] = expandReferences(state, params);
148
+ return request(
149
+ state,
150
+ "tasks",
151
+ { body: { data: resolvedParams }, method: "POST" },
152
+ callback
153
+ );
156
154
  };
157
155
  }
158
156
  function upsertTask(projectGid, params, callback) {
159
157
  return (state) => {
160
- const resolvedProjectGid = expandReferences(projectGid)(state);
161
- const { externalId, data } = expandReferences(params)(state);
162
- const { apiVersion, token } = state.configuration;
163
- const url = `https://app.asana.com/api/${apiVersion}/projects/${resolvedProjectGid}/tasks`;
164
- const config = {
165
- url,
166
- headers: { Authorization: `Bearer ${token}` },
167
- params: {
168
- opt_fields: `${externalId}`
158
+ const [resolvedProjectGid, { externalId, data }] = expandReferences(
159
+ state,
160
+ projectGid,
161
+ params
162
+ );
163
+ return request(
164
+ state,
165
+ `projects/${resolvedProjectGid}/tasks`,
166
+ { query: { opt_fields: `${externalId}` } },
167
+ (next) => {
168
+ const matchingTask = next.data.find(
169
+ (task) => task[externalId] === data[externalId]
170
+ );
171
+ if (matchingTask) {
172
+ console.log("Matching task found. Performing update.");
173
+ console.log("Data to update", data);
174
+ const { projects, workspace, ...remainingData } = data;
175
+ return updateTask(matchingTask.gid, remainingData, callback)(state);
176
+ } else {
177
+ console.log("No matching task found. Performing create.");
178
+ return createTask(data, callback)(state);
179
+ }
169
180
  }
170
- };
171
- return http.get(config)(state).then((response) => {
172
- const matchingTask = response.data.data.find(
173
- (task) => task[externalId] === data[externalId]
174
- );
175
- if (matchingTask) {
176
- console.log("Matching task found. Performing update.");
177
- console.log("Data to update", data);
178
- delete data.projects;
179
- delete data.workspace;
180
- return updateTask(matchingTask.gid, data, callback)(state);
181
- } else {
182
- console.log("No matching task found. Performing create.");
183
- return createTask(data, callback)(state);
181
+ );
182
+ };
183
+ }
184
+ function createTaskStory(taskGid, params, callback) {
185
+ return (state) => {
186
+ const [
187
+ resolvedTaskGid,
188
+ {
189
+ text,
190
+ html_text,
191
+ sticker_name,
192
+ is_pinned = false,
193
+ opt_pretty = false,
194
+ opt_fields = []
184
195
  }
185
- });
196
+ ] = expandReferences(state, taskGid, params);
197
+ const story = { text, html_text, is_pinned, sticker_name };
198
+ return request(
199
+ state,
200
+ `tasks/${resolvedTaskGid}/stories`,
201
+ {
202
+ body: { data: story },
203
+ query: { opt_fields, opt_pretty },
204
+ method: "POST"
205
+ },
206
+ callback
207
+ );
208
+ };
209
+ }
210
+ function request2(path, params, callback) {
211
+ return (state) => {
212
+ const [resolvedPath, { body = {}, query = {}, method = "GET" }] = expandReferences(state, path, params);
213
+ return request(
214
+ state,
215
+ resolvedPath,
216
+ { method, body, query },
217
+ callback
218
+ );
186
219
  };
187
220
  }
188
221
 
@@ -191,6 +224,8 @@ var src_default = Adaptor_exports;
191
224
  export {
192
225
  alterState,
193
226
  createTask,
227
+ createTaskStory,
228
+ cursor,
194
229
  dataPath,
195
230
  dataValue,
196
231
  dateFns,
@@ -202,9 +237,10 @@ export {
202
237
  fn,
203
238
  getTask,
204
239
  getTasks,
205
- http2 as http,
240
+ http,
206
241
  lastReferenceValue,
207
242
  merge,
243
+ request2 as request,
208
244
  sourceValue,
209
245
  updateTask,
210
246
  upsertTask
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfn/language-asana",
3
- "version": "3.0.1",
3
+ "version": "3.2.0",
4
4
  "description": "An adaptor to access objects in Asana",
5
5
  "homepage": "https://docs.openfn.org",
6
6
  "repository": {
@@ -23,10 +23,9 @@
23
23
  "configuration-schema.json"
24
24
  ],
25
25
  "dependencies": {
26
- "@openfn/language-common": "^1.8.1"
26
+ "@openfn/language-common": "^1.13.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@openfn/buildtools": "^1.0.2",
30
29
  "@openfn/simple-ast": "0.4.1",
31
30
  "assertion-error": "2.0.0",
32
31
  "chai": "4.3.6",
@@ -15,10 +15,9 @@ export function execute(...operations: Operations): Operation;
15
15
  * Get a single task of a given project.
16
16
  * @public
17
17
  * @example
18
- * getTask("taskGid",
19
- * {
20
- * opt_fields: "name,notes,assignee"
21
- * })
18
+ * getTask("1206933955023739", {
19
+ * opt_fields: "name,notes,assignee",
20
+ * });
22
21
  * @function
23
22
  * @param {string} taskGid - Globally unique identifier for the task
24
23
  * @param {object} params - Query params to include.
@@ -30,10 +29,9 @@ export function getTask(taskGid: string, params: object, callback: Function): Op
30
29
  * Get the list of tasks for a given project.
31
30
  * @public
32
31
  * @example
33
- * getTasks("projectGid",
34
- * {
35
- * opt_fields: "name,notes,assignee"
36
- * })
32
+ * getTasks("1206933955023739", {
33
+ * opt_fields: "name,notes,assignee",
34
+ * });
37
35
  * @function
38
36
  * @param {string} projectGid - Globally unique identifier for the project
39
37
  * @param {object} params - Query params to include.
@@ -45,11 +43,11 @@ export function getTasks(projectGid: string, params: object, callback: Function)
45
43
  * Update a specific task.
46
44
  * @public
47
45
  * @example
48
- * updateTask("taskGid",
49
- * {
50
- * name: 'test', "approval_status": "pending", "assignee": "12345"
51
- * }
52
- * )
46
+ * updateTask("1206933955023739", {
47
+ * name: "test",
48
+ * approval_status: "pending",
49
+ * assignee: "12345",
50
+ * });
53
51
  * @function
54
52
  * @param {string} taskGid - Globally unique identifier for the task
55
53
  * @param {object} params - Body parameters
@@ -61,11 +59,12 @@ export function updateTask(taskGid: string, params: object, callback: Function):
61
59
  * Create a task.
62
60
  * @public
63
61
  * @example
64
- * createTask(
65
- * {
66
- * name: 'test', "approval_status": "pending", "assignee": "12345"
67
- * }
68
- * )
62
+ * createTask({
63
+ * name: "test",
64
+ * approval_status: "pending",
65
+ * assignee: "12345",
66
+ * projects: ["1206933955023739"],
67
+ * });
69
68
  * @function
70
69
  * @param {object} params - Body parameters
71
70
  * @param {function} callback - (Optional) callback function
@@ -76,16 +75,15 @@ export function createTask(params: object, callback: Function): Operation;
76
75
  * Update or create a task.
77
76
  * @public
78
77
  * @example
79
- * upsertTask(
80
- * "1201382240880",
81
- * {
82
- * "externalId": "name",
83
- * "data": {
84
- * name: 'test', "approval_status": "pending", "assignee": "12345"
85
- * }
86
- *
87
- * }
88
- * )
78
+ * upsertTask("1201382240880", {
79
+ * externalId: "name",
80
+ * data: {
81
+ * name: "test",
82
+ * approval_status: "pending",
83
+ * projects: ["1201382240880"],
84
+ * assignee: "12345",
85
+ * },
86
+ * });
89
87
  * @function
90
88
  * @param {string} projectGid - Globally unique identifier for the project
91
89
  * @param {object} params - an object with an externalId and some task data.
@@ -93,4 +91,100 @@ export function createTask(params: object, callback: Function): Operation;
93
91
  * @returns {Operation}
94
92
  */
95
93
  export function upsertTask(projectGid: string, params: object, callback: Function): Operation;
96
- export { alterState, dataPath, dataValue, dateFns, each, field, fields, fn, http, lastReferenceValue, merge, sourceValue } from "@openfn/language-common";
94
+ /**
95
+ * Options provided to the createTaskStory request
96
+ * @typedef {Object} StoryOptions
97
+ * @property {string} text - The plain text of the comment to add. Cannot be used with html_text.
98
+ * @property {string} html_text - Opt In. HTML formatted text for a comment. This will not include the name of the creator.
99
+ * @property {boolean} is_pinned - Default to `false`. Whether the story should be pinned on the resource.
100
+ * @property {string} sticker_name - The name of the sticker in this story. `null` if there is no sticker.
101
+ * @property {array} opt_fields - Opt In. This endpoint returns a compact resource, which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to include.
102
+ * @property {boolean} opt_pretty - Defaults to `false`. Provides the response in a “pretty” format. In the case of JSON this means doing proper line breaking and indentation to make it readable. This will take extra time and increase the response size so it is advisable only to use this during debugging.
103
+ */
104
+ /**
105
+ * Create a story to a specific task.
106
+ * @public
107
+ * @example <caption>Create a plain text comment</caption>
108
+ * createTaskStory("1206933955023739", {
109
+ * text: "This is a comment",
110
+ * });
111
+ * @example <caption>Create a HTML formatted text comment</caption>
112
+ * createTaskStory("1206933955023739", {
113
+ * html_text: "<body>This is a comment</body>",
114
+ * });
115
+ * @function
116
+ * @param {string} taskGid - Globally unique identifier for the task
117
+ * @param {StoryOptions} params - Story parameters
118
+ * @param {function} callback - (Optional) callback function
119
+ * @returns {Operation}
120
+ */
121
+ export function createTaskStory(taskGid: string, params: StoryOptions, callback: Function): Operation;
122
+ /**
123
+ * Options provided to the Asana API request
124
+ * @typedef {Object} RequestOptions
125
+ * @property {object} body - Body data to append to the request.
126
+ * @property {object} query - An object of query parameters to be encoded into the URL.
127
+ * @property {string} method - The HTTP method to use. Defaults to `GET`
128
+ */
129
+ /**
130
+ * Make a request in Asana API
131
+ * @public
132
+ * @example
133
+ * request("/asanaEndpoint", {
134
+ * method: "POST",
135
+ * query: { foo: "bar", a: 1 },
136
+ * });
137
+ * @function
138
+ * @param {string} path - Path to resource
139
+ * @param {RequestOptions} params - Query, body and method parameters
140
+ * @param {function} callback - (Optional) Callback function
141
+ * @returns {Operation}
142
+ */
143
+ export function request(path: string, params: RequestOptions, callback: Function): Operation;
144
+ /**
145
+ * Options provided to the createTaskStory request
146
+ */
147
+ export type StoryOptions = {
148
+ /**
149
+ * - The plain text of the comment to add. Cannot be used with html_text.
150
+ */
151
+ text: string;
152
+ /**
153
+ * - Opt In. HTML formatted text for a comment. This will not include the name of the creator.
154
+ */
155
+ html_text: string;
156
+ /**
157
+ * - Default to `false`. Whether the story should be pinned on the resource.
158
+ */
159
+ is_pinned: boolean;
160
+ /**
161
+ * - The name of the sticker in this story. `null` if there is no sticker.
162
+ */
163
+ sticker_name: string;
164
+ /**
165
+ * - Opt In. This endpoint returns a compact resource, which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to include.
166
+ */
167
+ opt_fields: any[];
168
+ /**
169
+ * - Defaults to `false`. Provides the response in a “pretty” format. In the case of JSON this means doing proper line breaking and indentation to make it readable. This will take extra time and increase the response size so it is advisable only to use this during debugging.
170
+ */
171
+ opt_pretty: boolean;
172
+ };
173
+ /**
174
+ * Options provided to the Asana API request
175
+ */
176
+ export type RequestOptions = {
177
+ /**
178
+ * - Body data to append to the request.
179
+ */
180
+ body: object;
181
+ /**
182
+ * - An object of query parameters to be encoded into the URL.
183
+ */
184
+ query: object;
185
+ /**
186
+ * - The HTTP method to use. Defaults to `GET`
187
+ */
188
+ method: string;
189
+ };
190
+ export { alterState, cursor, dataPath, dataValue, dateFns, each, field, fields, fn, http, lastReferenceValue, merge, sourceValue } from "@openfn/language-common";
@@ -0,0 +1,2 @@
1
+ export function addAuth(headers: any, configuration?: {}): void;
2
+ export function request(state: any, path: any, params: any, callback?: (s: any) => any): any;