@37signals/basecamp 0.11.0 → 0.13.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 +112 -16
- package/dist/.build-complete +0 -0
- package/dist/client.d.ts +65 -11
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +235 -215
- package/dist/client.js.map +1 -1
- package/dist/download.d.ts +7 -0
- package/dist/download.d.ts.map +1 -1
- package/dist/download.js +82 -22
- package/dist/download.js.map +1 -1
- package/dist/errors.d.ts +19 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +128 -15
- package/dist/errors.js.map +1 -1
- package/dist/generated/metadata.d.ts.map +1 -1
- package/dist/generated/metadata.js +443 -133
- package/dist/generated/metadata.js.map +1 -1
- package/dist/generated/metadata.ts +443 -133
- package/dist/generated/openapi-stripped.json +8999 -4907
- package/dist/generated/path-mapping.d.ts.map +1 -1
- package/dist/generated/path-mapping.js +40 -16
- package/dist/generated/path-mapping.js.map +1 -1
- package/dist/generated/path-mapping.ts +40 -16
- package/dist/generated/schema.d.ts +5508 -2346
- package/dist/generated/services/bookmarks.d.ts +76 -0
- package/dist/generated/services/bookmarks.d.ts.map +1 -0
- package/dist/generated/services/bookmarks.js +114 -0
- package/dist/generated/services/bookmarks.js.map +1 -0
- package/dist/generated/services/bookmarks.ts +158 -0
- package/dist/generated/services/boosts.d.ts +10 -0
- package/dist/generated/services/boosts.d.ts.map +1 -1
- package/dist/generated/services/boosts.js +8 -0
- package/dist/generated/services/boosts.js.map +1 -1
- package/dist/generated/services/boosts.ts +12 -0
- package/dist/generated/services/calendars.d.ts +47 -0
- package/dist/generated/services/calendars.d.ts.map +1 -0
- package/dist/generated/services/calendars.js +73 -0
- package/dist/generated/services/calendars.js.map +1 -0
- package/dist/generated/services/calendars.ts +102 -0
- package/dist/generated/services/campfires.d.ts +54 -40
- package/dist/generated/services/campfires.d.ts.map +1 -1
- package/dist/generated/services/campfires.js +82 -65
- package/dist/generated/services/campfires.js.map +1 -1
- package/dist/generated/services/campfires.ts +107 -85
- package/dist/generated/services/cards.d.ts +5 -0
- package/dist/generated/services/cards.d.ts.map +1 -1
- package/dist/generated/services/cards.js +4 -0
- package/dist/generated/services/cards.js.map +1 -1
- package/dist/generated/services/cards.ts +6 -0
- package/dist/generated/services/checkins.d.ts +14 -0
- package/dist/generated/services/checkins.d.ts.map +1 -1
- package/dist/generated/services/checkins.js +14 -1
- package/dist/generated/services/checkins.js.map +1 -1
- package/dist/generated/services/checkins.ts +20 -0
- package/dist/generated/services/client-approvals.d.ts +6 -3
- package/dist/generated/services/client-approvals.d.ts.map +1 -1
- package/dist/generated/services/client-approvals.js +8 -5
- package/dist/generated/services/client-approvals.js.map +1 -1
- package/dist/generated/services/client-approvals.ts +10 -5
- package/dist/generated/services/client-correspondences.d.ts +6 -3
- package/dist/generated/services/client-correspondences.d.ts.map +1 -1
- package/dist/generated/services/client-correspondences.js +8 -5
- package/dist/generated/services/client-correspondences.js.map +1 -1
- package/dist/generated/services/client-correspondences.ts +10 -5
- package/dist/generated/services/client-replies.d.ts +11 -4
- package/dist/generated/services/client-replies.d.ts.map +1 -1
- package/dist/generated/services/client-replies.js +16 -8
- package/dist/generated/services/client-replies.js.map +1 -1
- package/dist/generated/services/client-replies.ts +18 -8
- package/dist/generated/services/cloud-files.d.ts +92 -0
- package/dist/generated/services/cloud-files.d.ts.map +1 -0
- package/dist/generated/services/cloud-files.js +121 -0
- package/dist/generated/services/cloud-files.js.map +1 -0
- package/dist/generated/services/cloud-files.ts +188 -0
- package/dist/generated/services/comments.d.ts +5 -0
- package/dist/generated/services/comments.d.ts.map +1 -1
- package/dist/generated/services/comments.js +4 -0
- package/dist/generated/services/comments.js.map +1 -1
- package/dist/generated/services/comments.ts +6 -0
- package/dist/generated/services/documents.d.ts +12 -7
- package/dist/generated/services/documents.d.ts.map +1 -1
- package/dist/generated/services/documents.js +10 -6
- package/dist/generated/services/documents.js.map +1 -1
- package/dist/generated/services/documents.ts +14 -8
- package/dist/generated/services/drafts.d.ts +38 -0
- package/dist/generated/services/drafts.d.ts.map +1 -0
- package/dist/generated/services/drafts.js +40 -0
- package/dist/generated/services/drafts.js.map +1 -0
- package/dist/generated/services/drafts.ts +67 -0
- package/dist/generated/services/events.d.ts +5 -0
- package/dist/generated/services/events.d.ts.map +1 -1
- package/dist/generated/services/events.js +4 -0
- package/dist/generated/services/events.js.map +1 -1
- package/dist/generated/services/events.ts +6 -0
- package/dist/generated/services/everything.d.ts +83 -16
- package/dist/generated/services/everything.d.ts.map +1 -1
- package/dist/generated/services/everything.js +23 -13
- package/dist/generated/services/everything.js.map +1 -1
- package/dist/generated/services/everything.ts +100 -25
- package/dist/generated/services/folders.d.ts +96 -0
- package/dist/generated/services/folders.d.ts.map +1 -0
- package/dist/generated/services/folders.js +140 -0
- package/dist/generated/services/folders.js.map +1 -0
- package/dist/generated/services/folders.ts +201 -0
- package/dist/generated/services/forwards.d.ts +7 -20
- package/dist/generated/services/forwards.d.ts.map +1 -1
- package/dist/generated/services/forwards.js +6 -35
- package/dist/generated/services/forwards.js.map +1 -1
- package/dist/generated/services/forwards.ts +10 -48
- package/dist/generated/services/gauges.d.ts +7 -0
- package/dist/generated/services/gauges.d.ts.map +1 -1
- package/dist/generated/services/gauges.js +5 -1
- package/dist/generated/services/gauges.js.map +1 -1
- package/dist/generated/services/gauges.ts +9 -1
- package/dist/generated/services/google-documents.d.ts +98 -0
- package/dist/generated/services/google-documents.d.ts.map +1 -0
- package/dist/generated/services/google-documents.js +123 -0
- package/dist/generated/services/google-documents.js.map +1 -0
- package/dist/generated/services/google-documents.ts +196 -0
- package/dist/generated/services/index.d.ts +12 -5
- package/dist/generated/services/index.d.ts.map +1 -1
- package/dist/generated/services/index.js +12 -5
- package/dist/generated/services/index.js.map +1 -1
- package/dist/generated/services/index.ts +12 -5
- package/dist/generated/services/messages.d.ts +2 -0
- package/dist/generated/services/messages.d.ts.map +1 -1
- package/dist/generated/services/messages.js +1 -1
- package/dist/generated/services/messages.js.map +1 -1
- package/dist/generated/services/messages.ts +3 -1
- package/dist/generated/services/my-assignments.d.ts +52 -0
- package/dist/generated/services/my-assignments.d.ts.map +1 -1
- package/dist/generated/services/my-assignments.js +71 -0
- package/dist/generated/services/my-assignments.js.map +1 -1
- package/dist/generated/services/my-assignments.ts +104 -0
- package/dist/generated/services/my-notes.d.ts +45 -0
- package/dist/generated/services/my-notes.d.ts.map +1 -0
- package/dist/generated/services/my-notes.js +62 -0
- package/dist/generated/services/my-notes.js.map +1 -0
- package/dist/generated/services/my-notes.ts +92 -0
- package/dist/generated/services/my-notifications.d.ts +4 -2
- package/dist/generated/services/my-notifications.d.ts.map +1 -1
- package/dist/generated/services/my-notifications.js.map +1 -1
- package/dist/generated/services/my-notifications.ts +4 -2
- package/dist/generated/services/people.d.ts +11 -1
- package/dist/generated/services/people.d.ts.map +1 -1
- package/dist/generated/services/people.js +13 -2
- package/dist/generated/services/people.js.map +1 -1
- package/dist/generated/services/people.ts +15 -1
- package/dist/generated/services/projects.d.ts +26 -0
- package/dist/generated/services/projects.d.ts.map +1 -1
- package/dist/generated/services/projects.js +49 -1
- package/dist/generated/services/projects.js.map +1 -1
- package/dist/generated/services/projects.ts +61 -1
- package/dist/generated/services/recordings.d.ts +2 -12
- package/dist/generated/services/recordings.d.ts.map +1 -1
- package/dist/generated/services/recordings.js +1 -26
- package/dist/generated/services/recordings.js.map +1 -1
- package/dist/generated/services/recordings.ts +3 -31
- package/dist/generated/services/reports.d.ts +8 -12
- package/dist/generated/services/reports.d.ts.map +1 -1
- package/dist/generated/services/reports.js +11 -5
- package/dist/generated/services/reports.js.map +1 -1
- package/dist/generated/services/reports.ts +13 -14
- package/dist/generated/services/schedules.d.ts +94 -15
- package/dist/generated/services/schedules.d.ts.map +1 -1
- package/dist/generated/services/schedules.js +19 -8
- package/dist/generated/services/schedules.js.map +1 -1
- package/dist/generated/services/schedules.ts +107 -17
- package/dist/generated/services/search.d.ts +2 -0
- package/dist/generated/services/search.d.ts.map +1 -1
- package/dist/generated/services/search.js +1 -1
- package/dist/generated/services/search.js.map +1 -1
- package/dist/generated/services/search.ts +3 -1
- package/dist/generated/services/templates.d.ts +2 -0
- package/dist/generated/services/templates.d.ts.map +1 -1
- package/dist/generated/services/templates.js +1 -1
- package/dist/generated/services/templates.js.map +1 -1
- package/dist/generated/services/templates.ts +3 -1
- package/dist/generated/services/timeline.d.ts +2 -0
- package/dist/generated/services/timeline.d.ts.map +1 -1
- package/dist/generated/services/timeline.js +1 -0
- package/dist/generated/services/timeline.js.map +1 -1
- package/dist/generated/services/timeline.ts +3 -0
- package/dist/generated/services/timesheets.d.ts +16 -0
- package/dist/generated/services/timesheets.d.ts.map +1 -1
- package/dist/generated/services/timesheets.js +26 -2
- package/dist/generated/services/timesheets.js.map +1 -1
- package/dist/generated/services/timesheets.ts +35 -2
- package/dist/generated/services/todolist-groups.d.ts +11 -6
- package/dist/generated/services/todolist-groups.d.ts.map +1 -1
- package/dist/generated/services/todolist-groups.js +7 -3
- package/dist/generated/services/todolist-groups.js.map +1 -1
- package/dist/generated/services/todolist-groups.ts +13 -7
- package/dist/generated/services/todolists.d.ts +15 -13
- package/dist/generated/services/todolists.d.ts.map +1 -1
- package/dist/generated/services/todolists.js +11 -8
- package/dist/generated/services/todolists.js.map +1 -1
- package/dist/generated/services/todolists.ts +19 -14
- package/dist/generated/services/todos.d.ts +35 -12
- package/dist/generated/services/todos.d.ts.map +1 -1
- package/dist/generated/services/todos.js +47 -25
- package/dist/generated/services/todos.js.map +1 -1
- package/dist/generated/services/todos.ts +74 -30
- package/dist/generated/services/uploads.d.ts +5 -0
- package/dist/generated/services/uploads.d.ts.map +1 -1
- package/dist/generated/services/uploads.js +4 -0
- package/dist/generated/services/uploads.js.map +1 -1
- package/dist/generated/services/uploads.ts +6 -0
- package/dist/generated/services/vaults.d.ts +5 -0
- package/dist/generated/services/vaults.d.ts.map +1 -1
- package/dist/generated/services/vaults.js +4 -0
- package/dist/generated/services/vaults.js.map +1 -1
- package/dist/generated/services/vaults.ts +6 -0
- package/dist/hooks/otel.d.ts +1 -1
- package/dist/hooks/otel.js +1 -1
- package/dist/index.d.ts +21 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -9
- package/dist/index.js.map +1 -1
- package/dist/oauth/discovery.d.ts.map +1 -1
- package/dist/oauth/discovery.js +1 -0
- package/dist/oauth/discovery.js.map +1 -1
- package/dist/pagination-utils.d.ts +46 -0
- package/dist/pagination-utils.d.ts.map +1 -1
- package/dist/pagination-utils.js +85 -2
- package/dist/pagination-utils.js.map +1 -1
- package/dist/pagination.d.ts +12 -1
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +1 -1
- package/dist/pagination.js.map +1 -1
- package/dist/retry.d.ts +110 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +253 -0
- package/dist/retry.js.map +1 -0
- package/dist/services/base.d.ts.map +1 -1
- package/dist/services/base.js +59 -5
- package/dist/services/base.js.map +1 -1
- package/dist/services/cards-extensions.d.ts +26 -21
- package/dist/services/cards-extensions.d.ts.map +1 -1
- package/dist/services/cards-extensions.js +28 -31
- package/dist/services/cards-extensions.js.map +1 -1
- package/dist/services/documents-extensions.d.ts +122 -0
- package/dist/services/documents-extensions.d.ts.map +1 -0
- package/dist/services/documents-extensions.js +125 -0
- package/dist/services/documents-extensions.js.map +1 -0
- package/dist/services/merge-safe.d.ts +167 -0
- package/dist/services/merge-safe.d.ts.map +1 -0
- package/dist/services/merge-safe.js +217 -0
- package/dist/services/merge-safe.js.map +1 -0
- package/dist/services/schedules-extensions.d.ts +266 -0
- package/dist/services/schedules-extensions.d.ts.map +1 -0
- package/dist/services/schedules-extensions.js +268 -0
- package/dist/services/schedules-extensions.js.map +1 -0
- package/dist/services/todolists-extensions.d.ts +110 -0
- package/dist/services/todolists-extensions.d.ts.map +1 -0
- package/dist/services/todolists-extensions.js +262 -0
- package/dist/services/todolists-extensions.js.map +1 -0
- package/dist/services/todos-extensions.d.ts +12 -1
- package/dist/services/todos-extensions.d.ts.map +1 -1
- package/dist/services/todos-extensions.js +27 -8
- package/dist/services/todos-extensions.js.map +1 -1
- package/package.json +5 -4
- package/src/generated/metadata.ts +443 -133
- package/src/generated/openapi-stripped.json +8999 -4907
- package/src/generated/path-mapping.ts +40 -16
- package/src/generated/schema.d.ts +5508 -2346
- package/src/generated/services/bookmarks.ts +158 -0
- package/src/generated/services/boosts.ts +12 -0
- package/src/generated/services/calendars.ts +102 -0
- package/src/generated/services/campfires.ts +107 -85
- package/src/generated/services/cards.ts +6 -0
- package/src/generated/services/checkins.ts +20 -0
- package/src/generated/services/client-approvals.ts +10 -5
- package/src/generated/services/client-correspondences.ts +10 -5
- package/src/generated/services/client-replies.ts +18 -8
- package/src/generated/services/cloud-files.ts +188 -0
- package/src/generated/services/comments.ts +6 -0
- package/src/generated/services/documents.ts +14 -8
- package/src/generated/services/drafts.ts +67 -0
- package/src/generated/services/events.ts +6 -0
- package/src/generated/services/everything.ts +100 -25
- package/src/generated/services/folders.ts +201 -0
- package/src/generated/services/forwards.ts +10 -48
- package/src/generated/services/gauges.ts +9 -1
- package/src/generated/services/google-documents.ts +196 -0
- package/src/generated/services/index.ts +12 -5
- package/src/generated/services/messages.ts +3 -1
- package/src/generated/services/my-assignments.ts +104 -0
- package/src/generated/services/my-notes.ts +92 -0
- package/src/generated/services/my-notifications.ts +4 -2
- package/src/generated/services/people.ts +15 -1
- package/src/generated/services/projects.ts +61 -1
- package/src/generated/services/recordings.ts +3 -31
- package/src/generated/services/reports.ts +13 -14
- package/src/generated/services/schedules.ts +107 -17
- package/src/generated/services/search.ts +3 -1
- package/src/generated/services/templates.ts +3 -1
- package/src/generated/services/timeline.ts +3 -0
- package/src/generated/services/timesheets.ts +35 -2
- package/src/generated/services/todolist-groups.ts +13 -7
- package/src/generated/services/todolists.ts +19 -14
- package/src/generated/services/todos.ts +74 -30
- package/src/generated/services/uploads.ts +6 -0
- package/src/generated/services/vaults.ts +6 -0
package/README.md
CHANGED
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
Official TypeScript SDK for the [Basecamp API](https://github.com/basecamp/bc3-api).
|
|
8
8
|
|
|
9
|
+
**Upgrading to v0.13.0?** Read [MIGRATING.md](../MIGRATING.md#typescript) before you bump the version — TypeScript carries nine breaks your compiler will not catch, all of which give no signal at all.
|
|
10
|
+
|
|
9
11
|
## Features
|
|
10
12
|
|
|
11
13
|
- Full type safety with TypeScript generics
|
|
12
14
|
- 30+ services covering the complete Basecamp API
|
|
13
15
|
- OAuth 2.0 with PKCE support
|
|
14
|
-
- ETag-based HTTP caching
|
|
16
|
+
- ETag-based HTTP caching (opt-in)
|
|
15
17
|
- Automatic retry with exponential backoff
|
|
16
18
|
- Pagination helpers for large result sets
|
|
17
19
|
- Observability hooks for logging, metrics, and tracing
|
|
@@ -25,6 +27,60 @@ npm install @37signals/basecamp
|
|
|
25
27
|
|
|
26
28
|
Requires Node.js 22.12+ and TypeScript 5.0+.
|
|
27
29
|
|
|
30
|
+
## Getting a token
|
|
31
|
+
|
|
32
|
+
Every Basecamp API request carries an OAuth 2.0 access token. There is no API key and no personal access token, so even a throwaway script starts here:
|
|
33
|
+
|
|
34
|
+
1. Choose the grant that matches how your code runs:
|
|
35
|
+
|
|
36
|
+
| Your integration | Grant | Who refreshes the token |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| already holds a token you obtained elsewhere | **static token** — [`Token Providers`](#token-providers) | you do |
|
|
39
|
+
| can receive a browser redirect (web app, or a local callback server) | **authorization code + PKCE** — [`Manual Authorization Flow`](#manual-authorization-flow), or [`Interactive Login`](#interactive-login-cli--desktop) for a CLI | your `accessToken` function, which the SDK re-invokes per request |
|
|
40
|
+
| has no browser, but a person can approve on another device (CLI, headless server, TV) | **device flow** — [`Device flow`](#device-flow-rfc-8628) | your `accessToken` function, which the SDK re-invokes per request |
|
|
41
|
+
|
|
42
|
+
The one-line rule: **a redirect URI you control → authorization code; no browser but someone to approve → device flow; a token already in hand → static token.** An unattended daemon or CI job fits none of the three on its own — the device flow needs a person to enter the user code at the verification URI — so provision a token out of band and hand it to the process as a static or refresh token.
|
|
43
|
+
|
|
44
|
+
2. Get the client credentials that grant needs:
|
|
45
|
+
|
|
46
|
+
- **Authorization code + PKCE** — register your own integration at **<https://launchpad.37signals.com/integrations>**. You get a client ID, a client secret, and whatever redirect URI you nominated.
|
|
47
|
+
- **Device flow** — nothing to register. It runs as the pre-registered public `basecamp-cli` client, which sends no secret, against the device endpoint that discovery returns. Launchpad advertises no device endpoint, so a client you register there is not the one this flow uses.
|
|
48
|
+
- **Static token** — nothing to register; you already hold the token.
|
|
49
|
+
|
|
50
|
+
A bare `accessToken` string is never refreshed — once it expires every call fails with `401` until you supply a new one. Use it to get a first successful call, then pass an async token provider or an `AuthStrategy` before you ship.
|
|
51
|
+
|
|
52
|
+
## Finding your account ID
|
|
53
|
+
|
|
54
|
+
Every API path is scoped to an account — `https://3.basecampapi.com/{accountId}/…` — so `createBasecampClient` needs that number before your first call. One token can reach several accounts, so ask the token which. `getInfo()` addresses Launchpad by default, which is right for a Launchpad-issued token; a **device-flow** token is issued by the discovered BC5 server, so pass that issuer as the `endpoint` option:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { createBasecampClient } from "@37signals/basecamp";
|
|
58
|
+
|
|
59
|
+
const token = process.env.BASECAMP_TOKEN!;
|
|
60
|
+
|
|
61
|
+
// createBasecampClient always requires an accountId, but authorization.getInfo()
|
|
62
|
+
// talks to Launchpad rather than the account-scoped API, so a placeholder is fine
|
|
63
|
+
// for the bootstrap call.
|
|
64
|
+
const bootstrap = createBasecampClient({ accountId: "0", accessToken: token });
|
|
65
|
+
|
|
66
|
+
// "bc3" is Basecamp; the unfiltered response also carries "hey" and other products.
|
|
67
|
+
// endpoint defaults to Launchpad, which is right for a Launchpad-issued token.
|
|
68
|
+
// For a device-flow token, pass the discovered issuer:
|
|
69
|
+
// { filterProduct: "bc3", endpoint: `${issuer}/authorization.json` }
|
|
70
|
+
const info = await bootstrap.authorization.getInfo({ filterProduct: "bc3" });
|
|
71
|
+
for (const account of info.accounts) {
|
|
72
|
+
console.log(`${account.id}: ${account.name}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Rebuild with the real account ID — that is the client you keep.
|
|
76
|
+
const client = createBasecampClient({
|
|
77
|
+
accountId: String(info.accounts[0].id),
|
|
78
|
+
accessToken: token,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`info.expiresAt` is a `Date` telling you how long the token has left, which is the quickest way to confirm a static token has not lapsed.
|
|
83
|
+
|
|
28
84
|
## Quick Start
|
|
29
85
|
|
|
30
86
|
```ts
|
|
@@ -356,7 +412,7 @@ The SDK provides typed services for the complete Basecamp API:
|
|
|
356
412
|
|
|
357
413
|
| Service | Methods |
|
|
358
414
|
|---------|---------|
|
|
359
|
-
| `projects` | list, get, create, update, trash |
|
|
415
|
+
| `projects` | list, get, create, update, trash, archive, unarchive |
|
|
360
416
|
| `templates` | list, get, createProject |
|
|
361
417
|
| `tools` | list, get, update |
|
|
362
418
|
| `people` | list, get, me, listPingable |
|
|
@@ -365,7 +421,7 @@ The SDK provides typed services for the complete Basecamp API:
|
|
|
365
421
|
|
|
366
422
|
| Service | Methods |
|
|
367
423
|
|---------|---------|
|
|
368
|
-
| `todos` | list, get, create, update,
|
|
424
|
+
| `todos` | list, get, create, update, complete, uncomplete, reposition |
|
|
369
425
|
| `todolists` | list, get, create, update, trash, reposition |
|
|
370
426
|
| `todosets` | get |
|
|
371
427
|
| `todolistGroups` | list, get, create, reposition |
|
|
@@ -438,7 +494,7 @@ The SDK provides typed services for the complete Basecamp API:
|
|
|
438
494
|
|
|
439
495
|
| Service | Methods |
|
|
440
496
|
|---------|---------|
|
|
441
|
-
| `forwards` | list, get,
|
|
497
|
+
| `forwards` | list, get, listReplies, getReply |
|
|
442
498
|
|
|
443
499
|
## Downloading Files
|
|
444
500
|
|
|
@@ -482,6 +538,22 @@ To bound the work, pass `maxItems` — every list options type extends `Paginati
|
|
|
482
538
|
const firstFifty = await client.projects.list({ maxItems: 50 });
|
|
483
539
|
```
|
|
484
540
|
|
|
541
|
+
### The `page` option
|
|
542
|
+
|
|
543
|
+
A positive `page` selects exactly that page: one request, that page's items,
|
|
544
|
+
no link-following.
|
|
545
|
+
|
|
546
|
+
```ts
|
|
547
|
+
const pageThree = await client.projects.list({ page: 3 });
|
|
548
|
+
console.log(pageThree.meta.truncated); // true when a further page existed
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
Omit `page` (or pass `0`) to auto-paginate the whole collection. `maxItems`
|
|
552
|
+
still trims a pinned page.
|
|
553
|
+
|
|
554
|
+
All six SDKs share these semantics — one request, that page only, no
|
|
555
|
+
link-following. See SPEC section 8.
|
|
556
|
+
|
|
485
557
|
For endpoints not covered by a service, drive pagination yourself over a raw `client.GET` response with `fetchAllPages` (collects all pages into one array) or `paginateAll` (async generator that yields one page at a time):
|
|
486
558
|
|
|
487
559
|
```ts
|
|
@@ -567,6 +639,32 @@ try {
|
|
|
567
639
|
| `validation` | 400, 422 | 9 | Invalid request data |
|
|
568
640
|
| `usage` | - | 1 | Configuration or argument error |
|
|
569
641
|
|
|
642
|
+
### Validation Errors
|
|
643
|
+
|
|
644
|
+
Basecamp rejects invalid writes with a body keyed by field. The SDK folds those
|
|
645
|
+
messages into `message` and keeps the raw map in `fieldErrors`, so you can drive
|
|
646
|
+
a form without re-parsing the message:
|
|
647
|
+
|
|
648
|
+
```typescript
|
|
649
|
+
try {
|
|
650
|
+
await client.calendars.updateCalendar(calendarId, { calendar: { color: "chartreuse" } });
|
|
651
|
+
} catch (error) {
|
|
652
|
+
if (isErrorCode(error, "validation")) {
|
|
653
|
+
// "color: is not a valid color"
|
|
654
|
+
console.error(error.message);
|
|
655
|
+
|
|
656
|
+
for (const [field, messages] of Object.entries(error.fieldErrors ?? {})) {
|
|
657
|
+
console.error(` ${field}: ${messages.join(", ")}`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
`fieldErrors` is `undefined` for every other error shape, and its messages are
|
|
664
|
+
the raw ones — `message` is capped at 500 characters, the map is not. It is a
|
|
665
|
+
null-prototype object, so a field literally named `__proto__` is an ordinary
|
|
666
|
+
key.
|
|
667
|
+
|
|
570
668
|
## Retry Behavior
|
|
571
669
|
|
|
572
670
|
The SDK automatically retries requests on transient failures:
|
|
@@ -588,26 +686,24 @@ const client = createBasecampClient({
|
|
|
588
686
|
|
|
589
687
|
## Caching
|
|
590
688
|
|
|
591
|
-
The SDK
|
|
592
|
-
|
|
593
|
-
```ts
|
|
594
|
-
// First request fetches from API
|
|
595
|
-
const projects = await client.projects.list();
|
|
596
|
-
|
|
597
|
-
// Second request returns cached data if unchanged (304 Not Modified)
|
|
598
|
-
const projects2 = await client.projects.list();
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
Disable caching if needed:
|
|
689
|
+
The SDK can do ETag-based HTTP caching to reduce API calls and respect Basecamp's rate limits, but it is **off by default** — `enableCache` defaults to `false`, and a client built without it sends no `If-None-Match` and stores no responses. Opt in:
|
|
602
690
|
|
|
603
691
|
```ts
|
|
604
692
|
const client = createBasecampClient({
|
|
605
693
|
accountId: "12345",
|
|
606
694
|
accessToken: "token",
|
|
607
|
-
enableCache:
|
|
695
|
+
enableCache: true,
|
|
608
696
|
});
|
|
697
|
+
|
|
698
|
+
// First request fetches from the API and stores the ETag
|
|
699
|
+
const projects = await client.projects.list();
|
|
700
|
+
|
|
701
|
+
// Second request revalidates with If-None-Match; a 304 is served from the store
|
|
702
|
+
const projects2 = await client.projects.list();
|
|
609
703
|
```
|
|
610
704
|
|
|
705
|
+
The store is in-memory and per-client — it lives and dies with the client instance — holds at most 1,000 entries, and is keyed by URL plus a hash of the `Authorization` header, so a refreshed or swapped token never reads another token's entries.
|
|
706
|
+
|
|
611
707
|
## Observability
|
|
612
708
|
|
|
613
709
|
### Console Logging
|
|
File without changes
|
package/dist/client.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { type AuthStrategy } from "./auth-strategy.js";
|
|
|
13
13
|
import { type DownloadResult } from "./download.js";
|
|
14
14
|
import { ProjectsService } from "./generated/services/projects.js";
|
|
15
15
|
import { TodosService } from "./services/todos-extensions.js";
|
|
16
|
-
import { TodolistsService } from "./
|
|
16
|
+
import { TodolistsService } from "./services/todolists-extensions.js";
|
|
17
17
|
import { TodosetsService } from "./generated/services/todosets.js";
|
|
18
18
|
import { HillChartsService } from "./generated/services/hill-charts.js";
|
|
19
19
|
import { PeopleService } from "./generated/services/people.js";
|
|
@@ -33,12 +33,19 @@ import { ClientApprovalsService } from "./generated/services/client-approvals.js
|
|
|
33
33
|
import { ClientCorrespondencesService } from "./generated/services/client-correspondences.js";
|
|
34
34
|
import { ClientRepliesService } from "./generated/services/client-replies.js";
|
|
35
35
|
import { WebhooksService } from "./generated/services/webhooks.js";
|
|
36
|
+
import { BookmarksService } from "./generated/services/bookmarks.js";
|
|
37
|
+
import { FoldersService } from "./generated/services/folders.js";
|
|
38
|
+
import { DraftsService } from "./generated/services/drafts.js";
|
|
39
|
+
import { CalendarsService } from "./generated/services/calendars.js";
|
|
40
|
+
import { MyNotesService } from "./generated/services/my-notes.js";
|
|
36
41
|
import { SubscriptionsService } from "./generated/services/subscriptions.js";
|
|
37
42
|
import { AttachmentsService } from "./generated/services/attachments.js";
|
|
38
43
|
import { VaultsService } from "./generated/services/vaults.js";
|
|
39
|
-
import { DocumentsService } from "./
|
|
44
|
+
import { DocumentsService } from "./services/documents-extensions.js";
|
|
40
45
|
import { UploadsService } from "./services/uploads-extensions.js";
|
|
41
|
-
import {
|
|
46
|
+
import { CloudFilesService } from "./generated/services/cloud-files.js";
|
|
47
|
+
import { GoogleDocumentsService } from "./generated/services/google-documents.js";
|
|
48
|
+
import { SchedulesService } from "./services/schedules-extensions.js";
|
|
42
49
|
import { EventsService } from "./generated/services/events.js";
|
|
43
50
|
import { RecordingsService } from "./generated/services/recordings.js";
|
|
44
51
|
import { SearchService } from "./generated/services/search.js";
|
|
@@ -73,11 +80,11 @@ export interface BasecampClient extends RawClient {
|
|
|
73
80
|
readonly raw: RawClient;
|
|
74
81
|
/** Hooks for observability (if configured) */
|
|
75
82
|
readonly hooks?: BasecampHooks;
|
|
76
|
-
/** Projects service - list, get, create, update, and
|
|
83
|
+
/** Projects service - list, get, create, update, trash, archive, and unarchive projects */
|
|
77
84
|
readonly projects: ProjectsService;
|
|
78
85
|
/** Todos service - list, get, create, update, complete, and manage todos */
|
|
79
86
|
readonly todos: TodosService;
|
|
80
|
-
/** Todolists service - list, get, create, and
|
|
87
|
+
/** Todolists service - list, get, create, update, edit, and replace todo lists */
|
|
81
88
|
readonly todolists: TodolistsService;
|
|
82
89
|
/** Todosets service - get todo sets (container for todo lists) */
|
|
83
90
|
readonly todosets: TodosetsService;
|
|
@@ -119,6 +126,16 @@ export interface BasecampClient extends RawClient {
|
|
|
119
126
|
readonly clientReplies: ClientRepliesService;
|
|
120
127
|
/** Webhooks service - create, update, delete webhooks */
|
|
121
128
|
readonly webhooks: WebhooksService;
|
|
129
|
+
/** Bookmarks service - the current user's personal bookmarks */
|
|
130
|
+
readonly bookmarks: BookmarksService;
|
|
131
|
+
/** Folders service - the current user's home-screen folders (wire type "Stack") */
|
|
132
|
+
readonly folders: FoldersService;
|
|
133
|
+
/** Drafts service - the current user's unpublished drafts */
|
|
134
|
+
readonly drafts: DraftsService;
|
|
135
|
+
/** Calendars service - per-account calendars (show + update) */
|
|
136
|
+
readonly calendars: CalendarsService;
|
|
137
|
+
/** MyNotes service - the current user's scratchpad note */
|
|
138
|
+
readonly myNotes: MyNotesService;
|
|
122
139
|
/** Subscriptions service - manage notification subscriptions */
|
|
123
140
|
readonly subscriptions: SubscriptionsService;
|
|
124
141
|
/** Attachments service - upload files for embedding in rich text */
|
|
@@ -129,6 +146,10 @@ export interface BasecampClient extends RawClient {
|
|
|
129
146
|
readonly documents: DocumentsService;
|
|
130
147
|
/** Uploads service - manage files in vaults */
|
|
131
148
|
readonly uploads: UploadsService;
|
|
149
|
+
/** Cloud files service - manage links to files on external services in vaults */
|
|
150
|
+
readonly cloudFiles: CloudFilesService;
|
|
151
|
+
/** Google documents service - manage links to Google Workspace documents in vaults */
|
|
152
|
+
readonly googleDocuments: GoogleDocumentsService;
|
|
132
153
|
/** Schedules service - manage schedules and calendar entries */
|
|
133
154
|
readonly schedules: SchedulesService;
|
|
134
155
|
/** Events service - view recording change events */
|
|
@@ -200,13 +221,13 @@ export interface BasecampClientOptions {
|
|
|
200
221
|
/** Maximum pages to follow during auto-pagination (defaults to 10,000) */
|
|
201
222
|
maxPages?: number;
|
|
202
223
|
}
|
|
203
|
-
export declare const VERSION = "0.
|
|
204
|
-
export declare const API_VERSION = "2026-
|
|
224
|
+
export declare const VERSION = "0.13.0";
|
|
225
|
+
export declare const API_VERSION = "2026-08-05";
|
|
205
226
|
/**
|
|
206
227
|
* Creates a type-safe Basecamp API client with built-in middleware for:
|
|
207
228
|
* - Authentication (Bearer token)
|
|
208
229
|
* - Retry with exponential backoff (respects Retry-After header)
|
|
209
|
-
* - ETag-based HTTP caching
|
|
230
|
+
* - ETag-based HTTP caching, opt-in via `enableCache` (defaults to false)
|
|
210
231
|
*
|
|
211
232
|
* @example
|
|
212
233
|
* ```ts
|
|
@@ -228,7 +249,23 @@ export declare function createBasecampClient(options: BasecampClientOptions): Ba
|
|
|
228
249
|
export declare function normalizeUrlPath(url: string): string;
|
|
229
250
|
/**
|
|
230
251
|
* Fetches all pages of a paginated resource using Link header pagination.
|
|
231
|
-
* Automatically follows rel="next" links until no more pages exist
|
|
252
|
+
* Automatically follows rel="next" links until no more pages exist, or until
|
|
253
|
+
* `maxPages` pages have been consumed.
|
|
254
|
+
*
|
|
255
|
+
* The cap is not optional in spirit: a Link header naming the page it was
|
|
256
|
+
* served from makes "until no more pages exist" never true, and the header is
|
|
257
|
+
* attacker-influenced (that is why `isSameOrigin` is checked below). Every
|
|
258
|
+
* other pagination loop in this SDK, and in the other five, is bounded the
|
|
259
|
+
* same way. Reaching the cap stops quietly — there is no meta channel on a
|
|
260
|
+
* bare `T[]` to report it, and throwing would break callers who legitimately
|
|
261
|
+
* have that many pages.
|
|
262
|
+
*
|
|
263
|
+
* @param maxPages - Safety cap on pages CONSUMED. Must be a positive integer;
|
|
264
|
+
* `0`, negatives, `NaN`, `Infinity` and non-integers all throw
|
|
265
|
+
* `BasecampError("usage")` before any request is made. Defaults to
|
|
266
|
+
* `DEFAULT_MAX_PAGES`.
|
|
267
|
+
* @throws {BasecampError} with `code: "usage"` if `maxPages` is not a positive
|
|
268
|
+
* integer.
|
|
232
269
|
*
|
|
233
270
|
* @example
|
|
234
271
|
* ```ts
|
|
@@ -240,11 +277,28 @@ export declare function normalizeUrlPath(url: string): string;
|
|
|
240
277
|
* );
|
|
241
278
|
* ```
|
|
242
279
|
*/
|
|
243
|
-
export declare function fetchAllPages<T>(initialResponse: Response, parse: (response: Response) => Promise<T[]>, authHeader?: string): Promise<T[]>;
|
|
280
|
+
export declare function fetchAllPages<T>(initialResponse: Response, parse: (response: Response) => Promise<T[]>, authHeader?: string, maxPages?: number): Promise<T[]>;
|
|
244
281
|
/**
|
|
245
282
|
* Async generator that yields pages of results one at a time.
|
|
246
283
|
* Useful for processing large datasets without loading everything into memory.
|
|
247
284
|
*
|
|
285
|
+
* Bounded by `maxPages` for the same reason as {@link fetchAllPages}: a Link
|
|
286
|
+
* header that points at its own page would otherwise yield forever.
|
|
287
|
+
*
|
|
288
|
+
* Validation is EAGER, which is why this is a plain function returning a
|
|
289
|
+
* generator rather than an `async function*`. The body of an `async function*`
|
|
290
|
+
* does not run until something iterates it, so a check written inside one would
|
|
291
|
+
* surface a bad `maxPages` at some later `for await` — possibly in a different
|
|
292
|
+
* function, on a generator that was passed along. A usage error is a programmer
|
|
293
|
+
* error and belongs at the call site that made it.
|
|
294
|
+
*
|
|
295
|
+
* @param maxPages - Safety cap on pages CONSUMED. Must be a positive integer;
|
|
296
|
+
* `0`, negatives, `NaN`, `Infinity` and non-integers all throw
|
|
297
|
+
* `BasecampError("usage")` from this call, before the generator is created
|
|
298
|
+
* and before any request is made. Defaults to `DEFAULT_MAX_PAGES`.
|
|
299
|
+
* @throws {BasecampError} with `code: "usage"` if `maxPages` is not a positive
|
|
300
|
+
* integer.
|
|
301
|
+
*
|
|
248
302
|
* @example
|
|
249
303
|
* ```ts
|
|
250
304
|
* for await (const page of paginateAll(response.response, (r) => r.json() as Promise<any[]>)) {
|
|
@@ -252,6 +306,6 @@ export declare function fetchAllPages<T>(initialResponse: Response, parse: (resp
|
|
|
252
306
|
* }
|
|
253
307
|
* ```
|
|
254
308
|
*/
|
|
255
|
-
export declare function paginateAll<T>(initialResponse: Response, parse: (response: Response) => Promise<T[]>, authHeader?: string): AsyncGenerator<T[], void, unknown>;
|
|
309
|
+
export declare function paginateAll<T>(initialResponse: Response, parse: (response: Response) => Promise<T[]>, authHeader?: string, maxPages?: number): AsyncGenerator<T[], void, unknown>;
|
|
256
310
|
export { parseNextLink, resolveURL, isSameOrigin };
|
|
257
311
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,YAAiC,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|