@superdurable/connector-asana 0.1.0 → 0.1.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Asana connector for Dex TypeScript
2
2
 
3
- Install `@superdurable/connector-asana@0.1.0` alongside `@superdurable/dex` and `@superdurable/connectors-sdk`. This package implements `listTasks`, `getTask`, `createTask`, `updateTask`, and `addComment`; it does not implement Triggers.
3
+ Install `@superdurable/connector-asana@0.1.1` alongside `@superdurable/dex` and `@superdurable/connectors-sdk`. This package implements `listTasks`, `getTask`, `createTask`, `updateTask`, and `addComment`; it does not implement Triggers.
4
4
 
5
5
  `Client` takes a `Config` and a `CredentialProvider<Credentials>`. Use `newProjectConnection` to load the named Dex Web connection, or `newConnection` to bind a client explicitly. The [approved request example](examples/approved-request-task/flow.ts) is a runnable Flow using every operation and the static `asana-approved-requests` connection name. Start its [Worker](examples/approved-request-task/main.ts) after configuring that connection in Dex Web. The [example guide](examples/approved-request-task/README.md) gives local verification commands.
6
6
 
@@ -4,7 +4,7 @@
4
4
  "package": {
5
5
  "ecosystem": "npm",
6
6
  "name": "@superdurable/connector-asana",
7
- "version": "0.1.0"
7
+ "version": "0.1.1"
8
8
  },
