@37signals/basecamp 0.7.2 → 0.8.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.
Files changed (96) hide show
  1. package/README.md +80 -1
  2. package/dist/client.d.ts +4 -4
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +30 -23
  5. package/dist/client.js.map +1 -1
  6. package/dist/download.d.ts.map +1 -1
  7. package/dist/errors.d.ts +10 -0
  8. package/dist/errors.d.ts.map +1 -1
  9. package/dist/errors.js +7 -1
  10. package/dist/errors.js.map +1 -1
  11. package/dist/generated/metadata.d.ts +32 -0
  12. package/dist/generated/metadata.d.ts.map +1 -0
  13. package/dist/generated/metadata.js +2670 -0
  14. package/dist/generated/metadata.js.map +1 -0
  15. package/dist/generated/{metadata.json → metadata.ts} +98 -45
  16. package/dist/generated/openapi-stripped.json +713 -440
  17. package/dist/generated/path-mapping.d.ts.map +1 -1
  18. package/dist/generated/path-mapping.js +6 -5
  19. package/dist/generated/path-mapping.js.map +1 -1
  20. package/dist/generated/path-mapping.ts +6 -5
  21. package/dist/generated/schema.d.ts +510 -297
  22. package/dist/generated/services/campfires.d.ts +22 -1
  23. package/dist/generated/services/campfires.d.ts.map +1 -1
  24. package/dist/generated/services/campfires.js +33 -1
  25. package/dist/generated/services/campfires.js.map +1 -1
  26. package/dist/generated/services/campfires.ts +46 -1
  27. package/dist/generated/services/card-columns.d.ts +31 -28
  28. package/dist/generated/services/card-columns.d.ts.map +1 -1
  29. package/dist/generated/services/card-columns.js +54 -51
  30. package/dist/generated/services/card-columns.js.map +1 -1
  31. package/dist/generated/services/card-columns.ts +62 -59
  32. package/dist/generated/services/index.d.ts +2 -2
  33. package/dist/generated/services/index.d.ts.map +1 -1
  34. package/dist/generated/services/index.js +2 -2
  35. package/dist/generated/services/index.js.map +1 -1
  36. package/dist/generated/services/index.ts +2 -2
  37. package/dist/generated/services/reports.d.ts +1 -1
  38. package/dist/generated/services/reports.js +1 -1
  39. package/dist/generated/services/reports.ts +1 -1
  40. package/dist/generated/services/todos.d.ts +8 -8
  41. package/dist/generated/services/todos.d.ts.map +1 -1
  42. package/dist/generated/services/todos.js +9 -6
  43. package/dist/generated/services/todos.js.map +1 -1
  44. package/dist/generated/services/todos.ts +12 -9
  45. package/dist/generated/services/tools.d.ts +11 -10
  46. package/dist/generated/services/tools.d.ts.map +1 -1
  47. package/dist/generated/services/tools.js +16 -8
  48. package/dist/generated/services/tools.js.map +1 -1
  49. package/dist/generated/services/tools.ts +21 -13
  50. package/dist/index.d.ts +6 -4
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +3 -3
  53. package/dist/index.js.map +1 -1
  54. package/dist/oauth/discovery.d.ts +105 -23
  55. package/dist/oauth/discovery.d.ts.map +1 -1
  56. package/dist/oauth/discovery.js +453 -61
  57. package/dist/oauth/discovery.js.map +1 -1
  58. package/dist/oauth/index.d.ts +2 -2
  59. package/dist/oauth/index.d.ts.map +1 -1
  60. package/dist/oauth/index.js +1 -1
  61. package/dist/oauth/index.js.map +1 -1
  62. package/dist/oauth/interactive-login.d.ts +20 -2
  63. package/dist/oauth/interactive-login.d.ts.map +1 -1
  64. package/dist/oauth/interactive-login.js +58 -4
  65. package/dist/oauth/interactive-login.js.map +1 -1
  66. package/dist/oauth/types.d.ts +54 -2
  67. package/dist/oauth/types.d.ts.map +1 -1
  68. package/dist/security.d.ts +22 -0
  69. package/dist/security.d.ts.map +1 -1
  70. package/dist/security.js +56 -1
  71. package/dist/security.js.map +1 -1
  72. package/dist/services/authorization.d.ts.map +1 -1
  73. package/dist/services/authorization.js +3 -0
  74. package/dist/services/authorization.js.map +1 -1
  75. package/dist/services/base.d.ts.map +1 -1
  76. package/dist/services/base.js +1 -3
  77. package/dist/services/base.js.map +1 -1
  78. package/dist/services/todos-extensions.d.ts +118 -0
  79. package/dist/services/todos-extensions.d.ts.map +1 -0
  80. package/dist/services/todos-extensions.js +113 -0
  81. package/dist/services/todos-extensions.js.map +1 -0
  82. package/dist/services/uploads-extensions.d.ts +33 -0
  83. package/dist/services/uploads-extensions.d.ts.map +1 -0
  84. package/dist/services/uploads-extensions.js +48 -0
  85. package/dist/services/uploads-extensions.js.map +1 -0
  86. package/package.json +7 -4
  87. package/src/generated/{metadata.json → metadata.ts} +98 -45
  88. package/src/generated/openapi-stripped.json +713 -440
  89. package/src/generated/path-mapping.ts +6 -5
  90. package/src/generated/schema.d.ts +510 -297
  91. package/src/generated/services/campfires.ts +46 -1
  92. package/src/generated/services/card-columns.ts +62 -59
  93. package/src/generated/services/index.ts +2 -2
  94. package/src/generated/services/reports.ts +1 -1
  95. package/src/generated/services/todos.ts +12 -9
  96. package/src/generated/services/tools.ts +21 -13
