@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
@@ -0,0 +1,322 @@
1
+ /** Relationships: friendships and blocks, and `oms.social.relationships`. */
2
+ import { Resource } from "../../http";
3
+ import type { ListParams } from "../../listing";
4
+ import type { User } from "../account";
5
+ import type { Id, Paginated, RequestOptions, Timestamp } from "../../types";
6
+ /** Primary key of a relationship row. An integer, for the same reason. */
7
+ export type RelationshipId = number;
8
+ /** A relationship row: one friendship or one block, between two users. */
9
+ export interface Relationship {
10
+ /** Integer. */
11
+ readonly id: RelationshipId;
12
+ readonly created_at: Timestamp;
13
+ readonly updated_at: Timestamp;
14
+ readonly kind: RelationshipKind;
15
+ readonly status: RelationshipStatus;
16
+ /** Whoever created the row. Always the authenticated user at create time. */
17
+ readonly requester_id: Id;
18
+ readonly accepter_id: Id;
19
+ readonly requester: User;
20
+ readonly accepter: User;
21
+ }
22
+ /** What a relationship row means. */
23
+ export type RelationshipKind = "friend" | "block";
24
+ /** Where a relationship row is in its lifecycle. */
25
+ export type RelationshipStatus = "pending" | "accepted";
26
+ /** Filter columns of `GET /relationships`, on top of {@link BASE_FILTER_COLUMNS}. */
27
+ export declare const RELATIONSHIP_FILTER_COLUMNS: readonly ["requester_id", "accepter_id"];
28
+ /** `extra_options` keys of `GET /relationships`. */
29
+ export declare const RELATIONSHIP_EXTRA_OPTION_KEYS: readonly ["user_id"];
30
+ /** `extra_options` of `GET /relationships`. `user_id` matches rows where the user is either end. */
31
+ export interface RelationshipExtraOptions {
32
+ readonly user_id?: Id;
33
+ }
34
+ /** Filters accepted by {@link RelationshipsNamespace.list}. */
35
+ export interface ListRelationshipsParams extends ListParams<(typeof RELATIONSHIP_FILTER_COLUMNS)[number], RelationshipExtraOptions> {
36
+ /**
37
+ * `extra_options[user_id]`: rows where this user is either end.
38
+ *
39
+ * Worth passing your own id even though it narrows nothing. The filter is
40
+ * what makes the server preload both ends of every row. Without it the
41
+ * nested {@link User} for both ends of every row is rendered out of an
42
+ * unprepared query - two extra `SELECT`s per relationship.
43
+ */
44
+ readonly userId?: Id;
45
+ /** `exact_search[requester_id]`: rows this user created. */
46
+ readonly requesterId?: Id;
47
+ /** `exact_search[accepter_id]`: rows aimed at this user. */
48
+ readonly accepterId?: Id;
49
+ }
50
+ /** Body of {@link RelationshipsNamespace.create}. */
51
+ export interface CreateRelationshipInput {
52
+ /** The other user. */
53
+ readonly userId: Id;
54
+ /** `"friend"` for a request, `"block"` for a block. */
55
+ readonly kind: RelationshipKind;
56
+ }
57
+ /**
58
+ * Friendships and blocks, reachable as `oms.social.relationships`.
59
+ *
60
+ * ## The state machine is TWO columns, not one
61
+ *
62
+ * There is no single `status` enum with a `blocked` member, however the UIs
63
+ * present it. A row carries `kind` (`friend` | `block`) and `status`
64
+ * (`pending` | `accepted`), and only three of the four combinations exist:
65
+ *
66
+ * | kind | status | what it is |
67
+ * | -------- | ---------- | ---------------------------------------------- |
68
+ * | `friend` | `pending` | a friend request, awaiting the accepter |
69
+ * | `friend` | `accepted` | a friendship |
70
+ * | `block` | `accepted` | the requester has blocked the accepter |
71
+ *
72
+ * `block` + `pending` is unreachable: a block is forced to `accepted` at
73
+ * birth, which also means a block's status can never be edited afterwards
74
+ * (see the transition rules below). Blocking is asymmetric and direction
75
+ * matters - `requester_id` blocked `accepter_id`, never the reverse.
76
+ *
77
+ * ## Transitions the server will accept
78
+ *
79
+ * `PATCH` may write `status` and nothing else. Any change whose PREVIOUS value
80
+ * was `accepted` is aborted, so:
81
+ *
82
+ * - `pending -> accepted` is the one real transition, and it is what
83
+ * {@link accept} does;
84
+ * - `pending -> pending` is a no-op that answers `200`, because nothing
85
+ * changed and the guard only fires on a change;
86
+ * - `accepted -> pending` is refused, `400 "Status cannot be changed"`;
87
+ * - `accepted -> accepted` is a no-op `200`, same reason as above;
88
+ * - anything outside `pending` / `accepted` is refused by the inclusion
89
+ * validation, `400 "Status is not included in the list"`.
90
+ *
91
+ * There is no un-accept, no un-block and no "decline" verb. Ending ANY
92
+ * relationship - rejecting a request, unfriending, unblocking - is
93
+ * {@link delete} on the row. That is one method for three intentions, and the
94
+ * server cannot tell them apart either.
95
+ *
96
+ * ## EITHER PARTY CAN ACCEPT. INCLUDING THE ONE WHO ASKED.
97
+ *
98
+ * Either end of the row may `PATCH` it, and nothing narrows that for the
99
+ * `pending -> accepted` transition. So the sender of a friend request can
100
+ * `PATCH` their own request to `accepted` and become the recipient's friend
101
+ * without the recipient doing anything.
102
+ *
103
+ * That is a real hole, not a subtlety of this SDK, and it is load-bearing
104
+ * because friendship gates real things elsewhere in the API - a `friends`
105
+ * playlist becomes visible, the friends listening feed starts carrying that
106
+ * user's playback. Do not build a UI that offers the requester an accept
107
+ * button, and do not treat `status: "accepted"` as proof of consent from the
108
+ * accepter.
109
+ *
110
+ * ## A block you receive is INVISIBLE to you
111
+ *
112
+ * A block aimed at you is hidden from listings AND from lookups by id. You
113
+ * can see blocks you made; you cannot see, list, count or delete a block
114
+ * someone made against you. Its only observable effect is that
115
+ * {@link DirectMessagesNamespace.send} answers `401`.
116
+ *
117
+ * ## Realtime
118
+ *
119
+ * Both interesting events reach the other party as `NotificationsChannel`
120
+ * pushes rather than as anything on this namespace: `friendship_request`
121
+ * (`{ asker_id, asker_handle }`) when a `friend`/`pending` row is created, and
122
+ * `friendship_accepted` (`{ accepter_id, accepter_handle }`) when it flips.
123
+ * Neither carries the relationship row, so a client still has to
124
+ * {@link list} after the nudge. `block`, `delete` and every failed transition
125
+ * are silent.
126
+ */
127
+ export declare class RelationshipsNamespace extends Resource {
128
+ /**
129
+ * `GET /relationships` - every relationship the caller is part of, in either
130
+ * direction, minus the blocks aimed at them.
131
+ *
132
+ * ## `kind` AND `status` ARE NOT FILTERABLE
133
+ *
134
+ * The filter columns are `requester_id, accepter_id` plus `id, created_at,
135
+ * updated_at`. `kind` and `status` are absent, and an unknown filter key
136
+ * does not get dropped - it is `400 "Unknown search filter: kind"`. So "list
137
+ * my friends" is not a query the API can answer: fetch the rows and filter
138
+ * here. {@link friends}, {@link incomingRequests}, {@link outgoingRequests}
139
+ * and {@link blocked} do exactly that.
140
+ *
141
+ * This is the single most surprising thing about the endpoint.
142
+ *
143
+ * ## Paging
144
+ *
145
+ * The SDK sends an explicit `modifiers[page]` and an explicit
146
+ * `created_at:desc` order, for the usual reason: with no page the server
147
+ * silently forces `1:500`, and offset paging over an unordered query can
148
+ * repeat and skip rows. A client that sends neither truncates at 500 rows
149
+ * without saying so - a real ceiling for an account with a long history,
150
+ * since blocks and dead requests count towards it.
151
+ *
152
+ * Indexes carry an `ETag`, so a conditional GET can come back `304`; the SDK
153
+ * does not send `If-None-Match` of its own.
154
+ */
155
+ list(params?: ListRelationshipsParams, options?: RequestOptions): Promise<Paginated<Relationship>>;
156
+ /**
157
+ * Every relationship row, paged out in full and filtered in memory.
158
+ *
159
+ * The building block under {@link friends} and its siblings, exported
160
+ * because "fetch them all, then filter" is the only shape this endpoint
161
+ * supports and every client ends up writing it.
162
+ *
163
+ * `limit` caps how many rows are pulled, so a pathological account cannot
164
+ * turn one call into an unbounded walk. It defaults to 2000, which is four
165
+ * requests at the server's maximum page size.
166
+ */
167
+ all(params?: ListRelationshipsParams, limit?: number, options?: RequestOptions): Promise<Relationship[]>;
168
+ /**
169
+ * The caller's accepted friends, as {@link User} records rather than as
170
+ * relationship rows.
171
+ *
172
+ * `selfId` is required and is NOT fetched for you: knowing which end of the
173
+ * row is "the other person" needs the caller's own id, and this namespace
174
+ * refuses to spend a `GET /sessions/mine` on every call to find it. Take it
175
+ * from `oms.account.me()` once and keep it.
176
+ *
177
+ * A friend appears exactly once even though the row could be in either
178
+ * direction. The result is derived from the same nested `requester` /
179
+ * `accepter` objects the listing already carries, so this costs no extra
180
+ * request beyond the paging {@link all} does.
181
+ */
182
+ friends(selfId: Id, options?: RequestOptions): Promise<User[]>;
183
+ /**
184
+ * Friend requests waiting for the caller to answer: `friend` + `pending`
185
+ * rows where the caller is the ACCEPTER.
186
+ *
187
+ * These are the ones {@link accept} is meant for. Answer with {@link accept}
188
+ * or refuse with {@link delete}; there is no third verb.
189
+ *
190
+ * This walks the listing itself, as do {@link friends}, {@link blocked} and
191
+ * {@link outgoingRequests}, because the server cannot filter on `kind` or
192
+ * `status`. A screen that wants more than one of them should call
193
+ * {@link all} ONCE and sort the rows with {@link isFriendship},
194
+ * {@link isPendingRequest} and {@link isBlock} rather than paying for the
195
+ * same walk four times.
196
+ */
197
+ incomingRequests(selfId: Id, options?: RequestOptions): Promise<Relationship[]>;
198
+ /**
199
+ * Friend requests the caller sent and nobody has answered: `friend` +
200
+ * `pending` rows where the caller is the REQUESTER.
201
+ *
202
+ * {@link delete} on one of these is a cancel. {@link accept} on one of these
203
+ * works too, and should not - see the class docs.
204
+ */
205
+ outgoingRequests(selfId: Id, options?: RequestOptions): Promise<Relationship[]>;
206
+ /**
207
+ * Users the caller has blocked.
208
+ *
209
+ * Only blocks the caller MADE. A block made against the caller is hidden
210
+ * and cannot be enumerated by any means; see the class docs.
211
+ */
212
+ blocked(selfId: Id, options?: RequestOptions): Promise<User[]>;
213
+ /**
214
+ * `POST /relationships` - creates a row. `201` with the record.
215
+ *
216
+ * `requester_id` is forced to the authenticated user and `status` is not
217
+ * writable: a `friend` starts `pending`, a `block` is born `accepted`.
218
+ * Prefer {@link request} and {@link block}, which say which of the two you
219
+ * meant.
220
+ *
221
+ * @throws {OmsApiError} `400 "Cannot create relationship with yourself"`,
222
+ * or `400 "A relationship of this kind already exists between these
223
+ * users"` when a `friend` row already exists in either direction.
224
+ */
225
+ create(input: CreateRelationshipInput, options?: RequestOptions): Promise<Relationship>;
226
+ /**
227
+ * Sends a friend request: `create({ kind: "friend" })`.
228
+ *
229
+ * At most one `friend` row may exist between two users in either direction,
230
+ * and the uniqueness check runs UNSCOPED - it sees rows the default scope
231
+ * hides from you. So a second request answers `400 "A relationship of this
232
+ * kind already exists between these users"`, and so does requesting someone
233
+ * who has already requested you (accept theirs instead) and, less obviously,
234
+ * requesting someone who has blocked you: their block row counts as an
235
+ * existing relationship. That last case is the only signal the API gives that
236
+ * a block against you exists, and it is indistinguishable from a duplicate
237
+ * request.
238
+ *
239
+ * The accepter gets a `friendship_request` notification over the cable.
240
+ */
241
+ request(userId: Id, options?: RequestOptions): Promise<Relationship>;
242
+ /**
243
+ * Blocks a user: `create({ kind: "block" })`.
244
+ *
245
+ * Three things happen server-side that no other call does:
246
+ *
247
+ * 1. the row is born `accepted`, so its status is immediately frozen;
248
+ * 2. every existing relationship between the two of you is DELETED first -
249
+ * an accepted friendship is gone, not suspended, and unblocking later
250
+ * does not bring it back;
251
+ * 3. that deletion is skipped when a block already exists between you in
252
+ * EITHER direction, which also means **blocking is not idempotent**: a
253
+ * second call creates a SECOND block row rather than answering with the
254
+ * first, because the uniqueness validation deliberately exempts blocks.
255
+ * Check {@link blocked} before calling, and unblock all the rows you find.
256
+ *
257
+ * The effect on the other user is exactly one thing: their
258
+ * {@link DirectMessagesNamespace.send} to you starts answering `401`. It does
259
+ * not stop you messaging them, it does not hide either profile, and it does
260
+ * not remove either of you from the other's
261
+ * {@link DirectMessagesNamespace.conversedUsers}, which is built from message
262
+ * history rather than from relationships.
263
+ *
264
+ * The blocked user is not notified.
265
+ */
266
+ block(userId: Id, options?: RequestOptions): Promise<Relationship>;
267
+ /**
268
+ * `PATCH /relationships/:id` with `status: "accepted"` - accepts a pending
269
+ * friend request. `200` with the updated record.
270
+ *
271
+ * Only ever call this on a row from {@link incomingRequests}. The server will
272
+ * happily accept one of your OWN outgoing requests, which is a hole, not a
273
+ * feature; see the class docs.
274
+ *
275
+ * The requester gets a `friendship_accepted` notification.
276
+ *
277
+ * @throws {OmsApiError} `400 "Status cannot be changed"` when the row was
278
+ * already `accepted` and something is trying to move it back; `401` when
279
+ * the caller is neither end of the row; `404 "Resource not found"` when the
280
+ * id is not visible to the caller - which includes a block made against
281
+ * them.
282
+ */
283
+ accept(id: RelationshipId, options?: RequestOptions): Promise<Relationship>;
284
+ /**
285
+ * `DELETE /relationships/:id` - `204`, empty body.
286
+ *
287
+ * The one verb for every ending: rejecting an incoming request, cancelling an
288
+ * outgoing one, unfriending, and unblocking. Either party may call it, and
289
+ * the row is gone for both - there is no soft state and no history.
290
+ *
291
+ * Unblocking does NOT restore the friendship the block destroyed on its way
292
+ * in. That row was deleted, not archived.
293
+ *
294
+ * Nobody is notified, so the other side finds out by noticing the row is no
295
+ * longer in their listing.
296
+ *
297
+ * `GET /relationships/:id` does not exist. Read a single row out of
298
+ * {@link list} instead.
299
+ */
300
+ delete(id: RelationshipId, options?: RequestOptions): Promise<void>;
301
+ }
302
+ /**
303
+ * The user at the other end of a relationship row, given the caller's own id.
304
+ *
305
+ * A relationship is stored with a direction (`requester` asked, `accepter` was
306
+ * asked) that a friends list does not care about, so every client writes this
307
+ * function. It is here once instead.
308
+ *
309
+ * Returns `undefined` when `selfId` is neither end of the row, and when the
310
+ * nested user object is missing - which the API does not currently do, but is
311
+ * treated as possible rather than asserted away.
312
+ */
313
+ export declare function counterpart(relationship: Relationship, selfId: Id): User | undefined;
314
+ /** `kind === "friend" && status === "accepted"`. */
315
+ export declare function isFriendship(relationship: Relationship): boolean;
316
+ /** An unanswered friend request, in either direction. */
317
+ export declare function isPendingRequest(relationship: Relationship): boolean;
318
+ /**
319
+ * A block the CALLER made. There is no such thing as a visible block against
320
+ * the caller - see {@link RelationshipsNamespace}.
321
+ */
322
+ export declare function isBlock(relationship: Relationship): boolean;
@@ -0,0 +1,37 @@
1
+ /** What direct messages and group chats share: the attachment kind and the caps both message families obey. */
2
+ import type { Timestamp } from "../../types";
3
+ /**
4
+ * 25 MiB, for a direct message and a group chat message alike, checked before
5
+ * anything is attached.
6
+ *
7
+ * IMAGES HAVE A LOWER, WORSE-BEHAVED CEILING. See
8
+ * {@link MESSAGE_IMAGE_MAX_BYTES}.
9
+ */
10
+ export declare const MESSAGE_ATTACHMENT_MAX_BYTES: number;
11
+ /**
12
+ * Fifteen minutes from `created_at`, for a direct message and a group chat
13
+ * message alike, after which an edit is `401`.
14
+ *
15
+ * Measured against the SERVER's clock. {@link canEditMessage} compares against
16
+ * the caller's, which is close enough to grey out a button and not close
17
+ * enough to promise the edit will land.
18
+ */
19
+ export declare const MESSAGE_EDIT_WINDOW_MS: number;
20
+ /** How the server classified an attachment, from its `content_type`. */
21
+ export type AttachmentKind = "image" | "audio" | "video" | "file";
22
+ /**
23
+ * Whether a message is still inside its edit window, for greying out a button.
24
+ *
25
+ * Measured against the CALLER's clock, and the server measures against its own,
26
+ * so this is an approximation that gets less honest the further the two drift.
27
+ * Always handle the `401` as well; do not treat `true` here as a promise that
28
+ * the edit will land, and do not treat `false` as a reason to skip the call if
29
+ * the user insists.
30
+ *
31
+ * Takes `now` so the function stays pure and the module stays isolate-safe -
32
+ * no `Date.now()` at module scope, and a caller can pass a server-derived
33
+ * clock if it has one.
34
+ */
35
+ export declare function canEditMessage(message: {
36
+ created_at: Timestamp;
37
+ }, now?: number): boolean;
@@ -68,8 +68,9 @@
68
68
  * cost actually is.
