@oxyhq/core 1.11.0 → 1.11.2
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/i18n/locales/en-US.json +108 -5
- package/dist/cjs/i18n/locales/es-ES.json +108 -5
- package/dist/cjs/i18n/locales/locales/en-US.json +108 -5
- package/dist/cjs/i18n/locales/locales/es-ES.json +108 -5
- package/dist/cjs/index.js +5 -2
- package/dist/cjs/mixins/OxyServices.topics.js +123 -0
- package/dist/cjs/mixins/OxyServices.user.js +14 -3
- package/dist/cjs/mixins/index.js +2 -0
- package/dist/cjs/models/Topic.js +16 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/i18n/locales/en-US.json +108 -5
- package/dist/esm/i18n/locales/es-ES.json +108 -5
- package/dist/esm/i18n/locales/locales/en-US.json +108 -5
- package/dist/esm/i18n/locales/locales/es-ES.json +108 -5
- package/dist/esm/index.js +1 -0
- package/dist/esm/mixins/OxyServices.topics.js +120 -0
- package/dist/esm/mixins/OxyServices.user.js +14 -3
- package/dist/esm/mixins/index.js +2 -0
- package/dist/esm/models/Topic.js +13 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/mixins/OxyServices.topics.d.ts +106 -0
- package/dist/types/mixins/OxyServices.user.d.ts +19 -2
- package/dist/types/models/Topic.d.ts +32 -0
- package/package.json +1 -1
- package/src/i18n/locales/en-US.json +108 -5
- package/src/i18n/locales/es-ES.json +108 -5
- package/src/index.ts +2 -0
- package/src/mixins/OxyServices.topics.ts +135 -0
- package/src/mixins/OxyServices.user.ts +26 -3
- package/src/mixins/index.ts +2 -0
- package/src/models/Topic.ts +35 -0
|
@@ -21,9 +21,26 @@ export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(B
|
|
|
21
21
|
*/
|
|
22
22
|
resolveProfile(handle: string): Promise<User | null>;
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Resolve (find or create) a non-local user. All user creation for
|
|
25
|
+
* external accounts (federated, agent, automated) goes through this
|
|
26
|
+
* method — calling services never write user data directly.
|
|
25
27
|
*/
|
|
26
|
-
|
|
28
|
+
resolveExternalUser(data: {
|
|
29
|
+
type: "federated" | "agent" | "automated";
|
|
30
|
+
username: string;
|
|
31
|
+
actorUri?: string;
|
|
32
|
+
domain?: string;
|
|
33
|
+
displayName?: string;
|
|
34
|
+
avatar?: string;
|
|
35
|
+
bio?: string;
|
|
36
|
+
ownerId?: string;
|
|
37
|
+
}): Promise<User>;
|
|
38
|
+
/**
|
|
39
|
+
* Get profile recommendations, optionally filtering out specific user types.
|
|
40
|
+
*/
|
|
41
|
+
getProfileRecommendations(options?: {
|
|
42
|
+
excludeTypes?: Array<"federated" | "agent" | "automated">;
|
|
43
|
+
}): Promise<Array<{
|
|
27
44
|
id: string;
|
|
28
45
|
username: string;
|
|
29
46
|
name?: {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare enum TopicType {
|
|
2
|
+
CATEGORY = "category",
|
|
3
|
+
TOPIC = "topic",
|
|
4
|
+
ENTITY = "entity"
|
|
5
|
+
}
|
|
6
|
+
export declare enum TopicSource {
|
|
7
|
+
SEED = "seed",
|
|
8
|
+
AI = "ai",
|
|
9
|
+
MANUAL = "manual",
|
|
10
|
+
SYSTEM = "system"
|
|
11
|
+
}
|
|
12
|
+
export interface TopicTranslation {
|
|
13
|
+
displayName: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface TopicData {
|
|
17
|
+
_id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
slug: string;
|
|
20
|
+
displayName: string;
|
|
21
|
+
description: string;
|
|
22
|
+
type: TopicType;
|
|
23
|
+
source: TopicSource;
|
|
24
|
+
aliases: string[];
|
|
25
|
+
parentTopicId?: string;
|
|
26
|
+
icon?: string;
|
|
27
|
+
image?: string;
|
|
28
|
+
isActive: boolean;
|
|
29
|
+
translations?: Record<string, TopicTranslation>;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -444,6 +444,34 @@
|
|
|
444
444
|
"title": "Why Karma?",
|
|
445
445
|
"text": "Karma unlocks special features and recognition in the Oxy Ecosystem. The more you contribute, the more you earn!"
|
|
446
446
|
}
|
|
447
|
+
},
|
|
448
|
+
"achievements": {
|
|
449
|
+
"unlocked": "Unlocked Achievements",
|
|
450
|
+
"locked": "Locked Achievements",
|
|
451
|
+
"firstStep": "First Step",
|
|
452
|
+
"firstStepDesc": "Earned your first karma point",
|
|
453
|
+
"novice": "Novice",
|
|
454
|
+
"noviceDesc": "Reached 10 karma points",
|
|
455
|
+
"contributor": "Contributor",
|
|
456
|
+
"contributorDesc": "Reached 50 karma points",
|
|
457
|
+
"risingStar": "Rising Star",
|
|
458
|
+
"risingStarDesc": "Reached 100 karma points",
|
|
459
|
+
"earlyAdopter": "Early Adopter",
|
|
460
|
+
"earlyAdopterDesc": "Been part of the community from the start",
|
|
461
|
+
"communityHero": "Community Hero",
|
|
462
|
+
"communityHeroDesc": "Reached 500 karma points",
|
|
463
|
+
"legend": "Legend",
|
|
464
|
+
"legendDesc": "Reached 1000 karma points",
|
|
465
|
+
"phoenix": "Phoenix",
|
|
466
|
+
"phoenixDesc": "Reached 2500 karma points",
|
|
467
|
+
"unstoppable": "Unstoppable",
|
|
468
|
+
"unstoppableDesc": "Reached 5000 karma points",
|
|
469
|
+
"bugHunter": "Bug Hunter",
|
|
470
|
+
"bugHunterDesc": "Reported helpful bugs",
|
|
471
|
+
"helper": "Helper",
|
|
472
|
+
"helperDesc": "Helped 10 users",
|
|
473
|
+
"streakMaster": "Streak Master",
|
|
474
|
+
"streakMasterDesc": "7 day activity streak"
|
|
447
475
|
}
|
|
448
476
|
},
|
|
449
477
|
"premium": {
|
|
@@ -533,6 +561,7 @@
|
|
|
533
561
|
},
|
|
534
562
|
"editProfile": {
|
|
535
563
|
"title": "Edit Profile",
|
|
564
|
+
"subtitle": "Manage your profile and preferences",
|
|
536
565
|
"sections": {
|
|
537
566
|
"profilePicture": "Profile Picture",
|
|
538
567
|
"basicInfo": "Basic Information",
|
|
@@ -543,29 +572,69 @@
|
|
|
543
572
|
"items": {
|
|
544
573
|
"displayName": {
|
|
545
574
|
"title": "Display Name",
|
|
546
|
-
"
|
|
575
|
+
"subtitle": "This is how your name will appear to others",
|
|
576
|
+
"add": "Add your display name",
|
|
577
|
+
"firstName": "First Name",
|
|
578
|
+
"firstNamePlaceholder": "Enter first name",
|
|
579
|
+
"lastName": "Last Name",
|
|
580
|
+
"lastNamePlaceholder": "Enter last name (optional)"
|
|
547
581
|
},
|
|
548
582
|
"username": {
|
|
549
583
|
"title": "Username",
|
|
550
|
-
"
|
|
584
|
+
"subtitle": "Your unique identifier on the platform",
|
|
585
|
+
"label": "Username",
|
|
586
|
+
"placeholder": "Choose a username",
|
|
587
|
+
"choose": "Choose a username",
|
|
588
|
+
"required": "Username is required",
|
|
589
|
+
"tooShort": "Username must be at least 3 characters"
|
|
551
590
|
},
|
|
552
591
|
"email": {
|
|
553
592
|
"title": "Email",
|
|
554
|
-
"
|
|
593
|
+
"subtitle": "Your primary email address",
|
|
594
|
+
"label": "Email Address",
|
|
595
|
+
"placeholder": "Enter your email address",
|
|
596
|
+
"add": "Add your email address",
|
|
597
|
+
"invalid": "Please enter a valid email address"
|
|
555
598
|
},
|
|
556
599
|
"bio": {
|
|
557
600
|
"title": "Bio",
|
|
601
|
+
"subtitle": "Tell people a bit about yourself",
|
|
602
|
+
"label": "Bio",
|
|
558
603
|
"placeholder": "Tell people about yourself"
|
|
559
604
|
},
|
|
605
|
+
"phone": {
|
|
606
|
+
"title": "Phone Number",
|
|
607
|
+
"subtitle": "Your contact phone number",
|
|
608
|
+
"label": "Phone Number",
|
|
609
|
+
"placeholder": "Enter your phone number"
|
|
610
|
+
},
|
|
611
|
+
"address": {
|
|
612
|
+
"title": "Address",
|
|
613
|
+
"subtitle": "Your physical address",
|
|
614
|
+
"label": "Address",
|
|
615
|
+
"placeholder": "Enter your address"
|
|
616
|
+
},
|
|
617
|
+
"birthday": {
|
|
618
|
+
"title": "Birthday",
|
|
619
|
+
"subtitle": "Your date of birth",
|
|
620
|
+
"label": "Birthday",
|
|
621
|
+
"placeholder": "YYYY-MM-DD"
|
|
622
|
+
},
|
|
560
623
|
"locations": {
|
|
561
624
|
"title": "Locations",
|
|
625
|
+
"subtitle": "Places you've been or live",
|
|
562
626
|
"add": "Add your locations",
|
|
627
|
+
"placeholder": "Enter location name",
|
|
628
|
+
"yourLocations": "Your Locations",
|
|
563
629
|
"count": "{{count}} location added",
|
|
564
630
|
"count_plural": "{{count}} locations added"
|
|
565
631
|
},
|
|
566
632
|
"links": {
|
|
567
633
|
"title": "Links",
|
|
634
|
+
"subtitle": "Share your website, social profiles, etc.",
|
|
568
635
|
"add": "Add your links",
|
|
636
|
+
"placeholder": "Enter URL",
|
|
637
|
+
"yourLinks": "Your Links",
|
|
569
638
|
"count": "{{count}} link added",
|
|
570
639
|
"count_plural": "{{count}} links added"
|
|
571
640
|
},
|
|
@@ -798,8 +867,19 @@
|
|
|
798
867
|
"account": "ACCOUNT PRIVACY",
|
|
799
868
|
"interactions": "INTERACTIONS",
|
|
800
869
|
"activity": "ACTIVITY & DATA",
|
|
801
|
-
"content": "CONTENT & SAFETY"
|
|
802
|
-
|
|
870
|
+
"content": "CONTENT & SAFETY",
|
|
871
|
+
"blockedUsers": "BLOCKED USERS",
|
|
872
|
+
"restrictedUsers": "RESTRICTED USERS"
|
|
873
|
+
},
|
|
874
|
+
"noBlockedUsers": "No blocked users",
|
|
875
|
+
"noRestrictedUsers": "No restricted users",
|
|
876
|
+
"unblock": "Unblock",
|
|
877
|
+
"unblockError": "Failed to unblock user",
|
|
878
|
+
"unrestrict": "Unrestrict",
|
|
879
|
+
"unrestrictError": "Failed to unrestrict user",
|
|
880
|
+
"restrictedDescription": "Limited interactions",
|
|
881
|
+
"userUnblocked": "User unblocked",
|
|
882
|
+
"userUnrestricted": "User unrestricted",
|
|
803
883
|
"isPrivateAccount": "Private Account",
|
|
804
884
|
"isPrivateAccountDesc": "Only approved followers can see your posts",
|
|
805
885
|
"profileVisibility": "Profile Visibility",
|
|
@@ -920,6 +1000,23 @@
|
|
|
920
1000
|
"subtitle": "How we use cookies and similar technologies"
|
|
921
1001
|
}
|
|
922
1002
|
},
|
|
1003
|
+
"faq": {
|
|
1004
|
+
"title": "FAQ",
|
|
1005
|
+
"searchPlaceholder": "Search FAQs...",
|
|
1006
|
+
"allCategories": "All",
|
|
1007
|
+
"loading": "Loading FAQs...",
|
|
1008
|
+
"noResults": "No FAQs match your search",
|
|
1009
|
+
"empty": "No FAQs available",
|
|
1010
|
+
"loadError": "Failed to load FAQs"
|
|
1011
|
+
},
|
|
1012
|
+
"userList": {
|
|
1013
|
+
"followers": "Followers",
|
|
1014
|
+
"following": "Following",
|
|
1015
|
+
"noFollowers": "No followers yet",
|
|
1016
|
+
"noFollowersDesc": "When people follow this user, they will appear here.",
|
|
1017
|
+
"noFollowing": "Not following anyone",
|
|
1018
|
+
"noFollowingDesc": "When this user follows people, they will appear here."
|
|
1019
|
+
},
|
|
923
1020
|
"common": {
|
|
924
1021
|
"errors": {
|
|
925
1022
|
"signOutFailed": "There was a problem signing you out. Please try again."
|
|
@@ -939,9 +1036,15 @@
|
|
|
939
1036
|
"getStarted": "Get Started",
|
|
940
1037
|
"createAccount": "Create Account",
|
|
941
1038
|
"signIn": "Sign In",
|
|
1039
|
+
"signOut": "Sign Out",
|
|
942
1040
|
"verify": "Verify",
|
|
943
1041
|
"resetPassword": "Reset Password"
|
|
944
1042
|
},
|
|
1043
|
+
"cancel": "Cancel",
|
|
1044
|
+
"retry": "Retry",
|
|
1045
|
+
"save": "Save",
|
|
1046
|
+
"saved": "Saved successfully",
|
|
1047
|
+
"saving": "Saving...",
|
|
945
1048
|
"links": {
|
|
946
1049
|
"recoverAccount": "Recover your account",
|
|
947
1050
|
"signUp": "Sign Up"
|
|
@@ -147,6 +147,7 @@
|
|
|
147
147
|
},
|
|
148
148
|
"editProfile": {
|
|
149
149
|
"title": "Editar perfil",
|
|
150
|
+
"subtitle": "Gestiona tu perfil y preferencias",
|
|
150
151
|
"sections": {
|
|
151
152
|
"profilePicture": "Foto de perfil",
|
|
152
153
|
"basicInfo": "Información básica",
|
|
@@ -157,29 +158,69 @@
|
|
|
157
158
|
"items": {
|
|
158
159
|
"displayName": {
|
|
159
160
|
"title": "Nombre para mostrar",
|
|
160
|
-
"
|
|
161
|
+
"subtitle": "Así aparecerá tu nombre para los demás",
|
|
162
|
+
"add": "Añade tu nombre para mostrar",
|
|
163
|
+
"firstName": "Nombre",
|
|
164
|
+
"firstNamePlaceholder": "Introduce tu nombre",
|
|
165
|
+
"lastName": "Apellido",
|
|
166
|
+
"lastNamePlaceholder": "Introduce tu apellido (opcional)"
|
|
161
167
|
},
|
|
162
168
|
"username": {
|
|
163
169
|
"title": "Usuario",
|
|
164
|
-
"
|
|
170
|
+
"subtitle": "Tu identificador único en la plataforma",
|
|
171
|
+
"label": "Usuario",
|
|
172
|
+
"placeholder": "Elige un usuario",
|
|
173
|
+
"choose": "Elige un usuario",
|
|
174
|
+
"required": "El usuario es obligatorio",
|
|
175
|
+
"tooShort": "El usuario debe tener al menos 3 caracteres"
|
|
165
176
|
},
|
|
166
177
|
"email": {
|
|
167
178
|
"title": "Correo electrónico",
|
|
168
|
-
"
|
|
179
|
+
"subtitle": "Tu dirección de correo principal",
|
|
180
|
+
"label": "Correo electrónico",
|
|
181
|
+
"placeholder": "Introduce tu correo electrónico",
|
|
182
|
+
"add": "Añade tu correo electrónico",
|
|
183
|
+
"invalid": "Introduce una dirección de correo válida"
|
|
169
184
|
},
|
|
170
185
|
"bio": {
|
|
171
186
|
"title": "Biografía",
|
|
187
|
+
"subtitle": "Cuenta algo sobre ti",
|
|
188
|
+
"label": "Biografía",
|
|
172
189
|
"placeholder": "Cuenta algo sobre ti"
|
|
173
190
|
},
|
|
191
|
+
"phone": {
|
|
192
|
+
"title": "Número de teléfono",
|
|
193
|
+
"subtitle": "Tu número de teléfono de contacto",
|
|
194
|
+
"label": "Número de teléfono",
|
|
195
|
+
"placeholder": "Introduce tu número de teléfono"
|
|
196
|
+
},
|
|
197
|
+
"address": {
|
|
198
|
+
"title": "Dirección",
|
|
199
|
+
"subtitle": "Tu dirección física",
|
|
200
|
+
"label": "Dirección",
|
|
201
|
+
"placeholder": "Introduce tu dirección"
|
|
202
|
+
},
|
|
203
|
+
"birthday": {
|
|
204
|
+
"title": "Fecha de nacimiento",
|
|
205
|
+
"subtitle": "Tu fecha de nacimiento",
|
|
206
|
+
"label": "Fecha de nacimiento",
|
|
207
|
+
"placeholder": "AAAA-MM-DD"
|
|
208
|
+
},
|
|
174
209
|
"locations": {
|
|
175
210
|
"title": "Ubicaciones",
|
|
211
|
+
"subtitle": "Lugares donde has estado o vives",
|
|
176
212
|
"add": "Añade tus ubicaciones",
|
|
213
|
+
"placeholder": "Introduce el nombre del lugar",
|
|
214
|
+
"yourLocations": "Tus ubicaciones",
|
|
177
215
|
"count": "{{count}} ubicación añadida",
|
|
178
216
|
"count_plural": "{{count}} ubicaciones añadidas"
|
|
179
217
|
},
|
|
180
218
|
"links": {
|
|
181
219
|
"title": "Enlaces",
|
|
220
|
+
"subtitle": "Comparte tu web, perfiles sociales, etc.",
|
|
182
221
|
"add": "Añade tus enlaces",
|
|
222
|
+
"placeholder": "Introduce la URL",
|
|
223
|
+
"yourLinks": "Tus enlaces",
|
|
183
224
|
"count": "{{count}} enlace añadido",
|
|
184
225
|
"count_plural": "{{count}} enlaces añadidos"
|
|
185
226
|
},
|
|
@@ -219,9 +260,15 @@
|
|
|
219
260
|
"getStarted": "Comenzar",
|
|
220
261
|
"createAccount": "Crear cuenta",
|
|
221
262
|
"signIn": "Entrar",
|
|
263
|
+
"signOut": "Cerrar sesión",
|
|
222
264
|
"verify": "Verificar",
|
|
223
265
|
"resetPassword": "Restablecer contraseña"
|
|
224
266
|
},
|
|
267
|
+
"cancel": "Cancelar",
|
|
268
|
+
"retry": "Reintentar",
|
|
269
|
+
"save": "Guardar",
|
|
270
|
+
"saved": "Guardado correctamente",
|
|
271
|
+
"saving": "Guardando...",
|
|
225
272
|
"links": {
|
|
226
273
|
"recoverAccount": "Recuperar tu cuenta",
|
|
227
274
|
"signUp": "Registrarse"
|
|
@@ -623,6 +670,34 @@
|
|
|
623
670
|
"title": "¿Por qué el karma?",
|
|
624
671
|
"text": "El karma desbloquea funciones especiales y reconocimiento en el ecosistema de Oxy. ¡Cuanto más contribuyas, más ganarás!"
|
|
625
672
|
}
|
|
673
|
+
},
|
|
674
|
+
"achievements": {
|
|
675
|
+
"unlocked": "Logros desbloqueados",
|
|
676
|
+
"locked": "Logros bloqueados",
|
|
677
|
+
"firstStep": "Primer paso",
|
|
678
|
+
"firstStepDesc": "Ganaste tu primer punto de karma",
|
|
679
|
+
"novice": "Novato",
|
|
680
|
+
"noviceDesc": "Alcanzaste 10 puntos de karma",
|
|
681
|
+
"contributor": "Contribuidor",
|
|
682
|
+
"contributorDesc": "Alcanzaste 50 puntos de karma",
|
|
683
|
+
"risingStar": "Estrella en ascenso",
|
|
684
|
+
"risingStarDesc": "Alcanzaste 100 puntos de karma",
|
|
685
|
+
"earlyAdopter": "Pionero",
|
|
686
|
+
"earlyAdopterDesc": "Parte de la comunidad desde el inicio",
|
|
687
|
+
"communityHero": "Héroe de la comunidad",
|
|
688
|
+
"communityHeroDesc": "Alcanzaste 500 puntos de karma",
|
|
689
|
+
"legend": "Leyenda",
|
|
690
|
+
"legendDesc": "Alcanzaste 1000 puntos de karma",
|
|
691
|
+
"phoenix": "Fénix",
|
|
692
|
+
"phoenixDesc": "Alcanzaste 2500 puntos de karma",
|
|
693
|
+
"unstoppable": "Imparable",
|
|
694
|
+
"unstoppableDesc": "Alcanzaste 5000 puntos de karma",
|
|
695
|
+
"bugHunter": "Cazador de errores",
|
|
696
|
+
"bugHunterDesc": "Reportaste errores útiles",
|
|
697
|
+
"helper": "Ayudante",
|
|
698
|
+
"helperDesc": "Ayudaste a 10 usuarios",
|
|
699
|
+
"streakMaster": "Maestro de rachas",
|
|
700
|
+
"streakMasterDesc": "Racha de actividad de 7 días"
|
|
626
701
|
}
|
|
627
702
|
},
|
|
628
703
|
"premium": {
|
|
@@ -819,8 +894,19 @@
|
|
|
819
894
|
"account": "PRIVACIDAD DE LA CUENTA",
|
|
820
895
|
"interactions": "INTERACCIONES",
|
|
821
896
|
"activity": "ACTIVIDAD Y DATOS",
|
|
822
|
-
"content": "CONTENIDO Y SEGURIDAD"
|
|
823
|
-
|
|
897
|
+
"content": "CONTENIDO Y SEGURIDAD",
|
|
898
|
+
"blockedUsers": "USUARIOS BLOQUEADOS",
|
|
899
|
+
"restrictedUsers": "USUARIOS RESTRINGIDOS"
|
|
900
|
+
},
|
|
901
|
+
"noBlockedUsers": "No hay usuarios bloqueados",
|
|
902
|
+
"noRestrictedUsers": "No hay usuarios restringidos",
|
|
903
|
+
"unblock": "Desbloquear",
|
|
904
|
+
"unblockError": "Error al desbloquear al usuario",
|
|
905
|
+
"unrestrict": "Quitar restricción",
|
|
906
|
+
"unrestrictError": "Error al quitar la restricción del usuario",
|
|
907
|
+
"restrictedDescription": "Interacciones limitadas",
|
|
908
|
+
"userUnblocked": "Usuario desbloqueado",
|
|
909
|
+
"userUnrestricted": "Restricción del usuario eliminada",
|
|
824
910
|
"isPrivateAccount": "Cuenta privada",
|
|
825
911
|
"isPrivateAccountDesc": "Solo los seguidores aprobados pueden ver tus publicaciones",
|
|
826
912
|
"profileVisibility": "Visibilidad del perfil",
|
|
@@ -940,5 +1026,22 @@
|
|
|
940
1026
|
"title": "Política de cookies",
|
|
941
1027
|
"subtitle": "Cómo usamos cookies y tecnologías similares"
|
|
942
1028
|
}
|
|
1029
|
+
},
|
|
1030
|
+
"faq": {
|
|
1031
|
+
"title": "Preguntas frecuentes",
|
|
1032
|
+
"searchPlaceholder": "Buscar en las FAQ...",
|
|
1033
|
+
"allCategories": "Todas",
|
|
1034
|
+
"loading": "Cargando preguntas frecuentes...",
|
|
1035
|
+
"noResults": "No se encontraron preguntas que coincidan con tu búsqueda",
|
|
1036
|
+
"empty": "No hay preguntas frecuentes disponibles",
|
|
1037
|
+
"loadError": "Error al cargar las preguntas frecuentes"
|
|
1038
|
+
},
|
|
1039
|
+
"userList": {
|
|
1040
|
+
"followers": "Seguidores",
|
|
1041
|
+
"following": "Siguiendo",
|
|
1042
|
+
"noFollowers": "Aún no hay seguidores",
|
|
1043
|
+
"noFollowersDesc": "Cuando alguien siga a este usuario, aparecerá aquí.",
|
|
1044
|
+
"noFollowing": "No sigue a nadie",
|
|
1045
|
+
"noFollowingDesc": "Cuando este usuario siga a alguien, aparecerá aquí."
|
|
943
1046
|
}
|
|
944
1047
|
}
|
package/src/index.ts
CHANGED
|
@@ -40,6 +40,8 @@ export type { KeyPair, SignedMessage, AuthChallenge, RecoveryPhraseResult } from
|
|
|
40
40
|
// --- Models & Types ---
|
|
41
41
|
export * from './models/interfaces';
|
|
42
42
|
export * from './models/session';
|
|
43
|
+
export type { TopicData, TopicTranslation } from './models/Topic';
|
|
44
|
+
export { TopicType, TopicSource } from './models/Topic';
|
|
43
45
|
|
|
44
46
|
// --- Device Management ---
|
|
45
47
|
export { DeviceManager } from './utils/deviceManager';
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Topics Methods Mixin
|
|
3
|
+
*
|
|
4
|
+
* Provides methods for topic discovery and management
|
|
5
|
+
*/
|
|
6
|
+
import type { OxyServicesBase } from '../OxyServices.base';
|
|
7
|
+
import type { TopicData, TopicTranslation } from '../models/Topic';
|
|
8
|
+
import { CACHE_TIMES } from './mixinHelpers';
|
|
9
|
+
|
|
10
|
+
export function OxyServicesTopicsMixin<T extends typeof OxyServicesBase>(Base: T) {
|
|
11
|
+
return class extends Base {
|
|
12
|
+
constructor(...args: any[]) {
|
|
13
|
+
super(...(args as [any]));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get top-level topic categories
|
|
18
|
+
* @param locale - Optional locale for translated results
|
|
19
|
+
* @returns List of category topics
|
|
20
|
+
*/
|
|
21
|
+
async getTopicCategories(locale?: string): Promise<TopicData[]> {
|
|
22
|
+
try {
|
|
23
|
+
const params: Record<string, string> = {};
|
|
24
|
+
if (locale) params.locale = locale;
|
|
25
|
+
return await this.makeRequest('GET', '/topics/categories', params, {
|
|
26
|
+
cache: true,
|
|
27
|
+
cacheTTL: CACHE_TIMES.EXTRA_LONG,
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
throw this.handleError(error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Search topics by query string
|
|
36
|
+
* @param query - Search query
|
|
37
|
+
* @param limit - Optional result limit
|
|
38
|
+
* @returns Matching topics
|
|
39
|
+
*/
|
|
40
|
+
async searchTopics(query: string, limit?: number): Promise<TopicData[]> {
|
|
41
|
+
try {
|
|
42
|
+
const params: Record<string, string | number> = { q: query };
|
|
43
|
+
if (limit) params.limit = limit;
|
|
44
|
+
return await this.makeRequest('GET', '/topics/search', params, {
|
|
45
|
+
cache: false,
|
|
46
|
+
});
|
|
47
|
+
} catch (error) {
|
|
48
|
+
throw this.handleError(error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* List topics with optional filters
|
|
54
|
+
* @param options - Filter and pagination options
|
|
55
|
+
* @returns List of topics
|
|
56
|
+
*/
|
|
57
|
+
async listTopics(options?: {
|
|
58
|
+
type?: string;
|
|
59
|
+
q?: string;
|
|
60
|
+
limit?: number;
|
|
61
|
+
offset?: number;
|
|
62
|
+
locale?: string;
|
|
63
|
+
}): Promise<TopicData[]> {
|
|
64
|
+
try {
|
|
65
|
+
const params: Record<string, string | number> = {};
|
|
66
|
+
if (options?.type) params.type = options.type;
|
|
67
|
+
if (options?.q) params.q = options.q;
|
|
68
|
+
if (options?.limit) params.limit = options.limit;
|
|
69
|
+
if (options?.offset) params.offset = options.offset;
|
|
70
|
+
if (options?.locale) params.locale = options.locale;
|
|
71
|
+
return await this.makeRequest('GET', '/topics', params, {
|
|
72
|
+
cache: true,
|
|
73
|
+
cacheTTL: CACHE_TIMES.SHORT,
|
|
74
|
+
});
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw this.handleError(error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get a single topic by slug
|
|
82
|
+
* @param slug - Topic slug
|
|
83
|
+
* @returns Topic data
|
|
84
|
+
*/
|
|
85
|
+
async getTopicBySlug(slug: string): Promise<TopicData> {
|
|
86
|
+
try {
|
|
87
|
+
return await this.makeRequest('GET', `/topics/${slug}`, undefined, {
|
|
88
|
+
cache: true,
|
|
89
|
+
cacheTTL: CACHE_TIMES.LONG,
|
|
90
|
+
});
|
|
91
|
+
} catch (error) {
|
|
92
|
+
throw this.handleError(error);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Resolve an array of topic names to existing or newly created topics
|
|
98
|
+
* @param names - Array of { name, type } objects to resolve
|
|
99
|
+
* @returns Resolved topic data
|
|
100
|
+
*/
|
|
101
|
+
async resolveTopicNames(
|
|
102
|
+
names: Array<{ name: string; type: string }>
|
|
103
|
+
): Promise<TopicData[]> {
|
|
104
|
+
try {
|
|
105
|
+
return await this.makeRequest('POST', '/topics/resolve', { names }, {
|
|
106
|
+
cache: false,
|
|
107
|
+
});
|
|
108
|
+
} catch (error) {
|
|
109
|
+
throw this.handleError(error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Update metadata for a topic
|
|
115
|
+
* @param slug - Topic slug
|
|
116
|
+
* @param data - Metadata fields to update
|
|
117
|
+
* @returns Updated topic data
|
|
118
|
+
*/
|
|
119
|
+
async updateTopicMetadata(
|
|
120
|
+
slug: string,
|
|
121
|
+
data: {
|
|
122
|
+
description?: string;
|
|
123
|
+
translations?: Record<string, TopicTranslation>;
|
|
124
|
+
}
|
|
125
|
+
): Promise<TopicData> {
|
|
126
|
+
try {
|
|
127
|
+
return await this.makeRequest('PATCH', `/topics/${slug}`, data, {
|
|
128
|
+
cache: false,
|
|
129
|
+
});
|
|
130
|
+
} catch (error) {
|
|
131
|
+
throw this.handleError(error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -105,9 +105,29 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
|
-
*
|
|
108
|
+
* Resolve (find or create) a non-local user. All user creation for
|
|
109
|
+
* external accounts (federated, agent, automated) goes through this
|
|
110
|
+
* method — calling services never write user data directly.
|
|
109
111
|
*/
|
|
110
|
-
async
|
|
112
|
+
async resolveExternalUser(data: {
|
|
113
|
+
type: 'federated' | 'agent' | 'automated';
|
|
114
|
+
username: string;
|
|
115
|
+
actorUri?: string;
|
|
116
|
+
domain?: string;
|
|
117
|
+
displayName?: string;
|
|
118
|
+
avatar?: string;
|
|
119
|
+
bio?: string;
|
|
120
|
+
ownerId?: string;
|
|
121
|
+
}): Promise<User> {
|
|
122
|
+
return this.makeRequest<User>('PUT', '/users/resolve', data);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get profile recommendations, optionally filtering out specific user types.
|
|
127
|
+
*/
|
|
128
|
+
async getProfileRecommendations(options?: {
|
|
129
|
+
excludeTypes?: Array<'federated' | 'agent' | 'automated'>;
|
|
130
|
+
}): Promise<Array<{
|
|
111
131
|
id: string;
|
|
112
132
|
username: string;
|
|
113
133
|
name?: { first?: string; last?: string; full?: string };
|
|
@@ -121,8 +141,11 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
121
141
|
_count?: { followers: number; following: number };
|
|
122
142
|
[key: string]: unknown;
|
|
123
143
|
}>> {
|
|
144
|
+
const params = options?.excludeTypes?.length
|
|
145
|
+
? { excludeTypes: options.excludeTypes.join(',') }
|
|
146
|
+
: undefined;
|
|
124
147
|
return this.withAuthRetry(async () => {
|
|
125
|
-
return await this.makeRequest('GET', '/profiles/recommendations',
|
|
148
|
+
return await this.makeRequest('GET', '/profiles/recommendations', params, { cache: true });
|
|
126
149
|
}, 'getProfileRecommendations');
|
|
127
150
|
}
|
|
128
151
|
|
package/src/mixins/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { OxyServicesDevicesMixin } from './OxyServices.devices';
|
|
|
23
23
|
import { OxyServicesSecurityMixin } from './OxyServices.security';
|
|
24
24
|
import { OxyServicesUtilityMixin } from './OxyServices.utility';
|
|
25
25
|
import { OxyServicesFeaturesMixin } from './OxyServices.features';
|
|
26
|
+
import { OxyServicesTopicsMixin } from './OxyServices.topics';
|
|
26
27
|
|
|
27
28
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
29
|
type MixinFunction = (Base: any) => any;
|
|
@@ -66,6 +67,7 @@ const MIXIN_PIPELINE: MixinFunction[] = [
|
|
|
66
67
|
OxyServicesDevicesMixin,
|
|
67
68
|
OxyServicesSecurityMixin,
|
|
68
69
|
OxyServicesFeaturesMixin,
|
|
70
|
+
OxyServicesTopicsMixin,
|
|
69
71
|
|
|
70
72
|
// Utility (last, can use all above)
|
|
71
73
|
OxyServicesUtilityMixin,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export enum TopicType {
|
|
2
|
+
CATEGORY = 'category',
|
|
3
|
+
TOPIC = 'topic',
|
|
4
|
+
ENTITY = 'entity',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export enum TopicSource {
|
|
8
|
+
SEED = 'seed',
|
|
9
|
+
AI = 'ai',
|
|
10
|
+
MANUAL = 'manual',
|
|
11
|
+
SYSTEM = 'system',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TopicTranslation {
|
|
15
|
+
displayName: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface TopicData {
|
|
20
|
+
_id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
slug: string;
|
|
23
|
+
displayName: string;
|
|
24
|
+
description: string;
|
|
25
|
+
type: TopicType;
|
|
26
|
+
source: TopicSource;
|
|
27
|
+
aliases: string[];
|
|
28
|
+
parentTopicId?: string;
|
|
29
|
+
icon?: string;
|
|
30
|
+
image?: string;
|
|
31
|
+
isActive: boolean;
|
|
32
|
+
translations?: Record<string, TopicTranslation>;
|
|
33
|
+
createdAt: string;
|
|
34
|
+
updatedAt: string;
|
|
35
|
+
}
|