@@ -0,0 +1,113 @@
1
+ import { TodosService as GeneratedTodosService } from "../generated/services/todos.js";
2
+ /**
3
+ * TodosService with merge-safe `update` and read-modify-write `edit` on
4
+ * top of the generated surface (`get`, `replace`, ...).
5
+ *
6
+ * Both compose the public `get` and `replace` methods, so hooks observe
7
+ * the two wire operations (`GetTodo` then `ReplaceTodo`), not a synthetic
8
+ * composite.
9
+ */
10
+ export class TodosService extends GeneratedTodosService {
11
+ /**
12
+ * Sets the given fields on a todo and preserves everything else: GETs
13
+ * the current todo, overlays the explicitly-set request fields, and PUTs
14
+ * the full representation back. An omitted (`undefined`) field is
15
+ * untouched, guaranteed; an explicitly-passed empty array clears.
16
+ *
17
+ * Not atomic: there is no conditional-update signal on this endpoint, so
18
+ * a concurrent write between the GET and PUT is overwritten — last write
19
+ * wins for the whole representation. The window is one round-trip. Use
20
+ * `replace` to overwrite deliberately.
21
+ *
22
+ * @param todoId - The todo ID
23
+ * @param req - Fields to set; omitted fields are preserved
24
+ * @returns The updated Todo
25
+ * @throws {BasecampError} If the request fails
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * // Retitle without touching description, dates, or assignees.
30
+ * await client.todos.update(123, { content: "New title" });
31
+ * ```
32
+ */
33
+ async update(todoId, req) {
34
+ const fields = await this.currentFields(todoId);
35
+ if (req.content !== undefined)
36
+ fields.content = req.content;
37
+ if (req.description !== undefined)
38
+ fields.description = req.description;
39
+ if (req.assigneeIds !== undefined)
40
+ fields.assigneeIds = req.assigneeIds;
41
+ if (req.completionSubscriberIds !== undefined) {
42
+ fields.completionSubscriberIds = req.completionSubscriberIds;
43
+ }
44
+ if (req.dueOn !== undefined)
45
+ fields.dueOn = req.dueOn;
46
+ if (req.startsOn !== undefined)
47
+ fields.startsOn = req.startsOn;
48
+ if (req.notify !== undefined)
49
+ fields.notify = req.notify;
50
+ return this.putFields(todoId, fields);
51
+ }
52
+ /**
53
+ * Applies a read-modify-write callback to a todo: GETs the current todo,
54
+ * hands the callback the full writable representation, and PUTs the
55
+ * whole thing back. Clearing a field means setting it empty (`""` or
56
+ * `[]`) — an untouched field keeps its current value. If the callback
57
+ * throws (or rejects), the edit aborts and nothing is written.
58
+ *
59
+ * Not atomic: there is no conditional-update signal on this endpoint, so
60
+ * a concurrent write between the GET and PUT is overwritten — last write
61
+ * wins for the whole representation. The window is one round-trip. Use
62
+ * `replace` to overwrite deliberately.
63
+ *
64
+ * @param todoId - The todo ID
65
+ * @param fn - Callback that mutates the todo's writable fields in place
66
+ * @returns The updated Todo
67
+ * @throws {BasecampError} If the request fails
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * await client.todos.edit(123, (t) => {
72
+ * t.content = `🚨 ${t.content}`;
73
+ * t.dueOn = ""; // clearing = setting empty on a full object
74
+ * });
75
+ * ```
76
+ */
77
+ async edit(todoId, fn) {
78
+ const fields = await this.currentFields(todoId);
79
+ await fn(fields);
80
+ return this.putFields(todoId, fields);
81
+ }
82
+ /** Fetches the todo and derives its full writable state. */
83
+ async currentFields(todoId) {
84
+ const current = await this.get(todoId);
85
+ return {
86
+ content: current.content ?? "",
87
+ description: current.description ?? "",
88
+ assigneeIds: (current.assignees ?? []).map((p) => p.id),
89
+ completionSubscriberIds: (current.completion_subscribers ?? []).map((p) => p.id),
90
+ dueOn: current.due_on ?? "",
91
+ startsOn: current.starts_on ?? "",
92
+ notify: false,
93
+ };
94
+ }
95
+ /**
96
+ * PUTs the full writable state via `replace`: content, description, and
97
+ * both ID lists are always sent (empties included, so clears survive);
98
+ * dates are sent only when non-empty (the server clears an omitted date,
99
+ * and `""` is a format error); notify is sent only when true.
100
+ */
101
+ putFields(todoId, f) {
102
+ return this.replace(todoId, {
103
+ content: f.content,
104
+ description: f.description,
105
+ assigneeIds: f.assigneeIds,
106
+ completionSubscriberIds: f.completionSubscriberIds,
107
+ dueOn: f.dueOn === "" ? undefined : f.dueOn,
108
+ startsOn: f.startsOn === "" ? undefined : f.startsOn,
109
+ notify: f.notify ? true : undefined,
110
+ });
111
+ }
112
+ }
113
+ //# sourceMappingURL=todos-extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todos-extensions.js","sourceRoot":"","sources":["../../src/services/todos-extensions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { BasecampHooks } from "../hooks.js";
2
+ import type { DownloadResult } from "../download.js";
3
+ import { UploadsService as GeneratedUploadsService } from "../generated/services/uploads.js";
4
+ import type { RawClient } from "./base.js";
5
+ /** Function signature for the client-level `downloadURL` primitive. */
6
+ type DownloadURLFn = (rawURL: string) => Promise<DownloadResult>;
7
+ /**
8
+ * UploadsService with a hand-written `download(uploadId)` convenience.
9
+ *
10
+ * The subclass injects the client-level `downloadURL` function so the
11
+ * convenience method can delegate to it — the authenticated-hop + 302-follow
12
+ * flow stays in one place (`createDownloadURL` in `download.ts`).
13
+ */
14
+ export declare class UploadsService extends GeneratedUploadsService {
15
+ private readonly downloadURLFn?;
16
+ constructor(client: RawClient, hooks?: BasecampHooks, fetchPage?: (url: string) => Promise<Response>, maxPages?: number, authenticatedFetch?: (url: string, init: RequestInit) => Promise<Response>, baseUrl?: string, downloadURLFn?: DownloadURLFn);
17
+ /**
18
+ * Downloads an upload's file content in one call.
19
+ *
20
+ * Fetches the upload metadata to retrieve `download_url`, then delegates to
21
+ * the client-level `downloadURL` primitive (authenticated-hop + 302-follow).
22
+ *
23
+ * @param uploadId - The upload's numeric id.
24
+ * @returns A `DownloadResult` whose `filename` prefers `upload.filename`
25
+ * from metadata, falling back to the URL-derived filename.
26
+ * @throws {BasecampError} `usage` if the upload has no `download_url`,
27
+ * or if the service was constructed without the injected download
28
+ * primitive (obtain the service through `createBasecampClient().uploads`).
29
+ */
30
+ download(uploadId: number): Promise<DownloadResult>;
31
+ }
32
+ export {};
33
+ //# sourceMappingURL=uploads-extensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploads-extensions.d.ts","sourceRoot":"","sources":["../../src/services/uploads-extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAE,cAAc,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,uEAAuE;AACvE,KAAK,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAEjE;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,uBAAuB;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAgB;gBAS7C,MAAM,EAAE,SAAS,EACjB,KAAK,CAAC,EAAE,aAAa,EACrB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,EAC9C,QAAQ,CAAC,EAAE,MAAM,EACjB,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,EAC1E,OAAO,CAAC,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,aAAa;IAM/B;;;;;;;;;;;;OAYG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAc1D"}
@@ -0,0 +1,48 @@
1
+ import { Errors } from "../errors.js";
2
+ import { UploadsService as GeneratedUploadsService } from "../generated/services/uploads.js";
3
+ /**
4
+ * UploadsService with a hand-written `download(uploadId)` convenience.
5
+ *
6
+ * The subclass injects the client-level `downloadURL` function so the
7
+ * convenience method can delegate to it — the authenticated-hop + 302-follow
8
+ * flow stays in one place (`createDownloadURL` in `download.ts`).
9
+ */
10
+ export class UploadsService extends GeneratedUploadsService {
11
+ downloadURLFn;
12
+ // Preserve BaseService's full positional signature (authenticatedFetch, baseUrl),
13
+ // then append downloadURLFn — otherwise existing `new UploadsService(client, hooks,
14
+ // fetchPage, maxPages, authenticatedFetch, baseUrl)` callers would silently miswire
15
+ // authenticatedFetch into the 5th slot. All params optional for direct-construction
16
+ // back-compat; `download()` throws a clear usage error if the primitive wasn't
17
+ // injected (i.e. the service was constructed outside createBasecampClient).
18
+ constructor(client, hooks, fetchPage, maxPages, authenticatedFetch, baseUrl, downloadURLFn) {
19
+ super(client, hooks, fetchPage, maxPages, authenticatedFetch, baseUrl);
20
+ this.downloadURLFn = downloadURLFn;
21
+ }
22
+ /**
23
+ * Downloads an upload's file content in one call.
24
+ *
25
+ * Fetches the upload metadata to retrieve `download_url`, then delegates to
26
+ * the client-level `downloadURL` primitive (authenticated-hop + 302-follow).
27
+ *
28
+ * @param uploadId - The upload's numeric id.
29
+ * @returns A `DownloadResult` whose `filename` prefers `upload.filename`
30
+ * from metadata, falling back to the URL-derived filename.
31
+ * @throws {BasecampError} `usage` if the upload has no `download_url`,
32
+ * or if the service was constructed without the injected download
33
+ * primitive (obtain the service through `createBasecampClient().uploads`).
34
+ */
35
+ async download(uploadId) {
36
+ if (!this.downloadURLFn) {
37
+ throw Errors.usage("uploads.download requires the download primitive — obtain UploadsService via createBasecampClient(...).uploads rather than instantiating it directly");
38
+ }
39
+ const upload = await this.get(uploadId);
40
+ const url = upload.download_url;
41
+ if (!url) {
42
+ throw Errors.usage(`upload ${uploadId} has no download_url`);
43
+ }
44
+ const result = await this.downloadURLFn(url);
45
+ return upload.filename ? { ...result, filename: upload.filename } : result;
46
+ }
47
+ }
48
+ //# sourceMappingURL=uploads-extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploads-extensions.js","sourceRoot":"","sources":["../../src/services/uploads-extensions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAM7F;;;;;;GAMG;AACH,MAAM,OAAO,cAAe,SAAQ,uBAAuB;IACxC,aAAa,CAAiB;IAE/C,kFAAkF;IAClF,oFAAoF;IACpF,oFAAoF;IACpF,oFAAoF;IACpF,+EAA+E;IAC/E,4EAA4E;IAC5E,YACE,MAAiB,EACjB,KAAqB,EACrB,SAA8C,EAC9C,QAAiB,EACjB,kBAA0E,EAC1E,OAAgB,EAChB,aAA6B;QAE7B,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,MAAM,CAAC,KAAK,CAChB,sJAAsJ,CACvJ,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC;QAChC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,QAAQ,sBAAsB,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7E,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@37signals/basecamp",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "TypeScript SDK for the Basecamp API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "src/generated"
21
21
  ],
