@omelhorsite/sdk 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +4 -4
  2. package/dist/index.js +4 -4
  3. package/dist/types/auth/device.d.ts +1 -1
  4. package/dist/types/auth/index.d.ts +2 -2
  5. package/dist/types/auth/tokens.d.ts +15 -15
  6. package/dist/types/client.d.ts +10 -10
  7. package/dist/types/errors.d.ts +12 -15
  8. package/dist/types/http.d.ts +74 -118
  9. package/dist/types/index.d.ts +1 -2
  10. package/dist/types/local/qr.d.ts +1 -1
  11. package/dist/types/local/wordlist.d.ts +2 -3
  12. package/dist/types/resources/account.d.ts +14 -17
  13. package/dist/types/resources/auth/index.d.ts +1 -1
  14. package/dist/types/resources/auth/passkeys.d.ts +127 -163
  15. package/dist/types/resources/auth/sessions.d.ts +110 -152
  16. package/dist/types/resources/chests.d.ts +27 -31
  17. package/dist/types/resources/dynamicQrs.d.ts +29 -45
  18. package/dist/types/resources/forms.d.ts +37 -58
  19. package/dist/types/resources/jobs.d.ts +28 -40
  20. package/dist/types/resources/media.d.ts +48 -61
  21. package/dist/types/resources/music/artists.d.ts +179 -245
  22. package/dist/types/resources/music/imports.d.ts +181 -210
  23. package/dist/types/resources/music/index.d.ts +8 -7
  24. package/dist/types/resources/music/playlists.d.ts +77 -110
  25. package/dist/types/resources/music/social.d.ts +153 -228
  26. package/dist/types/resources/music/songs.d.ts +160 -206
  27. package/dist/types/resources/realtime.d.ts +75 -88
  28. package/dist/types/resources/shortLinks.d.ts +33 -45
  29. package/dist/types/resources/storage/upload.d.ts +42 -56
  30. package/dist/types/resources/storage.d.ts +71 -104
  31. package/dist/types/resources/tools/backgroundRemoval.d.ts +11 -13
  32. package/dist/types/resources/tools/captions.d.ts +107 -135
  33. package/dist/types/resources/tools/upscale.d.ts +12 -16
  34. package/dist/types/types.d.ts +29 -38
  35. package/package.json +1 -1
package/README.md CHANGED
@@ -39,7 +39,7 @@ const oms = new Oms({
39
39
  baseUrl: "http://localhost:3000", // defaults to https://backend.omelhorsite.pt
40
40
  fetch: myFetch, // defaults to globalThis.fetch
41
41
  headers: { "X-Trace": id }, // merged under per-call headers
42
- timeoutMs: 30_000, // whole call, retries included; 0 disables
42
+ timeoutMs: 30_000, // per attempt; 0 disables
43
43
  retry: { maxAttempts: 3 }, // or false to never retry
44
44
  clientName: "my-worker/1.0", // becomes X-Oms-Client
45
45
  });
