@rustrak/client 0.19.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -286,9 +286,11 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
286
286
 
287
287
  | Method | Endpoint | Description |
288
288
  |---|---|---|
289
+ | `events.downloadAttachment({ path })` | `GET /api/projects/{project_id}/attachments/{attachment_id}` | Downloads an attachment. |
289
290
  | `events.get({ path })` | `GET /api/projects/{project_id}/issues/{issue_id}/events/{event_id}` | Gets a single event with full data |
290
291
  | `events.getBySentryId({ path })` | `GET /api/projects/{project_id}/events/sentry/{event_id}` | Resolve the ID returned by a Sentry SDK without already knowing the issue. |
291
292
  | `events.list({ path, query? })` | `GET /api/projects/{project_id}/issues/{issue_id}/events` | Lists events for an issue with cursor-based pagination |
293
+ | `events.listAttachments({ path })` | `GET /api/projects/{project_id}/issues/{issue_id}/events/{event_id}/attachments` | Lists the files sent with an event, such as a feedback's screenshot. |
292
294
 
293
295
  ### GitHub
294
296
 
@@ -332,6 +334,8 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
332
334
 
333
335
  | Method | Endpoint | Description |
334
336
  |---|---|---|
337
+ | `environments.list({ path })` | `GET /api/projects/{project_id}/environments` | Lists the environments a project's issues have been seen in, by name. |
338
+ | `feedback.list({ path, query? })` | `GET /api/projects/{project_id}/feedback` | Lists user feedback with what each user submitted. |
335
339
  | `issues.bulkDelete({ path, body })` | `DELETE /api/projects/{project_id}/issues` | Bulk delete by ids or filter |
336
340
  | `issues.bulkUpdate({ path, body })` | `PUT /api/projects/{project_id}/issues` | Bulk mutate |
337
341
  | `issues.createComment({ path, body })` | `POST /api/projects/{project_id}/issues/{issue_id}/comments` | Add a note. |
@@ -344,7 +348,7 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
344
348
  | `issues.getStats({ path, query? })` | `GET /api/projects/{project_id}/issues/{issue_id}/stats` | Zero-filled event-count timeseries. |
345
349
  | `issues.getTagValues({ path })` | `GET /api/projects/{project_id}/issues/{issue_id}/tags/{key}` | Lists the distinct values (with counts) for a tag key across the issue. |
346
350
  | `issues.list({ path, query? })` | `GET /api/projects/{project_id}/issues` | Lists issues for a project with offset-based pagination |
347
- | `issues.listUserReports({ path })` | `GET /api/projects/{project_id}/issues/{issue_id}/user-reports` | List user feedback for an issue. |
351
+ | `issues.listUserReports({ path, query? })` | `GET /api/projects/{project_id}/issues/{issue_id}/user-reports` | List user feedback for an issue. |
348
352
  | `issues.markSeen({ path })` | `POST /api/projects/{project_id}/issues/{issue_id}/seen` | Mark the issue as seen by the current user. |
349
353
  | `issues.setBookmark({ path, body })` | `PUT /api/projects/{project_id}/issues/{issue_id}/bookmark` | Set/clear the per-user bookmark. |
350
354
  | `issues.setSubscription({ path, body })` | `PUT /api/projects/{project_id}/issues/{issue_id}/subscription` | Set/clear the per-user subscription. |
