@omelhorsite/sdk 0.3.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 (92) hide show
  1. package/README.md +113 -131
  2. package/dist/index.js +1049 -1246
  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 +2 -2
  10. package/dist/types/internal/attachments.d.ts +17 -0
  11. package/dist/types/internal/helpers.d.ts +9 -0
  12. package/dist/types/listing.d.ts +90 -0
  13. package/dist/types/local/qr.d.ts +1 -1
  14. package/dist/types/local/wordlist.d.ts +2 -3
  15. package/dist/types/resources/account.d.ts +19 -19
  16. package/dist/types/resources/admin/authorizedApplications.d.ts +133 -0
  17. package/dist/types/resources/admin/chests.d.ts +51 -0
  18. package/dist/types/resources/admin/eventAlerts.d.ts +60 -0
  19. package/dist/types/resources/admin/identities.d.ts +99 -0
  20. package/dist/types/resources/admin/index.d.ts +77 -0
  21. package/dist/types/resources/admin/jobs.d.ts +97 -0
  22. package/dist/types/resources/admin/myOauthApplications.d.ts +282 -0
  23. package/dist/types/resources/admin/notepads.d.ts +49 -0
  24. package/dist/types/resources/admin/oauthApplications.d.ts +309 -0
  25. package/dist/types/resources/admin/quotas.d.ts +114 -0
  26. package/dist/types/resources/admin/shortLinks.d.ts +201 -0
  27. package/dist/types/resources/admin/types.d.ts +222 -0
  28. package/dist/types/resources/admin/vocalSeparations.d.ts +98 -0
  29. package/dist/types/resources/admin.d.ts +17 -13
  30. package/dist/types/resources/auth/index.d.ts +1 -1
  31. package/dist/types/resources/auth/passkeys.d.ts +127 -163
  32. package/dist/types/resources/auth/sessions.d.ts +116 -161
  33. package/dist/types/resources/chests.d.ts +27 -31
  34. package/dist/types/resources/content/analysis.d.ts +62 -0
  35. package/dist/types/resources/content/blogs.d.ts +471 -0
  36. package/dist/types/resources/content/feedbacks.d.ts +263 -0
  37. package/dist/types/resources/content/index.d.ts +52 -0
  38. package/dist/types/resources/content/intel/articles.d.ts +230 -0
  39. package/dist/types/resources/content/intel/config.d.ts +135 -0
  40. package/dist/types/resources/content/intel/index.d.ts +53 -0
  41. package/dist/types/resources/content/intel/items.d.ts +91 -0
  42. package/dist/types/resources/content/intel/reports.d.ts +108 -0
  43. package/dist/types/resources/content/intel/scripts.d.ts +152 -0
  44. package/dist/types/resources/content/intel/sources.d.ts +236 -0
  45. package/dist/types/resources/content/intel/stats.d.ts +105 -0
  46. package/dist/types/resources/content/intel/types.d.ts +86 -0
  47. package/dist/types/resources/content/jokes.d.ts +93 -0
  48. package/dist/types/resources/content/notifications.d.ts +147 -0
  49. package/dist/types/resources/content/serviceUsages.d.ts +73 -0
  50. package/dist/types/resources/content/servicesStatus.d.ts +194 -0
  51. package/dist/types/resources/content/siteConfig.d.ts +43 -0
  52. package/dist/types/resources/content/spaceInvaders.d.ts +154 -0
  53. package/dist/types/resources/content.d.ts +41 -236
  54. package/dist/types/resources/dynamicQrs.d.ts +29 -45
  55. package/dist/types/resources/forms.d.ts +37 -58
  56. package/dist/types/resources/jobs.d.ts +35 -44
  57. package/dist/types/resources/library/annotations.d.ts +162 -0
  58. package/dist/types/resources/library/books.d.ts +534 -0
  59. package/dist/types/resources/library/chat.d.ts +259 -0
  60. package/dist/types/resources/library/index.d.ts +39 -0
  61. package/dist/types/resources/library/shelves.d.ts +237 -0
  62. package/dist/types/resources/library/types.d.ts +120 -0
  63. package/dist/types/resources/library.d.ts +20 -22
  64. package/dist/types/resources/media.d.ts +48 -61
  65. package/dist/types/resources/movies/addons.d.ts +388 -0
  66. package/dist/types/resources/movies/collections.d.ts +352 -0
  67. package/dist/types/resources/movies/index.d.ts +29 -0
  68. package/dist/types/resources/movies/types.d.ts +50 -0
  69. package/dist/types/resources/movies/watchProgress.d.ts +277 -0
  70. package/dist/types/resources/movies.d.ts +27 -53
  71. package/dist/types/resources/music/artists.d.ts +182 -246
  72. package/dist/types/resources/music/imports.d.ts +190 -218
  73. package/dist/types/resources/music/index.d.ts +8 -7
  74. package/dist/types/resources/music/playlists.d.ts +85 -117
  75. package/dist/types/resources/music/social.d.ts +153 -228
  76. package/dist/types/resources/music/songs.d.ts +165 -227
  77. package/dist/types/resources/realtime.d.ts +75 -88
  78. package/dist/types/resources/shortLinks.d.ts +38 -47
  79. package/dist/types/resources/social/groupChats.d.ts +458 -0
  80. package/dist/types/resources/social/index.d.ts +19 -0
  81. package/dist/types/resources/social/messages.d.ts +424 -0
  82. package/dist/types/resources/social/relationships.d.ts +322 -0
  83. package/dist/types/resources/social/types.d.ts +37 -0
  84. package/dist/types/resources/social.d.ts +21 -3
  85. package/dist/types/resources/storage/upload.d.ts +42 -56
  86. package/dist/types/resources/storage.d.ts +94 -109
  87. package/dist/types/resources/tickets.d.ts +19 -10
  88. package/dist/types/resources/tools/backgroundRemoval.d.ts +11 -13
  89. package/dist/types/resources/tools/captions.d.ts +107 -135
  90. package/dist/types/resources/tools/upscale.d.ts +12 -16
  91. package/dist/types/types.d.ts +29 -38
  92. package/package.json +1 -1
