@oxy.so/core 7.13.0 → 7.13.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.
@@ -1895,7 +1895,6 @@ const dict = {
1895
1895
  transfer: 'Transfer ownership',
1896
1896
  },
1897
1897
  errors: {
1898
- emailRequired: 'Enter an email to invite.',
1899
1898
  emailInvalid: 'Enter a valid email address, like name@example.com.',
1900
1899
  missingAccount: 'No account selected.',
1901
1900
  noPermission: 'You do not have permission to view members.',
@@ -2332,7 +2331,6 @@ const dict = {
2332
2331
  newLabel: 'New password',
2333
2332
  repeatLabel: 'Repeat the password',
2334
2333
  tooShort: 'Use at least {{min}} characters.',
2335
- tooLong: 'Use at most {{max}} characters.',
2336
2334
  mismatch: "The passwords don't match.",
2337
2335
  signOutOthers: 'Sign out everywhere else',
2338
2336
  save: 'Save password',
@@ -1895,7 +1895,6 @@ const dict = {
1895
1895
  transfer: 'Transferir propiedad',
1896
1896
  },
1897
1897
  errors: {
1898
- emailRequired: 'Introduce un email para invitar.',
1899
1898
  emailInvalid: 'Introduce un email válido, como nombre@ejemplo.com.',
1900
1899
  missingAccount: 'Ninguna cuenta seleccionada.',
1901
1900
  noPermission: 'No tienes permiso para ver los miembros.',
@@ -2332,7 +2331,6 @@ const dict = {
2332
2331
  newLabel: 'Contraseña nueva',
2333
2332
  repeatLabel: 'Repite la contraseña',
2334
2333
  tooShort: 'Usa al menos {{min}} caracteres.',
2335
- tooLong: 'Usa como máximo {{max}} caracteres.',
2336
2334
  mismatch: 'Las contraseñas no coinciden.',
2337
2335
  signOutOthers: 'Cerrar sesión en todos los demás sitios',
2338
2336
  save: 'Guardar contraseña',
@@ -64,12 +64,19 @@ export const OXY_IDENTITY_CACHE_PREFIXES = [
64
64
  // `resolveProfile` — keyed by fediverse handle in the query payload.
65
65
  'GET:/profiles/resolve',
66
66
  ];
67
+ /**
68
+ * The path `getUserById` reads, its id encoded. Built in one place so the
69
+ * request and every key that evicts it cannot spell the id differently.
70
+ */
71
+ export function oxyUserByIdPath(userId) {
72
+ return `/users/${encodeURIComponent(userId)}`;
73
+ }
67
74
  /**
68
75
  * Build the exact cache key `getUserById` reads under. The only identity key
69
76
  * derivable from a user id, so the only one that does not need a prefix sweep.
70
77
  */
71
78
  export function oxyUserByIdCacheKey(userId) {
72
- return `GET:/users/${userId}`;
79
+ return `GET:${oxyUserByIdPath(userId)}`;
73
80
  }
74
81
  /**
75
82
  * Sweep an `OxyServices` GET response cache of everything that could carry the
@@ -1886,7 +1886,6 @@ declare const dict: {
1886
1886
  transfer: string;
1887
1887
  };
1888
1888
  errors: {
1889
- emailRequired: string;
1890
1889
  emailInvalid: string;
1891
1890
  missingAccount: string;
1892
1891
  noPermission: string;
@@ -2323,7 +2322,6 @@ declare const dict: {
2323
2322
  newLabel: string;
2324
2323
  repeatLabel: string;
2325
2324
  tooShort: string;
2326
- tooLong: string;
2327
2325
  mismatch: string;
2328
2326
  signOutOthers: string;
2329
2327
  save: string;
@@ -1886,7 +1886,6 @@ declare const dict: {
1886
1886
  transfer: string;
1887
1887
  };
1888
1888
  errors: {
1889
- emailRequired: string;
1890
1889
  emailInvalid: string;
1891
1890
  missingAccount: string;
1892
1891
  noPermission: string;
@@ -2323,7 +2322,6 @@ declare const dict: {
2323
2322
  newLabel: string;
2324
2323
  repeatLabel: string;
2325
2324
  tooShort: string;
2326
- tooLong: string;
2327
2325
  mismatch: string;
2328
2326
  signOutOthers: string;
2329
2327
  save: string;
@@ -65,6 +65,11 @@ export interface OxyIdentityCacheEvictor {
65
65
  * reads whose key cannot be derived from a user id. Swept wholesale.
66
66
  */
67
67
  export declare const OXY_IDENTITY_CACHE_PREFIXES: readonly string[];
68
+ /**
69
+ * The path `getUserById` reads, its id encoded. Built in one place so the
70
+ * request and every key that evicts it cannot spell the id differently.
71
+ */
72
+ export declare function oxyUserByIdPath(userId: string): string;
68
73
  /**
69
74
  * Build the exact cache key `getUserById` reads under. The only identity key
70
75
  * derivable from a user id, so the only one that does not need a prefix sweep.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxy.so/core",
3
- "version": "7.13.0",
3
+ "version": "7.13.1",
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",
@@ -27,8 +27,7 @@ import {
27
27
  buildUrl,
28
28
  type FollowGraphParams,
29
29
  } from '../utils/apiUtils';
30
-
31
- const enc = encodeURIComponent;
30
+ import { oxyUserByIdCacheKey, oxyUserByIdPath } from '../utils/identityCacheSweep';
32
31
 
33
32
  const GRAPH_TTL = 2 * 60 * 1000;
34
33
  const STATUS_TTL = 60 * 1000;
@@ -132,7 +131,7 @@ export class FollowsApi {
132
131
  async follow(userId: string): Promise<FollowMutationResult> {
133
132
  const result = await this.ctx.request<FollowMutationResult>(
134
133
  'POST',
135
- `/users/${enc(userId)}/follow`,
134
+ `${oxyUserByIdPath(userId)}/follow`,
136
135
  undefined,
137
136
  { cache: false },
138
137
  );
@@ -157,7 +156,7 @@ export class FollowsApi {
157
156
  async unfollow(userId: string): Promise<FollowMutationResult> {
158
157
  const result = await this.ctx.request<FollowMutationResult>(
159
158
  'DELETE',
160
- `/users/${enc(userId)}/follow`,
159
+ `${oxyUserByIdPath(userId)}/follow`,
161
160
  undefined,
162
161
  { cache: false },
163
162
  );
@@ -180,7 +179,7 @@ export class FollowsApi {
180
179
 
181
180
  /** Whether the signed-in user follows `userId`. Cached 1 minute, busted by every write. */
182
181
  async status(userId: string): Promise<{ isFollowing: boolean }> {
183
- return this.ctx.request('GET', `/users/${enc(userId)}/follow-status`, undefined, {
182
+ return this.ctx.request('GET', `${oxyUserByIdPath(userId)}/follow-status`, undefined, {
184
183
  cache: true,
185
184
  cacheTTL: STATUS_TTL,
186
185
  });
@@ -223,13 +222,19 @@ export class FollowsApi {
223
222
  * `limit`/`offset`/`sort` combination is its own cache entry (2 minutes).
224
223
  */
225
224
  async followers(userId: string, params?: FollowGraphParams): Promise<UserPage<'followers'>> {
226
- const { data, total, hasMore } = await this.userPage(`/users/${enc(userId)}/followers`, params);
225
+ const { data, total, hasMore } = await this.userPage(
226
+ `${oxyUserByIdPath(userId)}/followers`,
227
+ params,
228
+ );
227
229
  return { followers: data, total, hasMore };
228
230
  }
229
231
 
230
232
  /** Who a user follows. `sort` as in `followers`. */
231
233
  async following(userId: string, params?: FollowGraphParams): Promise<UserPage<'following'>> {
232
- const { data, total, hasMore } = await this.userPage(`/users/${enc(userId)}/following`, params);
234
+ const { data, total, hasMore } = await this.userPage(
235
+ `${oxyUserByIdPath(userId)}/following`,
236
+ params,
237
+ );
233
238
  return { following: data, total, hasMore };
234
239
  }
235
240
 
@@ -238,7 +243,10 @@ export class FollowsApi {
238
243
  * `userId`.
239
244
  */
240
245
  async mutuals(userId: string, params?: FollowGraphParams): Promise<UserPage<'mutuals'>> {
241
- const { data, total, hasMore } = await this.userPage(`/users/${enc(userId)}/mutuals`, params);
246
+ const { data, total, hasMore } = await this.userPage(
247
+ `${oxyUserByIdPath(userId)}/mutuals`,
248
+ params,
249
+ );
242
250
  return { mutuals: data, total, hasMore };
243
251
  }
244
252
 
@@ -445,15 +453,16 @@ export class FollowsApi {
445
453
  const keys: string[] = ['GET:/users/me/graph'];
446
454
  const prefixes: string[] = ['GET:/profiles/username/', 'GET:/profiles/resolve'];
447
455
  for (const id of targetUserIds) {
448
- keys.push(`GET:/users/${enc(id)}/follow-status`);
456
+ const user = oxyUserByIdPath(id);
457
+ keys.push(`GET:${user}/follow-status`);
449
458
  // Profiles embed the viewer-relative `relationship`.
450
- keys.push(`GET:/users/${enc(id)}`);
459
+ keys.push(oxyUserByIdCacheKey(id));
451
460
  // The target gained or lost a follower, and "followers you know" with it.
452
- prefixes.push(`GET:/users/${enc(id)}/followers`, `GET:/users/${enc(id)}/mutuals`);
461
+ prefixes.push(`GET:${user}/followers`, `GET:${user}/mutuals`);
453
462
  }
454
463
  // The viewer's own following list changed.
455
464
  const viewerId = this.ctx.oxy.session.userId;
456
- if (viewerId) prefixes.push(`GET:/users/${enc(viewerId)}/following`);
465
+ if (viewerId) prefixes.push(`GET:${oxyUserByIdPath(viewerId)}/following`);
457
466
  this.ctx.http.invalidateCache({ keys, prefixes });
458
467
  }
459
468
  }
package/src/api/users.ts CHANGED
@@ -12,7 +12,11 @@ import type { OxyContext } from '../client/context';
12
12
  import type { PaginationInfo, SearchProfilesResponse, User } from '../models/interfaces';
13
13
  import { buildQueryParams, type PaginationParams } from '../utils/apiUtils';
14
14
  import { normalizeUserIdentity, normalizeUserIdentityOrNull } from '../utils/userIdentity';
15
- import { OXY_IDENTITY_CACHE_PREFIXES, oxyUserByIdCacheKey } from '../utils/identityCacheSweep';
15
+ import {
16
+ OXY_IDENTITY_CACHE_PREFIXES,
17
+ oxyUserByIdCacheKey,
18
+ oxyUserByIdPath,
19
+ } from '../utils/identityCacheSweep';
16
20
  import {
17
21
  OXY_ACCOUNT_LIST_CACHE_KEY,
18
22
  OXY_ACCOUNT_LIST_CACHE_QUERY_PREFIX,
@@ -67,7 +71,7 @@ export class UsersApi {
67
71
  * registry-fresh read that neither serves nor overwrites a cached entry.
68
72
  */
69
73
  async get(userId: string, options?: { cache?: boolean }): Promise<User> {
70
- const user = await this.ctx.request<User>('GET', `/users/${enc(userId)}`, undefined, {
74
+ const user = await this.ctx.request<User>('GET', oxyUserByIdPath(userId), undefined, {
71
75
  cache: options?.cache ?? true,
72
76
  cacheTTL: PROFILE_TTL,
73
77
  });