@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.
- package/dist/cjs/api/follows.js +12 -11
- package/dist/cjs/api/users.js +1 -1
- package/dist/cjs/i18n/locales/compact/es-ES.generated.js +1 -1
- package/dist/cjs/i18n/locales/en-US.js +0 -2
- package/dist/cjs/i18n/locales/es-ES.js +0 -2
- package/dist/cjs/utils/identityCacheSweep.js +9 -1
- package/dist/esm/api/follows.js +12 -11
- package/dist/esm/api/users.js +2 -2
- package/dist/esm/i18n/locales/compact/es-ES.generated.js +1 -1
- package/dist/esm/i18n/locales/en-US.js +0 -2
- package/dist/esm/i18n/locales/es-ES.js +0 -2
- package/dist/esm/utils/identityCacheSweep.js +8 -1
- package/dist/types/i18n/locales/en-US.d.ts +0 -2
- package/dist/types/i18n/locales/es-ES.d.ts +0 -2
- package/dist/types/utils/identityCacheSweep.d.ts +5 -0
- package/package.json +1 -1
- package/src/api/follows.ts +21 -12
- package/src/api/users.ts +6 -2
- package/src/i18n/locales/compact/es-ES.generated.ts +1 -1
- package/src/i18n/locales/en-US.ts +0 -2
- package/src/i18n/locales/es-ES.ts +0 -2
- package/src/utils/identityCacheSweep.ts +9 -1
|
@@ -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
|
|
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
package/src/api/follows.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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',
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
456
|
+
const user = oxyUserByIdPath(id);
|
|
457
|
+
keys.push(`GET:${user}/follow-status`);
|
|
449
458
|
// Profiles embed the viewer-relative `relationship`.
|
|
450
|
-
keys.push(
|
|
459
|
+
keys.push(oxyUserByIdCacheKey(id));
|
|
451
460
|
// The target gained or lost a follower, and "followers you know" with it.
|
|
452
|
-
prefixes.push(`GET
|
|
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
|
|
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 {
|
|
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',
|
|
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
|
});
|