@@ -7,16 +7,12 @@
7
7
  * an anonymous respondent hits. The SDK exposes both; the public calls work
8
8
  * without a credential unless the form turns `settings.require_login` on.
9
9
  *
10
- * The endpoint is not a column on the form: it lives on a short link paired
11
- * with it, which is why renaming it is a real operation and why availability
12
- * has its own lookup.
10
+ * The endpoint belongs to a short link paired with the form, which is why
11
+ * renaming it is a real operation and why availability has its own lookup.
13
12
  */
14
13
  import { type ApiClient, Resource } from "../http";
15
14
  import type { BaseRecord, FileInput, Id, Json, RequestOptions, Timestamp } from "../types";
16
- /**
17
- * The reserved short-link namespace a published form is served under.
18
- * `Form::NAMESPACE` / `ShortLink::FORM_NAMESPACE`.
19
- */
15
+ /** The reserved short-link namespace a published form is served under. */
20
16
  export declare const FORM_NAMESPACE = "f";
21
17
  /**
22
18
  * Public prefix a published form resolves under, and the prefix
@@ -35,9 +31,8 @@ export type FormSchemaFieldType = "short_text" | "long_text" | "email" | "number
35
31
  * READ back off a form.
36
32
  *
37
33
  * `id` is not optional here even though it is optional when writing: the
38
- * sanitiser mints `SecureRandom.uuid` for any option that arrives without one,
39
- * so a stored option always has one. Write with
40
- * {@link FormSchemaFieldOptionInput}.
34
+ * server mints a UUID for any option that arrives without one, so a stored
35
+ * option always has one. Write with {@link FormSchemaFieldOptionInput}.
41
36
  */
