@oxyhq/core 3.7.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/mixins/OxyServices.user.js +52 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/mixins/OxyServices.user.js +52 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/mixins/OxyServices.user.d.ts +21 -0
- package/package.json +2 -2
- package/src/mixins/OxyServices.user.ts +60 -0
|
@@ -117,6 +117,27 @@ export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(B
|
|
|
117
117
|
* Get user by ID
|
|
118
118
|
*/
|
|
119
119
|
getUserById(userId: string): Promise<User>;
|
|
120
|
+
/**
|
|
121
|
+
* Fetch many users by id in one round-trip per chunk.
|
|
122
|
+
*
|
|
123
|
+
* Built for feed/hydration call sites that would otherwise issue one
|
|
124
|
+
* `getUserById` request per unique author (the classic M+1). Ids are
|
|
125
|
+
* deduplicated and validated (empty/blank ids dropped) before being split
|
|
126
|
+
* into chunks of {@link USERS_BY_IDS_CHUNK_SIZE} and POSTed to
|
|
127
|
+
* `/users/by-ids` as `{ ids }`. The server returns the matched users as a
|
|
128
|
+
* flat `User[]` (order is not guaranteed and the caller is expected to map
|
|
129
|
+
* by `id`); each is run through `normalizeUserIdentity`, matching
|
|
130
|
+
* `getUserById`.
|
|
131
|
+
*
|
|
132
|
+
* Resilience: chunks are independent. A failed chunk is logged and skipped
|
|
133
|
+
* — the method returns every user that resolved successfully rather than
|
|
134
|
+
* discarding the whole call on one chunk's failure. An empty/whitespace-only
|
|
135
|
+
* input resolves immediately with `[]` and performs no network call.
|
|
136
|
+
*
|
|
137
|
+
* Not cached at the SDK layer: the response is keyed on a multi-id POST body
|
|
138
|
+
* (low hit rate) and the backend maintains its own per-id Redis cache.
|
|
139
|
+
*/
|
|
140
|
+
getUsersByIds(ids: string[]): Promise<User[]>;
|
|
120
141
|
/**
|
|
121
142
|
* Get current user
|
|
122
143
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
}
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@oxyhq/contracts": "^0.
|
|
100
|
+
"@oxyhq/contracts": "^0.2.0",
|
|
101
101
|
"bip39": "^3.1.0",
|
|
102
102
|
"buffer": "^6.0.3",
|
|
103
103
|
"elliptic": "^6.6.1",
|
|
@@ -25,6 +25,12 @@ import { normalizeUserIdentity, normalizeUserIdentityOrNull } from '../utils/use
|
|
|
25
25
|
import { logger } from '../utils/loggerUtils';
|
|
26
26
|
import { extractErrorStatus } from '../utils/errorUtils';
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Maximum number of ids sent per `POST /users/by-ids` request. Matches the
|
|
30
|
+
* server-side batch cap; larger inputs are split into multiple chunked calls.
|
|
31
|
+
*/
|
|
32
|
+
const USERS_BY_IDS_CHUNK_SIZE = 100;
|
|
33
|
+
|
|
28
34
|
/** Per-user outcome returned by `POST /users/follow/bulk`. */
|
|
29
35
|
export interface BulkFollowEntry {
|
|
30
36
|
/** The user ID that was processed. */
|
|
@@ -315,6 +321,60 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
315
321
|
}
|
|
316
322
|
}
|
|
317
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Fetch many users by id in one round-trip per chunk.
|
|
326
|
+
*
|
|
327
|
+
* Built for feed/hydration call sites that would otherwise issue one
|
|
328
|
+
* `getUserById` request per unique author (the classic M+1). Ids are
|
|
329
|
+
* deduplicated and validated (empty/blank ids dropped) before being split
|
|
330
|
+
* into chunks of {@link USERS_BY_IDS_CHUNK_SIZE} and POSTed to
|
|
331
|
+
* `/users/by-ids` as `{ ids }`. The server returns the matched users as a
|
|
332
|
+
* flat `User[]` (order is not guaranteed and the caller is expected to map
|
|
333
|
+
* by `id`); each is run through `normalizeUserIdentity`, matching
|
|
334
|
+
* `getUserById`.
|
|
335
|
+
*
|
|
336
|
+
* Resilience: chunks are independent. A failed chunk is logged and skipped
|
|
337
|
+
* — the method returns every user that resolved successfully rather than
|
|
338
|
+
* discarding the whole call on one chunk's failure. An empty/whitespace-only
|
|
339
|
+
* input resolves immediately with `[]` and performs no network call.
|
|
340
|
+
*
|
|
341
|
+
* Not cached at the SDK layer: the response is keyed on a multi-id POST body
|
|
342
|
+
* (low hit rate) and the backend maintains its own per-id Redis cache.
|
|
343
|
+
*/
|
|
344
|
+
async getUsersByIds(ids: string[]): Promise<User[]> {
|
|
345
|
+
const uniqueIds = Array.from(
|
|
346
|
+
new Set(ids.filter((id): id is string => typeof id === 'string' && id.trim().length > 0)),
|
|
347
|
+
);
|
|
348
|
+
if (uniqueIds.length === 0) {
|
|
349
|
+
return [];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const chunks: string[][] = [];
|
|
353
|
+
for (let i = 0; i < uniqueIds.length; i += USERS_BY_IDS_CHUNK_SIZE) {
|
|
354
|
+
chunks.push(uniqueIds.slice(i, i + USERS_BY_IDS_CHUNK_SIZE));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Run chunks concurrently; a single chunk failure must not sink the rest.
|
|
358
|
+
const settled = await Promise.all(
|
|
359
|
+
chunks.map(async (chunk): Promise<User[]> => {
|
|
360
|
+
try {
|
|
361
|
+
const users = await this.makeRequest<User[]>('POST', '/users/by-ids', { ids: chunk }, { cache: false });
|
|
362
|
+
return Array.isArray(users) ? users.map((user) => normalizeUserIdentity(user)) : [];
|
|
363
|
+
} catch (error: unknown) {
|
|
364
|
+
logger.warn('getUsersByIds: chunk failed, continuing with remaining chunks', {
|
|
365
|
+
method: 'getUsersByIds',
|
|
366
|
+
chunkSize: chunk.length,
|
|
367
|
+
status: extractErrorStatus(error),
|
|
368
|
+
error: error instanceof Error ? error.message : String(error),
|
|
369
|
+
});
|
|
370
|
+
return [];
|
|
371
|
+
}
|
|
372
|
+
}),
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
return settled.flat();
|
|
376
|
+
}
|
|
377
|
+
|
|
318
378
|
/**
|
|
319
379
|
* Get current user
|
|
320
380
|
*/
|