69
69
  */
70
70
  import { Resource } from "../http";
71
+ import type { ListParams } from "../listing";
71
72
  import type { User } from "./account";
72
- import type { BaseRecord, FileInput, Id, NativeFile, PageParams, Paginated, RequestOptions, Timestamp } from "../types";
73
+ import type { BaseRecord, FileInput, Id, NativeFile, Paginated, RequestOptions, Timestamp } from "../types";
73
74
  /**
74
75
  * Primary key of a direct message. An INTEGER: `messages` is one of the tables
75
76
  * that kept an auto-increment key, so `id` and `quoted_message_id` are JSON
@@ -296,8 +297,17 @@ export declare class SocialNamespace extends Resource {
296
297
  readonly groupChats: GroupChatsNamespace;
297
298
  constructor(http: ConstructorParameters<typeof Resource>[0]);
298
299
  }
300
+ /** Filter columns of `GET /messages`. */
301
+ export declare const MESSAGE_FILTER_COLUMNS: readonly ["id", "created_at", "updated_at", "content", "sender_id", "receiver_id", "read_at"];
302
+ /** `extra_options` keys of `GET /messages`. */
303
+ export declare const MESSAGE_EXTRA_OPTION_KEYS: readonly ["user_id", "other_user_id"];
304
+ /** `extra_options` of `GET /messages`. Each matches rows where the user is either end. */
305
+ export interface MessageExtraOptions {
306
+ readonly user_id?: Id;
307
+ readonly other_user_id?: Id;
308
+ }
299
309
  /** Filters accepted by {@link DirectMessagesNamespace.list}. */