@@ -186,7 +186,7 @@ const done = await oms.tools.transcription.run(
186
186
  `run` is `create` plus `jobs.wait`. Use `create` on hosts with a wall-clock
187
187
  budget or nowhere to hold a wait: start the job, keep the id, pick it up later.
188
188
 
189
- Waiting resolves for both `"completed"` and `"failed"`: a failed job is an
189
+ Waiting resolves for both `"complete"` and `"failed"`: a failed job is an
190
190
  answer, not a transport error. Check the status before reading the result.
191
191
 
192
192
  ```ts
@@ -194,8 +194,8 @@ const job = await oms.jobs.wait({ id: started.job_id!, watchToken: started.watch
194
194
  if (job.status === "failed") throw new Error(job.error ?? "the job failed");
195
195
  ```
196
196
 
197
- A finished tool row says `status: "complete"`; a finished row in the job table
198
- says `"completed"`; the downloader says `"done"`. Compare against the exported
197
+ A finished job says `status: "complete"`, not `"completed"`, and the
198
+ downloader spells its own terminal state `"done"`. Compare against the exported
199
199
  constants, never against a literal.
200
200
 
201
201
  Check the quota before starting something expensive:
package/dist/index.js CHANGED
@@ -12835,7 +12835,7 @@ class MusicPlaylistsNamespace extends Resource {
12835
12835
  async reorder(id, songIds, options = {}) {
12836
12836
  const ids = integerIds(songIds, "songIds");
12837
12837
  if (ids.length === 0) {
12838
- throw new TypeError("reorder needs the complete desired order and refuses an empty array: the backend raises ArgumentError " + "for it, which surfaces as a 500 rather than a 400.");
12838
+ throw new TypeError("reorder needs the complete desired order and refuses an empty array: the server answers 500 for it, " + "not 400.");
12839
12839
  }
12840
12840
  await this.http.post(`/playlists/${encodeURIComponent(String(id))}/reorder`, { song_ids: ids }, options);
12841
12841
  }
@@ -12958,7 +12958,7 @@ function integerIds(ids, field) {
12958
12958
  return ids.map((raw, index) => {
12959
12959
  const value = typeof raw === "string" ? Number(raw) : raw;
12960
12960
  if (typeof value !== "number" || !Number.isInteger(value)) {
12961
- throw new TypeError(`${field}[${index}] is ${JSON.stringify(raw)}, which is not an integer id. Song ids are integers on this ` + "API, and the backend matches them by identity: a string id matches no row, so the request would " + "succeed and change nothing.");
12961
+ throw new TypeError(`${field}[${index}] is ${JSON.stringify(raw)}, which is not an integer id. Song ids are integers on this ` + "API and are matched by identity: a string id matches no row, so the request would succeed and " + "change nothing.");
12962
12962
  }
12963
12963
  return value;
12964
12964
  });
@@ -13553,7 +13553,7 @@ class CableConnectionImpl {
13553
13553
  const identifier = JSON.stringify(params);
13554
13554
  const registration = { handlers, live: true };
13555
13555
  if (this.subs.has(identifier)) {
13556
- throw new OmsNetworkError(`Already subscribed to ${identifier}. ActionCable keys subscriptions by identifier, so a second one would shadow the first: reuse the handle, or unsubscribe before resubscribing.`);
13556
+ throw new OmsNetworkError(`Already subscribed to ${identifier}. Subscriptions are keyed by identifier, so a second one would shadow the first: reuse the handle, or unsubscribe before resubscribing.`);
13557
13557
  }
13558
13558
  this.subs.set(identifier, registration);
13559
13559
  if (this.welcomed)
@@ -14861,7 +14861,7 @@ class CaptionsNamespace extends Resource {
14861
14861
  }
14862
14862
  async createChunked(input, options = {}) {
14863
14863
  if (isNativeFile(input.video.data)) {
14864
- throw new OmsError(`Cannot chunk-upload "${input.video.filename}": it is a React Native file descriptor ` + `(${input.video.data.uri}), and the chunked path has to slice the bytes. Use create() for a file ` + "under Cloudflare's ~100 MB request cap, or read the video into a Uint8Array first " + "(Expo: `new File(uri).bytes()`) and pass that.", "invalid_request");
14864
+ throw new OmsError(`Cannot chunk-upload "${input.video.filename}": it is a React Native file descriptor ` + `(${input.video.data.uri}), and the chunked path has to slice the bytes. Use create() for a file ` + "under the ~100 MB request cap, or read the video into a Uint8Array first " + "(Expo: `new File(uri).bytes()`) and pass that.", "invalid_request");
14865
14865
  }
14866
14866
  const { onProgress, onPart, ...request } = options;
14867
14867
  const { blob } = await readFileInput(input.video);
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * OAuth 2.0 Device Authorization Grant (RFC 8628).
3
3
  *
4
- * This is how a CLI or an MCP server signs a person in without ever handling
4
+ * This is how a terminal or a headless client signs a person in without ever handling
5
5
  * their password: the client asks for a code, the person opens a URL in a real
6
6
  * browser and approves, and the client polls the token endpoint until the
7
7
  * approval lands.
@@ -36,7 +36,7 @@ export * from "./device";
36
36
  export * from "./tokens";
37
37
  /** Who the current credential belongs to. */
38
38
  export interface WhoAmI {
39
- /** `users.id`. The stable identifier; matches the OIDC `sub` claim. */
39
+ /** The stable user identifier; matches the OIDC `sub` claim. */
40
40
  readonly id: string;
41
41
  /** Current handle. Mutable - never key anything on it. */
42
42
  readonly handle: string;
@@ -107,7 +107,7 @@ export declare class AuthNamespace extends Resource {
107
107
  }, options?: RequestOptions): Promise<void>;
108
108
  /**
109
109
  * Reads the OIDC claims of the current credential from
110
- * `GET /oauth/userinfo`. `sub` is `users.id`.
110
+ * `GET /oauth/userinfo`. `sub` is the user's stable `id`.
111
111
  *
112
112
  * Needs the `openid` scope; without it the answer is 403. Members whose
113
113
  * value is null or empty are omitted from the response, so read defensively.
@@ -2,15 +2,15 @@
2
2
  * Token providers: where the transport gets a bearer token from.
3
3
  *
4
4
  * The core has no storage. A provider is either a constant, or a thing the
5
- * host wired to its own store (the CLI's config file, a Worker KV namespace, a
5
+ * host wired to its own store (a config file, a Worker KV namespace, a
6
6
  * browser's memory). Nothing here reads a file or an environment variable.
7
7
  *
8
8
  * Two credential shapes exist today and both are just bearer tokens on the
9
9
  * wire:
10
- * - a legacy opaque session token (a UUID minted by `Session`), which never
11
- * expires and carries no scopes;
12
- * - an OAuth 2 / OIDC access token from doorkeeper, which does expire and does
13
- * carry scopes, and which comes with a refresh token.
10
+ * - a legacy opaque session token (a UUID), which never expires and carries no
11
+ * scopes;
12
+ * - an OAuth 2 / OIDC access token, which does expire and does carry scopes,
13
+ * and which comes with a refresh token.
14
14
  *
15
15
  * {@link TokenSet} models the second. The first is just a string.
16
16
  *
@@ -23,7 +23,7 @@ import { OmsError } from "../errors";
23
23
  import { type ApiClient, type TokenProvider } from "../http";
24
24
  import type { RequestOptions } from "../types";
25
25
  /**
26
- * An OAuth 2 token response, as doorkeeper returns it.
26
+ * An OAuth 2 token response, as the token endpoint returns it.
27
27
  *
28
28
  * `expiresAt` is absolute epoch milliseconds, not the `expires_in` seconds the
29
29
  * server sends, so a stored set stays correct across a restart.
@@ -45,8 +45,8 @@ export interface TokenSet {
45
45
  /** Claims the SDK reads out of an OIDC id token. */
46
46
  export interface IdentityClaims {
47
47
  /**
48
- * Stable user identifier: `users.id`. Never the handle and never the email,
49
- * both of which the user can change.
48
+ * Stable user identifier: the user's `id`, as `oms.account.me()` reports it.
49
+ * Never the handle and never the email, both of which the user can change.
50
50
  */
51
51
  readonly sub: string;
52
52
  readonly iss?: string;
@@ -87,8 +87,8 @@ export declare const DEFAULT_REFRESH_SKEW_MS = 60000;
87
87
  /**
88
88
  * Wraps a constant token. This is what `new Oms({ token })` builds.
89
89
  *
90
- * Accepts both credential kinds: an opaque session UUID and a doorkeeper
91
- * access token look identical on the wire.
90
+ * Accepts both credential kinds: an opaque session UUID and an OAuth access
91
+ * token look identical on the wire.
92
92
  */
93
93
  export declare function staticToken(token: string | null): TokenProvider;
94
94
  /**
@@ -304,8 +304,8 @@ export declare class OmsOAuthError extends OmsError {
304
304
  * Recognises an OAuth error inside whatever the transport threw.
305
305
  *
306
306
  * Deliberately narrow: only 400 and 401 bodies are read as OAuth errors. A 429
307
- * comes from rack-attack with the body `{"error":"rate_limited"}`, and that
308
- * `error` key is NOT an OAuth code - reading it as one abandons a perfectly
307
+ * carries the body `{"error":"rate_limited"}`, and that `error` key is NOT an
308
+ * OAuth code - reading it as one abandons a perfectly
309
309
  * live device flow. It stays an {@link OmsQuotaError} and the caller handles
310
310
  * it as a rate limit.
311
311
  *
@@ -316,8 +316,8 @@ export declare function oauthErrorFrom(thrown: unknown): OmsOAuthError | undefin
316
316
  export interface InsufficientScope {
317
317
  /**
318
318
  * The scopes the endpoint needed. EMPTY when the server named none, which
319
- * means the endpoint has not been opened to OAuth clients at all - a backend
320
- * gap, not a client bug. The two cases must read differently to the user.
319
+ * means the endpoint accepts no OAuth token at all - a server-side gap, not
320
+ * a client bug. The two cases must read differently to the user.
321
321
  */
322
322
  readonly required: string[];
323
323
  /** The `realm` parameter, when present. */
@@ -342,7 +342,7 @@ export declare function readInsufficientScope(error: unknown): InsufficientScope
342
342
  *
343
343
  * The OAuth endpoints do not take JSON, which is why this exists next to
344
344
  * `ApiClient.post` rather than using it. Blank values are dropped rather than
345
- * sent empty, because doorkeeper reads `""` as a present-but-invalid parameter.
345
+ * sent empty, because the server reads `""` as a present-but-invalid parameter.
346
346
  *
347
347
  * Retries are OFF and stay off. Replaying `POST /oauth/token` after a lost
348
348
  * response is not safe: the server may have rotated the refresh token already,
@@ -41,7 +41,7 @@ import type { FetchLike, RetryOptions } from "./types";
41
41
  * Anything accepted as a credential by {@link Oms}.
42
42
  *
43
43
  * A bare string is either kind of bearer token the API takes: a legacy opaque
44
- * `Session` UUID or an OAuth access token. A function is called on every
44
+ * session UUID or an OAuth access token. A function is called on every
45
45
  * request. A {@link TokenProvider} additionally gets a chance to refresh on a
46
46
  * 401 - see `auth/tokens.ts`.
47
47
  */
@@ -66,7 +66,7 @@ export interface OmsOptions {
66
66
  * by name.
67
67
  *
68
68
  * ```ts
69
- * // in the omelhorsite web app, served from the same site as the API
69
+ * // on a first-party page, served from the same site as the API
70
70
  * const oms = new Oms({ sessionCookie: true });
71
71
  * ```
72
72
  */
@@ -75,13 +75,13 @@ export interface OmsOptions {
75
75
  readonly baseUrl?: string;
76
76
  /**
77
77
  * The fetch to talk through. Defaults to `globalThis.fetch`. Injecting one is
78
- * how a Worker adds a cache, how a test swaps in a double, and how the CLI
78
+ * how a Worker adds a cache, how a test swaps in a double, and how a host
79
79
  * adds a proxy - the SDK never patches a global.
80
80
  */
81
81
  readonly fetch?: FetchLike;
82
82
  /** Headers merged into every request, below per-call headers. */
83
83
  readonly headers?: Record<string, string>;
84
- /** Default deadline for one call including its retries. `0` disables it. */
84
+ /** Default deadline for one attempt; a retry gets a fresh one. `0` disables it. */
85
85
  readonly timeoutMs?: number;
86
86
  /** Default backoff policy, or `false` to never retry. */
87
87
  readonly retry?: RetryOptions | false;
@@ -103,10 +103,10 @@ export interface OmsOptions {
103
103
  *
104
104
  * ## Two credentials, two namespaces
105
105
  *
106
- * `oms.sessions` mints the opaque `Session` token the website and the mobile
107
- * apps use, which carries the whole account. `oms.auth` runs OAuth, whose
108
- * tokens are scoped and, because `enforce_oauth_scope!` denies by omission,
109
- * cannot reach most of the API at all. `oms.realtime` accepts only the first
106
+ * `oms.sessions` mints the opaque session token, which carries the whole
107
+ * account. `oms.auth` runs OAuth, whose tokens are scoped and, because an
108
+ * endpoint with no declared scope refuses every OAuth token, cannot reach most
109
+ * of the API at all. `oms.realtime` accepts only the first
110
110
  * kind. Picking the wrong one shows up as a `403 insufficient_scope`, or on the
111
111
  * cable as a connection that is silently anonymous.
112
112
  *
@@ -178,9 +178,9 @@ export declare class Oms {
178
178
  /** OAuth client registration for anyone, plus the `/admin/*` routes. */
179
179
  readonly admin: AdminNamespace;
180
180
  /**
181
- * The ActionCable connection: playback handoff, jams, notifications, job
181
+ * The WebSocket connection: playback handoff, jams, notifications, job
182
182
  * progress. Opens nothing until {@link RealtimeNamespace.connect} is called,
183
- * and wants a `Session` token rather than the client's own credential - see
183
+ * and wants a session token rather than the client's own credential - see
184
184
  * that method for why.
185
185
  */
186
186
  readonly realtime: RealtimeNamespace;
@@ -8,15 +8,15 @@
8
8
  * The API answers with at least four different error body shapes, so anything
9
9
  * that reads an error body must go through {@link normalizeErrorBody}:
10
10
  *
11
- * - a bare JSON string: `"Image too large"` (ResponseHelpers)
12
- * - a sentence from ActiveModel: `"Name can't be blank and ..."` (error_messages)
11
+ * - a bare JSON string: `"Image too large"`
12
+ * - a validation sentence: `"Name can't be blank and ..."`
13
13
  * - an object with `error`: `{"error":"rate_limited","retry_after":37}`
14
14
  * - an object of field errors: `{"errors":{"url":["is invalid"]}}`
15
15
  * - plain text / HTML: short-link 404 pages, proxy errors
16
16
  */
17
17
  /** Machine-readable code carried by every SDK error. */
18
18
  export type OmsErrorCode = "api_error" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "invalid_request" | "quota_exceeded" | "rate_limited" | "server_error" | "timeout" | "aborted" | "network" | "unsupported" | "unknown";
19
- /** Extra context attached to an error, useful for logs and for the CLI. */
19
+ /** Extra context attached to an error, useful for logs. */
20
20
  export interface OmsErrorContext {
21
21
  /** HTTP method of the failing request, when there was one. */
22
22
  readonly method?: string;
@@ -38,9 +38,9 @@ export declare class OmsError extends Error {
38
38
  * This class's own name, as a LITERAL.
39
39
  *
40
40
  * `this.name = new.target.name` would be the obvious way to do this and it
41
- * is wrong here: `bun build --minify` renames the classes, so the shipped
42
- * `oms` binary reported `name: "A"` in its JSON error envelope while a dev
43
- * run reported `OmsNetworkError`. A minifier renames identifiers, never
41
+ * is wrong here: `bun build --minify` renames the classes, so a minified
42
+ * build reported `name: "A"` in its JSON error envelope while a dev run
43
+ * reported `OmsNetworkError`. A minifier renames identifiers, never
44
44
  * string literals or property names, so a static literal survives the build.
45
45
  *
46
46
  * Every subclass shadows this, and `new.target` is the constructor that was
@@ -95,9 +95,6 @@ export declare class OmsApiError extends OmsError {
95
95
  }
96
96
  /**
97
97
  * 401 or 403: the credential is missing, expired, or not allowed to do this.
98
- *
99
- * The CLI turns this into "run `oms auth login`"; the MCP server turns it into
100
- * a device-flow prompt.
101
98
  */
102
99
  export declare class OmsAuthError extends OmsApiError {
103
100
  static readonly errorName: string;
@@ -107,10 +104,10 @@ export declare class OmsAuthError extends OmsApiError {
107
104
  /**
108
105
  * 429, or a documented daily-quota rejection.
109
106
  *
110
- * Two different producers land here and they do not look alike:
111
- * rack-attack answers `{"error":"rate_limited","retry_after":37}` with a
112
- * `Retry-After` header, while a controller quota gate answers a bare string
113
- * such as `"Daily edit quota reached (5/day)"` with no header at all. Read
107
+ * Two different producers land here and they do not look alike: a rate limit
108
+ * answers `{"error":"rate_limited","retry_after":37}` with a `Retry-After`
109
+ * header, while a daily quota answers a bare string such as
110
+ * `"Daily edit quota reached (5/day)"` with no header at all. Read
114
111
  * {@link retryAfterMs}; it is `undefined` in the second case.
115
112
  */
116
113
  export declare class OmsQuotaError extends OmsApiError {
@@ -160,7 +157,7 @@ export interface NormalizedError {
160
157
  readonly message: string;
161
158
  /** A code the server named itself (`{"error":"rate_limited"}`), if any. */
162
159
  readonly serverCode: string | undefined;
163
- /** Per-field messages, when the body was shaped like ActiveModel errors. */
160
+ /** Per-field messages, when the body was a field-to-messages map. */
164
161
  readonly fieldErrors: Record<string, string[]> | undefined;
165
162
  }
166
163
  /**
@@ -179,7 +176,7 @@ export interface NormalizedError {
179
176
  export declare function normalizeErrorBody(body: unknown, fallback?: string): NormalizedError;
180
177
  /**
181
178
  * Reads a `Retry-After` header. RFC 9110 allows both delay-seconds and an
182
- * HTTP-date; rack-attack sends seconds, but a proxy in front may not.
179
+ * HTTP-date; the API sends seconds, but a proxy in front may not.
183
180
  *
184
181
  * @returns Milliseconds to wait, or `undefined` when the header is absent or junk.
185
182
  */