@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.
- 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 +264 -403
- 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
|
@@ -865,13 +865,17 @@ import { readFileSync as readFileSync4 } from "fs";
|
|
|
865
865
|
import { dirname as dirname5, join as join6 } from "path";
|
|
866
866
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
867
867
|
function getVersion() {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
868
|
+
let dir = dirname5(fileURLToPath2(import.meta.url));
|
|
869
|
+
for (let i = 0; i < 5; i++) {
|
|
870
|
+
const candidate = join6(dir, "package.json");
|
|
871
|
+
try {
|
|
872
|
+
const pkg3 = JSON.parse(readFileSync4(candidate, "utf-8"));
|
|
873
|
+
if (pkg3.name === "@gzl10/nexus-backend") return pkg3.version;
|
|
874
|
+
} catch {
|
|
875
|
+
}
|
|
876
|
+
dir = dirname5(dir);
|
|
874
877
|
}
|
|
878
|
+
return "unknown";
|
|
875
879
|
}
|
|
876
880
|
async function collectInfo() {
|
|
877
881
|
const config3 = resolveConfig();
|
|
@@ -8705,18 +8709,20 @@ function createSystemController(ctx) {
|
|
|
8705
8709
|
/**
|
|
8706
8710
|
* GET /system/capabilities
|
|
8707
8711
|
* Public endpoint — no authentication required.
|
|
8708
|
-
*
|
|
8712
|
+
* Resolves all registered capabilities (core + plugin-contributed).
|
|
8709
8713
|
*/
|
|
8710
|
-
getCapabilities(_req, res) {
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
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
|
+
}
|
|
8720
8726
|
}
|
|
8721
8727
|
};
|
|
8722
8728
|
function toManifestDTO(manifest, req) {
|
|
@@ -9289,8 +9295,8 @@ function registerCoreVars(registry2) {
|
|
|
9289
9295
|
registry2.register("auth", "core", [
|
|
9290
9296
|
{
|
|
9291
9297
|
name: "AUTH_SECRET",
|
|
9292
|
-
description: { en: "JWT signing secret. Must be at least 32 characters.
|
|
9293
|
-
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,
|
|
9294
9300
|
sensitive: true
|
|
9295
9301
|
},
|
|
9296
9302
|
{
|
|
@@ -9807,96 +9813,70 @@ var init_system = __esm({
|
|
|
9807
9813
|
}
|
|
9808
9814
|
});
|
|
9809
9815
|
|
|
9810
|
-
// src/modules/ui-settings/ui-
|
|
9811
|
-
import { useTextField as useTextField7, useImageField } from "@gzl10/nexus-sdk/fields";
|
|
9812
|
-
var
|
|
9813
|
-
var
|
|
9814
|
-
"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"() {
|
|
9815
9821
|
"use strict";
|
|
9816
|
-
|
|
9822
|
+
uiStyleGuideEntity = {
|
|
9817
9823
|
type: "single",
|
|
9818
9824
|
realtime: "sync",
|
|
9819
|
-
key: "
|
|
9820
|
-
label: { en: "
|
|
9821
|
-
icon: "mdi:palette-
|
|
9825
|
+
key: "ui_style_guide",
|
|
9826
|
+
label: { en: "Style Guide", es: "Gu\xEDa de Estilos" },
|
|
9827
|
+
icon: "mdi:palette-outline",
|
|
9822
9828
|
public: true,
|
|
9823
|
-
routePrefix: "/ui-
|
|
9829
|
+
routePrefix: "/ui-style-guide",
|
|
9824
9830
|
defaults: {
|
|
9825
9831
|
appName: "Nexus",
|
|
9826
9832
|
logo: null,
|
|
9827
9833
|
logoDark: null,
|
|
9828
|
-
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"
|
|
9829
9842
|
},
|
|
9830
9843
|
fields: {
|
|
9831
9844
|
appName: useTextField7({
|
|
9832
9845
|
label: { en: "App Name", es: "Nombre de la App" },
|
|
9833
|
-
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" },
|
|
9834
9847
|
size: 100,
|
|
9835
9848
|
required: true
|
|
9836
9849
|
}),
|
|
9837
9850
|
logo: useImageField({
|
|
9838
9851
|
label: { en: "Logo (Light Theme)", es: "Logo (Tema Claro)" },
|
|
9839
|
-
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" },
|
|
9840
9853
|
folder: "branding",
|
|
9841
9854
|
isPublic: true,
|
|
9842
9855
|
dedupe: true
|
|
9843
9856
|
}),
|
|
9844
9857
|
logoDark: useImageField({
|
|
9845
9858
|
label: { en: "Logo (Dark Theme)", es: "Logo (Tema Oscuro)" },
|
|
9846
|
-
hint: { en: "
|
|
9859
|
+
hint: { en: "Lighter version for dark backgrounds", es: "Versi\xF3n m\xE1s clara para fondos oscuros" },
|
|
9847
9860
|
folder: "branding",
|
|
9848
9861
|
isPublic: true,
|
|
9849
9862
|
dedupe: true
|
|
9850
9863
|
}),
|
|
9851
9864
|
favicon: useImageField({
|
|
9852
9865
|
label: { en: "Favicon", es: "Favicon" },
|
|
9853
|
-
hint: { en: "
|
|
9866
|
+
hint: { en: "32x32 or 64x64 PNG/ICO", es: "32x32 o 64x64 PNG/ICO" },
|
|
9854
9867
|
accept: "image/x-icon,image/png,image/svg+xml",
|
|
9855
9868
|
maxSize: "256KB",
|
|
9856
9869
|
folder: "branding",
|
|
9857
9870
|
isPublic: true,
|
|
9858
9871
|
dedupe: true
|
|
9859
|
-
})
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
ADMIN: { actions: ["read", "update"] }
|
|
9865
|
-
}
|
|
9866
|
-
}
|
|
9867
|
-
};
|
|
9868
|
-
}
|
|
9869
|
-
});
|
|
9870
|
-
|
|
9871
|
-
// src/modules/ui-settings/ui-theme.entity.ts
|
|
9872
|
-
import { useSelectField as useSelectField6, useColorField } from "@gzl10/nexus-sdk/fields";
|
|
9873
|
-
var uiThemeEntity;
|
|
9874
|
-
var init_ui_theme_entity = __esm({
|
|
9875
|
-
"src/modules/ui-settings/ui-theme.entity.ts"() {
|
|
9876
|
-
"use strict";
|
|
9877
|
-
uiThemeEntity = {
|
|
9878
|
-
type: "single",
|
|
9879
|
-
realtime: "sync",
|
|
9880
|
-
key: "ui_theme",
|
|
9881
|
-
label: { en: "Theme & Colors", es: "Tema y Colores" },
|
|
9882
|
-
icon: "mdi:palette",
|
|
9883
|
-
public: true,
|
|
9884
|
-
routePrefix: "/ui-theme",
|
|
9885
|
-
defaults: {
|
|
9886
|
-
// Typography
|
|
9887
|
-
font: "space-grotesk",
|
|
9888
|
-
// Theme & Colors
|
|
9889
|
-
theme: "system",
|
|
9890
|
-
primaryColor: "#3B82F6",
|
|
9891
|
-
dopamineTheme: "none",
|
|
9892
|
-
// Layout
|
|
9893
|
-
loginLayout: "centered"
|
|
9894
|
-
},
|
|
9895
|
-
fields: {
|
|
9896
|
-
// === 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
|
+
}),
|
|
9897
9877
|
font: useSelectField6({
|
|
9898
9878
|
label: { en: "Font", es: "Fuente" },
|
|
9899
|
-
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" },
|
|
9900
9880
|
options: [
|
|
9901
9881
|
{ value: "space-grotesk", label: "Space Grotesk" },
|
|
9902
9882
|
{ value: "inter", label: "Inter" },
|
|
@@ -9906,37 +9886,38 @@ var init_ui_theme_entity = __esm({
|
|
|
9906
9886
|
{ value: "system", label: { en: "System Default", es: "Sistema" } }
|
|
9907
9887
|
]
|
|
9908
9888
|
}),
|
|
9909
|
-
|
|
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
|
+
}),
|
|
9910
9909
|
theme: useSelectField6({
|
|
9911
9910
|
label: { en: "Theme", es: "Tema" },
|
|
9912
|
-
hint: { en: "System follows
|
|
9911
|
+
hint: { en: "System follows device preferences", es: "Sistema sigue las preferencias del dispositivo" },
|
|
9913
9912
|
options: [
|
|
9914
9913
|
{ value: "light", label: { en: "Light", es: "Claro" } },
|
|
9915
9914
|
{ value: "dark", label: { en: "Dark", es: "Oscuro" } },
|
|
9916
9915
|
{ value: "system", label: { en: "System", es: "Sistema" } }
|
|
9917
9916
|
]
|
|
9918
9917
|
}),
|
|
9919
|
-
dopamineTheme: useSelectField6({
|
|
9920
|
-
label: { en: "Dopamine Theme", es: "Tema Dopamina" },
|
|
9921
|
-
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)" },
|
|
9922
|
-
options: [
|
|
9923
|
-
{ value: "none", label: { en: "None (Custom Color)", es: "Ninguno (Color personalizado)" } },
|
|
9924
|
-
{ value: "electric", label: { en: "Electric (Cobalt Blue)", es: "El\xE9ctrico (Azul Cobalto)" } },
|
|
9925
|
-
{ value: "sunset", label: { en: "Sunset (Coral Red)", es: "Atardecer (Rojo Coral)" } },
|
|
9926
|
-
{ value: "ocean", label: { en: "Ocean (Teal)", es: "Oc\xE9ano (Verde Azulado)" } },
|
|
9927
|
-
{ value: "forest", label: { en: "Forest (Mint)", es: "Bosque (Menta)" } },
|
|
9928
|
-
{ value: "lavender", label: { en: "Lavender (Violet)", es: "Lavanda (Violeta)" } },
|
|
9929
|
-
{ value: "cherry", label: { en: "Cherry (Fuchsia)", es: "Cereza (Fucsia)" } },
|
|
9930
|
-
{ value: "amber", label: { en: "Amber (Golden)", es: "\xC1mbar (Dorado)" } },
|
|
9931
|
-
{ value: "tangerine", label: { en: "Tangerine (Orange)", es: "Mandarina (Naranja)" } },
|
|
9932
|
-
{ value: "slate", label: { en: "Slate (Cool Gray)", es: "Pizarra (Gris Fr\xEDo)" } },
|
|
9933
|
-
{ value: "bronze", label: { en: "Bronze (Earth)", es: "Bronce (Tierra)" } }
|
|
9934
|
-
]
|
|
9935
|
-
}),
|
|
9936
|
-
// === Login Layout ===
|
|
9937
9918
|
loginLayout: useSelectField6({
|
|
9938
9919
|
label: { en: "Login Layout", es: "Dise\xF1o de Login" },
|
|
9939
|
-
hint: { en: "
|
|
9920
|
+
hint: { en: "Auth page visual layout", es: "Dise\xF1o visual de p\xE1ginas de autenticaci\xF3n" },
|
|
9940
9921
|
options: [
|
|
9941
9922
|
{ value: "centered", label: { en: "Centered", es: "Centrado" } },
|
|
9942
9923
|
{ value: "split", label: { en: "Split", es: "Dividido" } },
|
|
@@ -9944,140 +9925,10 @@ var init_ui_theme_entity = __esm({
|
|
|
9944
9925
|
{ value: "floating", label: { en: "Floating", es: "Flotante" } },
|
|
9945
9926
|
{ value: "minimal", label: { en: "Minimal", es: "Minimalista" } }
|
|
9946
9927
|
]
|
|
9947
|
-
}),
|
|
9948
|
-
primaryColor: {
|
|
9949
|
-
...useColorField({
|
|
9950
|
-
label: { en: "Primary Color", es: "Color Principal" },
|
|
9951
|
-
hint: { en: "Custom accent color for buttons, links and highlights", es: "Color de acento personalizado para botones, enlaces y resaltados" }
|
|
9952
|
-
}),
|
|
9953
|
-
// Hide when a dopamine theme is active (show only if 'none')
|
|
9954
|
-
hidden: { field: "dopamineTheme", $ne: "none" }
|
|
9955
|
-
}
|
|
9956
|
-
},
|
|
9957
|
-
casl: {
|
|
9958
|
-
subject: "UiTheme",
|
|
9959
|
-
permissions: {
|
|
9960
|
-
ADMIN: { actions: ["read", "update"] }
|
|
9961
|
-
}
|
|
9962
|
-
}
|
|
9963
|
-
};
|
|
9964
|
-
}
|
|
9965
|
-
});
|
|
9966
|
-
|
|
9967
|
-
// src/modules/ui-settings/ui-effects.entity.ts
|
|
9968
|
-
import { useSelectField as useSelectField7, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
|
|
9969
|
-
var uiEffectsEntity;
|
|
9970
|
-
var init_ui_effects_entity = __esm({
|
|
9971
|
-
"src/modules/ui-settings/ui-effects.entity.ts"() {
|
|
9972
|
-
"use strict";
|
|
9973
|
-
uiEffectsEntity = {
|
|
9974
|
-
type: "single",
|
|
9975
|
-
realtime: "sync",
|
|
9976
|
-
key: "ui_effects",
|
|
9977
|
-
label: { en: "Visual Effects", es: "Efectos Visuales" },
|
|
9978
|
-
icon: "mdi:shimmer",
|
|
9979
|
-
public: true,
|
|
9980
|
-
routePrefix: "/ui-effects",
|
|
9981
|
-
defaults: {
|
|
9982
|
-
glassIntensity: "medium",
|
|
9983
|
-
borderStyle: "rounded",
|
|
9984
|
-
enableAnimations: true,
|
|
9985
|
-
enableOrganicShapes: false
|
|
9986
|
-
},
|
|
9987
|
-
fields: {
|
|
9988
|
-
glassIntensity: useSelectField7({
|
|
9989
|
-
label: { en: "Glass Intensity", es: "Intensidad Glass" },
|
|
9990
|
-
hint: { en: "Glassmorphism blur effect on cards and modals", es: "Efecto de desenfoque glassmorphism en cards y modales" },
|
|
9991
|
-
options: [
|
|
9992
|
-
{ value: "none", label: { en: "None", es: "Ninguno" } },
|
|
9993
|
-
{ value: "low", label: { en: "Low", es: "Baja" } },
|
|
9994
|
-
{ value: "medium", label: { en: "Medium", es: "Media" } },
|
|
9995
|
-
{ value: "high", label: { en: "High", es: "Alta" } }
|
|
9996
|
-
]
|
|
9997
|
-
}),
|
|
9998
|
-
borderStyle: useSelectField7({
|
|
9999
|
-
label: { en: "Border Style", es: "Estilo de Bordes" },
|
|
10000
|
-
hint: { en: "Corner radius for buttons, cards and inputs", es: "Radio de esquinas para botones, cards e inputs" },
|
|
10001
|
-
options: [
|
|
10002
|
-
{ value: "sharp", label: { en: "Sharp", es: "Cuadrados" } },
|
|
10003
|
-
{ value: "rounded", label: { en: "Rounded", es: "Redondeados" } },
|
|
10004
|
-
{ value: "organic", label: { en: "Organic", es: "Org\xE1nicos" } }
|
|
10005
|
-
]
|
|
10006
|
-
}),
|
|
10007
|
-
enableAnimations: useSwitchField2({
|
|
10008
|
-
label: { en: "Enable Animations", es: "Habilitar Animaciones" },
|
|
10009
|
-
hint: { en: "Micro-interactions and transitions (hover, focus, page changes)", es: "Micro-interacciones y transiciones (hover, focus, cambios de p\xE1gina)" },
|
|
10010
|
-
defaultValue: true,
|
|
10011
|
-
meta: { sortable: true }
|
|
10012
|
-
}),
|
|
10013
|
-
enableOrganicShapes: useSwitchField2({
|
|
10014
|
-
label: { en: "Enable Organic Shapes", es: "Habilitar Formas Org\xE1nicas" },
|
|
10015
|
-
hint: { en: "Asymmetric border-radius for a more natural, playful look", es: "Border-radius asim\xE9trico para un aspecto m\xE1s natural y divertido" },
|
|
10016
|
-
defaultValue: false,
|
|
10017
|
-
meta: { sortable: true },
|
|
10018
|
-
hidden: { field: "borderStyle", $ne: "organic" }
|
|
10019
|
-
})
|
|
10020
|
-
},
|
|
10021
|
-
casl: {
|
|
10022
|
-
subject: "UiEffects",
|
|
10023
|
-
permissions: {
|
|
10024
|
-
ADMIN: { actions: ["read", "update"] }
|
|
10025
|
-
}
|
|
10026
|
-
}
|
|
10027
|
-
};
|
|
10028
|
-
}
|
|
10029
|
-
});
|
|
10030
|
-
|
|
10031
|
-
// src/modules/ui-settings/ui-accessibility.entity.ts
|
|
10032
|
-
import { useSelectField as useSelectField8, useSwitchField as useSwitchField3 } from "@gzl10/nexus-sdk/fields";
|
|
10033
|
-
var uiAccessibilityEntity;
|
|
10034
|
-
var init_ui_accessibility_entity = __esm({
|
|
10035
|
-
"src/modules/ui-settings/ui-accessibility.entity.ts"() {
|
|
10036
|
-
"use strict";
|
|
10037
|
-
uiAccessibilityEntity = {
|
|
10038
|
-
type: "single",
|
|
10039
|
-
realtime: "sync",
|
|
10040
|
-
key: "ui_accessibility",
|
|
10041
|
-
label: { en: "Accessibility", es: "Accesibilidad" },
|
|
10042
|
-
icon: "mdi:human",
|
|
10043
|
-
public: true,
|
|
10044
|
-
routePrefix: "/ui-accessibility",
|
|
10045
|
-
defaults: {
|
|
10046
|
-
typographyScale: "default",
|
|
10047
|
-
reducedMotion: false,
|
|
10048
|
-
highContrast: false
|
|
10049
|
-
},
|
|
10050
|
-
fields: {
|
|
10051
|
-
typographyScale: useSelectField8({
|
|
10052
|
-
label: { en: "Typography Scale", es: "Escala Tipogr\xE1fica" },
|
|
10053
|
-
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)" },
|
|
10054
|
-
options: [
|
|
10055
|
-
{ value: "compact", label: { en: "Compact (smaller)", es: "Compacta (m\xE1s peque\xF1a)" } },
|
|
10056
|
-
{ value: "default", label: { en: "Default", es: "Por defecto" } },
|
|
10057
|
-
{ value: "relaxed", label: { en: "Relaxed (larger)", es: "Relajada (m\xE1s grande)" } }
|
|
10058
|
-
]
|
|
10059
|
-
}),
|
|
10060
|
-
reducedMotion: useSwitchField3({
|
|
10061
|
-
label: { en: "Reduced Motion", es: "Movimiento Reducido" },
|
|
10062
|
-
defaultValue: false,
|
|
10063
|
-
meta: { sortable: true },
|
|
10064
|
-
hint: {
|
|
10065
|
-
en: "Minimizes animations for users sensitive to motion (WCAG 2.1)",
|
|
10066
|
-
es: "Minimiza animaciones para usuarios sensibles al movimiento (WCAG 2.1)"
|
|
10067
|
-
}
|
|
10068
|
-
}),
|
|
10069
|
-
highContrast: useSwitchField3({
|
|
10070
|
-
label: { en: "High Contrast", es: "Alto Contraste" },
|
|
10071
|
-
defaultValue: false,
|
|
10072
|
-
meta: { sortable: true },
|
|
10073
|
-
hint: {
|
|
10074
|
-
en: "Increases text contrast for better readability (WCAG AAA)",
|
|
10075
|
-
es: "Aumenta el contraste del texto para mejor legibilidad (WCAG AAA)"
|
|
10076
|
-
}
|
|
10077
9928
|
})
|
|
10078
9929
|
},
|
|
10079
9930
|
casl: {
|
|
10080
|
-
subject: "
|
|
9931
|
+
subject: "UiStyleGuide",
|
|
10081
9932
|
permissions: {
|
|
10082
9933
|
ADMIN: { actions: ["read", "update"] }
|
|
10083
9934
|
}
|
|
@@ -10087,44 +9938,62 @@ var init_ui_accessibility_entity = __esm({
|
|
|
10087
9938
|
});
|
|
10088
9939
|
|
|
10089
9940
|
// src/modules/ui-settings/index.ts
|
|
9941
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
9942
|
+
import { join as join9 } from "path";
|
|
10090
9943
|
var uiSettingsModule;
|
|
10091
9944
|
var init_ui_settings = __esm({
|
|
10092
9945
|
"src/modules/ui-settings/index.ts"() {
|
|
10093
9946
|
"use strict";
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
init_ui_effects_entity();
|
|
10097
|
-
init_ui_accessibility_entity();
|
|
10098
|
-
init_ui_branding_entity();
|
|
10099
|
-
init_ui_theme_entity();
|
|
10100
|
-
init_ui_effects_entity();
|
|
10101
|
-
init_ui_accessibility_entity();
|
|
9947
|
+
init_ui_style_guide_entity();
|
|
9948
|
+
init_ui_style_guide_entity();
|
|
10102
9949
|
uiSettingsModule = {
|
|
10103
9950
|
name: "ui-settings",
|
|
10104
|
-
label: { en: "
|
|
9951
|
+
label: { en: "Style Guide", es: "Gu\xEDa de Estilos" },
|
|
10105
9952
|
icon: "mdi:palette-outline",
|
|
10106
9953
|
description: {
|
|
10107
|
-
en: "
|
|
10108
|
-
es: "Configuraci\xF3n de
|
|
9954
|
+
en: "Brand identity and visual style configuration",
|
|
9955
|
+
es: "Configuraci\xF3n de identidad de marca y estilo visual"
|
|
10109
9956
|
},
|
|
10110
9957
|
type: "core",
|
|
10111
9958
|
category: "settings",
|
|
10112
9959
|
dependencies: ["logger"],
|
|
10113
|
-
definitions: [
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
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
|
+
}
|
|
10120
9989
|
};
|
|
10121
9990
|
}
|
|
10122
9991
|
});
|
|
10123
9992
|
|
|
10124
9993
|
// src/modules/storage/drivers/filesystem.driver.ts
|
|
10125
|
-
import { createReadStream, createWriteStream, existsSync as
|
|
9994
|
+
import { createReadStream, createWriteStream, existsSync as existsSync7, unlinkSync, mkdirSync as mkdirSync3 } from "fs";
|
|
10126
9995
|
import { readFile, readdir, stat, copyFile, rename, mkdir } from "fs/promises";
|
|
10127
|
-
import { join as
|
|
9996
|
+
import { join as join10, dirname as dirname6, extname, basename } from "path";
|
|
10128
9997
|
import { createHash } from "crypto";
|
|
10129
9998
|
var FilesystemDriver;
|
|
10130
9999
|
var init_filesystem_driver = __esm({
|
|
@@ -10138,7 +10007,7 @@ var init_filesystem_driver = __esm({
|
|
|
10138
10007
|
this.basePath = config3.basePath;
|
|
10139
10008
|
this.baseUrl = config3.baseUrl;
|
|
10140
10009
|
this.generateId = config3.generateId;
|
|
10141
|
-
if (!
|
|
10010
|
+
if (!existsSync7(this.basePath)) {
|
|
10142
10011
|
mkdirSync3(this.basePath, { recursive: true });
|
|
10143
10012
|
}
|
|
10144
10013
|
}
|
|
@@ -10148,9 +10017,9 @@ var init_filesystem_driver = __esm({
|
|
|
10148
10017
|
const diskFilename = `${id}${ext}`;
|
|
10149
10018
|
const folder = options?.folder || "";
|
|
10150
10019
|
const relativePath = folder ? `${folder}/${diskFilename}` : diskFilename;
|
|
10151
|
-
const fullPath =
|
|
10020
|
+
const fullPath = join10(this.basePath, relativePath);
|
|
10152
10021
|
const dir = dirname6(fullPath);
|
|
10153
|
-
if (!
|
|
10022
|
+
if (!existsSync7(dir)) {
|
|
10154
10023
|
mkdirSync3(dir, { recursive: true });
|
|
10155
10024
|
}
|
|
10156
10025
|
const hash = createHash("sha256").update(buffer).digest("hex");
|
|
@@ -10174,25 +10043,25 @@ var init_filesystem_driver = __esm({
|
|
|
10174
10043
|
};
|
|
10175
10044
|
}
|
|
10176
10045
|
async get(path3) {
|
|
10177
|
-
const fullPath =
|
|
10178
|
-
if (!
|
|
10046
|
+
const fullPath = join10(this.basePath, path3);
|
|
10047
|
+
if (!existsSync7(fullPath)) {
|
|
10179
10048
|
throw new Error(`File not found: ${path3}`);
|
|
10180
10049
|
}
|
|
10181
10050
|
return createReadStream(fullPath);
|
|
10182
10051
|
}
|
|
10183
10052
|
async getBuffer(path3) {
|
|
10184
|
-
const fullPath =
|
|
10053
|
+
const fullPath = join10(this.basePath, path3);
|
|
10185
10054
|
return readFile(fullPath);
|
|
10186
10055
|
}
|
|
10187
10056
|
async delete(path3) {
|
|
10188
|
-
const fullPath =
|
|
10189
|
-
if (
|
|
10057
|
+
const fullPath = join10(this.basePath, path3);
|
|
10058
|
+
if (existsSync7(fullPath)) {
|
|
10190
10059
|
unlinkSync(fullPath);
|
|
10191
10060
|
}
|
|
10192
10061
|
}
|
|
10193
10062
|
async exists(path3) {
|
|
10194
|
-
const fullPath =
|
|
10195
|
-
return
|
|
10063
|
+
const fullPath = join10(this.basePath, path3);
|
|
10064
|
+
return existsSync7(fullPath);
|
|
10196
10065
|
}
|
|
10197
10066
|
getUrl(path3) {
|
|
10198
10067
|
if (!this.baseUrl) return null;
|
|
@@ -10202,14 +10071,14 @@ var init_filesystem_driver = __esm({
|
|
|
10202
10071
|
// EXTENDED METHODS
|
|
10203
10072
|
// ============================================================================
|
|
10204
10073
|
async list(folder) {
|
|
10205
|
-
const targetPath = folder ?
|
|
10206
|
-
if (!
|
|
10074
|
+
const targetPath = folder ? join10(this.basePath, folder) : this.basePath;
|
|
10075
|
+
if (!existsSync7(targetPath)) {
|
|
10207
10076
|
return [];
|
|
10208
10077
|
}
|
|
10209
10078
|
const entries = await readdir(targetPath, { withFileTypes: true });
|
|
10210
10079
|
const results = [];
|
|
10211
10080
|
for (const entry of entries) {
|
|
10212
|
-
const entryPath =
|
|
10081
|
+
const entryPath = join10(targetPath, entry.name);
|
|
10213
10082
|
const relativePath = folder ? `${folder}/${entry.name}` : entry.name;
|
|
10214
10083
|
const stats = await stat(entryPath);
|
|
10215
10084
|
results.push({
|
|
@@ -10223,10 +10092,10 @@ var init_filesystem_driver = __esm({
|
|
|
10223
10092
|
return results;
|
|
10224
10093
|
}
|
|
10225
10094
|
async copy(src, dst) {
|
|
10226
|
-
const srcPath =
|
|
10227
|
-
const dstPath =
|
|
10095
|
+
const srcPath = join10(this.basePath, src);
|
|
10096
|
+
const dstPath = join10(this.basePath, dst);
|
|
10228
10097
|
const dstDir = dirname6(dstPath);
|
|
10229
|
-
if (!
|
|
10098
|
+
if (!existsSync7(dstDir)) {
|
|
10230
10099
|
await mkdir(dstDir, { recursive: true });
|
|
10231
10100
|
}
|
|
10232
10101
|
await copyFile(srcPath, dstPath);
|
|
@@ -10249,10 +10118,10 @@ var init_filesystem_driver = __esm({
|
|
|
10249
10118
|
};
|
|
10250
10119
|
}
|
|
10251
10120
|
async move(src, dst) {
|
|
10252
|
-
const srcPath =
|
|
10253
|
-
const dstPath =
|
|
10121
|
+
const srcPath = join10(this.basePath, src);
|
|
10122
|
+
const dstPath = join10(this.basePath, dst);
|
|
10254
10123
|
const dstDir = dirname6(dstPath);
|
|
10255
|
-
if (!
|
|
10124
|
+
if (!existsSync7(dstDir)) {
|
|
10256
10125
|
await mkdir(dstDir, { recursive: true });
|
|
10257
10126
|
}
|
|
10258
10127
|
await rename(srcPath, dstPath);
|
|
@@ -10275,7 +10144,7 @@ var init_filesystem_driver = __esm({
|
|
|
10275
10144
|
};
|
|
10276
10145
|
}
|
|
10277
10146
|
async getMetadata(path3) {
|
|
10278
|
-
const fullPath =
|
|
10147
|
+
const fullPath = join10(this.basePath, path3);
|
|
10279
10148
|
const stats = await stat(fullPath);
|
|
10280
10149
|
return {
|
|
10281
10150
|
path: path3,
|
|
@@ -10289,8 +10158,8 @@ var init_filesystem_driver = __esm({
|
|
|
10289
10158
|
throw new Error("Signed URLs are not supported by the filesystem driver");
|
|
10290
10159
|
}
|
|
10291
10160
|
async createFolder(path3) {
|
|
10292
|
-
const fullPath =
|
|
10293
|
-
if (!
|
|
10161
|
+
const fullPath = join10(this.basePath, path3);
|
|
10162
|
+
if (!existsSync7(fullPath)) {
|
|
10294
10163
|
await mkdir(fullPath, { recursive: true });
|
|
10295
10164
|
}
|
|
10296
10165
|
}
|
|
@@ -10521,8 +10390,8 @@ var init_s3_driver = __esm({
|
|
|
10521
10390
|
});
|
|
10522
10391
|
|
|
10523
10392
|
// src/modules/storage/storage.config.ts
|
|
10524
|
-
import { join as
|
|
10525
|
-
import { existsSync as
|
|
10393
|
+
import { join as join11, isAbsolute as isAbsolute2 } from "path";
|
|
10394
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
10526
10395
|
function getDefaultScope(driver) {
|
|
10527
10396
|
return driver === "s3" ? DEFAULT_S3_SCOPE : DEFAULT_FILESYSTEM_SCOPE;
|
|
10528
10397
|
}
|
|
@@ -10537,7 +10406,7 @@ function resolveStoragePath(path3, projPath) {
|
|
|
10537
10406
|
return path3;
|
|
10538
10407
|
}
|
|
10539
10408
|
const cleanPath = path3.startsWith("./") ? path3.slice(2) : path3;
|
|
10540
|
-
return
|
|
10409
|
+
return join11(projPath, "data", cleanPath);
|
|
10541
10410
|
}
|
|
10542
10411
|
async function getConfigByScope(db3, scope) {
|
|
10543
10412
|
if (!generateIdFn) {
|
|
@@ -10568,7 +10437,7 @@ function buildConfigFromRow(row) {
|
|
|
10568
10437
|
if (row.driver === "filesystem") {
|
|
10569
10438
|
const fsMeta = metadata;
|
|
10570
10439
|
config3.basePath = resolveStoragePath(fsMeta.basePath || "./storage", projectPath);
|
|
10571
|
-
if (!
|
|
10440
|
+
if (!existsSync8(config3.basePath)) {
|
|
10572
10441
|
mkdirSync4(config3.basePath, { recursive: true });
|
|
10573
10442
|
}
|
|
10574
10443
|
} else if (row.driver === "s3") {
|
|
@@ -10600,7 +10469,7 @@ function buildConfigFromEnv(driver) {
|
|
|
10600
10469
|
if (driver === "filesystem") {
|
|
10601
10470
|
const rawPath = process.env["STORAGE_PATH"] || "./storage";
|
|
10602
10471
|
config3.basePath = resolveStoragePath(rawPath, projectPath);
|
|
10603
|
-
if (!
|
|
10472
|
+
if (!existsSync8(config3.basePath)) {
|
|
10604
10473
|
mkdirSync4(config3.basePath, { recursive: true });
|
|
10605
10474
|
}
|
|
10606
10475
|
} else if (driver === "s3") {
|
|
@@ -11039,7 +10908,7 @@ var init_storage_service = __esm({
|
|
|
11039
10908
|
});
|
|
11040
10909
|
|
|
11041
10910
|
// src/modules/storage/storage.entity.ts
|
|
11042
|
-
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";
|
|
11043
10912
|
var DEFAULT_MAX_SIZE2, storageConfigEntity, storageFilesEntity;
|
|
11044
10913
|
var init_storage_entity = __esm({
|
|
11045
10914
|
"src/modules/storage/storage.entity.ts"() {
|
|
@@ -11074,7 +10943,7 @@ var init_storage_entity = __esm({
|
|
|
11074
10943
|
hint: { en: "Unique identifier (e.g. default_filesystem, default_s3)", es: "Identificador \xFAnico (ej: default_filesystem, default_s3)" }
|
|
11075
10944
|
}),
|
|
11076
10945
|
driver: {
|
|
11077
|
-
...
|
|
10946
|
+
...useSelectField7({
|
|
11078
10947
|
label: { en: "Driver", es: "Controlador" },
|
|
11079
10948
|
required: true,
|
|
11080
10949
|
hint: { en: "Storage backend", es: "Backend de almacenamiento" },
|
|
@@ -11091,7 +10960,7 @@ var init_storage_entity = __esm({
|
|
|
11091
10960
|
size: 500,
|
|
11092
10961
|
nullable: true
|
|
11093
10962
|
}),
|
|
11094
|
-
max_file_size:
|
|
10963
|
+
max_file_size: useNumberField5({
|
|
11095
10964
|
label: { en: "Max File Size (bytes)", es: "Tama\xF1o m\xE1ximo de archivo (bytes)" },
|
|
11096
10965
|
hint: { en: "Maximum size in bytes (default: 10MB = 10485760)", es: "Tama\xF1o m\xE1ximo en bytes (default: 10MB = 10485760)" },
|
|
11097
10966
|
nullable: false,
|
|
@@ -11284,7 +11153,7 @@ var init_storage_entity = __esm({
|
|
|
11284
11153
|
index: true,
|
|
11285
11154
|
meta: { sortable: true, searchable: true }
|
|
11286
11155
|
}),
|
|
11287
|
-
size:
|
|
11156
|
+
size: useNumberField5({
|
|
11288
11157
|
label: { en: "Size", es: "Tama\xF1o" },
|
|
11289
11158
|
required: true,
|
|
11290
11159
|
nullable: false,
|
|
@@ -11826,7 +11695,7 @@ var init_storage = __esm({
|
|
|
11826
11695
|
});
|
|
11827
11696
|
|
|
11828
11697
|
// src/modules/users/users.entity.ts
|
|
11829
|
-
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";
|
|
11830
11699
|
import { z as z3 } from "zod";
|
|
11831
11700
|
var userEntity, roleEntity, userRoleEntity;
|
|
11832
11701
|
var init_users_entity = __esm({
|
|
@@ -11900,7 +11769,7 @@ var init_users_entity = __esm({
|
|
|
11900
11769
|
label: { en: "Marketing Opt-in", es: "Aceptar marketing" },
|
|
11901
11770
|
meta: { exportable: true, showInForm: false, showInDisplay: false }
|
|
11902
11771
|
}),
|
|
11903
|
-
locale:
|
|
11772
|
+
locale: useSelectField8({
|
|
11904
11773
|
label: { en: "Language", es: "Idioma" },
|
|
11905
11774
|
options: [
|
|
11906
11775
|
{ value: "es", label: { en: "Spanish", es: "Espa\xF1ol" } },
|
|
@@ -11910,13 +11779,13 @@ var init_users_entity = __esm({
|
|
|
11910
11779
|
meta: { sortable: true },
|
|
11911
11780
|
defaultValue: "en"
|
|
11912
11781
|
}),
|
|
11913
|
-
timezone:
|
|
11782
|
+
timezone: useSelectField8({
|
|
11914
11783
|
label: { en: "Timezone", es: "Zona horaria" },
|
|
11915
11784
|
master: "timezones",
|
|
11916
11785
|
meta: { sortable: true },
|
|
11917
11786
|
defaultValue: "timezones:Europe/Madrid"
|
|
11918
11787
|
}),
|
|
11919
|
-
type:
|
|
11788
|
+
type: useSelectField8({
|
|
11920
11789
|
label: { en: "Type", es: "Tipo" },
|
|
11921
11790
|
defaultValue: "human",
|
|
11922
11791
|
options: [
|
|
@@ -12085,7 +11954,7 @@ var init_users_entity = __esm({
|
|
|
12085
11954
|
expose: false,
|
|
12086
11955
|
fields: {
|
|
12087
11956
|
id: useIdField4(),
|
|
12088
|
-
user_id:
|
|
11957
|
+
user_id: useSelectField8({
|
|
12089
11958
|
label: { en: "User", es: "Usuario" },
|
|
12090
11959
|
required: true,
|
|
12091
11960
|
table: "users",
|
|
@@ -12096,7 +11965,7 @@ var init_users_entity = __esm({
|
|
|
12096
11965
|
labelField: "name",
|
|
12097
11966
|
meta: { searchable: true }
|
|
12098
11967
|
}),
|
|
12099
|
-
role_id:
|
|
11968
|
+
role_id: useSelectField8({
|
|
12100
11969
|
label: { en: "Role", es: "Rol" },
|
|
12101
11970
|
required: true,
|
|
12102
11971
|
table: "roles",
|
|
@@ -13040,7 +12909,7 @@ var init_users = __esm({
|
|
|
13040
12909
|
});
|
|
13041
12910
|
|
|
13042
12911
|
// src/modules/auth/auth.entity.ts
|
|
13043
|
-
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";
|
|
13044
12913
|
var refreshTokenEntity, authIdentitiesEntity;
|
|
13045
12914
|
var init_auth_entity = __esm({
|
|
13046
12915
|
"src/modules/auth/auth.entity.ts"() {
|
|
@@ -13121,7 +12990,7 @@ var init_auth_entity = __esm({
|
|
|
13121
12990
|
order: 5,
|
|
13122
12991
|
fields: {
|
|
13123
12992
|
id: useIdField5(),
|
|
13124
|
-
user_id:
|
|
12993
|
+
user_id: useSelectField9({
|
|
13125
12994
|
label: { en: "User", es: "Usuario" },
|
|
13126
12995
|
table: "users",
|
|
13127
12996
|
column: "id",
|
|
@@ -13205,6 +13074,28 @@ var init_auth_routes = __esm({
|
|
|
13205
13074
|
}
|
|
13206
13075
|
});
|
|
13207
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
|
+
|
|
13208
13099
|
// src/modules/auth/auth.config.ts
|
|
13209
13100
|
import { z as z5 } from "zod";
|
|
13210
13101
|
function configError(module, errors) {
|
|
@@ -13221,12 +13112,6 @@ function parseAuthEnv() {
|
|
|
13221
13112
|
if (!result.success) {
|
|
13222
13113
|
const errors = result.error.issues.map((issue) => {
|
|
13223
13114
|
const path3 = issue.path.join(".");
|
|
13224
|
-
if (path3 === "AUTH_SECRET" && issue.code === "invalid_type") {
|
|
13225
|
-
return "AUTH_SECRET is required. Set it in your .env file or environment.";
|
|
13226
|
-
}
|
|
13227
|
-
if (path3 === "AUTH_SECRET" && issue.code === "too_small") {
|
|
13228
|
-
return `AUTH_SECRET must be at least 32 characters (current: ${String(process.env["AUTH_SECRET"]).length})`;
|
|
13229
|
-
}
|
|
13230
13115
|
return `${path3}: ${issue.message}`;
|
|
13231
13116
|
});
|
|
13232
13117
|
configError("auth", errors);
|
|
@@ -13245,7 +13130,7 @@ function getAuthEnv() {
|
|
|
13245
13130
|
function getAuthConfig() {
|
|
13246
13131
|
const authEnv = getAuthEnv();
|
|
13247
13132
|
return {
|
|
13248
|
-
secret:
|
|
13133
|
+
secret: getAuthSecret(),
|
|
13249
13134
|
accessExpires: authEnv.AUTH_ACCESS_EXPIRES,
|
|
13250
13135
|
refreshExpires: authEnv.AUTH_REFRESH_EXPIRES,
|
|
13251
13136
|
rateLimitMax: authEnv.AUTH_RATE_LIMIT_MAX,
|
|
@@ -13262,8 +13147,8 @@ var authEnvSchema, _authEnv;
|
|
|
13262
13147
|
var init_auth_config = __esm({
|
|
13263
13148
|
"src/modules/auth/auth.config.ts"() {
|
|
13264
13149
|
"use strict";
|
|
13150
|
+
init_secret_resolver();
|
|
13265
13151
|
authEnvSchema = z5.object({
|
|
13266
|
-
AUTH_SECRET: z5.string().min(32, "AUTH_SECRET must be at least 32 characters"),
|
|
13267
13152
|
AUTH_ACCESS_EXPIRES: z5.string().default("15m"),
|
|
13268
13153
|
AUTH_REFRESH_EXPIRES: z5.string().default("7d"),
|
|
13269
13154
|
// Rate limiting (default: 5 requests per 15 minutes)
|
|
@@ -13437,7 +13322,7 @@ var init_auth_middleware = __esm({
|
|
|
13437
13322
|
});
|
|
13438
13323
|
|
|
13439
13324
|
// src/modules/auth/auth.pat.entity.ts
|
|
13440
|
-
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";
|
|
13441
13326
|
var personalTokenEntity;
|
|
13442
13327
|
var init_auth_pat_entity = __esm({
|
|
13443
13328
|
"src/modules/auth/auth.pat.entity.ts"() {
|
|
@@ -13454,7 +13339,7 @@ var init_auth_pat_entity = __esm({
|
|
|
13454
13339
|
routePrefix: "/personal-tokens",
|
|
13455
13340
|
fields: {
|
|
13456
13341
|
id: useIdField6(),
|
|
13457
|
-
user_id:
|
|
13342
|
+
user_id: useSelectField10({
|
|
13458
13343
|
label: { en: "User", es: "Usuario" },
|
|
13459
13344
|
table: "users",
|
|
13460
13345
|
column: "id",
|
|
@@ -13489,7 +13374,7 @@ var init_auth_pat_entity = __esm({
|
|
|
13489
13374
|
unique: true,
|
|
13490
13375
|
meta: { exportable: false }
|
|
13491
13376
|
}),
|
|
13492
|
-
scope:
|
|
13377
|
+
scope: useSelectField10({
|
|
13493
13378
|
label: { en: "Permission", es: "Permiso" },
|
|
13494
13379
|
required: true,
|
|
13495
13380
|
options: [
|
|
@@ -13521,42 +13406,6 @@ var init_auth_pat_entity = __esm({
|
|
|
13521
13406
|
}
|
|
13522
13407
|
});
|
|
13523
13408
|
|
|
13524
|
-
// src/modules/auth/actions/providers.action.ts
|
|
13525
|
-
var providersAction;
|
|
13526
|
-
var init_providers_action = __esm({
|
|
13527
|
-
"src/modules/auth/actions/providers.action.ts"() {
|
|
13528
|
-
"use strict";
|
|
13529
|
-
init_auth_config();
|
|
13530
|
-
providersAction = {
|
|
13531
|
-
key: "providers",
|
|
13532
|
-
label: { en: "Get Auth Providers", es: "Obtener proveedores de autenticaci\xF3n" },
|
|
13533
|
-
icon: "mdi:account-key",
|
|
13534
|
-
scope: "module",
|
|
13535
|
-
hidden: true,
|
|
13536
|
-
method: "GET",
|
|
13537
|
-
skipAuth: true,
|
|
13538
|
-
handler: async (ctx) => {
|
|
13539
|
-
const providerServices = ctx.services.getBySuffix(".provider");
|
|
13540
|
-
const results = await Promise.all(
|
|
13541
|
-
providerServices.map(async ({ service }) => {
|
|
13542
|
-
try {
|
|
13543
|
-
return await service.getInfo();
|
|
13544
|
-
} catch {
|
|
13545
|
-
return null;
|
|
13546
|
-
}
|
|
13547
|
-
})
|
|
13548
|
-
);
|
|
13549
|
-
const providers = results.filter((info) => info !== null);
|
|
13550
|
-
const config3 = getAuthConfig();
|
|
13551
|
-
return {
|
|
13552
|
-
providers,
|
|
13553
|
-
registrationEnabled: !config3.disableRegistration
|
|
13554
|
-
};
|
|
13555
|
-
}
|
|
13556
|
-
};
|
|
13557
|
-
}
|
|
13558
|
-
});
|
|
13559
|
-
|
|
13560
13409
|
// src/modules/auth/actions/helpers.ts
|
|
13561
13410
|
function getCookieOptions(req) {
|
|
13562
13411
|
const config3 = getAuthConfig();
|
|
@@ -14113,7 +13962,6 @@ var authActions;
|
|
|
14113
13962
|
var init_actions2 = __esm({
|
|
14114
13963
|
"src/modules/auth/actions/index.ts"() {
|
|
14115
13964
|
"use strict";
|
|
14116
|
-
init_providers_action();
|
|
14117
13965
|
init_login_action();
|
|
14118
13966
|
init_register_action();
|
|
14119
13967
|
init_forgot_password_action();
|
|
@@ -14129,7 +13977,6 @@ var init_actions2 = __esm({
|
|
|
14129
13977
|
init_list_tokens_action();
|
|
14130
13978
|
init_revoke_token_action();
|
|
14131
13979
|
init_impersonate_action();
|
|
14132
|
-
init_providers_action();
|
|
14133
13980
|
init_login_action();
|
|
14134
13981
|
init_register_action();
|
|
14135
13982
|
init_forgot_password_action();
|
|
@@ -14145,7 +13992,6 @@ var init_actions2 = __esm({
|
|
|
14145
13992
|
init_list_tokens_action();
|
|
14146
13993
|
init_revoke_token_action();
|
|
14147
13994
|
authActions = [
|
|
14148
|
-
providersAction,
|
|
14149
13995
|
loginAction,
|
|
14150
13996
|
registerAction,
|
|
14151
13997
|
forgotPasswordAction,
|
|
@@ -14364,7 +14210,7 @@ var init_otp_manager = __esm({
|
|
|
14364
14210
|
});
|
|
14365
14211
|
|
|
14366
14212
|
// src/modules/auth/auth.service.ts
|
|
14367
|
-
import { createHash as createHash4, randomBytes } from "crypto";
|
|
14213
|
+
import { createHash as createHash4, randomBytes as randomBytes2 } from "crypto";
|
|
14368
14214
|
function createAuthService(ctx) {
|
|
14369
14215
|
const { errors, abilities, crypto: crypto3 } = ctx.core;
|
|
14370
14216
|
const { generateId: generateId2 } = ctx.core;
|
|
@@ -14781,7 +14627,7 @@ function createAuthService(ctx) {
|
|
|
14781
14627
|
},
|
|
14782
14628
|
// === Personal Access Tokens ===
|
|
14783
14629
|
async createPersonalToken(userId, input, requestInfo) {
|
|
14784
|
-
const rawToken = "nxs_" +
|
|
14630
|
+
const rawToken = "nxs_" + randomBytes2(32).toString("hex");
|
|
14785
14631
|
const tokenHash = createHash4("sha256").update(rawToken).digest("hex");
|
|
14786
14632
|
const tokenPrefix = "nxs_..." + rawToken.slice(-6);
|
|
14787
14633
|
const id = generateId2();
|
|
@@ -15117,8 +14963,8 @@ var init_mail_config = __esm({
|
|
|
15117
14963
|
|
|
15118
14964
|
// src/modules/mail/mail.service.ts
|
|
15119
14965
|
import nodemailer from "nodemailer";
|
|
15120
|
-
import { readFileSync as
|
|
15121
|
-
import { join as
|
|
14966
|
+
import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
|
|
14967
|
+
import { join as join12 } from "path";
|
|
15122
14968
|
function getMailService() {
|
|
15123
14969
|
if (!mailServiceInstance) {
|
|
15124
14970
|
throw new Error("MailService not initialized. Call initMailService() first.");
|
|
@@ -15135,8 +14981,8 @@ var init_mail_service = __esm({
|
|
|
15135
14981
|
"src/modules/mail/mail.service.ts"() {
|
|
15136
14982
|
"use strict";
|
|
15137
14983
|
init_mail_config();
|
|
15138
|
-
TEMPLATE_REL_PATH =
|
|
15139
|
-
LOGO_REL_PATH =
|
|
14984
|
+
TEMPLATE_REL_PATH = join12("public", "mail", "base.html");
|
|
14985
|
+
LOGO_REL_PATH = join12("public", "nexus", "nexus-light-512.png");
|
|
15140
14986
|
mailServiceInstance = null;
|
|
15141
14987
|
MailService = class {
|
|
15142
14988
|
transporter;
|
|
@@ -15150,10 +14996,10 @@ var init_mail_service = __esm({
|
|
|
15150
14996
|
this.logger = logger3.child({ service: "mail" });
|
|
15151
14997
|
this.loggerService = loggerService;
|
|
15152
14998
|
const libPath = options?.libPath ?? process.cwd();
|
|
15153
|
-
this.template =
|
|
15154
|
-
const logoPath =
|
|
15155
|
-
if (
|
|
15156
|
-
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");
|
|
15157
15003
|
this.defaultLogoUrl = `data:image/png;base64,${logoBase64}`;
|
|
15158
15004
|
} else {
|
|
15159
15005
|
this.defaultLogoUrl = "";
|
|
@@ -15245,7 +15091,7 @@ var init_mail_service = __esm({
|
|
|
15245
15091
|
});
|
|
15246
15092
|
|
|
15247
15093
|
// src/modules/mail/mail.entity.ts
|
|
15248
|
-
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";
|
|
15249
15095
|
import nodemailer2 from "nodemailer";
|
|
15250
15096
|
async function getMailConfigFromDB(ctx) {
|
|
15251
15097
|
const configService = ctx.services["config"];
|
|
@@ -15314,12 +15160,12 @@ var init_mail_entity = __esm({
|
|
|
15314
15160
|
nullable: false,
|
|
15315
15161
|
hint: { en: "Default: SMTP_HOST env var", es: "Por defecto: variable SMTP_HOST" }
|
|
15316
15162
|
}),
|
|
15317
|
-
port:
|
|
15163
|
+
port: useNumberField6({
|
|
15318
15164
|
label: { en: "Port", es: "Puerto" },
|
|
15319
15165
|
nullable: false,
|
|
15320
15166
|
hint: { en: "Default: SMTP_PORT env var", es: "Por defecto: variable SMTP_PORT" }
|
|
15321
15167
|
}),
|
|
15322
|
-
secure:
|
|
15168
|
+
secure: useSwitchField3({
|
|
15323
15169
|
label: { en: "TLS/SSL", es: "TLS/SSL" },
|
|
15324
15170
|
hint: { en: "Default: SMTP_SECURE env var", es: "Por defecto: variable SMTP_SECURE" }
|
|
15325
15171
|
}),
|
|
@@ -15522,7 +15368,7 @@ var init_mail_entity = __esm({
|
|
|
15522
15368
|
meta: { searchable: true, sortable: true }
|
|
15523
15369
|
}),
|
|
15524
15370
|
status: {
|
|
15525
|
-
...
|
|
15371
|
+
...useSelectField11({
|
|
15526
15372
|
label: { en: "Status", es: "Estado" },
|
|
15527
15373
|
options: [
|
|
15528
15374
|
{ value: "pending", label: { en: "Pending", es: "Pendiente" } },
|
|
@@ -15546,7 +15392,7 @@ var init_mail_entity = __esm({
|
|
|
15546
15392
|
label: { en: "Error", es: "Error" },
|
|
15547
15393
|
nullable: true
|
|
15548
15394
|
}),
|
|
15549
|
-
sent_by:
|
|
15395
|
+
sent_by: useSelectField11({
|
|
15550
15396
|
label: { en: "Sent by", es: "Enviado por" },
|
|
15551
15397
|
table: "users",
|
|
15552
15398
|
column: "id",
|
|
@@ -16172,7 +16018,7 @@ var init_toggle_plugin_action = __esm({
|
|
|
16172
16018
|
});
|
|
16173
16019
|
|
|
16174
16020
|
// src/modules/plugins/plugins.entity.ts
|
|
16175
|
-
import { useTextField as useTextField13, useSelectField as
|
|
16021
|
+
import { useTextField as useTextField13, useSelectField as useSelectField12, useCheckboxField as useCheckboxField5 } from "@gzl10/nexus-sdk/fields";
|
|
16176
16022
|
import { OFFICIAL_PLUGINS } from "@gzl10/nexus-sdk";
|
|
16177
16023
|
var allowPluginManagement, pluginsEntity;
|
|
16178
16024
|
var init_plugins_entity = __esm({
|
|
@@ -16214,7 +16060,7 @@ var init_plugins_entity = __esm({
|
|
|
16214
16060
|
size: 20,
|
|
16215
16061
|
nullable: false
|
|
16216
16062
|
}),
|
|
16217
|
-
category:
|
|
16063
|
+
category: useSelectField12({
|
|
16218
16064
|
label: { en: "Category", es: "Categor\xEDa" },
|
|
16219
16065
|
options: [
|
|
16220
16066
|
{ value: "content", label: { en: "Content", es: "Contenido" } },
|
|
@@ -16293,7 +16139,7 @@ var init_plugins_entity = __esm({
|
|
|
16293
16139
|
|
|
16294
16140
|
// src/modules/plugins/plugins.routes.ts
|
|
16295
16141
|
import { Router } from "express";
|
|
16296
|
-
import { existsSync as
|
|
16142
|
+
import { existsSync as existsSync10 } from "fs";
|
|
16297
16143
|
function createPluginRoutes(ctx) {
|
|
16298
16144
|
const router = Router();
|
|
16299
16145
|
let imageMap = null;
|
|
@@ -16301,7 +16147,7 @@ function createPluginRoutes(ctx) {
|
|
|
16301
16147
|
if (!imageMap) {
|
|
16302
16148
|
const discovered = await ctx.core.plugins.discover();
|
|
16303
16149
|
imageMap = new Map(
|
|
16304
|
-
discovered.filter((p) => p.image &&
|
|
16150
|
+
discovered.filter((p) => p.image && existsSync10(p.image)).map((p) => [p.code, p.image])
|
|
16305
16151
|
);
|
|
16306
16152
|
}
|
|
16307
16153
|
return imageMap;
|
|
@@ -16356,7 +16202,7 @@ var init_plugins = __esm({
|
|
|
16356
16202
|
import {
|
|
16357
16203
|
useIdField as useIdField8,
|
|
16358
16204
|
useTextField as useTextField14,
|
|
16359
|
-
useSelectField as
|
|
16205
|
+
useSelectField as useSelectField13,
|
|
16360
16206
|
useTextareaField as useTextareaField4,
|
|
16361
16207
|
useJsonField as useJsonField3,
|
|
16362
16208
|
useDatetimeField as useDatetimeField7,
|
|
@@ -16398,7 +16244,7 @@ var init_audit_entity = __esm({
|
|
|
16398
16244
|
}),
|
|
16399
16245
|
validation: { min: 1, max: 100 }
|
|
16400
16246
|
},
|
|
16401
|
-
actor_id:
|
|
16247
|
+
actor_id: useSelectField13({
|
|
16402
16248
|
label: { en: "Actor", es: "Actor" },
|
|
16403
16249
|
table: "users",
|
|
16404
16250
|
column: "id",
|
|
@@ -16675,6 +16521,7 @@ import jwt3 from "jsonwebtoken";
|
|
|
16675
16521
|
var init_jwt = __esm({
|
|
16676
16522
|
"src/core/jwt/index.ts"() {
|
|
16677
16523
|
"use strict";
|
|
16524
|
+
init_secret_resolver();
|
|
16678
16525
|
}
|
|
16679
16526
|
});
|
|
16680
16527
|
|
|
@@ -17086,6 +16933,7 @@ var init_socket = __esm({
|
|
|
17086
16933
|
"use strict";
|
|
17087
16934
|
init_emitter();
|
|
17088
16935
|
init_logger();
|
|
16936
|
+
init_secret_resolver();
|
|
17089
16937
|
io = null;
|
|
17090
16938
|
userSockets = /* @__PURE__ */ new Map();
|
|
17091
16939
|
socketUsers = /* @__PURE__ */ new Map();
|
|
@@ -17279,8 +17127,8 @@ var init_port_check = __esm({
|
|
|
17279
17127
|
});
|
|
17280
17128
|
|
|
17281
17129
|
// src/db/seed-runner.ts
|
|
17282
|
-
import { existsSync as
|
|
17283
|
-
import { join as
|
|
17130
|
+
import { existsSync as existsSync11 } from "fs";
|
|
17131
|
+
import { join as join13 } from "path";
|
|
17284
17132
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
17285
17133
|
var init_seed_runner = __esm({
|
|
17286
17134
|
"src/db/seed-runner.ts"() {
|
|
@@ -18305,7 +18153,7 @@ var init_migration_helpers = __esm({
|
|
|
18305
18153
|
// src/db/migration-generator.ts
|
|
18306
18154
|
import path2 from "path";
|
|
18307
18155
|
import fs2 from "fs/promises";
|
|
18308
|
-
import { readFileSync as
|
|
18156
|
+
import { readFileSync as readFileSync8, mkdirSync as mkdirSync5, realpathSync } from "fs";
|
|
18309
18157
|
function getColumnIndexBytes(field) {
|
|
18310
18158
|
if (!field?.db) return 255 * MYSQL_BYTES_PER_CHAR;
|
|
18311
18159
|
const size = field.db.size ?? 255;
|
|
@@ -18397,7 +18245,7 @@ function resolvePrefix(scope) {
|
|
|
18397
18245
|
function detectDefaultScope() {
|
|
18398
18246
|
try {
|
|
18399
18247
|
const pkgPath = path2.join(getProjectPath(), "package.json");
|
|
18400
|
-
const pkg3 = JSON.parse(
|
|
18248
|
+
const pkg3 = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
18401
18249
|
const pkgName = pkg3?.name;
|
|
18402
18250
|
if (pkgName === "@gzl10/nexus-backend") {
|
|
18403
18251
|
return "core";
|
|
@@ -19186,7 +19034,7 @@ var init_db = __esm({
|
|
|
19186
19034
|
// src/core/tunnel.ts
|
|
19187
19035
|
import { spawn, execSync } from "child_process";
|
|
19188
19036
|
import { writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
19189
|
-
import { join as
|
|
19037
|
+
import { join as join14 } from "path";
|
|
19190
19038
|
import { tmpdir } from "os";
|
|
19191
19039
|
function stopTunnel() {
|
|
19192
19040
|
if (tunnelProcess) {
|
|
@@ -19290,6 +19138,7 @@ async function stop() {
|
|
|
19290
19138
|
resetConfigCache();
|
|
19291
19139
|
clearCustomCaslRules();
|
|
19292
19140
|
clearSeedPermissions();
|
|
19141
|
+
_resetSecretResolver();
|
|
19293
19142
|
await resetServeSPA();
|
|
19294
19143
|
return;
|
|
19295
19144
|
}
|
|
@@ -19325,6 +19174,7 @@ async function stop() {
|
|
|
19325
19174
|
resetConfigCache();
|
|
19326
19175
|
clearCustomCaslRules();
|
|
19327
19176
|
clearSeedPermissions();
|
|
19177
|
+
_resetSecretResolver();
|
|
19328
19178
|
await resetServeSPA();
|
|
19329
19179
|
currentConfig = void 0;
|
|
19330
19180
|
server = null;
|
|
@@ -19385,6 +19235,7 @@ var init_server = __esm({
|
|
|
19385
19235
|
init_ensure_system_tables();
|
|
19386
19236
|
init_load_config();
|
|
19387
19237
|
init_tunnel();
|
|
19238
|
+
init_secret_resolver();
|
|
19388
19239
|
server = null;
|
|
19389
19240
|
gracefulShutdownRegistered = false;
|
|
19390
19241
|
setupGracefulShutdown();
|
|
@@ -19440,10 +19291,11 @@ var init_hash = __esm({
|
|
|
19440
19291
|
});
|
|
19441
19292
|
|
|
19442
19293
|
// src/core/crypto/symmetric.ts
|
|
19443
|
-
import { createCipheriv, createDecipheriv, randomBytes as
|
|
19294
|
+
import { createCipheriv, createDecipheriv, randomBytes as randomBytes3, hkdfSync } from "crypto";
|
|
19444
19295
|
var init_symmetric = __esm({
|
|
19445
19296
|
"src/core/crypto/symmetric.ts"() {
|
|
19446
19297
|
"use strict";
|
|
19298
|
+
init_secret_resolver();
|
|
19447
19299
|
}
|
|
19448
19300
|
});
|
|
19449
19301
|
|
|
@@ -19555,6 +19407,13 @@ var init_events_api = __esm({
|
|
|
19555
19407
|
}
|
|
19556
19408
|
});
|
|
19557
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
|
+
|
|
19558
19417
|
// src/engine/context.ts
|
|
19559
19418
|
import { ForbiddenError as CASLForbiddenError3, subject } from "@casl/ability";
|
|
19560
19419
|
import { DEFAULT_TENANT_ID as DEFAULT_TENANT_ID2, DEFAULT_LOCALES as DEFAULT_LOCALES2 } from "@gzl10/nexus-sdk";
|
|
@@ -19581,6 +19440,7 @@ var init_context = __esm({
|
|
|
19581
19440
|
init_plugin_ops();
|
|
19582
19441
|
init_load_config();
|
|
19583
19442
|
init_events_api();
|
|
19443
|
+
init_capabilities_registry();
|
|
19584
19444
|
init_seed_runner();
|
|
19585
19445
|
init_cache_manager();
|
|
19586
19446
|
sharedCacheManager = null;
|
|
@@ -19599,6 +19459,7 @@ var init_engine = __esm({
|
|
|
19599
19459
|
init_subject_extractor();
|
|
19600
19460
|
init_definition_extractors();
|
|
19601
19461
|
init_context();
|
|
19462
|
+
init_capabilities_registry();
|
|
19602
19463
|
}
|
|
19603
19464
|
});
|
|
19604
19465
|
|
|
@@ -19616,8 +19477,8 @@ __export(migrate_commands_exports, {
|
|
|
19616
19477
|
handleUp: () => handleUp,
|
|
19617
19478
|
loadModulesForMigration: () => loadModulesForMigration
|
|
19618
19479
|
});
|
|
19619
|
-
import { readFileSync as
|
|
19620
|
-
import { join as
|
|
19480
|
+
import { readFileSync as readFileSync9, existsSync as existsSync12 } from "fs";
|
|
19481
|
+
import { join as join15 } from "path";
|
|
19621
19482
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
19622
19483
|
import Table from "cli-table3";
|
|
19623
19484
|
import { consola as consola2 } from "consola";
|
|
@@ -19627,15 +19488,15 @@ function scopeToSourceId(scope) {
|
|
|
19627
19488
|
}
|
|
19628
19489
|
async function loadSelfPlugin() {
|
|
19629
19490
|
const projectPath2 = getProjectPath();
|
|
19630
|
-
const pkgPath =
|
|
19631
|
-
if (!
|
|
19491
|
+
const pkgPath = join15(projectPath2, "package.json");
|
|
19492
|
+
if (!existsSync12(pkgPath)) return;
|
|
19632
19493
|
try {
|
|
19633
|
-
const pkg3 = JSON.parse(
|
|
19494
|
+
const pkg3 = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
19634
19495
|
const pkgName = pkg3?.name;
|
|
19635
19496
|
if (!pkgName || !/nexus-plugin-/.test(pkgName)) return;
|
|
19636
|
-
const srcEntry =
|
|
19637
|
-
const distEntry =
|
|
19638
|
-
if (
|
|
19497
|
+
const srcEntry = join15(projectPath2, "src", "index.ts");
|
|
19498
|
+
const distEntry = join15(projectPath2, "dist", "index.js");
|
|
19499
|
+
if (existsSync12(srcEntry)) {
|
|
19639
19500
|
try {
|
|
19640
19501
|
const { tsImport } = await import("tsx/esm/api");
|
|
19641
19502
|
const mod = await tsImport(
|
|
@@ -19645,7 +19506,7 @@ async function loadSelfPlugin() {
|
|
|
19645
19506
|
const manifest = extractPluginManifest(mod);
|
|
19646
19507
|
if (manifest) {
|
|
19647
19508
|
if (!manifest.migrationsDir) {
|
|
19648
|
-
manifest.migrationsDir =
|
|
19509
|
+
manifest.migrationsDir = join15(projectPath2, "migrations");
|
|
19649
19510
|
}
|
|
19650
19511
|
registerPlugin(manifest);
|
|
19651
19512
|
return;
|
|
@@ -19654,13 +19515,13 @@ async function loadSelfPlugin() {
|
|
|
19654
19515
|
console.error(` \u26A0 Failed to load plugin src/index.ts: ${err.message}`);
|
|
19655
19516
|
}
|
|
19656
19517
|
}
|
|
19657
|
-
if (
|
|
19518
|
+
if (existsSync12(distEntry)) {
|
|
19658
19519
|
try {
|
|
19659
19520
|
const mod = await import(pathToFileURL3(distEntry).href);
|
|
19660
19521
|
const manifest = extractPluginManifest(mod);
|
|
19661
19522
|
if (manifest) {
|
|
19662
19523
|
if (!manifest.migrationsDir) {
|
|
19663
|
-
manifest.migrationsDir =
|
|
19524
|
+
manifest.migrationsDir = join15(projectPath2, "migrations");
|
|
19664
19525
|
}
|
|
19665
19526
|
registerPlugin(manifest);
|
|
19666
19527
|
return;
|
|
@@ -19979,7 +19840,7 @@ __export(db_commands_exports, {
|
|
|
19979
19840
|
handleDbWipe: () => handleDbWipe
|
|
19980
19841
|
});
|
|
19981
19842
|
import { spawn as spawn2 } from "child_process";
|
|
19982
|
-
import { isAbsolute as isAbsolute3, join as
|
|
19843
|
+
import { isAbsolute as isAbsolute3, join as join16 } from "path";
|
|
19983
19844
|
import { statSync as statSync2 } from "fs";
|
|
19984
19845
|
import { consola as consola3 } from "consola";
|
|
19985
19846
|
async function handleDbWipe(options) {
|
|
@@ -20067,7 +19928,7 @@ function handleDbShell() {
|
|
|
20067
19928
|
if (dbType === "sqlite") {
|
|
20068
19929
|
let filename = url.replace(/^(file:|sqlite:)/, "");
|
|
20069
19930
|
if (!isAbsolute3(filename)) {
|
|
20070
|
-
filename =
|
|
19931
|
+
filename = join16(getProjectPath(), "data", filename);
|
|
20071
19932
|
}
|
|
20072
19933
|
cmd = "sqlite3";
|
|
20073
19934
|
args = [filename];
|
|
@@ -20112,7 +19973,7 @@ async function collectDbInfo() {
|
|
|
20112
19973
|
if (url !== ":memory:" && !url.includes(":memory:")) {
|
|
20113
19974
|
let filename = url.replace(/^(file:|sqlite:)/, "");
|
|
20114
19975
|
if (!isAbsolute3(filename)) {
|
|
20115
|
-
filename =
|
|
19976
|
+
filename = join16(getProjectPath(), "data", filename);
|
|
20116
19977
|
}
|
|
20117
19978
|
try {
|
|
20118
19979
|
const stat2 = statSync2(filename);
|
|
@@ -20169,8 +20030,8 @@ __export(plugin_commands_exports, {
|
|
|
20169
20030
|
handlePluginList: () => handlePluginList,
|
|
20170
20031
|
handlePluginRemove: () => handlePluginRemove
|
|
20171
20032
|
});
|
|
20172
|
-
import { existsSync as
|
|
20173
|
-
import { join as
|
|
20033
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
20034
|
+
import { join as join17 } from "path";
|
|
20174
20035
|
import Table2 from "cli-table3";
|
|
20175
20036
|
import { consola as consola4 } from "consola";
|
|
20176
20037
|
import { OFFICIAL_PLUGINS as OFFICIAL_PLUGINS2 } from "@gzl10/nexus-sdk";
|
|
@@ -20178,10 +20039,10 @@ function pluginLabel(name) {
|
|
|
20178
20039
|
return shortPluginName(name).split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
20179
20040
|
}
|
|
20180
20041
|
function readPluginVersion(projectPath2, pkgName) {
|
|
20181
|
-
const pkgJsonPath =
|
|
20182
|
-
if (!
|
|
20042
|
+
const pkgJsonPath = join17(projectPath2, "node_modules", pkgName, "package.json");
|
|
20043
|
+
if (!existsSync13(pkgJsonPath)) return null;
|
|
20183
20044
|
try {
|
|
20184
|
-
const pkg3 = JSON.parse(
|
|
20045
|
+
const pkg3 = JSON.parse(readFileSync10(pkgJsonPath, "utf-8"));
|
|
20185
20046
|
return pkg3.version ?? null;
|
|
20186
20047
|
} catch {
|
|
20187
20048
|
return null;
|
|
@@ -20467,19 +20328,19 @@ var sync_commands_exports = {};
|
|
|
20467
20328
|
__export(sync_commands_exports, {
|
|
20468
20329
|
handleSyncCommands: () => handleSyncCommands
|
|
20469
20330
|
});
|
|
20470
|
-
import { existsSync as
|
|
20471
|
-
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";
|
|
20472
20333
|
import { homedir } from "os";
|
|
20473
20334
|
import { createConsola } from "consola";
|
|
20474
20335
|
async function handleSyncCommands(options) {
|
|
20475
|
-
const sourceDir =
|
|
20476
|
-
const targetDir =
|
|
20477
|
-
if (!
|
|
20336
|
+
const sourceDir = join18(getLibPath(), "claude-commands");
|
|
20337
|
+
const targetDir = join18(homedir(), ".claude", "commands");
|
|
20338
|
+
if (!existsSync14(sourceDir)) {
|
|
20478
20339
|
logger2.warn(`Commands source not found: ${sourceDir}`);
|
|
20479
20340
|
logger2.info("Make sure @gzl10/nexus-backend is properly installed.");
|
|
20480
20341
|
return;
|
|
20481
20342
|
}
|
|
20482
|
-
if (!
|
|
20343
|
+
if (!existsSync14(targetDir)) {
|
|
20483
20344
|
if (options.dryRun) {
|
|
20484
20345
|
logger2.info(`Would create: ${targetDir}`);
|
|
20485
20346
|
} else {
|
|
@@ -20494,16 +20355,16 @@ async function handleSyncCommands(options) {
|
|
|
20494
20355
|
}
|
|
20495
20356
|
const result = { added: [], updated: [], unchanged: [] };
|
|
20496
20357
|
for (const file of sourceFiles) {
|
|
20497
|
-
const sourcePath =
|
|
20498
|
-
const targetPath =
|
|
20499
|
-
const sourceContent =
|
|
20500
|
-
if (!
|
|
20358
|
+
const sourcePath = join18(sourceDir, file);
|
|
20359
|
+
const targetPath = join18(targetDir, file);
|
|
20360
|
+
const sourceContent = readFileSync11(sourcePath, "utf-8");
|
|
20361
|
+
if (!existsSync14(targetPath)) {
|
|
20501
20362
|
if (!options.dryRun) {
|
|
20502
20363
|
writeFileSync3(targetPath, sourceContent, "utf-8");
|
|
20503
20364
|
}
|
|
20504
20365
|
result.added.push(file);
|
|
20505
20366
|
} else {
|
|
20506
|
-
const targetContent =
|
|
20367
|
+
const targetContent = readFileSync11(targetPath, "utf-8");
|
|
20507
20368
|
if (sourceContent !== targetContent) {
|
|
20508
20369
|
if (!options.dryRun) {
|
|
20509
20370
|
writeFileSync3(targetPath, sourceContent, "utf-8");
|
|
@@ -20549,8 +20410,8 @@ __export(seed_commands_exports, {
|
|
|
20549
20410
|
handleSeedExport: () => handleSeedExport,
|
|
20550
20411
|
importSeedFiles: () => importSeedFiles
|
|
20551
20412
|
});
|
|
20552
|
-
import { existsSync as
|
|
20553
|
-
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";
|
|
20554
20415
|
import { consola as consola5 } from "consola";
|
|
20555
20416
|
function deserializeJsonFields(record, fields) {
|
|
20556
20417
|
const result = { ...record };
|
|
@@ -20579,7 +20440,7 @@ async function handleSeedExport(entity) {
|
|
|
20579
20440
|
const db3 = getDb();
|
|
20580
20441
|
try {
|
|
20581
20442
|
const modules = getOrderedModules();
|
|
20582
|
-
const seedDir =
|
|
20443
|
+
const seedDir = join19(getProjectPath(), "data", "seeds");
|
|
20583
20444
|
const seedableEntities = [];
|
|
20584
20445
|
for (const mod of modules) {
|
|
20585
20446
|
for (const def of mod.definitions ?? []) {
|
|
@@ -20600,7 +20461,7 @@ async function handleSeedExport(entity) {
|
|
|
20600
20461
|
}
|
|
20601
20462
|
return;
|
|
20602
20463
|
}
|
|
20603
|
-
if (!
|
|
20464
|
+
if (!existsSync15(seedDir)) {
|
|
20604
20465
|
mkdirSync7(seedDir, { recursive: true });
|
|
20605
20466
|
}
|
|
20606
20467
|
for (const { module: modName, table, fields } of seedableEntities) {
|
|
@@ -20612,7 +20473,7 @@ async function handleSeedExport(entity) {
|
|
|
20612
20473
|
const exported = rows.map(
|
|
20613
20474
|
(row) => deserializeJsonFields(row, fields)
|
|
20614
20475
|
);
|
|
20615
|
-
const filePath =
|
|
20476
|
+
const filePath = join19(seedDir, `${table}.json`);
|
|
20616
20477
|
writeFileSync4(filePath, JSON.stringify(exported, null, 2) + "\n", "utf-8");
|
|
20617
20478
|
consola5.success(`${table}: exported ${rows.length} records to data/seeds/${table}.json (module: ${modName})`);
|
|
20618
20479
|
}
|
|
@@ -20624,8 +20485,8 @@ async function handleSeedExport(entity) {
|
|
|
20624
20485
|
}
|
|
20625
20486
|
}
|
|
20626
20487
|
async function importSeedFiles(db3, modules, logger3) {
|
|
20627
|
-
const seedDir =
|
|
20628
|
-
if (!
|
|
20488
|
+
const seedDir = join19(getProjectPath(), "data", "seeds");
|
|
20489
|
+
if (!existsSync15(seedDir)) return;
|
|
20629
20490
|
const files = readdirSync3(seedDir).filter((f) => f.endsWith(".json"));
|
|
20630
20491
|
if (files.length === 0) return;
|
|
20631
20492
|
const seedableDefs = /* @__PURE__ */ new Map();
|
|
@@ -20646,8 +20507,8 @@ async function importSeedFiles(db3, modules, logger3) {
|
|
|
20646
20507
|
logger3.debug(`data/seeds/${file}: skipped (entity "${table}" is not seedable)`);
|
|
20647
20508
|
continue;
|
|
20648
20509
|
}
|
|
20649
|
-
const filePath =
|
|
20650
|
-
const raw =
|
|
20510
|
+
const filePath = join19(seedDir, file);
|
|
20511
|
+
const raw = readFileSync12(filePath, "utf-8");
|
|
20651
20512
|
let records;
|
|
20652
20513
|
try {
|
|
20653
20514
|
records = JSON.parse(raw);
|
|
@@ -20694,12 +20555,12 @@ if (!nodeEnv || nodeEnv === "development") {
|
|
|
20694
20555
|
}
|
|
20695
20556
|
|
|
20696
20557
|
// src/cli.ts
|
|
20697
|
-
import { readFileSync as
|
|
20558
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
20698
20559
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
20699
|
-
import { dirname as dirname8, join as
|
|
20560
|
+
import { dirname as dirname8, join as join20 } from "path";
|
|
20700
20561
|
import { Command } from "commander";
|
|
20701
20562
|
var __dirname2 = dirname8(fileURLToPath3(import.meta.url));
|
|
20702
|
-
var pkg2 = JSON.parse(
|
|
20563
|
+
var pkg2 = JSON.parse(readFileSync13(join20(__dirname2, "..", "package.json"), "utf-8"));
|
|
20703
20564
|
var program = new Command();
|
|
20704
20565
|
program.name("nexus").description("Nexus Backend CLI").version(pkg2.version);
|
|
20705
20566
|
program.command("info").description("Show Nexus environment, database, plugins, and paths").option("--json", "Output as JSON").action(async (options) => {
|