300
- export interface ListMessagesParams extends PageParams {
310
+ export interface ListMessagesParams extends ListParams<(typeof MESSAGE_FILTER_COLUMNS)[number], MessageExtraOptions> {
301
311
  /**
302
312
  * The other end of the conversation. Sent as
303
313
  * `extra_options[other_user_id]`, which the server expands to
@@ -621,8 +631,16 @@ export declare class DirectMessagesNamespace extends Resource {
621
631
  */
622
632
  attachmentUrl(id: MessageId): Promise<string>;
623
633
  }
634
+ /** Filter columns of `GET /relationships`, on top of {@link BASE_FILTER_COLUMNS}. */
635
+ export declare const RELATIONSHIP_FILTER_COLUMNS: readonly ["requester_id", "accepter_id"];
636
+ /** `extra_options` keys of `GET /relationships`. */
637
+ export declare const RELATIONSHIP_EXTRA_OPTION_KEYS: readonly ["user_id"];
638
+ /** `extra_options` of `GET /relationships`. `user_id` matches rows where the user is either end. */
639
+ export interface RelationshipExtraOptions {
640
+ readonly user_id?: Id;
641
+ }
624
642
  /** Filters accepted by {@link RelationshipsNamespace.list}. */
625
- export interface ListRelationshipsParams extends PageParams {
643
+ export interface ListRelationshipsParams extends ListParams<(typeof RELATIONSHIP_FILTER_COLUMNS)[number], RelationshipExtraOptions> {
626
644
  /**
627
645
  * `extra_options[user_id]`: rows where this user is either end.
628
646
  *
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * The direct-upload driver.
3
3
  *
4
- * Bytes never pass through Rails. The flow the backend implements, and the one
5
- * this module follows exactly:
4
+ * Bytes never pass through the API. The flow:
6
5
  *
7
6
  * 1. `POST /fs_nodes/batch_upload_urls` with a manifest of up to 100 files
8
7
  * (`client_id`, `name`, `size`, and optionally `relative_path`,
9
8
  * `content_type`, `checksum`). ONE request does directory resolution, one
10
- * quota reservation under a single lock, node creation and plan minting.
9
+ * quota reservation, node creation and plan minting.
11
10
  * 2. Per file the server answers a {@link UploadPlan}:
12
11
  * - `strategy: "direct"` below 32 MiB: PUT the whole body to a presigned URL
13
12
  * with the exact headers returned, then remember `blob_signed_id`;
@@ -25,27 +24,21 @@
25
24
  * self-contained implementation - see the note there.
26
25
  * - The presigned PUTs go to the object store, NOT to the API. They must be
27
26
  * sent with the injected fetch but WITHOUT the `Authorization` header, or
28
- * MinIO rejects the request for having two authentication schemes.
27
+ * the store rejects the request for having two authentication schemes.
29
28
  *
30
29
  * A node whose bytes never landed is adopted on the next attempt rather than
31
30
  * failing, so a torn batch is simply retried with the same manifest.
32
31
  *
33
- * Multipart is not an optimisation. The object store sits behind Cloudflare on
34
- * a plan that caps a request body at roughly 100 MB, so anything larger has no
35
- * other way in.
32
+ * Multipart is not an optimisation. A single request to the object store is
33
+ * capped at roughly 100 MB, so anything larger has no other way in.
36
34
  *
37
35
  * ## Progress, and why it ticks per transfer rather than per byte
38
36
  *
39
- * The bytes go to a presigned MinIO URL. Rails is never in the data path, and
40
- * neither is rack-attack - so a progress bar here is a pure client-side
41
- * problem, and the SDK solves it as far as `fetch` allows and no further.
37
+ * `fetch` has no upload-progress event, and the two ways around it were both
38
+ * rejected for the core:
42
39
  *
43
- * `fetch` has no upload-progress event. The two ways out were weighed and both
44
- * were rejected for the core:
45
- *
46
- * - **XHR**, which is what the web frontend's axios uses today, is the only API
47
- * that reports request bytes as they leave. It does not exist in a
48
- * Cloudflare-Worker-class isolate, and this package must load there.
40
+ * - **XHR** is the only API that reports request bytes as they leave. It does
41
+ * not exist in a Worker-class isolate, and this package must load there.
49
42
  * - **A counting `ReadableStream` request body** would run in an isolate, and
50
43
  * still does not work HERE. A stream body forces chunked transfer encoding,
51
44
  * while a presigned PUT is signed over a fixed `Content-Length` (and, on the
@@ -82,35 +75,28 @@ import type { FsNode } from "../storage";
82
75
  * import { MULTIPART_THRESHOLD } from "@omelhorsite/sdk";
83
76
  * ```
84
77
  *
85
- * The number was verified in all three places it is currently written down, and
86
- * as of this writing they agree:
87
- *
88
- * - `FsServices::NodeBatchCreator::MULTIPART_THRESHOLD = 32.megabytes`, which
89
- * is the only one that decides anything. The server compares
90
- * `entry[:size] >= MULTIPART_THRESHOLD` and puts `strategy` in the plan.
91
- * - the web frontend's `lib/upload_core.ts`, which keeps its own literal.
92
- * - here.
93
- *
94
- * The client-side copies exist because the CHECKSUM has to be in the manifest
95
- * before the server has decided anything: below the threshold the digest is
96
- * mandatory (it is Content-MD5-bound into the presigned signature), at or above
97
- * it is pointless (multipart verifies per-part ETags). So the comparison is
98
- * made twice, and {@link manifestEntryFor} uses `<` against exactly the
99
- * server's `>=`.
78
+ * The server decides the strategy per file with `size >= 32 MiB` and puts it
79
+ * in the plan. The client-side copy exists because the CHECKSUM has to be in
80
+ * the manifest before the server has decided anything: below the threshold
81
+ * the digest is mandatory (it is Content-MD5-bound into the presigned
82
+ * signature), at or above it is pointless (multipart verifies per-part ETags).
83
+ * So the comparison is made twice, and {@link manifestEntryFor} uses `<`
84
+ * against exactly the server's `>=`.
100
85
  *
101
86
  * Drift is expensive and silent in one direction: a client that thinks the
102
87
  * threshold is HIGHER than the server's omits the checksum on a file the server
103
- * still plans as direct, and the upload dies at MinIO with a signature error
104
- * that never mentions checksums. That is the whole reason this is exported.
88
+ * still plans as direct, and the upload dies at the object store with a
89
+ * signature error that never mentions checksums. That is the whole reason this
90
+ * is exported.
105
91
  */
106
92
  export declare const MULTIPART_THRESHOLD: number;
107
93
  /**
108
- * Part size for the multipart path. Mirrors the backend, but it is only a
94
+ * Part size for the multipart path. The server's default, but only a
109
95
  * fallback: the real part size is whatever `multipart/start` answered, and that
110
96
  * is the number the driver slices with.
111
97
  */
112
98
  export declare const MULTIPART_PART_SIZE: number;
113
- /** Maximum files in one `batch_upload_urls` call. Mirrors the backend. */
99
+ /** Maximum files in one `batch_upload_urls` call. Server limit. */
114
100
  export declare const MAX_BATCH = 100;
115
101
  /**
116
102
  * Files sent in one `batch_upload_urls` call by default.
@@ -120,25 +106,25 @@ export declare const MAX_BATCH = 100;
120
106
  * run leaves reserved-but-unused bytes behind.
121
107
  */
122
108
  export declare const DEFAULT_BATCH_SIZE = 50;
123
- /** Maximum part URLs requested in one call. Mirrors the backend. */
109
+ /** Maximum part URLs requested in one call. Server limit. */
124
110
  export declare const MAX_PART_URLS = 100;
125
- /** Parts one multipart upload may have. Mirrors the backend's `MAX_PARTS`. */
111
+ /** Parts one multipart upload may have. Server limit. */
126
112
  export declare const MAX_PARTS = 10000;
127
113
  /** Part URLs asked for in one round trip. Below {@link MAX_PART_URLS} on purpose. */
128
114
  export declare const PART_URL_WINDOW = 32;
129
- /** Parallel presigned PUTs in flight by default. The store is a Pi behind Cloudflare. */
115
+ /** Parallel presigned PUTs in flight by default. Keep it modest. */
130
116
  export declare const DEFAULT_UPLOAD_CONCURRENCY = 4;
131
117
  /**
132
- * The `fs_upload/authed` throttle: `batch_upload_urls`, `batch_attach_blobs`
133
- * and every `multipart/*` call share 300 requests a minute, keyed by session.
134
- * {@link UploadManager} paces itself against this so a large run degrades into
135
- * waiting rather than into a wall of 429s.
118
+ * `batch_upload_urls`, `batch_attach_blobs` and every `multipart/*` call
119
+ * share 300 requests a minute, keyed by session. {@link UploadManager} paces
120
+ * itself against this so a large run degrades into waiting rather than into a
121
+ * wall of 429s.
136
122
  */
137
123
  export declare const FS_UPLOAD_RATE_LIMIT = 300;
138
124
  /**
139
- * The `fs_bulk_job/authed` throttle: `copy`, `create_directories`,
140
- * `empty_trash` and `move_to_trash` share TWELVE requests a minute. It is the
141
- * tightest limit in the API and the easiest one to trip by looping.
125
+ * `copy`, `create_directories`, `empty_trash` and `move_to_trash` share
126
+ * TWELVE requests a minute. It is the tightest limit in the API and the
127
+ * easiest one to trip by looping.
142
128
  */
143
129
  export declare const FS_BULK_JOB_RATE_LIMIT = 12;
144
130
  /** One entry of the manifest sent to `batch_upload_urls`. */
@@ -247,7 +233,7 @@ export interface UploadInput {
247
233
  * folder upload costs no extra round trips. A `..` segment is a 400.
248
234
  */
249
235
  readonly relativePaths?: string[];
250
- /** Parallel PUTs in flight. Keep it modest: the store is a Pi behind Cloudflare. */
236
+ /** Parallel PUTs in flight. Keep it modest. */
251
237
  readonly concurrency?: number;
252
238
  /** Files per `batch_upload_urls` call. Clamped to {@link MAX_BATCH}. */
253
239
  readonly batchSize?: number;
@@ -338,7 +324,7 @@ export interface UploadManagerOptions {
338
324
  *
339
325
  * Two things the wrapper MUST get right, both of which the SDK's own
340
326
  * transport already does. It must not add an `Authorization` header or a
341
- * cookie: the presigned signature is the credential and MinIO rejects a
327
+ * cookie: the presigned signature is the credential and the store rejects a
342
328
  * request carrying two authentication schemes. And it must expose `ETag` on
343
329
  * the `Response` it builds, or the multipart tier has nothing to complete
344
330
  * with - in a browser that additionally needs `ETag` in the bucket's
@@ -356,7 +342,7 @@ export interface UploadManagerOptions {
356
342
  * steps, for instance to resume a torn multipart.
357
343
  */
358
344
  export declare class UploadManager extends Resource {
359
- /** Paces every control-plane call against the `fs_upload` throttle. */
345
+ /** Paces every control-plane call against the 300-a-minute upload limit. */
360
346
  readonly gate: StorageRateGate;
361
347
  private readonly transport;
362
348
  private readonly md5;
@@ -402,9 +388,9 @@ export declare class UploadManager extends Resource {
402
388
  * progress accounting drives `createBatch` -> {@link putDirect} /
403
389
  * {@link uploadMultipart} -> {@link attachBlobs} itself, and this is where it
404
390
  * learns the per-file strategy and the byte counts it will be reporting
405
- * against. Whatever it does, it must pace itself against `fs_upload` (300
406
- * requests a minute, shared by every call in this class) - {@link gate} is
407
- * exposed for exactly that.
391
+ * against. Whatever it does, it must pace itself against the 300 requests a
392
+ * minute shared by every call in this class - {@link gate} is exposed for
393
+ * exactly that.
408
394
  *
409
395
  * @throws {OmsApiError} 400 on a structural problem, 404 when the parent is
410
396
  * not a directory the caller may write to.
@@ -417,8 +403,8 @@ export declare class UploadManager extends Resource {
417
403
  * PUTs one whole body to a presigned URL.
418
404
  *
419
405
  * Sends the plan's headers verbatim and NO `Authorization`: this request goes
420
- * to the object store, not to the API. MinIO refuses a request that carries
421
- * both a presigned signature and a bearer header.
406
+ * to the object store, not to the API, and the store refuses a request that
407
+ * carries both a presigned signature and a bearer header.
422
408
  *
423
409
  * Retries a network fault or a 5xx from the store. A 4xx is never retried: an
424
410
  * expired signature or a checksum mismatch is deterministic and a retry only
@@ -450,7 +436,7 @@ export declare class UploadManager extends Resource {
450
436
  * with per-item results even when every item failed: read `attached` on each
451
437
  * one, and never infer success from the status. A caller driving the flow by
452
438
  * hand must not skip this - a node with no blob is invisible in listings and
453
- * is eventually swept by `FsNodeUploadReaperJob`.
439
+ * is eventually swept by the server.
454
440
  */
455
441
  attachBlobs(attachments: Array<{
456
442
  fs_node_id: Id;
@@ -504,7 +490,7 @@ export declare class UploadManager extends Resource {
504
490
  * parts, PUT them in parallel, complete.
505
491
  *
506
492
  * Parts are sliced with the size the SERVER reported, never with
507
- * {@link MULTIPART_PART_SIZE}, so a change on the backend does not silently
493
+ * {@link MULTIPART_PART_SIZE}, so a server-side change does not silently
508
494
  * corrupt an upload here.
509
495
  *
510
496
  * Phases 2 and 3 at once for a file at or above {@link MULTIPART_THRESHOLD}:
@@ -562,7 +548,7 @@ export declare class UploadManager extends Resource {
562
548
  /**
563
549
  * Base64 MD5 of a blob, in the exact form `Content-MD5` wants.
564
550
  *
565
- * The algorithm is not negotiable: the backend binds this digest into the
551
+ * The algorithm is not negotiable: the server binds this digest into the
566
552
  * presigned PUT signature as `Content-MD5`, so anything else makes the object
567
553
  * store reject the upload with a signature error that never mentions checksums.
568
554
  *