@oxyhq/core 3.7.1 → 3.8.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.
@@ -8,6 +8,11 @@ const signatureService_1 = require("../crypto/signatureService");
8
8
  const userIdentity_1 = require("../utils/userIdentity");
9
9
  const loggerUtils_1 = require("../utils/loggerUtils");
10
10
  const errorUtils_1 = require("../utils/errorUtils");
11
+ /**
12
+ * Maximum number of ids sent per `POST /users/by-ids` request. Matches the
13
+ * server-side batch cap; larger inputs are split into multiple chunked calls.
14
+ */
15
+ const USERS_BY_IDS_CHUNK_SIZE = 100;
11
16
  function OxyServicesUserMixin(Base) {
12
17
  return class extends Base {
13
18
  constructor(...args) {
@@ -216,6 +221,64 @@ function OxyServicesUserMixin(Base) {
216
221
  throw this.handleError(error);
217
222
  }
218
223
  }
224
+ /**
225
+ * Fetch many users by id in one round-trip per chunk.
226
+ *
227
+ * Built for feed/hydration call sites that would otherwise issue one
228
+ * `getUserById` request per unique author (the classic M+1). Ids are
229
+ * deduplicated and validated (empty/blank ids dropped) before being split
230
+ * into chunks of {@link USERS_BY_IDS_CHUNK_SIZE} and POSTed to
231
+ * `/users/by-ids` as `{ ids }`. The server returns the matched users as a
232
+ * flat `User[]` (order is not guaranteed and the caller is expected to map
233
+ * by `id`); each is run through `normalizeUserIdentity`, matching
234
+ * `getUserById`.
235
+ *
236
+ * **Service-token auth (required).** `/users/by-ids` is a server-to-server
237
+ * bulk fetch of PUBLIC user data and is called via `makeServiceRequest`,
238
+ * which attaches `Authorization: Bearer <serviceToken>`. oxy-api's CSRF
239
+ * middleware skips bearer-authenticated requests, so the calling client
240
+ * MUST be service-configured (`configureServiceAuth(apiKey, apiSecret)`)
241
+ * before invoking this method; otherwise `getServiceToken()` throws because
242
+ * no credentials are available. (A plain user-session request fails here:
243
+ * server-to-server there is no cookie jar, so the auto-attached
244
+ * `X-CSRF-Token` has no matching cookie and oxy-api rejects the POST with
245
+ * 403 "CSRF token missing".)
246
+ *
247
+ * Resilience: chunks are independent. A failed chunk is logged and skipped
248
+ * — the method returns every user that resolved successfully rather than
249
+ * discarding the whole call on one chunk's failure. An empty/whitespace-only
250
+ * input resolves immediately with `[]` and performs no network call.
251
+ *
252
+ * Not cached at the SDK layer: the response is keyed on a multi-id POST body
253
+ * (low hit rate) and the backend maintains its own per-id Redis cache.
254
+ */
255
+ async getUsersByIds(ids) {
256
+ const uniqueIds = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.trim().length > 0)));
257
+ if (uniqueIds.length === 0) {
258
+ return [];
259
+ }
260
+ const chunks = [];
261
+ for (let i = 0; i < uniqueIds.length; i += USERS_BY_IDS_CHUNK_SIZE) {
262
+ chunks.push(uniqueIds.slice(i, i + USERS_BY_IDS_CHUNK_SIZE));
263
+ }
264
+ // Run chunks concurrently; a single chunk failure must not sink the rest.
265
+ const settled = await Promise.all(chunks.map(async (chunk) => {
266
+ try {
267
+ const users = await this.makeServiceRequest('POST', '/users/by-ids', { ids: chunk });
268
+ return Array.isArray(users) ? users.map((user) => (0, userIdentity_1.normalizeUserIdentity)(user)) : [];
269
+ }
270
+ catch (error) {
271
+ loggerUtils_1.logger.warn('getUsersByIds: chunk failed, continuing with remaining chunks', {
272
+ method: 'getUsersByIds',
273
+ chunkSize: chunk.length,
274
+ status: (0, errorUtils_1.extractErrorStatus)(error),
275
+ error: error instanceof Error ? error.message : String(error),
276
+ });
277
+ return [];
278
+ }
279
+ }));
280
+ return settled.flat();
281
+ }
219
282
  /**
220
283
  * Get current user
221
284
  */