9
9
  "factories": [
10
10
  {
@@ -1,15 +1,50 @@
1
1
  // src/generated/models.ts
2
2
  import { z } from "zod";
3
+ import { SecretString } from "@superdurable/connectors-sdk";
4
+ var goTimeJSONPattern = /^(\d{4})-(\d{2})-(\d{2})T(\d{1,2}):(\d{2}):(\d{2})(?:[.,](\d+))?(Z|([+-])(\d{2}):(\d{2}))$/;
5
+ function isGoTimeJSON(value) {
6
+ const match = goTimeJSONPattern.exec(value);
7
+ if (!match) return false;
8
+ const [, yearText, monthText, dayText, hourText, minuteText, secondText, , zone, , zoneHourText, zoneMinuteText] = match;
9
+ const year = Number(yearText);
10
+ const month = Number(monthText);
11
+ const day = Number(dayText);
12
+ const isLeap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
13
+ const monthDays = [31, isLeap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
14
+ return month >= 1 && month <= 12 && day >= 1 && day <= monthDays[month - 1] && Number(hourText) <= 23 && Number(minuteText) <= 59 && Number(secondText) <= 59 && (zone === "Z" || Number(zoneHourText) <= 24 && Number(zoneMinuteText) <= 60);
15
+ }
16
+ function canonicalGoTimeJSON(value) {
17
+ const match = goTimeJSONPattern.exec(value);
18
+ const [, year, month, day, hour, minute, second, fraction, zone, sign, zoneHour, zoneMinute] = match;
19
+ const clock = year + "-" + month + "-" + day + "T" + hour.padStart(2, "0") + ":" + minute + ":" + second;
20
+ const digits = (fraction ?? "").slice(0, 9).replace(/0+$/, "");
21
+ const offsetMinutes = zone === "Z" ? 0 : (Number(zoneHour) * 60 + Number(zoneMinute)) * (sign === "+" ? 1 : -1);
22
+ if (Math.abs(offsetMinutes) >= 1440) return value;
23
+ const offset = offsetMinutes === 0 ? "Z" : (offsetMinutes > 0 ? "+" : "-") + String(Math.floor(Math.abs(offsetMinutes) / 60)).padStart(2, "0") + ":" + String(Math.abs(offsetMinutes) % 60).padStart(2, "0");
24
+ return clock + (digits ? "." + digits : "") + offset;
25
+ }
26
+ var GoTimeJSONSchema = z.string().refine(isGoTimeJSON, "invalid Go time.Time JSON timestamp").transform(canonicalGoTimeJSON);
3
27
  var ConfigSchema = z.object({
4
28
  "endpoint": z.string().optional(),
5
29
  "maxResponseBytes": z.number().int().optional()
6
30
  });
31
+ function decodeCredentials(value) {
32
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("credential fields are invalid");
33
+ const fields = value;
34
+ const allowed = /* @__PURE__ */ new Set(["access_token"]);
35
+ if (Object.keys(fields).some((key) => !allowed.has(key))) throw new TypeError("stored credential does not match the connector credential fields");
36
+ if (fields["access_token"] != null && !(typeof fields["access_token"] === "string")) throw new TypeError("credential access_token has an invalid type");
37
+ const credentials = {};
38
+ if (!fields["access_token"]) throw new TypeError("credential access_token is required");
39
+ credentials.accessToken = new SecretString(fields["access_token"] ?? "");
40
+ return credentials;
41
+ }
7
42
  var ListTasksInputSchema = z.strictObject({
8
43
  "projectId": z.string().optional(),
9
44
  "sectionId": z.string().optional(),
10
45
  "isIncompleteOnly": z.boolean().optional(),
11
- "completedSince": z.iso.datetime({ offset: true }).nullable().optional(),
12
- "modifiedSince": z.iso.datetime({ offset: true }).nullable().optional(),
46
+ "completedSince": GoTimeJSONSchema.nullable().optional(),
47
+ "modifiedSince": GoTimeJSONSchema.nullable().optional(),
13
48
  "pageSize": z.number().int().optional(),
14
49
  "offset": z.string().optional()
15
50
  });
@@ -56,10 +91,10 @@ var TaskSchema = z.strictObject({
56
91
  "name": z.string(),
57
92
  "resourceSubtype": z.string().optional(),
58
93
  "isCompleted": z.boolean(),
59
- "completedAt": z.iso.datetime({ offset: true }).nullable().optional(),
94
+ "completedAt": GoTimeJSONSchema.nullable().optional(),
60
95
  "assignee": UserReferenceSchema.optional(),
61
96
  "dueOn": z.string().optional(),
62
- "dueAt": z.iso.datetime({ offset: true }).nullable().optional(),
97
+ "dueAt": GoTimeJSONSchema.nullable().optional(),
63
98
  "startOn": z.string().optional(),
64
99
  "memberships": z.array(TaskMembershipSchema).optional(),
65
100
  "parent": TaskReferenceSchema.optional(),
@@ -68,8 +103,8 @@ var TaskSchema = z.strictObject({
68
103
  "isNotesTruncated": z.boolean().optional(),
69
104
  "customFields": z.array(CustomFieldValueSchema).optional(),
70
105
  "permalinkUrl": z.string().optional(),
71
- "createdAt": z.iso.datetime({ offset: true }),
72
- "modifiedAt": z.iso.datetime({ offset: true })
106
+ "createdAt": GoTimeJSONSchema,
107
+ "modifiedAt": GoTimeJSONSchema
73
108
  });
74
109
  var ListTasksOutputSchema = z.strictObject({
75
110
  "tasks": z.array(TaskSchema).nullable(),
@@ -102,7 +137,7 @@ var CreateTaskOutputSchema = z.strictObject({
102
137
  "sectionId": z.string().optional(),
103
138
  "workspaceId": z.string().optional(),
104
139
  "permalinkUrl": z.string().optional(),
105
- "createdAt": z.iso.datetime({ offset: true }).nullable().optional()
140
+ "createdAt": GoTimeJSONSchema.nullable().optional()
106
141
  });
107
142
  var UpdateTaskInputSchema = z.strictObject({
108
143
  "taskId": z.string(),
@@ -125,7 +160,7 @@ var AddCommentOutputSchema = z.strictObject({
125
160
  "taskId": z.string(),
126
161
  "commentId": z.string().optional(),
127
162
  "author": UserReferenceSchema.optional(),
128
- "createdAt": z.iso.datetime({ offset: true }).nullable().optional()
163
+ "createdAt": GoTimeJSONSchema.nullable().optional()
129
164
  });
130
165
 
131
166
  // src/generated/definitions.ts
@@ -274,6 +309,7 @@ function newConnectionWithOperations(operations, reference) {
274
309
 
275
310
  export {
276
311
  ConfigSchema,
312
+ decodeCredentials,
277
313
  ListTasksInputSchema,
278
314
  UserReferenceSchema,
279
315
  ProjectReferenceSchema,
@@ -18,6 +18,8 @@ interface Credentials {
18
18
  /** Secret Asana personal access token created at https://app.asana.com/0/my-apps under Personal access tokens > Create new token; Asana treats the value as opaque, so paste it exactly as shown once. Dex Web stores it as a secret and sends it only to Asana as a bearer token, and blank means no Asana call can authenticate. */
19
19
  accessToken: SecretString;
20
20
  }
21
+ /** Decode private credential fields for the connector. */
22
+ declare function decodeCredentials(value: unknown): Credentials;
21
23
  /** Host-owned source of private connector credentials. */
22
24
  type CredentialSource = CredentialProvider<Credentials>;
23
25
  /** ListTasksInput selects one page of tasks. Set exactly one of ProjectID and SectionID, and at most one
@@ -266,8 +268,8 @@ declare const ListTasksInputSchema: z.ZodObject<{
266
268
  projectId: z.ZodOptional<z.ZodString>;
267
269
  sectionId: z.ZodOptional<z.ZodString>;
268
270
  isIncompleteOnly: z.ZodOptional<z.ZodBoolean>;
269
- completedSince: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
270
- modifiedSince: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
271
+ completedSince: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
272
+ modifiedSince: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
271
273
  pageSize: z.ZodOptional<z.ZodNumber>;
272
274
  offset: z.ZodOptional<z.ZodString>;
273
275
  }, z.core.$strict>;
@@ -335,13 +337,13 @@ declare const TaskSchema: z.ZodObject<{
335
337
  name: z.ZodString;
336
338
  resourceSubtype: z.ZodOptional<z.ZodString>;
337
339
  isCompleted: z.ZodBoolean;
338
- completedAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
340
+ completedAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
339
341
  assignee: z.ZodOptional<z.ZodObject<{
340
342
  id: z.ZodString;
341
343
  name: z.ZodOptional<z.ZodString>;
342
344
  }, z.core.$strict>>;
343
345
  dueOn: z.ZodOptional<z.ZodString>;
344
- dueAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
346
+ dueAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
345
347
  startOn: z.ZodOptional<z.ZodString>;
346
348
  memberships: z.ZodOptional<z.ZodArray<z.ZodObject<{
347
349
  project: z.ZodObject<{
@@ -380,8 +382,8 @@ declare const TaskSchema: z.ZodObject<{
380
382
  }, z.core.$strict>>>;
381
383
  }, z.core.$strict>>>;
382
384
  permalinkUrl: z.ZodOptional<z.ZodString>;
383
- createdAt: z.ZodISODateTime;
384
- modifiedAt: z.ZodISODateTime;
385
+ createdAt: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
386
+ modifiedAt: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
385
387
  }, z.core.$strict>;
386
388
  /** Runtime validator for ListTasksOutput. */
387
389
  declare const ListTasksOutputSchema: z.ZodObject<{
@@ -390,13 +392,13 @@ declare const ListTasksOutputSchema: z.ZodObject<{
390
392
  name: z.ZodString;
391
393
  resourceSubtype: z.ZodOptional<z.ZodString>;
392
394
  isCompleted: z.ZodBoolean;
393
- completedAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
395
+ completedAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
394
396
  assignee: z.ZodOptional<z.ZodObject<{
395
397
  id: z.ZodString;
396
398
  name: z.ZodOptional<z.ZodString>;
397
399
  }, z.core.$strict>>;
398
400
  dueOn: z.ZodOptional<z.ZodString>;
399
- dueAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
401
+ dueAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
400
402
  startOn: z.ZodOptional<z.ZodString>;
401
403
  memberships: z.ZodOptional<z.ZodArray<z.ZodObject<{
402
404
  project: z.ZodObject<{
@@ -435,8 +437,8 @@ declare const ListTasksOutputSchema: z.ZodObject<{
435
437
  }, z.core.$strict>>>;
436
438
  }, z.core.$strict>>>;
437
439
  permalinkUrl: z.ZodOptional<z.ZodString>;
438
- createdAt: z.ZodISODateTime;
439
- modifiedAt: z.ZodISODateTime;
440
+ createdAt: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
441
+ modifiedAt: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
440
442
  }, z.core.$strict>>>;
441
443
  nextOffset: z.ZodOptional<z.ZodString>;
442
444
  }, z.core.$strict>;
@@ -477,7 +479,7 @@ declare const CreateTaskOutputSchema: z.ZodObject<{
477
479
  sectionId: z.ZodOptional<z.ZodString>;
478
480
  workspaceId: z.ZodOptional<z.ZodString>;
479
481
  permalinkUrl: z.ZodOptional<z.ZodString>;
480
- createdAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
482
+ createdAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
481
483
  }, z.core.$strict>;
482
484
  /** Runtime validator for UpdateTaskInput. */
483
485
  declare const UpdateTaskInputSchema: z.ZodObject<{
@@ -502,13 +504,13 @@ declare const UpdateTaskOutputSchema: z.ZodObject<{
502
504
  name: z.ZodString;
503
505
  resourceSubtype: z.ZodOptional<z.ZodString>;
504
506
  isCompleted: z.ZodBoolean;
505
- completedAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
507
+ completedAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
506
508
  assignee: z.ZodOptional<z.ZodObject<{
507
509
  id: z.ZodString;
508
510
  name: z.ZodOptional<z.ZodString>;
509
511
  }, z.core.$strict>>;
510
512
  dueOn: z.ZodOptional<z.ZodString>;
511
- dueAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
513
+ dueAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
512
514
  startOn: z.ZodOptional<z.ZodString>;
513
515
  memberships: z.ZodOptional<z.ZodArray<z.ZodObject<{
514
516
  project: z.ZodObject<{
@@ -547,8 +549,8 @@ declare const UpdateTaskOutputSchema: z.ZodObject<{
547
549
  }, z.core.$strict>>>;
548
550
  }, z.core.$strict>>>;
549
551
  permalinkUrl: z.ZodOptional<z.ZodString>;
550
- createdAt: z.ZodISODateTime;
551
- modifiedAt: z.ZodISODateTime;
552
+ createdAt: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
553
+ modifiedAt: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
552
554
  }, z.core.$strict>>;
553
555
  isMovedToSection: z.ZodOptional<z.ZodBoolean>;
554
556
  }, z.core.$strict>;
@@ -565,7 +567,7 @@ declare const AddCommentOutputSchema: z.ZodObject<{
565
567
  id: z.ZodString;
566
568
  name: z.ZodOptional<z.ZodString>;
567
569
  }, z.core.$strict>>;
568
- createdAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
570
+ createdAt: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
569
571
  }, z.core.$strict>;
570
572
 
571
573
  /** Typed operations supplied by a client or mock. */
@@ -595,4 +597,4 @@ declare function newConnection(client: Operations, reference: ConnectionRef): Co
595
597
  /** Bind scripted operations to a named connection. */
596
598
  declare function newConnectionWithOperations(operations: Operations, reference: ConnectionRef): Connection;
597
599
 
598
- export { type AddCommentInput as A, TaskReferenceSchema as B, Connection as C, TaskSchema as D, type EnumOptionReference as E, UpdateTaskInputSchema as F, type GetTaskInput as G, UpdateTaskOutputSchema as H, type UserReference as I, UserReferenceSchema as J, WorkspaceReferenceSchema as K, type ListTasksInput as L, newConnection as M, newConnectionWithOperations as N, type Operations as O, type ProjectReference as P, type SectionReference as S, type Task as T, type UpdateTaskInput as U, type WorkspaceReference as W, type AddCommentOutput as a, type CreateTaskInput as b, type CreateTaskOutput as c, type ListTasksOutput as d, type UpdateTaskOutput as e, type Config as f, type Credentials as g, AddCommentInputSchema as h, AddCommentOutputSchema as i, ConfigSchema as j, CreateTaskInputSchema as k, CreateTaskOutputSchema as l, type CredentialSource as m, type CustomFieldValue as n, type CustomFieldValueInput as o, CustomFieldValueInputSchema as p, CustomFieldValueSchema as q, EnumOptionReferenceSchema as r, GetTaskInputSchema as s, ListTasksInputSchema as t, ListTasksOutputSchema as u, ProjectReferenceSchema as v, SectionReferenceSchema as w, type TaskMembership as x, TaskMembershipSchema as y, type TaskReference as z };
600
+ export { type AddCommentInput as A, TaskReferenceSchema as B, Connection as C, TaskSchema as D, type EnumOptionReference as E, UpdateTaskInputSchema as F, type GetTaskInput as G, UpdateTaskOutputSchema as H, type UserReference as I, UserReferenceSchema as J, WorkspaceReferenceSchema as K, type ListTasksInput as L, decodeCredentials as M, newConnection as N, type Operations as O, type ProjectReference as P, newConnectionWithOperations as Q, type SectionReference as S, type Task as T, type UpdateTaskInput as U, type WorkspaceReference as W, type AddCommentOutput as a, type CreateTaskInput as b, type CreateTaskOutput as c, type ListTasksOutput as d, type UpdateTaskOutput as e, type Config as f, type Credentials as g, AddCommentInputSchema as h, AddCommentOutputSchema as i, ConfigSchema as j, CreateTaskInputSchema as k, CreateTaskOutputSchema as l, type CredentialSource as m, type CustomFieldValue as n, type CustomFieldValueInput as o, CustomFieldValueInputSchema as p, CustomFieldValueSchema as q, EnumOptionReferenceSchema as r, GetTaskInputSchema as s, ListTasksInputSchema as t, ListTasksOutputSchema as u, ProjectReferenceSchema as v, SectionReferenceSchema as w, type TaskMembership as x, TaskMembershipSchema as y, type TaskReference as z };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AddCommentInput, a as AddCommentOutput, C as Connection, b as CreateTaskInput, c as CreateTaskOutput, G as GetTaskInput, T as Task, L as ListTasksInput, d as ListTasksOutput, U as UpdateTaskInput, e as UpdateTaskOutput, f as Config, g as Credentials } from './connection-BBAfdtyU.js';
2
- export { h as AddCommentInputSchema, i as AddCommentOutputSchema, j as ConfigSchema, k as CreateTaskInputSchema, l as CreateTaskOutputSchema, m as CredentialSource, n as CustomFieldValue, o as CustomFieldValueInput, p as CustomFieldValueInputSchema, q as CustomFieldValueSchema, E as EnumOptionReference, r as EnumOptionReferenceSchema, s as GetTaskInputSchema, t as ListTasksInputSchema, u as ListTasksOutputSchema, O as Operations, P as ProjectReference, v as ProjectReferenceSchema, S as SectionReference, w as SectionReferenceSchema, x as TaskMembership, y as TaskMembershipSchema, z as TaskReference, B as TaskReferenceSchema, D as TaskSchema, F as UpdateTaskInputSchema, H as UpdateTaskOutputSchema, I as UserReference, J as UserReferenceSchema, W as WorkspaceReference, K as WorkspaceReferenceSchema, M as newConnection, N as newConnectionWithOperations } from './connection-BBAfdtyU.js';
1
+ import { A as AddCommentInput, a as AddCommentOutput, C as Connection, b as CreateTaskInput, c as CreateTaskOutput, G as GetTaskInput, T as Task, L as ListTasksInput, d as ListTasksOutput, U as UpdateTaskInput, e as UpdateTaskOutput, f as Config, g as Credentials } from './connection-Bu8DfK5s.js';
2
+ export { h as AddCommentInputSchema, i as AddCommentOutputSchema, j as ConfigSchema, k as CreateTaskInputSchema, l as CreateTaskOutputSchema, m as CredentialSource, n as CustomFieldValue, o as CustomFieldValueInput, p as CustomFieldValueInputSchema, q as CustomFieldValueSchema, E as EnumOptionReference, r as EnumOptionReferenceSchema, s as GetTaskInputSchema, t as ListTasksInputSchema, u as ListTasksOutputSchema, O as Operations, P as ProjectReference, v as ProjectReferenceSchema, S as SectionReference, w as SectionReferenceSchema, x as TaskMembership, y as TaskMembershipSchema, z as TaskReference, B as TaskReferenceSchema, D as TaskSchema, F as UpdateTaskInputSchema, H as UpdateTaskOutputSchema, I as UserReference, J as UserReferenceSchema, W as WorkspaceReference, K as WorkspaceReferenceSchema, M as decodeCredentials, N as newConnection, Q as newConnectionWithOperations } from './connection-Bu8DfK5s.js';
3
3
  import * as _superdurable_connectors_sdk from '@superdurable/connectors-sdk';
4
4
  import { MutationDefinition, QueryDefinition, MutationStepConfig, Mutation, MutationResult, QueryStepConfig, Query, QueryResult, MutationStep, QueryStep, Call, QueryAttempt, MutationAttempt, CredentialProvider, ReceiptDraft, Failure } from '@superdurable/connectors-sdk';
5
5
  import { StepTarget } from '@superdurable/dex';
package/dist/index.js CHANGED
@@ -61,9 +61,10 @@ import {
61
61
  UpdateTaskOutputSchema,
62
62
  UserReferenceSchema,
63
63
  WorkspaceReferenceSchema,
64
+ decodeCredentials,
64
65
  newConnection,
65
66
  newConnectionWithOperations
66
- } from "./chunk-BX7GRLMD.js";
67
+ } from "./chunk-JITMOBYX.js";
67
68
 
68
69
  // src/generated/steps.ts
69
70
  import { goToBranch, newMutationStep, newQueryStep } from "@superdurable/connectors-sdk";
@@ -296,6 +297,37 @@ var parseTime = (value) => {
296
297
  return Number.isNaN(date.getTime()) ? void 0 : date.toISOString().replace(/\.000Z$/, "Z");
297
298
  };
298
299
  var queryForFields = (fields) => new URLSearchParams({ opt_fields: fields });
300
+ function asanaFence(call, operation) {
301
+ const context = new Proxy(call.context, {
302
+ get(target, property) {
303
+ if (property === "getLastHeartbeatValue") return () => {
304
+ const checkpoint = target.getLastHeartbeatValue();
305
+ if (!checkpoint) return checkpoint;
306
+ if (checkpoint.operation !== operation) throw new TypeError("Asana checkpoint belongs to another operation");
307
+ return { callId: checkpoint.callId, attempt: checkpoint.attempt, state: checkpoint.canResend ? "canResend" : "claimed", ...checkpoint.objectId ? { providerId: checkpoint.objectId } : {} };
308
+ };
309
+ if (property === "recordHeartbeat") return async (value2) => {
310
+ const marker = value2;
311
+ await target.recordHeartbeat({
312
+ callId: marker.callId,
313
+ operation,
314
+ attempt: marker.attempt,
315
+ ...marker.providerId ? { objectId: marker.providerId } : {},
316
+ ...["canResend", "notSent"].includes(marker.state) ? { canResend: true } : {}
317
+ });
318
+ };
319
+ const value = Reflect.get(target, property, target);
320
+ return typeof value === "function" ? value.bind(target) : value;
321
+ }
322
+ });
323
+ return newFence({ ...call, context }, 3e4);
324
+ }
325
+ async function recordAsanaReadback(call, operation, objectId) {
326
+ try {
327
+ await call.context.recordHeartbeat({ callId: call.id, operation, attempt: call.context.attempt, objectId });
328
+ } catch {
329
+ }
330
+ }
299
331
  function readOutcome(client, operation, subject, exchange) {
300
332
  const delay = client.retryAfter(exchange);
301
333
  if ("error" in exchange) {
@@ -425,14 +457,17 @@ var CreateTaskOperation = class {
425
457
  } catch (error) {
426
458
  return newMutationBranch("defect", requested, zeroReceipt(), failure("createTask", "VALIDATION", String(error)));
427
459
  }
428
- const fence = newFence(call, 3e4);
460
+ const fence = asanaFence(call, "createTask");
429
461
  const decision = fence.decide();
430
462
  if (decision.kind === "failClosed") return newMutationUncertain(requested, failure("createTask", "LOCAL_DEFECT", "Asana task dispatch checkpoint is unavailable"), this.client.receipt(call));
431
463
  const taskId = decision.marker?.providerId;
432
464
  if (decision.kind === "readBackRequired" && !taskId) return newMutationUncertain(requested, failure("createTask", "TRANSPORT", "Asana task dispatch checkpoint does not permit another create"), this.client.receipt(call));
433
465
  const token = await this.client.token(call);
434
466
  if (!token) return taskId ? newMutationRetry(failure("createTask", "AUTHENTICATION", "Asana connection credentials are unavailable")) : newMutationBranch("defect", requested, zeroReceipt(), failure("createTask", "AUTHENTICATION", "Asana connection credentials are unavailable"));
435
- if (taskId) return this.readBack(call, token, requested, taskId);
467
+ if (taskId) {
468
+ await recordAsanaReadback(call, "createTask", taskId);
469
+ return this.readBack(call, token, requested, taskId);
470
+ }
436
471
  let exchange;
437
472
  try {
438
473
  exchange = await fence.dispatch((signal) => this.client.exchange(call, token, "POST", "/tasks", queryForFields(createdTaskFields), { data: fields }, signal));
@@ -566,14 +601,17 @@ var AddCommentOperation = class {
566
601
  } catch (error) {
567
602
  return newMutationBranch("defect", requested, zeroReceipt(), failure("addComment", "VALIDATION", String(error)));
568
603
  }
569
- const fence = newFence(call, 3e4);
604
+ const fence = asanaFence(call, "addComment");
570
605
  const decision = fence.decide();
571
606
  if (decision.kind === "failClosed") return newMutationUncertain(requested, failure("addComment", "LOCAL_DEFECT", "Asana comment dispatch checkpoint is unavailable"), this.client.receipt(call));
572
607
  const storyId = decision.marker?.providerId;
573
608
  if (decision.kind === "readBackRequired" && !storyId) return newMutationUncertain(requested, failure("addComment", "TRANSPORT", "Asana comment dispatch checkpoint does not permit another comment"), this.client.receipt(call));
574
609
  const token = await this.client.token(call);
575
610
  if (!token) return storyId ? newMutationRetry(failure("addComment", "AUTHENTICATION", "Asana connection credentials are unavailable")) : newMutationBranch("defect", requested, zeroReceipt(), failure("addComment", "AUTHENTICATION", "Asana connection credentials are unavailable"));
576
- if (storyId) return this.readBack(call, token, requested, storyId);
611
+ if (storyId) {
612
+ await recordAsanaReadback(call, "addComment", storyId);
613
+ return this.readBack(call, token, requested, storyId);
614
+ }
577
615
  let exchange;
578
616
  try {
579
617
  exchange = await fence.dispatch((signal) => this.client.exchange(call, token, "POST", `/tasks/${taskId}/stories`, queryForFields(createdStoryFields), { data: { text: input.text } }, signal));
@@ -865,6 +903,7 @@ export {
865
903
  UserReferenceSchema,
866
904
  WorkspaceReferenceSchema,
867
905
  dataObject,
906
+ decodeCredentials,
868
907
  failure,
869
908
  newAddCommentStep,
870
909
  newConnection,
package/dist/mock.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { MockQuery, MockMutation, Case } from '@superdurable/connectors-sdk/connectormock';
2
2
  import { Failure } from '@superdurable/connectors-sdk';
3
- import { O as Operations, C as Connection, L as ListTasksInput, d as ListTasksOutput, G as GetTaskInput, T as Task, b as CreateTaskInput, c as CreateTaskOutput, U as UpdateTaskInput, e as UpdateTaskOutput, A as AddCommentInput, a as AddCommentOutput, n as CustomFieldValue, o as CustomFieldValueInput, E as EnumOptionReference, P as ProjectReference, S as SectionReference, x as TaskMembership, z as TaskReference, I as UserReference, W as WorkspaceReference } from './connection-BBAfdtyU.js';
3
+ import { O as Operations, C as Connection, L as ListTasksInput, d as ListTasksOutput, G as GetTaskInput, T as Task, b as CreateTaskInput, c as CreateTaskOutput, U as UpdateTaskInput, e as UpdateTaskOutput, A as AddCommentInput, a as AddCommentOutput, n as CustomFieldValue, o as CustomFieldValueInput, E as EnumOptionReference, P as ProjectReference, S as SectionReference, x as TaskMembership, z as TaskReference, I as UserReference, W as WorkspaceReference } from './connection-Bu8DfK5s.js';
4
4
  import 'zod';
5
5
 
6
6
  /** Go zero value for ListTasksInput in scripted cases. */
package/dist/mock.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  UserReferenceSchema,
27
27
  WorkspaceReferenceSchema,
28
28
  newConnectionWithOperations
29
- } from "./chunk-BX7GRLMD.js";
29
+ } from "./chunk-JITMOBYX.js";
30
30
 
31
31
  // src/generated/mock.ts
32
32
  import { branchCase, retryCase, uncertainCase, newMutation, newQuery } from "@superdurable/connectors-sdk/connectormock";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdurable/connector-asana",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Asana task and comment operations for Dex",
5
5
  "repository": {
6
6
  "type": "git",