22
22
  "scripts": {
23
- "generate": "tsx scripts/strip-account-id.ts ../openapi.json src/generated/openapi-stripped.json && openapi-typescript src/generated/openapi-stripped.json -o src/generated/schema.d.ts && tsx scripts/patch-flexible-ids.ts && tsx scripts/extract-metadata.ts src/generated/openapi-stripped.json > src/generated/metadata.json && tsx scripts/generate-path-mapping.ts",
23
+ "generate": "tsx scripts/strip-account-id.ts ../openapi.json src/generated/openapi-stripped.json && openapi-typescript src/generated/openapi-stripped.json -o src/generated/schema.d.ts && tsx scripts/patch-flexible-ids.ts && tsx scripts/extract-metadata.ts src/generated/openapi-stripped.json > src/generated/metadata.ts && tsx scripts/generate-path-mapping.ts",
24
24
  "build": "tsc",
25
25
  "postbuild": "node -e \"fs=require('fs');fs.cpSync('src/generated','dist/generated',{recursive:true});\"",
26
26
  "prepublishOnly": "npm run build",
@@ -53,7 +53,7 @@
53
53
  "openapi-fetch": "^0.17.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@types/node": "^25.3.2",
56
+ "@types/node": "^26.1.0",
57
57
  "@vitest/coverage-v8": "^4.0.18",
58
58
  "msw": "^2.12.10",
59
59
  "openapi-typescript": "^7.13.0",
@@ -66,6 +66,9 @@
66
66
  "typescript": ">=5.0.0"
67
67
  },
