@gzl10/nexus-backend 0.19.1 → 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.
- package/claude-commands/nexus-docs.md +2 -2
- package/claude-commands/nexus-update-tutorial-app.md +2 -2
- package/claude-commands/nexus-update-tutorial-plugin.md +1 -1
- package/dist/cli.js +254 -397
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +684 -714
- package/dist/index.js.map +1 -1
- package/dist/main.js +679 -709
- package/dist/main.js.map +1 -1
- package/dist/migration-helpers/index.js +388 -526
- package/dist/migration-helpers/index.js.map +1 -1
- package/dist/testing/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -8709,18 +8709,20 @@ function createSystemController(ctx) {
|
|
|
8709
8709
|
/**
|
|
8710
8710
|
* GET /system/capabilities
|
|
8711
8711
|
* Public endpoint — no authentication required.
|
|
8712
|
-
*
|
|
8712
|
+
* Resolves all registered capabilities (core + plugin-contributed).
|
|
8713
8713
|
*/
|
|
8714
|
-
getCapabilities(_req, res) {
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
8723
|
-
|
|
8714
|
+
async getCapabilities(_req, res) {
|
|
8715
|
+
try {
|
|
8716
|
+
res.set("Cache-Control", "public, max-age=300");
|
|
8717
|
+
const body = await ctx.capabilities.resolve();
|
|
8718
|
+
res.json(body);
|
|
8719
|
+
} catch (err) {
|
|
8720
|
+
ctx.core.logger.error({ err }, "Failed to resolve capabilities");
|
|
8721
|
+
res.set("Cache-Control", "no-cache");
|
|
8722
|
+
res.status(500).json({
|
|
8723
|
+
error: { code: "INTERNAL_ERROR", message: "Failed to resolve capabilities" }
|
|
8724
|
+
});
|
|
8725
|
+
}
|
|
8724
8726
|
}
|
|
8725
8727
|
};
|
|
8726
8728
|
function toManifestDTO(manifest, req) {
|
|
@@ -9293,8 +9295,8 @@ function registerCoreVars(registry2) {
|
|
|
9293
9295
|
registry2.register("auth", "core", [
|
|
9294
9296
|
{
|
|
9295
9297
|
name: "AUTH_SECRET",
|
|
9296
|
-
description: { en: "JWT signing secret. Must be at least 32 characters.
|
|
9297
|
-
required:
|
|
9298
|
+
description: { en: "JWT signing secret (optional). If not set, auto-generated and persisted in database. Must be at least 32 characters. Set explicitly for multi-instance deployments", es: "Clave de firma JWT (opcional). Si no se establece, se genera autom\xE1ticamente y se persiste en la base de datos. M\xEDnimo 32 caracteres. Establecer expl\xEDcitamente para despliegues multi-instancia" },
|
|
9299
|
+
required: false,
|
|
9298
9300
|
sensitive: true
|
|
9299
9301
|
},
|
|
9300
9302
|
{
|
|
@@ -9811,96 +9813,70 @@ var init_system = __esm({
|
|
|
9811
9813
|
}
|
|
9812
9814
|
});
|
|
9813
9815
|
|
|
9814
|
-
// src/modules/ui-settings/ui-
|
|
9815
|
-
import { useTextField as useTextField7, useImageField } from "@gzl10/nexus-sdk/fields";
|
|
9816
|
-
var
|
|
9817
|
-
var
|
|
9818
|
-
"src/modules/ui-settings/ui-
|
|
9816
|
+
// src/modules/ui-settings/ui-style-guide.entity.ts
|
|
9817
|
+
import { useTextField as useTextField7, useImageField, useSelectField as useSelectField6, useColorField, useNumberField as useNumberField4, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
|
|
9818
|
+
var uiStyleGuideEntity;
|
|
9819
|
+
var init_ui_style_guide_entity = __esm({
|
|
9820
|
+
"src/modules/ui-settings/ui-style-guide.entity.ts"() {
|
|
9819
9821
|
"use strict";
|
|
9820
|
-
|
|
9822
|
+
uiStyleGuideEntity = {
|
|
9821
9823
|
type: "single",
|
|
9822
9824
|
realtime: "sync",
|
|
9823
|
-
key: "
|
|
9824
|
-
label: { en: "
|
|
9825
|
-
icon: "mdi:palette-
|
|
9825
|
+
key: "ui_style_guide",
|
|
9826
|
+
label: { en: "Style Guide", es: "Gu\xEDa de Estilos" },
|
|
9827
|
+
icon: "mdi:palette-outline",
|
|
9826
9828
|
public: true,
|
|
9827
|
-
routePrefix: "/ui-
|
|
9829
|
+
routePrefix: "/ui-style-guide",
|
|
9828
9830
|
defaults: {
|
|
9829
9831
|
appName: "Nexus",
|
|
9830
9832
|
logo: null,
|
|
9831
9833
|
logoDark: null,
|
|
9832
|
-
favicon: null
|
|
9834
|
+
favicon: null,
|
|
9835
|
+
primaryColor: "#3B82F6",
|
|
9836
|
+
font: "space-grotesk",
|
|
9837
|
+
typographyScale: "default",
|
|
9838
|
+
borderRadius: 8,
|
|
9839
|
+
glassEffect: true,
|
|
9840
|
+
theme: "system",
|
|
9841
|
+
loginLayout: "centered"
|
|
9833
9842
|
},
|
|
9834
9843
|
fields: {
|
|
9835
9844
|
appName: useTextField7({
|
|
9836
9845
|
label: { en: "App Name", es: "Nombre de la App" },
|
|
9837
|
-
hint: { en: "Displayed in
|
|
9846
|
+
hint: { en: "Displayed in header, browser tab and emails", es: "Se muestra en header, pesta\xF1a del navegador y emails" },
|
|
9838
9847
|
size: 100,
|
|
9839
9848
|
required: true
|
|
9840
9849
|
}),
|
|
9841
9850
|
logo: useImageField({
|
|
9842
9851
|
label: { en: "Logo (Light Theme)", es: "Logo (Tema Claro)" },
|
|
9843
|
-
hint: { en: "
|
|
9852
|
+
hint: { en: "SVG or PNG with transparent background, max 200px height", es: "SVG o PNG con fondo transparente, m\xE1x 200px de alto" },
|
|
9844
9853
|
folder: "branding",
|
|
9845
9854
|
isPublic: true,
|
|
9846
9855
|
dedupe: true
|
|
9847
9856
|
}),
|
|
9848
9857
|
logoDark: useImageField({
|
|
9849
9858
|
label: { en: "Logo (Dark Theme)", es: "Logo (Tema Oscuro)" },
|
|
9850
|
-
hint: { en: "
|
|
9859
|
+
hint: { en: "Lighter version for dark backgrounds", es: "Versi\xF3n m\xE1s clara para fondos oscuros" },
|
|
9851
9860
|
folder: "branding",
|
|
9852
9861
|
isPublic: true,
|
|
9853
9862
|
dedupe: true
|
|
9854
9863
|
}),
|
|
9855
9864
|
favicon: useImageField({
|
|
9856
9865
|
label: { en: "Favicon", es: "Favicon" },
|
|
9857
|
-
hint: { en: "
|
|
9866
|
+
hint: { en: "32x32 or 64x64 PNG/ICO", es: "32x32 o 64x64 PNG/ICO" },
|
|
9858
9867
|
accept: "image/x-icon,image/png,image/svg+xml",
|
|
9859
9868
|
maxSize: "256KB",
|
|
9860
9869
|
folder: "branding",
|
|
9861
9870
|
isPublic: true,
|
|
9862
9871
|
dedupe: true
|
|
9863
|
-
})
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
ADMIN: { actions: ["read", "update"] }
|
|
9869
|
-
}
|
|
9870
|
-
}
|
|
9871
|
-
};
|
|
9872
|
-
}
|
|
9873
|
-
});
|
|
9874
|
-
|
|
9875
|
-
// src/modules/ui-settings/ui-theme.entity.ts
|
|
9876
|
-
import { useSelectField as useSelectField6, useColorField } from "@gzl10/nexus-sdk/fields";
|
|
9877
|
-
var uiThemeEntity;
|
|
9878
|
-
var init_ui_theme_entity = __esm({
|
|
9879
|
-
"src/modules/ui-settings/ui-theme.entity.ts"() {
|
|
9880
|
-
"use strict";
|
|
9881
|
-
uiThemeEntity = {
|
|
9882
|
-
type: "single",
|
|
9883
|
-
realtime: "sync",
|
|
9884
|
-
key: "ui_theme",
|
|
9885
|
-
label: { en: "Theme & Colors", es: "Tema y Colores" },
|
|
9886
|
-
icon: "mdi:palette",
|
|
9887
|
-
public: true,
|
|
9888
|
-
routePrefix: "/ui-theme",
|
|
9889
|
-
defaults: {
|
|
9890
|
-
// Typography
|
|
9891
|
-
font: "space-grotesk",
|
|
9892
|
-
// Theme & Colors
|
|
9893
|
-
theme: "system",
|
|
9894
|
-
primaryColor: "#3B82F6",
|
|
9895
|
-
dopamineTheme: "none",
|
|
9896
|
-
// Layout
|
|
9897
|
-
loginLayout: "centered"
|
|
9898
|
-
},
|
|
9899
|
-
fields: {
|
|
9900
|
-
// === Typography ===
|
|
9872
|
+
}),
|
|
9873
|
+
primaryColor: useColorField({
|
|
9874
|
+
label: { en: "Primary Color", es: "Color Principal" },
|
|
9875
|
+
hint: { en: "Accent color for buttons, links and highlights", es: "Color de acento para botones, enlaces y resaltados" }
|
|
9876
|
+
}),
|
|
9901
9877
|
font: useSelectField6({
|
|
9902
9878
|
label: { en: "Font", es: "Fuente" },
|
|
9903
|
-
hint: { en: "Primary font for headings and UI
|
|
9879
|
+
hint: { en: "Primary font for headings and UI", es: "Fuente principal para t\xEDtulos e interfaz" },
|
|
9904
9880
|
options: [
|
|
9905
9881
|
{ value: "space-grotesk", label: "Space Grotesk" },
|
|
9906
9882
|
{ value: "inter", label: "Inter" },
|
|
@@ -9910,37 +9886,38 @@ var init_ui_theme_entity = __esm({
|
|
|
9910
9886
|
{ value: "system", label: { en: "System Default", es: "Sistema" } }
|
|
9911
9887
|
]
|
|
9912
9888
|
}),
|
|
9913
|
-
|
|
9889
|
+
typographyScale: useSelectField6({
|
|
9890
|
+
label: { en: "Typography Scale", es: "Escala Tipogr\xE1fica" },
|
|
9891
|
+
hint: { en: "Font size scaling (WCAG 1.4.4)", es: "Escala de tama\xF1os de fuente (WCAG 1.4.4)" },
|
|
9892
|
+
options: [
|
|
9893
|
+
{ value: "compact", label: { en: "Compact", es: "Compacta" } },
|
|
9894
|
+
{ value: "default", label: { en: "Default", es: "Por defecto" } },
|
|
9895
|
+
{ value: "relaxed", label: { en: "Relaxed", es: "Relajada" } }
|
|
9896
|
+
]
|
|
9897
|
+
}),
|
|
9898
|
+
borderRadius: useNumberField4({
|
|
9899
|
+
label: { en: "Border Radius", es: "Radio de Bordes" },
|
|
9900
|
+
hint: { en: "Corner roundness in pixels (0 = sharp, 16 = very round)", es: "Redondeo de esquinas en p\xEDxeles (0 = cuadrado, 16 = muy redondo)" },
|
|
9901
|
+
defaultValue: 8,
|
|
9902
|
+
validation: { min: 0, max: 16 }
|
|
9903
|
+
}),
|
|
9904
|
+
glassEffect: useSwitchField2({
|
|
9905
|
+
label: { en: "Glass Effect", es: "Efecto Glass" },
|
|
9906
|
+
hint: { en: "Glassmorphism blur on cards and modals", es: "Desenfoque glassmorphism en cards y modales" },
|
|
9907
|
+
defaultValue: true
|
|
9908
|
+
}),
|
|
9914
9909
|
theme: useSelectField6({
|
|
9915
9910
|
label: { en: "Theme", es: "Tema" },
|
|
9916
|
-
hint: { en: "System follows
|
|
9911
|
+
hint: { en: "System follows device preferences", es: "Sistema sigue las preferencias del dispositivo" },
|
|
9917
9912
|
options: [
|
|
9918
9913
|
{ value: "light", label: { en: "Light", es: "Claro" } },
|
|
9919
9914
|
{ value: "dark", label: { en: "Dark", es: "Oscuro" } },
|
|
9920
9915
|
{ value: "system", label: { en: "System", es: "Sistema" } }
|
|
9921
9916
|
]
|
|
9922
9917
|
}),
|
|
9923
|
-
dopamineTheme: useSelectField6({
|
|
9924
|
-
label: { en: "Dopamine Theme", es: "Tema Dopamina" },
|
|
9925
|
-
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)" },
|
|
9926
|
-
options: [
|
|
9927
|
-
{ value: "none", label: { en: "None (Custom Color)", es: "Ninguno (Color personalizado)" } },
|
|
9928
|
-
{ value: "electric", label: { en: "Electric (Cobalt Blue)", es: "El\xE9ctrico (Azul Cobalto)" } },
|
|
9929
|
-
{ value: "sunset", label: { en: "Sunset (Coral Red)", es: "Atardecer (Rojo Coral)" } },
|
|
9930
|
-
{ value: "ocean", label: { en: "Ocean (Teal)", es: "Oc\xE9ano (Verde Azulado)" } },
|
|
9931
|
-
{ value: "forest", label: { en: "Forest (Mint)", es: "Bosque (Menta)" } },
|
|
9932
|
-
{ value: "lavender", label: { en: "Lavender (Violet)", es: "Lavanda (Violeta)" } },
|
|
9933
|
-
{ value: "cherry", label: { en: "Cherry (Fuchsia)", es: "Cereza (Fucsia)" } },
|
|
9934
|
-
{ value: "amber", label: { en: "Amber (Golden)", es: "\xC1mbar (Dorado)" } },
|
|
9935
|
-
{ value: "tangerine", label: { en: "Tangerine (Orange)", es: "Mandarina (Naranja)" } },
|
|
9936
|
-
{ value: "slate", label: { en: "Slate (Cool Gray)", es: "Pizarra (Gris Fr\xEDo)" } },
|
|
9937
|
-
{ value: "bronze", label: { en: "Bronze (Earth)", es: "Bronce (Tierra)" } }
|
|
9938
|
-
]
|
|
9939
|
-
}),
|
|
9940
|
-
// === Login Layout ===
|
|
9941
9918
|
loginLayout: useSelectField6({
|
|
9942
9919
|
label: { en: "Login Layout", es: "Dise\xF1o de Login" },
|
|
9943
|
-
hint: { en: "
|
|
9920
|
+
hint: { en: "Auth page visual layout", es: "Dise\xF1o visual de p\xE1ginas de autenticaci\xF3n" },
|
|
9944
9921
|
options: [
|
|
9945
9922
|
{ value: "centered", label: { en: "Centered", es: "Centrado" } },
|
|
9946
9923
|
{ value: "split", label: { en: "Split", es: "Dividido" } },
|
|
@@ -9948,140 +9925,10 @@ var init_ui_theme_entity = __esm({
|
|
|
9948
9925
|
{ value: "floating", label: { en: "Floating", es: "Flotante" } },
|
|
9949
9926
|
{ value: "minimal", label: { en: "Minimal", es: "Minimalista" } }
|
|
9950
9927
|
]
|
|
9951
|
-
}),
|
|
9952
|
-
primaryColor: {
|
|
9953
|
-
...useColorField({
|
|
9954
|
-
label: { en: "Primary Color", es: "Color Principal" },
|
|
9955
|
-
hint: { en: "Custom accent color for buttons, links and highlights", es: "Color de acento personalizado para botones, enlaces y resaltados" }
|
|
9956
|
-
}),
|
|
9957
|
-
// Hide when a dopamine theme is active (show only if 'none')
|
|
9958
|
-
hidden: { field: "dopamineTheme", $ne: "none" }
|
|
9959
|
-
}
|
|
9960
|
-
},
|
|
9961
|
-
casl: {
|
|
9962
|
-
subject: "UiTheme",
|
|
9963
|
-
permissions: {
|
|
9964
|
-
ADMIN: { actions: ["read", "update"] }
|
|
9965
|
-
}
|
|
9966
|
-
}
|
|
9967
|
-
};
|
|
9968
|
-
}
|
|
9969
|
-
});
|
|
9970
|
-
|
|
9971
|
-
// src/modules/ui-settings/ui-effects.entity.ts
|
|
9972
|
-
import { useSelectField as useSelectField7, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
|
|
9973
|
-
var uiEffectsEntity;
|
|
9974
|
-
var init_ui_effects_entity = __esm({
|
|
9975
|
-
"src/modules/ui-settings/ui-effects.entity.ts"() {
|
|
9976
|
-
"use strict";
|
|
9977
|
-
uiEffectsEntity = {
|
|
9978
|
-
type: "single",
|
|
9979
|
-
realtime: "sync",
|
|
9980
|
-
key: "ui_effects",
|
|
9981
|
-
label: { en: "Visual Effects", es: "Efectos Visuales" },
|
|
9982
|
-
icon: "mdi:shimmer",
|
|
9983
|
-
public: true,
|
|
9984
|
-
routePrefix: "/ui-effects",
|
|
9985
|
-
defaults: {
|
|
9986
|
-
glassIntensity: "medium",
|
|
9987
|
-
borderStyle: "rounded",
|
|
9988
|
-
enableAnimations: true,
|
|
9989
|
-
enableOrganicShapes: false
|
|
9990
|
-
},
|
|
9991
|
-
fields: {
|
|
9992
|
-
glassIntensity: useSelectField7({
|
|
9993
|
-
label: { en: "Glass Intensity", es: "Intensidad Glass" },
|
|
9994
|
-
hint: { en: "Glassmorphism blur effect on cards and modals", es: "Efecto de desenfoque glassmorphism en cards y modales" },
|
|
9995
|
-
options: [
|
|
9996
|
-
{ value: "none", label: { en: "None", es: "Ninguno" } },
|
|
9997
|
-
{ value: "low", label: { en: "Low", es: "Baja" } },
|
|
9998
|
-
{ value: "medium", label: { en: "Medium", es: "Media" } },
|
|
9999
|
-
{ value: "high", label: { en: "High", es: "Alta" } }
|
|
10000
|
-
]
|
|
10001
|
-
}),
|
|
10002
|
-
borderStyle: useSelectField7({
|
|
10003
|
-
label: { en: "Border Style", es: "Estilo de Bordes" },
|
|
10004
|
-
hint: { en: "Corner radius for buttons, cards and inputs", es: "Radio de esquinas para botones, cards e inputs" },
|
|
10005
|
-
options: [
|
|
10006
|
-
{ value: "sharp", label: { en: "Sharp", es: "Cuadrados" } },
|
|
10007
|
-
{ value: "rounded", label: { en: "Rounded", es: "Redondeados" } },
|
|
10008
|
-
{ value: "organic", label: { en: "Organic", es: "Org\xE1nicos" } }
|
|
10009
|
-
]
|
|
10010
|
-
}),
|
|
10011
|
-
enableAnimations: useSwitchField2({
|
|
10012
|
-
label: { en: "Enable Animations", es: "Habilitar Animaciones" },
|
|
10013
|
-
hint: { en: "Micro-interactions and transitions (hover, focus, page changes)", es: "Micro-interacciones y transiciones (hover, focus, cambios de p\xE1gina)" },
|
|
10014
|
-
defaultValue: true,
|
|
10015
|
-
meta: { sortable: true }
|
|
10016
|
-
}),
|
|
10017
|
-
enableOrganicShapes: useSwitchField2({
|
|
10018
|
-
label: { en: "Enable Organic Shapes", es: "Habilitar Formas Org\xE1nicas" },
|
|
10019
|
-
hint: { en: "Asymmetric border-radius for a more natural, playful look", es: "Border-radius asim\xE9trico para un aspecto m\xE1s natural y divertido" },
|
|
10020
|
-
defaultValue: false,
|
|
10021
|
-
meta: { sortable: true },
|
|
10022
|
-
hidden: { field: "borderStyle", $ne: "organic" }
|
|
10023
|
-
})
|
|
10024
|
-
},
|
|
10025
|
-
casl: {
|
|
10026
|
-
subject: "UiEffects",
|
|
10027
|
-
permissions: {
|
|
10028
|
-
ADMIN: { actions: ["read", "update"] }
|
|
10029
|
-
}
|
|
10030
|
-
}
|
|
10031
|
-
};
|
|
10032
|
-
}
|
|
10033
|
-
});
|
|
10034
|
-
|
|
10035
|
-
// src/modules/ui-settings/ui-accessibility.entity.ts
|
|
10036
|
-
import { useSelectField as useSelectField8, useSwitchField as useSwitchField3 } from "@gzl10/nexus-sdk/fields";
|
|
10037
|
-
var uiAccessibilityEntity;
|
|
10038
|
-
var init_ui_accessibility_entity = __esm({
|
|
10039
|
-
"src/modules/ui-settings/ui-accessibility.entity.ts"() {
|
|
10040
|
-
"use strict";
|
|
10041
|
-
uiAccessibilityEntity = {
|
|
10042
|
-
type: "single",
|
|
10043
|
-
realtime: "sync",
|
|
10044
|
-
key: "ui_accessibility",
|
|
10045
|
-
label: { en: "Accessibility", es: "Accesibilidad" },
|
|
10046
|
-
icon: "mdi:human",
|
|
10047
|
-
public: true,
|
|
10048
|
-
routePrefix: "/ui-accessibility",
|
|
10049
|
-
defaults: {
|
|
10050
|
-
typographyScale: "default",
|
|
10051
|
-
reducedMotion: false,
|
|
10052
|
-
highContrast: false
|
|
10053
|
-
},
|
|
10054
|
-
fields: {
|
|
10055
|
-
typographyScale: useSelectField8({
|
|
10056
|
-
label: { en: "Typography Scale", es: "Escala Tipogr\xE1fica" },
|
|
10057
|
-
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)" },
|
|
10058
|
-
options: [
|
|
10059
|
-
{ value: "compact", label: { en: "Compact (smaller)", es: "Compacta (m\xE1s peque\xF1a)" } },
|
|
10060
|
-
{ value: "default", label: { en: "Default", es: "Por defecto" } },
|
|
10061
|
-
{ value: "relaxed", label: { en: "Relaxed (larger)", es: "Relajada (m\xE1s grande)" } }
|
|
10062
|
-
]
|
|
10063
|
-
}),
|
|
10064
|
-
reducedMotion: useSwitchField3({
|
|
10065
|
-
label: { en: "Reduced Motion", es: "Movimiento Reducido" },
|
|
10066
|
-
defaultValue: false,
|
|
10067
|
-
meta: { sortable: true },
|
|
10068
|
-
hint: {
|
|
10069
|
-
en: "Minimizes animations for users sensitive to motion (WCAG 2.1)",
|
|
10070
|
-
es: "Minimiza animaciones para usuarios sensibles al movimiento (WCAG 2.1)"
|
|
10071
|
-
}
|
|
10072
|
-
}),
|
|
10073
|
-
highContrast: useSwitchField3({
|
|
10074
|
-
label: { en: "High Contrast", es: "Alto Contraste" },
|
|
10075
|
-
defaultValue: false,
|
|
10076
|
-
meta: { sortable: true },
|
|
10077
|
-
hint: {
|
|
10078
|
-
en: "Increases text contrast for better readability (WCAG AAA)",
|
|
10079
|
-
es: "Aumenta el contraste del texto para mejor legibilidad (WCAG AAA)"
|
|
10080
|
-
}
|
|
10081
9928
|
})
|
|
10082
9929
|
},
|
|
10083
9930
|
casl: {
|
|
10084
|
-
subject: "
|
|
9931
|
+
subject: "UiStyleGuide",
|
|
10085
9932
|
permissions: {
|
|
10086
9933
|
ADMIN: { actions: ["read", "update"] }
|
|
10087
9934
|
}
|
|
@@ -10091,44 +9938,62 @@ var init_ui_accessibility_entity = __esm({
|
|
|
10091
9938
|
});
|
|
10092
9939
|
|
|
10093
9940
|
// src/modules/ui-settings/index.ts
|
|
9941
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
9942
|
+
import { join as join9 } from "path";
|
|
10094
9943
|
var uiSettingsModule;
|
|
10095
9944
|
var init_ui_settings = __esm({
|
|
10096
9945
|
"src/modules/ui-settings/index.ts"() {
|
|
10097
9946
|
"use strict";
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
init_ui_effects_entity();
|
|
10101
|
-
init_ui_accessibility_entity();
|
|
10102
|
-
init_ui_branding_entity();
|
|
10103
|
-
init_ui_theme_entity();
|
|
10104
|
-
init_ui_effects_entity();
|
|
10105
|
-
init_ui_accessibility_entity();
|
|
9947
|
+
init_ui_style_guide_entity();
|
|
9948
|
+
init_ui_style_guide_entity();
|
|
10106
9949
|
uiSettingsModule = {
|
|
10107
9950
|
name: "ui-settings",
|
|
10108
|
-
label: { en: "
|
|
9951
|
+
label: { en: "Style Guide", es: "Gu\xEDa de Estilos" },
|
|
10109
9952
|
icon: "mdi:palette-outline",
|
|
10110
9953
|
description: {
|
|
10111
|
-
en: "
|
|
10112
|
-
es: "Configuraci\xF3n de
|
|
9954
|
+
en: "Brand identity and visual style configuration",
|
|
9955
|
+
es: "Configuraci\xF3n de identidad de marca y estilo visual"
|
|
10113
9956
|
},
|
|
10114
9957
|
type: "core",
|
|
10115
9958
|
category: "settings",
|
|
10116
9959
|
dependencies: ["logger"],
|
|
10117
|
-
definitions: [
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
9960
|
+
definitions: [uiStyleGuideEntity],
|
|
9961
|
+
routePrefix: "/ui-settings",
|
|
9962
|
+
/**
|
|
9963
|
+
* Seed style guide from data/seeds/ui-style-guide.json if it exists.
|
|
9964
|
+
* Idempotent: only inserts if no record exists yet.
|
|
9965
|
+
*
|
|
9966
|
+
* Workflow:
|
|
9967
|
+
* 1. Configure style guide in dev via admin UI
|
|
9968
|
+
* 2. Export: GET /api/v1/ui-settings/ui-style-guide → save to data/seeds/ui-style-guide.json
|
|
9969
|
+
* 3. Commit the seed file
|
|
9970
|
+
* 4. On other environments, seed runs automatically on startup
|
|
9971
|
+
*/
|
|
9972
|
+
seed: async (ctx) => {
|
|
9973
|
+
const db3 = ctx.db.knex;
|
|
9974
|
+
const existing = await db3("single_records").where("key", "ui_style_guide").first();
|
|
9975
|
+
if (existing) return;
|
|
9976
|
+
const seedPath = join9(process.cwd(), "data", "seeds", "ui-style-guide.json");
|
|
9977
|
+
if (!existsSync6(seedPath)) return;
|
|
9978
|
+
try {
|
|
9979
|
+
const seedData = JSON.parse(readFileSync6(seedPath, "utf-8"));
|
|
9980
|
+
await db3("single_records").insert({
|
|
9981
|
+
key: "ui_style_guide",
|
|
9982
|
+
value: JSON.stringify(seedData)
|
|
9983
|
+
});
|
|
9984
|
+
ctx.core.logger.info("Seeded ui_style_guide from data/seeds/ui-style-guide.json");
|
|
9985
|
+
} catch {
|
|
9986
|
+
ctx.core.logger.warn("Failed to parse data/seeds/ui-style-guide.json, skipping seed");
|
|
9987
|
+
}
|
|
9988
|
+
}
|
|
10124
9989
|
};
|
|
10125
9990
|
}
|
|
10126
9991
|
});
|
|
10127
9992
|
|
|
10128
9993
|
// src/modules/storage/drivers/filesystem.driver.ts
|
|
10129
|
-
import { createReadStream, createWriteStream, existsSync as
|
|
9994
|
+
import { createReadStream, createWriteStream, existsSync as existsSync7, unlinkSync, mkdirSync as mkdirSync3 } from "fs";
|
|
10130
9995
|
import { readFile, readdir, stat, copyFile, rename, mkdir } from "fs/promises";
|
|
10131
|
-
import { join as
|
|
9996
|
+
import { join as join10, dirname as dirname6, extname, basename } from "path";
|
|
10132
9997
|
import { createHash } from "crypto";
|
|
10133
9998
|
var FilesystemDriver;
|
|
10134
9999
|
var init_filesystem_driver = __esm({
|
|
@@ -10142,7 +10007,7 @@ var init_filesystem_driver = __esm({
|
|
|
10142
10007
|
this.basePath = config3.basePath;
|
|
10143
10008
|
this.baseUrl = config3.baseUrl;
|
|
10144
10009
|
this.generateId = config3.generateId;
|
|
10145
|
-
if (!
|
|
10010
|
+
if (!existsSync7(this.basePath)) {
|
|
10146
10011
|
mkdirSync3(this.basePath, { recursive: true });
|
|
10147
10012
|
}
|
|
10148
10013
|
}
|
|
@@ -10152,9 +10017,9 @@ var init_filesystem_driver = __esm({
|
|
|
10152
10017
|
const diskFilename = `${id}${ext}`;
|
|
10153
10018
|
const folder = options?.folder || "";
|
|
10154
10019
|
const relativePath = folder ? `${folder}/${diskFilename}` : diskFilename;
|
|
10155
|
-
const fullPath =
|
|
10020
|
+
const fullPath = join10(this.basePath, relativePath);
|
|
10156
10021
|
const dir = dirname6(fullPath);
|
|
10157
|
-
if (!
|
|
10022
|
+
if (!existsSync7(dir)) {
|
|
10158
10023
|
mkdirSync3(dir, { recursive: true });
|
|
10159
10024
|
}
|
|
10160
10025
|
const hash = createHash("sha256").update(buffer).digest("hex");
|
|
@@ -10178,25 +10043,25 @@ var init_filesystem_driver = __esm({
|
|
|
10178
10043
|
};
|
|
10179
10044
|
}
|
|
10180
10045
|
async get(path3) {
|
|
10181
|
-
const fullPath =
|
|
10182
|
-
if (!
|
|
10046
|
+
const fullPath = join10(this.basePath, path3);
|
|
10047
|
+
if (!existsSync7(fullPath)) {
|
|
10183
10048
|
throw new Error(`File not found: ${path3}`);
|
|
10184
10049
|
}
|
|
10185
10050
|
return createReadStream(fullPath);
|
|
10186
10051
|
}
|
|
10187
10052
|
async getBuffer(path3) {
|
|
10188
|
-
const fullPath =
|
|
10053
|
+
const fullPath = join10(this.basePath, path3);
|
|
10189
10054
|
return readFile(fullPath);
|
|
10190
10055
|
}
|
|
10191
10056
|
async delete(path3) {
|
|
10192
|
-
const fullPath =
|
|
10193
|
-
if (
|
|
10057
|
+
const fullPath = join10(this.basePath, path3);
|
|
10058
|
+
if (existsSync7(fullPath)) {
|
|
10194
10059
|
unlinkSync(fullPath);
|
|
10195
10060
|
}
|
|
10196
10061
|
}
|
|
10197
10062
|
async exists(path3) {
|
|
10198
|
-
const fullPath =
|
|
10199
|
-
return
|
|
10063
|
+
const fullPath = join10(this.basePath, path3);
|
|
10064
|
+
return existsSync7(fullPath);
|
|
10200
10065
|
}
|
|
10201
10066
|
getUrl(path3) {
|
|
10202
10067
|
if (!this.baseUrl) return null;
|
|
@@ -10206,14 +10071,14 @@ var init_filesystem_driver = __esm({
|
|
|
10206
10071
|
// EXTENDED METHODS
|
|
10207
10072
|
// ============================================================================
|
|
10208
10073
|
async list(folder) {
|
|
10209
|
-
const targetPath = folder ?
|
|
10210
|
-
if (!
|
|
10074
|
+
const targetPath = folder ? join10(this.basePath, folder) : this.basePath;
|
|
10075
|
+
if (!existsSync7(targetPath)) {
|
|
10211
10076
|
return [];
|
|
10212
10077
|
}
|
|
10213
10078
|
const entries = await readdir(targetPath, { withFileTypes: true });
|
|
10214
10079
|
const results = [];
|
|
10215
10080
|
for (const entry of entries) {
|
|
10216
|
-
const entryPath =
|
|
10081
|
+
const entryPath = join10(targetPath, entry.name);
|
|
10217
10082
|
const relativePath = folder ? `${folder}/${entry.name}` : entry.name;
|
|
10218
10083
|
const stats = await stat(entryPath);
|
|
10219
10084
|
results.push({
|
|
@@ -10227,10 +10092,10 @@ var init_filesystem_driver = __esm({
|
|
|
10227
10092
|
return results;
|
|
10228
10093
|
}
|
|
10229
10094
|
async copy(src, dst) {
|
|
10230
|
-
const srcPath =
|
|
10231
|
-
const dstPath =
|
|
10095
|
+
const srcPath = join10(this.basePath, src);
|
|
10096
|
+
const dstPath = join10(this.basePath, dst);
|
|
10232
10097
|
const dstDir = dirname6(dstPath);
|
|
10233
|
-
if (!
|
|
10098
|
+
if (!existsSync7(dstDir)) {
|
|
10234
10099
|
await mkdir(dstDir, { recursive: true });
|
|
10235
10100
|
}
|
|
10236
10101
|
await copyFile(srcPath, dstPath);
|
|
@@ -10253,10 +10118,10 @@ var init_filesystem_driver = __esm({
|
|
|
10253
10118
|
};
|
|
10254
10119
|
}
|
|
10255
10120
|
async move(src, dst) {
|
|
10256
|
-
const srcPath =
|
|
10257
|
-
const dstPath =
|
|
10121
|
+
const srcPath = join10(this.basePath, src);
|
|
10122
|
+
const dstPath = join10(this.basePath, dst);
|
|
10258
10123
|
const dstDir = dirname6(dstPath);
|
|
10259
|
-
if (!
|
|
10124
|
+
if (!existsSync7(dstDir)) {
|
|
10260
10125
|
await mkdir(dstDir, { recursive: true });
|
|
10261
10126
|
}
|
|
10262
10127
|
await rename(srcPath, dstPath);
|
|
@@ -10279,7 +10144,7 @@ var init_filesystem_driver = __esm({
|
|
|
10279
10144
|
};
|
|
10280
10145
|
}
|
|
10281
10146
|
async getMetadata(path3) {
|
|
10282
|
-
const fullPath =
|
|
10147
|
+
const fullPath = join10(this.basePath, path3);
|
|
10283
10148
|
const stats = await stat(fullPath);
|
|
10284
10149
|
return {
|
|
10285
10150
|
path: path3,
|
|
@@ -10293,8 +10158,8 @@ var init_filesystem_driver = __esm({
|
|
|
10293
10158
|
throw new Error("Signed URLs are not supported by the filesystem driver");
|
|
10294
10159
|
}
|
|
10295
10160
|
async createFolder(path3) {
|
|
10296
|
-
const fullPath =
|
|
10297
|
-
if (!
|
|
10161
|
+
const fullPath = join10(this.basePath, path3);
|
|
10162
|
+
if (!existsSync7(fullPath)) {
|
|
10298
10163
|
await mkdir(fullPath, { recursive: true });
|
|
10299
10164
|
}
|
|
10300
10165
|
}
|
|
@@ -10525,8 +10390,8 @@ var init_s3_driver = __esm({
|
|
|
10525
10390
|
});
|
|
10526
10391
|
|
|
10527
10392
|
// src/modules/storage/storage.config.ts
|
|
10528
|
-
import { join as
|
|
10529
|
-
import { existsSync as
|
|
10393
|
+
import { join as join11, isAbsolute as isAbsolute2 } from "path";
|
|
10394
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
10530
10395
|
function getDefaultScope(driver) {
|
|
10531
10396
|
return driver === "s3" ? DEFAULT_S3_SCOPE : DEFAULT_FILESYSTEM_SCOPE;
|
|
10532
10397
|
}
|
|
@@ -10541,7 +10406,7 @@ function resolveStoragePath(path3, projPath) {
|
|
|
10541
10406
|
return path3;
|
|
10542
10407
|
}
|
|
10543
10408
|
const cleanPath = path3.startsWith("./") ? path3.slice(2) : path3;
|
|
10544
|
-
return
|
|
10409
|
+
return join11(projPath, "data", cleanPath);
|
|
10545
10410
|
}
|
|
10546
10411
|
async function getConfigByScope(db3, scope) {
|
|
10547
10412
|
if (!generateIdFn) {
|
|
@@ -10572,7 +10437,7 @@ function buildConfigFromRow(row) {
|
|
|
10572
10437
|
if (row.driver === "filesystem") {
|
|
10573
10438
|
const fsMeta = metadata;
|
|
10574
10439
|
config3.basePath = resolveStoragePath(fsMeta.basePath || "./storage", projectPath);
|
|
10575
|
-
if (!
|
|
10440
|
+
if (!existsSync8(config3.basePath)) {
|
|
10576
10441
|
mkdirSync4(config3.basePath, { recursive: true });
|
|
10577
10442
|
}
|
|
10578
10443
|
} else if (row.driver === "s3") {
|
|
@@ -10604,7 +10469,7 @@ function buildConfigFromEnv(driver) {
|
|
|
10604
10469
|
if (driver === "filesystem") {
|
|
10605
10470
|
const rawPath = process.env["STORAGE_PATH"] || "./storage";
|
|
10606
10471
|
config3.basePath = resolveStoragePath(rawPath, projectPath);
|
|
10607
|
-
if (!
|
|
10472
|
+
if (!existsSync8(config3.basePath)) {
|
|
10608
10473
|
mkdirSync4(config3.basePath, { recursive: true });
|
|
10609
10474
|
}
|
|
10610
10475
|
} else if (driver === "s3") {
|
|
@@ -11043,7 +10908,7 @@ var init_storage_service = __esm({
|
|
|
11043
10908
|
});
|
|
11044
10909
|
|
|
11045
10910
|
// src/modules/storage/storage.entity.ts
|
|
11046
|
-
import { useIdField as useIdField3, useTextField as useTextField8, useSelectField as
|
|
10911
|
+
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";
|
|
11047
10912
|
var DEFAULT_MAX_SIZE2, storageConfigEntity, storageFilesEntity;
|
|
11048
10913
|
var init_storage_entity = __esm({
|
|
11049
10914
|
"src/modules/storage/storage.entity.ts"() {
|
|
@@ -11078,7 +10943,7 @@ var init_storage_entity = __esm({
|
|
|
11078
10943
|
hint: { en: "Unique identifier (e.g. default_filesystem, default_s3)", es: "Identificador \xFAnico (ej: default_filesystem, default_s3)" }
|
|
11079
10944
|
}),
|
|
11080
10945
|
driver: {
|
|
11081
|
-
...
|
|
10946
|
+
...useSelectField7({
|
|
11082
10947
|
label: { en: "Driver", es: "Controlador" },
|
|
11083
10948
|
required: true,
|
|
11084
10949
|
hint: { en: "Storage backend", es: "Backend de almacenamiento" },
|
|
@@ -11095,7 +10960,7 @@ var init_storage_entity = __esm({
|
|
|
11095
10960
|
size: 500,
|
|
11096
10961
|
nullable: true
|
|
11097
10962
|
}),
|
|
11098
|
-
max_file_size:
|
|
10963
|
+
max_file_size: useNumberField5({
|
|
11099
10964
|
label: { en: "Max File Size (bytes)", es: "Tama\xF1o m\xE1ximo de archivo (bytes)" },
|
|
11100
10965
|
hint: { en: "Maximum size in bytes (default: 10MB = 10485760)", es: "Tama\xF1o m\xE1ximo en bytes (default: 10MB = 10485760)" },
|
|
11101
10966
|
nullable: false,
|
|
@@ -11288,7 +11153,7 @@ var init_storage_entity = __esm({
|
|
|
11288
11153
|
index: true,
|
|
11289
11154
|
meta: { sortable: true, searchable: true }
|
|
11290
11155
|
}),
|
|
11291
|
-
size:
|
|
11156
|
+
size: useNumberField5({
|
|
11292
11157
|
label: { en: "Size", es: "Tama\xF1o" },
|
|
11293
11158
|
required: true,
|
|
11294
11159
|
nullable: false,
|
|
@@ -11830,7 +11695,7 @@ var init_storage = __esm({
|
|
|
11830
11695
|
});
|
|
11831
11696
|
|
|
11832
11697
|
// src/modules/users/users.entity.ts
|
|
11833
|
-
import { useIdField as useIdField4, useSelectField as
|
|
11698
|
+
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";
|
|
11834
11699
|
import { z as z3 } from "zod";
|
|
11835
11700
|
var userEntity, roleEntity, userRoleEntity;
|
|
11836
11701
|
var init_users_entity = __esm({
|
|
@@ -11904,7 +11769,7 @@ var init_users_entity = __esm({
|
|
|
11904
11769
|
label: { en: "Marketing Opt-in", es: "Aceptar marketing" },
|
|
11905
11770
|
meta: { exportable: true, showInForm: false, showInDisplay: false }
|
|
11906
11771
|
}),
|
|
11907
|
-
locale:
|
|
11772
|
+
locale: useSelectField8({
|
|
11908
11773
|
label: { en: "Language", es: "Idioma" },
|
|
11909
11774
|
options: [
|
|
11910
11775
|
{ value: "es", label: { en: "Spanish", es: "Espa\xF1ol" } },
|
|
@@ -11914,13 +11779,13 @@ var init_users_entity = __esm({
|
|
|
11914
11779
|
meta: { sortable: true },
|
|
11915
11780
|
defaultValue: "en"
|
|
11916
11781
|
}),
|
|
11917
|
-
timezone:
|
|
11782
|
+
timezone: useSelectField8({
|
|
11918
11783
|
label: { en: "Timezone", es: "Zona horaria" },
|
|
11919
11784
|
master: "timezones",
|
|
11920
11785
|
meta: { sortable: true },
|
|
11921
11786
|
defaultValue: "timezones:Europe/Madrid"
|
|
11922
11787
|
}),
|
|
11923
|
-
type:
|
|
11788
|
+
type: useSelectField8({
|
|
11924
11789
|
label: { en: "Type", es: "Tipo" },
|
|
11925
11790
|
defaultValue: "human",
|
|
11926
11791
|
options: [
|
|
@@ -12089,7 +11954,7 @@ var init_users_entity = __esm({
|
|
|
12089
11954
|
expose: false,
|
|
12090
11955
|
fields: {
|
|
12091
11956
|
id: useIdField4(),
|
|
12092
|
-
user_id:
|
|
11957
|
+
user_id: useSelectField8({
|
|
12093
11958
|
label: { en: "User", es: "Usuario" },
|
|
12094
11959
|
required: true,
|
|
12095
11960
|
table: "users",
|
|
@@ -12100,7 +11965,7 @@ var init_users_entity = __esm({
|
|
|
12100
11965
|
labelField: "name",
|
|
12101
11966
|
meta: { searchable: true }
|
|
12102
11967
|
}),
|
|
12103
|
-
role_id:
|
|
11968
|
+
role_id: useSelectField8({
|
|
12104
11969
|
label: { en: "Role", es: "Rol" },
|
|
12105
11970
|
required: true,
|
|
12106
11971
|
table: "roles",
|
|
@@ -13044,7 +12909,7 @@ var init_users = __esm({
|
|
|
13044
12909
|
});
|
|
13045
12910
|
|
|
13046
12911
|
// src/modules/auth/auth.entity.ts
|
|
13047
|
-
import { useIdField as useIdField5, useTextField as useTextField10, useSelectField as
|
|
12912
|
+
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";
|
|
13048
12913
|
var refreshTokenEntity, authIdentitiesEntity;
|
|
13049
12914
|
var init_auth_entity = __esm({
|
|
13050
12915
|
"src/modules/auth/auth.entity.ts"() {
|
|
@@ -13125,7 +12990,7 @@ var init_auth_entity = __esm({
|
|
|
13125
12990
|
order: 5,
|
|
13126
12991
|
fields: {
|
|
13127
12992
|
id: useIdField5(),
|
|
13128
|
-
user_id:
|
|
12993
|
+
user_id: useSelectField9({
|
|
13129
12994
|
label: { en: "User", es: "Usuario" },
|
|
13130
12995
|
table: "users",
|
|
13131
12996
|
column: "id",
|
|
@@ -13209,6 +13074,28 @@ var init_auth_routes = __esm({
|
|
|
13209
13074
|
}
|
|
13210
13075
|
});
|
|
13211
13076
|
|
|
13077
|
+
// src/core/crypto/secret-resolver.ts
|
|
13078
|
+
import { randomBytes } from "crypto";
|
|
13079
|
+
function _resetSecretResolver() {
|
|
13080
|
+
_secret = null;
|
|
13081
|
+
_db = null;
|
|
13082
|
+
}
|
|
13083
|
+
function getAuthSecret() {
|
|
13084
|
+
if (_secret) return _secret;
|
|
13085
|
+
const envSecret = process.env["AUTH_SECRET"];
|
|
13086
|
+
if (envSecret) return envSecret;
|
|
13087
|
+
throw new Error("AUTH_SECRET not initialized. Call initAuthSecret() during startup.");
|
|
13088
|
+
}
|
|
13089
|
+
var _secret, _db;
|
|
13090
|
+
var init_secret_resolver = __esm({
|
|
13091
|
+
"src/core/crypto/secret-resolver.ts"() {
|
|
13092
|
+
"use strict";
|
|
13093
|
+
init_database();
|
|
13094
|
+
_secret = null;
|
|
13095
|
+
_db = null;
|
|
13096
|
+
}
|
|
13097
|
+
});
|
|
13098
|
+
|
|
13212
13099
|
// src/modules/auth/auth.config.ts
|
|
13213
13100
|
import { z as z5 } from "zod";
|
|
13214
13101
|
function configError(module, errors) {
|
|
@@ -13225,12 +13112,6 @@ function parseAuthEnv() {
|
|
|
13225
13112
|
if (!result.success) {
|
|
13226
13113
|
const errors = result.error.issues.map((issue) => {
|
|
13227
13114
|
const path3 = issue.path.join(".");
|
|
13228
|
-
if (path3 === "AUTH_SECRET" && issue.code === "invalid_type") {
|
|
13229
|
-
return "AUTH_SECRET is required. Set it in your .env file or environment.";
|
|
13230
|
-
}
|
|
13231
|
-
if (path3 === "AUTH_SECRET" && issue.code === "too_small") {
|
|
13232
|
-
return `AUTH_SECRET must be at least 32 characters (current: ${String(process.env["AUTH_SECRET"]).length})`;
|
|
13233
|
-
}
|
|
13234
13115
|
return `${path3}: ${issue.message}`;
|
|
13235
13116
|
});
|
|
13236
13117
|
configError("auth", errors);
|
|
@@ -13249,7 +13130,7 @@ function getAuthEnv() {
|
|
|
13249
13130
|
function getAuthConfig() {
|
|
13250
13131
|
const authEnv = getAuthEnv();
|
|
13251
13132
|
return {
|
|
13252
|
-
secret:
|
|
13133
|
+
secret: getAuthSecret(),
|
|
13253
13134
|
accessExpires: authEnv.AUTH_ACCESS_EXPIRES,
|
|
13254
13135
|
refreshExpires: authEnv.AUTH_REFRESH_EXPIRES,
|
|
13255
13136
|
rateLimitMax: authEnv.AUTH_RATE_LIMIT_MAX,
|
|
@@ -13266,8 +13147,8 @@ var authEnvSchema, _authEnv;
|
|
|
13266
13147
|
var init_auth_config = __esm({
|
|
13267
13148
|
"src/modules/auth/auth.config.ts"() {
|
|
13268
13149
|
"use strict";
|
|
13150
|
+
init_secret_resolver();
|
|
13269
13151
|
authEnvSchema = z5.object({
|
|
13270
|
-
AUTH_SECRET: z5.string().min(32, "AUTH_SECRET must be at least 32 characters"),
|
|
13271
13152
|
AUTH_ACCESS_EXPIRES: z5.string().default("15m"),
|
|
13272
13153
|
AUTH_REFRESH_EXPIRES: z5.string().default("7d"),
|
|
13273
13154
|
// Rate limiting (default: 5 requests per 15 minutes)
|
|
@@ -13441,7 +13322,7 @@ var init_auth_middleware = __esm({
|
|
|
13441
13322
|
});
|
|
13442
13323
|
|
|
13443
13324
|
// src/modules/auth/auth.pat.entity.ts
|
|
13444
|
-
import { useIdField as useIdField6, useTextField as useTextField11, useSelectField as
|
|
13325
|
+
import { useIdField as useIdField6, useTextField as useTextField11, useSelectField as useSelectField10, useDatetimeField as useDatetimeField5, useExpiresAtField as useExpiresAtField2 } from "@gzl10/nexus-sdk/fields";
|
|
13445
13326
|
var personalTokenEntity;
|
|
13446
13327
|
var init_auth_pat_entity = __esm({
|
|
13447
13328
|
"src/modules/auth/auth.pat.entity.ts"() {
|
|
@@ -13458,7 +13339,7 @@ var init_auth_pat_entity = __esm({
|
|
|
13458
13339
|
routePrefix: "/personal-tokens",
|
|
13459
13340
|
fields: {
|
|
13460
13341
|
id: useIdField6(),
|
|
13461
|
-
user_id:
|
|
13342
|
+
user_id: useSelectField10({
|
|
13462
13343
|
label: { en: "User", es: "Usuario" },
|
|
13463
13344
|
table: "users",
|
|
13464
13345
|
column: "id",
|
|
@@ -13493,7 +13374,7 @@ var init_auth_pat_entity = __esm({
|
|
|
13493
13374
|
unique: true,
|
|
13494
13375
|
meta: { exportable: false }
|
|
13495
13376
|
}),
|
|
13496
|
-
scope:
|
|
13377
|
+
scope: useSelectField10({
|
|
13497
13378
|
label: { en: "Permission", es: "Permiso" },
|
|
13498
13379
|
required: true,
|
|
13499
13380
|
options: [
|
|
@@ -13525,42 +13406,6 @@ var init_auth_pat_entity = __esm({
|
|
|
13525
13406
|
}
|
|
13526
13407
|
});
|
|
13527
13408
|
|
|
13528
|
-
// src/modules/auth/actions/providers.action.ts
|
|
13529
|
-
var providersAction;
|
|
13530
|
-
var init_providers_action = __esm({
|
|
13531
|
-
"src/modules/auth/actions/providers.action.ts"() {
|
|
13532
|
-
"use strict";
|
|
13533
|
-
init_auth_config();
|
|
13534
|
-
providersAction = {
|
|
13535
|
-
key: "providers",
|
|
13536
|
-
label: { en: "Get Auth Providers", es: "Obtener proveedores de autenticaci\xF3n" },
|
|
13537
|
-
icon: "mdi:account-key",
|
|
13538
|
-
scope: "module",
|
|
13539
|
-
hidden: true,
|
|
13540
|
-
method: "GET",
|
|
13541
|
-
skipAuth: true,
|
|
13542
|
-
handler: async (ctx) => {
|
|
13543
|
-
const providerServices = ctx.services.getBySuffix(".provider");
|
|
13544
|
-
const results = await Promise.all(
|
|
13545
|
-
providerServices.map(async ({ service }) => {
|
|
13546
|
-
try {
|
|
13547
|
-
return await service.getInfo();
|
|
13548
|
-
} catch {
|
|
13549
|
-
return null;
|
|
13550
|
-
}
|
|
13551
|
-
})
|
|
13552
|
-
);
|
|
13553
|
-
const providers = results.filter((info) => info !== null);
|
|
13554
|
-
const config3 = getAuthConfig();
|
|
13555
|
-
return {
|
|
13556
|
-
providers,
|
|
13557
|
-
registrationEnabled: !config3.disableRegistration
|
|
13558
|
-
};
|
|
13559
|
-
}
|
|
13560
|
-
};
|
|
13561
|
-
}
|
|
13562
|
-
});
|
|
13563
|
-
|
|
13564
13409
|
// src/modules/auth/actions/helpers.ts
|
|
13565
13410
|
function getCookieOptions(req) {
|
|
13566
13411
|
const config3 = getAuthConfig();
|
|
@@ -14117,7 +13962,6 @@ var authActions;
|
|
|
14117
13962
|
var init_actions2 = __esm({
|
|
14118
13963
|
"src/modules/auth/actions/index.ts"() {
|
|
14119
13964
|
"use strict";
|
|
14120
|
-
init_providers_action();
|
|
14121
13965
|
init_login_action();
|
|
14122
13966
|
init_register_action();
|
|
14123
13967
|
init_forgot_password_action();
|
|
@@ -14133,7 +13977,6 @@ var init_actions2 = __esm({
|
|
|
14133
13977
|
init_list_tokens_action();
|
|
14134
13978
|
init_revoke_token_action();
|
|
14135
13979
|
init_impersonate_action();
|
|
14136
|
-
init_providers_action();
|
|
14137
13980
|
init_login_action();
|
|
14138
13981
|
init_register_action();
|
|
14139
13982
|
init_forgot_password_action();
|
|
@@ -14149,7 +13992,6 @@ var init_actions2 = __esm({
|
|
|
14149
13992
|
init_list_tokens_action();
|
|
14150
13993
|
init_revoke_token_action();
|
|
14151
13994
|
authActions = [
|
|
14152
|
-
providersAction,
|
|
14153
13995
|
loginAction,
|
|
14154
13996
|
registerAction,
|
|
14155
13997
|
forgotPasswordAction,
|
|
@@ -14368,7 +14210,7 @@ var init_otp_manager = __esm({
|
|
|
14368
14210
|
});
|
|
14369
14211
|
|
|
14370
14212
|
// src/modules/auth/auth.service.ts
|
|
14371
|
-
import { createHash as createHash4, randomBytes } from "crypto";
|
|
14213
|
+
import { createHash as createHash4, randomBytes as randomBytes2 } from "crypto";
|
|
14372
14214
|
function createAuthService(ctx) {
|
|
14373
14215
|
const { errors, abilities, crypto: crypto3 } = ctx.core;
|
|
14374
14216
|
const { generateId: generateId2 } = ctx.core;
|
|
@@ -14785,7 +14627,7 @@ function createAuthService(ctx) {
|
|
|
14785
14627
|
},
|
|
14786
14628
|
// === Personal Access Tokens ===
|
|
14787
14629
|
async createPersonalToken(userId, input, requestInfo) {
|
|
14788
|
-
const rawToken = "nxs_" +
|
|
14630
|
+
const rawToken = "nxs_" + randomBytes2(32).toString("hex");
|
|
14789
14631
|
const tokenHash = createHash4("sha256").update(rawToken).digest("hex");
|
|
14790
14632
|
const tokenPrefix = "nxs_..." + rawToken.slice(-6);
|
|
14791
14633
|
const id = generateId2();
|
|
@@ -15121,8 +14963,8 @@ var init_mail_config = __esm({
|
|
|
15121
14963
|
|
|
15122
14964
|
// src/modules/mail/mail.service.ts
|
|
15123
14965
|
import nodemailer from "nodemailer";
|
|
15124
|
-
import { readFileSync as
|
|
15125
|
-
import { join as
|
|
14966
|
+
import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
|
|
14967
|
+
import { join as join12 } from "path";
|
|
15126
14968
|
function getMailService() {
|
|
15127
14969
|
if (!mailServiceInstance) {
|
|
15128
14970
|
throw new Error("MailService not initialized. Call initMailService() first.");
|
|
@@ -15139,8 +14981,8 @@ var init_mail_service = __esm({
|
|
|
15139
14981
|
"src/modules/mail/mail.service.ts"() {
|
|
15140
14982
|
"use strict";
|
|
15141
14983
|
init_mail_config();
|
|
15142
|
-
TEMPLATE_REL_PATH =
|
|
15143
|
-
LOGO_REL_PATH =
|
|
14984
|
+
TEMPLATE_REL_PATH = join12("public", "mail", "base.html");
|
|
14985
|
+
LOGO_REL_PATH = join12("public", "nexus", "nexus-light-512.png");
|
|
15144
14986
|
mailServiceInstance = null;
|
|
15145
14987
|
MailService = class {
|
|
15146
14988
|
transporter;
|
|
@@ -15154,10 +14996,10 @@ var init_mail_service = __esm({
|
|
|
15154
14996
|
this.logger = logger3.child({ service: "mail" });
|
|
15155
14997
|
this.loggerService = loggerService;
|
|
15156
14998
|
const libPath = options?.libPath ?? process.cwd();
|
|
15157
|
-
this.template =
|
|
15158
|
-
const logoPath =
|
|
15159
|
-
if (
|
|
15160
|
-
const logoBase64 =
|
|
14999
|
+
this.template = readFileSync7(join12(libPath, TEMPLATE_REL_PATH), "utf-8");
|
|
15000
|
+
const logoPath = join12(libPath, LOGO_REL_PATH);
|
|
15001
|
+
if (existsSync9(logoPath)) {
|
|
15002
|
+
const logoBase64 = readFileSync7(logoPath).toString("base64");
|
|
15161
15003
|
this.defaultLogoUrl = `data:image/png;base64,${logoBase64}`;
|
|
15162
15004
|
} else {
|
|
15163
15005
|
this.defaultLogoUrl = "";
|
|
@@ -15249,7 +15091,7 @@ var init_mail_service = __esm({
|
|
|
15249
15091
|
});
|
|
15250
15092
|
|
|
15251
15093
|
// src/modules/mail/mail.entity.ts
|
|
15252
|
-
import { useIdField as useIdField7, useTextField as useTextField12, useSelectField as
|
|
15094
|
+
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";
|
|
15253
15095
|
import nodemailer2 from "nodemailer";
|
|
15254
15096
|
async function getMailConfigFromDB(ctx) {
|
|
15255
15097
|
const configService = ctx.services["config"];
|
|
@@ -15318,12 +15160,12 @@ var init_mail_entity = __esm({
|
|
|
15318
15160
|
nullable: false,
|
|
15319
15161
|
hint: { en: "Default: SMTP_HOST env var", es: "Por defecto: variable SMTP_HOST" }
|
|
15320
15162
|
}),
|
|
15321
|
-
port:
|
|
15163
|
+
port: useNumberField6({
|
|
15322
15164
|
label: { en: "Port", es: "Puerto" },
|
|
15323
15165
|
nullable: false,
|
|
15324
15166
|
hint: { en: "Default: SMTP_PORT env var", es: "Por defecto: variable SMTP_PORT" }
|
|
15325
15167
|
}),
|
|
15326
|
-
secure:
|
|
15168
|
+
secure: useSwitchField3({
|
|
15327
15169
|
label: { en: "TLS/SSL", es: "TLS/SSL" },
|
|
15328
15170
|
hint: { en: "Default: SMTP_SECURE env var", es: "Por defecto: variable SMTP_SECURE" }
|
|
15329
15171
|
}),
|
|
@@ -15526,7 +15368,7 @@ var init_mail_entity = __esm({
|
|
|
15526
15368
|
meta: { searchable: true, sortable: true }
|
|
15527
15369
|
}),
|
|
15528
15370
|
status: {
|
|
15529
|
-
...
|
|
15371
|
+
...useSelectField11({
|
|
15530
15372
|
label: { en: "Status", es: "Estado" },
|
|
15531
15373
|
options: [
|
|
15532
15374
|
{ value: "pending", label: { en: "Pending", es: "Pendiente" } },
|
|
@@ -15550,7 +15392,7 @@ var init_mail_entity = __esm({
|
|
|
15550
15392
|
label: { en: "Error", es: "Error" },
|
|
15551
15393
|
nullable: true
|
|
15552
15394
|
}),
|
|
15553
|
-
sent_by:
|
|
15395
|
+
sent_by: useSelectField11({
|
|
15554
15396
|
label: { en: "Sent by", es: "Enviado por" },
|
|
15555
15397
|
table: "users",
|
|
15556
15398
|
column: "id",
|
|
@@ -16176,7 +16018,7 @@ var init_toggle_plugin_action = __esm({
|
|
|
16176
16018
|
});
|
|
16177
16019
|
|
|
16178
16020
|
// src/modules/plugins/plugins.entity.ts
|
|
16179
|
-
import { useTextField as useTextField13, useSelectField as
|
|
16021
|
+
import { useTextField as useTextField13, useSelectField as useSelectField12, useCheckboxField as useCheckboxField5 } from "@gzl10/nexus-sdk/fields";
|
|
16180
16022
|
import { OFFICIAL_PLUGINS } from "@gzl10/nexus-sdk";
|
|
16181
16023
|
var allowPluginManagement, pluginsEntity;
|
|
16182
16024
|
var init_plugins_entity = __esm({
|
|
@@ -16218,7 +16060,7 @@ var init_plugins_entity = __esm({
|
|
|
16218
16060
|
size: 20,
|
|
16219
16061
|
nullable: false
|
|
16220
16062
|
}),
|
|
16221
|
-
category:
|
|
16063
|
+
category: useSelectField12({
|
|
16222
16064
|
label: { en: "Category", es: "Categor\xEDa" },
|
|
16223
16065
|
options: [
|
|
16224
16066
|
{ value: "content", label: { en: "Content", es: "Contenido" } },
|
|
@@ -16297,7 +16139,7 @@ var init_plugins_entity = __esm({
|
|
|
16297
16139
|
|
|
16298
16140
|
// src/modules/plugins/plugins.routes.ts
|
|
16299
16141
|
import { Router } from "express";
|
|
16300
|
-
import { existsSync as
|
|
16142
|
+
import { existsSync as existsSync10 } from "fs";
|
|
16301
16143
|
function createPluginRoutes(ctx) {
|
|
16302
16144
|
const router = Router();
|
|
16303
16145
|
let imageMap = null;
|
|
@@ -16305,7 +16147,7 @@ function createPluginRoutes(ctx) {
|
|
|
16305
16147
|
if (!imageMap) {
|
|
16306
16148
|
const discovered = await ctx.core.plugins.discover();
|
|
16307
16149
|
imageMap = new Map(
|
|
16308
|
-
discovered.filter((p) => p.image &&
|
|
16150
|
+
discovered.filter((p) => p.image && existsSync10(p.image)).map((p) => [p.code, p.image])
|
|
16309
16151
|
);
|
|
16310
16152
|
}
|
|
16311
16153
|
return imageMap;
|
|
@@ -16360,7 +16202,7 @@ var init_plugins = __esm({
|
|
|
16360
16202
|
import {
|
|
16361
16203
|
useIdField as useIdField8,
|
|
16362
16204
|
useTextField as useTextField14,
|
|
16363
|
-
useSelectField as
|
|
16205
|
+
useSelectField as useSelectField13,
|
|
16364
16206
|
useTextareaField as useTextareaField4,
|
|
16365
16207
|
useJsonField as useJsonField3,
|
|
16366
16208
|
useDatetimeField as useDatetimeField7,
|
|
@@ -16402,7 +16244,7 @@ var init_audit_entity = __esm({
|
|
|
16402
16244
|
}),
|
|
16403
16245
|
validation: { min: 1, max: 100 }
|
|
16404
16246
|
},
|
|
16405
|
-
actor_id:
|
|
16247
|
+
actor_id: useSelectField13({
|
|
16406
16248
|
label: { en: "Actor", es: "Actor" },
|
|
16407
16249
|
table: "users",
|
|
16408
16250
|
column: "id",
|
|
@@ -16679,6 +16521,7 @@ import jwt3 from "jsonwebtoken";
|
|
|
16679
16521
|
var init_jwt = __esm({
|
|
16680
16522
|
"src/core/jwt/index.ts"() {
|
|
16681
16523
|
"use strict";
|
|
16524
|
+
init_secret_resolver();
|
|
16682
16525
|
}
|
|
16683
16526
|
});
|
|
16684
16527
|
|
|
@@ -17090,6 +16933,7 @@ var init_socket = __esm({
|
|
|
17090
16933
|
"use strict";
|
|
17091
16934
|
init_emitter();
|
|
17092
16935
|
init_logger();
|
|
16936
|
+
init_secret_resolver();
|
|
17093
16937
|
io = null;
|
|
17094
16938
|
userSockets = /* @__PURE__ */ new Map();
|
|
17095
16939
|
socketUsers = /* @__PURE__ */ new Map();
|
|
@@ -17283,8 +17127,8 @@ var init_port_check = __esm({
|
|
|
17283
17127
|
});
|
|
17284
17128
|
|
|
17285
17129
|
// src/db/seed-runner.ts
|
|
17286
|
-
import { existsSync as
|
|
17287
|
-
import { join as
|
|
17130
|
+
import { existsSync as existsSync11 } from "fs";
|
|
17131
|
+
import { join as join13 } from "path";
|
|
17288
17132
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
17289
17133
|
var init_seed_runner = __esm({
|
|
17290
17134
|
"src/db/seed-runner.ts"() {
|
|
@@ -18309,7 +18153,7 @@ var init_migration_helpers = __esm({
|
|
|
18309
18153
|
// src/db/migration-generator.ts
|
|
18310
18154
|
import path2 from "path";
|
|
18311
18155
|
import fs2 from "fs/promises";
|
|
18312
|
-
import { readFileSync as
|
|
18156
|
+
import { readFileSync as readFileSync8, mkdirSync as mkdirSync5, realpathSync } from "fs";
|
|
18313
18157
|
function getColumnIndexBytes(field) {
|
|
18314
18158
|
if (!field?.db) return 255 * MYSQL_BYTES_PER_CHAR;
|
|
18315
18159
|
const size = field.db.size ?? 255;
|
|
@@ -18401,7 +18245,7 @@ function resolvePrefix(scope) {
|
|
|
18401
18245
|
function detectDefaultScope() {
|
|
18402
18246
|
try {
|
|
18403
18247
|
const pkgPath = path2.join(getProjectPath(), "package.json");
|
|
18404
|
-
const pkg3 = JSON.parse(
|
|
18248
|
+
const pkg3 = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
18405
18249
|
const pkgName = pkg3?.name;
|
|
18406
18250
|
if (pkgName === "@gzl10/nexus-backend") {
|
|
18407
18251
|
return "core";
|
|
@@ -19190,7 +19034,7 @@ var init_db = __esm({
|
|
|
19190
19034
|
// src/core/tunnel.ts
|
|
19191
19035
|
import { spawn, execSync } from "child_process";
|
|
19192
19036
|
import { writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
19193
|
-
import { join as
|
|
19037
|
+
import { join as join14 } from "path";
|
|
19194
19038
|
import { tmpdir } from "os";
|
|
19195
19039
|
function stopTunnel() {
|
|
19196
19040
|
if (tunnelProcess) {
|
|
@@ -19294,6 +19138,7 @@ async function stop() {
|
|
|
19294
19138
|
resetConfigCache();
|
|
19295
19139
|
clearCustomCaslRules();
|
|
19296
19140
|
clearSeedPermissions();
|
|
19141
|
+
_resetSecretResolver();
|
|
19297
19142
|
await resetServeSPA();
|
|
19298
19143
|
return;
|
|
19299
19144
|
}
|
|
@@ -19329,6 +19174,7 @@ async function stop() {
|
|
|
19329
19174
|
resetConfigCache();
|
|
19330
19175
|
clearCustomCaslRules();
|
|
19331
19176
|
clearSeedPermissions();
|
|
19177
|
+
_resetSecretResolver();
|
|
19332
19178
|
await resetServeSPA();
|
|
19333
19179
|
currentConfig = void 0;
|
|
19334
19180
|
server = null;
|
|
@@ -19389,6 +19235,7 @@ var init_server = __esm({
|
|
|
19389
19235
|
init_ensure_system_tables();
|
|
19390
19236
|
init_load_config();
|
|
19391
19237
|
init_tunnel();
|
|
19238
|
+
init_secret_resolver();
|
|
19392
19239
|
server = null;
|
|
19393
19240
|
gracefulShutdownRegistered = false;
|
|
19394
19241
|
setupGracefulShutdown();
|
|
@@ -19444,10 +19291,11 @@ var init_hash = __esm({
|
|
|
19444
19291
|
});
|
|
19445
19292
|
|
|
19446
19293
|
// src/core/crypto/symmetric.ts
|
|
19447
|
-
import { createCipheriv, createDecipheriv, randomBytes as
|
|
19294
|
+
import { createCipheriv, createDecipheriv, randomBytes as randomBytes3, hkdfSync } from "crypto";
|
|
19448
19295
|
var init_symmetric = __esm({
|
|
19449
19296
|
"src/core/crypto/symmetric.ts"() {
|
|
19450
19297
|
"use strict";
|
|
19298
|
+
init_secret_resolver();
|
|
19451
19299
|
}
|
|
19452
19300
|
});
|
|
19453
19301
|
|
|
@@ -19559,6 +19407,13 @@ var init_events_api = __esm({
|
|
|
19559
19407
|
}
|
|
19560
19408
|
});
|
|
19561
19409
|
|
|
19410
|
+
// src/engine/capabilities-registry.ts
|
|
19411
|
+
var init_capabilities_registry = __esm({
|
|
19412
|
+
"src/engine/capabilities-registry.ts"() {
|
|
19413
|
+
"use strict";
|
|
19414
|
+
}
|
|
19415
|
+
});
|
|
19416
|
+
|
|
19562
19417
|
// src/engine/context.ts
|
|
19563
19418
|
import { ForbiddenError as CASLForbiddenError3, subject } from "@casl/ability";
|
|
19564
19419
|
import { DEFAULT_TENANT_ID as DEFAULT_TENANT_ID2, DEFAULT_LOCALES as DEFAULT_LOCALES2 } from "@gzl10/nexus-sdk";
|
|
@@ -19585,6 +19440,7 @@ var init_context = __esm({
|
|
|
19585
19440
|
init_plugin_ops();
|
|
19586
19441
|
init_load_config();
|
|
19587
19442
|
init_events_api();
|
|
19443
|
+
init_capabilities_registry();
|
|
19588
19444
|
init_seed_runner();
|
|
19589
19445
|
init_cache_manager();
|
|
19590
19446
|
sharedCacheManager = null;
|
|
@@ -19603,6 +19459,7 @@ var init_engine = __esm({
|
|
|
19603
19459
|
init_subject_extractor();
|
|
19604
19460
|
init_definition_extractors();
|
|
19605
19461
|
init_context();
|
|
19462
|
+
init_capabilities_registry();
|
|
19606
19463
|
}
|
|
19607
19464
|
});
|
|
19608
19465
|
|
|
@@ -19620,8 +19477,8 @@ __export(migrate_commands_exports, {
|
|
|
19620
19477
|
handleUp: () => handleUp,
|
|
19621
19478
|
loadModulesForMigration: () => loadModulesForMigration
|
|
19622
19479
|
});
|
|
19623
|
-
import { readFileSync as
|
|
19624
|
-
import { join as
|
|
19480
|
+
import { readFileSync as readFileSync9, existsSync as existsSync12 } from "fs";
|
|
19481
|
+
import { join as join15 } from "path";
|
|
19625
19482
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
19626
19483
|
import Table from "cli-table3";
|
|
19627
19484
|
import { consola as consola2 } from "consola";
|
|
@@ -19631,15 +19488,15 @@ function scopeToSourceId(scope) {
|
|
|
19631
19488
|
}
|
|
19632
19489
|
async function loadSelfPlugin() {
|
|
19633
19490
|
const projectPath2 = getProjectPath();
|
|
19634
|
-
const pkgPath =
|
|
19635
|
-
if (!
|
|
19491
|
+
const pkgPath = join15(projectPath2, "package.json");
|
|
19492
|
+
if (!existsSync12(pkgPath)) return;
|
|
19636
19493
|
try {
|
|
19637
|
-
const pkg3 = JSON.parse(
|
|
19494
|
+
const pkg3 = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
19638
19495
|
const pkgName = pkg3?.name;
|
|
19639
19496
|
if (!pkgName || !/nexus-plugin-/.test(pkgName)) return;
|
|
19640
|
-
const srcEntry =
|
|
19641
|
-
const distEntry =
|
|
19642
|
-
if (
|
|
19497
|
+
const srcEntry = join15(projectPath2, "src", "index.ts");
|
|
19498
|
+
const distEntry = join15(projectPath2, "dist", "index.js");
|
|
19499
|
+
if (existsSync12(srcEntry)) {
|
|
19643
19500
|
try {
|
|
19644
19501
|
const { tsImport } = await import("tsx/esm/api");
|
|
19645
19502
|
const mod = await tsImport(
|
|
@@ -19649,7 +19506,7 @@ async function loadSelfPlugin() {
|
|
|
19649
19506
|
const manifest = extractPluginManifest(mod);
|
|
19650
19507
|
if (manifest) {
|
|
19651
19508
|
if (!manifest.migrationsDir) {
|
|
19652
|
-
manifest.migrationsDir =
|
|
19509
|
+
manifest.migrationsDir = join15(projectPath2, "migrations");
|
|
19653
19510
|
}
|
|
19654
19511
|
registerPlugin(manifest);
|
|
19655
19512
|
return;
|
|
@@ -19658,13 +19515,13 @@ async function loadSelfPlugin() {
|
|
|
19658
19515
|
console.error(` \u26A0 Failed to load plugin src/index.ts: ${err.message}`);
|
|
19659
19516
|
}
|
|
19660
19517
|
}
|
|
19661
|
-
if (
|
|
19518
|
+
if (existsSync12(distEntry)) {
|
|
19662
19519
|
try {
|
|
19663
19520
|
const mod = await import(pathToFileURL3(distEntry).href);
|
|
19664
19521
|
const manifest = extractPluginManifest(mod);
|
|
19665
19522
|
if (manifest) {
|
|
19666
19523
|
if (!manifest.migrationsDir) {
|
|
19667
|
-
manifest.migrationsDir =
|
|
19524
|
+
manifest.migrationsDir = join15(projectPath2, "migrations");
|
|
19668
19525
|
}
|
|
19669
19526
|
registerPlugin(manifest);
|
|
19670
19527
|
return;
|
|
@@ -19983,7 +19840,7 @@ __export(db_commands_exports, {
|
|
|
19983
19840
|
handleDbWipe: () => handleDbWipe
|
|
19984
19841
|
});
|
|
19985
19842
|
import { spawn as spawn2 } from "child_process";
|
|
19986
|
-
import { isAbsolute as isAbsolute3, join as
|
|
19843
|
+
import { isAbsolute as isAbsolute3, join as join16 } from "path";
|
|
19987
19844
|
import { statSync as statSync2 } from "fs";
|
|
19988
19845
|
import { consola as consola3 } from "consola";
|
|
19989
19846
|
async function handleDbWipe(options) {
|
|
@@ -20071,7 +19928,7 @@ function handleDbShell() {
|
|
|
20071
19928
|
if (dbType === "sqlite") {
|
|
20072
19929
|
let filename = url.replace(/^(file:|sqlite:)/, "");
|
|
20073
19930
|
if (!isAbsolute3(filename)) {
|
|
20074
|
-
filename =
|
|
19931
|
+
filename = join16(getProjectPath(), "data", filename);
|
|
20075
19932
|
}
|
|
20076
19933
|
cmd = "sqlite3";
|
|
20077
19934
|
args = [filename];
|
|
@@ -20116,7 +19973,7 @@ async function collectDbInfo() {
|
|
|
20116
19973
|
if (url !== ":memory:" && !url.includes(":memory:")) {
|
|
20117
19974
|
let filename = url.replace(/^(file:|sqlite:)/, "");
|
|
20118
19975
|
if (!isAbsolute3(filename)) {
|
|
20119
|
-
filename =
|
|
19976
|
+
filename = join16(getProjectPath(), "data", filename);
|
|
20120
19977
|
}
|
|
20121
19978
|
try {
|
|
20122
19979
|
const stat2 = statSync2(filename);
|
|
@@ -20173,8 +20030,8 @@ __export(plugin_commands_exports, {
|
|
|
20173
20030
|
handlePluginList: () => handlePluginList,
|
|
20174
20031
|
handlePluginRemove: () => handlePluginRemove
|
|
20175
20032
|
});
|
|
20176
|
-
import { existsSync as
|
|
20177
|
-
import { join as
|
|
20033
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
20034
|
+
import { join as join17 } from "path";
|
|
20178
20035
|
import Table2 from "cli-table3";
|
|
20179
20036
|
import { consola as consola4 } from "consola";
|
|
20180
20037
|
import { OFFICIAL_PLUGINS as OFFICIAL_PLUGINS2 } from "@gzl10/nexus-sdk";
|
|
@@ -20182,10 +20039,10 @@ function pluginLabel(name) {
|
|
|
20182
20039
|
return shortPluginName(name).split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
20183
20040
|
}
|
|
20184
20041
|
function readPluginVersion(projectPath2, pkgName) {
|
|
20185
|
-
const pkgJsonPath =
|
|
20186
|
-
if (!
|
|
20042
|
+
const pkgJsonPath = join17(projectPath2, "node_modules", pkgName, "package.json");
|
|
20043
|
+
if (!existsSync13(pkgJsonPath)) return null;
|
|
20187
20044
|
try {
|
|
20188
|
-
const pkg3 = JSON.parse(
|
|
20045
|
+
const pkg3 = JSON.parse(readFileSync10(pkgJsonPath, "utf-8"));
|
|
20189
20046
|
return pkg3.version ?? null;
|
|
20190
20047
|
} catch {
|
|
20191
20048
|
return null;
|
|
@@ -20471,19 +20328,19 @@ var sync_commands_exports = {};
|
|
|
20471
20328
|
__export(sync_commands_exports, {
|
|
20472
20329
|
handleSyncCommands: () => handleSyncCommands
|
|
20473
20330
|
});
|
|
20474
|
-
import { existsSync as
|
|
20475
|
-
import { join as
|
|
20331
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync6, readdirSync as readdirSync2, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
|
|
20332
|
+
import { join as join18, basename as basename4 } from "path";
|
|
20476
20333
|
import { homedir } from "os";
|
|
20477
20334
|
import { createConsola } from "consola";
|
|
20478
20335
|
async function handleSyncCommands(options) {
|
|
20479
|
-
const sourceDir =
|
|
20480
|
-
const targetDir =
|
|
20481
|
-
if (!
|
|
20336
|
+
const sourceDir = join18(getLibPath(), "claude-commands");
|
|
20337
|
+
const targetDir = join18(homedir(), ".claude", "commands");
|
|
20338
|
+
if (!existsSync14(sourceDir)) {
|
|
20482
20339
|
logger2.warn(`Commands source not found: ${sourceDir}`);
|
|
20483
20340
|
logger2.info("Make sure @gzl10/nexus-backend is properly installed.");
|
|
20484
20341
|
return;
|
|
20485
20342
|
}
|
|
20486
|
-
if (!
|
|
20343
|
+
if (!existsSync14(targetDir)) {
|
|
20487
20344
|
if (options.dryRun) {
|
|
20488
20345
|
logger2.info(`Would create: ${targetDir}`);
|
|
20489
20346
|
} else {
|
|
@@ -20498,16 +20355,16 @@ async function handleSyncCommands(options) {
|
|
|
20498
20355
|
}
|
|
20499
20356
|
const result = { added: [], updated: [], unchanged: [] };
|
|
20500
20357
|
for (const file of sourceFiles) {
|
|
20501
|
-
const sourcePath =
|
|
20502
|
-
const targetPath =
|
|
20503
|
-
const sourceContent =
|
|
20504
|
-
if (!
|
|
20358
|
+
const sourcePath = join18(sourceDir, file);
|
|
20359
|
+
const targetPath = join18(targetDir, file);
|
|
20360
|
+
const sourceContent = readFileSync11(sourcePath, "utf-8");
|
|
20361
|
+
if (!existsSync14(targetPath)) {
|
|
20505
20362
|
if (!options.dryRun) {
|
|
20506
20363
|
writeFileSync3(targetPath, sourceContent, "utf-8");
|
|
20507
20364
|
}
|
|
20508
20365
|
result.added.push(file);
|
|
20509
20366
|
} else {
|
|
20510
|
-
const targetContent =
|
|
20367
|
+
const targetContent = readFileSync11(targetPath, "utf-8");
|
|
20511
20368
|
if (sourceContent !== targetContent) {
|
|
20512
20369
|
if (!options.dryRun) {
|
|
20513
20370
|
writeFileSync3(targetPath, sourceContent, "utf-8");
|
|
@@ -20553,8 +20410,8 @@ __export(seed_commands_exports, {
|
|
|
20553
20410
|
handleSeedExport: () => handleSeedExport,
|
|
20554
20411
|
importSeedFiles: () => importSeedFiles
|
|
20555
20412
|
});
|
|
20556
|
-
import { existsSync as
|
|
20557
|
-
import { join as
|
|
20413
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync7, writeFileSync as writeFileSync4, readdirSync as readdirSync3, readFileSync as readFileSync12 } from "fs";
|
|
20414
|
+
import { join as join19, basename as basename5 } from "path";
|
|
20558
20415
|
import { consola as consola5 } from "consola";
|
|
20559
20416
|
function deserializeJsonFields(record, fields) {
|
|
20560
20417
|
const result = { ...record };
|
|
@@ -20583,7 +20440,7 @@ async function handleSeedExport(entity) {
|
|
|
20583
20440
|
const db3 = getDb();
|
|
20584
20441
|
try {
|
|
20585
20442
|
const modules = getOrderedModules();
|
|
20586
|
-
const seedDir =
|
|
20443
|
+
const seedDir = join19(getProjectPath(), "data", "seeds");
|
|
20587
20444
|
const seedableEntities = [];
|
|
20588
20445
|
for (const mod of modules) {
|
|
20589
20446
|
for (const def of mod.definitions ?? []) {
|
|
@@ -20604,7 +20461,7 @@ async function handleSeedExport(entity) {
|
|
|
20604
20461
|
}
|
|
20605
20462
|
return;
|
|
20606
20463
|
}
|
|
20607
|
-
if (!
|
|
20464
|
+
if (!existsSync15(seedDir)) {
|
|
20608
20465
|
mkdirSync7(seedDir, { recursive: true });
|
|
20609
20466
|
}
|
|
20610
20467
|
for (const { module: modName, table, fields } of seedableEntities) {
|
|
@@ -20616,7 +20473,7 @@ async function handleSeedExport(entity) {
|
|
|
20616
20473
|
const exported = rows.map(
|
|
20617
20474
|
(row) => deserializeJsonFields(row, fields)
|
|
20618
20475
|
);
|
|
20619
|
-
const filePath =
|
|
20476
|
+
const filePath = join19(seedDir, `${table}.json`);
|
|
20620
20477
|
writeFileSync4(filePath, JSON.stringify(exported, null, 2) + "\n", "utf-8");
|
|
20621
20478
|
consola5.success(`${table}: exported ${rows.length} records to data/seeds/${table}.json (module: ${modName})`);
|
|
20622
20479
|
}
|
|
@@ -20628,8 +20485,8 @@ async function handleSeedExport(entity) {
|
|
|
20628
20485
|
}
|
|
20629
20486
|
}
|
|
20630
20487
|
async function importSeedFiles(db3, modules, logger3) {
|
|
20631
|
-
const seedDir =
|
|
20632
|
-
if (!
|
|
20488
|
+
const seedDir = join19(getProjectPath(), "data", "seeds");
|
|
20489
|
+
if (!existsSync15(seedDir)) return;
|
|
20633
20490
|
const files = readdirSync3(seedDir).filter((f) => f.endsWith(".json"));
|
|
20634
20491
|
if (files.length === 0) return;
|
|
20635
20492
|
const seedableDefs = /* @__PURE__ */ new Map();
|
|
@@ -20650,8 +20507,8 @@ async function importSeedFiles(db3, modules, logger3) {
|
|
|
20650
20507
|
logger3.debug(`data/seeds/${file}: skipped (entity "${table}" is not seedable)`);
|
|
20651
20508
|
continue;
|
|
20652
20509
|
}
|
|
20653
|
-
const filePath =
|
|
20654
|
-
const raw =
|
|
20510
|
+
const filePath = join19(seedDir, file);
|
|
20511
|
+
const raw = readFileSync12(filePath, "utf-8");
|
|
20655
20512
|
let records;
|
|
20656
20513
|
try {
|
|
20657
20514
|
records = JSON.parse(raw);
|
|
@@ -20698,12 +20555,12 @@ if (!nodeEnv || nodeEnv === "development") {
|
|
|
20698
20555
|
}
|
|
20699
20556
|
|
|
20700
20557
|
// src/cli.ts
|
|
20701
|
-
import { readFileSync as
|
|
20558
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
20702
20559
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
20703
|
-
import { dirname as dirname8, join as
|
|
20560
|
+
import { dirname as dirname8, join as join20 } from "path";
|
|
20704
20561
|
import { Command } from "commander";
|
|
20705
20562
|
var __dirname2 = dirname8(fileURLToPath3(import.meta.url));
|
|
20706
|
-
var pkg2 = JSON.parse(
|
|
20563
|
+
var pkg2 = JSON.parse(readFileSync13(join20(__dirname2, "..", "package.json"), "utf-8"));
|
|
20707
20564
|
var program = new Command();
|
|
20708
20565
|
program.name("nexus").description("Nexus Backend CLI").version(pkg2.version);
|
|
20709
20566
|
program.command("info").description("Show Nexus environment, database, plugins, and paths").option("--json", "Output as JSON").action(async (options) => {
|