@@ -420,6 +424,7 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
420
424
  | `sentry.listProjects({ query? })` | `GET /api/0/projects/` | The projects the token can see, newest first (Sentry's `ProjectIndexEndpoint`, `core/endpoints/project_index.py`). |
421
425
  | `sentry.listRepos({ path })` | `GET /api/0/organizations/{org_slug}/repos/` | The code repositories connected to the organization (Sentry's `OrganizationRepositoriesEndpoint`). |
422
426
  | `sentry.openIssue({ path })` | `GET /{org_slug}/{project_slug}/issues/{issue_id}` | The issue page GitLab's "View in Sentry" opens: Sentry redirects this legacy path to the issue (`static/app/router/routes.tsx`), Rustrak to its dashboard. |
427
+ | `sentry.submitUserFeedback({ path, body })` | `POST /api/0/projects/{org_slug}/{project_slug}/user-feedback/` | Submit a user report about an error event (Sentry's `ProjectUserReportsEndpoint`, `feedback/endpoints/project_user_reports.py`). |
423
428
  | `sentry.updateIssue({ path, body })` | `PUT /api/0/issues/{issue_id}/` | Sets an issue's status and returns the issue (Sentry's `GroupDetailsEndpoint.put`). |
424
429
 
425
430
  ### Sessions
@@ -465,10 +470,12 @@ Every method, grouped as it hangs off the client (`client.issues.list(...)`).
465
470
 
466
471
  | Method | Endpoint | Description |
467
472
  |---|---|---|
473
+ | `storage.compact()` | `POST /api/storage/compaction` | Rewrites a SQLite file created before incremental mode, so it gives freed space back from then on. |
468
474
  | `storage.executeCleanup({ body })` | `POST /api/storage/cleanup` | Starts deleting old data and the issues it empties. |
469
475
  | `storage.gcSourceMaps()` | `POST /api/storage/source-maps/gc` | Delete orphaned source maps (DB + disk). |
470
476
  | `storage.getAge()` | `GET /api/storage/age` | Rows per age bucket, per project and kind. |
471
477
  | `storage.getCleanupStatus()` | `GET /api/storage/cleanup/status` | Progress of the running cleanup, or the outcome of the last one. |
478
+ | `storage.getCompaction()` | `GET /api/storage/compaction` | Whether the database file shrinks when data is deleted, and the disk a one-off compaction needs. |
472
479
  | `storage.getProjects()` | `GET /api/storage/projects` | Per-project counts and estimated weight. |
473
480
  | `storage.getRetention()` | `GET /api/storage/retention` | |
474
481
  | `storage.getSummary()` | `GET /api/storage/summary` | Row counts, DB size, and source-map weight. |
package/dist/client.cjs CHANGED
@@ -5,6 +5,7 @@ const require_result = require("./result.cjs");
5
5
  const require_http = require("./utils/http.cjs");
6
6
  let zod = require("zod");
7
7
  //#region src/client.ts
8
+ const BINARY = /* @__PURE__ */ new Set(["events.downloadAttachment"]);
8
9
  /**
9
10
  * Main Rustrak API client. Every method returns a `Result`; nothing throws for
10
11
  * an expected failure.
@@ -47,6 +48,7 @@ function createApi(config) {
47
48
  methods[method] = async (options = {}) => toResult(await resource[method]({
48
49
  ...options,
49
50
  headers: options.headers instanceof Headers || Array.isArray(options.headers) ? Object.fromEntries(new Headers(options.headers)) : options.headers,
51
+ ...BINARY.has(`${name}.${method}`) && { parseAs: "blob" },
50
52
  throwOnError: false
51
53
  }));
52
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.cjs","names":["Rustrak","createClient","createConfig","createFetch","Ok","isTransportFailure","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 { 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 isTransportFailure,\n transformHttpError,\n} from './utils/http.js';\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> = 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<Result<Data<Awaited<R>>, RustrakError>>\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> = { readonly [M in keyof T]: Call<T[M]> };\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]>;\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. `auto` would hand back an\n // HTML page or a stream as a 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 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 (isTransportFailure(error)) 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":";;;;;;;;;;;;;;;;;;;;;;AAsDA,MAAa,gBAAgB,MAAM;CACjC,YAAY,QAAsB;EAEhC,OAAO,OAAO,eAAe,UAAU,MAAM,GAAG,WAAW,SAAS;CACtE;AACF;AAIA,SAAS,UAAU,QAAqC;CACtD,MAAM,MAAM,IAAIA,gBAAAA,QAAQ,EACtB,QAAQC,mBAAAA,aACNC,kBAAAA,aAAa;EACX,SAAS,OAAO;EAChB,aAAa;EACb,OAAOC,aAAAA,YAAY,MAAM;EAGzB,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,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,IAAIC,aAAAA,mBAAmB,KAAK,GAAG,OAAOC,eAAAA,IAAI,MAAM,YAAY;CAC5D,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"}
1
+ {"version":3,"file":"client.cjs","names":["Rustrak","createClient","createConfig","createFetch","Ok","isTransportFailure","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 { 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 isTransportFailure,\n transformHttpError,\n} from './utils/http.js';\n\n/**\n * Operations whose 2xx is a file, not JSON: read as a `Blob`. The spec leaves\n * the body untyped (zod has no binary type), so the type comes from here.\n */\ntype Binary = 'events.downloadAttachment';\nconst BINARY: ReadonlySet<string> = new Set<Binary>([\n 'events.downloadAttachment',\n]);\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.has(`${name}.${method}`) && { parseAs: 'blob' }),\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 (isTransportFailure(error)) 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":";;;;;;;AAiBA,MAAM,yBAA8B,IAAI,IAAY,CAClD,2BACF,CAAC;;;;;;;;;;;;;;;;AAmDD,MAAa,gBAAgB,MAAM;CACjC,YAAY,QAAsB;EAEhC,OAAO,OAAO,eAAe,UAAU,MAAM,GAAG,WAAW,SAAS;CACtE;AACF;AAIA,SAAS,UAAU,QAAqC;CACtD,MAAM,MAAM,IAAIA,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,OAAO,IAAI,GAAG,KAAK,GAAG,QAAQ,KAAK,EAAE,SAAS,OAAO;IACzD,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,IAAIC,aAAAA,mBAAmB,KAAK,GAAG,OAAOC,eAAAA,IAAI,MAAM,YAAY;CAC5D,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
@@ -3,15 +3,16 @@ import { RustrakError } from "./errors.cjs";
3
3
  import { Rustrak } from "./generated/sdk.gen.cjs";
4
4
  import { Result } from "./result.cjs";
5
5
  //#region src/client.d.ts
6
+ type Binary = 'events.downloadAttachment';
6
7
  type RequestKeys = 'path' | 'query' | 'body' | 'headers' | 'signal';
7
- type Call<F> = 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<Data<Awaited<R>>, RustrakError>> : never;
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, {
9
10
  error: undefined;
10
11
  }> extends {
11
12
  data: infer D;
12
13
  } ? D : never;
13
- type Resource<T> = { readonly [M in keyof T]: Call<T[M]>; };
14
- export type RustrakClient = { readonly [R in keyof Rustrak]: Resource<Rustrak[R]>; };
14
+ type Resource<T, Name extends string> = { readonly [M in keyof T]: Call<T[M], `${Name}.${M & string}` extends Binary ? true : false>; };
15
+ export type RustrakClient = { readonly [R in keyof Rustrak]: Resource<Rustrak[R], R & string>; };
15
16
  export declare const RustrakClient: new (config: ClientConfig) => RustrakClient;
16
17
  //#endregion
17
18
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.cts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KAaK;KAEA,KAAK,KAAK,YAAW,eAAe,YAAY,SAE5C,iBAAiB,KAAK,GAAG,cAAc,GAAG,iBACxC,UAAU,KAAK,GAAG,cAAc,GAAG,kBACnC,SAAS,KAAK,GAAG,cAAc,GAAG,mBACpC,QAAQ,OAAO,KAAK,QAAQ,KAAK;KAIrC,KAAK,KACR,QAAQ;EAAK;;EAA8B,YAAY;IAAM;KAE1D,SAAS,iBAAiB,WAAW,IAAI,KAAK,EAAE;YAQzC,4BACA,WAAW,UAAU,SAAS,QAAQ;qBAkBrC,oBAMX,QAAQ,iBACL"}
1
+ {"version":3,"file":"client.d.cts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KAgBK;KAMA;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
@@ -3,15 +3,16 @@ import { RustrakError } from "./errors.mjs";
3
3
  import { Rustrak } from "./generated/sdk.gen.mjs";
4
4
  import { Result } from "./result.mjs";
5
5
  //#region src/client.d.ts
6
+ type Binary = 'events.downloadAttachment';
6
7
  type RequestKeys = 'path' | 'query' | 'body' | 'headers' | 'signal';
7
- type Call<F> = 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<Data<Awaited<R>>, RustrakError>> : never;
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, {
9
10
  error: undefined;
10
11
  }> extends {
11
12
  data: infer D;
12
13
  } ? D : never;
13
- type Resource<T> = { readonly [M in keyof T]: Call<T[M]>; };
14
- export type RustrakClient = { readonly [R in keyof Rustrak]: Resource<Rustrak[R]>; };
14
+ type Resource<T, Name extends string> = { readonly [M in keyof T]: Call<T[M], `${Name}.${M & string}` extends Binary ? true : false>; };
15
+ export type RustrakClient = { readonly [R in keyof Rustrak]: Resource<Rustrak[R], R & string>; };
15
16
  export declare const RustrakClient: new (config: ClientConfig) => RustrakClient;
16
17
  //#endregion
17
18
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KAaK;KAEA,KAAK,KAAK,YAAW,eAAe,YAAY,SAE5C,iBAAiB,KAAK,GAAG,cAAc,GAAG,iBACxC,UAAU,KAAK,GAAG,cAAc,GAAG,kBACnC,SAAS,KAAK,GAAG,cAAc,GAAG,mBACpC,QAAQ,OAAO,KAAK,QAAQ,KAAK;KAIrC,KAAK,KACR,QAAQ;EAAK;;EAA8B,YAAY;IAAM;KAE1D,SAAS,iBAAiB,WAAW,IAAI,KAAK,EAAE;YAQzC,4BACA,WAAW,UAAU,SAAS,QAAQ;qBAkBrC,oBAMX,QAAQ,iBACL"}
1
+ {"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KAgBK;KAMA;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
@@ -5,6 +5,7 @@ import { Err, Ok } from "./result.mjs";
5
5
  import { createFetch, isTransportFailure, transformHttpError } from "./utils/http.mjs";
6
6
  import { ZodError } from "zod";
7
7
  //#region src/client.ts
8
+ const BINARY = /* @__PURE__ */ new Set(["events.downloadAttachment"]);
8
9
  /**
9
10
  * Main Rustrak API client. Every method returns a `Result`; nothing throws for
10
11
  * an expected failure.
@@ -47,6 +48,7 @@ function createApi(config) {
47
48
  methods[method] = async (options = {}) => toResult(await resource[method]({
48
49
  ...options,
49
50
  headers: options.headers instanceof Headers || Array.isArray(options.headers) ? Object.fromEntries(new Headers(options.headers)) : options.headers,
51
+ ...BINARY.has(`${name}.${method}`) && { parseAs: "blob" },
50
52
  throwOnError: false
51
53
  }));
52
54
  }
@@ -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 isTransportFailure,\n transformHttpError,\n} from './utils/http.js';\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> = 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<Result<Data<Awaited<R>>, RustrakError>>\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> = { readonly [M in keyof T]: Call<T[M]> };\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]>;\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. `auto` would hand back an\n // HTML page or a stream as a 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 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 (isTransportFailure(error)) 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":";;;;;;;;;;;;;;;;;;;;;;AAsDA,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;EAGzB,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,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,mBAAmB,KAAK,GAAG,OAAO,IAAI,MAAM,YAAY;CAC5D,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"}
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 isTransportFailure,\n transformHttpError,\n} from './utils/http.js';\n\n/**\n * Operations whose 2xx is a file, not JSON: read as a `Blob`. The spec leaves\n * the body untyped (zod has no binary type), so the type comes from here.\n */\ntype Binary = 'events.downloadAttachment';\nconst BINARY: ReadonlySet<string> = new Set<Binary>([\n 'events.downloadAttachment',\n]);\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.has(`${name}.${method}`) && { parseAs: 'blob' }),\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 (isTransportFailure(error)) 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":";;;;;;;AAiBA,MAAM,yBAA8B,IAAI,IAAY,CAClD,2BACF,CAAC;;;;;;;;;;;;;;;;AAmDD,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,OAAO,IAAI,GAAG,KAAK,GAAG,QAAQ,KAAK,EAAE,SAAS,OAAO;IACzD,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,mBAAmB,KAAK,GAAG,OAAO,IAAI,MAAM,YAAY;CAC5D,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"}
@@ -187,6 +187,34 @@ var Sentry = class extends HeyApiClient {
187
187
  });
188
188
  }