42
37
  export interface FormSchemaFieldOption {
43
38
  /** Stable within the form. */
@@ -54,13 +49,13 @@ export interface FormSchemaFieldOptionInput {
54
49
  *
55
50
  * `id` is the key answers are filed under - NOT the label.
56
51
  *
57
- * Four of these keys are non-optional because `Forms::InputSanitizer#field`
58
- * writes them on EVERY field it keeps, whatever arrived: `id` (minted when
59
- * absent), `type`, `label` and `description` (both coerced with `.to_s`, so an
60
- * absent one is stored as `""`, not dropped) and `required` (cast to a real
61
- * boolean). The three that stay optional are genuinely absent from the stored
62
- * object when unused: `placeholder` is only kept when present, `options` only
63
- * for the three choice types, and `min`/`max` only for `number`.
52
+ * Five of these keys are non-optional because the server writes them on EVERY
53
+ * field it keeps, whatever arrived: `id` (minted when absent), `type`, `label`
54
+ * and `description` (an absent one is stored as `""`, not dropped) and
55
+ * `required` (always a real boolean). The rest are genuinely absent from the
56
+ * stored object when unused: `placeholder` is only kept when present,
57
+ * `options` only for the three choice types, and `min`/`max` only for
58
+ * `number`.
64
59
  *
65
60
  * Write with {@link FormSchemaFieldInput}, where all of that is optional.
66
61
  */
@@ -84,8 +79,8 @@ export interface FormSchemaField {
84
79
  * One field as WRITTEN.
85
80
  *
86
81
  * Every key but `type` may be omitted. `type` may not: a field whose type is
87
- * not one of `Form::FIELD_TYPES` is dropped from the schema in silence, which
88
- * looks exactly like a field that was never sent.
82
+ * not one of {@link FormSchemaFieldType} is dropped from the schema in
83
+ * silence, which looks exactly like a field that was never sent.
89
84
  *
90
85
  * A {@link FormSchemaField} read off a form is assignable here, so the
91
86
  * read-edit-write round trip needs no mapping.
@@ -105,8 +100,8 @@ export interface FormSchemaFieldInput {
105
100
  }
106
101
  /**
107
102
  * The field definition of a form, as read. Always `{ fields: [...] }`, never
108
- * `null` and never a bare array: the column is `NOT NULL DEFAULT
109
- * '{"fields":[]}'` and the sanitiser rebuilds the envelope on every write.
103
+ * `null` and never a bare array: a new form starts with an empty envelope and
104
+ * the server rebuilds it on every write.
110
105
  */
111
106
  export interface FormSchema {
112
107
  readonly fields: FormSchemaField[];
@@ -114,8 +109,8 @@ export interface FormSchema {
114
109
  /**
115
110
  * The field definition as written. The server rebuilds it from scratch keeping
116
111
  * only the keys {@link FormSchemaFieldInput} names, so anything extra is lost
117
- * without a word - and a write that is not a Hash at all is silently read as
118
- * `{ fields: [] }`, which empties the form rather than failing.
112
+ * without a word - and a write that is not an object at all is silently read
113
+ * as `{ fields: [] }`, which empties the form rather than failing.
119
114
  */
120
115
  export interface FormSchemaInput {
121
116
  readonly fields: FormSchemaFieldInput[];
@@ -153,10 +148,9 @@ export interface FormSettings {
153
148
  /**
154
149
  * A hosted form, owner view.
155
150
  *
156
- * One shape, not two: `FormsController` renders `form.render` with no view on
157
- * index, show, create AND update, so the `:extended` view `ApplicationBlueprint`
158
- * declares is never reached here and there is no richer variant to ask for.
159
- * Every key below is therefore on every response.
151
+ * One shape, not two: index, show, create AND update all answer the same
152
+ * record, and there is no richer variant to ask for. Every key below is on
153
+ * every response.
160
154
  */
161
155
  export interface Form extends BaseRecord {
162
156
  readonly user_id: Id;
@@ -180,19 +174,14 @@ export interface Form extends BaseRecord {
180
174
  readonly published_at: Timestamp | null;
181
175
  /** Bumped by every `getPublic` call, the SDK's included. Never `null`. */
182
176
  readonly views_count: number;
183
- /**
184
- * Answers recorded. Computed per request - batched into one grouped COUNT
185
- * for a whole listing, one COUNT for a single render - so it is always
186
- * current and never cached.
187
- */
177
+ /** Answers recorded. Computed per request, so it is always current. */
188
178
  readonly submissions_count: number;
189
179
  }
190
180
  /**
191
181
  * The reduced form a public respondent is allowed to see.
192
182
  *
193
- * NOT a subset of {@link Form}: the controller builds this hash by hand rather
194
- * than rendering a blueprint view, so it carries `require_login` - which is not
195
- * a field on `Form` at all, only a key inside `settings` - and carries no
183
+ * NOT a subset of {@link Form}: it carries `require_login` - which is not a
184
+ * field on `Form` at all, only a key inside `settings` - and carries no
196
185
  * timestamps, no `user_id`, no counts and no `status`. Seven keys, always all
197
186
  * seven.
198
187
  */
@@ -208,14 +197,10 @@ export interface PublicForm {
208
197
  /**
209
198
  * One answered form.
210
199
  *
211
- * Deliberately has no `updated_at`: a submission is never edited, and
212
- * `FormSubmissionBlueprint` is the one blueprint in the API that inherits
213
- * `Blueprinter::Base` directly rather than `ApplicationBlueprint`, precisely so
214
- * that the automatic `updated_at` cannot creep in. Do not add it here on the
215
- * assumption that every record has one.
200
+ * Deliberately has no `updated_at`: a submission is never edited. Do not add
201
+ * it here on the assumption that every record has one.
216
202
  *
217
- * The other seven keys are all declared unconditionally, so all seven are
218
- * always present; four of them are nullable columns.
203
+ * All seven keys are always present; four of them are nullable.
219
204
  */
220
205
  export interface FormSubmission {
221
206
  readonly id: Id;
@@ -240,23 +225,18 @@ export interface FormSubmission {
240
225
  /** Parsed from the respondent's user agent. `null` when unparseable. */
241
226
  readonly device_name: string | null;
242
227
  /**
243
- * When the answers were recorded. The controller writes `Time.current` on
244
- * every submission it creates, so this is `null` only for a row predating
245
- * that - but the column is nullable, so check before formatting it.
228
+ * When the answers were recorded. Set on every submission the API creates,
229
+ * so this is `null` only for an old row - but it is nullable, so check
230
+ * before formatting it.
246
231
  */
247
232
  readonly completed_at: Timestamp | null;
248
233
  readonly created_at: Timestamp;
249
234
  }
250
- /**
251
- * What `POST /form_attachments` answers with.
252
- *
253
- * Built by hand in the controller rather than by a blueprint, so this is the
254
- * literal four-key hash it renders and there is no `created_at` to read.
255
- */
235
+ /** What `POST /form_attachments` answers with. Four keys, no `created_at`. */
256
236
  export interface FormAttachment {
257
237
  readonly id: Id;
258
238
  readonly filename: string;
259
- /** One of `FormAttachment::ALLOWED_TYPES`; a save with anything else is a 400. */
239
+ /** JPEG, PNG, WebP, GIF or HEIC; a save with anything else is a 400. */
260
240
  readonly content_type: string;
261
241
  /** Absolute URL that serves the bytes inline, no credential required. */
262
242
  readonly url: string;
@@ -266,8 +246,8 @@ export interface FormAttachment {
266
246
  * conditional and mutually exclusive.
267
247
  *
268
248
  * `reason` appears only on the rejected branch and only ever holds
269
- * `"invalid"` - the controller has a single rejection reason for forms,
270
- * covering both a bad shape and a reserved word. (Link trees, which look
249
+ * `"invalid"` - the server has a single rejection reason for forms, covering
250
+ * both a bad shape and a reserved word. (Link trees, which look
271
251
  * identical, do distinguish the two; see `LinkTreeSlugAvailability`.)
272
252
  * `suggestions` appears only on the well-formed-but-taken branch.
273
253
  */
@@ -289,10 +269,9 @@ export interface FormEndpointAvailability {
289
269
  */
290
270
  export interface CreateFormInput {
291
271
  /**
292
- * Optional, despite being the thing a person names the form by: the
293
- * controller runs it through `.to_s.strip` and the model only validates its
294
- * LENGTH (200 maximum), so an omitted title saves an untitled form rather
295
- * than failing. Pass one.
272
+ * Optional, despite being the thing a person names the form by: the server
273
+ * trims it and only validates its LENGTH (200 maximum), so an omitted title
274
+ * saves an untitled form rather than failing. Pass one.
296
275
  */
297
276
  readonly title?: string;
298
277
  /**
@@ -11,11 +11,10 @@
11
11
  * {@link JobsNamespace.wait}, so the polling policy lives here once. Do not
12
12
  * write a second polling loop inside a tool module.
13
13
  *
14
- * Only two tools enqueue through the generic `jobs` table - background removal
15
- * and upscale. The other five are polled by re-reading their own row, which is
16
- * still not a reason to write a loop there: {@link pollUntilTerminal} is the
17
- * same engine with a different `poll` function, and that is what those modules
18
- * call.
14
+ * Only two tools hand back a generic job - background removal and upscale.
15
+ * The other five are polled by re-reading their own record, which is still not
16
+ * a reason to write a loop there: {@link pollUntilTerminal} is the same engine
17
+ * with a different `poll` function, and that is what those modules call.
19
18
  *
20
19
  * The loop is deliberately dumb and bounded:
21
20
  *
@@ -44,9 +43,10 @@
44
43
  * that deserves an exception.
45
44
  */
46
45
  import { Resource } from "../http";
47
- import type { BaseRecord, Id, Json, JobStatus, Paginated, PageParams, Progress, RequestOptions, Timestamp, WaitOptions } from "../types";
46
+ import type { ListParams } from "../listing";
47
+ import type { BaseRecord, Id, Json, JobStatus, Paginated, Progress, RequestOptions, Timestamp, WaitOptions } from "../types";
48
48
  /**
49
- * The five status strings, spelled the way the backend spells them.
49
+ * The five status strings, spelled the way the API spells them.
50
50
  *
51
51
  * `complete`, not `completed`. `canceled`, one L. Reach for this object instead
52
52
  * of typing the literal: a loop that waits for `"completed"` waits forever.
@@ -70,31 +70,24 @@ export declare function isJobTerminal(status: string): boolean;
70
70
  /**
71
71
  * A background job.
72
72
  *
73
- * `JobBlueprint` declares thirteen fields and nothing else, so EVERY key below
74
- * is present on every response. A `?` here would mean "the server sometimes
75
- * leaves this out", and it never does; what varies is the VALUE, because most
76
- * of these are nullable columns that fill in as the job moves.
73
+ * EVERY key below is present on every response. A `?` here would mean "the
74
+ * server sometimes leaves this out", and it never does; what varies is the
75
+ * VALUE, because most of these are nullable and fill in as the job moves.
77
76
  *
78
- * Two keys are deliberately NOT here, and a client migrating off the old web
79
- * service will expect them: `updater_id` and `destroyer_id`. Both columns
80
- * exist on the `jobs` table and both are indexed, but `JobBlueprint` renders
81
- * NEITHER, so anything declaring them has been reading `undefined` for as long
82
- * as it has existed. Declaring them here would only move the lie.
77
+ * There is no `updater_id` and no `destroyer_id`; anything declaring them
78
+ * reads `undefined`.
83
79
  */
84
80
  export interface Job extends BaseRecord {
85
81
  readonly status: JobStatus;
86
82
  /**
87
- * Feature-level kind of the run. `Job::JOB_TYPES` holds exactly two strings:
88
- * `"omsvs"` (vocal separation) and `"unknown"`, which is the column default
89
- * every generic enqueue gets - the upscale and background-removal proxies
90
- * included. It is NOT the worker's class name, and a third value cannot
91
- * appear without a model change, because an inclusion validation rejects it.
83
+ * Feature-level kind of the run: `"omsvs"` (vocal separation) or
84
+ * `"unknown"`, which is what every generic enqueue gets - the upscale and
85
+ * background-removal runs included. It is NOT the name of the work done.
92
86
  */
93
87
  readonly job_type: string;
94
88
  /**
95
- * Enqueue-time arguments. The column is `jsonb DEFAULT '{}'`, so a row whose
96
- * enqueuer wrote nothing carries `{}` rather than `null`. Shape depends on
97
- * `job_type`.
89
+ * Enqueue-time arguments. `{}` rather than `null` when the enqueuer wrote
90
+ * nothing. Shape depends on `job_type`.
98
91
  */
99
92
  readonly payload: Json;
100
93
  /** Set when a worker claimed the job; `null` while it is still `"pending"`. */
@@ -102,22 +95,20 @@ export interface Job extends BaseRecord {
102
95
  /** Set when the job reached a terminal state, cancellation included. */
103
96
  readonly finished_at: Timestamp | null;
104
97
  /**
105
- * Percentage, an integer in `[0, 100]`. The column is `NOT NULL DEFAULT 0`
106
- * and the model validates the range, so this is a real number from the
107
- * moment the row exists: `0` means "not started", never "unknown".
98
+ * Percentage, an integer in `[0, 100]`. A real number from the moment the
99
+ * row exists: `0` means "not started", never "unknown".
108
100
  */
109
101
  readonly progress: number;
110
102
  /**
111
103
  * Failure message once `status === "failed"` - and ALSO the reason once
112
- * `"canceled"`, because `Job#cancel!` writes it into this same column. A
104
+ * `"canceled"`, because a cancellation writes its reason here too. A
113
105
  * non-null `error` therefore does not by itself mean the work failed. Read
114
106
  * `status`.
115
107
  */
116
108
  readonly error: string | null;
117
109
  /**
118
- * Whatever the worker returned, stored by `ApplicationJob`'s
119
- * `around_perform`. Shape depends on `job_type`, and the two proxies worth
120
- * naming both answer an object carrying a signed download link:
110
+ * Whatever the work returned. Shape depends on `job_type`, and the two
111
+ * tools worth naming both answer an object carrying a signed download link:
121
112
  *
122
113
  * - upscale: `{ upscale_id, result_url }`;
123
114
  * - background removal: `{ background_removal_id, result_url }`.
@@ -143,10 +134,12 @@ export interface JobRef {
143
134
  /** Signed token scoped to this one job. Required when anonymous. */
144
135
  readonly watchToken?: string;
145
136
  }
137
+ /** Filter columns of `GET /jobs`. */
138
+ export declare const JOB_FILTER_COLUMNS: readonly ["id", "job_type", "status", "created_at", "updated_at", "finished_at"];
146
139
  /** Filters for {@link JobsNamespace.list}. */
147
- export interface ListJobsParams extends PageParams {
148
- readonly status?: JobStatus | JobStatus[];
149
- readonly jobType?: string | string[];
140
+ export interface ListJobsParams extends ListParams<(typeof JOB_FILTER_COLUMNS)[number]> {
141
+ readonly status?: JobStatus | readonly JobStatus[];
142
+ readonly jobType?: string | readonly string[];
150
143
  }
151
144
  /** Pause before the second poll, in milliseconds. */
152
145
  export declare const DEFAULT_POLL_INTERVAL_MS = 1000;
@@ -210,9 +203,8 @@ export declare class JobsNamespace extends Resource {
210
203
  * an anonymous caller sees an empty page - never a 401, because the scope is
211
204
  * empty rather than forbidden.
212
205
  *
213
- * @throws {OmsApiError} 400 naming the key when a filter is not on the
214
- * controller's allowlist (`id`, `job_type`, `status`, `created_at`,
215
- * `updated_at`, `finished_at`).
206
+ * @throws {OmsApiError} 400 naming the key when a filter is not one of
207
+ * `id`, `job_type`, `status`, `created_at`, `updated_at`, `finished_at`.
216
208
  */
217
209
  list(params?: ListJobsParams, options?: RequestOptions): Promise<Paginated<Job>>;
218
210
  /**
@@ -224,7 +216,7 @@ export declare class JobsNamespace extends Resource {
224
216
  *
225
217
  * @throws {OmsApiError} 404 when the job is gone, which for a finished job
226
218
  * also happens once its retention window expires. A wrong, expired or
227
- * missing watch token is the same 404, not a 401: the controller never says
219
+ * missing watch token is the same 404, not a 401: the server never says
228
220
  * whether the id exists.
229
221
  */
230
222
  get(ref: JobRef | Id, options?: RequestOptions): Promise<Job>;
@@ -262,13 +254,12 @@ export declare function jobRef(ref: JobRef | Id): JobRef;
262
254
  * Renders a job as a {@link Progress}.
263
255
  *
264
256
  * `total` is 100 rather than `undefined` because `progress` is a percentage the
265
- * server always has: the column is `NOT NULL DEFAULT 0`, so there is no
266
- * "unknown" to be honest about.
257
+ * server always has: there is no "unknown" to be honest about.
267
258
  *
268
259
  * The `typeof` guard is not defensive typing for its own sake. `Job.progress`
269
- * is declared non-nullable because the column is, but this function is also
270
- * handed rows that came off `JobChannel` and rows a host deserialised itself,
271
- * and reading `undefined` as `NaN%` would put a broken number on a progress
272
- * bar rather than a zero.
260
+ * is declared non-nullable, but this function is also handed rows that came
261
+ * off the realtime job channel and rows a host deserialised itself, and
262
+ * reading `undefined` as `NaN%` would put a broken number on a progress bar
263
+ * rather than a zero.
273
264
  */
274
265
  export declare function jobProgress(job: Job): Progress;
@@ -0,0 +1,162 @@
1
+ /** The `library.annotations` namespace, with the inputs and limits only it uses. */
2
+ import { Resource } from "../../http";
3
+ import type { ListParams } from "../../listing";
4
+ import type { Paginated, RequestOptions } from "../../types";
5
+ import type { BookAnnotation, BookAnnotationId, BookAnnotationKind, BookAnnotationLocation, BookId } from "./types";
6
+ /** Longest note accepted. */
7
+ export declare const BOOK_ANNOTATION_NOTE_MAX_LENGTH = 5000;
8
+ /** Longest selected text accepted. */
9
+ export declare const BOOK_ANNOTATION_SELECTED_TEXT_MAX_LENGTH = 8000;
10
+ /** Filter columns of `GET /book_annotations`, on top of {@link BASE_FILTER_COLUMNS}. */
11
+ export declare const BOOK_ANNOTATION_FILTER_COLUMNS: readonly ["book_id", "kind"];
12
+ /** Arguments for {@link LibraryAnnotationsNamespace.list}. */
13
+ export interface ListBookAnnotationsParams extends ListParams<(typeof BOOK_ANNOTATION_FILTER_COLUMNS)[number]> {
14
+ /** Exact book id. The filter every reader screen uses. */
15
+ readonly bookId?: BookId;
16
+ /** Exact kind, or an array of kinds (which becomes `IN (...)`). */
17
+ readonly kind?: BookAnnotationKind | readonly BookAnnotationKind[];
18
+ /** `"column:asc"` / `"column:desc"`. Defaults to `created_at:asc`. */
19
+ readonly order?: string;
20
+ }
21
+ /** Arguments for {@link LibraryAnnotationsNamespace.create}. */
22
+ export interface CreateBookAnnotationInput {
23
+ readonly bookId: BookId;
24
+ readonly kind: BookAnnotationKind;
25
+ /** Omitted or empty becomes `{}`, which is a valid annotation with no anchor. */
26
+ readonly location?: BookAnnotationLocation;
27
+ readonly color?: string | null;
28
+ readonly note?: string | null;
29
+ readonly selectedText?: string | null;
30
+ }
31
+ /**
32
+ * Arguments for {@link LibraryAnnotationsNamespace.update}.
33
+ *
34
+ * `kind`, `book_id` and `selected_text` are NOT updatable: only `color`,
35
+ * `note` and `location` are read. Anything else is dropped in silence - a 200
36
+ * with an unchanged row.
37
+ */
38
+ export interface UpdateBookAnnotationInput {
39
+ readonly color?: string | null;
40
+ readonly note?: string | null;
41
+ /**
42
+ * Only sent when the key is present, because the server tests for the key
43
+ * rather than for a value. Passing `{}` therefore CLEARS the anchor rather
44
+ * than leaving it alone.
45
+ */
46
+ readonly location?: BookAnnotationLocation;
47
+ }
48
+ /** The `library.annotations` namespace, reachable as `oms.library.annotations`. */
49
+ export declare class LibraryAnnotationsNamespace extends Resource {
50
+ /**
51
+ * `GET /book_annotations` - the caller's own highlights, notes, bookmarks and
52
+ * progress markers.
53
+ *
54
+ * There is no owner filter and there does not need to be one: a caller can
55
+ * only ever see its own rows - even on a book a thousand people have public
56
+ * access to.
57
+ *
58
+ * Unlike every read in the other two namespaces, this one needs a session,
59
+ * so an anonymous call is a `401`, not an empty list.
60
+ *
61
+ * Ordered by `created_at` ascending by default (the controller adds the
62
+ * `order(:created_at)` itself), which is reading order for a set of
63
+ * highlights. Override it with `order` for a "recently annotated" view.
64
+ *
65
+ * Filtering by `bookId` is the normal call, and it is what opens a reader:
66
+ * one request per book, not one per highlight.
67
+ *
68
+ * @throws {OmsApiError} 400 naming the offending key when a filter is not
69
+ * one of `book_id`, `kind`, `id`, `created_at`, `updated_at`.
70
+ */
71
+ list(params?: ListBookAnnotationsParams, options?: RequestOptions): Promise<Paginated<BookAnnotation>>;
72
+ /**
73
+ * Every annotation on one book, in reading order, following pages until the
74
+ * book is exhausted.
75
+ *
76
+ * A convenience over {@link list} because this is what a reader does on open
77
+ * and because a heavily annotated book genuinely passes 500 rows - the point
78
+ * at which one page stops being enough and a naive caller silently loses the
79
+ * rest.
80
+ *
81
+ * `kinds` narrows to, say, highlights only. It becomes an `IN (...)`.
82
+ */
83
+ forBook(bookId: BookId, params?: {
84
+ kinds?: readonly BookAnnotationKind[];
85
+ pageSize?: number;
86
+ }, options?: RequestOptions): Promise<BookAnnotation[]>;
87
+ /**
88
+ * The reader's "where I left off" marker for one book, or `null` when they
89
+ * have never opened it.
90
+ *
91
+ * There is at most one, because
92
+ * {@link LibraryBooksNamespace.saveProgress} upserts on
93
+ * `(book, user, kind: "progress")`. This reads it back; that writes it.
94
+ */
95
+ progressFor(bookId: BookId, options?: RequestOptions): Promise<BookAnnotation | null>;
96
+ /**
97
+ * "What am I in the middle of?" - the reader's most recently touched progress
98
+ * markers, newest first.
99
+ *
100
+ * One request for the whole continue-reading shelf, which is the point: the
101
+ * alternative is one request per cover. The rows carry `book_id` and nothing
102
+ * about the book, so pair it with
103
+ * {@link LibraryBooksNamespace.list} filtered by `ids` to get the titles in a
104
+ * second request rather than in N.
105
+ *
106
+ * @param limit rows to return. Clamped to 500 by the server like any page.
107
+ */
108
+ continueReading(limit?: number, options?: RequestOptions): Promise<BookAnnotation[]>;
109
+ /**
110
+ * `POST /book_annotations` - records a highlight, a note or a bookmark.
111
+ *
112
+ * The author is taken from the session, so `user_id` is not sendable. The
113
+ * book additionally has to be visible to the caller, which is what lets a
114
+ * reader annotate somebody else's public book while keeping the annotation
115
+ * entirely private to them.
116
+ *
117
+ * Do NOT use this for reading progress. It would create a SECOND `progress`
118
+ * row - nothing here de-duplicates by kind - and the reader would then have
119
+ * two conflicting "where I left off" markers with no way to tell which is
120
+ * live. {@link LibraryBooksNamespace.saveProgress} upserts; this does not.
121
+ *
122
+ * Not retried by default: a replay after a lost answer duplicates the
123
+ * highlight.
124
+ *
125
+ * @throws {OmsAuthError} 401 twice over, with different bodies: `"Session
126
+ * required to access this resource."` when anonymous, and `"You are not
127
+ * authorized to create this resource"` when the book is not visible to
128
+ * the caller - a 401 rather than the 404 you might expect.
129
+ * @throws {OmsApiError} 400 for a `kind` outside
130
+ * {@link BOOK_ANNOTATION_KINDS}, or a note or selection over its length
131
+ * cap.
132
+ */
133
+ create(input: CreateBookAnnotationInput, options?: RequestOptions): Promise<BookAnnotation>;
134
+ /**
135
+ * `PATCH /book_annotations/:id` - edits the note or the colour of an existing
136
+ * annotation, and optionally moves it.
137
+ *
138
+ * Only `color`, `note` and `location` are writable. `kind`, `book_id` and
139
+ * `selected_text` are dropped in silence - a `200` with an unchanged row,
140
+ * which is the failure mode worth knowing about here. To change a highlight
141
+ * into a note, delete and recreate.
142
+ *
143
+ * `location` is only sent when you pass one, because the server tests for
144
+ * the key: passing `{}` therefore CLEARS the anchor rather than leaving it
145
+ * alone.
146
+ *
147
+ * @throws {OmsAuthError} 401 when the annotation is not yours.
148
+ * @throws {OmsApiError} 404 for an unknown id - and for anyone else's
149
+ * annotation, since nobody else's are ever visible.
150
+ */
151
+ update(id: BookAnnotationId, input: UpdateBookAnnotationInput, options?: RequestOptions): Promise<BookAnnotation>;
152
+ /**
153
+ * `DELETE /book_annotations/:id` - removes one annotation.
154
+ *
155
+ * Deleting a `progress` row is how a reader is put back at the start of a
156
+ * book; there is no other reset.
157
+ *
158
+ * @throws {OmsAuthError} 401 when the annotation is not yours.
159
+ * @throws {OmsApiError} 404 the second time round.
160
+ */
161
+ delete(id: BookAnnotationId, options?: RequestOptions): Promise<void>;
162
+ }