@rustrak/client 0.24.0 → 0.26.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 +76 -61
- package/dist/client.cjs +4 -3
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -1
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.mts +2 -1
- package/dist/client.d.mts.map +1 -1
- package/dist/client.mjs +5 -4
- package/dist/client.mjs.map +1 -1
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts.map +1 -1
- package/dist/errors.cjs +19 -6
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +1 -1
- package/dist/errors.d.cts.map +1 -1
- package/dist/errors.d.mts +1 -1
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +19 -7
- package/dist/errors.mjs.map +1 -1
- package/dist/generated/binary.gen.cjs +6 -0
- package/dist/generated/binary.gen.cjs.map +1 -0
- package/dist/generated/binary.gen.d.cts +2 -0
- package/dist/generated/binary.gen.d.cts.map +1 -0
- package/dist/generated/binary.gen.d.mts +2 -0
- package/dist/generated/binary.gen.d.mts.map +1 -0
- package/dist/generated/binary.gen.mjs +6 -0
- package/dist/generated/binary.gen.mjs.map +1 -0
- package/dist/generated/sdk.gen.cjs +371 -199
- package/dist/generated/sdk.gen.cjs.map +1 -1
- package/dist/generated/sdk.gen.d.cts +24 -2
- package/dist/generated/sdk.gen.d.cts.map +1 -1
- package/dist/generated/sdk.gen.d.mts +24 -2
- package/dist/generated/sdk.gen.d.mts.map +1 -1
- package/dist/generated/sdk.gen.mjs +370 -201
- package/dist/generated/sdk.gen.mjs.map +1 -1
- package/dist/generated/types.gen.d.cts +313 -47
- package/dist/generated/types.gen.d.cts.map +1 -1
- package/dist/generated/types.gen.d.mts +313 -47
- package/dist/generated/types.gen.d.mts.map +1 -1
- package/dist/generated/zod.gen.cjs +315 -88
- package/dist/generated/zod.gen.cjs.map +1 -1
- package/dist/generated/zod.gen.mjs +275 -84
- package/dist/generated/zod.gen.mjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/result.cjs +0 -2
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts.map +1 -1
- package/dist/result.d.mts.map +1 -1
- package/dist/result.mjs +0 -2
- package/dist/result.mjs.map +1 -1
- package/dist/utils/http.cjs +18 -31
- package/dist/utils/http.cjs.map +1 -1
- package/dist/utils/http.mjs +20 -32
- package/dist/utils/http.mjs.map +1 -1
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ const resolved = await client.issues.update({
|
|
|
87
87
|
- **Validated both ways**: requests and responses are checked against Zod schemas generated from the same spec; a mismatch is a typed error, not a crash
|
|
88
88
|
- **No exceptions**: every method returns `Result<T, RustrakError>`, so failure is in the type, and the value survives the React server/client boundary
|
|
89
89
|
- **Tree-shakeable**: ESM is published one module per file with `sideEffects: false`
|
|
90
|
-
- **Retries**: exponential backoff on 408 and
|
|
90
|
+
- **Retries**: exponential backoff on an unreachable server and on 408, 500, 502, 503 and 504, for idempotent methods (`GET`, `PUT`, `DELETE`). Not on a timeout or a 429: `isRetryable` says yes to both, but when to retry is the caller's call
|
|
91
91
|
- **Redacted 5xx**: a server error never carries a server-supplied message, so internal detail cannot reach a UI
|
|
92
92
|
|
|
93
93
|
## Configuration
|
|
@@ -157,8 +157,8 @@ console.log(result.data);
|
|
|
157
157
|
| `gone` | 410 | ✅ | ❌ | |
|
|
158
158
|
| `payload_too_large` | 413 | ✅ | ❌ | Envelope ingestion only |
|
|
159
159
|
| `rate_limited` | 429 | ✅ | ✅ | Optional `retryAfter` in seconds |
|
|
160
|
-
| `client_error` | other 4xx | ✅ |
|
|
161
|
-
| `server_error` | 5xx | ✅ |
|
|
160
|
+
| `client_error` | other 4xx | ✅ | 408 only | Catch-all, so no status is unrepresentable |
|
|
161
|
+
| `server_error` | 5xx | ✅ | 500, 502, 503, 504 | **Message is always a fixed generic string** |
|
|
162
162
|
| `network` | n/a | no | ✅ | DNS, refused connection, TLS, timeout |
|
|
163
163
|
| `invalid_response` | n/a | no | ❌ | 2xx whose body failed its schema |
|
|
164
164
|
| `invalid_request` | n/a | no | ❌ | Your input failed its schema; nothing was sent |
|
|
@@ -226,6 +226,19 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
226
226
|
<!-- api:start -->
|
|
227
227
|
<!-- Generated by `pnpm generate` from openapi.json. Do not edit by hand. -->
|
|
228
228
|
|
|
229
|
+
### Access
|
|
230
|
+
|
|
231
|
+
| Method | Endpoint | Description |
|
|
232
|
+
|---|---|---|
|
|
233
|
+
| `access.catalog()` | `GET /api/access/catalog` | Lists every resource a permission can name, with its module, scope and actions. |
|
|
234
|
+
| `access.me()` | `GET /api/access/me` | Returns what the caller may do, on the instance and on each project. |
|
|
235
|
+
| `roles.create({ body })` | `POST /api/roles` | Creates a role from permissions the caller holds themselves. |
|
|
236
|
+
| `roles.delete({ path })` | `DELETE /api/roles/{id}` | Deletes a role nobody holds. |
|
|
237
|
+
| `roles.list()` | `GET /api/roles` | Lists every role with its permissions and how often it is assigned. |
|
|
238
|
+
| `roles.update({ path, body })` | `PUT /api/roles/{id}` | Replaces a role's name, description and permissions. |
|
|
239
|
+
| `users.assignments({ path })` | `GET /api/users/{id}/assignments` | Lists the roles a user holds, on the instance and on each project. |
|
|
240
|
+
| `users.setAssignments({ path, body })` | `PUT /api/users/{id}/assignments` | Replaces every role and personal permission a user holds. |
|
|
241
|
+
|
|
229
242
|
### Agents
|
|
230
243
|
|
|
231
244
|
| Method | Endpoint | Description |
|
|
@@ -235,54 +248,53 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
235
248
|
| `agents.duration({ path, query? })` | `GET /api/projects/{project_id}/agents/duration` | Time-bucketed avg/p95 duration for `agent`/`ai_client` spans. |
|
|
236
249
|
| `agents.environments({ path })` | `GET /api/projects/{project_id}/agents/environments` | The options the environment filter offers, read from the data rather than hardcoded — an installation may name its environments anything. |
|
|
237
250
|
| `agents.modelsCalls({ path, query? })` | `GET /api/projects/{project_id}/agents/models/calls` | Top models by LLM call count (`gen_ai.operation.type:ai_client`). |
|
|
238
|
-
| `agents.modelsTable({ path, query? })` | `GET /api/projects/{project_id}/agents/models` |
|
|
251
|
+
| `agents.modelsTable({ path, query? })` | `GET /api/projects/{project_id}/agents/models` | Lists the AI models a project's agents called, with requests, tokens and latency. |
|
|
239
252
|
| `agents.modelsTokens({ path, query? })` | `GET /api/projects/{project_id}/agents/models/tokens` | Top models by total tokens used (`gen_ai.operation.type:ai_client`). |
|
|
240
253
|
| `agents.runs({ path, query? })` | `GET /api/projects/{project_id}/agents/runs` | Time-bucketed count of agent-run spans (`gen_ai.operation.type:agent`). |
|
|
241
254
|
| `agents.summary({ path, query? })` | `GET /api/projects/{project_id}/agents/summary` | Agent runs, LLM calls, tool calls, errors, tokens and latency over the selected window — the numbers the six charts cannot state outright. |
|
|
242
255
|
| `agents.tools({ path, query? })` | `GET /api/projects/{project_id}/agents/tools` | Top tools by call count (`gen_ai.operation.type:tool`). |
|
|
243
|
-
| `agents.toolsTable({ path, query? })` | `GET /api/projects/{project_id}/agents/tools/stats` |
|
|
256
|
+
| `agents.toolsTable({ path, query? })` | `GET /api/projects/{project_id}/agents/tools/stats` | Lists the tools a project's agents called, with calls, errors and latency. |
|
|
244
257
|
| `agents.traces({ path, query? })` | `GET /api/projects/{project_id}/agents/traces` | Paginated per-trace_id aggregate (duration, tokens, tool usage) across all AI spans sharing that trace, regardless of origin. |
|
|
245
258
|
|
|
246
259
|
### Alert Channels
|
|
247
260
|
|
|
248
261
|
| Method | Endpoint | Description |
|
|
249
262
|
|---|---|---|
|
|
250
|
-
| `alertChannels.create({ body })` | `POST /api/integrations` |
|
|
251
|
-
| `alertChannels.delete({ path })` | `DELETE /api/integrations/{id}` |
|
|
252
|
-
| `alertChannels.get({ path })` | `GET /api/integrations/{id}` |
|
|
253
|
-
| `alertChannels.list()` | `GET /api/integrations` |
|
|
263
|
+
| `alertChannels.create({ body })` | `POST /api/integrations` | Creates a notification integration (webhook, Slack, email…). |
|
|
264
|
+
| `alertChannels.delete({ path })` | `DELETE /api/integrations/{id}` | Deletes a notification integration. |
|
|
265
|
+
| `alertChannels.get({ path })` | `GET /api/integrations/{id}` | Gets one notification integration. |
|
|
266
|
+
| `alertChannels.list()` | `GET /api/integrations` | Lists the channels alerts can go through. |
|
|
254
267
|
| `alertChannels.previewTemplate({ body })` | `POST /api/integrations/preview-template` | Renders a Custom Webhook template against a sample payload and hands back the body that would be sent. |
|
|
255
|
-
| `alertChannels.test({ path, body })` | `POST /api/integrations/{id}/test` |
|
|
256
|
-
| `alertChannels.update({ path, body })` | `PATCH /api/integrations/{id}` |
|
|
268
|
+
| `alertChannels.test({ path, body })` | `POST /api/integrations/{id}/test` | Sends a test notification through an integration. |
|
|
269
|
+
| `alertChannels.update({ path, body })` | `PATCH /api/integrations/{id}` | Updates a notification integration. |
|
|
257
270
|
|
|
258
271
|
### Alert Rules
|
|
259
272
|
|
|
260
273
|
| Method | Endpoint | Description |
|
|
261
274
|
|---|---|---|
|
|
262
|
-
| `alertRules.create({ path, body })` | `POST /api/projects/{project_id}/alert-rules` |
|
|
263
|
-
| `alertRules.delete({ path })` | `DELETE /api/projects/{project_id}/alert-rules/{rule_id}` |
|
|
264
|
-
| `alertRules.get({ path })` | `GET /api/projects/{project_id}/alert-rules/{rule_id}` |
|
|
275
|
+
| `alertRules.create({ path, body })` | `POST /api/projects/{project_id}/alert-rules` | Creates an alert rule in a project. |
|
|
276
|
+
| `alertRules.delete({ path })` | `DELETE /api/projects/{project_id}/alert-rules/{rule_id}` | Deletes an alert rule. |
|
|
277
|
+
| `alertRules.get({ path })` | `GET /api/projects/{project_id}/alert-rules/{rule_id}` | Gets one alert rule. |
|
|
265
278
|
| `alertRules.historyByDay({ path, query? })` | `GET /api/projects/{project_id}/alert-history/daily` | Count a project's alert deliveries per day, by outcome. |
|
|
266
|
-
| `alertRules.list({ path })` | `GET /api/projects/{project_id}/alert-rules` |
|
|
267
|
-
| `alertRules.listHistory({ path, query? })` | `GET /api/projects/{project_id}/alert-history` |
|
|
268
|
-
| `alertRules.update({ path, body })` | `PATCH /api/projects/{project_id}/alert-rules/{rule_id}` |
|
|
279
|
+
| `alertRules.list({ path })` | `GET /api/projects/{project_id}/alert-rules` | Lists a project's alert rules. |
|
|
280
|
+
| `alertRules.listHistory({ path, query? })` | `GET /api/projects/{project_id}/alert-history` | Lists the alerts a project sent, newest first. |
|
|
281
|
+
| `alertRules.update({ path, body })` | `PATCH /api/projects/{project_id}/alert-rules/{rule_id}` | Updates an alert rule. |
|
|
269
282
|
|
|
270
283
|
### Auth
|
|
271
284
|
|
|
272
285
|
| Method | Endpoint | Description |
|
|
273
286
|
|---|---|---|
|
|
274
287
|
| `auth.acceptInvitation({ body })` | `POST /auth/accept-invitation` | Accept a pending invitation: creates the user (with the invite's email + role) and logs in. |
|
|
275
|
-
| `auth.changePassword({ body })` | `POST /auth/me/password` | Change the current user's password |
|
|
288
|
+
| `auth.changePassword({ body })` | `POST /auth/me/password` | Change the current user's password. |
|
|
276
289
|
| `auth.confirmSsoLink({ body })` | `POST /auth/sso/link` | Link the pending SSO identity to its account once the account's password is given, and sign in. |
|
|
277
290
|
| `auth.getCurrentUser()` | `GET /auth/me` | Get current authenticated user |
|
|
278
291
|
| `auth.getInvitation({ path })` | `GET /auth/invitation/{token}` | Returns the invitation's details if it is still acceptable (for the accept page). |
|
|
279
292
|
| `auth.login({ body })` | `POST /auth/login` | Authenticate user and create session |
|
|
280
293
|
| `auth.logout()` | `POST /auth/logout` | Clear session |
|
|
281
|
-
| `auth.register({ body })` | `POST /auth/register` | Registration is invite-only — always rejected. |
|
|
282
294
|
| `auth.ssoCallback({ query? })` | `GET /auth/sso/callback` | Validate the provider response, resolve or provision the local account, and establish the normal Rustrak session. |
|
|
283
295
|
| `auth.ssoConfig()` | `GET /auth/sso/config` | Public, non-sensitive information used to render the login page. |
|
|
284
296
|
| `auth.ssoLink()` | `GET /auth/sso/link` | The account an SSO login matched, shown while its owner confirms. |
|
|
285
|
-
| `auth.ssoStart()` | `POST /auth/sso/start` | Create a one-time OIDC authorization request and retain its protections in the
|
|
297
|
+
| `auth.ssoStart()` | `POST /auth/sso/start` | Create a one-time OIDC authorization request and retain its protections in the session. |
|
|
286
298
|
| `auth.updateCurrentUser({ body })` | `PATCH /auth/me` | Update the current user's presentation preferences |
|
|
287
299
|
|
|
288
300
|
### Events
|
|
@@ -301,20 +313,20 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
301
313
|
|---|---|---|
|
|
302
314
|
| `github.callback({ query })` | `GET /api/github/callback` | GitHub sends the browser here after creating the app; the code trades for its credentials. |
|
|
303
315
|
| `github.createIssue({ path, body })` | `POST /api/projects/{project_id}/issues/{issue_id}/github/issues` | Opens a GitHub issue and links it. |
|
|
304
|
-
| `github.deleteProjectRepository({ path })` | `DELETE /api/projects/{project_id}/github` |
|
|
305
|
-
| `github.disconnect()` | `DELETE /api/github` |
|
|
316
|
+
| `github.deleteProjectRepository({ path })` | `DELETE /api/projects/{project_id}/github` | Unlinks a project from its GitHub repository. |
|
|
317
|
+
| `github.disconnect()` | `DELETE /api/github` | Disconnects the GitHub App from this instance. |
|
|
306
318
|
| `github.getMyLogin()` | `GET /api/github/me` | The GitHub username assignees sync through. |
|
|
307
|
-
| `github.getProjectRepository({ path })` | `GET /api/projects/{project_id}/github` |
|
|
319
|
+
| `github.getProjectRepository({ path })` | `GET /api/projects/{project_id}/github` | Gets the GitHub repository a project is linked to. |
|
|
308
320
|
| `github.installed({ query })` | `GET /api/github/installed` | GitHub sends the browser here after the app is installed on an account. |
|
|
309
321
|
| `github.issue({ path })` | `GET /api/projects/{project_id}/issues/{issue_id}/github` | The issue's links, the commits that may have caused it, and who owns its culprit file. |
|
|
310
322
|
| `github.issueDraft({ path })` | `GET /api/projects/{project_id}/issues/{issue_id}/github/draft` | What creating a GitHub issue sends by default, with the templates applied, for the person to edit first. |
|
|
311
323
|
| `github.linkIssue({ path, body })` | `POST /api/projects/{project_id}/issues/{issue_id}/github/links` | Links an existing GitHub issue or pull request. |
|
|
312
324
|
| `github.manifest({ body })` | `POST /api/github/manifest` | What the dashboard posts to GitHub so GitHub creates an app already configured for this server. |
|
|
313
325
|
| `github.putIssueTemplate({ body })` | `PUT /api/github/issue-template` | The labels, title prefix and body footer every GitHub issue starts with, before a project's own. |
|
|
314
|
-
| `github.putMyLogin({ body })` | `PUT /api/github/me` |
|
|
315
|
-
| `github.putProjectRepository({ path, body })` | `PUT /api/projects/{project_id}/github` |
|
|
326
|
+
| `github.putMyLogin({ body })` | `PUT /api/github/me` | Sets or clears the caller's GitHub username, which assignees sync through. |
|
|
327
|
+
| `github.putProjectRepository({ path, body })` | `PUT /api/projects/{project_id}/github` | Links a project to a GitHub repository. |
|
|
316
328
|
| `github.repositories({ query })` | `GET /api/github/repositories` | The repositories a project can point at, for whoever may change that project's settings. |
|
|
317
|
-
| `github.status()` | `GET /api/github` |
|
|
329
|
+
| `github.status()` | `GET /api/github` | Shows whether a GitHub App is connected, and how. |
|
|
318
330
|
| `github.syncCodeowners({ path })` | `POST /api/projects/{project_id}/github/codeowners` | Copies the repository's CODEOWNERS so ownership can be answered without asking GitHub each time. |
|
|
319
331
|
| `github.unlinkIssue({ path })` | `DELETE /api/projects/{project_id}/issues/{issue_id}/github/links/{link_id}` | |
|
|
320
332
|
| `github.webhook({ body })` | `POST /api/github/webhook` | Public, and trusted only through the signature GitHub computes with the app's webhook secret. |
|
|
@@ -331,9 +343,11 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
331
343
|
|
|
332
344
|
| Method | Endpoint | Description |
|
|
333
345
|
|---|---|---|
|
|
334
|
-
| `invitations.create({ body })` | `POST /api/invitations` | Create an invitation (
|
|
335
|
-
| `invitations.
|
|
336
|
-
| `invitations.
|
|
346
|
+
| `invitations.create({ body })` | `POST /api/invitations` | Create an invitation (needs `invitations:create`) |
|
|
347
|
+
| `invitations.emailStatus()` | `GET /api/invitations/email-status` | Whether invitation emails can be sent (needs `invitations:read`) |
|
|
348
|
+
| `invitations.list()` | `GET /api/invitations` | List invitations (needs `invitations:read`) |
|
|
349
|
+
| `invitations.resend({ path })` | `POST /api/invitations/{id}/resend` | Email the invite link again (needs `invitations:create`) |
|
|
350
|
+
| `invitations.revoke({ path })` | `DELETE /api/invitations/{id}` | Revoke a pending invitation (needs `invitations:delete`) |
|
|
337
351
|
|
|
338
352
|
### Issues
|
|
339
353
|
|
|
@@ -341,8 +355,8 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
341
355
|
|---|---|---|
|
|
342
356
|
| `environments.list({ path })` | `GET /api/projects/{project_id}/environments` | Lists the environments a project's issues have been seen in, by name. |
|
|
343
357
|
| `feedback.list({ path, query? })` | `GET /api/projects/{project_id}/feedback` | Lists user feedback with what each user submitted. |
|
|
344
|
-
| `issues.bulkDelete({ path, body })` | `DELETE /api/projects/{project_id}/issues` |
|
|
345
|
-
| `issues.bulkUpdate({ path, body })` | `PUT /api/projects/{project_id}/issues` |
|
|
358
|
+
| `issues.bulkDelete({ path, body })` | `DELETE /api/projects/{project_id}/issues` | Deletes many issues at once, selected by id or by filter. |
|
|
359
|
+
| `issues.bulkUpdate({ path, body })` | `PUT /api/projects/{project_id}/issues` | Sets the status or priority of many issues at once, by id. |
|
|
346
360
|
| `issues.createComment({ path, body })` | `POST /api/projects/{project_id}/issues/{issue_id}/comments` | Add a note. |
|
|
347
361
|
| `issues.createUserReport({ path, body })` | `POST /api/projects/{project_id}/issues/{issue_id}/user-reports` | Attach user feedback to an issue. |
|
|
348
362
|
| `issues.delete({ path })` | `DELETE /api/projects/{project_id}/issues/{issue_id}` | Hard-deletes an issue and all associated events |
|
|
@@ -371,21 +385,22 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
371
385
|
|
|
372
386
|
| Method | Endpoint | Description |
|
|
373
387
|
|---|---|---|
|
|
374
|
-
| `members.
|
|
375
|
-
| `members.
|
|
376
|
-
| `members.
|
|
388
|
+
| `members.candidates({ path })` | `GET /api/projects/{project_id}/members/candidates` | Lists the people and the roles the caller can give on the project, so it takes neither `users:read` nor `roles:read` to manage its members. |
|
|
389
|
+
| `members.list({ path })` | `GET /api/projects/{project_id}/members` | Lists everyone holding a role on the project, with those roles; personal permissions are not roles. |
|
|
390
|
+
| `members.remove({ path })` | `DELETE /api/projects/{project_id}/members/{user_id}` | Removes the roles a user holds on this project; roles on all projects and personal permissions stay. |
|
|
391
|
+
| `members.upsert({ path, body })` | `PUT /api/projects/{project_id}/members` | Sets the roles a user holds on the project. |
|
|
377
392
|
|
|
378
393
|
### Monitors
|
|
379
394
|
|
|
380
395
|
| Method | Endpoint | Description |
|
|
381
396
|
|---|---|---|
|
|
382
|
-
| `monitors.create({ path, body })` | `POST /api/projects/{project_id}/monitors` |
|
|
383
|
-
| `monitors.delete({ path })` | `DELETE /api/projects/{project_id}/monitors/{slug}` |
|
|
384
|
-
| `monitors.get({ path })` | `GET /api/projects/{project_id}/monitors/{slug}` |
|
|
385
|
-
| `monitors.list({ path })` | `GET /api/projects/{project_id}/monitors` |
|
|
386
|
-
| `monitors.listCheckins({ path, query? })` | `GET /api/projects/{project_id}/monitors/{slug}/checkins` |
|
|
397
|
+
| `monitors.create({ path, body })` | `POST /api/projects/{project_id}/monitors` | Creates a cron monitor in a project. |
|
|
398
|
+
| `monitors.delete({ path })` | `DELETE /api/projects/{project_id}/monitors/{slug}` | Deletes a cron monitor and its check-ins. |
|
|
399
|
+
| `monitors.get({ path })` | `GET /api/projects/{project_id}/monitors/{slug}` | Gets one cron monitor. |
|
|
400
|
+
| `monitors.list({ path })` | `GET /api/projects/{project_id}/monitors` | Lists a project's cron monitors. |
|
|
401
|
+
| `monitors.listCheckins({ path, query? })` | `GET /api/projects/{project_id}/monitors/{slug}/checkins` | Lists a cron monitor's check-ins, newest first. |
|
|
387
402
|
| `monitors.stats({ path, query? })` | `GET /api/projects/{project_id}/monitor-stats` | Counts the check-ins of a project's monitors by status over a window, bucket by bucket. |
|
|
388
|
-
| `monitors.update({ path, body })` | `PUT /api/projects/{project_id}/monitors/{slug}` |
|
|
403
|
+
| `monitors.update({ path, body })` | `PUT /api/projects/{project_id}/monitors/{slug}` | Updates a cron monitor. |
|
|
389
404
|
|
|
390
405
|
### OAuth
|
|
391
406
|
|
|
@@ -404,7 +419,7 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
404
419
|
| `projects.delete({ path })` | `DELETE /api/projects/{id}` | Delete a project |
|
|
405
420
|
| `projects.get({ path })` | `GET /api/projects/{id}` | Get a project by ID |
|
|
406
421
|
| `projects.getRateLimits()` | `GET /api/rate-limits` | What a project without limits of its own follows |
|
|
407
|
-
| `projects.list({ query? })` | `GET /api/projects` | List projects with pagination |
|
|
422
|
+
| `projects.list({ query? })` | `GET /api/projects` | List projects with pagination. |
|
|
408
423
|
| `projects.update({ path, body })` | `PATCH /api/projects/{id}` | Update a project |
|
|
409
424
|
|
|
410
425
|
### Releases
|
|
@@ -415,7 +430,7 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
415
430
|
| `releases.finalize({ path, body })` | `PUT /api/0/projects/{org_slug}/{project_slug}/releases/{version}/` | Generic partial update (`ref`, `url`, `dateReleased`). |
|
|
416
431
|
| `releases.get({ path, query? })` | `GET /api/projects/{project_id}/releases/{release}` | Gets one release with its events, new issues, environments and session health. |
|
|
417
432
|
| `releases.list({ path, query? })` | `GET /api/projects/{project_id}/releases` | Lists a project's releases, newest first, with the events, new issues, environments and session health of each. |
|
|
418
|
-
| `releases.newIssues({ path, query? })` | `GET /api/projects/{project_id}/releases/{release}/new-issues` |
|
|
433
|
+
| `releases.newIssues({ path, query? })` | `GET /api/projects/{project_id}/releases/{release}/new-issues` | Lists the issues first seen in a release. |
|
|
419
434
|
|
|
420
435
|
### Schedules
|
|
421
436
|
|
|
@@ -429,7 +444,7 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
429
444
|
|---|---|---|
|
|
430
445
|
| `sentry.getIssue({ path })` | `GET /api/0/issues/{issue_id}/` | One issue with its releases and its 24h and 30d series (Sentry's `GroupDetailsEndpoint`). |
|
|
431
446
|
| `sentry.getLatestEvent({ path })` | `GET /api/0/issues/{issue_id}/events/latest/` | The issue's most recent event (Sentry's `GroupEventDetailsEndpoint`, `issues/endpoints/group_event_details.py`). |
|
|
432
|
-
| `sentry.listIssues({ path, query? })` | `GET /api/0/projects/{org_slug}/{project_slug}/issues/` |
|
|
447
|
+
| `sentry.listIssues({ path, query? })` | `GET /api/0/projects/{org_slug}/{project_slug}/issues/` | Issues, filtered by `query`, sorted by `sort` and paginated by `cursor` (Sentry's `ProjectGroupIndexEndpoint`, `issues/endpoints/project_group_index.py`). |
|
|
433
448
|
| `sentry.listOrganizations()` | `GET /api/0/organizations/` | The organizations the token belongs to (Sentry's `OrganizationIndexEndpoint`): always the one synthetic org. |
|
|
434
449
|
| `sentry.listProjects({ query? })` | `GET /api/0/projects/` | The projects the token can see, newest first (Sentry's `ProjectIndexEndpoint`, `core/endpoints/project_index.py`). |
|
|
435
450
|
| `sentry.listRepos({ path })` | `GET /api/0/organizations/{org_slug}/repos/` | The code repositories connected to the organization (Sentry's `OrganizationRepositoriesEndpoint`). |
|
|
@@ -441,16 +456,16 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
441
456
|
|
|
442
457
|
| Method | Endpoint | Description |
|
|
443
458
|
|---|---|---|
|
|
444
|
-
| `sessions.getStats({ path, query? })` | `GET /api/projects/{project_id}/sessions/stats` |
|
|
445
|
-
| `sessions.getSummary({ path, query? })` | `GET /api/projects/{project_id}/sessions/summary` |
|
|
446
|
-
| `sessions.getTimeseries({ path, query? })` | `GET /api/projects/{project_id}/sessions/timeseries` |
|
|
459
|
+
| `sessions.getStats({ path, query? })` | `GET /api/projects/{project_id}/sessions/stats` | Session counts by release, for release health. |
|
|
460
|
+
| `sessions.getSummary({ path, query? })` | `GET /api/projects/{project_id}/sessions/summary` | Totals and crash-free rates for a project's sessions. |
|
|
461
|
+
| `sessions.getTimeseries({ path, query? })` | `GET /api/projects/{project_id}/sessions/timeseries` | Session counts over time, bucketed for a chart. |
|
|
447
462
|
|
|
448
463
|
### Settings
|
|
449
464
|
|
|
450
465
|
| Method | Endpoint | Description |
|
|
451
466
|
|---|---|---|
|
|
452
467
|
| `settings.getMcp()` | `GET /api/settings/mcp` | Whether the MCP endpoint at `/mcp` is on. |
|
|
453
|
-
| `settings.updateMcp({ body })` | `PUT /api/settings/mcp` | Turns the MCP endpoint at `/mcp` on or off. |
|
|
468
|
+
| `settings.updateMcp({ body })` | `PUT /api/settings/mcp` | Turns the MCP endpoint at `/mcp` on or off (needs `mcp:update`). |
|
|
454
469
|
|
|
455
470
|
### Source Maps
|
|
456
471
|
|
|
@@ -458,10 +473,10 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
458
473
|
|---|---|---|
|
|
459
474
|
| `debugFiles.assemble({ path, body })` | `POST /api/0/projects/{org_slug}/{project_slug}/files/difs/assemble/` | Assemble uploaded chunks into debug information files (ProGuard mappings, JVM source bundles). |
|
|
460
475
|
| `debugFiles.upload({ path, body })` | `POST /api/0/projects/{org_slug}/{project_slug}/files/dsyms/` | Upload a zip of debug information files (the path `sentry-cli upload-proguard` takes). |
|
|
461
|
-
| `sourceMaps.artifactBundleAssemble({ path, body })` | `POST /api/0/organizations/{org_slug}/artifactbundle/assemble/` |
|
|
462
|
-
| `sourceMaps.chunkUpload({ path, body })` | `POST /api/0/organizations/{org_slug}/chunk-upload/` |
|
|
463
|
-
| `sourceMaps.chunkUploadCapability({ path })` | `GET /api/0/organizations/{org_slug}/chunk-upload/` |
|
|
464
|
-
| `sourceMaps.list({ path })` | `GET /api/0/projects/{org_slug}/{project_slug}/files/source-maps/` |
|
|
476
|
+
| `sourceMaps.artifactBundleAssemble({ path, body })` | `POST /api/0/organizations/{org_slug}/artifactbundle/assemble/` | Assembles uploaded chunks into an artifact bundle (sentry-cli `sourcemaps upload`). |
|
|
477
|
+
| `sourceMaps.chunkUpload({ path, body })` | `POST /api/0/organizations/{org_slug}/chunk-upload/` | Receives chunks of a source map or debug file upload from sentry-cli. |
|
|
478
|
+
| `sourceMaps.chunkUploadCapability({ path })` | `GET /api/0/organizations/{org_slug}/chunk-upload/` | Describes how sentry-cli should upload chunks: size, concurrency and accepted kinds. |
|
|
479
|
+
| `sourceMaps.list({ path })` | `GET /api/0/projects/{org_slug}/{project_slug}/files/source-maps/` | Lists a project's uploaded source map artifacts (sentry-cli). |
|
|
465
480
|
| `sourceMaps.orgDetails({ path })` | `GET /api/0/organizations/{org_slug}/` | Always returns 200 with synthetic org data — sentry-cli validates this before uploading. |
|
|
466
481
|
|
|
467
482
|
### Spans
|
|
@@ -475,8 +490,8 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
475
490
|
|
|
476
491
|
| Method | Endpoint | Description |
|
|
477
492
|
|---|---|---|
|
|
478
|
-
| `stats.getEventTimeseries({ path, query? })` | `GET /api/projects/{project_id}/events/stats` |
|
|
479
|
-
| `stats.getSummary({ path, query? })` | `GET /api/projects/{project_id}/stats/summary` |
|
|
493
|
+
| `stats.getEventTimeseries({ path, query? })` | `GET /api/projects/{project_id}/events/stats` | Counts a project's events over time, bucketed for a chart. |
|
|
494
|
+
| `stats.getSummary({ path, query? })` | `GET /api/projects/{project_id}/stats/summary` | Headline figures for a project's overview: events, new and open issues. |
|
|
480
495
|
|
|
481
496
|
### Storage
|
|
482
497
|
|
|
@@ -489,35 +504,35 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
|
|
|
489
504
|
| `storage.getCleanupStatus()` | `GET /api/storage/cleanup/status` | Progress of the running cleanup, or the outcome of the last one. |
|
|
490
505
|
| `storage.getCompaction()` | `GET /api/storage/compaction` | Whether the database file shrinks when data is deleted, and the disk a one-off compaction needs. |
|
|
491
506
|
| `storage.getProjects()` | `GET /api/storage/projects` | Per-project counts and estimated weight. |
|
|
492
|
-
| `storage.getRetention()` | `GET /api/storage/retention` |
|
|
507
|
+
| `storage.getRetention()` | `GET /api/storage/retention` | Gets the retention settings and the cleanup schedule. |
|
|
493
508
|
| `storage.getSummary()` | `GET /api/storage/summary` | Row counts, DB size, and source-map weight. |
|
|
494
509
|
| `storage.previewCleanup({ body })` | `POST /api/storage/cleanup/preview` | Dry-run count, mutates nothing. |
|
|
495
510
|
| `storage.previewRetention({ body })` | `POST /api/storage/retention/preview` | What saving these settings would delete on the next cleanup, without saving or deleting anything. |
|
|
496
511
|
| `storage.previewSourceMapGc()` | `POST /api/storage/source-maps/gc/preview` | Dry-run orphan count, deletes nothing. |
|
|
497
512
|
| `storage.runRetention()` | `POST /api/storage/retention/run` | Enforces the saved retention now, without waiting for the schedule. |
|
|
498
|
-
| `storage.updateRetention({ body })` | `PUT /api/storage/retention` |
|
|
513
|
+
| `storage.updateRetention({ body })` | `PUT /api/storage/retention` | Updates the retention settings; the next cleanup is scheduled at once. |
|
|
499
514
|
|
|
500
515
|
### Team
|
|
501
516
|
|
|
502
517
|
| Method | Endpoint | Description |
|
|
503
518
|
|---|---|---|
|
|
504
|
-
| `team.deleteUser({ path })` | `DELETE /api/team/{user_id}` | Remove a user from the instance (
|
|
505
|
-
| `team.list()` | `GET /api/team` | List all users (
|
|
506
|
-
| `team.updateRole({ path, body })` | `PATCH /api/team/{user_id}/role` | Change a user's global role (
|
|
519
|
+
| `team.deleteUser({ path })` | `DELETE /api/team/{user_id}` | Remove a user from the instance (needs `users:delete`) |
|
|
520
|
+
| `team.list()` | `GET /api/team` | List all users (needs `users:read`) |
|
|
521
|
+
| `team.updateRole({ path, body })` | `PATCH /api/team/{user_id}/role` | Change a user's global role (needs `users:update`) |
|
|
507
522
|
|
|
508
523
|
### Telemetry
|
|
509
524
|
|
|
510
525
|
| Method | Endpoint | Description |
|
|
511
526
|
|---|---|---|
|
|
512
|
-
| `telemetry.preview()` | `GET /api/telemetry/preview` |
|
|
527
|
+
| `telemetry.preview()` | `GET /api/telemetry/preview` | Shows the exact anonymous telemetry report this instance would send. |
|
|
513
528
|
|
|
514
529
|
### Tokens
|
|
515
530
|
|
|
516
531
|
| Method | Endpoint | Description |
|
|
517
532
|
|---|---|---|
|
|
518
|
-
| `tokens.create({ body })` | `POST /api/tokens` | Create a new token (
|
|
533
|
+
| `tokens.create({ body })` | `POST /api/tokens` | Create a new token (from a signed-in session only) |
|
|
519
534
|
| `tokens.delete({ path })` | `DELETE /api/tokens/{id}` | Revoke a token |
|
|
520
|
-
| `tokens.get({ path })` | `GET /api/tokens/{id}` |
|
|
535
|
+
| `tokens.get({ path })` | `GET /api/tokens/{id}` | Token details, masked |
|
|
521
536
|
| `tokens.list()` | `GET /api/tokens` | List tokens (masked) |
|
|
522
537
|
|
|
523
538
|
### Transactions
|
package/dist/client.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_binary_gen = require("./generated/binary.gen.cjs");
|
|
1
2
|
const require_utils_gen = require("./generated/client/utils.gen.cjs");
|
|
2
3
|
const require_client_gen = require("./generated/client/client.gen.cjs");
|
|
3
4
|
const require_sdk_gen = require("./generated/sdk.gen.cjs");
|
|
@@ -5,7 +6,7 @@ const require_result = require("./result.cjs");
|
|
|
5
6
|
const require_http = require("./utils/http.cjs");
|
|
6
7
|
let zod = require("zod");
|
|
7
8
|
// src/client.ts
|
|
8
|
-
const
|
|
9
|
+
const BINARY_OPERATIONS = new Set(require_binary_gen.BINARY);
|
|
9
10
|
/**
|
|
10
11
|
* Main Rustrak API client. Every method returns a `Result`; nothing throws for
|
|
11
12
|
* an expected failure.
|
|
@@ -48,7 +49,7 @@ function createApi(config) {
|
|
|
48
49
|
methods[method] = async (options = {}) => toResult(await resource[method]({
|
|
49
50
|
...options,
|
|
50
51
|
headers: options.headers instanceof Headers || Array.isArray(options.headers) ? Object.fromEntries(new Headers(options.headers)) : options.headers,
|
|
51
|
-
...
|
|
52
|
+
...BINARY_OPERATIONS.has(`${name}.${method}`) && { parseAs: "blob" },
|
|
52
53
|
throwOnError: false
|
|
53
54
|
}));
|
|
54
55
|
}
|
|
@@ -66,7 +67,7 @@ function createApi(config) {
|
|
|
66
67
|
*/
|
|
67
68
|
function toResult({ data, error, response }) {
|
|
68
69
|
if (error === void 0) return require_result.Ok(data);
|
|
69
|
-
if (require_http.
|
|
70
|
+
if (error instanceof require_http.RustrakTransportFailure) return require_result.Err(error.rustrakError);
|
|
70
71
|
if (response && !response.ok) return require_result.Err(require_http.transformHttpError(response, error));
|
|
71
72
|
if (!response && error instanceof zod.ZodError) return require_result.Err({
|
|
72
73
|
kind: "invalid_request",
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.cjs","names":["Rustrak","createClient","createConfig","createFetch","Ok","
|
|
1
|
+
{"version":3,"file":"client.cjs","names":["BINARY","Rustrak","createClient","createConfig","createFetch","Ok","RustrakTransportFailure","Err","transformHttpError","ZodError"],"sources":["../src/client.ts"],"sourcesContent":["import { ZodError } from 'zod';\nimport type { ClientConfig } from './config.js';\nimport type { RustrakError } from './errors.js';\nimport { BINARY } from './generated/binary.gen.js';\nimport { createClient, createConfig } from './generated/client/index.js';\nimport { Rustrak } from './generated/sdk.gen.js';\nimport { Err, Ok, type Result } from './result.js';\nimport {\n createFetch,\n RustrakTransportFailure,\n transformHttpError,\n} from './utils/http.js';\n\n/**\n * Operations whose 2xx is a file, read as a `Blob`. The spec leaves the body\n * untyped (zod has no binary type), so the type comes from this list.\n */\ntype Binary = (typeof BINARY)[number];\nconst BINARY_OPERATIONS: ReadonlySet<string> = new Set(BINARY);\n\n/** What a caller may pass: the request's own parts, never client plumbing. */\ntype RequestKeys = 'path' | 'query' | 'body' | 'headers' | 'signal';\n\ntype Call<F, Bytes extends boolean> = F extends (options: infer O) => infer R\n ? (\n ...args: {} extends Pick<O, Extract<keyof O, RequestKeys>>\n ? [options?: Pick<O, Extract<keyof O, RequestKeys>>]\n : [options: Pick<O, Extract<keyof O, RequestKeys>>]\n ) => Promise<\n Result<Bytes extends true ? Blob : Data<Awaited<R>>, RustrakError>\n >\n : never;\n\n/** The success half of the generated `{ data, error }` union. */\ntype Data<R> =\n Extract<R, { error: undefined }> extends { data: infer D } ? D : never;\n\ntype Resource<T, Name extends string> = {\n readonly [M in keyof T]: Call<\n T[M],\n `${Name}.${M & string}` extends Binary ? true : false\n >;\n};\n\n/**\n * Every operation in `openapi.json`, grouped by tag:\n * `client.issues.list({ path: { project_id } })`.\n *\n * Generated in `src/generated/`; this file only changes what a call returns.\n */\nexport type RustrakClient = {\n readonly [R in keyof Rustrak]: Resource<Rustrak[R], R & string>;\n};\n\n/**\n * Main Rustrak API client. Every method returns a `Result`; nothing throws for\n * an expected failure.\n *\n * @example\n * ```typescript\n * const client = new RustrakClient({\n * baseUrl: 'http://localhost:8080',\n * token: 'your-api-token',\n * });\n *\n * const issues = await client.issues.list({ path: { project_id: 1 } });\n * if (issues.success) console.log(issues.data.items);\n * ```\n */\nexport const RustrakClient = class {\n constructor(config: ClientConfig) {\n // biome-ignore lint/correctness/noConstructorReturn: the instance is the generated SDK with every method wrapped\n return Object.setPrototypeOf(createApi(config), new.target.prototype);\n }\n} as unknown as new (\n config: ClientConfig,\n) => RustrakClient;\n\nfunction createApi(config: ClientConfig): RustrakClient {\n const sdk = new Rustrak({\n client: createClient(\n createConfig({\n baseUrl: config.baseUrl,\n credentials: 'include',\n fetch: createFetch(config),\n // Every 2xx in the spec is JSON or empty, except the files in\n // `BINARY`. `auto` would hand back an HTML page or a stream as a\n // success without validating it.\n parseAs: 'json',\n headers: {\n // Without it a content-negotiating hop can answer with HTML.\n Accept: 'application/json',\n ...config.headers,\n ...(config.token && { Authorization: `Bearer ${config.token}` }),\n },\n }),\n ),\n });\n\n const api: Record<string, Record<string, unknown>> = {};\n for (const name of Object.getOwnPropertyNames(Rustrak.prototype)) {\n if (name === 'constructor') continue;\n const resource = sdk[name as keyof Rustrak] as unknown as Record<\n string,\n (options: object) => Promise<Outcome>\n >;\n const methods: Record<string, unknown> = {};\n for (const method of Object.getOwnPropertyNames(\n Object.getPrototypeOf(resource),\n )) {\n if (method === 'constructor') continue;\n methods[method] = async (options: { headers?: unknown } = {}) =>\n toResult(\n await resource[method]!({\n ...options,\n // A JSON write spreads these into an object, which keeps nothing\n // of a `Headers` or an array of pairs.\n headers:\n options.headers instanceof Headers ||\n Array.isArray(options.headers)\n ? Object.fromEntries(new Headers(options.headers))\n : options.headers,\n ...(BINARY_OPERATIONS.has(`${name}.${method}`) && {\n parseAs: 'blob',\n }),\n throwOnError: false,\n }),\n );\n }\n api[name] = methods;\n }\n return api as unknown as RustrakClient;\n}\n\ntype Outcome = {\n data?: unknown;\n error?: unknown;\n response?: Response;\n};\n\n/**\n * The boundary: the generated client's `{ data, error, response }` becomes a\n * `Result`.\n *\n * Only failures this file recognises become an `Err`. Anything else, a\n * `TypeError` from a genuine bug, is rethrown so it crashes where it can be\n * debugged instead of being laundered into `{ success: false }`.\n */\nfunction toResult({\n data,\n error,\n response,\n}: Outcome): Result<unknown, RustrakError> {\n if (error === undefined) return Ok(data);\n if (error instanceof RustrakTransportFailure) return Err(error.rustrakError);\n if (response && !response.ok) {\n // `error` is the parsed body, or its text when it is not JSON.\n return Err(transformHttpError(response, error));\n }\n if (!response && error instanceof ZodError) {\n return Err({\n kind: 'invalid_request',\n message: 'The request input did not match the expected schema.',\n });\n }\n if (response && error instanceof SyntaxError) {\n return Err({\n kind: 'invalid_response',\n message: 'The server returned a body that is not valid JSON.',\n });\n }\n if (response && error instanceof ZodError) {\n // No Zod issues: they embed the offending response data.\n return Err({\n kind: 'invalid_response',\n message: 'The server response did not match the expected schema.',\n });\n }\n throw error;\n}\n"],"mappings":";;;;;;;;AAkBA,MAAM,oBAAyC,IAAI,IAAIA,mBAAAA,MAAM;;;;;;;;;;;;;;;;AAmD7D,MAAa,gBAAgB,MAAM;CACjC,YAAY,QAAsB;EAEhC,OAAO,OAAO,eAAe,UAAU,MAAM,GAAG,WAAW,SAAS;CACtE;AACF;AAIA,SAAS,UAAU,QAAqC;CACtD,MAAM,MAAM,IAAIC,gBAAAA,QAAQ,EACtB,QAAQC,mBAAAA,aACNC,kBAAAA,aAAa;EACX,SAAS,OAAO;EAChB,aAAa;EACb,OAAOC,aAAAA,YAAY,MAAM;EAIzB,SAAS;EACT,SAAS;GAEP,QAAQ;GACR,GAAG,OAAO;GACV,GAAI,OAAO,SAAS,EAAE,eAAe,UAAU,OAAO,QAAQ;EAChE;CACF,CAAC,CACH,EACF,CAAC;CAED,MAAM,MAA+C,CAAC;CACtD,KAAK,MAAM,QAAQ,OAAO,oBAAoBH,gBAAAA,QAAQ,SAAS,GAAG;EAChE,IAAI,SAAS,eAAe;EAC5B,MAAM,WAAW,IAAI;EAIrB,MAAM,UAAmC,CAAC;EAC1C,KAAK,MAAM,UAAU,OAAO,oBAC1B,OAAO,eAAe,QAAQ,CAChC,GAAG;GACD,IAAI,WAAW,eAAe;GAC9B,QAAQ,UAAU,OAAO,UAAiC,CAAC,MACzD,SACE,MAAM,SAAS,OAAO,CAAE;IACtB,GAAG;IAGH,SACE,QAAQ,mBAAmB,WAC3B,MAAM,QAAQ,QAAQ,OAAO,IACzB,OAAO,YAAY,IAAI,QAAQ,QAAQ,OAAO,CAAC,IAC/C,QAAQ;IACd,GAAI,kBAAkB,IAAI,GAAG,KAAK,GAAG,QAAQ,KAAK,EAChD,SAAS,OACX;IACA,cAAc;GAChB,CAAC,CACH;EACJ;EACA,IAAI,QAAQ;CACd;CACA,OAAO;AACT;;;;;;;;;AAgBA,SAAS,SAAS,EAChB,MACA,OACA,YACyC;CACzC,IAAI,UAAU,KAAA,GAAW,OAAOI,eAAAA,GAAG,IAAI;CACvC,IAAI,iBAAiBC,aAAAA,yBAAyB,OAAOC,eAAAA,IAAI,MAAM,YAAY;CAC3E,IAAI,YAAY,CAAC,SAAS,IAExB,OAAOA,eAAAA,IAAIC,aAAAA,mBAAmB,UAAU,KAAK,CAAC;CAEhD,IAAI,CAAC,YAAY,iBAAiBC,IAAAA,UAChC,OAAOF,eAAAA,IAAI;EACT,MAAM;EACN,SAAS;CACX,CAAC;CAEH,IAAI,YAAY,iBAAiB,aAC/B,OAAOA,eAAAA,IAAI;EACT,MAAM;EACN,SAAS;CACX,CAAC;CAEH,IAAI,YAAY,iBAAiBE,IAAAA,UAE/B,OAAOF,eAAAA,IAAI;EACT,MAAM;EACN,SAAS;CACX,CAAC;CAEH,MAAM;AACR"}
|
package/dist/client.d.cts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ClientConfig } from "./config.cjs";
|
|
2
2
|
import { RustrakError } from "./errors.cjs";
|
|
3
|
+
import { BINARY } from "./generated/binary.gen.cjs";
|
|
3
4
|
import { Rustrak } from "./generated/sdk.gen.cjs";
|
|
4
5
|
import { Result } from "./result.cjs";
|
|
5
|
-
type Binary =
|
|
6
|
+
type Binary = (typeof BINARY)[number];
|
|
6
7
|
type RequestKeys = 'path' | 'query' | 'body' | 'headers' | 'signal';
|
|
7
8
|
type Call<F, Bytes extends boolean> = F extends ((options: infer O) => infer R) ? (...args: {} extends Pick<O, Extract<keyof O, RequestKeys>> ? [options?: Pick<O, Extract<keyof O, RequestKeys>>] : [options: Pick<O, Extract<keyof O, RequestKeys>>]) => Promise<Result<Bytes extends true ? Blob : Data<Awaited<R>>, RustrakError>> : never;
|
|
8
9
|
type Data<R> = Extract<R, {
|
package/dist/client.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.cts","names":[],"sources":["../src/client.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.cts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KAiBK,iBAAiB;KAIjB;KAEA,KAAK,GAAG,yBAAyB,YAAW,eAAe,YAAY,SAEnE,iBAAiB,KAAK,GAAG,cAAc,GAAG,iBACxC,UAAU,KAAK,GAAG,cAAc,GAAG,kBACnC,SAAS,KAAK,GAAG,cAAc,GAAG,mBACpC,QACH,OAAO,qBAAqB,OAAO,KAAK,QAAQ,KAAK;KAKtD,KAAK,KACR,QAAQ;EAAK;;EAA8B,YAAY;IAAM;KAE1D,SAAS,GAAG,mCACL,WAAW,IAAI,KACvB,EAAE,OACC,QAAQ,qBAAqB;YAUxB,4BACA,WAAW,UAAU,SAAS,QAAQ,IAAI;qBAkBzC,oBAMX,QAAQ,iBACL"}
|
package/dist/client.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ClientConfig } from "./config.mjs";
|
|
2
2
|
import { RustrakError } from "./errors.mjs";
|
|
3
|
+
import { BINARY } from "./generated/binary.gen.mjs";
|
|
3
4
|
import { Rustrak } from "./generated/sdk.gen.mjs";
|
|
4
5
|
import { Result } from "./result.mjs";
|
|
5
|
-
type Binary =
|
|
6
|
+
type Binary = (typeof BINARY)[number];
|
|
6
7
|
type RequestKeys = 'path' | 'query' | 'body' | 'headers' | 'signal';
|
|
7
8
|
type Call<F, Bytes extends boolean> = F extends ((options: infer O) => infer R) ? (...args: {} extends Pick<O, Extract<keyof O, RequestKeys>> ? [options?: Pick<O, Extract<keyof O, RequestKeys>>] : [options: Pick<O, Extract<keyof O, RequestKeys>>]) => Promise<Result<Bytes extends true ? Blob : Data<Awaited<R>>, RustrakError>> : never;
|
|
8
9
|
type Data<R> = Extract<R, {
|
package/dist/client.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KAiBK,iBAAiB;KAIjB;KAEA,KAAK,GAAG,yBAAyB,YAAW,eAAe,YAAY,SAEnE,iBAAiB,KAAK,GAAG,cAAc,GAAG,iBACxC,UAAU,KAAK,GAAG,cAAc,GAAG,kBACnC,SAAS,KAAK,GAAG,cAAc,GAAG,mBACpC,QACH,OAAO,qBAAqB,OAAO,KAAK,QAAQ,KAAK;KAKtD,KAAK,KACR,QAAQ;EAAK;;EAA8B,YAAY;IAAM;KAE1D,SAAS,GAAG,mCACL,WAAW,IAAI,KACvB,EAAE,OACC,QAAQ,qBAAqB;YAUxB,4BACA,WAAW,UAAU,SAAS,QAAQ,IAAI;qBAkBzC,oBAMX,QAAQ,iBACL"}
|
package/dist/client.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { BINARY } from "./generated/binary.gen.mjs";
|
|
1
2
|
import { createConfig } from "./generated/client/utils.gen.mjs";
|
|
2
3
|
import { createClient } from "./generated/client/client.gen.mjs";
|
|
3
4
|
import { Rustrak } from "./generated/sdk.gen.mjs";
|
|
4
5
|
import { Err, Ok } from "./result.mjs";
|
|
5
|
-
import {
|
|
6
|
+
import { RustrakTransportFailure, createFetch, transformHttpError } from "./utils/http.mjs";
|
|
6
7
|
import { ZodError } from "zod";
|
|
7
8
|
// src/client.ts
|
|
8
|
-
const
|
|
9
|
+
const BINARY_OPERATIONS = new Set(BINARY);
|
|
9
10
|
/**
|
|
10
11
|
* Main Rustrak API client. Every method returns a `Result`; nothing throws for
|
|
11
12
|
* an expected failure.
|
|
@@ -48,7 +49,7 @@ function createApi(config) {
|
|
|
48
49
|
methods[method] = async (options = {}) => toResult(await resource[method]({
|
|
49
50
|
...options,
|
|
50
51
|
headers: options.headers instanceof Headers || Array.isArray(options.headers) ? Object.fromEntries(new Headers(options.headers)) : options.headers,
|
|
51
|
-
...
|
|
52
|
+
...BINARY_OPERATIONS.has(`${name}.${method}`) && { parseAs: "blob" },
|
|
52
53
|
throwOnError: false
|
|
53
54
|
}));
|
|
54
55
|
}
|
|
@@ -66,7 +67,7 @@ function createApi(config) {
|
|
|
66
67
|
*/
|
|
67
68
|
function toResult({ data, error, response }) {
|
|
68
69
|
if (error === void 0) return Ok(data);
|
|
69
|
-
if (
|
|
70
|
+
if (error instanceof RustrakTransportFailure) return Err(error.rustrakError);
|
|
70
71
|
if (response && !response.ok) return Err(transformHttpError(response, error));
|
|
71
72
|
if (!response && error instanceof ZodError) return Err({
|
|
72
73
|
kind: "invalid_request",
|
package/dist/client.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import { ZodError } from 'zod';\nimport type { ClientConfig } from './config.js';\nimport type { RustrakError } from './errors.js';\nimport { createClient, createConfig } from './generated/client/index.js';\nimport { Rustrak } from './generated/sdk.gen.js';\nimport { Err, Ok, type Result } from './result.js';\nimport {\n createFetch,\n
|
|
1
|
+
{"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import { ZodError } from 'zod';\nimport type { ClientConfig } from './config.js';\nimport type { RustrakError } from './errors.js';\nimport { BINARY } from './generated/binary.gen.js';\nimport { createClient, createConfig } from './generated/client/index.js';\nimport { Rustrak } from './generated/sdk.gen.js';\nimport { Err, Ok, type Result } from './result.js';\nimport {\n createFetch,\n RustrakTransportFailure,\n transformHttpError,\n} from './utils/http.js';\n\n/**\n * Operations whose 2xx is a file, read as a `Blob`. The spec leaves the body\n * untyped (zod has no binary type), so the type comes from this list.\n */\ntype Binary = (typeof BINARY)[number];\nconst BINARY_OPERATIONS: ReadonlySet<string> = new Set(BINARY);\n\n/** What a caller may pass: the request's own parts, never client plumbing. */\ntype RequestKeys = 'path' | 'query' | 'body' | 'headers' | 'signal';\n\ntype Call<F, Bytes extends boolean> = F extends (options: infer O) => infer R\n ? (\n ...args: {} extends Pick<O, Extract<keyof O, RequestKeys>>\n ? [options?: Pick<O, Extract<keyof O, RequestKeys>>]\n : [options: Pick<O, Extract<keyof O, RequestKeys>>]\n ) => Promise<\n Result<Bytes extends true ? Blob : Data<Awaited<R>>, RustrakError>\n >\n : never;\n\n/** The success half of the generated `{ data, error }` union. */\ntype Data<R> =\n Extract<R, { error: undefined }> extends { data: infer D } ? D : never;\n\ntype Resource<T, Name extends string> = {\n readonly [M in keyof T]: Call<\n T[M],\n `${Name}.${M & string}` extends Binary ? true : false\n >;\n};\n\n/**\n * Every operation in `openapi.json`, grouped by tag:\n * `client.issues.list({ path: { project_id } })`.\n *\n * Generated in `src/generated/`; this file only changes what a call returns.\n */\nexport type RustrakClient = {\n readonly [R in keyof Rustrak]: Resource<Rustrak[R], R & string>;\n};\n\n/**\n * Main Rustrak API client. Every method returns a `Result`; nothing throws for\n * an expected failure.\n *\n * @example\n * ```typescript\n * const client = new RustrakClient({\n * baseUrl: 'http://localhost:8080',\n * token: 'your-api-token',\n * });\n *\n * const issues = await client.issues.list({ path: { project_id: 1 } });\n * if (issues.success) console.log(issues.data.items);\n * ```\n */\nexport const RustrakClient = class {\n constructor(config: ClientConfig) {\n // biome-ignore lint/correctness/noConstructorReturn: the instance is the generated SDK with every method wrapped\n return Object.setPrototypeOf(createApi(config), new.target.prototype);\n }\n} as unknown as new (\n config: ClientConfig,\n) => RustrakClient;\n\nfunction createApi(config: ClientConfig): RustrakClient {\n const sdk = new Rustrak({\n client: createClient(\n createConfig({\n baseUrl: config.baseUrl,\n credentials: 'include',\n fetch: createFetch(config),\n // Every 2xx in the spec is JSON or empty, except the files in\n // `BINARY`. `auto` would hand back an HTML page or a stream as a\n // success without validating it.\n parseAs: 'json',\n headers: {\n // Without it a content-negotiating hop can answer with HTML.\n Accept: 'application/json',\n ...config.headers,\n ...(config.token && { Authorization: `Bearer ${config.token}` }),\n },\n }),\n ),\n });\n\n const api: Record<string, Record<string, unknown>> = {};\n for (const name of Object.getOwnPropertyNames(Rustrak.prototype)) {\n if (name === 'constructor') continue;\n const resource = sdk[name as keyof Rustrak] as unknown as Record<\n string,\n (options: object) => Promise<Outcome>\n >;\n const methods: Record<string, unknown> = {};\n for (const method of Object.getOwnPropertyNames(\n Object.getPrototypeOf(resource),\n )) {\n if (method === 'constructor') continue;\n methods[method] = async (options: { headers?: unknown } = {}) =>\n toResult(\n await resource[method]!({\n ...options,\n // A JSON write spreads these into an object, which keeps nothing\n // of a `Headers` or an array of pairs.\n headers:\n options.headers instanceof Headers ||\n Array.isArray(options.headers)\n ? Object.fromEntries(new Headers(options.headers))\n : options.headers,\n ...(BINARY_OPERATIONS.has(`${name}.${method}`) && {\n parseAs: 'blob',\n }),\n throwOnError: false,\n }),\n );\n }\n api[name] = methods;\n }\n return api as unknown as RustrakClient;\n}\n\ntype Outcome = {\n data?: unknown;\n error?: unknown;\n response?: Response;\n};\n\n/**\n * The boundary: the generated client's `{ data, error, response }` becomes a\n * `Result`.\n *\n * Only failures this file recognises become an `Err`. Anything else, a\n * `TypeError` from a genuine bug, is rethrown so it crashes where it can be\n * debugged instead of being laundered into `{ success: false }`.\n */\nfunction toResult({\n data,\n error,\n response,\n}: Outcome): Result<unknown, RustrakError> {\n if (error === undefined) return Ok(data);\n if (error instanceof RustrakTransportFailure) return Err(error.rustrakError);\n if (response && !response.ok) {\n // `error` is the parsed body, or its text when it is not JSON.\n return Err(transformHttpError(response, error));\n }\n if (!response && error instanceof ZodError) {\n return Err({\n kind: 'invalid_request',\n message: 'The request input did not match the expected schema.',\n });\n }\n if (response && error instanceof SyntaxError) {\n return Err({\n kind: 'invalid_response',\n message: 'The server returned a body that is not valid JSON.',\n });\n }\n if (response && error instanceof ZodError) {\n // No Zod issues: they embed the offending response data.\n return Err({\n kind: 'invalid_response',\n message: 'The server response did not match the expected schema.',\n });\n }\n throw error;\n}\n"],"mappings":";;;;;;;;AAkBA,MAAM,oBAAyC,IAAI,IAAI,MAAM;;;;;;;;;;;;;;;;AAmD7D,MAAa,gBAAgB,MAAM;CACjC,YAAY,QAAsB;EAEhC,OAAO,OAAO,eAAe,UAAU,MAAM,GAAG,WAAW,SAAS;CACtE;AACF;AAIA,SAAS,UAAU,QAAqC;CACtD,MAAM,MAAM,IAAI,QAAQ,EACtB,QAAQ,aACN,aAAa;EACX,SAAS,OAAO;EAChB,aAAa;EACb,OAAO,YAAY,MAAM;EAIzB,SAAS;EACT,SAAS;GAEP,QAAQ;GACR,GAAG,OAAO;GACV,GAAI,OAAO,SAAS,EAAE,eAAe,UAAU,OAAO,QAAQ;EAChE;CACF,CAAC,CACH,EACF,CAAC;CAED,MAAM,MAA+C,CAAC;CACtD,KAAK,MAAM,QAAQ,OAAO,oBAAoB,QAAQ,SAAS,GAAG;EAChE,IAAI,SAAS,eAAe;EAC5B,MAAM,WAAW,IAAI;EAIrB,MAAM,UAAmC,CAAC;EAC1C,KAAK,MAAM,UAAU,OAAO,oBAC1B,OAAO,eAAe,QAAQ,CAChC,GAAG;GACD,IAAI,WAAW,eAAe;GAC9B,QAAQ,UAAU,OAAO,UAAiC,CAAC,MACzD,SACE,MAAM,SAAS,OAAO,CAAE;IACtB,GAAG;IAGH,SACE,QAAQ,mBAAmB,WAC3B,MAAM,QAAQ,QAAQ,OAAO,IACzB,OAAO,YAAY,IAAI,QAAQ,QAAQ,OAAO,CAAC,IAC/C,QAAQ;IACd,GAAI,kBAAkB,IAAI,GAAG,KAAK,GAAG,QAAQ,KAAK,EAChD,SAAS,OACX;IACA,cAAc;GAChB,CAAC,CACH;EACJ;EACA,IAAI,QAAQ;CACd;CACA,OAAO;AACT;;;;;;;;;AAgBA,SAAS,SAAS,EAChB,MACA,OACA,YACyC;CACzC,IAAI,UAAU,KAAA,GAAW,OAAO,GAAG,IAAI;CACvC,IAAI,iBAAiB,yBAAyB,OAAO,IAAI,MAAM,YAAY;CAC3E,IAAI,YAAY,CAAC,SAAS,IAExB,OAAO,IAAI,mBAAmB,UAAU,KAAK,CAAC;CAEhD,IAAI,CAAC,YAAY,iBAAiB,UAChC,OAAO,IAAI;EACT,MAAM;EACN,SAAS;CACX,CAAC;CAEH,IAAI,YAAY,iBAAiB,aAC/B,OAAO,IAAI;EACT,MAAM;EACN,SAAS;CACX,CAAC;CAEH,IAAI,YAAY,iBAAiB,UAE/B,OAAO,IAAI;EACT,MAAM;EACN,SAAS;CACX,CAAC;CAEH,MAAM;AACR"}
|
package/dist/config.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.cts","names":[],"sources":["../src/config.ts"],"mappings":"A,
|
|
1
|
+
{"version":3,"file":"config.d.cts","names":[],"sources":["../src/config.ts"],"mappings":"A,iBAAiB;EAEf;EAGA;EAMA;EAMA;EAEA,UAAU"}
|
package/dist/config.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.mts","names":[],"sources":["../src/config.ts"],"mappings":"A,
|
|
1
|
+
{"version":3,"file":"config.d.mts","names":[],"sources":["../src/config.ts"],"mappings":"A,iBAAiB;EAEf;EAGA;EAMA;EAMA;EAEA,UAAU"}
|
package/dist/errors.cjs
CHANGED
|
@@ -16,6 +16,7 @@ const FIELD_ERROR_CODES = [
|
|
|
16
16
|
"already_exists",
|
|
17
17
|
"too_short",
|
|
18
18
|
"too_long",
|
|
19
|
+
"incorrect",
|
|
19
20
|
"custom"
|
|
20
21
|
];
|
|
21
22
|
/**
|
|
@@ -33,19 +34,31 @@ const NETWORK_ERROR_MESSAGE = "The request could not reach the server.";
|
|
|
33
34
|
/** The fixed message a `network` error carries when the client timed out. */
|
|
34
35
|
const TIMEOUT_ERROR_MESSAGE = "The request timed out.";
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
* Statuses where the same request may well succeed a moment later. The one
|
|
38
|
+
* rule behind {@link isRetryable} and the transport's automatic retries.
|
|
39
|
+
*/
|
|
40
|
+
const TRANSIENT_STATUSES = /* @__PURE__ */ new Set([
|
|
41
|
+
408,
|
|
42
|
+
429,
|
|
43
|
+
500,
|
|
44
|
+
502,
|
|
45
|
+
503,
|
|
46
|
+
504
|
|
47
|
+
]);
|
|
48
|
+
/**
|
|
49
|
+
* Whether retrying the same call could plausibly succeed: a request that never
|
|
50
|
+
* got a response, or a transient status. A `rate_limited` error says how long
|
|
51
|
+
* to wait in `retryAfter`. Everything else is deterministic: the same request
|
|
52
|
+
* will fail the same way.
|
|
41
53
|
*/
|
|
42
54
|
function isRetryable(error) {
|
|
43
|
-
return error.kind === "network" ||
|
|
55
|
+
return error.kind === "network" || "status" in error && TRANSIENT_STATUSES.has(error.status);
|
|
44
56
|
}
|
|
45
57
|
exports.FIELD_ERROR_CODES = FIELD_ERROR_CODES;
|
|
46
58
|
exports.NETWORK_ERROR_MESSAGE = NETWORK_ERROR_MESSAGE;
|
|
47
59
|
exports.SERVER_ERROR_MESSAGE = SERVER_ERROR_MESSAGE;
|
|
48
60
|
exports.TIMEOUT_ERROR_MESSAGE = TIMEOUT_ERROR_MESSAGE;
|
|
61
|
+
exports.TRANSIENT_STATUSES = TRANSIENT_STATUSES;
|
|
49
62
|
exports.isRetryable = isRetryable;
|
|
50
63
|
|
|
51
64
|
//# sourceMappingURL=errors.cjs.map
|