68
68
  "overrides": {
69
- "minimatch": ">=10.2.1"
69
+ "minimatch": ">=10.2.1",
70
+ "brace-expansion": ">=5.0.7",
71
+ "fast-uri": ">=3.1.3",
72
+ "js-yaml": "^4.3.0"
70
73
  }
71
74
  }
@@ -1,7 +1,43 @@
1
- {
1
+ // Generated from OpenAPI x-basecamp-* extensions. Do not edit by hand.
2
+
3
+ export interface RetryConfig {
4
+ maxAttempts: number;
5
+ baseDelayMs: number;
6
+ backoff: "exponential" | "linear" | "constant";
7
+ retryOn: number[];
8
+ }
9
+
10
+ export interface PaginationConfig {
11
+ style: "link" | "cursor" | "page";
12
+ pageParam?: string;
13
+ totalCountHeader?: string;
14
+ maxPageSize?: number;
15
+ key?: string;
16
+ }
17
+
18
+ export interface IdempotentConfig {
19
+ keySupported?: boolean;
20
+ keyHeader?: string;
21
+ natural?: boolean;
22
+ }
23
+
24
+ export interface OperationMetadata {
25
+ retry?: RetryConfig;
26
+ pagination?: PaginationConfig;
27
+ idempotent?: IdempotentConfig;
28
+ }
29
+
30
+ export interface MetadataOutput {
31
+ $schema: string;
32
+ version: string;
33
+ generated: string;
34
+ operations: Record<string, OperationMetadata>;
35
+ }
36
+
37
+ const metadata: MetadataOutput = {
2
38
  "$schema": "https://basecamp.com/schemas/sdk-metadata.json",
3
39
  "version": "1.0.0",
4
- "generated": "2026-03-26T04:17:19.408Z",
40
+ "generated": "2026-07-22T08:32:59.805Z",
5
41
  "operations": {
6
42
  "GetAccount": {
7
43
  "retry": {
@@ -92,7 +128,7 @@
92
128
  "natural": true
93
129
  }
94
130
  },
95
- "ListWebhooks": {
131
+ "SetCardColumnColor": {
96
132
  "retry": {
97
133
  "maxAttempts": 3,
98
134
  "baseDelayMs": 1000,
@@ -102,13 +138,11 @@
102
138
  503
103
139
  ]
104
140
  },
105
- "pagination": {
106
- "style": "link",
107
- "totalCountHeader": "X-Total-Count",
108
- "maxPageSize": 50
141
+ "idempotent": {
142
+ "natural": true
109
143
  }
110
144
  },
111
- "CreateWebhook": {
145
+ "EnableCardColumnOnHold": {
112
146
  "retry": {
113
147
  "maxAttempts": 2,
114
148
  "baseDelayMs": 1000,
@@ -119,7 +153,7 @@
119
153
  ]
120
154
  }
121
155
  },
122
- "GetCard": {
156
+ "DisableCardColumnOnHold": {
123
157
  "retry": {
124
158
  "maxAttempts": 3,
125
159
  "baseDelayMs": 1000,
@@ -128,34 +162,39 @@
128
162
  429,
129
163
  503
130
164
  ]
165
+ },
166
+ "idempotent": {
167
+ "natural": true
131
168
  }
132
169
  },
133
- "UpdateCard": {
170
+ "CreateTool": {
134
171
  "retry": {
135
- "maxAttempts": 3,
172
+ "maxAttempts": 2,
136
173
  "baseDelayMs": 1000,
137
174
  "backoff": "exponential",
138
175
  "retryOn": [
139
176
  429,
140
177
  503
141
178
  ]
142
- },
143
- "idempotent": {
144
- "natural": true
145
179
  }
146
180
  },
147
- "MoveCard": {
181
+ "ListWebhooks": {
148
182
  "retry": {
149
- "maxAttempts": 2,
183
+ "maxAttempts": 3,
150
184
  "baseDelayMs": 1000,
151
185
  "backoff": "exponential",
152
186
  "retryOn": [
153
187
  429,
154
188
  503
155
189
  ]
190
+ },
191
+ "pagination": {
192
+ "style": "link",
193
+ "totalCountHeader": "X-Total-Count",
194
+ "maxPageSize": 50
156
195
  }
157
196
  },
158
- "RepositionCardStep": {
197
+ "CreateWebhook": {
159
198
  "retry": {
160
199
  "maxAttempts": 2,
161
200
  "baseDelayMs": 1000,
@@ -166,9 +205,9 @@
166
205
  ]
167
206
  }
168
207
  },
169
- "CreateCardStep": {
208
+ "GetCard": {
170
209
  "retry": {
171
- "maxAttempts": 2,
210
+ "maxAttempts": 3,
172
211
  "baseDelayMs": 1000,
173
212
  "backoff": "exponential",
174
213
  "retryOn": [
@@ -177,7 +216,7 @@
177
216
  ]
178
217
  }
179
218
  },
180
- "GetCardColumn": {
219
+ "UpdateCard": {
181
220
  "retry": {
182
221
  "maxAttempts": 3,
183
222
  "baseDelayMs": 1000,
@@ -186,37 +225,34 @@
186
225
  429,
187
226
  503
188
227
  ]
228
+ },
229
+ "idempotent": {
230
+ "natural": true
189
231
  }
190
232
  },
191
- "UpdateCardColumn": {
233
+ "MoveCard": {
192
234
  "retry": {
193
- "maxAttempts": 3,
235
+ "maxAttempts": 2,
194
236
  "baseDelayMs": 1000,
195
237
  "backoff": "exponential",
196
238
  "retryOn": [
197
239
  429,
198
240
  503
199
241
  ]
200
- },
201
- "idempotent": {
202
- "natural": true
203
242
  }
204
243
  },
205
- "SetCardColumnColor": {
244
+ "RepositionCardStep": {
206
245
  "retry": {
207
- "maxAttempts": 3,
246
+ "maxAttempts": 2,
208
247
  "baseDelayMs": 1000,
209
248
  "backoff": "exponential",
210
249
  "retryOn": [
211
250
  429,
212
251
  503
213
252
  ]
214
- },
215
- "idempotent": {
216
- "natural": true
217
253
  }
218
254
  },
219
- "EnableCardColumnOnHold": {
255
+ "CreateCardStep": {
220
256
  "retry": {
221
257
  "maxAttempts": 2,
222
258
  "baseDelayMs": 1000,
@@ -227,7 +263,18 @@
227
263
  ]
228
264
  }
229
265
  },
230
- "DisableCardColumnOnHold": {
266
+ "GetCardColumn": {
267
+ "retry": {
268
+ "maxAttempts": 3,
269
+ "baseDelayMs": 1000,
270
+ "backoff": "exponential",
271
+ "retryOn": [
272
+ 429,
273
+ 503
274
+ ]
275
+ }
276
+ },
277
+ "UpdateCardColumn": {
231
278
  "retry": {
232
279
  "maxAttempts": 3,
233
280
  "baseDelayMs": 1000,
@@ -565,6 +612,20 @@
565
612
  ]
566
613
  }
567
614
  },
615
+ "UpdateCampfireLine": {
616
+ "retry": {
617
+ "maxAttempts": 3,
618
+ "baseDelayMs": 1000,
619
+ "backoff": "exponential",
620
+ "retryOn": [
621
+ 429,
622
+ 503
623
+ ]
624
+ },
625
+ "idempotent": {
626
+ "natural": true
627
+ }
628
+ },
568
629
  "DeleteCampfireLine": {
569
630
  "retry": {
570
631
  "maxAttempts": 3,
@@ -728,17 +789,6 @@
728
789
  "natural": true
729
790
  }
730
791
  },
731
- "CloneTool": {
732
- "retry": {
733
- "maxAttempts": 2,
734
- "baseDelayMs": 1000,
735
- "backoff": "exponential",
736
- "retryOn": [
737
- 429,
738
- 503
739
- ]
740
- }
741
- },
742
792
  "GetTool": {
743
793
  "retry": {
744
794
  "maxAttempts": 3,
@@ -2330,7 +2380,7 @@
2330
2380
  ]
2331
2381
  }
2332
2382
  },
2333
- "UpdateTodo": {
2383
+ "ReplaceTodo": {
2334
2384
  "retry": {
2335
2385
  "maxAttempts": 3,
2336
2386
  "baseDelayMs": 1000,
@@ -2650,4 +2700,7 @@
2650
2700
  }
2651
2701
  }
2652
2702
  }
2653
- }
2703
+ };
2704
+
2705
+ export default metadata;
2706
+