189
189
  /**
190
+ * POST /api/0/projects/{org_slug}/{project_slug}/user-feedback/
191
+ *
192
+ * Submit a user report about an error event (Sentry's
193
+ * `ProjectUserReportsEndpoint`, `feedback/endpoints/project_user_reports.py`).
194
+ * Accepts `Authorization: DSN <dsn>` as well as a token; the report becomes a
195
+ * feedback, as the `user_report` envelope item does.
196
+ */
197
+ submitUserFeedback(options) {
198
+ return (options.client ?? this.client).post({
199
+ requestValidator: async (data) => await zod.object({
200
+ body: require_zod_gen.zSentrySubmitUserFeedbackBody,
201
+ path: require_zod_gen.zSentrySubmitUserFeedbackPath,
202
+ query: zod.never().optional()
203
+ }).parseAsync(data),
204
+ responseValidator: async (data) => await require_zod_gen.zSentrySubmitUserFeedbackResponse.parseAsync(data),
205
+ security: [{
206
+ scheme: "bearer",
207
+ type: "http"
208
+ }],
209
+ url: "/api/0/projects/{org_slug}/{project_slug}/user-feedback/",
210
+ ...options,
211
+ headers: {
212
+ "Content-Type": "application/json",
213
+ ...options.headers
214
+ }
215
+ });
216
+ }
217
+ /**
190
218
  * GET /{org_slug}/{project_slug}/issues/{issue_id}/
191
219
  *
192
220
  * The issue page GitLab's "View in Sentry" opens: Sentry redirects this
@@ -1488,6 +1516,27 @@ var AlertRules = class extends HeyApiClient {
1488
1516
  }
1489
1517
  };
1490
1518
  var Events = class extends HeyApiClient {
1519
+ /**
1520
+ * GET /api/projects/{project_id}/attachments/{attachment_id}
1521
+ * Downloads an attachment. Only a real image is served inline; anything
1522
+ * else, whatever type it claims, is a download that never runs.
1523
+ */
1524
+ downloadAttachment(options) {
1525
+ return (options.client ?? this.client).get({
1526
+ requestValidator: async (data) => await zod.object({
1527
+ body: zod.never().optional(),
1528
+ path: require_zod_gen.zEventsDownloadAttachmentPath,
1529
+ query: zod.never().optional()
1530
+ }).parseAsync(data),
1531
+ responseValidator: async (data) => await require_zod_gen.zEventsDownloadAttachmentResponse.parseAsync(data),
1532
+ security: [{
1533
+ scheme: "bearer",
1534
+ type: "http"
1535
+ }],
1536
+ url: "/api/projects/{project_id}/attachments/{attachment_id}",
1537
+ ...options
1538
+ });
1539
+ }
1491
1540
  /**
1492
1541
  * Resolve the ID returned by a Sentry SDK without already knowing the issue.
1493
1542
  */
