@entifix/next-shell 0.5.0 → 0.7.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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/back-office/group-by-screen-type.d.ts +2 -2
- package/dist/lib/back-office/group-by-screen-type.js +2 -2
- package/dist/lib/back-office/group-by-screen-type.js.map +1 -1
- package/dist/lib/back-office/nav.d.ts +1 -2
- package/dist/lib/back-office/nav.d.ts.map +1 -1
- package/dist/lib/back-office/nav.js.map +1 -1
- package/dist/lib/back-office/sidebar-nav.d.ts +2 -2
- package/dist/lib/back-office/sidebar-nav.js +2 -2
- package/dist/lib/back-office/sidebar-nav.js.map +1 -1
- package/dist/lib/command-palette/command-palette-host.js +1 -1
- package/dist/lib/command-palette/command-palette-host.js.map +1 -1
- package/dist/lib/command-palette/use-command-recency.d.ts +1 -1
- package/dist/lib/command-palette/use-command-recency.js +1 -1
- package/dist/lib/command-palette/use-command-recency.js.map +1 -1
- package/dist/lib/command-palette/use-nav-source.d.ts +4 -3
- package/dist/lib/command-palette/use-nav-source.d.ts.map +1 -1
- package/dist/lib/command-palette/use-nav-source.js +4 -3
- package/dist/lib/command-palette/use-nav-source.js.map +1 -1
- package/dist/lib/command-palette/use-records-source.d.ts +1 -1
- package/dist/lib/command-palette/use-records-source.js +2 -2
- package/dist/lib/command-palette/use-records-source.js.map +1 -1
- package/dist/lib/command-palette/use-tabs-source.d.ts +1 -1
- package/dist/lib/command-palette/use-tabs-source.js +1 -1
- package/dist/lib/command-palette/use-tabs-source.js.map +1 -1
- package/dist/lib/command-palette/use-use-cases-source.js +2 -2
- package/dist/lib/command-palette/use-use-cases-source.js.map +1 -1
- package/dist/lib/config/service-proxy-route.d.ts +11 -2
- package/dist/lib/config/service-proxy-route.d.ts.map +1 -1
- package/dist/lib/config/service-proxy-route.js +27 -4
- package/dist/lib/config/service-proxy-route.js.map +1 -1
- package/dist/lib/crud/entity-crud-form.js +3 -3
- package/dist/lib/crud/entity-crud-form.js.map +1 -1
- package/dist/lib/crud/hand-off-write.d.ts +1 -1
- package/dist/lib/crud/hand-off-write.js +1 -1
- package/dist/lib/crud/hand-off-write.js.map +1 -1
- package/dist/lib/crud/make-entity-crud.d.ts.map +1 -1
- package/dist/lib/crud/make-entity-crud.js +5 -6
- package/dist/lib/crud/make-entity-crud.js.map +1 -1
- package/dist/lib/crud/make-entity-crud.types.d.ts +8 -10
- package/dist/lib/crud/make-entity-crud.types.d.ts.map +1 -1
- package/dist/lib/crud/make-entity-crud.types.js.map +1 -1
- package/dist/lib/crud/pending-notice.d.ts +2 -2
- package/dist/lib/crud/pending-notice.js +2 -2
- package/dist/lib/crud/pending-notice.js.map +1 -1
- package/dist/lib/crud/use-crud-render-link.d.ts.map +1 -1
- package/dist/lib/crud/use-crud-render-link.js +5 -1
- package/dist/lib/crud/use-crud-render-link.js.map +1 -1
- package/dist/lib/crud/use-entity-affordances.d.ts +1 -1
- package/dist/lib/crud/use-entity-affordances.js +1 -1
- package/dist/lib/crud/use-entity-affordances.js.map +1 -1
- package/dist/lib/crud/use-entity-bulk.d.ts +2 -2
- package/dist/lib/crud/use-entity-bulk.js +2 -2
- package/dist/lib/crud/use-entity-bulk.js.map +1 -1
- package/dist/lib/i18n/catalog/en.d.ts.map +1 -1
- package/dist/lib/i18n/catalog/en.js +1 -119
- package/dist/lib/i18n/catalog/en.js.map +1 -1
- package/dist/lib/i18n/catalog/es.d.ts +2 -131
- package/dist/lib/i18n/catalog/es.d.ts.map +1 -1
- package/dist/lib/i18n/catalog/es.js +2 -136
- package/dist/lib/i18n/catalog/es.js.map +1 -1
- package/dist/lib/i18n/catalog/index.d.ts +0 -226
- package/dist/lib/i18n/catalog/index.d.ts.map +1 -1
- package/dist/lib/i18n/spec-catalog.js +4 -4
- package/dist/lib/i18n/spec-catalog.js.map +1 -1
- package/dist/lib/search/record-search-route.d.ts +1 -1
- package/dist/lib/search/record-search-route.js +1 -1
- package/dist/lib/search/record-search-route.js.map +1 -1
- package/dist/lib/search/record-search-source.d.ts +1 -2
- package/dist/lib/search/record-search-source.d.ts.map +1 -1
- package/dist/lib/search/record-search-source.js.map +1 -1
- package/dist/lib/search/record-search.types.d.ts +1 -1
- package/dist/lib/search/record-search.types.js +1 -1
- package/dist/lib/search/record-search.types.js.map +1 -1
- package/dist/lib/session/account-links.js +1 -1
- package/dist/lib/session/account-links.js.map +1 -1
- package/dist/lib/session/session-keepalive.d.ts +2 -4
- package/dist/lib/session/session-keepalive.d.ts.map +1 -1
- package/dist/lib/session/session-keepalive.js +2 -4
- package/dist/lib/session/session-keepalive.js.map +1 -1
- package/dist/lib/session/use-session-refresh.js +1 -1
- package/dist/lib/session/use-session-refresh.js.map +1 -1
- package/dist/lib/wizard/wizard-tab-kind.d.ts +1 -2
- package/dist/lib/wizard/wizard-tab-kind.d.ts.map +1 -1
- package/dist/lib/wizard/wizard-tab-kind.js +1 -2
- package/dist/lib/wizard/wizard-tab-kind.js.map +1 -1
- package/dist/lib/workspace/drafts-state.d.ts.map +1 -1
- package/dist/lib/workspace/drafts-state.js +3 -2
- package/dist/lib/workspace/drafts-state.js.map +1 -1
- package/dist/lib/workspace/entity-tab-kind.d.ts +1 -2
- package/dist/lib/workspace/entity-tab-kind.d.ts.map +1 -1
- package/dist/lib/workspace/entity-tab-kind.js +1 -2
- package/dist/lib/workspace/entity-tab-kind.js.map +1 -1
- package/dist/lib/workspace/pending-state.d.ts +5 -4
- package/dist/lib/workspace/pending-state.d.ts.map +1 -1
- package/dist/lib/workspace/pending-state.js +1 -1
- package/dist/lib/workspace/pending-state.js.map +1 -1
- package/dist/lib/workspace/tabs-state.js +1 -1
- package/dist/lib/workspace/tabs-state.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/package.json +9 -9
|
@@ -1,138 +1,4 @@
|
|
|
1
1
|
/** Copy owned by the Next shells — back-office chrome and the tab workspace. */ export const shell = {
|
|
2
|
-
/**
|
|
3
|
-
* System management — the operator surface. Lives in the framework shell so
|
|
4
|
-
* a dedicated management app can mount the same screens later, which is why the
|
|
5
|
-
* copy is here rather than in an app catalog.
|
|
6
|
-
*/ /**
|
|
7
|
-
* La superficie de existencias — las primeras pantallas de Operaciones del
|
|
8
|
-
* back office.
|
|
9
|
-
*
|
|
10
|
-
* El *nombre del nivel* ("Operaciones") sale de `nav.screenType.operation`;
|
|
11
|
-
* esto nombra el grupo dentro de él.
|
|
12
|
-
*/ stock: {
|
|
13
|
-
nav: {
|
|
14
|
-
stock: 'Existencias',
|
|
15
|
-
items: 'Existencias en almacén',
|
|
16
|
-
movements: 'Libro de movimientos',
|
|
17
|
-
reservations: 'Reservas'
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
order: {
|
|
21
|
-
nav: {
|
|
22
|
-
orders: 'Pedidos'
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
settlement: {
|
|
26
|
-
nav: {
|
|
27
|
-
// El mismo nombre de grupo en las dos gradas: un acuerdo se redacta
|
|
28
|
-
// (Definiciones) y el resto lo produce un proceso (Operaciones). El
|
|
29
|
-
// encabezado de cada grada sale de `nav.screenType`.
|
|
30
|
-
settlement: 'Liquidaciones',
|
|
31
|
-
agreements: 'Acuerdos',
|
|
32
|
-
entries: 'Apuntes de comisión',
|
|
33
|
-
runs: 'Liquidaciones',
|
|
34
|
-
payouts: 'Pagos a vendedores'
|
|
35
|
-
},
|
|
36
|
-
agreement: {
|
|
37
|
-
channelRatesHint: 'Déjalo en blanco para cobrar la comisión por defecto en ese canal. Un 0 significa que no se cobra nada.',
|
|
38
|
-
channelRateDefault: 'Por defecto',
|
|
39
|
-
noChannelRates: 'Sin tarifas por canal'
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
sales: {
|
|
43
|
-
nav: {
|
|
44
|
-
sales: 'Ventas',
|
|
45
|
-
channels: 'Canales de venta',
|
|
46
|
-
guided: 'Ventas',
|
|
47
|
-
counterSale: 'Vender en mostrador'
|
|
48
|
-
},
|
|
49
|
-
counterSale: {
|
|
50
|
-
title: 'Venta en mostrador',
|
|
51
|
-
steps: {
|
|
52
|
-
channel: 'Canal',
|
|
53
|
-
lines: 'Productos',
|
|
54
|
-
payment: 'Cobro',
|
|
55
|
-
summary: 'Resumen'
|
|
56
|
-
},
|
|
57
|
-
channelHint: 'Elige el canal por el que se hace esta venta.',
|
|
58
|
-
linesHint: 'Agrega los productos publicados que estás vendiendo.',
|
|
59
|
-
addLine: 'Agregar producto',
|
|
60
|
-
removeLine: 'Quitar',
|
|
61
|
-
quantity: 'Cantidad',
|
|
62
|
-
offering: 'Producto',
|
|
63
|
-
total: 'Total',
|
|
64
|
-
paymentMethod: 'Forma de pago',
|
|
65
|
-
charge: 'Cobrar',
|
|
66
|
-
sold: 'Venta registrada',
|
|
67
|
-
soldDetail: 'La existencia ya se descontó y el pedido quedó registrado.',
|
|
68
|
-
newSale: 'Nueva venta',
|
|
69
|
-
emptyLines: 'Agrega al menos un producto para cobrar.'
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
marketplaceAdmin: {
|
|
73
|
-
nav: {
|
|
74
|
-
// Moved out of the `app:` catalog with the nav table itself: this copy
|
|
75
|
-
// belongs to the shell that owns the screens, so a second host mounting
|
|
76
|
-
// it does not re-translate them.
|
|
77
|
-
catalog: 'Catálogo',
|
|
78
|
-
products: 'Productos',
|
|
79
|
-
brands: 'Marcas',
|
|
80
|
-
categories: 'Categorías',
|
|
81
|
-
offerings: 'Ofertas comerciales',
|
|
82
|
-
offeringPrices: 'Precios de oferta',
|
|
83
|
-
// La sección Asistentes. El *nombre del nivel* ("Asistentes") sale de
|
|
84
|
-
// `nav.screenType.wizard`; esto nombra el grupo dentro de él.
|
|
85
|
-
guided: 'Catálogo'
|
|
86
|
-
},
|
|
87
|
-
/**
|
|
88
|
-
* El asistente de alta de producto. Los nombres de los pasos son de este
|
|
89
|
-
* dominio, no del control — por eso viven acá y no en `controls`.
|
|
90
|
-
*/ wizard: {
|
|
91
|
-
productSetup: {
|
|
92
|
-
title: 'Nuevo producto',
|
|
93
|
-
launch: 'Nuevo producto guiado',
|
|
94
|
-
steps: {
|
|
95
|
-
start: 'Origen',
|
|
96
|
-
source: 'Producto base',
|
|
97
|
-
identity: 'Identificación',
|
|
98
|
-
classification: 'Clasificación',
|
|
99
|
-
summary: 'Resumen'
|
|
100
|
-
},
|
|
101
|
-
start: {
|
|
102
|
-
question: '¿Cómo querés empezar?',
|
|
103
|
-
blank: 'Desde cero',
|
|
104
|
-
blankHint: 'Cargar los datos a mano.',
|
|
105
|
-
duplicate: 'Duplicar uno existente',
|
|
106
|
-
duplicateHint: 'Partir de un producto ya cargado. El código no se copia: identifica al original.'
|
|
107
|
-
},
|
|
108
|
-
source: {
|
|
109
|
-
prompt: 'Elegí el producto del que querés partir.',
|
|
110
|
-
chosen: 'Producto base: {{name}}',
|
|
111
|
-
required: 'Elegí un producto para continuar.'
|
|
112
|
-
},
|
|
113
|
-
summary: {
|
|
114
|
-
prompt: 'Revisá lo cargado antes de crearlo.',
|
|
115
|
-
origin: 'Origen',
|
|
116
|
-
originBlank: 'Desde cero',
|
|
117
|
-
originDuplicate: 'Duplicado de {{name}}',
|
|
118
|
-
empty: 'Sin definir'
|
|
119
|
-
},
|
|
120
|
-
recap: 'Ya habías respondido:'
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
systemManagement: {
|
|
125
|
-
nav: {
|
|
126
|
-
section: 'Sistema',
|
|
127
|
-
configuration: 'Configuración'
|
|
128
|
-
},
|
|
129
|
-
configuration: {
|
|
130
|
-
title: 'Configuración de la plataforma',
|
|
131
|
-
description: 'Parámetros que cada servicio resuelve al arrancar. Editar un valor afecta al servicio en su próximo arranque.',
|
|
132
|
-
secretPlaceholder: '•••••• (sin cambios)',
|
|
133
|
-
secretHint: 'Dejar en blanco mantiene el valor guardado. Escribir uno nuevo lo reemplaza.'
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
2
|
nav: {
|
|
137
3
|
primary: 'Principal',
|
|
138
4
|
openInWorkspace: 'Abrir {{label}} en el espacio de trabajo',
|
|
@@ -140,7 +6,7 @@
|
|
|
140
6
|
openInNewTab: 'Abrir {{label}} en una pestaña nueva',
|
|
141
7
|
openInNewTabShort: 'Abrir en una pestaña nueva',
|
|
142
8
|
/**
|
|
143
|
-
* The screen taxonomy
|
|
9
|
+
* The screen taxonomy — the sidebar's top tier, above the
|
|
144
10
|
* domain. `Definiciones` rather than `Maestros` because the ERP term needs
|
|
145
11
|
* the ERP background to parse, and rather than `Catálogos` or `Referencias`
|
|
146
12
|
* because both already mean something else here: the product catalog, and a
|
|
@@ -153,7 +19,7 @@
|
|
|
153
19
|
}
|
|
154
20
|
},
|
|
155
21
|
/**
|
|
156
|
-
* La paleta de comandos
|
|
22
|
+
* La paleta de comandos. Vive en `shell:` y no en `controls:`
|
|
157
23
|
* porque el control es agnóstico —recibe copia ya resuelta— y quien la
|
|
158
24
|
* arma es el back office.
|
|
159
25
|
*/ commandPalette: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/i18n/catalog/es.ts"],"sourcesContent":["/** Copy owned by the Next shells — back-office chrome and the tab workspace. */\nexport const shell = {\n /**\n * System management — the operator surface. Lives in the framework shell so\n * a dedicated management app can mount the same screens later, which is why the\n * copy is here rather than in an app catalog.\n */\n /**\n * La superficie de existencias — las primeras pantallas de Operaciones del\n * back office.\n *\n * El *nombre del nivel* (\"Operaciones\") sale de `nav.screenType.operation`;\n * esto nombra el grupo dentro de él.\n */\n stock: {\n nav: {\n stock: 'Existencias',\n items: 'Existencias en almacén',\n movements: 'Libro de movimientos',\n reservations: 'Reservas',\n },\n },\n order: {\n nav: {\n orders: 'Pedidos',\n },\n },\n settlement: {\n nav: {\n // El mismo nombre de grupo en las dos gradas: un acuerdo se redacta\n // (Definiciones) y el resto lo produce un proceso (Operaciones). El\n // encabezado de cada grada sale de `nav.screenType`.\n settlement: 'Liquidaciones',\n agreements: 'Acuerdos',\n entries: 'Apuntes de comisión',\n runs: 'Liquidaciones',\n payouts: 'Pagos a vendedores',\n },\n agreement: {\n channelRatesHint:\n 'Déjalo en blanco para cobrar la comisión por defecto en ese canal. Un 0 significa que no se cobra nada.',\n channelRateDefault: 'Por defecto',\n noChannelRates: 'Sin tarifas por canal',\n },\n },\n sales: {\n nav: {\n sales: 'Ventas',\n channels: 'Canales de venta',\n guided: 'Ventas',\n counterSale: 'Vender en mostrador',\n },\n counterSale: {\n title: 'Venta en mostrador',\n steps: {\n channel: 'Canal',\n lines: 'Productos',\n payment: 'Cobro',\n summary: 'Resumen',\n },\n channelHint: 'Elige el canal por el que se hace esta venta.',\n linesHint: 'Agrega los productos publicados que estás vendiendo.',\n addLine: 'Agregar producto',\n removeLine: 'Quitar',\n quantity: 'Cantidad',\n offering: 'Producto',\n total: 'Total',\n paymentMethod: 'Forma de pago',\n charge: 'Cobrar',\n sold: 'Venta registrada',\n soldDetail: 'La existencia ya se descontó y el pedido quedó registrado.',\n newSale: 'Nueva venta',\n emptyLines: 'Agrega al menos un producto para cobrar.',\n },\n },\n marketplaceAdmin: {\n nav: {\n // Moved out of the `app:` catalog with the nav table itself: this copy\n // belongs to the shell that owns the screens, so a second host mounting\n // it does not re-translate them.\n catalog: 'Catálogo',\n products: 'Productos',\n brands: 'Marcas',\n categories: 'Categorías',\n offerings: 'Ofertas comerciales',\n offeringPrices: 'Precios de oferta',\n // La sección Asistentes. El *nombre del nivel* (\"Asistentes\") sale de\n // `nav.screenType.wizard`; esto nombra el grupo dentro de él.\n guided: 'Catálogo',\n },\n /**\n * El asistente de alta de producto. Los nombres de los pasos son de este\n * dominio, no del control — por eso viven acá y no en `controls`.\n */\n wizard: {\n productSetup: {\n title: 'Nuevo producto',\n launch: 'Nuevo producto guiado',\n steps: {\n start: 'Origen',\n source: 'Producto base',\n identity: 'Identificación',\n classification: 'Clasificación',\n summary: 'Resumen',\n },\n start: {\n question: '¿Cómo querés empezar?',\n blank: 'Desde cero',\n blankHint: 'Cargar los datos a mano.',\n duplicate: 'Duplicar uno existente',\n duplicateHint:\n 'Partir de un producto ya cargado. El código no se copia: identifica al original.',\n },\n source: {\n prompt: 'Elegí el producto del que querés partir.',\n chosen: 'Producto base: {{name}}',\n required: 'Elegí un producto para continuar.',\n },\n summary: {\n prompt: 'Revisá lo cargado antes de crearlo.',\n origin: 'Origen',\n originBlank: 'Desde cero',\n originDuplicate: 'Duplicado de {{name}}',\n empty: 'Sin definir',\n },\n recap: 'Ya habías respondido:',\n },\n },\n },\n systemManagement: {\n nav: {\n section: 'Sistema',\n configuration: 'Configuración',\n },\n configuration: {\n title: 'Configuración de la plataforma',\n description:\n 'Parámetros que cada servicio resuelve al arrancar. Editar un valor afecta al servicio en su próximo arranque.',\n secretPlaceholder: '•••••• (sin cambios)',\n secretHint:\n 'Dejar en blanco mantiene el valor guardado. Escribir uno nuevo lo reemplaza.',\n },\n },\n nav: {\n primary: 'Principal',\n openInWorkspace: 'Abrir {{label}} en el espacio de trabajo',\n openInWorkspaceShort: 'Abrir en el espacio de trabajo',\n openInNewTab: 'Abrir {{label}} en una pestaña nueva',\n openInNewTabShort: 'Abrir en una pestaña nueva',\n /**\n * The screen taxonomy (ADR 0033) — the sidebar's top tier, above the\n * domain. `Definiciones` rather than `Maestros` because the ERP term needs\n * the ERP background to parse, and rather than `Catálogos` or `Referencias`\n * because both already mean something else here: the product catalog, and a\n * product's code in `storefront.category.sortByCode`.\n */\n screenType: {\n master: 'Definiciones',\n operation: 'Operaciones',\n wizard: 'Asistentes',\n report: 'Consultas',\n },\n },\n /**\n * La paleta de comandos (ADR 0044). Vive en `shell:` y no en `controls:`\n * porque el control es agnóstico —recibe copia ya resuelta— y quien la\n * arma es el back office.\n */\n commandPalette: {\n /** El disparador visible, que existe justo porque un atajo puede fallar. */\n open: 'Buscar o ejecutar',\n /** El nombre accesible del diálogo y de su campo. */\n title: 'Buscar o ejecutar',\n placeholder: 'Busca un registro, una pantalla o un comando…',\n newPlaceholder: '¿Qué quieres crear?',\n newLabel: 'Nuevo…',\n /** El nombre de la página apilada, y también el del control para volver. */\n newTitle: 'Nuevo',\n back: 'Volver',\n empty: 'Sin resultados',\n loading: 'Buscando…',\n more_one: '{{count}} más',\n more_other: '{{count}} más',\n /** Escribe al menos dos caracteres — el suelo que impone `/api/search`. */\n typeMore: 'Escribe al menos {{count}} caracteres para buscar registros.',\n groups: {\n actions: 'Acciones',\n commands: 'Comandos',\n navigation: 'Navegación',\n tabs: 'Pestañas abiertas',\n records: 'Registros',\n },\n /**\n * Dos redacciones para dos cosas distintas: «no es tuyo» es el estado\n * **normal** de un operador sin organización, y pintarlo como avería en\n * cada tecleo enseña a ignorar el aviso que sí importa.\n */\n unavailableScope: 'No disponible aquí: {{reason}}',\n unavailableReach: 'No pudimos consultar este origen: {{reason}}',\n /** Sufijo del comando que abre un destino como pestaña del espacio. */\n openInWorkspaceHint: 'Pestaña',\n },\n sidebar: {\n expand: 'Expandir barra lateral',\n collapse: 'Contraer barra lateral',\n openMenu: 'Abrir el menú',\n closeMenu: 'Cerrar el menú',\n // The drawer is a dialog, so it needs a name of its own — the landmark\n // inside it is the nav, and a dialog with no accessible name is announced\n // as just \"dialog\".\n menu: 'Menú de navegación',\n expandGroup: 'Desplegar {{group}}',\n collapseGroup: 'Plegar {{group}}',\n },\n /**\n * The session strip, rendered by `SessionKeepalive` only inside the final\n * window before the absolute ceiling. One key, because the strip says one\n * thing: nothing here counts down, since a number that moves invites a person\n * to watch it rather than to save their work.\n */\n session: {\n expiringSoon:\n 'Tu sesión está por expirar. Guarda tu trabajo e inicia sesión de nuevo para continuar.',\n },\n breadcrumbs: {\n home: 'Inicio',\n // The `/new` segment, which every domain's create route shares. It was\n // an auth-specific string until one host started serving two domains,\n // at which point a catalog page's breadcrumb read \"New user\".\n new: 'Nuevo',\n },\n /**\n * The account surface. The auth shell owns the screens, but `ACCOUNT_DESTINATIONS`\n * — the one list every app builds its menu from — lives in the shell, so the\n * shell owns their names too and resolves them itself.\n */\n account: {\n profile: 'Perfil',\n security: 'Seguridad',\n sessions: 'Sesiones',\n signOut: 'Cerrar sesión',\n },\n workspace: {\n copyLink: 'Copiar enlace',\n empty:\n 'No hay pestañas abiertas. Elige un catálogo en la barra lateral para empezar.',\n unsupported: 'Esta pestaña no se puede abrir aquí.',\n // The confirmation that guards closing a dirty tab. The title carries the\n // question, so the message states the consequence rather than repeating it\n // — it was phrased as a question while `window.confirm` rendered it, which\n // had nowhere to put a title.\n discardTitle: 'Descartar cambios',\n discard:\n 'Esta pestaña tiene cambios sin guardar. Si la cierras, se perderán.',\n discardConfirm: 'Descartar',\n // What became of a write the server has not finished. `count` is the\n // number in flight; a failure names no reason here, because the only one a\n // transaction carries is a server exception string in whatever language it\n // was written in — that is rendered beside this, unlocalized and marked so.\n pendingLabel: 'Estado de los guardados',\n savePending_one: 'Guardando 1 registro…',\n savePending_other: 'Guardando {{count}} registros…',\n saveFailed: 'No se pudo guardar el registro.',\n saveFailedDismiss: 'Descartar',\n },\n /**\n * The storefront. Its pages live in `shells-next-marketplace`, so its copy\n * lives here and not in an app catalog — `app:` is reserved for `apps/`.\n */\n};\n"],"names":["shell","stock","nav","items","movements","reservations","order","orders","settlement","agreements","entries","runs","payouts","agreement","channelRatesHint","channelRateDefault","noChannelRates","sales","channels","guided","counterSale","title","steps","channel","lines","payment","summary","channelHint","linesHint","addLine","removeLine","quantity","offering","total","paymentMethod","charge","sold","soldDetail","newSale","emptyLines","marketplaceAdmin","catalog","products","brands","categories","offerings","offeringPrices","wizard","productSetup","launch","start","source","identity","classification","question","blank","blankHint","duplicate","duplicateHint","prompt","chosen","required","origin","originBlank","originDuplicate","empty","recap","systemManagement","section","configuration","description","secretPlaceholder","secretHint","primary","openInWorkspace","openInWorkspaceShort","openInNewTab","openInNewTabShort","screenType","master","operation","report","commandPalette","open","placeholder","newPlaceholder","newLabel","newTitle","back","loading","more_one","more_other","typeMore","groups","actions","commands","navigation","tabs","records","unavailableScope","unavailableReach","openInWorkspaceHint","sidebar","expand","collapse","openMenu","closeMenu","menu","expandGroup","collapseGroup","session","expiringSoon","breadcrumbs","home","new","account","profile","security","sessions","signOut","workspace","copyLink","unsupported","discardTitle","discard","discardConfirm","pendingLabel","savePending_one","savePending_other","saveFailed","saveFailedDismiss"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/i18n/catalog/es.ts"],"sourcesContent":["/** Copy owned by the Next shells — back-office chrome and the tab workspace. */\nexport const shell = {\n nav: {\n primary: 'Principal',\n openInWorkspace: 'Abrir {{label}} en el espacio de trabajo',\n openInWorkspaceShort: 'Abrir en el espacio de trabajo',\n openInNewTab: 'Abrir {{label}} en una pestaña nueva',\n openInNewTabShort: 'Abrir en una pestaña nueva',\n /**\n * The screen taxonomy — the sidebar's top tier, above the\n * domain. `Definiciones` rather than `Maestros` because the ERP term needs\n * the ERP background to parse, and rather than `Catálogos` or `Referencias`\n * because both already mean something else here: the product catalog, and a\n * product's code in `storefront.category.sortByCode`.\n */\n screenType: {\n master: 'Definiciones',\n operation: 'Operaciones',\n wizard: 'Asistentes',\n report: 'Consultas',\n },\n },\n /**\n * La paleta de comandos. Vive en `shell:` y no en `controls:`\n * porque el control es agnóstico —recibe copia ya resuelta— y quien la\n * arma es el back office.\n */\n commandPalette: {\n /** El disparador visible, que existe justo porque un atajo puede fallar. */\n open: 'Buscar o ejecutar',\n /** El nombre accesible del diálogo y de su campo. */\n title: 'Buscar o ejecutar',\n placeholder: 'Busca un registro, una pantalla o un comando…',\n newPlaceholder: '¿Qué quieres crear?',\n newLabel: 'Nuevo…',\n /** El nombre de la página apilada, y también el del control para volver. */\n newTitle: 'Nuevo',\n back: 'Volver',\n empty: 'Sin resultados',\n loading: 'Buscando…',\n more_one: '{{count}} más',\n more_other: '{{count}} más',\n /** Escribe al menos dos caracteres — el suelo que impone `/api/search`. */\n typeMore: 'Escribe al menos {{count}} caracteres para buscar registros.',\n groups: {\n actions: 'Acciones',\n commands: 'Comandos',\n navigation: 'Navegación',\n tabs: 'Pestañas abiertas',\n records: 'Registros',\n },\n /**\n * Dos redacciones para dos cosas distintas: «no es tuyo» es el estado\n * **normal** de un operador sin organización, y pintarlo como avería en\n * cada tecleo enseña a ignorar el aviso que sí importa.\n */\n unavailableScope: 'No disponible aquí: {{reason}}',\n unavailableReach: 'No pudimos consultar este origen: {{reason}}',\n /** Sufijo del comando que abre un destino como pestaña del espacio. */\n openInWorkspaceHint: 'Pestaña',\n },\n sidebar: {\n expand: 'Expandir barra lateral',\n collapse: 'Contraer barra lateral',\n openMenu: 'Abrir el menú',\n closeMenu: 'Cerrar el menú',\n // The drawer is a dialog, so it needs a name of its own — the landmark\n // inside it is the nav, and a dialog with no accessible name is announced\n // as just \"dialog\".\n menu: 'Menú de navegación',\n expandGroup: 'Desplegar {{group}}',\n collapseGroup: 'Plegar {{group}}',\n },\n /**\n * The session strip, rendered by `SessionKeepalive` only inside the final\n * window before the absolute ceiling. One key, because the strip says one\n * thing: nothing here counts down, since a number that moves invites a person\n * to watch it rather than to save their work.\n */\n session: {\n expiringSoon:\n 'Tu sesión está por expirar. Guarda tu trabajo e inicia sesión de nuevo para continuar.',\n },\n breadcrumbs: {\n home: 'Inicio',\n // The `/new` segment, which every domain's create route shares. It was\n // an auth-specific string until one host started serving two domains,\n // at which point a catalog page's breadcrumb read \"New user\".\n new: 'Nuevo',\n },\n /**\n * The account surface. The auth shell owns the screens, but `ACCOUNT_DESTINATIONS`\n * — the one list every app builds its menu from — lives in the shell, so the\n * shell owns their names too and resolves them itself.\n */\n account: {\n profile: 'Perfil',\n security: 'Seguridad',\n sessions: 'Sesiones',\n signOut: 'Cerrar sesión',\n },\n workspace: {\n copyLink: 'Copiar enlace',\n empty:\n 'No hay pestañas abiertas. Elige un catálogo en la barra lateral para empezar.',\n unsupported: 'Esta pestaña no se puede abrir aquí.',\n // The confirmation that guards closing a dirty tab. The title carries the\n // question, so the message states the consequence rather than repeating it\n // — it was phrased as a question while `window.confirm` rendered it, which\n // had nowhere to put a title.\n discardTitle: 'Descartar cambios',\n discard:\n 'Esta pestaña tiene cambios sin guardar. Si la cierras, se perderán.',\n discardConfirm: 'Descartar',\n // What became of a write the server has not finished. `count` is the\n // number in flight; a failure names no reason here, because the only one a\n // transaction carries is a server exception string in whatever language it\n // was written in — that is rendered beside this, unlocalized and marked so.\n pendingLabel: 'Estado de los guardados',\n savePending_one: 'Guardando 1 registro…',\n savePending_other: 'Guardando {{count}} registros…',\n saveFailed: 'No se pudo guardar el registro.',\n saveFailedDismiss: 'Descartar',\n },\n /**\n * The storefront. Its pages live in `shells-next-marketplace`, so its copy\n * lives here and not in an app catalog — `app:` is reserved for `apps/`.\n */\n};\n"],"names":["shell","nav","primary","openInWorkspace","openInWorkspaceShort","openInNewTab","openInNewTabShort","screenType","master","operation","wizard","report","commandPalette","open","title","placeholder","newPlaceholder","newLabel","newTitle","back","empty","loading","more_one","more_other","typeMore","groups","actions","commands","navigation","tabs","records","unavailableScope","unavailableReach","openInWorkspaceHint","sidebar","expand","collapse","openMenu","closeMenu","menu","expandGroup","collapseGroup","session","expiringSoon","breadcrumbs","home","new","account","profile","security","sessions","signOut","workspace","copyLink","unsupported","discardTitle","discard","discardConfirm","pendingLabel","savePending_one","savePending_other","saveFailed","saveFailedDismiss"],"mappings":"AAAA,8EAA8E,GAC9E,OAAO,MAAMA,QAAQ;IACnBC,KAAK;QACHC,SAAS;QACTC,iBAAiB;QACjBC,sBAAsB;QACtBC,cAAc;QACdC,mBAAmB;QACnB;;;;;;KAMC,GACDC,YAAY;YACVC,QAAQ;YACRC,WAAW;YACXC,QAAQ;YACRC,QAAQ;QACV;IACF;IACA;;;;GAIC,GACDC,gBAAgB;QACd,0EAA0E,GAC1EC,MAAM;QACN,mDAAmD,GACnDC,OAAO;QACPC,aAAa;QACbC,gBAAgB;QAChBC,UAAU;QACV,0EAA0E,GAC1EC,UAAU;QACVC,MAAM;QACNC,OAAO;QACPC,SAAS;QACTC,UAAU;QACVC,YAAY;QACZ,yEAAyE,GACzEC,UAAU;QACVC,QAAQ;YACNC,SAAS;YACTC,UAAU;YACVC,YAAY;YACZC,MAAM;YACNC,SAAS;QACX;QACA;;;;KAIC,GACDC,kBAAkB;QAClBC,kBAAkB;QAClB,qEAAqE,GACrEC,qBAAqB;IACvB;IACAC,SAAS;QACPC,QAAQ;QACRC,UAAU;QACVC,UAAU;QACVC,WAAW;QACX,uEAAuE;QACvE,0EAA0E;QAC1E,oBAAoB;QACpBC,MAAM;QACNC,aAAa;QACbC,eAAe;IACjB;IACA;;;;;GAKC,GACDC,SAAS;QACPC,cACE;IACJ;IACAC,aAAa;QACXC,MAAM;QACN,uEAAuE;QACvE,sEAAsE;QACtE,8DAA8D;QAC9DC,KAAK;IACP;IACA;;;;GAIC,GACDC,SAAS;QACPC,SAAS;QACTC,UAAU;QACVC,UAAU;QACVC,SAAS;IACX;IACAC,WAAW;QACTC,UAAU;QACVjC,OACE;QACFkC,aAAa;QACb,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,8BAA8B;QAC9BC,cAAc;QACdC,SACE;QACFC,gBAAgB;QAChB,qEAAqE;QACrE,2EAA2E;QAC3E,2EAA2E;QAC3E,4EAA4E;QAC5EC,cAAc;QACdC,iBAAiB;QACjBC,mBAAmB;QACnBC,YAAY;QACZC,mBAAmB;IACrB;AAKF,EAAE"}
|
|
@@ -6,119 +6,6 @@
|
|
|
6
6
|
export declare const shellCatalogs: {
|
|
7
7
|
readonly es: {
|
|
8
8
|
readonly shell: {
|
|
9
|
-
stock: {
|
|
10
|
-
nav: {
|
|
11
|
-
stock: string;
|
|
12
|
-
items: string;
|
|
13
|
-
movements: string;
|
|
14
|
-
reservations: string;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
order: {
|
|
18
|
-
nav: {
|
|
19
|
-
orders: string;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
settlement: {
|
|
23
|
-
nav: {
|
|
24
|
-
settlement: string;
|
|
25
|
-
agreements: string;
|
|
26
|
-
entries: string;
|
|
27
|
-
runs: string;
|
|
28
|
-
payouts: string;
|
|
29
|
-
};
|
|
30
|
-
agreement: {
|
|
31
|
-
channelRatesHint: string;
|
|
32
|
-
channelRateDefault: string;
|
|
33
|
-
noChannelRates: string;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
sales: {
|
|
37
|
-
nav: {
|
|
38
|
-
sales: string;
|
|
39
|
-
channels: string;
|
|
40
|
-
guided: string;
|
|
41
|
-
counterSale: string;
|
|
42
|
-
};
|
|
43
|
-
counterSale: {
|
|
44
|
-
title: string;
|
|
45
|
-
steps: {
|
|
46
|
-
channel: string;
|
|
47
|
-
lines: string;
|
|
48
|
-
payment: string;
|
|
49
|
-
summary: string;
|
|
50
|
-
};
|
|
51
|
-
channelHint: string;
|
|
52
|
-
linesHint: string;
|
|
53
|
-
addLine: string;
|
|
54
|
-
removeLine: string;
|
|
55
|
-
quantity: string;
|
|
56
|
-
offering: string;
|
|
57
|
-
total: string;
|
|
58
|
-
paymentMethod: string;
|
|
59
|
-
charge: string;
|
|
60
|
-
sold: string;
|
|
61
|
-
soldDetail: string;
|
|
62
|
-
newSale: string;
|
|
63
|
-
emptyLines: string;
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
marketplaceAdmin: {
|
|
67
|
-
nav: {
|
|
68
|
-
catalog: string;
|
|
69
|
-
products: string;
|
|
70
|
-
brands: string;
|
|
71
|
-
categories: string;
|
|
72
|
-
offerings: string;
|
|
73
|
-
offeringPrices: string;
|
|
74
|
-
guided: string;
|
|
75
|
-
};
|
|
76
|
-
wizard: {
|
|
77
|
-
productSetup: {
|
|
78
|
-
title: string;
|
|
79
|
-
launch: string;
|
|
80
|
-
steps: {
|
|
81
|
-
start: string;
|
|
82
|
-
source: string;
|
|
83
|
-
identity: string;
|
|
84
|
-
classification: string;
|
|
85
|
-
summary: string;
|
|
86
|
-
};
|
|
87
|
-
start: {
|
|
88
|
-
question: string;
|
|
89
|
-
blank: string;
|
|
90
|
-
blankHint: string;
|
|
91
|
-
duplicate: string;
|
|
92
|
-
duplicateHint: string;
|
|
93
|
-
};
|
|
94
|
-
source: {
|
|
95
|
-
prompt: string;
|
|
96
|
-
chosen: string;
|
|
97
|
-
required: string;
|
|
98
|
-
};
|
|
99
|
-
summary: {
|
|
100
|
-
prompt: string;
|
|
101
|
-
origin: string;
|
|
102
|
-
originBlank: string;
|
|
103
|
-
originDuplicate: string;
|
|
104
|
-
empty: string;
|
|
105
|
-
};
|
|
106
|
-
recap: string;
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
systemManagement: {
|
|
111
|
-
nav: {
|
|
112
|
-
section: string;
|
|
113
|
-
configuration: string;
|
|
114
|
-
};
|
|
115
|
-
configuration: {
|
|
116
|
-
title: string;
|
|
117
|
-
description: string;
|
|
118
|
-
secretPlaceholder: string;
|
|
119
|
-
secretHint: string;
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
9
|
nav: {
|
|
123
10
|
primary: string;
|
|
124
11
|
openInWorkspace: string;
|
|
@@ -195,119 +82,6 @@ export declare const shellCatalogs: {
|
|
|
195
82
|
};
|
|
196
83
|
readonly en: {
|
|
197
84
|
readonly shell: {
|
|
198
|
-
stock: {
|
|
199
|
-
nav: {
|
|
200
|
-
stock: string;
|
|
201
|
-
items: string;
|
|
202
|
-
movements: string;
|
|
203
|
-
reservations: string;
|
|
204
|
-
};
|
|
205
|
-
};
|
|
206
|
-
order: {
|
|
207
|
-
nav: {
|
|
208
|
-
orders: string;
|
|
209
|
-
};
|
|
210
|
-
};
|
|
211
|
-
settlement: {
|
|
212
|
-
nav: {
|
|
213
|
-
settlement: string;
|
|
214
|
-
agreements: string;
|
|
215
|
-
entries: string;
|
|
216
|
-
runs: string;
|
|
217
|
-
payouts: string;
|
|
218
|
-
};
|
|
219
|
-
agreement: {
|
|
220
|
-
channelRatesHint: string;
|
|
221
|
-
channelRateDefault: string;
|
|
222
|
-
noChannelRates: string;
|
|
223
|
-
};
|
|
224
|
-
};
|
|
225
|
-
sales: {
|
|
226
|
-
nav: {
|
|
227
|
-
sales: string;
|
|
228
|
-
channels: string;
|
|
229
|
-
guided: string;
|
|
230
|
-
counterSale: string;
|
|
231
|
-
};
|
|
232
|
-
counterSale: {
|
|
233
|
-
title: string;
|
|
234
|
-
steps: {
|
|
235
|
-
channel: string;
|
|
236
|
-
lines: string;
|
|
237
|
-
payment: string;
|
|
238
|
-
summary: string;
|
|
239
|
-
};
|
|
240
|
-
channelHint: string;
|
|
241
|
-
linesHint: string;
|
|
242
|
-
addLine: string;
|
|
243
|
-
removeLine: string;
|
|
244
|
-
quantity: string;
|
|
245
|
-
offering: string;
|
|
246
|
-
total: string;
|
|
247
|
-
paymentMethod: string;
|
|
248
|
-
charge: string;
|
|
249
|
-
sold: string;
|
|
250
|
-
soldDetail: string;
|
|
251
|
-
newSale: string;
|
|
252
|
-
emptyLines: string;
|
|
253
|
-
};
|
|
254
|
-
};
|
|
255
|
-
marketplaceAdmin: {
|
|
256
|
-
nav: {
|
|
257
|
-
catalog: string;
|
|
258
|
-
products: string;
|
|
259
|
-
brands: string;
|
|
260
|
-
categories: string;
|
|
261
|
-
offerings: string;
|
|
262
|
-
offeringPrices: string;
|
|
263
|
-
guided: string;
|
|
264
|
-
};
|
|
265
|
-
wizard: {
|
|
266
|
-
productSetup: {
|
|
267
|
-
title: string;
|
|
268
|
-
launch: string;
|
|
269
|
-
steps: {
|
|
270
|
-
start: string;
|
|
271
|
-
source: string;
|
|
272
|
-
identity: string;
|
|
273
|
-
classification: string;
|
|
274
|
-
summary: string;
|
|
275
|
-
};
|
|
276
|
-
start: {
|
|
277
|
-
question: string;
|
|
278
|
-
blank: string;
|
|
279
|
-
blankHint: string;
|
|
280
|
-
duplicate: string;
|
|
281
|
-
duplicateHint: string;
|
|
282
|
-
};
|
|
283
|
-
source: {
|
|
284
|
-
prompt: string;
|
|
285
|
-
chosen: string;
|
|
286
|
-
required: string;
|
|
287
|
-
};
|
|
288
|
-
summary: {
|
|
289
|
-
prompt: string;
|
|
290
|
-
origin: string;
|
|
291
|
-
originBlank: string;
|
|
292
|
-
originDuplicate: string;
|
|
293
|
-
empty: string;
|
|
294
|
-
};
|
|
295
|
-
recap: string;
|
|
296
|
-
};
|
|
297
|
-
};
|
|
298
|
-
};
|
|
299
|
-
systemManagement: {
|
|
300
|
-
nav: {
|
|
301
|
-
section: string;
|
|
302
|
-
configuration: string;
|
|
303
|
-
};
|
|
304
|
-
configuration: {
|
|
305
|
-
title: string;
|
|
306
|
-
description: string;
|
|
307
|
-
secretPlaceholder: string;
|
|
308
|
-
secretHint: string;
|
|
309
|
-
};
|
|
310
|
-
};
|
|
311
85
|
nav: {
|
|
312
86
|
primary: string;
|
|
313
87
|
openInWorkspace: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/catalog/index.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/catalog/index.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGhB,CAAC;AAEX,qEAAqE;AACrE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC;AAE1D,eAAO,MAAM,gBAAgB,oBAAqB,CAAC"}
|
|
@@ -3,11 +3,11 @@ import { registerFallbackCatalog } from '@entifix/react-controls';
|
|
|
3
3
|
* An `entity` catalog for this package's own specs.
|
|
4
4
|
*
|
|
5
5
|
* ⚠️ **A fixture, not a shipped catalog.** `entity` names the *host's* entities,
|
|
6
|
-
* so a framework shipping one would be shipping product copy — which
|
|
7
|
-
* [ADR
|
|
8
|
-
*
|
|
6
|
+
* so a framework shipping one would be shipping product copy — which
|
|
7
|
+
* [ADR 0001](../../../../../../docs/adr/0001-the-tier-contract-and-the-host-seam.md)
|
|
8
|
+
* calls a defect. These specs assert that a nav entry, a palette command and a
|
|
9
9
|
* workspace tab name a record in the catalog's own words; a fixture proves that
|
|
10
|
-
* as well as
|
|
10
|
+
* as well as a host's copy would, and keeps the assertions readable as sentences.
|
|
11
11
|
*/ const es = {
|
|
12
12
|
product: {
|
|
13
13
|
label: 'Producto',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/i18n/spec-catalog.ts"],"sourcesContent":["import { registerFallbackCatalog } from '@entifix/react-controls';\n\n/**\n * An `entity` catalog for this package's own specs.\n *\n * ⚠️ **A fixture, not a shipped catalog.** `entity` names the *host's* entities,\n * so a framework shipping one would be shipping product copy — which
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/i18n/spec-catalog.ts"],"sourcesContent":["import { registerFallbackCatalog } from '@entifix/react-controls';\n\n/**\n * An `entity` catalog for this package's own specs.\n *\n * ⚠️ **A fixture, not a shipped catalog.** `entity` names the *host's* entities,\n * so a framework shipping one would be shipping product copy — which\n * [ADR 0001](../../../../../../docs/adr/0001-the-tier-contract-and-the-host-seam.md)\n * calls a defect. These specs assert that a nav entry, a palette command and a\n * workspace tab name a record in the catalog's own words; a fixture proves that\n * as well as a host's copy would, and keeps the assertions readable as sentences.\n */\nconst es = {\n product: { label: 'Producto', plural: 'Productos' },\n thing: { label: 'Cosa', plural: 'Cosas' },\n widget: { label: 'Artilugio', plural: 'Artilugios' },\n 'product-category': { label: 'Categoría', plural: 'Categorías' },\n 'product-brand': {\n label: 'Marca',\n plural: 'Marcas',\n form: { newTitle: 'Nueva marca', editTitle: 'Editar marca' },\n fields: {\n id: 'Id',\n code: 'Código',\n name: 'Nombre',\n website: 'Sitio web',\n },\n // No `archive` on purpose — a CRUD spec asserts that a verb the\n // catalog does not name still renders, as its key.\n useCases: { retire: 'Retirar' },\n },\n 'product-specification': {\n label: 'Producto',\n plural: 'Productos',\n fields: { id: 'Id', name: 'Nombre', brand: 'Marca' },\n },\n 'user-identity': {\n label: 'Usuario',\n plural: 'Usuarios',\n useCases: {\n signOutOthers: 'Cerrar mis otras sesiones',\n signOutOthersConfirm:\n 'Se cerrarán todas tus sesiones en otros dispositivos y navegadores. ' +\n 'Ésta seguirá abierta.',\n signOutOthersKeywords: 'cerrar sesión, dispositivos, logout',\n },\n },\n} as const;\n\nregisterFallbackCatalog('entity', { es, en: es });\n\n/**\n * The same for `errors` — the code vocabulary a host's services answer with.\n * The palette renders a scope refusal through it, so it needs the two codes\n * these specs actually raise.\n */\nconst errors = {\n noActiveOrganization: 'Selecciona una organización para ver estos registros.',\n alreadyRetired: 'El registro ya estaba retirado.',\n unexpected: 'Ocurrió un error inesperado.',\n} as const;\n\nregisterFallbackCatalog('errors', { es: errors, en: errors });\n"],"names":["registerFallbackCatalog","es","product","label","plural","thing","widget","form","newTitle","editTitle","fields","id","code","name","website","useCases","retire","brand","signOutOthers","signOutOthersConfirm","signOutOthersKeywords","en","errors","noActiveOrganization","alreadyRetired","unexpected"],"mappings":"AAAA,SAASA,uBAAuB,QAAQ,0BAA0B;AAElE;;;;;;;;;CASC,GACD,MAAMC,KAAK;IACTC,SAAS;QAAEC,OAAO;QAAYC,QAAQ;IAAY;IAClDC,OAAO;QAAEF,OAAO;QAAQC,QAAQ;IAAQ;IACxCE,QAAQ;QAAEH,OAAO;QAAaC,QAAQ;IAAa;IACnD,oBAAoB;QAAED,OAAO;QAAaC,QAAQ;IAAa;IAC/D,iBAAiB;QACfD,OAAO;QACPC,QAAQ;QACRG,MAAM;YAAEC,UAAU;YAAeC,WAAW;QAAe;QAC3DC,QAAQ;YACNC,IAAI;YACJC,MAAM;YACNC,MAAM;YACNC,SAAS;QACX;QACA,gEAAgE;QAChE,mDAAmD;QACnDC,UAAU;YAAEC,QAAQ;QAAU;IAChC;IACA,yBAAyB;QACvBb,OAAO;QACPC,QAAQ;QACRM,QAAQ;YAAEC,IAAI;YAAME,MAAM;YAAUI,OAAO;QAAQ;IACrD;IACA,iBAAiB;QACfd,OAAO;QACPC,QAAQ;QACRW,UAAU;YACRG,eAAe;YACfC,sBACE,yEACA;YACFC,uBAAuB;QACzB;IACF;AACF;AAEApB,wBAAwB,UAAU;IAAEC;IAAIoB,IAAIpB;AAAG;AAE/C;;;;CAIC,GACD,MAAMqB,SAAS;IACbC,sBAAsB;IACtBC,gBAAgB;IAChBC,YAAY;AACd;AAEAzB,wBAAwB,UAAU;IAAEC,IAAIqB;IAAQD,IAAIC;AAAO"}
|
|
@@ -28,7 +28,7 @@ export interface RecordSearchRouteOptions {
|
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* `GET /api/search` — records matching a term, across every source this host
|
|
31
|
-
* mounts
|
|
31
|
+
* mounts.
|
|
32
32
|
*
|
|
33
33
|
* The caller's own session is the only credential that crosses: each source is
|
|
34
34
|
* asked over the same guarded route its screens use, so what comes back is
|
|
@@ -76,7 +76,7 @@ const clampLimit = (raw, fallback)=>{
|
|
|
76
76
|
};
|
|
77
77
|
/**
|
|
78
78
|
* `GET /api/search` — records matching a term, across every source this host
|
|
79
|
-
* mounts
|
|
79
|
+
* mounts.
|
|
80
80
|
*
|
|
81
81
|
* The caller's own session is the only credential that crosses: each source is
|
|
82
82
|
* asked over the same guarded route its screens use, so what comes back is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/search/record-search-route.ts"],"sourcesContent":["import { NextResponse } from 'next/server';\n\nimport { bearerHeader, sessionToken } from '../session/bearer.js';\nimport type {\n RecordSearchGroup,\n RecordSearchResponse,\n RecordSearchUnavailable,\n RecordSearchUnavailableReason,\n} from './record-search.types.js';\nimport type { RecordSearchSource } from './record-search-source.js';\n\nexport const SEARCH_TERM_PARAM = 'q';\nexport const SEARCH_SOURCES_PARAM = 'sources';\nexport const SEARCH_LIMIT_PARAM = 'limit';\n\n/**\n * Below this, nothing is queried at all.\n *\n * A `like` becomes an unanchored, case-insensitive `$regex`, which no index can\n * serve — so this endpoint is a collection scan by construction. One character\n * matches most of every collection and is worth nothing to the person typing, so\n * the floor costs them nothing and saves four scans per keystroke.\n */\nexport const MIN_TERM_LENGTH = 2;\nexport const DEFAULT_GROUP_LIMIT = 5;\nexport const MAX_GROUP_LIMIT = 20;\nexport const DEFAULT_SOURCE_TIMEOUT_MS = 1_500;\n\n/** Upstream statuses that mean something other than \"we could not reach it\". */\nconst REASON_FOR_STATUS: Readonly<\n Record<number, RecordSearchUnavailableReason>\n> = {\n 400: 'invalidQuery',\n 401: 'unauthenticated',\n 403: 'forbidden',\n 404: 'notFound',\n 409: 'noActiveOrganization',\n};\n\nexport interface RecordSearchRouteOptions {\n /**\n * The sources to fan out over, **in the order results are presented**. That\n * order is the ranking: an operator learns where a kind of record lands, which\n * a relevance score across four unrelated entities cannot offer.\n */\n readonly sources: readonly RecordSearchSource[];\n /** Per-source budget. Concurrent, so this also bounds the whole request. */\n readonly timeoutMs?: number;\n /** Records per group. */\n readonly limit?: number;\n}\n\ntype SourceOutcome =\n | { readonly ok: true; readonly group: RecordSearchGroup }\n | { readonly ok: false; readonly unavailable: RecordSearchUnavailable };\n\nconst unavailable = (\n source: RecordSearchSource,\n reason: RecordSearchUnavailableReason,\n status?: number,\n): SourceOutcome => ({\n ok: false,\n unavailable: {\n source: source.key,\n entity: source.entity,\n reason,\n ...(status === undefined ? {} : { status }),\n },\n});\n\n/**\n * Ask one source, and **never reject**.\n *\n * Returning a typed outcome rather than throwing is what makes the fan-out a\n * plain `Promise.all`: isolation comes from this catch, not from\n * `allSettled` — whose rejected arm would then be unreachable and untestable.\n */\nconst runSource = async (\n source: RecordSearchSource,\n term: string,\n limit: number,\n token: string | undefined,\n timeoutMs: number,\n): Promise<SourceOutcome> => {\n let upstream: Response;\n try {\n upstream = await fetch(source.url(term, limit), {\n headers: bearerHeader(token),\n cache: 'no-store',\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (error) {\n // `AbortSignal.timeout` rejects with a `DOMException` named `TimeoutError`;\n // branching on the name rather than the class keeps this reachable from a\n // test without fabricating a platform error.\n return unavailable(\n source,\n (error as { name?: string }).name === 'TimeoutError'\n ? 'timeout'\n : 'network',\n );\n }\n\n if (!upstream.ok) {\n return unavailable(\n source,\n REASON_FOR_STATUS[upstream.status] ?? 'unexpected',\n upstream.status,\n );\n }\n\n const body = await upstream.json().catch(() => undefined);\n const page = source.read(body);\n return page === undefined\n ? unavailable(source, 'unexpected', upstream.status)\n : {\n ok: true,\n group: {\n source: source.key,\n entity: source.entity,\n labelKey: source.labelKey,\n items: page.items,\n total: page.total,\n },\n };\n};\n\nconst clampLimit = (raw: string | null, fallback: number): number => {\n const asked = Number(raw);\n if (!Number.isInteger(asked) || asked < 1) return fallback;\n return Math.min(asked, MAX_GROUP_LIMIT);\n};\n\n/**\n * `GET /api/search` — records matching a term, across every source this host\n * mounts (ADR 0040).\n *\n * The caller's own session is the only credential that crosses: each source is\n * asked over the same guarded route its screens use, so what comes back is\n * already authorized for this principal and this organization. There is no\n * index, and there must never be one — a prefetched index is a tenant leak, and\n * it is the reason this is a fan-out rather than a search service.\n *\n * A source that fails is **named** in `unavailable` rather than dropped. An\n * absent group renders as \"no matches\", which is a confident claim the server is\n * in no position to make about a service it could not reach.\n */\nexport const createRecordSearchRoute = ({\n sources,\n timeoutMs = DEFAULT_SOURCE_TIMEOUT_MS,\n limit: defaultLimit = DEFAULT_GROUP_LIMIT,\n}: RecordSearchRouteOptions) => {\n const byKey = new Map(sources.map(source => [source.key, source]));\n\n return async function GET(request: Request): Promise<Response> {\n // The services decide what this caller may read; this only carries the\n // token. But the gate is not redundant: `catalog-reference` reads are\n // unauthenticated at the service by design, so without it a signed-out\n // caller gets brand matches back and the answer reads as a real search —\n // and the endpoint becomes an anonymous amplifier against that service.\n const token = await sessionToken();\n if (token === undefined) {\n return NextResponse.json(\n { error: 'unauthenticated', code: 'unauthenticated' },\n { status: 401 },\n );\n }\n\n const params = new URL(request.url).searchParams;\n\n const asked = (params.get(SEARCH_SOURCES_PARAM) ?? '')\n .split(',')\n .filter(name => name !== '');\n const unknown = asked.find(name => !byKey.has(name));\n if (unknown !== undefined) {\n // Loud rather than ignored: no keystroke can produce this, only a caller\n // naming a source that does not exist — and silently searching everything\n // instead would answer a question nobody asked.\n return NextResponse.json(\n {\n error: 'invalid query',\n code: 'invalidQuery',\n detail: `unknown search source \"${unknown}\"`,\n },\n { status: 400 },\n );\n }\n const selected =\n asked.length === 0\n ? sources\n : sources.filter(source => asked.includes(source.key));\n\n const term = (params.get(SEARCH_TERM_PARAM) ?? '').trim();\n const answer = (body: RecordSearchResponse) =>\n // The body is scoped to one principal and one organization. `no-store` is\n // correctness here, not tuning.\n NextResponse.json(body, { headers: { 'cache-control': 'no-store' } });\n\n if (term.length < MIN_TERM_LENGTH) {\n return answer({ term, groups: [], unavailable: [] });\n }\n\n const limit = clampLimit(params.get(SEARCH_LIMIT_PARAM), defaultLimit);\n const outcomes = await Promise.all(\n selected.map(source => runSource(source, term, limit, token, timeoutMs)),\n );\n\n return answer({\n term,\n // Declared order, never completion order — otherwise the list reshuffles\n // with the network and nobody can learn where anything lands.\n groups: outcomes.flatMap(outcome => (outcome.ok ? [outcome.group] : [])),\n unavailable: outcomes.flatMap(outcome =>\n outcome.ok ? [] : [outcome.unavailable],\n ),\n });\n };\n};\n"],"names":["NextResponse","bearerHeader","sessionToken","SEARCH_TERM_PARAM","SEARCH_SOURCES_PARAM","SEARCH_LIMIT_PARAM","MIN_TERM_LENGTH","DEFAULT_GROUP_LIMIT","MAX_GROUP_LIMIT","DEFAULT_SOURCE_TIMEOUT_MS","REASON_FOR_STATUS","unavailable","source","reason","status","ok","key","entity","undefined","runSource","term","limit","token","timeoutMs","upstream","fetch","url","headers","cache","signal","AbortSignal","timeout","error","name","body","json","catch","page","read","group","labelKey","items","total","clampLimit","raw","fallback","asked","Number","isInteger","Math","min","createRecordSearchRoute","sources","defaultLimit","byKey","Map","map","GET","request","params","code","URL","searchParams","get","split","filter","unknown","find","has","detail","selected","length","includes","trim","answer","groups","outcomes","Promise","all","flatMap","outcome"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/search/record-search-route.ts"],"sourcesContent":["import { NextResponse } from 'next/server';\n\nimport { bearerHeader, sessionToken } from '../session/bearer.js';\nimport type {\n RecordSearchGroup,\n RecordSearchResponse,\n RecordSearchUnavailable,\n RecordSearchUnavailableReason,\n} from './record-search.types.js';\nimport type { RecordSearchSource } from './record-search-source.js';\n\nexport const SEARCH_TERM_PARAM = 'q';\nexport const SEARCH_SOURCES_PARAM = 'sources';\nexport const SEARCH_LIMIT_PARAM = 'limit';\n\n/**\n * Below this, nothing is queried at all.\n *\n * A `like` becomes an unanchored, case-insensitive `$regex`, which no index can\n * serve — so this endpoint is a collection scan by construction. One character\n * matches most of every collection and is worth nothing to the person typing, so\n * the floor costs them nothing and saves four scans per keystroke.\n */\nexport const MIN_TERM_LENGTH = 2;\nexport const DEFAULT_GROUP_LIMIT = 5;\nexport const MAX_GROUP_LIMIT = 20;\nexport const DEFAULT_SOURCE_TIMEOUT_MS = 1_500;\n\n/** Upstream statuses that mean something other than \"we could not reach it\". */\nconst REASON_FOR_STATUS: Readonly<\n Record<number, RecordSearchUnavailableReason>\n> = {\n 400: 'invalidQuery',\n 401: 'unauthenticated',\n 403: 'forbidden',\n 404: 'notFound',\n 409: 'noActiveOrganization',\n};\n\nexport interface RecordSearchRouteOptions {\n /**\n * The sources to fan out over, **in the order results are presented**. That\n * order is the ranking: an operator learns where a kind of record lands, which\n * a relevance score across four unrelated entities cannot offer.\n */\n readonly sources: readonly RecordSearchSource[];\n /** Per-source budget. Concurrent, so this also bounds the whole request. */\n readonly timeoutMs?: number;\n /** Records per group. */\n readonly limit?: number;\n}\n\ntype SourceOutcome =\n | { readonly ok: true; readonly group: RecordSearchGroup }\n | { readonly ok: false; readonly unavailable: RecordSearchUnavailable };\n\nconst unavailable = (\n source: RecordSearchSource,\n reason: RecordSearchUnavailableReason,\n status?: number,\n): SourceOutcome => ({\n ok: false,\n unavailable: {\n source: source.key,\n entity: source.entity,\n reason,\n ...(status === undefined ? {} : { status }),\n },\n});\n\n/**\n * Ask one source, and **never reject**.\n *\n * Returning a typed outcome rather than throwing is what makes the fan-out a\n * plain `Promise.all`: isolation comes from this catch, not from\n * `allSettled` — whose rejected arm would then be unreachable and untestable.\n */\nconst runSource = async (\n source: RecordSearchSource,\n term: string,\n limit: number,\n token: string | undefined,\n timeoutMs: number,\n): Promise<SourceOutcome> => {\n let upstream: Response;\n try {\n upstream = await fetch(source.url(term, limit), {\n headers: bearerHeader(token),\n cache: 'no-store',\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (error) {\n // `AbortSignal.timeout` rejects with a `DOMException` named `TimeoutError`;\n // branching on the name rather than the class keeps this reachable from a\n // test without fabricating a platform error.\n return unavailable(\n source,\n (error as { name?: string }).name === 'TimeoutError'\n ? 'timeout'\n : 'network',\n );\n }\n\n if (!upstream.ok) {\n return unavailable(\n source,\n REASON_FOR_STATUS[upstream.status] ?? 'unexpected',\n upstream.status,\n );\n }\n\n const body = await upstream.json().catch(() => undefined);\n const page = source.read(body);\n return page === undefined\n ? unavailable(source, 'unexpected', upstream.status)\n : {\n ok: true,\n group: {\n source: source.key,\n entity: source.entity,\n labelKey: source.labelKey,\n items: page.items,\n total: page.total,\n },\n };\n};\n\nconst clampLimit = (raw: string | null, fallback: number): number => {\n const asked = Number(raw);\n if (!Number.isInteger(asked) || asked < 1) return fallback;\n return Math.min(asked, MAX_GROUP_LIMIT);\n};\n\n/**\n * `GET /api/search` — records matching a term, across every source this host\n * mounts.\n *\n * The caller's own session is the only credential that crosses: each source is\n * asked over the same guarded route its screens use, so what comes back is\n * already authorized for this principal and this organization. There is no\n * index, and there must never be one — a prefetched index is a tenant leak, and\n * it is the reason this is a fan-out rather than a search service.\n *\n * A source that fails is **named** in `unavailable` rather than dropped. An\n * absent group renders as \"no matches\", which is a confident claim the server is\n * in no position to make about a service it could not reach.\n */\nexport const createRecordSearchRoute = ({\n sources,\n timeoutMs = DEFAULT_SOURCE_TIMEOUT_MS,\n limit: defaultLimit = DEFAULT_GROUP_LIMIT,\n}: RecordSearchRouteOptions) => {\n const byKey = new Map(sources.map(source => [source.key, source]));\n\n return async function GET(request: Request): Promise<Response> {\n // The services decide what this caller may read; this only carries the\n // token. But the gate is not redundant: `catalog-reference` reads are\n // unauthenticated at the service by design, so without it a signed-out\n // caller gets brand matches back and the answer reads as a real search —\n // and the endpoint becomes an anonymous amplifier against that service.\n const token = await sessionToken();\n if (token === undefined) {\n return NextResponse.json(\n { error: 'unauthenticated', code: 'unauthenticated' },\n { status: 401 },\n );\n }\n\n const params = new URL(request.url).searchParams;\n\n const asked = (params.get(SEARCH_SOURCES_PARAM) ?? '')\n .split(',')\n .filter(name => name !== '');\n const unknown = asked.find(name => !byKey.has(name));\n if (unknown !== undefined) {\n // Loud rather than ignored: no keystroke can produce this, only a caller\n // naming a source that does not exist — and silently searching everything\n // instead would answer a question nobody asked.\n return NextResponse.json(\n {\n error: 'invalid query',\n code: 'invalidQuery',\n detail: `unknown search source \"${unknown}\"`,\n },\n { status: 400 },\n );\n }\n const selected =\n asked.length === 0\n ? sources\n : sources.filter(source => asked.includes(source.key));\n\n const term = (params.get(SEARCH_TERM_PARAM) ?? '').trim();\n const answer = (body: RecordSearchResponse) =>\n // The body is scoped to one principal and one organization. `no-store` is\n // correctness here, not tuning.\n NextResponse.json(body, { headers: { 'cache-control': 'no-store' } });\n\n if (term.length < MIN_TERM_LENGTH) {\n return answer({ term, groups: [], unavailable: [] });\n }\n\n const limit = clampLimit(params.get(SEARCH_LIMIT_PARAM), defaultLimit);\n const outcomes = await Promise.all(\n selected.map(source => runSource(source, term, limit, token, timeoutMs)),\n );\n\n return answer({\n term,\n // Declared order, never completion order — otherwise the list reshuffles\n // with the network and nobody can learn where anything lands.\n groups: outcomes.flatMap(outcome => (outcome.ok ? [outcome.group] : [])),\n unavailable: outcomes.flatMap(outcome =>\n outcome.ok ? [] : [outcome.unavailable],\n ),\n });\n };\n};\n"],"names":["NextResponse","bearerHeader","sessionToken","SEARCH_TERM_PARAM","SEARCH_SOURCES_PARAM","SEARCH_LIMIT_PARAM","MIN_TERM_LENGTH","DEFAULT_GROUP_LIMIT","MAX_GROUP_LIMIT","DEFAULT_SOURCE_TIMEOUT_MS","REASON_FOR_STATUS","unavailable","source","reason","status","ok","key","entity","undefined","runSource","term","limit","token","timeoutMs","upstream","fetch","url","headers","cache","signal","AbortSignal","timeout","error","name","body","json","catch","page","read","group","labelKey","items","total","clampLimit","raw","fallback","asked","Number","isInteger","Math","min","createRecordSearchRoute","sources","defaultLimit","byKey","Map","map","GET","request","params","code","URL","searchParams","get","split","filter","unknown","find","has","detail","selected","length","includes","trim","answer","groups","outcomes","Promise","all","flatMap","outcome"],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { type Entity, type EntityConstructor } from '@entifix/core';
|
|
2
2
|
import type { RecordSearchOption } from './record-search.types.js';
|
|
3
3
|
/**
|
|
4
|
-
* What a host declares in order to make one entity searchable from the palette
|
|
5
|
-
* (ADR 0040).
|
|
4
|
+
* What a host declares in order to make one entity searchable from the palette.
|
|
6
5
|
*
|
|
7
6
|
* The search and label members are **declared**, not derived, and that is not an
|
|
8
7
|
* oversight in the metadata: `linkSearchProperty`/`linkLabelProperty` are
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-search-source.d.ts","sourceRoot":"","sources":["../../../src/lib/search/record-search-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,iBAAiB,EAMvB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE
|
|
1
|
+
{"version":3,"file":"record-search-source.d.ts","sourceRoot":"","sources":["../../../src/lib/search/record-search-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,iBAAiB,EAMvB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB,CAAC,OAAO,SAAS,MAAM;IAC9D,sEAAsE;IACtE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvD,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,sDAAsD;IACtD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,CACb,IAAI,EAAE,OAAO,KACV;QAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACjE;AAoBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,SAAS,MAAM,EAAE,uGAS9D,wBAAwB,CAAC,OAAO,CAAC,KAAG,kBA2ItC,CAAC"}
|