@gzl10/nexus-backend 0.19.0 → 0.20.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.
@@ -7940,96 +7940,70 @@ var init_system = __esm({
7940
7940
  }
7941
7941
  });
7942
7942
 
7943
- // src/modules/ui-settings/ui-branding.entity.ts
7944
- import { useTextField as useTextField7, useImageField } from "@gzl10/nexus-sdk/fields";
7945
- var uiBrandingEntity;
7946
- var init_ui_branding_entity = __esm({
7947
- "src/modules/ui-settings/ui-branding.entity.ts"() {
7943
+ // src/modules/ui-settings/ui-style-guide.entity.ts
7944
+ import { useTextField as useTextField7, useImageField, useSelectField as useSelectField6, useColorField, useNumberField as useNumberField4, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
7945
+ var uiStyleGuideEntity;
7946
+ var init_ui_style_guide_entity = __esm({
7947
+ "src/modules/ui-settings/ui-style-guide.entity.ts"() {
7948
7948
  "use strict";
7949
- uiBrandingEntity = {
7949
+ uiStyleGuideEntity = {
7950
7950
  type: "single",
7951
7951
  realtime: "sync",
7952
- key: "ui_branding",
7953
- label: { en: "Branding", es: "Identidad Corporativa" },
7954
- icon: "mdi:palette-swatch-outline",
7952
+ key: "ui_style_guide",
7953
+ label: { en: "Style Guide", es: "Gu\xEDa de Estilos" },
7954
+ icon: "mdi:palette-outline",
7955
7955
  public: true,
7956
- routePrefix: "/ui-branding",
7956
+ routePrefix: "/ui-style-guide",
7957
7957
  defaults: {
7958
7958
  appName: "Nexus",
7959
7959
  logo: null,
7960
7960
  logoDark: null,
7961
- favicon: null
7961
+ favicon: null,
7962
+ primaryColor: "#3B82F6",
7963
+ font: "space-grotesk",
7964
+ typographyScale: "default",
7965
+ borderRadius: 8,
7966
+ glassEffect: true,
7967
+ theme: "system",
7968
+ loginLayout: "centered"
7962
7969
  },
7963
7970
  fields: {
7964
7971
  appName: useTextField7({
7965
7972
  label: { en: "App Name", es: "Nombre de la App" },
7966
- hint: { en: "Displayed in the header, browser tab and emails", es: "Se muestra en el header, pesta\xF1a del navegador y emails" },
7973
+ hint: { en: "Displayed in header, browser tab and emails", es: "Se muestra en header, pesta\xF1a del navegador y emails" },
7967
7974
  size: 100,
7968
7975
  required: true
7969
7976
  }),
7970
7977
  logo: useImageField({
7971
7978
  label: { en: "Logo (Light Theme)", es: "Logo (Tema Claro)" },
7972
- hint: { en: "Recommended: SVG or PNG with transparent background, max 200px height", es: "Recomendado: SVG o PNG con fondo transparente, m\xE1x 200px de alto" },
7979
+ hint: { en: "SVG or PNG with transparent background, max 200px height", es: "SVG o PNG con fondo transparente, m\xE1x 200px de alto" },
7973
7980
  folder: "branding",
7974
7981
  isPublic: true,
7975
7982
  dedupe: true
7976
7983
  }),
7977
7984
  logoDark: useImageField({
7978
7985
  label: { en: "Logo (Dark Theme)", es: "Logo (Tema Oscuro)" },
7979
- hint: { en: "Optional: Use a lighter version for dark backgrounds", es: "Opcional: Usa una versi\xF3n m\xE1s clara para fondos oscuros" },
7986
+ hint: { en: "Lighter version for dark backgrounds", es: "Versi\xF3n m\xE1s clara para fondos oscuros" },
7980
7987
  folder: "branding",
7981
7988
  isPublic: true,
7982
7989
  dedupe: true
7983
7990
  }),
7984
7991
  favicon: useImageField({
7985
7992
  label: { en: "Favicon", es: "Favicon" },
7986
- hint: { en: "Browser tab icon. Recommended: 32x32 or 64x64 PNG/ICO", es: "Icono de pesta\xF1a del navegador. Recomendado: 32x32 o 64x64 PNG/ICO" },
7993
+ hint: { en: "32x32 or 64x64 PNG/ICO", es: "32x32 o 64x64 PNG/ICO" },
7987
7994
  accept: "image/x-icon,image/png,image/svg+xml",
7988
7995
  maxSize: "256KB",
7989
7996
  folder: "branding",
7990
7997
  isPublic: true,
7991
7998
  dedupe: true
7992
- })
7993
- },
7994
- casl: {
7995
- subject: "UiBranding",
7996
- permissions: {
7997
- ADMIN: { actions: ["read", "update"] }
7998
- }
7999
- }
8000
- };
8001
- }
8002
- });
8003
-
8004
- // src/modules/ui-settings/ui-theme.entity.ts
8005
- import { useSelectField as useSelectField6, useColorField } from "@gzl10/nexus-sdk/fields";
8006
- var uiThemeEntity;
8007
- var init_ui_theme_entity = __esm({
8008
- "src/modules/ui-settings/ui-theme.entity.ts"() {
8009
- "use strict";
8010
- uiThemeEntity = {
8011
- type: "single",
8012
- realtime: "sync",
8013
- key: "ui_theme",
8014
- label: { en: "Theme & Colors", es: "Tema y Colores" },
8015
- icon: "mdi:palette",
8016
- public: true,
8017
- routePrefix: "/ui-theme",
8018
- defaults: {
8019
- // Typography
8020
- font: "space-grotesk",
8021
- // Theme & Colors
8022
- theme: "system",
8023
- primaryColor: "#3B82F6",
8024
- dopamineTheme: "none",
8025
- // Layout
8026
- loginLayout: "centered"
8027
- },
8028
- fields: {
8029
- // === Typography ===
7999
+ }),
8000
+ primaryColor: useColorField({
8001
+ label: { en: "Primary Color", es: "Color Principal" },
8002
+ hint: { en: "Accent color for buttons, links and highlights", es: "Color de acento para botones, enlaces y resaltados" }
8003
+ }),
8030
8004
  font: useSelectField6({
8031
8005
  label: { en: "Font", es: "Fuente" },
8032
- hint: { en: "Primary font for headings and UI elements", es: "Fuente principal para t\xEDtulos y elementos de interfaz" },
8006
+ hint: { en: "Primary font for headings and UI", es: "Fuente principal para t\xEDtulos e interfaz" },
8033
8007
  options: [
8034
8008
  { value: "space-grotesk", label: "Space Grotesk" },
8035
8009
  { value: "inter", label: "Inter" },
@@ -8039,37 +8013,38 @@ var init_ui_theme_entity = __esm({
8039
8013
  { value: "system", label: { en: "System Default", es: "Sistema" } }
8040
8014
  ]
8041
8015
  }),
8042
- // === Theme & Colors ===
8016
+ typographyScale: useSelectField6({
8017
+ label: { en: "Typography Scale", es: "Escala Tipogr\xE1fica" },
8018
+ hint: { en: "Font size scaling (WCAG 1.4.4)", es: "Escala de tama\xF1os de fuente (WCAG 1.4.4)" },
8019
+ options: [
8020
+ { value: "compact", label: { en: "Compact", es: "Compacta" } },
8021
+ { value: "default", label: { en: "Default", es: "Por defecto" } },
8022
+ { value: "relaxed", label: { en: "Relaxed", es: "Relajada" } }
8023
+ ]
8024
+ }),
8025
+ borderRadius: useNumberField4({
8026
+ label: { en: "Border Radius", es: "Radio de Bordes" },
8027
+ hint: { en: "Corner roundness in pixels (0 = sharp, 16 = very round)", es: "Redondeo de esquinas en p\xEDxeles (0 = cuadrado, 16 = muy redondo)" },
8028
+ defaultValue: 8,
8029
+ validation: { min: 0, max: 16 }
8030
+ }),
8031
+ glassEffect: useSwitchField2({
8032
+ label: { en: "Glass Effect", es: "Efecto Glass" },
8033
+ hint: { en: "Glassmorphism blur on cards and modals", es: "Desenfoque glassmorphism en cards y modales" },
8034
+ defaultValue: true
8035
+ }),
8043
8036
  theme: useSelectField6({
8044
8037
  label: { en: "Theme", es: "Tema" },
8045
- hint: { en: "System follows your device preferences", es: "Sistema sigue las preferencias de tu dispositivo" },
8038
+ hint: { en: "System follows device preferences", es: "Sistema sigue las preferencias del dispositivo" },
8046
8039
  options: [
8047
8040
  { value: "light", label: { en: "Light", es: "Claro" } },
8048
8041
  { value: "dark", label: { en: "Dark", es: "Oscuro" } },
8049
8042
  { value: "system", label: { en: "System", es: "Sistema" } }
8050
8043
  ]
8051
8044
  }),
8052
- dopamineTheme: useSelectField6({
8053
- label: { en: "Dopamine Theme", es: "Tema Dopamina" },
8054
- hint: { en: "Vibrant color presets optimized for light and dark modes (2025/2026 trends)", es: "Presets de colores vibrantes optimizados para modo claro y oscuro (tendencias 2025/2026)" },
8055
- options: [
8056
- { value: "none", label: { en: "None (Custom Color)", es: "Ninguno (Color personalizado)" } },
8057
- { value: "electric", label: { en: "Electric (Cobalt Blue)", es: "El\xE9ctrico (Azul Cobalto)" } },
8058
- { value: "sunset", label: { en: "Sunset (Coral Red)", es: "Atardecer (Rojo Coral)" } },
8059
- { value: "ocean", label: { en: "Ocean (Teal)", es: "Oc\xE9ano (Verde Azulado)" } },
8060
- { value: "forest", label: { en: "Forest (Mint)", es: "Bosque (Menta)" } },
8061
- { value: "lavender", label: { en: "Lavender (Violet)", es: "Lavanda (Violeta)" } },
8062
- { value: "cherry", label: { en: "Cherry (Fuchsia)", es: "Cereza (Fucsia)" } },
8063
- { value: "amber", label: { en: "Amber (Golden)", es: "\xC1mbar (Dorado)" } },
8064
- { value: "tangerine", label: { en: "Tangerine (Orange)", es: "Mandarina (Naranja)" } },
8065
- { value: "slate", label: { en: "Slate (Cool Gray)", es: "Pizarra (Gris Fr\xEDo)" } },
8066
- { value: "bronze", label: { en: "Bronze (Earth)", es: "Bronce (Tierra)" } }
8067
- ]
8068
- }),
8069
- // === Login Layout ===
8070
8045
  loginLayout: useSelectField6({
8071
8046
  label: { en: "Login Layout", es: "Dise\xF1o de Login" },
8072
- hint: { en: "Visual layout for authentication pages", es: "Dise\xF1o visual para p\xE1ginas de autenticaci\xF3n" },
8047
+ hint: { en: "Auth page visual layout", es: "Dise\xF1o visual de p\xE1ginas de autenticaci\xF3n" },
8073
8048
  options: [
8074
8049
  { value: "centered", label: { en: "Centered", es: "Centrado" } },
8075
8050
  { value: "split", label: { en: "Split", es: "Dividido" } },
@@ -8077,140 +8052,10 @@ var init_ui_theme_entity = __esm({
8077
8052
  { value: "floating", label: { en: "Floating", es: "Flotante" } },
8078
8053
  { value: "minimal", label: { en: "Minimal", es: "Minimalista" } }
8079
8054
  ]
8080
- }),
8081
- primaryColor: {
8082
- ...useColorField({
8083
- label: { en: "Primary Color", es: "Color Principal" },
8084
- hint: { en: "Custom accent color for buttons, links and highlights", es: "Color de acento personalizado para botones, enlaces y resaltados" }
8085
- }),
8086
- // Hide when a dopamine theme is active (show only if 'none')
8087
- hidden: { field: "dopamineTheme", $ne: "none" }
8088
- }
8089
- },
8090
- casl: {
8091
- subject: "UiTheme",
8092
- permissions: {
8093
- ADMIN: { actions: ["read", "update"] }
8094
- }
8095
- }
8096
- };
8097
- }
8098
- });
8099
-
8100
- // src/modules/ui-settings/ui-effects.entity.ts
8101
- import { useSelectField as useSelectField7, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
8102
- var uiEffectsEntity;
8103
- var init_ui_effects_entity = __esm({
8104
- "src/modules/ui-settings/ui-effects.entity.ts"() {
8105
- "use strict";
8106
- uiEffectsEntity = {
8107
- type: "single",
8108
- realtime: "sync",
8109
- key: "ui_effects",
8110
- label: { en: "Visual Effects", es: "Efectos Visuales" },
8111
- icon: "mdi:shimmer",
8112
- public: true,
8113
- routePrefix: "/ui-effects",
8114
- defaults: {
8115
- glassIntensity: "medium",
8116
- borderStyle: "rounded",
8117
- enableAnimations: true,
8118
- enableOrganicShapes: false
8119
- },
8120
- fields: {
8121
- glassIntensity: useSelectField7({
8122
- label: { en: "Glass Intensity", es: "Intensidad Glass" },
8123
- hint: { en: "Glassmorphism blur effect on cards and modals", es: "Efecto de desenfoque glassmorphism en cards y modales" },
8124
- options: [
8125
- { value: "none", label: { en: "None", es: "Ninguno" } },
8126
- { value: "low", label: { en: "Low", es: "Baja" } },
8127
- { value: "medium", label: { en: "Medium", es: "Media" } },
8128
- { value: "high", label: { en: "High", es: "Alta" } }
8129
- ]
8130
- }),
8131
- borderStyle: useSelectField7({
8132
- label: { en: "Border Style", es: "Estilo de Bordes" },
8133
- hint: { en: "Corner radius for buttons, cards and inputs", es: "Radio de esquinas para botones, cards e inputs" },
8134
- options: [
8135
- { value: "sharp", label: { en: "Sharp", es: "Cuadrados" } },
8136
- { value: "rounded", label: { en: "Rounded", es: "Redondeados" } },
8137
- { value: "organic", label: { en: "Organic", es: "Org\xE1nicos" } }
8138
- ]
8139
- }),
8140
- enableAnimations: useSwitchField2({
8141
- label: { en: "Enable Animations", es: "Habilitar Animaciones" },
8142
- hint: { en: "Micro-interactions and transitions (hover, focus, page changes)", es: "Micro-interacciones y transiciones (hover, focus, cambios de p\xE1gina)" },
8143
- defaultValue: true,
8144
- meta: { sortable: true }
8145
- }),
8146
- enableOrganicShapes: useSwitchField2({
8147
- label: { en: "Enable Organic Shapes", es: "Habilitar Formas Org\xE1nicas" },
8148
- hint: { en: "Asymmetric border-radius for a more natural, playful look", es: "Border-radius asim\xE9trico para un aspecto m\xE1s natural y divertido" },
8149
- defaultValue: false,
8150
- meta: { sortable: true },
8151
- hidden: { field: "borderStyle", $ne: "organic" }
8152
8055
  })
8153
8056
  },
8154
8057
  casl: {
8155
- subject: "UiEffects",
8156
- permissions: {
8157
- ADMIN: { actions: ["read", "update"] }
8158
- }
8159
- }
8160
- };
8161
- }
8162
- });
8163
-
8164
- // src/modules/ui-settings/ui-accessibility.entity.ts
8165
- import { useSelectField as useSelectField8, useSwitchField as useSwitchField3 } from "@gzl10/nexus-sdk/fields";
8166
- var uiAccessibilityEntity;
8167
- var init_ui_accessibility_entity = __esm({
8168
- "src/modules/ui-settings/ui-accessibility.entity.ts"() {
8169
- "use strict";
8170
- uiAccessibilityEntity = {
8171
- type: "single",
8172
- realtime: "sync",
8173
- key: "ui_accessibility",
8174
- label: { en: "Accessibility", es: "Accesibilidad" },
8175
- icon: "mdi:human",
8176
- public: true,
8177
- routePrefix: "/ui-accessibility",
8178
- defaults: {
8179
- typographyScale: "default",
8180
- reducedMotion: false,
8181
- highContrast: false
8182
- },
8183
- fields: {
8184
- typographyScale: useSelectField8({
8185
- label: { en: "Typography Scale", es: "Escala Tipogr\xE1fica" },
8186
- hint: { en: "Adjusts font sizes for better readability (WCAG 1.4.4)", es: "Ajusta tama\xF1os de fuente para mejor legibilidad (WCAG 1.4.4)" },
8187
- options: [
8188
- { value: "compact", label: { en: "Compact (smaller)", es: "Compacta (m\xE1s peque\xF1a)" } },
8189
- { value: "default", label: { en: "Default", es: "Por defecto" } },
8190
- { value: "relaxed", label: { en: "Relaxed (larger)", es: "Relajada (m\xE1s grande)" } }
8191
- ]
8192
- }),
8193
- reducedMotion: useSwitchField3({
8194
- label: { en: "Reduced Motion", es: "Movimiento Reducido" },
8195
- defaultValue: false,
8196
- meta: { sortable: true },
8197
- hint: {
8198
- en: "Minimizes animations for users sensitive to motion (WCAG 2.1)",
8199
- es: "Minimiza animaciones para usuarios sensibles al movimiento (WCAG 2.1)"
8200
- }
8201
- }),
8202
- highContrast: useSwitchField3({
8203
- label: { en: "High Contrast", es: "Alto Contraste" },
8204
- defaultValue: false,
8205
- meta: { sortable: true },
8206
- hint: {
8207
- en: "Increases text contrast for better readability (WCAG AAA)",
8208
- es: "Aumenta el contraste del texto para mejor legibilidad (WCAG AAA)"
8209
- }
8210
- })
8211
- },
8212
- casl: {
8213
- subject: "UiAccessibility",
8058
+ subject: "UiStyleGuide",
8214
8059
  permissions: {
8215
8060
  ADMIN: { actions: ["read", "update"] }
8216
8061
  }
@@ -8220,24 +8065,20 @@ var init_ui_accessibility_entity = __esm({
8220
8065
  });
8221
8066
 
8222
8067
  // src/modules/ui-settings/index.ts
8068
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
8069
+ import { join as join5 } from "path";
8223
8070
  var init_ui_settings = __esm({
8224
8071
  "src/modules/ui-settings/index.ts"() {
8225
8072
  "use strict";
8226
- init_ui_branding_entity();
8227
- init_ui_theme_entity();
8228
- init_ui_effects_entity();
8229
- init_ui_accessibility_entity();
8230
- init_ui_branding_entity();
8231
- init_ui_theme_entity();
8232
- init_ui_effects_entity();
8233
- init_ui_accessibility_entity();
8073
+ init_ui_style_guide_entity();
8074
+ init_ui_style_guide_entity();
8234
8075
  }
8235
8076
  });
8236
8077
 
8237
8078
  // src/modules/storage/drivers/filesystem.driver.ts
8238
- import { createReadStream, createWriteStream, existsSync as existsSync3, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
8079
+ import { createReadStream, createWriteStream, existsSync as existsSync4, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
8239
8080
  import { readFile, readdir, stat, copyFile, rename, mkdir } from "fs/promises";
8240
- import { join as join5, dirname as dirname3, extname, basename } from "path";
8081
+ import { join as join6, dirname as dirname3, extname, basename } from "path";
8241
8082
  import { createHash } from "crypto";
8242
8083
  var init_filesystem_driver = __esm({
8243
8084
  "src/modules/storage/drivers/filesystem.driver.ts"() {
@@ -8265,8 +8106,8 @@ var init_s3_driver = __esm({
8265
8106
  });
8266
8107
 
8267
8108
  // src/modules/storage/storage.config.ts
8268
- import { join as join6, isAbsolute } from "path";
8269
- import { existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
8109
+ import { join as join7, isAbsolute } from "path";
8110
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
8270
8111
  var DEFAULT_MAX_SIZE, projectPath;
8271
8112
  var init_storage_config = __esm({
8272
8113
  "src/modules/storage/storage.config.ts"() {
@@ -8298,7 +8139,7 @@ var init_storage_service = __esm({
8298
8139
  });
8299
8140
 
8300
8141
  // src/modules/storage/storage.entity.ts
8301
- import { useIdField as useIdField3, useTextField as useTextField8, useSelectField as useSelectField9, useUrlField, useNumberField as useNumberField4, useCheckboxField as useCheckboxField3, useJsonField as useJsonField2, useMetadataField, usePublicField } from "@gzl10/nexus-sdk/fields";
8142
+ import { useIdField as useIdField3, useTextField as useTextField8, useSelectField as useSelectField7, useUrlField, useNumberField as useNumberField5, useCheckboxField as useCheckboxField3, useJsonField as useJsonField2, useMetadataField, usePublicField } from "@gzl10/nexus-sdk/fields";
8302
8143
  var DEFAULT_MAX_SIZE2, storageConfigEntity, storageFilesEntity;
8303
8144
  var init_storage_entity = __esm({
8304
8145
  "src/modules/storage/storage.entity.ts"() {
@@ -8333,7 +8174,7 @@ var init_storage_entity = __esm({
8333
8174
  hint: { en: "Unique identifier (e.g. default_filesystem, default_s3)", es: "Identificador \xFAnico (ej: default_filesystem, default_s3)" }
8334
8175
  }),
8335
8176
  driver: {
8336
- ...useSelectField9({
8177
+ ...useSelectField7({
8337
8178
  label: { en: "Driver", es: "Controlador" },
8338
8179
  required: true,
8339
8180
  hint: { en: "Storage backend", es: "Backend de almacenamiento" },
@@ -8350,7 +8191,7 @@ var init_storage_entity = __esm({
8350
8191
  size: 500,
8351
8192
  nullable: true
8352
8193
  }),
8353
- max_file_size: useNumberField4({
8194
+ max_file_size: useNumberField5({
8354
8195
  label: { en: "Max File Size (bytes)", es: "Tama\xF1o m\xE1ximo de archivo (bytes)" },
8355
8196
  hint: { en: "Maximum size in bytes (default: 10MB = 10485760)", es: "Tama\xF1o m\xE1ximo en bytes (default: 10MB = 10485760)" },
8356
8197
  nullable: false,
@@ -8543,7 +8384,7 @@ var init_storage_entity = __esm({
8543
8384
  index: true,
8544
8385
  meta: { sortable: true, searchable: true }
8545
8386
  }),
8546
- size: useNumberField4({
8387
+ size: useNumberField5({
8547
8388
  label: { en: "Size", es: "Tama\xF1o" },
8548
8389
  required: true,
8549
8390
  nullable: false,
@@ -8682,7 +8523,7 @@ var init_storage = __esm({
8682
8523
  });
8683
8524
 
8684
8525
  // src/modules/users/users.entity.ts
8685
- import { useIdField as useIdField4, useSelectField as useSelectField10, useEmailField, usePasswordField, useTextField as useTextField9, useDatetimeField as useDatetimeField3, useCheckboxField as useCheckboxField4, useImageField as useImageField2, useNameField as useNameField2, useMetadataField as useMetadataField2, useDescriptionField as useDescriptionField2 } from "@gzl10/nexus-sdk/fields";
8526
+ import { useIdField as useIdField4, useSelectField as useSelectField8, useEmailField, usePasswordField, useTextField as useTextField9, useDatetimeField as useDatetimeField3, useCheckboxField as useCheckboxField4, useImageField as useImageField2, useNameField as useNameField2, useMetadataField as useMetadataField2, useDescriptionField as useDescriptionField2 } from "@gzl10/nexus-sdk/fields";
8686
8527
  import { z as z2 } from "zod";
8687
8528
  var userEntity, roleEntity, userRoleEntity;
8688
8529
  var init_users_entity = __esm({
@@ -8756,7 +8597,7 @@ var init_users_entity = __esm({
8756
8597
  label: { en: "Marketing Opt-in", es: "Aceptar marketing" },
8757
8598
  meta: { exportable: true, showInForm: false, showInDisplay: false }
8758
8599
  }),
8759
- locale: useSelectField10({
8600
+ locale: useSelectField8({
8760
8601
  label: { en: "Language", es: "Idioma" },
8761
8602
  options: [
8762
8603
  { value: "es", label: { en: "Spanish", es: "Espa\xF1ol" } },
@@ -8766,13 +8607,13 @@ var init_users_entity = __esm({
8766
8607
  meta: { sortable: true },
8767
8608
  defaultValue: "en"
8768
8609
  }),
8769
- timezone: useSelectField10({
8610
+ timezone: useSelectField8({
8770
8611
  label: { en: "Timezone", es: "Zona horaria" },
8771
8612
  master: "timezones",
8772
8613
  meta: { sortable: true },
8773
8614
  defaultValue: "timezones:Europe/Madrid"
8774
8615
  }),
8775
- type: useSelectField10({
8616
+ type: useSelectField8({
8776
8617
  label: { en: "Type", es: "Tipo" },
8777
8618
  defaultValue: "human",
8778
8619
  options: [
@@ -8941,7 +8782,7 @@ var init_users_entity = __esm({
8941
8782
  expose: false,
8942
8783
  fields: {
8943
8784
  id: useIdField4(),
8944
- user_id: useSelectField10({
8785
+ user_id: useSelectField8({
8945
8786
  label: { en: "User", es: "Usuario" },
8946
8787
  required: true,
8947
8788
  table: "users",
@@ -8952,7 +8793,7 @@ var init_users_entity = __esm({
8952
8793
  labelField: "name",
8953
8794
  meta: { searchable: true }
8954
8795
  }),
8955
- role_id: useSelectField10({
8796
+ role_id: useSelectField8({
8956
8797
  label: { en: "Role", es: "Rol" },
8957
8798
  required: true,
8958
8799
  table: "roles",
@@ -9012,7 +8853,7 @@ var init_users = __esm({
9012
8853
  });
9013
8854
 
9014
8855
  // src/modules/auth/auth.entity.ts
9015
- import { useIdField as useIdField5, useTextField as useTextField10, useSelectField as useSelectField11, useDatetimeField as useDatetimeField4, useEmailField as useEmailField2, useMetadataField as useMetadataField3, useExpiresAtField } from "@gzl10/nexus-sdk/fields";
8856
+ import { useIdField as useIdField5, useTextField as useTextField10, useSelectField as useSelectField9, useDatetimeField as useDatetimeField4, useEmailField as useEmailField2, useMetadataField as useMetadataField3, useExpiresAtField } from "@gzl10/nexus-sdk/fields";
9016
8857
  var refreshTokenEntity, authIdentitiesEntity;
9017
8858
  var init_auth_entity = __esm({
9018
8859
  "src/modules/auth/auth.entity.ts"() {
@@ -9093,7 +8934,7 @@ var init_auth_entity = __esm({
9093
8934
  order: 5,
9094
8935
  fields: {
9095
8936
  id: useIdField5(),
9096
- user_id: useSelectField11({
8937
+ user_id: useSelectField9({
9097
8938
  label: { en: "User", es: "Usuario" },
9098
8939
  table: "users",
9099
8940
  column: "id",
@@ -9166,30 +9007,258 @@ var init_auth_routes = __esm({
9166
9007
  }
9167
9008
  });
9168
9009
 
9169
- // src/modules/auth/auth.config.ts
9010
+ // src/config/env.ts
9170
9011
  import { z as z4 } from "zod";
9012
+ function resolveConfig() {
9013
+ env = envSchema.parse(process.env);
9014
+ process.env["TZ"] = env.TZ;
9015
+ resolvedConfig = {
9016
+ nodeEnv: env.NODE_ENV,
9017
+ port: env.PORT,
9018
+ host: "0.0.0.0",
9019
+ ui: {
9020
+ enabled: env.NEXUS_UI_ENABLED,
9021
+ base: env.NEXUS_UI_BASE,
9022
+ path: env.NEXUS_UI_PATH
9023
+ },
9024
+ corsOrigin: env.CORS_ORIGIN,
9025
+ databaseUrl: env.DATABASE_URL,
9026
+ adminEmail: env.ADMIN_EMAIL,
9027
+ adminPassword: env.ADMIN_PASSWORD,
9028
+ timezone: env.TZ
9029
+ };
9030
+ return resolvedConfig;
9031
+ }
9032
+ function getConfig() {
9033
+ if (!resolvedConfig) {
9034
+ return resolveConfig();
9035
+ }
9036
+ return resolvedConfig;
9037
+ }
9038
+ function resetConfig() {
9039
+ resolvedConfig = null;
9040
+ }
9041
+ var envSchema, env, resolvedConfig;
9042
+ var init_env = __esm({
9043
+ "src/config/env.ts"() {
9044
+ "use strict";
9045
+ envSchema = z4.object({
9046
+ NODE_ENV: z4.enum(["development", "production", "test"]).default("development"),
9047
+ PORT: z4.coerce.number().default(3e3),
9048
+ CORS_ORIGIN: z4.string().default("*"),
9049
+ BACKEND_URL: z4.string().optional(),
9050
+ DATABASE_URL: z4.string().default("file:./dev.db"),
9051
+ REDIS_URL: z4.string().url().optional(),
9052
+ REDIS_PREFIX: z4.string().default("nexus"),
9053
+ ADMIN_EMAIL: z4.string().email().optional(),
9054
+ ADMIN_PASSWORD: z4.string().min(6).optional(),
9055
+ COOKIE_DOMAIN: z4.string().optional(),
9056
+ TZ: z4.string().default("UTC"),
9057
+ TRUST_PROXY: z4.coerce.boolean().default(false),
9058
+ NEXUS_UI_ENABLED: z4.coerce.boolean().default(true),
9059
+ NEXUS_UI_BASE: z4.string().default("/"),
9060
+ NEXUS_UI_PATH: z4.string().default("../ui/dist"),
9061
+ NEXUS_CHECK_DRIFT: z4.coerce.boolean().optional(),
9062
+ NEXUS_FAIL_ON_DRIFT: z4.coerce.boolean().optional(),
9063
+ FRPC_SERVER: z4.string().optional(),
9064
+ FRPC_SERVER_PORT: z4.coerce.number().default(7e3),
9065
+ FRPC_TOKEN: z4.string().optional(),
9066
+ FRPC_SUBDOMAIN: z4.string().optional()
9067
+ });
9068
+ env = envSchema.parse(process.env);
9069
+ process.env["TZ"] = env.TZ;
9070
+ resolvedConfig = null;
9071
+ }
9072
+ });
9073
+
9074
+ // src/db/sql-utils.ts
9075
+ function extractTableFromSql(sql, type2) {
9076
+ const match = sql.match(SQL_PATTERNS[type2]);
9077
+ return match?.[1];
9078
+ }
9079
+ function extractTableFromSelect(sql) {
9080
+ return extractTableFromSql(sql, "select");
9081
+ }
9082
+ function extractTableFromInsert(sql) {
9083
+ return extractTableFromSql(sql, "insert");
9084
+ }
9085
+ function extractTableFromUpdate(sql) {
9086
+ return extractTableFromSql(sql, "update");
9087
+ }
9088
+ function extractTableFromDelete(sql) {
9089
+ return extractTableFromSql(sql, "delete");
9090
+ }
9091
+ var SQL_PATTERNS;
9092
+ var init_sql_utils = __esm({
9093
+ "src/db/sql-utils.ts"() {
9094
+ "use strict";
9095
+ SQL_PATTERNS = {
9096
+ select: /from\s+["'`]?(\w+)["'`]?/i,
9097
+ insert: /insert into\s+["'`]?(\w+)["'`]?/i,
9098
+ update: /update\s+["'`]?(\w+)["'`]?/i,
9099
+ delete: /delete from\s+["'`]?(\w+)["'`]?/i
9100
+ };
9101
+ }
9102
+ });
9103
+
9104
+ // src/db/sqlite-compat.ts
9105
+ function createSqliteBooleanProcessor() {
9106
+ const booleanColumns = /* @__PURE__ */ new Map();
9107
+ function registerBooleanColumn2(table, column) {
9108
+ if (!booleanColumns.has(table)) {
9109
+ booleanColumns.set(table, /* @__PURE__ */ new Set());
9110
+ }
9111
+ booleanColumns.get(table).add(column);
9112
+ }
9113
+ function convertBooleans2(table, row) {
9114
+ const columns = booleanColumns.get(table);
9115
+ if (!columns || columns.size === 0) return row;
9116
+ const result = { ...row };
9117
+ for (const column of columns) {
9118
+ if (column in result) {
9119
+ const value = result[column];
9120
+ if (value === 0 || value === 1) {
9121
+ result[column] = value === 1;
9122
+ }
9123
+ }
9124
+ }
9125
+ return result;
9126
+ }
9127
+ function postProcess(result, queryContext) {
9128
+ const sql = queryContext?.sql?.toLowerCase() ?? "";
9129
+ if (!sql.startsWith("select")) return result;
9130
+ const table = extractTableFromSelect(sql);
9131
+ if (!table) return result;
9132
+ if (Array.isArray(result)) {
9133
+ return result.map(
9134
+ (row) => typeof row === "object" && row !== null ? convertBooleans2(table, row) : row
9135
+ );
9136
+ }
9137
+ if (typeof result === "object" && result !== null) {
9138
+ return convertBooleans2(table, result);
9139
+ }
9140
+ return result;
9141
+ }
9142
+ function clear() {
9143
+ booleanColumns.clear();
9144
+ }
9145
+ return { registerBooleanColumn: registerBooleanColumn2, convertBooleans: convertBooleans2, postProcess, clear };
9146
+ }
9147
+ var defaultProcessor, registerBooleanColumn, convertBooleans, sqlitePostProcess;
9148
+ var init_sqlite_compat = __esm({
9149
+ "src/db/sqlite-compat.ts"() {
9150
+ "use strict";
9151
+ init_sql_utils();
9152
+ defaultProcessor = createSqliteBooleanProcessor();
9153
+ registerBooleanColumn = defaultProcessor.registerBooleanColumn;
9154
+ convertBooleans = defaultProcessor.convertBooleans;
9155
+ sqlitePostProcess = defaultProcessor.postProcess;
9156
+ }
9157
+ });
9158
+
9159
+ // src/config/database.ts
9160
+ import { join as join8, dirname as dirname5, isAbsolute as isAbsolute2 } from "path";
9161
+ import { mkdirSync as mkdirSync4 } from "fs";
9162
+ function getDatabaseConfig() {
9163
+ const url = getConfig().databaseUrl;
9164
+ if (IN_MEMORY_RE.test(url)) {
9165
+ return {
9166
+ client: "better-sqlite3",
9167
+ connection: { filename: ":memory:" },
9168
+ useNullAsDefault: true,
9169
+ postProcessResponse: sqlitePostProcess,
9170
+ pool: { min: 0, max: 1 }
9171
+ };
9172
+ }
9173
+ if (url.startsWith("file:") || url.startsWith("sqlite:")) {
9174
+ let filename = url.replace(/^(file:|sqlite:)/, "");
9175
+ if (!isAbsolute2(filename)) {
9176
+ filename = join8(getProjectPath(), "data", filename);
9177
+ }
9178
+ mkdirSync4(dirname5(filename), { recursive: true });
9179
+ return {
9180
+ client: "better-sqlite3",
9181
+ connection: { filename },
9182
+ useNullAsDefault: true,
9183
+ postProcessResponse: sqlitePostProcess
9184
+ };
9185
+ }
9186
+ if (url.startsWith("postgresql://") || url.startsWith("postgres://")) {
9187
+ return {
9188
+ client: "pg",
9189
+ connection: url,
9190
+ pool: { min: 2, max: 10 }
9191
+ };
9192
+ }
9193
+ if (url.startsWith("mysql://")) {
9194
+ const offsetMinutes = (/* @__PURE__ */ new Date()).getTimezoneOffset();
9195
+ const offsetHours = Math.abs(Math.floor(offsetMinutes / 60));
9196
+ const offsetMins = Math.abs(offsetMinutes % 60);
9197
+ const sign = offsetMinutes <= 0 ? "+" : "-";
9198
+ const tzOffset = `${sign}${String(offsetHours).padStart(2, "0")}:${String(offsetMins).padStart(2, "0")}`;
9199
+ return {
9200
+ client: "mysql2",
9201
+ connection: {
9202
+ uri: url,
9203
+ timezone: tzOffset
9204
+ // mysql2 requiere formato "+HH:MM"
9205
+ },
9206
+ pool: { min: 2, max: 10 }
9207
+ };
9208
+ }
9209
+ throw new Error(`Unsupported database URL: ${url}`);
9210
+ }
9211
+ var IN_MEMORY_RE;
9212
+ var init_database = __esm({
9213
+ "src/config/database.ts"() {
9214
+ "use strict";
9215
+ init_env();
9216
+ init_paths();
9217
+ init_sqlite_compat();
9218
+ IN_MEMORY_RE = /^((file:|sqlite:)?:memory:?)$/;
9219
+ }
9220
+ });
9221
+
9222
+ // src/core/crypto/secret-resolver.ts
9223
+ import { randomBytes } from "crypto";
9224
+ function _resetSecretResolver() {
9225
+ _secret = null;
9226
+ _db = null;
9227
+ }
9228
+ var _secret, _db;
9229
+ var init_secret_resolver = __esm({
9230
+ "src/core/crypto/secret-resolver.ts"() {
9231
+ "use strict";
9232
+ init_database();
9233
+ _secret = null;
9234
+ _db = null;
9235
+ }
9236
+ });
9237
+
9238
+ // src/modules/auth/auth.config.ts
9239
+ import { z as z5 } from "zod";
9171
9240
  var authEnvSchema;
9172
9241
  var init_auth_config = __esm({
9173
9242
  "src/modules/auth/auth.config.ts"() {
9174
9243
  "use strict";
9175
- authEnvSchema = z4.object({
9176
- AUTH_SECRET: z4.string().min(32, "AUTH_SECRET must be at least 32 characters"),
9177
- AUTH_ACCESS_EXPIRES: z4.string().default("15m"),
9178
- AUTH_REFRESH_EXPIRES: z4.string().default("7d"),
9244
+ init_secret_resolver();
9245
+ authEnvSchema = z5.object({
9246
+ AUTH_ACCESS_EXPIRES: z5.string().default("15m"),
9247
+ AUTH_REFRESH_EXPIRES: z5.string().default("7d"),
9179
9248
  // Rate limiting (default: 5 requests per 15 minutes)
9180
- AUTH_RATE_LIMIT_MAX: z4.coerce.number().default(5),
9181
- AUTH_RATE_LIMIT_WINDOW: z4.coerce.number().default(900),
9249
+ AUTH_RATE_LIMIT_MAX: z5.coerce.number().default(5),
9250
+ AUTH_RATE_LIMIT_WINDOW: z5.coerce.number().default(900),
9182
9251
  // seconds
9183
9252
  // Cookie domain for SSO across subdomains (e.g., '.example.com')
9184
- AUTH_COOKIE_DOMAIN: z4.string().optional(),
9253
+ AUTH_COOKIE_DOMAIN: z5.string().optional(),
9185
9254
  // Challenge threshold: failed attempts before requiring OTP (default: 2)
9186
- AUTH_CHALLENGE_THRESHOLD: z4.coerce.number().default(2),
9255
+ AUTH_CHALLENGE_THRESHOLD: z5.coerce.number().default(2),
9187
9256
  // Skip OTP verification for registration (DEVELOPMENT ONLY - rejected in production)
9188
- AUTH_SKIP_REGISTER_OTP: z4.coerce.boolean().default(false),
9257
+ AUTH_SKIP_REGISTER_OTP: z5.coerce.boolean().default(false),
9189
9258
  // Disable self-registration via POST /auth/register (default: false)
9190
- AUTH_DISABLE_REGISTRATION: z4.coerce.boolean().default(false),
9259
+ AUTH_DISABLE_REGISTRATION: z5.coerce.boolean().default(false),
9191
9260
  // Disable auto-creation of users on first OIDC login (default: false)
9192
- AUTH_DISABLE_AUTO_CREATE: z4.coerce.boolean().default(false)
9261
+ AUTH_DISABLE_AUTO_CREATE: z5.coerce.boolean().default(false)
9193
9262
  });
9194
9263
  }
9195
9264
  });
@@ -9204,7 +9273,7 @@ var init_auth_middleware = __esm({
9204
9273
  });
9205
9274
 
9206
9275
  // src/modules/auth/auth.pat.entity.ts
9207
- import { useIdField as useIdField6, useTextField as useTextField11, useSelectField as useSelectField12, useDatetimeField as useDatetimeField5, useExpiresAtField as useExpiresAtField2 } from "@gzl10/nexus-sdk/fields";
9276
+ import { useIdField as useIdField6, useTextField as useTextField11, useSelectField as useSelectField10, useDatetimeField as useDatetimeField5, useExpiresAtField as useExpiresAtField2 } from "@gzl10/nexus-sdk/fields";
9208
9277
  var personalTokenEntity;
9209
9278
  var init_auth_pat_entity = __esm({
9210
9279
  "src/modules/auth/auth.pat.entity.ts"() {
@@ -9221,7 +9290,7 @@ var init_auth_pat_entity = __esm({
9221
9290
  routePrefix: "/personal-tokens",
9222
9291
  fields: {
9223
9292
  id: useIdField6(),
9224
- user_id: useSelectField12({
9293
+ user_id: useSelectField10({
9225
9294
  label: { en: "User", es: "Usuario" },
9226
9295
  table: "users",
9227
9296
  column: "id",
@@ -9256,7 +9325,7 @@ var init_auth_pat_entity = __esm({
9256
9325
  unique: true,
9257
9326
  meta: { exportable: false }
9258
9327
  }),
9259
- scope: useSelectField12({
9328
+ scope: useSelectField10({
9260
9329
  label: { en: "Permission", es: "Permiso" },
9261
9330
  required: true,
9262
9331
  options: [
@@ -9288,14 +9357,6 @@ var init_auth_pat_entity = __esm({
9288
9357
  }
9289
9358
  });
9290
9359
 
9291
- // src/modules/auth/actions/providers.action.ts
9292
- var init_providers_action = __esm({
9293
- "src/modules/auth/actions/providers.action.ts"() {
9294
- "use strict";
9295
- init_auth_config();
9296
- }
9297
- });
9298
-
9299
9360
  // src/modules/auth/actions/helpers.ts
9300
9361
  var init_helpers2 = __esm({
9301
9362
  "src/modules/auth/actions/helpers.ts"() {
@@ -9426,7 +9487,6 @@ var init_impersonate_action = __esm({
9426
9487
  var init_actions2 = __esm({
9427
9488
  "src/modules/auth/actions/index.ts"() {
9428
9489
  "use strict";
9429
- init_providers_action();
9430
9490
  init_login_action();
9431
9491
  init_register_action();
9432
9492
  init_forgot_password_action();
@@ -9442,7 +9502,6 @@ var init_actions2 = __esm({
9442
9502
  init_list_tokens_action();
9443
9503
  init_revoke_token_action();
9444
9504
  init_impersonate_action();
9445
- init_providers_action();
9446
9505
  init_login_action();
9447
9506
  init_register_action();
9448
9507
  init_forgot_password_action();
@@ -9478,7 +9537,7 @@ var init_otp_manager = __esm({
9478
9537
  });
9479
9538
 
9480
9539
  // src/modules/auth/auth.service.ts
9481
- import { createHash as createHash4, randomBytes } from "crypto";
9540
+ import { createHash as createHash4, randomBytes as randomBytes2 } from "crypto";
9482
9541
  var REFRESH_TOKENS, AUTH_IDENTITIES, PERSONAL_TOKENS;
9483
9542
  var init_auth_service = __esm({
9484
9543
  "src/modules/auth/auth.service.ts"() {
@@ -9495,38 +9554,38 @@ var init_auth_service = __esm({
9495
9554
  });
9496
9555
 
9497
9556
  // src/modules/auth/auth.types.ts
9498
- import { z as z5 } from "zod";
9557
+ import { z as z6 } from "zod";
9499
9558
  var loginSchema, registerSchema, forgotPasswordSchema, resetPasswordSchema, createPersonalTokenSchema;
9500
9559
  var init_auth_types = __esm({
9501
9560
  "src/modules/auth/auth.types.ts"() {
9502
9561
  "use strict";
9503
- loginSchema = z5.object({
9504
- email: z5.string().email("Invalid email"),
9505
- password: z5.string().min(1, "Password required"),
9506
- otp: z5.string().length(6).optional(),
9507
- deviceId: z5.string().max(64).optional(),
9508
- deviceName: z5.string().max(100).optional()
9562
+ loginSchema = z6.object({
9563
+ email: z6.string().email("Invalid email"),
9564
+ password: z6.string().min(1, "Password required"),
9565
+ otp: z6.string().length(6).optional(),
9566
+ deviceId: z6.string().max(64).optional(),
9567
+ deviceName: z6.string().max(100).optional()
9509
9568
  });
9510
- registerSchema = z5.object({
9511
- email: z5.string().email("Invalid email"),
9512
- password: z5.string().min(8, "Password must be at least 8 characters"),
9513
- name: z5.string().min(2, "Name must be at least 2 characters"),
9514
- otp: z5.string().length(6).optional(),
9515
- deviceId: z5.string().max(64).optional(),
9516
- deviceName: z5.string().max(100).optional()
9569
+ registerSchema = z6.object({
9570
+ email: z6.string().email("Invalid email"),
9571
+ password: z6.string().min(8, "Password must be at least 8 characters"),
9572
+ name: z6.string().min(2, "Name must be at least 2 characters"),
9573
+ otp: z6.string().length(6).optional(),
9574
+ deviceId: z6.string().max(64).optional(),
9575
+ deviceName: z6.string().max(100).optional()
9517
9576
  });
9518
- forgotPasswordSchema = z5.object({
9519
- email: z5.string().email("Invalid email")
9577
+ forgotPasswordSchema = z6.object({
9578
+ email: z6.string().email("Invalid email")
9520
9579
  });
9521
- resetPasswordSchema = z5.object({
9522
- email: z5.string().email("Invalid email"),
9523
- otp: z5.string().length(6, "OTP must be 6 digits"),
9524
- newPassword: z5.string().min(8, "Password must be at least 8 characters")
9580
+ resetPasswordSchema = z6.object({
9581
+ email: z6.string().email("Invalid email"),
9582
+ otp: z6.string().length(6, "OTP must be 6 digits"),
9583
+ newPassword: z6.string().min(8, "Password must be at least 8 characters")
9525
9584
  });
9526
- createPersonalTokenSchema = z5.object({
9527
- name: z5.string().min(1).max(100),
9528
- scope: z5.enum(["readonly", "readwrite"]),
9529
- expires_at: z5.string().datetime().optional()
9585
+ createPersonalTokenSchema = z6.object({
9586
+ name: z6.string().min(1).max(100),
9587
+ scope: z6.enum(["readonly", "readwrite"]),
9588
+ expires_at: z6.string().datetime().optional()
9530
9589
  });
9531
9590
  }
9532
9591
  });
@@ -9546,18 +9605,18 @@ var init_auth = __esm({
9546
9605
  });
9547
9606
 
9548
9607
  // src/modules/mail/mail.config.ts
9549
- import { z as z6 } from "zod";
9608
+ import { z as z7 } from "zod";
9550
9609
  var mailEnvSchema, mailEnv;
9551
9610
  var init_mail_config = __esm({
9552
9611
  "src/modules/mail/mail.config.ts"() {
9553
9612
  "use strict";
9554
- mailEnvSchema = z6.object({
9555
- SMTP_HOST: z6.string().default("localhost"),
9556
- SMTP_PORT: z6.coerce.number().default(1025),
9557
- SMTP_SECURE: z6.string().default("false").transform((v) => v === "true" || v === "1"),
9558
- SMTP_USER: z6.string().optional(),
9559
- SMTP_PASS: z6.string().optional(),
9560
- SMTP_FROM: z6.string().default("noreply@nexus.local")
9613
+ mailEnvSchema = z7.object({
9614
+ SMTP_HOST: z7.string().default("localhost"),
9615
+ SMTP_PORT: z7.coerce.number().default(1025),
9616
+ SMTP_SECURE: z7.string().default("false").transform((v) => v === "true" || v === "1"),
9617
+ SMTP_USER: z7.string().optional(),
9618
+ SMTP_PASS: z7.string().optional(),
9619
+ SMTP_FROM: z7.string().default("noreply@nexus.local")
9561
9620
  });
9562
9621
  mailEnv = mailEnvSchema.parse(process.env);
9563
9622
  }
@@ -9565,7 +9624,7 @@ var init_mail_config = __esm({
9565
9624
 
9566
9625
  // src/modules/mail/mail.service.ts
9567
9626
  import nodemailer from "nodemailer";
9568
- import { join as join7 } from "path";
9627
+ import { join as join9 } from "path";
9569
9628
  function getMailService() {
9570
9629
  if (!mailServiceInstance) {
9571
9630
  throw new Error("MailService not initialized. Call initMailService() first.");
@@ -9577,14 +9636,14 @@ var init_mail_service = __esm({
9577
9636
  "src/modules/mail/mail.service.ts"() {
9578
9637
  "use strict";
9579
9638
  init_mail_config();
9580
- TEMPLATE_REL_PATH = join7("public", "mail", "base.html");
9581
- LOGO_REL_PATH = join7("public", "nexus", "nexus-light-512.png");
9639
+ TEMPLATE_REL_PATH = join9("public", "mail", "base.html");
9640
+ LOGO_REL_PATH = join9("public", "nexus", "nexus-light-512.png");
9582
9641
  mailServiceInstance = null;
9583
9642
  }
9584
9643
  });
9585
9644
 
9586
9645
  // src/modules/mail/mail.entity.ts
9587
- import { useIdField as useIdField7, useTextField as useTextField12, useSelectField as useSelectField13, useNumberField as useNumberField5, useSwitchField as useSwitchField4, useEmailField as useEmailField3, usePasswordField as usePasswordField2, useTextareaField as useTextareaField3, useTagsField as useTagsField2, useDatetimeField as useDatetimeField6 } from "@gzl10/nexus-sdk/fields";
9646
+ import { useIdField as useIdField7, useTextField as useTextField12, useSelectField as useSelectField11, useNumberField as useNumberField6, useSwitchField as useSwitchField3, useEmailField as useEmailField3, usePasswordField as usePasswordField2, useTextareaField as useTextareaField3, useTagsField as useTagsField2, useDatetimeField as useDatetimeField6 } from "@gzl10/nexus-sdk/fields";
9588
9647
  import nodemailer2 from "nodemailer";
9589
9648
  async function getMailConfigFromDB(ctx) {
9590
9649
  const configService = ctx.services["config"];
@@ -9653,12 +9712,12 @@ var init_mail_entity = __esm({
9653
9712
  nullable: false,
9654
9713
  hint: { en: "Default: SMTP_HOST env var", es: "Por defecto: variable SMTP_HOST" }
9655
9714
  }),
9656
- port: useNumberField5({
9715
+ port: useNumberField6({
9657
9716
  label: { en: "Port", es: "Puerto" },
9658
9717
  nullable: false,
9659
9718
  hint: { en: "Default: SMTP_PORT env var", es: "Por defecto: variable SMTP_PORT" }
9660
9719
  }),
9661
- secure: useSwitchField4({
9720
+ secure: useSwitchField3({
9662
9721
  label: { en: "TLS/SSL", es: "TLS/SSL" },
9663
9722
  hint: { en: "Default: SMTP_SECURE env var", es: "Por defecto: variable SMTP_SECURE" }
9664
9723
  }),
@@ -9829,7 +9888,7 @@ var init_mail_entity = __esm({
9829
9888
  meta: { searchable: true, sortable: true }
9830
9889
  }),
9831
9890
  status: {
9832
- ...useSelectField13({
9891
+ ...useSelectField11({
9833
9892
  label: { en: "Status", es: "Estado" },
9834
9893
  options: [
9835
9894
  { value: "pending", label: { en: "Pending", es: "Pendiente" } },
@@ -9853,7 +9912,7 @@ var init_mail_entity = __esm({
9853
9912
  label: { en: "Error", es: "Error" },
9854
9913
  nullable: true
9855
9914
  }),
9856
- sent_by: useSelectField13({
9915
+ sent_by: useSelectField11({
9857
9916
  label: { en: "Sent by", es: "Enviado por" },
9858
9917
  table: "users",
9859
9918
  column: "id",
@@ -9904,7 +9963,7 @@ var init_observability_service = __esm({
9904
9963
  });
9905
9964
 
9906
9965
  // src/modules/observability/observability.config.ts
9907
- import { z as z7 } from "zod";
9966
+ import { z as z8 } from "zod";
9908
9967
  function getOtelConfig() {
9909
9968
  if (cachedConfig) return cachedConfig;
9910
9969
  const env2 = otelEnvSchema.parse(process.env);
@@ -9921,12 +9980,12 @@ var otelEnvSchema, cachedConfig;
9921
9980
  var init_observability_config = __esm({
9922
9981
  "src/modules/observability/observability.config.ts"() {
9923
9982
  "use strict";
9924
- otelEnvSchema = z7.object({
9925
- OTEL_ENABLED: z7.coerce.boolean().default(false),
9926
- OTEL_SERVICE_NAME: z7.string().default("nexus"),
9927
- OTEL_PROMETHEUS_PORT: z7.coerce.number().int().min(0).max(65535).default(9464),
9928
- OTEL_EXPORTER_OTLP_ENDPOINT: z7.string().url().optional(),
9929
- OTEL_TRACE_SAMPLE_RATE: z7.coerce.number().min(0).max(1).default(1)
9983
+ otelEnvSchema = z8.object({
9984
+ OTEL_ENABLED: z8.coerce.boolean().default(false),
9985
+ OTEL_SERVICE_NAME: z8.string().default("nexus"),
9986
+ OTEL_PROMETHEUS_PORT: z8.coerce.number().int().min(0).max(65535).default(9464),
9987
+ OTEL_EXPORTER_OTLP_ENDPOINT: z8.string().url().optional(),
9988
+ OTEL_TRACE_SAMPLE_RATE: z8.coerce.number().min(0).max(1).default(1)
9930
9989
  });
9931
9990
  cachedConfig = null;
9932
9991
  }
@@ -10153,7 +10212,7 @@ var init_toggle_plugin_action = __esm({
10153
10212
  });
10154
10213
 
10155
10214
  // src/modules/plugins/plugins.entity.ts
10156
- import { useTextField as useTextField13, useSelectField as useSelectField14, useCheckboxField as useCheckboxField5 } from "@gzl10/nexus-sdk/fields";
10215
+ import { useTextField as useTextField13, useSelectField as useSelectField12, useCheckboxField as useCheckboxField5 } from "@gzl10/nexus-sdk/fields";
10157
10216
  import { OFFICIAL_PLUGINS } from "@gzl10/nexus-sdk";
10158
10217
  var allowPluginManagement, pluginsEntity;
10159
10218
  var init_plugins_entity = __esm({
@@ -10195,7 +10254,7 @@ var init_plugins_entity = __esm({
10195
10254
  size: 20,
10196
10255
  nullable: false
10197
10256
  }),
10198
- category: useSelectField14({
10257
+ category: useSelectField12({
10199
10258
  label: { en: "Category", es: "Categor\xEDa" },
10200
10259
  options: [
10201
10260
  { value: "content", label: { en: "Content", es: "Contenido" } },
@@ -10274,7 +10333,7 @@ var init_plugins_entity = __esm({
10274
10333
 
10275
10334
  // src/modules/plugins/plugins.routes.ts
10276
10335
  import { Router } from "express";
10277
- import { existsSync as existsSync5 } from "fs";
10336
+ import { existsSync as existsSync6 } from "fs";
10278
10337
  var init_plugins_routes = __esm({
10279
10338
  "src/modules/plugins/plugins.routes.ts"() {
10280
10339
  "use strict";
@@ -10295,7 +10354,7 @@ var init_plugins = __esm({
10295
10354
  import {
10296
10355
  useIdField as useIdField8,
10297
10356
  useTextField as useTextField14,
10298
- useSelectField as useSelectField15,
10357
+ useSelectField as useSelectField13,
10299
10358
  useTextareaField as useTextareaField4,
10300
10359
  useJsonField as useJsonField3,
10301
10360
  useDatetimeField as useDatetimeField7,
@@ -10337,7 +10396,7 @@ var init_audit_entity = __esm({
10337
10396
  }),
10338
10397
  validation: { min: 1, max: 100 }
10339
10398
  },
10340
- actor_id: useSelectField15({
10399
+ actor_id: useSelectField13({
10341
10400
  label: { en: "Actor", es: "Actor" },
10342
10401
  table: "users",
10343
10402
  column: "id",
@@ -10455,91 +10514,6 @@ var init_subject_extractor = __esm({
10455
10514
  }
10456
10515
  });
10457
10516
 
10458
- // src/db/sql-utils.ts
10459
- function extractTableFromSql(sql, type2) {
10460
- const match = sql.match(SQL_PATTERNS[type2]);
10461
- return match?.[1];
10462
- }
10463
- function extractTableFromSelect(sql) {
10464
- return extractTableFromSql(sql, "select");
10465
- }
10466
- function extractTableFromInsert(sql) {
10467
- return extractTableFromSql(sql, "insert");
10468
- }
10469
- function extractTableFromUpdate(sql) {
10470
- return extractTableFromSql(sql, "update");
10471
- }
10472
- function extractTableFromDelete(sql) {
10473
- return extractTableFromSql(sql, "delete");
10474
- }
10475
- var SQL_PATTERNS;
10476
- var init_sql_utils = __esm({
10477
- "src/db/sql-utils.ts"() {
10478
- "use strict";
10479
- SQL_PATTERNS = {
10480
- select: /from\s+["'`]?(\w+)["'`]?/i,
10481
- insert: /insert into\s+["'`]?(\w+)["'`]?/i,
10482
- update: /update\s+["'`]?(\w+)["'`]?/i,
10483
- delete: /delete from\s+["'`]?(\w+)["'`]?/i
10484
- };
10485
- }
10486
- });
10487
-
10488
- // src/db/sqlite-compat.ts
10489
- function createSqliteBooleanProcessor() {
10490
- const booleanColumns = /* @__PURE__ */ new Map();
10491
- function registerBooleanColumn2(table, column) {
10492
- if (!booleanColumns.has(table)) {
10493
- booleanColumns.set(table, /* @__PURE__ */ new Set());
10494
- }
10495
- booleanColumns.get(table).add(column);
10496
- }
10497
- function convertBooleans2(table, row) {
10498
- const columns = booleanColumns.get(table);
10499
- if (!columns || columns.size === 0) return row;
10500
- const result = { ...row };
10501
- for (const column of columns) {
10502
- if (column in result) {
10503
- const value = result[column];
10504
- if (value === 0 || value === 1) {
10505
- result[column] = value === 1;
10506
- }
10507
- }
10508
- }
10509
- return result;
10510
- }
10511
- function postProcess(result, queryContext) {
10512
- const sql = queryContext?.sql?.toLowerCase() ?? "";
10513
- if (!sql.startsWith("select")) return result;
10514
- const table = extractTableFromSelect(sql);
10515
- if (!table) return result;
10516
- if (Array.isArray(result)) {
10517
- return result.map(
10518
- (row) => typeof row === "object" && row !== null ? convertBooleans2(table, row) : row
10519
- );
10520
- }
10521
- if (typeof result === "object" && result !== null) {
10522
- return convertBooleans2(table, result);
10523
- }
10524
- return result;
10525
- }
10526
- function clear() {
10527
- booleanColumns.clear();
10528
- }
10529
- return { registerBooleanColumn: registerBooleanColumn2, convertBooleans: convertBooleans2, postProcess, clear };
10530
- }
10531
- var defaultProcessor, registerBooleanColumn, convertBooleans, sqlitePostProcess;
10532
- var init_sqlite_compat = __esm({
10533
- "src/db/sqlite-compat.ts"() {
10534
- "use strict";
10535
- init_sql_utils();
10536
- defaultProcessor = createSqliteBooleanProcessor();
10537
- registerBooleanColumn = defaultProcessor.registerBooleanColumn;
10538
- convertBooleans = defaultProcessor.convertBooleans;
10539
- sqlitePostProcess = defaultProcessor.postProcess;
10540
- }
10541
- });
10542
-
10543
10517
  // src/runtime/types.ts
10544
10518
  var init_types = __esm({
10545
10519
  "src/runtime/types.ts"() {
@@ -10651,7 +10625,7 @@ var init_external_service = __esm({
10651
10625
  });
10652
10626
 
10653
10627
  // src/runtime/validation/schema-builder.ts
10654
- import { z as z8 } from "zod";
10628
+ import { z as z9 } from "zod";
10655
10629
  var init_schema_builder2 = __esm({
10656
10630
  "src/runtime/validation/schema-builder.ts"() {
10657
10631
  "use strict";
@@ -10755,8 +10729,8 @@ var init_runtime = __esm({
10755
10729
  });
10756
10730
 
10757
10731
  // src/db/seed-runner.ts
10758
- import { existsSync as existsSync6 } from "fs";
10759
- import { join as join8 } from "path";
10732
+ import { existsSync as existsSync7 } from "fs";
10733
+ import { join as join10 } from "path";
10760
10734
  import { pathToFileURL } from "url";
10761
10735
  var init_seed_runner = __esm({
10762
10736
  "src/db/seed-runner.ts"() {
@@ -10791,133 +10765,6 @@ var init_migration_sources = __esm({
10791
10765
  }
10792
10766
  });
10793
10767
 
10794
- // src/config/env.ts
10795
- import { z as z9 } from "zod";
10796
- function resolveConfig() {
10797
- env = envSchema.parse(process.env);
10798
- process.env["TZ"] = env.TZ;
10799
- resolvedConfig = {
10800
- nodeEnv: env.NODE_ENV,
10801
- port: env.PORT,
10802
- host: "0.0.0.0",
10803
- ui: {
10804
- enabled: env.NEXUS_UI_ENABLED,
10805
- base: env.NEXUS_UI_BASE,
10806
- path: env.NEXUS_UI_PATH
10807
- },
10808
- corsOrigin: env.CORS_ORIGIN,
10809
- databaseUrl: env.DATABASE_URL,
10810
- adminEmail: env.ADMIN_EMAIL,
10811
- adminPassword: env.ADMIN_PASSWORD,
10812
- timezone: env.TZ
10813
- };
10814
- return resolvedConfig;
10815
- }
10816
- function getConfig() {
10817
- if (!resolvedConfig) {
10818
- return resolveConfig();
10819
- }
10820
- return resolvedConfig;
10821
- }
10822
- function resetConfig() {
10823
- resolvedConfig = null;
10824
- }
10825
- var envSchema, env, resolvedConfig;
10826
- var init_env = __esm({
10827
- "src/config/env.ts"() {
10828
- "use strict";
10829
- envSchema = z9.object({
10830
- NODE_ENV: z9.enum(["development", "production", "test"]).default("development"),
10831
- PORT: z9.coerce.number().default(3e3),
10832
- CORS_ORIGIN: z9.string().default("*"),
10833
- BACKEND_URL: z9.string().optional(),
10834
- DATABASE_URL: z9.string().default("file:./dev.db"),
10835
- REDIS_URL: z9.string().url().optional(),
10836
- REDIS_PREFIX: z9.string().default("nexus"),
10837
- ADMIN_EMAIL: z9.string().email().optional(),
10838
- ADMIN_PASSWORD: z9.string().min(6).optional(),
10839
- COOKIE_DOMAIN: z9.string().optional(),
10840
- TZ: z9.string().default("UTC"),
10841
- TRUST_PROXY: z9.coerce.boolean().default(false),
10842
- NEXUS_UI_ENABLED: z9.coerce.boolean().default(true),
10843
- NEXUS_UI_BASE: z9.string().default("/"),
10844
- NEXUS_UI_PATH: z9.string().default("../ui/dist"),
10845
- NEXUS_CHECK_DRIFT: z9.coerce.boolean().optional(),
10846
- NEXUS_FAIL_ON_DRIFT: z9.coerce.boolean().optional(),
10847
- FRPC_SERVER: z9.string().optional(),
10848
- FRPC_SERVER_PORT: z9.coerce.number().default(7e3),
10849
- FRPC_TOKEN: z9.string().optional(),
10850
- FRPC_SUBDOMAIN: z9.string().optional()
10851
- });
10852
- env = envSchema.parse(process.env);
10853
- process.env["TZ"] = env.TZ;
10854
- resolvedConfig = null;
10855
- }
10856
- });
10857
-
10858
- // src/config/database.ts
10859
- import { join as join9, dirname as dirname5, isAbsolute as isAbsolute2 } from "path";
10860
- import { mkdirSync as mkdirSync4 } from "fs";
10861
- function getDatabaseConfig() {
10862
- const url = getConfig().databaseUrl;
10863
- if (IN_MEMORY_RE.test(url)) {
10864
- return {
10865
- client: "better-sqlite3",
10866
- connection: { filename: ":memory:" },
10867
- useNullAsDefault: true,
10868
- postProcessResponse: sqlitePostProcess,
10869
- pool: { min: 0, max: 1 }
10870
- };
10871
- }
10872
- if (url.startsWith("file:") || url.startsWith("sqlite:")) {
10873
- let filename = url.replace(/^(file:|sqlite:)/, "");
10874
- if (!isAbsolute2(filename)) {
10875
- filename = join9(getProjectPath(), "data", filename);
10876
- }
10877
- mkdirSync4(dirname5(filename), { recursive: true });
10878
- return {
10879
- client: "better-sqlite3",
10880
- connection: { filename },
10881
- useNullAsDefault: true,
10882
- postProcessResponse: sqlitePostProcess
10883
- };
10884
- }
10885
- if (url.startsWith("postgresql://") || url.startsWith("postgres://")) {
10886
- return {
10887
- client: "pg",
10888
- connection: url,
10889
- pool: { min: 2, max: 10 }
10890
- };
10891
- }
10892
- if (url.startsWith("mysql://")) {
10893
- const offsetMinutes = (/* @__PURE__ */ new Date()).getTimezoneOffset();
10894
- const offsetHours = Math.abs(Math.floor(offsetMinutes / 60));
10895
- const offsetMins = Math.abs(offsetMinutes % 60);
10896
- const sign = offsetMinutes <= 0 ? "+" : "-";
10897
- const tzOffset = `${sign}${String(offsetHours).padStart(2, "0")}:${String(offsetMins).padStart(2, "0")}`;
10898
- return {
10899
- client: "mysql2",
10900
- connection: {
10901
- uri: url,
10902
- timezone: tzOffset
10903
- // mysql2 requiere formato "+HH:MM"
10904
- },
10905
- pool: { min: 2, max: 10 }
10906
- };
10907
- }
10908
- throw new Error(`Unsupported database URL: ${url}`);
10909
- }
10910
- var IN_MEMORY_RE;
10911
- var init_database = __esm({
10912
- "src/config/database.ts"() {
10913
- "use strict";
10914
- init_env();
10915
- init_paths();
10916
- init_sqlite_compat();
10917
- IN_MEMORY_RE = /^((file:|sqlite:)?:memory:?)$/;
10918
- }
10919
- });
10920
-
10921
10768
  // src/db/query-interceptor.ts
10922
10769
  function setupQueryInterceptor(knexInstance) {
10923
10770
  const queryTimings = /* @__PURE__ */ new Map();
@@ -11049,7 +10896,7 @@ var init_migration_helpers = __esm({
11049
10896
  // src/db/migration-generator.ts
11050
10897
  import path2 from "path";
11051
10898
  import fs2 from "fs/promises";
11052
- import { readFileSync as readFileSync3, mkdirSync as mkdirSync5, realpathSync } from "fs";
10899
+ import { readFileSync as readFileSync4, mkdirSync as mkdirSync5, realpathSync } from "fs";
11053
10900
  var init_migration_generator = __esm({
11054
10901
  "src/db/migration-generator.ts"() {
11055
10902
  "use strict";
@@ -11204,6 +11051,13 @@ var init_events_api = __esm({
11204
11051
  }
11205
11052
  });
11206
11053
 
11054
+ // src/engine/capabilities-registry.ts
11055
+ var init_capabilities_registry = __esm({
11056
+ "src/engine/capabilities-registry.ts"() {
11057
+ "use strict";
11058
+ }
11059
+ });
11060
+
11207
11061
  // src/core/cache/lru-cache.ts
11208
11062
  var init_lru_cache = __esm({
11209
11063
  "src/core/cache/lru-cache.ts"() {
@@ -11269,6 +11123,7 @@ var init_context = __esm({
11269
11123
  init_plugin_ops();
11270
11124
  init_load_config();
11271
11125
  init_events_api();
11126
+ init_capabilities_registry();
11272
11127
  init_seed_runner();
11273
11128
  init_cache_manager();
11274
11129
  sharedCacheManager = null;
@@ -11287,6 +11142,7 @@ var init_engine = __esm({
11287
11142
  init_subject_extractor();
11288
11143
  init_definition_extractors();
11289
11144
  init_context();
11145
+ init_capabilities_registry();
11290
11146
  }
11291
11147
  });
11292
11148
 
@@ -11335,6 +11191,7 @@ import jwt3 from "jsonwebtoken";
11335
11191
  var init_jwt = __esm({
11336
11192
  "src/core/jwt/index.ts"() {
11337
11193
  "use strict";
11194
+ init_secret_resolver();
11338
11195
  }
11339
11196
  });
11340
11197
 
@@ -11508,6 +11365,7 @@ var init_socket = __esm({
11508
11365
  "use strict";
11509
11366
  init_emitter();
11510
11367
  init_logger();
11368
+ init_secret_resolver();
11511
11369
  io = null;
11512
11370
  userSockets = /* @__PURE__ */ new Map();
11513
11371
  socketUsers = /* @__PURE__ */ new Map();
@@ -11703,7 +11561,7 @@ var init_port_check = __esm({
11703
11561
  // src/core/tunnel.ts
11704
11562
  import { spawn, execSync } from "child_process";
11705
11563
  import { writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
11706
- import { join as join10 } from "path";
11564
+ import { join as join11 } from "path";
11707
11565
  import { tmpdir } from "os";
11708
11566
  function stopTunnel() {
11709
11567
  if (tunnelProcess) {
@@ -11807,6 +11665,7 @@ async function stop() {
11807
11665
  resetConfigCache();
11808
11666
  clearCustomCaslRules();
11809
11667
  clearSeedPermissions();
11668
+ _resetSecretResolver();
11810
11669
  await resetServeSPA();
11811
11670
  return;
11812
11671
  }
@@ -11842,6 +11701,7 @@ async function stop() {
11842
11701
  resetConfigCache();
11843
11702
  clearCustomCaslRules();
11844
11703
  clearSeedPermissions();
11704
+ _resetSecretResolver();
11845
11705
  await resetServeSPA();
11846
11706
  currentConfig = void 0;
11847
11707
  server = null;
@@ -11902,6 +11762,7 @@ var init_server = __esm({
11902
11762
  init_ensure_system_tables();
11903
11763
  init_load_config();
11904
11764
  init_tunnel();
11765
+ init_secret_resolver();
11905
11766
  server = null;
11906
11767
  gracefulShutdownRegistered = false;
11907
11768
  setupGracefulShutdown();
@@ -11957,10 +11818,11 @@ var init_hash = __esm({
11957
11818
  });
11958
11819
 
11959
11820
  // src/core/crypto/symmetric.ts
11960
- import { createCipheriv, createDecipheriv, randomBytes as randomBytes2, hkdfSync } from "crypto";
11821
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes3, hkdfSync } from "crypto";
11961
11822
  var init_symmetric = __esm({
11962
11823
  "src/core/crypto/symmetric.ts"() {
11963
11824
  "use strict";
11825
+ init_secret_resolver();
11964
11826
  }
11965
11827
  });
11966
11828