@@ -1547,6 +1596,48 @@ var Events = class extends HeyApiClient {
1547
1596
  ...options
1548
1597
  });
1549
1598
  }
1599
+ /**
1600
+ * GET /api/projects/{project_id}/issues/{issue_id}/events/{event_id}/attachments
1601
+ * Lists the files sent with an event, such as a feedback's screenshot.
1602
+ */
1603
+ listAttachments(options) {
1604
+ return (options.client ?? this.client).get({
1605
+ requestValidator: async (data) => await zod.object({
1606
+ body: zod.never().optional(),
1607
+ path: require_zod_gen.zEventsListAttachmentsPath,
1608
+ query: zod.never().optional()
1609
+ }).parseAsync(data),
1610
+ responseValidator: async (data) => await require_zod_gen.zEventsListAttachmentsResponse.parseAsync(data),
1611
+ security: [{
1612
+ scheme: "bearer",
1613
+ type: "http"
1614
+ }],
1615
+ url: "/api/projects/{project_id}/issues/{issue_id}/events/{event_id}/attachments",
1616
+ ...options
1617
+ });
1618
+ }
1619
+ };
1620
+ var Environments = class extends HeyApiClient {
1621
+ /**
1622
+ * GET /api/projects/{project_id}/environments
1623
+ * Lists the environments a project's issues have been seen in, by name.
1624
+ */
1625
+ list(options) {
1626
+ return (options.client ?? this.client).get({
1627
+ requestValidator: async (data) => await zod.object({
1628
+ body: zod.never().optional(),
1629
+ path: require_zod_gen.zEnvironmentsListPath,
1630
+ query: zod.never().optional()
1631
+ }).parseAsync(data),
1632
+ responseValidator: async (data) => await require_zod_gen.zEnvironmentsListResponse.parseAsync(data),
1633
+ security: [{
1634
+ scheme: "bearer",
1635
+ type: "http"
1636
+ }],
1637
+ url: "/api/projects/{project_id}/environments",
1638
+ ...options
1639
+ });
1640
+ }
1550
1641
  };
