valtech-components 4.0.938 → 4.0.940
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/esm2022/lib/components/molecules/group-picker/group-picker.component.mjs +97 -0
- package/esm2022/lib/components/organisms/group-members/group-members.component.mjs +178 -0
- package/esm2022/lib/directives/feature-guard.directive.mjs +48 -0
- package/esm2022/lib/services/feature-control.service.mjs +117 -0
- package/esm2022/lib/services/groups/groups.service.mjs +92 -0
- package/esm2022/lib/services/groups/types.mjs +2 -0
- package/esm2022/lib/services/qr-generator/qrbrand.mjs +89 -0
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +9 -1
- package/fesm2022/valtech-components.mjs +598 -2
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/molecules/group-picker/group-picker.component.d.ts +28 -0
- package/lib/components/organisms/group-members/group-members.component.d.ts +43 -0
- package/lib/directives/feature-guard.directive.d.ts +21 -0
- package/lib/services/feature-control.service.d.ts +50 -0
- package/lib/services/groups/groups.service.d.ts +39 -0
- package/lib/services/groups/types.d.ts +69 -0
- package/lib/services/qr-generator/qrbrand.d.ts +50 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +7 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { EventEmitter, OnInit } from '@angular/core';
|
|
2
|
+
import { ValGroup } from '../../../services/groups/types';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* val-group-picker — elegir el grupo dueño de un recurso (ADR-083).
|
|
6
|
+
*
|
|
7
|
+
* Se auto-carga: pide sus propios grupos a `GroupsService` en vez de esperar
|
|
8
|
+
* que el consumer se los pase. Es la razón por la que existe como componente y
|
|
9
|
+
* no como un `<select>` armado a mano en cada app — "una línea, una etiqueta
|
|
10
|
+
* i18n" (ver ADR-083 §"Qué se construye una sola vez").
|
|
11
|
+
*
|
|
12
|
+
* Sin texto hardcodeado: los labels llegan por `@Input` (lib i18n-agnostic).
|
|
13
|
+
* Cada app pone su palabra ("Equipo", "Sucursal", "Refugio").
|
|
14
|
+
*/
|
|
15
|
+
export declare class GroupPickerComponent implements OnInit {
|
|
16
|
+
label: string;
|
|
17
|
+
placeholder: string;
|
|
18
|
+
noGroupLabel: string;
|
|
19
|
+
value: string | null;
|
|
20
|
+
disabled: boolean;
|
|
21
|
+
valueChange: EventEmitter<string>;
|
|
22
|
+
private readonly groupsSvc;
|
|
23
|
+
groups: ValGroup[];
|
|
24
|
+
ngOnInit(): void;
|
|
25
|
+
onChange(v: string): void;
|
|
26
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GroupPickerComponent, never>;
|
|
27
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GroupPickerComponent, "val-group-picker", never, { "label": { "alias": "label"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "noGroupLabel": { "alias": "noGroupLabel"; "required": false; }; "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
|
|
2
|
+
import { ButtonMetadata } from '../../types';
|
|
3
|
+
import { ValGroupMember } from '../../../services/groups/types';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/** Persona elegible para agregar al grupo (típicamente un `OrgMember`). */
|
|
6
|
+
export interface GroupMemberCandidate {
|
|
7
|
+
userId: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
email?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* val-group-members — administrar la membresía de UN grupo (ADR-083).
|
|
13
|
+
*
|
|
14
|
+
* Deliberadamente NO trae su propio selector de personas: la fuente de
|
|
15
|
+
* "quiénes son los miembros elegibles de la organización" varía por app (org
|
|
16
|
+
* members, invitados, etc.), así que se recibe por `@Input candidates` en vez
|
|
17
|
+
* de que este organismo importe un servicio de organización que no le
|
|
18
|
+
* corresponde. Sin candidatos, igual funciona: solo lista y quita.
|
|
19
|
+
*
|
|
20
|
+
* Sin texto hardcodeado (lib i18n-agnostic): los labels llegan por `@Input`.
|
|
21
|
+
*/
|
|
22
|
+
export declare class GroupMembersComponent implements OnChanges {
|
|
23
|
+
groupId: string;
|
|
24
|
+
/** Personas elegibles para agregar. Vacío = el organismo solo lista/quita. */
|
|
25
|
+
candidates: GroupMemberCandidate[];
|
|
26
|
+
addPlaceholder: string;
|
|
27
|
+
emptyLabel: string;
|
|
28
|
+
removeLabel: string;
|
|
29
|
+
membersChange: EventEmitter<ValGroupMember[]>;
|
|
30
|
+
private readonly groupsSvc;
|
|
31
|
+
members: ValGroupMember[];
|
|
32
|
+
busy: boolean;
|
|
33
|
+
get removeButtonProps(): ButtonMetadata;
|
|
34
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
35
|
+
private reload;
|
|
36
|
+
/** Candidatos que todavía no están en el grupo — evita ofrecer un alta duplicada. */
|
|
37
|
+
eligible(): GroupMemberCandidate[];
|
|
38
|
+
nameFor(userId: string): string;
|
|
39
|
+
add(userId: string): void;
|
|
40
|
+
remove(userId: string): void;
|
|
41
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GroupMembersComponent, never>;
|
|
42
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GroupMembersComponent, "val-group-members", never, { "groupId": { "alias": "groupId"; "required": true; }; "candidates": { "alias": "candidates"; "required": false; }; "addPlaceholder": { "alias": "addPlaceholder"; "required": false; }; "emptyLabel": { "alias": "emptyLabel"; "required": false; }; "removeLabel": { "alias": "removeLabel"; "required": false; }; }, { "membersChange": "membersChange"; }, never, never, true, never>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { TemplateRef, ViewContainerRef, OnInit } from '@angular/core';
|
|
2
|
+
import { FeatureControlService } from '../services/feature-control.service';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Structural directive to hide elements when a feature is disabled.
|
|
6
|
+
*
|
|
7
|
+
* Usage: <button *valFeatureGuard="'oauth_facebook'">Sign in with Facebook</button>
|
|
8
|
+
* If oauth_facebook is disabled, the button is not rendered.
|
|
9
|
+
*/
|
|
10
|
+
export declare class FeatureGuardDirective implements OnInit {
|
|
11
|
+
private templateRef;
|
|
12
|
+
private viewContainer;
|
|
13
|
+
private featureControl;
|
|
14
|
+
set valFeatureGuard(featureKey: string);
|
|
15
|
+
private featureKey;
|
|
16
|
+
constructor(templateRef: TemplateRef<any>, viewContainer: ViewContainerRef, featureControl: FeatureControlService);
|
|
17
|
+
ngOnInit(): void;
|
|
18
|
+
private updateVisibility;
|
|
19
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FeatureGuardDirective, never>;
|
|
20
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<FeatureGuardDirective, "[valFeatureGuard]", never, { "valFeatureGuard": { "alias": "valFeatureGuard"; "required": false; }; }, {}, never, never, true, never>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { AnalyticsService } from './firebase/analytics.service';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export interface UserFeature {
|
|
5
|
+
key: string;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
rolloutPercentage?: number;
|
|
8
|
+
rolloutHash?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class FeatureControlService {
|
|
11
|
+
private http;
|
|
12
|
+
private analytics?;
|
|
13
|
+
private features;
|
|
14
|
+
private isLoaded;
|
|
15
|
+
private previousState;
|
|
16
|
+
constructor(http: HttpClient, analytics?: AnalyticsService);
|
|
17
|
+
private logFeatureEvent;
|
|
18
|
+
/**
|
|
19
|
+
* Load user features from backend.
|
|
20
|
+
* Call this during app initialization (AppComponent ctor or effect).
|
|
21
|
+
* Logs feature state changes to Firebase Analytics.
|
|
22
|
+
*/
|
|
23
|
+
loadUserFeatures(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Check if a feature is enabled for the current user.
|
|
26
|
+
* Returns true if feature is not found (optimistic default).
|
|
27
|
+
* If rollout percentage is set, uses consistent hashing for canary rollouts.
|
|
28
|
+
*/
|
|
29
|
+
isEnabled(featureKey: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get a computed signal for a feature.
|
|
32
|
+
* Use in templates: *ngIf="featureEnabled('oauth_facebook')()"
|
|
33
|
+
* Or in component: featureEnabled('payment_settings').
|
|
34
|
+
*/
|
|
35
|
+
featureEnabled(featureKey: string): () => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Get all features for debugging (admin only).
|
|
38
|
+
*/
|
|
39
|
+
getAllFeatures(): Map<string, boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Check if features have been loaded.
|
|
42
|
+
*/
|
|
43
|
+
isReady(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Watch for feature changes (for testing/demo purposes).
|
|
46
|
+
*/
|
|
47
|
+
watchFeatures(): import("@angular/core").WritableSignal<Map<string, boolean>>;
|
|
48
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FeatureControlService, [null, { optional: true; }]>;
|
|
49
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<FeatureControlService>;
|
|
50
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { ValtechAuthConfig } from '../auth/types';
|
|
4
|
+
import { ValGroup, ValGroupMember, CreateGroupRequest, UpdateGroupRequest, AddGroupMemberRequest, MyGroupsResponse } from './types';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* Cliente de `/v2/groups/*` (ADR-083). Servicio de PLATAFORMA: no sabe qué es
|
|
8
|
+
* un blueprint ni un refugio, solo agrupa recursos y personas. Cada app lo
|
|
9
|
+
* consume igual — es lo que evita reescribir esta capa por producto.
|
|
10
|
+
*/
|
|
11
|
+
export declare class GroupsService {
|
|
12
|
+
private config;
|
|
13
|
+
private http;
|
|
14
|
+
constructor(config: ValtechAuthConfig, http: HttpClient);
|
|
15
|
+
private get baseUrl();
|
|
16
|
+
/** Grupos activos de la organización (filtrados por app en el backend). */
|
|
17
|
+
listGroups(): Observable<ValGroup[]>;
|
|
18
|
+
/** Incluye archivados: para la pantalla de administración. */
|
|
19
|
+
listAllGroups(): Observable<ValGroup[]>;
|
|
20
|
+
getGroup(id: string): Observable<ValGroup>;
|
|
21
|
+
createGroup(req: CreateGroupRequest): Observable<ValGroup>;
|
|
22
|
+
updateGroup(id: string, req: UpdateGroupRequest): Observable<ValGroup>;
|
|
23
|
+
/**
|
|
24
|
+
* No hay `deleteGroup`: el ADR-083 decidió que un servicio de plataforma no
|
|
25
|
+
* puede saber si un vertical todavía apunta al grupo, y como "sin grupo"
|
|
26
|
+
* significa visible para toda la organización, borrarlo publicaría sus
|
|
27
|
+
* recursos a la planta entera. `archiveGroup`/`restoreGroup` cubren la
|
|
28
|
+
* necesidad real sin ese riesgo.
|
|
29
|
+
*/
|
|
30
|
+
archiveGroup(id: string): Observable<ValGroup>;
|
|
31
|
+
restoreGroup(id: string): Observable<ValGroup>;
|
|
32
|
+
listMembers(groupId: string): Observable<ValGroupMember[]>;
|
|
33
|
+
addMember(groupId: string, req: AddGroupMemberRequest): Observable<ValGroupMember[]>;
|
|
34
|
+
removeMember(groupId: string, userId: string): Observable<ValGroupMember[]>;
|
|
35
|
+
/** Los grupos del usuario actual. Referencial: el filtrado real corre en el backend. */
|
|
36
|
+
myGroups(): Observable<MyGroupsResponse>;
|
|
37
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GroupsService, never>;
|
|
38
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<GroupsService>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grupos (ADR-083) — subdivisión de una organización que agrupa RECURSOS y
|
|
3
|
+
* PERSONAS a la vez. Servicio de plataforma, agnóstico de dominio: el mismo
|
|
4
|
+
* contrato sirve a la línea de producción de Merotz, al refugio de Chesed o al
|
|
5
|
+
* evento de Bingo. Cada app le pone su etiqueta ("Equipo", "Sucursal") vía i18n
|
|
6
|
+
* — el modelo no la sabe.
|
|
7
|
+
*/
|
|
8
|
+
export interface ValGroup {
|
|
9
|
+
id: string;
|
|
10
|
+
orgId: string;
|
|
11
|
+
appId: string;
|
|
12
|
+
/** Etiqueta de dominio que declara la app: "machine", "shelter", "event". */
|
|
13
|
+
kind?: string;
|
|
14
|
+
/** Texto del CLIENTE ("Línea 3"): no se traduce. */
|
|
15
|
+
name: string;
|
|
16
|
+
parentId?: string;
|
|
17
|
+
archived: boolean;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
createdBy?: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ValGroupMember {
|
|
23
|
+
groupId: string;
|
|
24
|
+
orgId: string;
|
|
25
|
+
userId: string;
|
|
26
|
+
groupName?: string;
|
|
27
|
+
addedAt: string;
|
|
28
|
+
addedBy?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface CreateGroupRequest {
|
|
31
|
+
name: string;
|
|
32
|
+
kind?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface UpdateGroupRequest {
|
|
35
|
+
name: string;
|
|
36
|
+
}
|
|
37
|
+
export interface AddGroupMemberRequest {
|
|
38
|
+
userId: string;
|
|
39
|
+
}
|
|
40
|
+
export interface GroupResponse {
|
|
41
|
+
operationId: string;
|
|
42
|
+
group: ValGroup;
|
|
43
|
+
}
|
|
44
|
+
export interface ListGroupsResponse {
|
|
45
|
+
operationId: string;
|
|
46
|
+
groups: ValGroup[];
|
|
47
|
+
count: number;
|
|
48
|
+
}
|
|
49
|
+
export interface ListGroupMembersResponse {
|
|
50
|
+
operationId: string;
|
|
51
|
+
members: ValGroupMember[];
|
|
52
|
+
count: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Respuesta de "mis grupos": lo que alimenta el filtrado del lado del cliente
|
|
56
|
+
* cuando hace falta mostrar contexto (p.ej. qué grupo eligió el usuario por
|
|
57
|
+
* default), aunque el filtrado real siempre corre en el backend.
|
|
58
|
+
*/
|
|
59
|
+
export interface MyGroupsResponse {
|
|
60
|
+
operationId: string;
|
|
61
|
+
groupIds: string[];
|
|
62
|
+
/**
|
|
63
|
+
* El usuario ve TODOS los grupos sin importar membresía (permiso
|
|
64
|
+
* `groups:all`). Sin `omitempty` del lado del backend a propósito: un
|
|
65
|
+
* `false` ausente sería indistinguible de una respuesta vieja.
|
|
66
|
+
*/
|
|
67
|
+
allGroups: boolean;
|
|
68
|
+
groups: ValGroupMember[];
|
|
69
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contrato de marca de un QR, compartido entre backend y frontend (ADR-078).
|
|
3
|
+
*
|
|
4
|
+
* Espejo TypeScript de `backend/go/services/pkg/qrbrand/qrbrand.go`. Los tests
|
|
5
|
+
* de contraste de este archivo usan LOS MISMOS casos que el lado Go
|
|
6
|
+
* (`qrbrand_test.go`) — si un lado cambia el número esperado sin el otro,
|
|
7
|
+
* dejan de coincidir.
|
|
8
|
+
*
|
|
9
|
+
* No dibuja nada: valida que una combinación de colores sea escaneable y
|
|
10
|
+
* decide cuánta corrección de errores necesita un QR que lleva logo encima.
|
|
11
|
+
* El renderizado real sigue siendo QrGeneratorService (cliente) y qrpng.go
|
|
12
|
+
* (backend, correo) — cada uno dibuja a su manera; lo que comparten es esta
|
|
13
|
+
* validación.
|
|
14
|
+
*/
|
|
15
|
+
export type QrBrandDotStyle = 'square' | 'rounded' | 'dots';
|
|
16
|
+
export type QrBrandErrorCorrection = 'L' | 'M' | 'Q' | 'H';
|
|
17
|
+
export interface QrBrandLogo {
|
|
18
|
+
assetId: string;
|
|
19
|
+
/** Fracción del QR (0–1) que el logo tapa en el centro. */
|
|
20
|
+
clearArea?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface QrBrand {
|
|
23
|
+
orgId: string;
|
|
24
|
+
appId: string;
|
|
25
|
+
ink: string;
|
|
26
|
+
bg: string;
|
|
27
|
+
dotStyle?: QrBrandDotStyle;
|
|
28
|
+
logo?: QrBrandLogo;
|
|
29
|
+
}
|
|
30
|
+
/** Sin marca configurada: tinta sobre blanco. Nunca se persiste. */
|
|
31
|
+
export declare function defaultQrBrand(orgId: string, appId: string): QrBrand;
|
|
32
|
+
export declare class QrBrandValidationError extends Error {
|
|
33
|
+
readonly field: string;
|
|
34
|
+
constructor(field: string, message: string);
|
|
35
|
+
}
|
|
36
|
+
/** Contraste WCAG entre dos colores hex (#RRGGBB). Fórmula estándar (L1+0.05)/(L2+0.05). */
|
|
37
|
+
export declare function qrContrastRatio(hexA: string, hexB: string): number;
|
|
38
|
+
/**
|
|
39
|
+
* Rechaza una combinación de colores que un lector real no va a poder leer.
|
|
40
|
+
* Escaneabilidad sobre estética: esta función no negocia (ADR-078 regla 1).
|
|
41
|
+
* Lanza QrBrandValidationError; no retorna un booleano — el caller casi
|
|
42
|
+
* siempre necesita el mensaje para mostrarlo en el formulario.
|
|
43
|
+
*/
|
|
44
|
+
export declare function validateQrBrand(b: QrBrand): void;
|
|
45
|
+
/**
|
|
46
|
+
* El logo obliga a subir la corrección de errores, no se le pregunta al
|
|
47
|
+
* usuario (ADR-078 regla 2). Sin logo, M alcanza. Con logo, sube a Q; con
|
|
48
|
+
* logo grande (>15% del área), sube al máximo H.
|
|
49
|
+
*/
|
|
50
|
+
export declare function qrErrorCorrectionFor(b: QrBrand): QrBrandErrorCorrection;
|
package/lib/version.d.ts
CHANGED
package/package.json
CHANGED
package/public-api.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './lib/version';
|
|
|
2
2
|
export * from './lib/services/access-control';
|
|
3
3
|
export * from './lib/directives/has-permission.directive';
|
|
4
4
|
export * from './lib/directives/light-ripple.directive';
|
|
5
|
+
export * from './lib/directives/feature-guard.directive';
|
|
5
6
|
export * from './lib/components/atoms/avatar/avatar.component';
|
|
6
7
|
export * from './lib/components/atoms/avatar/types';
|
|
7
8
|
export * from './lib/components/atoms/box/box.component';
|
|
@@ -434,6 +435,7 @@ export * from './lib/services/confirmation-dialog/confirmation-dialog.service';
|
|
|
434
435
|
export * from './lib/services/confirmation-dialog/types';
|
|
435
436
|
export * from './lib/services/qr-generator/qr-generator.service';
|
|
436
437
|
export * from './lib/services/qr-generator/types';
|
|
438
|
+
export * from './lib/services/qr-generator/qrbrand';
|
|
437
439
|
export * from './lib/services/ticket-card-image/ticket-card-image.service';
|
|
438
440
|
export * from './lib/services/ticket-card-image/types';
|
|
439
441
|
export * from './lib/services/modal/modal.service';
|
|
@@ -447,7 +449,12 @@ export * from './lib/services/markdown-article/beautify-legal-article';
|
|
|
447
449
|
export * from './lib/services/legal-link/legal-link.service';
|
|
448
450
|
export * from './lib/services/firebase';
|
|
449
451
|
export * from './lib/services/auth';
|
|
452
|
+
export * from './lib/services/feature-control.service';
|
|
450
453
|
export { OrgService } from './lib/services/org/org.service';
|
|
454
|
+
export { GroupPickerComponent } from './lib/components/molecules/group-picker/group-picker.component';
|
|
455
|
+
export { GroupMembersComponent, GroupMemberCandidate, } from './lib/components/organisms/group-members/group-members.component';
|
|
456
|
+
export { GroupsService } from './lib/services/groups/groups.service';
|
|
457
|
+
export { ValGroup, ValGroupMember, CreateGroupRequest as CreateValGroupRequest, UpdateGroupRequest as UpdateValGroupRequest, AddGroupMemberRequest, GroupResponse as ValGroupResponse, ListGroupsResponse as ListValGroupsResponse, ListGroupMembersResponse as ListValGroupMembersResponse, MyGroupsResponse, } from './lib/services/groups/types';
|
|
451
458
|
export { PersonaService, PersonaConfig, PERSONA_CONFIG, providePersona, } from './lib/services/persona/persona.service';
|
|
452
459
|
export { HandleService } from './lib/services/handles/handles.service';
|
|
453
460
|
export type { HandleOwnerType, HandleResolveResult, HandleSearchResult, ResolveHandleResponse, SearchHandlesResponse, } from './lib/services/handles/handles.service';
|