1551
1642
  var Stats = class extends HeyApiClient {
1552
1643
  /**
@@ -1588,6 +1679,29 @@ var Stats = class extends HeyApiClient {
1588
1679
  });
1589
1680
  }
1590
1681
  };
1682
+ var Feedback = class extends HeyApiClient {
1683
+ /**
1684
+ * GET /api/projects/{project_id}/feedback
1685
+ * Lists user feedback with what each user submitted. Every feedback is an
1686
+ * issue of category `feedback`; spam is a muted one.
1687
+ */
1688
+ list(options) {
1689
+ return (options.client ?? this.client).get({
1690
+ requestValidator: async (data) => await zod.object({
1691
+ body: zod.never().optional(),
1692
+ path: require_zod_gen.zFeedbackListPath,
1693
+ query: require_zod_gen.zFeedbackListQuery.optional()
1694
+ }).parseAsync(data),
1695
+ responseValidator: async (data) => await require_zod_gen.zFeedbackListResponse.parseAsync(data),
1696
+ security: [{
1697
+ scheme: "bearer",
1698
+ type: "http"
1699
+ }],
1700
+ url: "/api/projects/{project_id}/feedback",
1701
+ ...options
1702
+ });
1703
+ }
1704
+ };
1591
1705
  var Issues = class extends HeyApiClient {
1592
1706
  /**
1593
1707
  * DELETE /api/projects/{project_id}/issues (bulk delete by ids or filter)
@@ -1913,7 +2027,7 @@ var Issues = class extends HeyApiClient {
1913
2027
  requestValidator: async (data) => await zod.object({
1914
2028
  body: zod.never().optional(),
1915
2029
  path: require_zod_gen.zIssuesListUserReportsPath,
1916
- query: zod.never().optional()
2030
+ query: require_zod_gen.zIssuesListUserReportsQuery.optional()
1917
2031
  }).parseAsync(data),
1918
2032
  responseValidator: async (data) => await require_zod_gen.zIssuesListUserReportsResponse.parseAsync(data),
1919
2033
  security: [{
@@ -2532,6 +2646,47 @@ var Storage = class extends HeyApiClient {
2532
2646
  });
2533
2647
  }
2534
2648
  /**
2649
+ * GET /api/storage/compaction — whether the database file shrinks when data
2650
+ * is deleted, and the disk a one-off compaction needs.
2651
+ */
2652
+ getCompaction(options) {
2653
+ return (options?.client ?? this.client).get({
2654
+ requestValidator: async (data) => await zod.object({
2655
+ body: zod.never().optional(),
2656
+ path: zod.never().optional(),
2657
+ query: zod.never().optional()
2658
+ }).parseAsync(data),
2659
+ responseValidator: async (data) => await require_zod_gen.zStorageGetCompactionResponse.parseAsync(data),
2660
+ security: [{
2661
+ scheme: "bearer",
2662
+ type: "http"
2663
+ }],
2664
+ url: "/api/storage/compaction",
2665
+ ...options
2666
+ });
2667
+ }
2668
+ /**
2669
+ * POST /api/storage/compaction — rewrites a SQLite file created before
2670
+ * incremental mode, so it gives freed space back from then on. Writes wait
2671
+ * while it runs; follow it with `GET /api/storage/cleanup/status`.
2672
+ */
2673
+ compact(options) {
2674
+ return (options?.client ?? this.client).post({
2675
+ requestValidator: async (data) => await zod.object({
2676
+ body: zod.never().optional(),
2677
+ path: zod.never().optional(),
2678
+ query: zod.never().optional()
2679
+ }).parseAsync(data),
2680
+ responseValidator: async (data) => await require_zod_gen.zStorageCompactResponse.parseAsync(data),
2681
+ security: [{
2682
+ scheme: "bearer",
2683
+ type: "http"
2684
+ }],
2685
+ url: "/api/storage/compaction",
2686
+ ...options
2687
+ });
2688
+ }
2689
+ /**
2535
2690
  * GET /api/storage/projects — per-project counts and estimated weight.
2536
2691
  */
2537
2692
  getProjects(options) {
@@ -3236,10 +3391,18 @@ var Rustrak = class Rustrak extends HeyApiClient {
3236
3391
  get events() {
3237
3392
  return this._events ??= new Events({ client: this.client });
3238
3393
  }
3394
+ _environments;
3395
+ get environments() {
3396
+ return this._environments ??= new Environments({ client: this.client });
3397
+ }
3239
3398
  _stats;
3240
3399
  get stats() {
3241
3400
  return this._stats ??= new Stats({ client: this.client });
3242
3401
  }
3402
+ _feedback;
3403
+ get feedback() {
3404
+ return this._feedback ??= new Feedback({ client: this.client });
3405
+ }
3243
3406
  _issues;
3244
3407
  get issues() {
3245
3408
  return this._issues ??= new Issues({ client: this.client });
@@ -3306,7 +3469,9 @@ exports.Agents = Agents;
3306
3469
  exports.AlertChannels = AlertChannels;
3307
3470
  exports.AlertRules = AlertRules;
3308
3471
  exports.Auth = Auth;
3472
+ exports.Environments = Environments;
3309
3473
  exports.Events = Events;
3474
+ exports.Feedback = Feedback;
3310
3475
  exports.Github = Github;
3311
3476
  exports.Health = Health;
3312
3477
  exports.Invitations = Invitations;