@gzl10/nexus-backend 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-error-CKbYJQ9V.d.ts +136 -0
- package/dist/cli.js +521 -282
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -135
- package/dist/index.js +632 -147
- package/dist/index.js.map +1 -1
- package/dist/main.js +632 -147
- package/dist/main.js.map +1 -1
- package/dist/migration-helpers/index.d.ts +63 -0
- package/dist/migration-helpers/index.js +12116 -0
- package/dist/migration-helpers/index.js.map +1 -0
- package/dist/testing/index.d.ts +81 -0
- package/dist/testing/index.js +1675 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +17 -3
package/dist/main.js
CHANGED
|
@@ -106,7 +106,7 @@ var init_package = __esm({
|
|
|
106
106
|
"package.json"() {
|
|
107
107
|
package_default = {
|
|
108
108
|
name: "@gzl10/nexus-backend",
|
|
109
|
-
version: "0.
|
|
109
|
+
version: "0.19.0",
|
|
110
110
|
description: "Backend as a Service (BaaS) with Express 5, Knex and CASL",
|
|
111
111
|
type: "module",
|
|
112
112
|
main: "./dist/index.js",
|
|
@@ -118,6 +118,14 @@ var init_package = __esm({
|
|
|
118
118
|
".": {
|
|
119
119
|
import: "./dist/index.js",
|
|
120
120
|
types: "./dist/index.d.ts"
|
|
121
|
+
},
|
|
122
|
+
"./testing": {
|
|
123
|
+
import: "./dist/testing/index.js",
|
|
124
|
+
types: "./dist/testing/index.d.ts"
|
|
125
|
+
},
|
|
126
|
+
"./migrations": {
|
|
127
|
+
import: "./dist/migration-helpers/index.js",
|
|
128
|
+
types: "./dist/migration-helpers/index.d.ts"
|
|
121
129
|
}
|
|
122
130
|
},
|
|
123
131
|
files: [
|
|
@@ -223,9 +231,11 @@ var init_package = __esm({
|
|
|
223
231
|
"@types/cookie-parser": "^1.4.10",
|
|
224
232
|
"@types/cors": "^2.8.19",
|
|
225
233
|
"@types/express": "^5.0.6",
|
|
234
|
+
"@types/express-serve-static-core": "^5.1.1",
|
|
226
235
|
"@types/jsonwebtoken": "^9.0.10",
|
|
227
236
|
"@types/multer": "^2.1.0",
|
|
228
237
|
"@types/nodemailer": "^7.0.11",
|
|
238
|
+
"@types/qs": "^6.15.0",
|
|
229
239
|
"@types/supertest": "^6.0.3",
|
|
230
240
|
"pino-pretty": "^13.1.3",
|
|
231
241
|
"socket.io-client": "^4.8.3",
|
|
@@ -234,11 +244,15 @@ var init_package = __esm({
|
|
|
234
244
|
vite: "^8.0.3"
|
|
235
245
|
},
|
|
236
246
|
peerDependencies: {
|
|
237
|
-
vite: ">=6.0.0"
|
|
247
|
+
vite: ">=6.0.0",
|
|
248
|
+
vitest: ">=3.0.0"
|
|
238
249
|
},
|
|
239
250
|
peerDependenciesMeta: {
|
|
240
251
|
vite: {
|
|
241
252
|
optional: true
|
|
253
|
+
},
|
|
254
|
+
vitest: {
|
|
255
|
+
optional: true
|
|
242
256
|
}
|
|
243
257
|
},
|
|
244
258
|
publishConfig: {
|
|
@@ -1140,6 +1154,14 @@ async function isWorkspacePackage(name) {
|
|
|
1140
1154
|
}
|
|
1141
1155
|
}
|
|
1142
1156
|
async function installPlugin(name, opts) {
|
|
1157
|
+
const projectPath2 = opts?.projectPath ?? process.cwd();
|
|
1158
|
+
const pkgPath = join2(projectPath2, "package.json");
|
|
1159
|
+
if (existsSync2(pkgPath)) {
|
|
1160
|
+
const pkg3 = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1161
|
+
if (pkg3.name === "@gzl10/nexus-backend") {
|
|
1162
|
+
throw new Error("Cannot install plugins inside @gzl10/nexus-backend. Run this command from a Nexus project directory.");
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1143
1165
|
const isWorkspace = await isWorkspacePackage(name);
|
|
1144
1166
|
let pkg2;
|
|
1145
1167
|
if (opts?.version) {
|
|
@@ -1156,11 +1178,28 @@ async function installPlugin(name, opts) {
|
|
|
1156
1178
|
plugins[name] = { enabled: true };
|
|
1157
1179
|
writePluginsFile(plugins, filePath);
|
|
1158
1180
|
}
|
|
1181
|
+
function isPackageInstalled(name, projectPath2) {
|
|
1182
|
+
const base = projectPath2 || process.cwd();
|
|
1183
|
+
const pkgPath = join2(base, "package.json");
|
|
1184
|
+
try {
|
|
1185
|
+
const pkg2 = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1186
|
+
return !!(pkg2.dependencies?.[name] || pkg2.devDependencies?.[name]);
|
|
1187
|
+
} catch {
|
|
1188
|
+
return false;
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1159
1191
|
async function uninstallPlugin(name, projectPath2) {
|
|
1160
|
-
await execAsync(`pnpm remove ${name}`);
|
|
1161
1192
|
const filePath = getPluginsFilePath(projectPath2);
|
|
1162
1193
|
const plugins = readPluginsFile(filePath);
|
|
1163
|
-
|
|
1194
|
+
const isRegistered = name in plugins;
|
|
1195
|
+
const isInstalled = isPackageInstalled(name, projectPath2);
|
|
1196
|
+
if (!isRegistered && !isInstalled) {
|
|
1197
|
+
throw new Error(`Plugin ${shortPluginName(name)} is not installed`);
|
|
1198
|
+
}
|
|
1199
|
+
if (isInstalled) {
|
|
1200
|
+
await execAsync(`pnpm remove ${name}`);
|
|
1201
|
+
}
|
|
1202
|
+
if (isRegistered) {
|
|
1164
1203
|
delete plugins[name];
|
|
1165
1204
|
writePluginsFile(plugins, filePath);
|
|
1166
1205
|
}
|
|
@@ -2148,6 +2187,7 @@ var init_definitions = __esm({
|
|
|
2148
2187
|
};
|
|
2149
2188
|
mastersEntity = {
|
|
2150
2189
|
table: "masters",
|
|
2190
|
+
seedable: true,
|
|
2151
2191
|
routePrefix: "/",
|
|
2152
2192
|
label: { en: "Master", es: "Maestro" },
|
|
2153
2193
|
labelPlural: { en: "Masters", es: "Maestros" },
|
|
@@ -2179,14 +2219,15 @@ var init_definitions = __esm({
|
|
|
2179
2219
|
meta: { sortable: true, searchable: true }
|
|
2180
2220
|
}),
|
|
2181
2221
|
label: useLocalizedField({ label: { en: "Name", es: "Nombre" } }),
|
|
2182
|
-
order: orderField,
|
|
2222
|
+
order: { ...orderField, meta: { ...orderField.meta, showInDisplay: false } },
|
|
2183
2223
|
is_active: isActiveField,
|
|
2184
2224
|
metadata: useJsonField({
|
|
2185
2225
|
label: { en: "Metadata", es: "Metadatos" },
|
|
2186
2226
|
hint: {
|
|
2187
2227
|
en: "Type-specific fields (symbol, flag, etc.)",
|
|
2188
2228
|
es: "Campos espec\xEDficos del tipo"
|
|
2189
|
-
}
|
|
2229
|
+
},
|
|
2230
|
+
meta: { showInDisplay: false }
|
|
2190
2231
|
})
|
|
2191
2232
|
},
|
|
2192
2233
|
hooks: () => ({
|
|
@@ -2195,6 +2236,12 @@ var init_definitions = __esm({
|
|
|
2195
2236
|
data["id"] = `${data["type"]}:${data["code"]}`;
|
|
2196
2237
|
}
|
|
2197
2238
|
return data;
|
|
2239
|
+
},
|
|
2240
|
+
beforeUpdate: async (_id, data) => {
|
|
2241
|
+
if ("type" in data || "code" in data) {
|
|
2242
|
+
throw new Error("Cannot update type or code of a master record. Delete and recreate instead.");
|
|
2243
|
+
}
|
|
2244
|
+
return data;
|
|
2198
2245
|
}
|
|
2199
2246
|
}),
|
|
2200
2247
|
defaultSort: { field: "order", order: "asc" },
|
|
@@ -2246,7 +2293,7 @@ function createMasterRegistry() {
|
|
|
2246
2293
|
await ctx.db.knex("masters").insert(row).onConflict(["type", "code"]).merge();
|
|
2247
2294
|
}
|
|
2248
2295
|
} else {
|
|
2249
|
-
await ctx.db.knex("masters").insert(rows);
|
|
2296
|
+
await ctx.db.knex("masters").insert(rows).onConflict(["type", "code"]).ignore();
|
|
2250
2297
|
}
|
|
2251
2298
|
}
|
|
2252
2299
|
},
|
|
@@ -8679,15 +8726,12 @@ var init_document_types = __esm({
|
|
|
8679
8726
|
}
|
|
8680
8727
|
});
|
|
8681
8728
|
|
|
8682
|
-
// src/modules/masters/
|
|
8683
|
-
var
|
|
8684
|
-
var
|
|
8685
|
-
"src/modules/masters/
|
|
8729
|
+
// src/modules/masters/constants.ts
|
|
8730
|
+
var DEFAULT_MASTER_TYPES, PREDEFINED_MASTERS;
|
|
8731
|
+
var init_constants = __esm({
|
|
8732
|
+
"src/modules/masters/constants.ts"() {
|
|
8686
8733
|
"use strict";
|
|
8687
|
-
|
|
8688
|
-
init_registry2();
|
|
8689
|
-
init_definitions();
|
|
8690
|
-
init_registry2();
|
|
8734
|
+
DEFAULT_MASTER_TYPES = ["languages", "timezones"];
|
|
8691
8735
|
PREDEFINED_MASTERS = {
|
|
8692
8736
|
currencies: () => Promise.resolve().then(() => (init_currencies(), currencies_exports)).then((m) => m.default),
|
|
8693
8737
|
languages: () => Promise.resolve().then(() => (init_languages(), languages_exports)).then((m) => m.default),
|
|
@@ -8704,15 +8748,137 @@ var init_masters = __esm({
|
|
|
8704
8748
|
"phone-prefixes": () => Promise.resolve().then(() => (init_phone_prefixes(), phone_prefixes_exports)).then((m) => m.default),
|
|
8705
8749
|
"document-types": () => Promise.resolve().then(() => (init_document_types(), document_types_exports)).then((m) => m.default)
|
|
8706
8750
|
};
|
|
8751
|
+
}
|
|
8752
|
+
});
|
|
8753
|
+
|
|
8754
|
+
// src/modules/masters/actions/install-type.ts
|
|
8755
|
+
import { useSelectField as useSelectField2 } from "@gzl10/nexus-sdk/fields";
|
|
8756
|
+
var installTypeAction;
|
|
8757
|
+
var init_install_type = __esm({
|
|
8758
|
+
"src/modules/masters/actions/install-type.ts"() {
|
|
8759
|
+
"use strict";
|
|
8760
|
+
init_constants();
|
|
8761
|
+
installTypeAction = {
|
|
8762
|
+
key: "install-type",
|
|
8763
|
+
scope: "module",
|
|
8764
|
+
label: { en: "Install Master Type", es: "Instalar Tipo de Maestro" },
|
|
8765
|
+
icon: "mdi:database-plus",
|
|
8766
|
+
variant: "primary",
|
|
8767
|
+
output: {},
|
|
8768
|
+
input: {
|
|
8769
|
+
type: useSelectField2({
|
|
8770
|
+
label: { en: "Master Type", es: "Tipo de Maestro" },
|
|
8771
|
+
required: true,
|
|
8772
|
+
options: Object.keys(PREDEFINED_MASTERS).filter((t) => !DEFAULT_MASTER_TYPES.includes(t)).map((t) => ({
|
|
8773
|
+
value: t,
|
|
8774
|
+
label: t.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
8775
|
+
}))
|
|
8776
|
+
})
|
|
8777
|
+
},
|
|
8778
|
+
handler: async (ctx, input) => {
|
|
8779
|
+
if (process.env["NODE_ENV"] === "production") {
|
|
8780
|
+
throw new ctx.core.errors.ForbiddenError("Master type management is only available in development");
|
|
8781
|
+
}
|
|
8782
|
+
const { type: type2 } = input;
|
|
8783
|
+
const loader = PREDEFINED_MASTERS[type2];
|
|
8784
|
+
if (!loader) {
|
|
8785
|
+
throw new ctx.core.errors.AppError(`Unknown predefined master type: ${type2}`, 400);
|
|
8786
|
+
}
|
|
8787
|
+
const existing = await ctx.db.knex("masters").where({ type: type2 }).first();
|
|
8788
|
+
if (existing) {
|
|
8789
|
+
throw new ctx.core.errors.ConflictError(`Master type "${type2}" is already installed`);
|
|
8790
|
+
}
|
|
8791
|
+
const entries = await loader();
|
|
8792
|
+
const rows = entries.map((entry, i) => ({
|
|
8793
|
+
id: `${type2}:${entry.code}`,
|
|
8794
|
+
type: type2,
|
|
8795
|
+
code: entry.code,
|
|
8796
|
+
label: JSON.stringify(typeof entry.label === "string" ? { en: entry.label } : entry.label),
|
|
8797
|
+
order: entry.order ?? i,
|
|
8798
|
+
is_active: entry.is_active ?? true,
|
|
8799
|
+
metadata: entry.metadata ? JSON.stringify(entry.metadata) : null
|
|
8800
|
+
}));
|
|
8801
|
+
await ctx.db.knex("masters").insert(rows).onConflict(["type", "code"]).ignore();
|
|
8802
|
+
return { installed: type2, count: rows.length };
|
|
8803
|
+
}
|
|
8804
|
+
};
|
|
8805
|
+
}
|
|
8806
|
+
});
|
|
8807
|
+
|
|
8808
|
+
// src/modules/masters/actions/uninstall-type.ts
|
|
8809
|
+
import { useTextField as useTextField3 } from "@gzl10/nexus-sdk/fields";
|
|
8810
|
+
var uninstallTypeAction;
|
|
8811
|
+
var init_uninstall_type = __esm({
|
|
8812
|
+
"src/modules/masters/actions/uninstall-type.ts"() {
|
|
8813
|
+
"use strict";
|
|
8814
|
+
init_constants();
|
|
8815
|
+
uninstallTypeAction = {
|
|
8816
|
+
key: "uninstall-type",
|
|
8817
|
+
scope: "module",
|
|
8818
|
+
label: { en: "Uninstall Master Type", es: "Desinstalar Tipo de Maestro" },
|
|
8819
|
+
icon: "mdi:database-minus",
|
|
8820
|
+
variant: "danger",
|
|
8821
|
+
output: {},
|
|
8822
|
+
confirm: {
|
|
8823
|
+
type: "simple",
|
|
8824
|
+
title: { en: "Uninstall Master Type", es: "Desinstalar Tipo de Maestro" },
|
|
8825
|
+
message: {
|
|
8826
|
+
en: "This will delete ALL records of the selected type. This action cannot be undone.",
|
|
8827
|
+
es: "Esto eliminar\xE1 TODOS los registros del tipo seleccionado. Esta acci\xF3n no se puede deshacer."
|
|
8828
|
+
}
|
|
8829
|
+
},
|
|
8830
|
+
input: {
|
|
8831
|
+
type: useTextField3({
|
|
8832
|
+
label: { en: "Type slug to uninstall", es: "Slug del tipo a desinstalar" },
|
|
8833
|
+
required: true,
|
|
8834
|
+
hint: {
|
|
8835
|
+
en: 'Enter the master type slug (e.g., "currencies", "countries")',
|
|
8836
|
+
es: 'Introduce el slug del tipo (ej: "currencies", "countries")'
|
|
8837
|
+
}
|
|
8838
|
+
})
|
|
8839
|
+
},
|
|
8840
|
+
handler: async (ctx, input) => {
|
|
8841
|
+
if (process.env["NODE_ENV"] === "production") {
|
|
8842
|
+
throw new ctx.core.errors.ForbiddenError("Master type management is only available in development");
|
|
8843
|
+
}
|
|
8844
|
+
const { type: type2 } = input;
|
|
8845
|
+
if (DEFAULT_MASTER_TYPES.includes(type2)) {
|
|
8846
|
+
throw new ctx.core.errors.AppError(`Cannot uninstall default master type "${type2}" (required by core)`, 400);
|
|
8847
|
+
}
|
|
8848
|
+
const existing = await ctx.db.knex("masters").where({ type: type2 }).first();
|
|
8849
|
+
if (!existing) {
|
|
8850
|
+
throw new ctx.core.errors.NotFoundError(`Master type "${type2}" is not installed`);
|
|
8851
|
+
}
|
|
8852
|
+
const deleted = await ctx.db.knex("masters").where({ type: type2 }).del();
|
|
8853
|
+
return { uninstalled: type2, count: deleted };
|
|
8854
|
+
}
|
|
8855
|
+
};
|
|
8856
|
+
}
|
|
8857
|
+
});
|
|
8858
|
+
|
|
8859
|
+
// src/modules/masters/index.ts
|
|
8860
|
+
var mastersModule;
|
|
8861
|
+
var init_masters = __esm({
|
|
8862
|
+
"src/modules/masters/index.ts"() {
|
|
8863
|
+
"use strict";
|
|
8864
|
+
init_definitions();
|
|
8865
|
+
init_registry2();
|
|
8866
|
+
init_constants();
|
|
8867
|
+
init_install_type();
|
|
8868
|
+
init_uninstall_type();
|
|
8869
|
+
init_definitions();
|
|
8870
|
+
init_registry2();
|
|
8871
|
+
init_constants();
|
|
8707
8872
|
mastersModule = {
|
|
8708
8873
|
name: "masters",
|
|
8709
8874
|
type: "core",
|
|
8710
|
-
label: { en: "
|
|
8875
|
+
label: { en: "Masters", es: "Maestros" },
|
|
8711
8876
|
icon: "mdi:database-outline",
|
|
8712
8877
|
description: { en: "Reference data catalogs", es: "Cat\xE1logos de datos de referencia" },
|
|
8713
|
-
category: "
|
|
8878
|
+
category: "settings",
|
|
8714
8879
|
routePrefix: "/masters",
|
|
8715
8880
|
definitions: [mastersEntity],
|
|
8881
|
+
actions: [installTypeAction, uninstallTypeAction],
|
|
8716
8882
|
init: (ctx) => {
|
|
8717
8883
|
if (!ctx.services.has("masters")) {
|
|
8718
8884
|
ctx.services.register("masters", createMasterRegistry());
|
|
@@ -8723,13 +8889,14 @@ var init_masters = __esm({
|
|
|
8723
8889
|
ctx.services.register("masters", createMasterRegistry());
|
|
8724
8890
|
}
|
|
8725
8891
|
const registry2 = ctx.services.get("masters");
|
|
8726
|
-
const
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8892
|
+
const existing = await ctx.db.knex("masters").first();
|
|
8893
|
+
if (!existing) {
|
|
8894
|
+
for (const type2 of DEFAULT_MASTER_TYPES) {
|
|
8895
|
+
const loader = PREDEFINED_MASTERS[type2];
|
|
8896
|
+
if (!loader) continue;
|
|
8897
|
+
const entries = await loader();
|
|
8898
|
+
registry2.register(type2, entries, { seed: "if-empty" });
|
|
8899
|
+
}
|
|
8733
8900
|
}
|
|
8734
8901
|
await registry2.seed(ctx);
|
|
8735
8902
|
}
|
|
@@ -8993,6 +9160,7 @@ function toPageDTO(page) {
|
|
|
8993
9160
|
dataSource: page.dataSource,
|
|
8994
9161
|
widgets: page.widgets,
|
|
8995
9162
|
component: page.component,
|
|
9163
|
+
contentEndpoint: page.contentEndpoint,
|
|
8996
9164
|
meta: page.meta,
|
|
8997
9165
|
layout: page.layout
|
|
8998
9166
|
};
|
|
@@ -9256,7 +9424,7 @@ var init_system_routes = __esm({
|
|
|
9256
9424
|
|
|
9257
9425
|
// src/modules/system/system.entity.ts
|
|
9258
9426
|
import * as os from "os";
|
|
9259
|
-
import { useIconField, useTextField as
|
|
9427
|
+
import { useIconField, useTextField as useTextField4, useSelectField as useSelectField3, useNumberField as useNumberField2, useCheckboxField, useTagsField, useNameField, useDescriptionField } from "@gzl10/nexus-sdk/fields";
|
|
9260
9428
|
var moduleEntity, osEntity;
|
|
9261
9429
|
var init_system_entity = __esm({
|
|
9262
9430
|
"src/modules/system/system.entity.ts"() {
|
|
@@ -9274,7 +9442,7 @@ var init_system_entity = __esm({
|
|
|
9274
9442
|
name: useNameField({
|
|
9275
9443
|
size: 50
|
|
9276
9444
|
}),
|
|
9277
|
-
label:
|
|
9445
|
+
label: useTextField4({
|
|
9278
9446
|
label: { en: "Label", es: "Etiqueta" },
|
|
9279
9447
|
size: 100,
|
|
9280
9448
|
nullable: false,
|
|
@@ -9282,7 +9450,7 @@ var init_system_entity = __esm({
|
|
|
9282
9450
|
}),
|
|
9283
9451
|
icon: useIconField({ label: { en: "Icon", es: "Icono" }, size: 50 }),
|
|
9284
9452
|
type: {
|
|
9285
|
-
...
|
|
9453
|
+
...useSelectField3({
|
|
9286
9454
|
label: { en: "Type", es: "Tipo" },
|
|
9287
9455
|
options: [
|
|
9288
9456
|
{ value: "core", label: { en: "Core", es: "Core" } },
|
|
@@ -9298,7 +9466,7 @@ var init_system_entity = __esm({
|
|
|
9298
9466
|
description: useDescriptionField({
|
|
9299
9467
|
mode: "text"
|
|
9300
9468
|
}),
|
|
9301
|
-
routePrefix:
|
|
9469
|
+
routePrefix: useTextField4({
|
|
9302
9470
|
label: { en: "Route", es: "Ruta" },
|
|
9303
9471
|
size: 50,
|
|
9304
9472
|
nullable: true
|
|
@@ -9356,14 +9524,14 @@ var init_system_entity = __esm({
|
|
|
9356
9524
|
order: 1,
|
|
9357
9525
|
refreshInterval: 5e3,
|
|
9358
9526
|
fields: {
|
|
9359
|
-
hostname:
|
|
9527
|
+
hostname: useTextField4({
|
|
9360
9528
|
label: { en: "Hostname", es: "Nombre de servidor" },
|
|
9361
9529
|
size: 100,
|
|
9362
9530
|
nullable: false,
|
|
9363
9531
|
inputProps: { order: 1 }
|
|
9364
9532
|
}),
|
|
9365
9533
|
platform: {
|
|
9366
|
-
...
|
|
9534
|
+
...useSelectField3({
|
|
9367
9535
|
label: { en: "Platform", es: "Plataforma" },
|
|
9368
9536
|
options: [
|
|
9369
9537
|
{ value: "darwin", label: { en: "macOS", es: "macOS" } },
|
|
@@ -9377,7 +9545,7 @@ var init_system_entity = __esm({
|
|
|
9377
9545
|
inputProps: { order: 2 }
|
|
9378
9546
|
},
|
|
9379
9547
|
arch: {
|
|
9380
|
-
...
|
|
9548
|
+
...useSelectField3({
|
|
9381
9549
|
label: { en: "Architecture", es: "Arquitectura" },
|
|
9382
9550
|
options: [
|
|
9383
9551
|
{ value: "x64", label: { en: "x64", es: "x64" } },
|
|
@@ -9390,7 +9558,7 @@ var init_system_entity = __esm({
|
|
|
9390
9558
|
inputProps: { order: 3 }
|
|
9391
9559
|
},
|
|
9392
9560
|
type: {
|
|
9393
|
-
...
|
|
9561
|
+
...useTextField4({
|
|
9394
9562
|
label: { en: "Type", es: "Tipo" },
|
|
9395
9563
|
size: 30,
|
|
9396
9564
|
nullable: false
|
|
@@ -9398,7 +9566,7 @@ var init_system_entity = __esm({
|
|
|
9398
9566
|
inputProps: { order: 4 }
|
|
9399
9567
|
},
|
|
9400
9568
|
release: {
|
|
9401
|
-
...
|
|
9569
|
+
...useTextField4({
|
|
9402
9570
|
label: { en: "Release", es: "Versi\xF3n" },
|
|
9403
9571
|
size: 50,
|
|
9404
9572
|
nullable: false
|
|
@@ -9421,7 +9589,7 @@ var init_system_entity = __esm({
|
|
|
9421
9589
|
inputProps: { order: 7, format: "duration" }
|
|
9422
9590
|
},
|
|
9423
9591
|
cpuModel: {
|
|
9424
|
-
...
|
|
9592
|
+
...useTextField4({
|
|
9425
9593
|
label: { en: "CPU Model", es: "Modelo de CPU" },
|
|
9426
9594
|
size: 100,
|
|
9427
9595
|
nullable: false
|
|
@@ -9487,7 +9655,7 @@ var init_system_entity = __esm({
|
|
|
9487
9655
|
});
|
|
9488
9656
|
|
|
9489
9657
|
// src/modules/system/migration-history.entity.ts
|
|
9490
|
-
import { useIdField as useIdField2, useTextField as
|
|
9658
|
+
import { useIdField as useIdField2, useTextField as useTextField5, useNumberField as useNumberField3, useSelectField as useSelectField4, useDatetimeField as useDatetimeField2, useTextareaField as useTextareaField2 } from "@gzl10/nexus-sdk/fields";
|
|
9491
9659
|
var migrationHistoryEntity;
|
|
9492
9660
|
var init_migration_history_entity = __esm({
|
|
9493
9661
|
"src/modules/system/migration-history.entity.ts"() {
|
|
@@ -9504,9 +9672,9 @@ var init_migration_history_entity = __esm({
|
|
|
9504
9672
|
calendarFrom: "executed_at",
|
|
9505
9673
|
fields: {
|
|
9506
9674
|
id: useIdField2(),
|
|
9507
|
-
name:
|
|
9675
|
+
name: useTextField5({ label: { en: "Migration Name", es: "Nombre de la Migraci\xF3n" }, required: true, size: 255, unique: true, meta: { sortable: true, searchable: true } }),
|
|
9508
9676
|
batch: useNumberField3({ label: { en: "Batch", es: "Lote" }, required: true, meta: { sortable: true } }),
|
|
9509
|
-
status:
|
|
9677
|
+
status: useSelectField4({
|
|
9510
9678
|
label: { en: "Status", es: "Estado" },
|
|
9511
9679
|
options: [
|
|
9512
9680
|
{ value: "running", label: { en: "Running", es: "Ejecutando" } },
|
|
@@ -9538,7 +9706,7 @@ var init_migration_history_entity = __esm({
|
|
|
9538
9706
|
});
|
|
9539
9707
|
|
|
9540
9708
|
// src/modules/system/env-config.entity.ts
|
|
9541
|
-
import { useTextField as
|
|
9709
|
+
import { useTextField as useTextField6, useSelectField as useSelectField5, useCheckboxField as useCheckboxField2 } from "@gzl10/nexus-sdk/fields";
|
|
9542
9710
|
function maskValue(value, sensitive) {
|
|
9543
9711
|
if (!sensitive) return value;
|
|
9544
9712
|
try {
|
|
@@ -9563,14 +9731,14 @@ var init_env_config_entity = __esm({
|
|
|
9563
9731
|
routePrefix: "/env-config",
|
|
9564
9732
|
defaultSort: { field: "category", order: "asc" },
|
|
9565
9733
|
fields: {
|
|
9566
|
-
name:
|
|
9734
|
+
name: useTextField6({
|
|
9567
9735
|
label: { en: "Variable", es: "Variable" },
|
|
9568
9736
|
size: 100,
|
|
9569
9737
|
nullable: false,
|
|
9570
9738
|
meta: { sortable: true, searchable: true }
|
|
9571
9739
|
}),
|
|
9572
9740
|
category: {
|
|
9573
|
-
...
|
|
9741
|
+
...useSelectField5({
|
|
9574
9742
|
label: { en: "Category", es: "Categor\xEDa" },
|
|
9575
9743
|
options: [
|
|
9576
9744
|
{ value: "server", label: { en: "Server", es: "Servidor" } },
|
|
@@ -9585,18 +9753,18 @@ var init_env_config_entity = __esm({
|
|
|
9585
9753
|
meta: { sortable: true }
|
|
9586
9754
|
})
|
|
9587
9755
|
},
|
|
9588
|
-
source:
|
|
9756
|
+
source: useTextField6({
|
|
9589
9757
|
label: { en: "Source", es: "Origen" },
|
|
9590
9758
|
size: 50,
|
|
9591
9759
|
nullable: false,
|
|
9592
9760
|
meta: { sortable: true }
|
|
9593
9761
|
}),
|
|
9594
|
-
value:
|
|
9762
|
+
value: useTextField6({
|
|
9595
9763
|
label: { en: "Value", es: "Valor" },
|
|
9596
9764
|
size: 255,
|
|
9597
9765
|
nullable: true
|
|
9598
9766
|
}),
|
|
9599
|
-
default:
|
|
9767
|
+
default: useTextField6({
|
|
9600
9768
|
label: { en: "Default", es: "Por defecto" },
|
|
9601
9769
|
size: 100,
|
|
9602
9770
|
nullable: true
|
|
@@ -10302,7 +10470,7 @@ var init_system = __esm({
|
|
|
10302
10470
|
});
|
|
10303
10471
|
|
|
10304
10472
|
// src/modules/ui-settings/ui-branding.entity.ts
|
|
10305
|
-
import { useTextField as
|
|
10473
|
+
import { useTextField as useTextField7, useImageField } from "@gzl10/nexus-sdk/fields";
|
|
10306
10474
|
var uiBrandingEntity;
|
|
10307
10475
|
var init_ui_branding_entity = __esm({
|
|
10308
10476
|
"src/modules/ui-settings/ui-branding.entity.ts"() {
|
|
@@ -10322,7 +10490,7 @@ var init_ui_branding_entity = __esm({
|
|
|
10322
10490
|
favicon: null
|
|
10323
10491
|
},
|
|
10324
10492
|
fields: {
|
|
10325
|
-
appName:
|
|
10493
|
+
appName: useTextField7({
|
|
10326
10494
|
label: { en: "App Name", es: "Nombre de la App" },
|
|
10327
10495
|
hint: { en: "Displayed in the header, browser tab and emails", es: "Se muestra en el header, pesta\xF1a del navegador y emails" },
|
|
10328
10496
|
size: 100,
|
|
@@ -10363,7 +10531,7 @@ var init_ui_branding_entity = __esm({
|
|
|
10363
10531
|
});
|
|
10364
10532
|
|
|
10365
10533
|
// src/modules/ui-settings/ui-theme.entity.ts
|
|
10366
|
-
import { useSelectField as
|
|
10534
|
+
import { useSelectField as useSelectField6, useColorField } from "@gzl10/nexus-sdk/fields";
|
|
10367
10535
|
var uiThemeEntity;
|
|
10368
10536
|
var init_ui_theme_entity = __esm({
|
|
10369
10537
|
"src/modules/ui-settings/ui-theme.entity.ts"() {
|
|
@@ -10388,7 +10556,7 @@ var init_ui_theme_entity = __esm({
|
|
|
10388
10556
|
},
|
|
10389
10557
|
fields: {
|
|
10390
10558
|
// === Typography ===
|
|
10391
|
-
font:
|
|
10559
|
+
font: useSelectField6({
|
|
10392
10560
|
label: { en: "Font", es: "Fuente" },
|
|
10393
10561
|
hint: { en: "Primary font for headings and UI elements", es: "Fuente principal para t\xEDtulos y elementos de interfaz" },
|
|
10394
10562
|
options: [
|
|
@@ -10401,7 +10569,7 @@ var init_ui_theme_entity = __esm({
|
|
|
10401
10569
|
]
|
|
10402
10570
|
}),
|
|
10403
10571
|
// === Theme & Colors ===
|
|
10404
|
-
theme:
|
|
10572
|
+
theme: useSelectField6({
|
|
10405
10573
|
label: { en: "Theme", es: "Tema" },
|
|
10406
10574
|
hint: { en: "System follows your device preferences", es: "Sistema sigue las preferencias de tu dispositivo" },
|
|
10407
10575
|
options: [
|
|
@@ -10410,7 +10578,7 @@ var init_ui_theme_entity = __esm({
|
|
|
10410
10578
|
{ value: "system", label: { en: "System", es: "Sistema" } }
|
|
10411
10579
|
]
|
|
10412
10580
|
}),
|
|
10413
|
-
dopamineTheme:
|
|
10581
|
+
dopamineTheme: useSelectField6({
|
|
10414
10582
|
label: { en: "Dopamine Theme", es: "Tema Dopamina" },
|
|
10415
10583
|
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)" },
|
|
10416
10584
|
options: [
|
|
@@ -10428,7 +10596,7 @@ var init_ui_theme_entity = __esm({
|
|
|
10428
10596
|
]
|
|
10429
10597
|
}),
|
|
10430
10598
|
// === Login Layout ===
|
|
10431
|
-
loginLayout:
|
|
10599
|
+
loginLayout: useSelectField6({
|
|
10432
10600
|
label: { en: "Login Layout", es: "Dise\xF1o de Login" },
|
|
10433
10601
|
hint: { en: "Visual layout for authentication pages", es: "Dise\xF1o visual para p\xE1ginas de autenticaci\xF3n" },
|
|
10434
10602
|
options: [
|
|
@@ -10459,7 +10627,7 @@ var init_ui_theme_entity = __esm({
|
|
|
10459
10627
|
});
|
|
10460
10628
|
|
|
10461
10629
|
// src/modules/ui-settings/ui-effects.entity.ts
|
|
10462
|
-
import { useSelectField as
|
|
10630
|
+
import { useSelectField as useSelectField7, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
|
|
10463
10631
|
var uiEffectsEntity;
|
|
10464
10632
|
var init_ui_effects_entity = __esm({
|
|
10465
10633
|
"src/modules/ui-settings/ui-effects.entity.ts"() {
|
|
@@ -10479,7 +10647,7 @@ var init_ui_effects_entity = __esm({
|
|
|
10479
10647
|
enableOrganicShapes: false
|
|
10480
10648
|
},
|
|
10481
10649
|
fields: {
|
|
10482
|
-
glassIntensity:
|
|
10650
|
+
glassIntensity: useSelectField7({
|
|
10483
10651
|
label: { en: "Glass Intensity", es: "Intensidad Glass" },
|
|
10484
10652
|
hint: { en: "Glassmorphism blur effect on cards and modals", es: "Efecto de desenfoque glassmorphism en cards y modales" },
|
|
10485
10653
|
options: [
|
|
@@ -10489,7 +10657,7 @@ var init_ui_effects_entity = __esm({
|
|
|
10489
10657
|
{ value: "high", label: { en: "High", es: "Alta" } }
|
|
10490
10658
|
]
|
|
10491
10659
|
}),
|
|
10492
|
-
borderStyle:
|
|
10660
|
+
borderStyle: useSelectField7({
|
|
10493
10661
|
label: { en: "Border Style", es: "Estilo de Bordes" },
|
|
10494
10662
|
hint: { en: "Corner radius for buttons, cards and inputs", es: "Radio de esquinas para botones, cards e inputs" },
|
|
10495
10663
|
options: [
|
|
@@ -10523,7 +10691,7 @@ var init_ui_effects_entity = __esm({
|
|
|
10523
10691
|
});
|
|
10524
10692
|
|
|
10525
10693
|
// src/modules/ui-settings/ui-accessibility.entity.ts
|
|
10526
|
-
import { useSelectField as
|
|
10694
|
+
import { useSelectField as useSelectField8, useSwitchField as useSwitchField3 } from "@gzl10/nexus-sdk/fields";
|
|
10527
10695
|
var uiAccessibilityEntity;
|
|
10528
10696
|
var init_ui_accessibility_entity = __esm({
|
|
10529
10697
|
"src/modules/ui-settings/ui-accessibility.entity.ts"() {
|
|
@@ -10542,7 +10710,7 @@ var init_ui_accessibility_entity = __esm({
|
|
|
10542
10710
|
highContrast: false
|
|
10543
10711
|
},
|
|
10544
10712
|
fields: {
|
|
10545
|
-
typographyScale:
|
|
10713
|
+
typographyScale: useSelectField8({
|
|
10546
10714
|
label: { en: "Typography Scale", es: "Escala Tipogr\xE1fica" },
|
|
10547
10715
|
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)" },
|
|
10548
10716
|
options: [
|
|
@@ -11533,7 +11701,7 @@ var init_storage_service = __esm({
|
|
|
11533
11701
|
});
|
|
11534
11702
|
|
|
11535
11703
|
// src/modules/storage/storage.entity.ts
|
|
11536
|
-
import { useIdField as useIdField3, useTextField as
|
|
11704
|
+
import { useIdField as useIdField3, useTextField as useTextField8, useSelectField as useSelectField9, useUrlField, useNumberField as useNumberField4, useCheckboxField as useCheckboxField3, useJsonField as useJsonField2, useMetadataField, usePublicField } from "@gzl10/nexus-sdk/fields";
|
|
11537
11705
|
var DEFAULT_MAX_SIZE2, storageConfigEntity, storageFilesEntity;
|
|
11538
11706
|
var init_storage_entity = __esm({
|
|
11539
11707
|
"src/modules/storage/storage.entity.ts"() {
|
|
@@ -11559,7 +11727,7 @@ var init_storage_entity = __esm({
|
|
|
11559
11727
|
},
|
|
11560
11728
|
fields: {
|
|
11561
11729
|
id: useIdField3(),
|
|
11562
|
-
scope:
|
|
11730
|
+
scope: useTextField8({
|
|
11563
11731
|
label: { en: "Scope", es: "\xC1mbito" },
|
|
11564
11732
|
disabled: true,
|
|
11565
11733
|
size: 100,
|
|
@@ -11568,7 +11736,7 @@ var init_storage_entity = __esm({
|
|
|
11568
11736
|
hint: { en: "Unique identifier (e.g. default_filesystem, default_s3)", es: "Identificador \xFAnico (ej: default_filesystem, default_s3)" }
|
|
11569
11737
|
}),
|
|
11570
11738
|
driver: {
|
|
11571
|
-
...
|
|
11739
|
+
...useSelectField9({
|
|
11572
11740
|
label: { en: "Driver", es: "Controlador" },
|
|
11573
11741
|
required: true,
|
|
11574
11742
|
hint: { en: "Storage backend", es: "Backend de almacenamiento" },
|
|
@@ -11591,7 +11759,7 @@ var init_storage_entity = __esm({
|
|
|
11591
11759
|
nullable: false,
|
|
11592
11760
|
displayProps: { format: "bytes" }
|
|
11593
11761
|
}),
|
|
11594
|
-
allowed_mime_types:
|
|
11762
|
+
allowed_mime_types: useTextField8({
|
|
11595
11763
|
label: { en: "Allowed MIME Types", es: "Tipos MIME permitidos" },
|
|
11596
11764
|
hint: { en: "Allowed types separated by comma (e.g. image/*,application/pdf)", es: "Tipos permitidos separados por coma (ej: image/*,application/pdf)" },
|
|
11597
11765
|
size: 1e3,
|
|
@@ -11756,21 +11924,21 @@ var init_storage_entity = __esm({
|
|
|
11756
11924
|
],
|
|
11757
11925
|
fields: {
|
|
11758
11926
|
id: useIdField3(),
|
|
11759
|
-
filename:
|
|
11927
|
+
filename: useTextField8({
|
|
11760
11928
|
label: { en: "Original Filename", es: "Nombre original" },
|
|
11761
11929
|
required: true,
|
|
11762
11930
|
size: 255,
|
|
11763
11931
|
nullable: false,
|
|
11764
11932
|
meta: { sortable: true, searchable: true }
|
|
11765
11933
|
}),
|
|
11766
|
-
disk_filename:
|
|
11934
|
+
disk_filename: useTextField8({
|
|
11767
11935
|
label: { en: "Disk Filename", es: "Nombre en disco" },
|
|
11768
11936
|
required: true,
|
|
11769
11937
|
hidden: true,
|
|
11770
11938
|
size: 255,
|
|
11771
11939
|
nullable: false
|
|
11772
11940
|
}),
|
|
11773
|
-
mimetype:
|
|
11941
|
+
mimetype: useTextField8({
|
|
11774
11942
|
label: { en: "MIME Type", es: "Tipo MIME" },
|
|
11775
11943
|
required: true,
|
|
11776
11944
|
size: 100,
|
|
@@ -11786,14 +11954,14 @@ var init_storage_entity = __esm({
|
|
|
11786
11954
|
meta: { sortable: true },
|
|
11787
11955
|
displayProps: { format: "bytes" }
|
|
11788
11956
|
}),
|
|
11789
|
-
folder:
|
|
11957
|
+
folder: useTextField8({
|
|
11790
11958
|
label: { en: "Folder", es: "Carpeta" },
|
|
11791
11959
|
size: 100,
|
|
11792
11960
|
nullable: true,
|
|
11793
11961
|
index: true,
|
|
11794
11962
|
meta: { searchable: true }
|
|
11795
11963
|
}),
|
|
11796
|
-
scope:
|
|
11964
|
+
scope: useTextField8({
|
|
11797
11965
|
label: { en: "Storage Scope", es: "\xC1mbito de almacenamiento" },
|
|
11798
11966
|
hidden: true,
|
|
11799
11967
|
size: 50,
|
|
@@ -11804,7 +11972,7 @@ var init_storage_entity = __esm({
|
|
|
11804
11972
|
es: "\xC1mbito de configuraci\xF3n de almacenamiento usado para este archivo"
|
|
11805
11973
|
}
|
|
11806
11974
|
}),
|
|
11807
|
-
path:
|
|
11975
|
+
path: useTextField8({
|
|
11808
11976
|
label: { en: "Full Path", es: "Ruta completa" },
|
|
11809
11977
|
required: true,
|
|
11810
11978
|
hidden: true,
|
|
@@ -11817,13 +11985,13 @@ var init_storage_entity = __esm({
|
|
|
11817
11985
|
nullable: true,
|
|
11818
11986
|
meta: { exportable: true, showInDisplay: false }
|
|
11819
11987
|
}),
|
|
11820
|
-
thumbnail_path:
|
|
11988
|
+
thumbnail_path: useTextField8({
|
|
11821
11989
|
label: { en: "Thumbnail Path", es: "Ruta de miniatura" },
|
|
11822
11990
|
size: 500,
|
|
11823
11991
|
nullable: true,
|
|
11824
11992
|
meta: { showInDisplay: false }
|
|
11825
11993
|
}),
|
|
11826
|
-
hash:
|
|
11994
|
+
hash: useTextField8({
|
|
11827
11995
|
label: { en: "SHA256 Hash", es: "Hash SHA256" },
|
|
11828
11996
|
hidden: true,
|
|
11829
11997
|
size: 64,
|
|
@@ -12320,7 +12488,7 @@ var init_storage = __esm({
|
|
|
12320
12488
|
});
|
|
12321
12489
|
|
|
12322
12490
|
// src/modules/users/users.entity.ts
|
|
12323
|
-
import { useIdField as useIdField4, useSelectField as
|
|
12491
|
+
import { useIdField as useIdField4, useSelectField as useSelectField10, useEmailField, usePasswordField, useTextField as useTextField9, useDatetimeField as useDatetimeField3, useCheckboxField as useCheckboxField4, useImageField as useImageField2, useNameField as useNameField2, useMetadataField as useMetadataField2, useDescriptionField as useDescriptionField2 } from "@gzl10/nexus-sdk/fields";
|
|
12324
12492
|
import { z as z3 } from "zod";
|
|
12325
12493
|
var userEntity, roleEntity, userRoleEntity;
|
|
12326
12494
|
var init_users_entity = __esm({
|
|
@@ -12383,7 +12551,7 @@ var init_users_entity = __esm({
|
|
|
12383
12551
|
nullable: true,
|
|
12384
12552
|
meta: { exportable: true, showInForm: false, showInDisplay: false }
|
|
12385
12553
|
}),
|
|
12386
|
-
consent_version:
|
|
12554
|
+
consent_version: useTextField9({
|
|
12387
12555
|
label: { en: "Consent Version", es: "Versi\xF3n de consentimiento" },
|
|
12388
12556
|
hidden: true,
|
|
12389
12557
|
size: 20,
|
|
@@ -12394,7 +12562,7 @@ var init_users_entity = __esm({
|
|
|
12394
12562
|
label: { en: "Marketing Opt-in", es: "Aceptar marketing" },
|
|
12395
12563
|
meta: { exportable: true, showInForm: false, showInDisplay: false }
|
|
12396
12564
|
}),
|
|
12397
|
-
locale:
|
|
12565
|
+
locale: useSelectField10({
|
|
12398
12566
|
label: { en: "Language", es: "Idioma" },
|
|
12399
12567
|
options: [
|
|
12400
12568
|
{ value: "es", label: { en: "Spanish", es: "Espa\xF1ol" } },
|
|
@@ -12404,13 +12572,13 @@ var init_users_entity = __esm({
|
|
|
12404
12572
|
meta: { sortable: true },
|
|
12405
12573
|
defaultValue: "en"
|
|
12406
12574
|
}),
|
|
12407
|
-
timezone:
|
|
12575
|
+
timezone: useSelectField10({
|
|
12408
12576
|
label: { en: "Timezone", es: "Zona horaria" },
|
|
12409
12577
|
master: "timezones",
|
|
12410
12578
|
meta: { sortable: true },
|
|
12411
12579
|
defaultValue: "timezones:Europe/Madrid"
|
|
12412
12580
|
}),
|
|
12413
|
-
type:
|
|
12581
|
+
type: useSelectField10({
|
|
12414
12582
|
label: { en: "Type", es: "Tipo" },
|
|
12415
12583
|
defaultValue: "human",
|
|
12416
12584
|
options: [
|
|
@@ -12579,7 +12747,7 @@ var init_users_entity = __esm({
|
|
|
12579
12747
|
expose: false,
|
|
12580
12748
|
fields: {
|
|
12581
12749
|
id: useIdField4(),
|
|
12582
|
-
user_id:
|
|
12750
|
+
user_id: useSelectField10({
|
|
12583
12751
|
label: { en: "User", es: "Usuario" },
|
|
12584
12752
|
required: true,
|
|
12585
12753
|
table: "users",
|
|
@@ -12590,7 +12758,7 @@ var init_users_entity = __esm({
|
|
|
12590
12758
|
labelField: "name",
|
|
12591
12759
|
meta: { searchable: true }
|
|
12592
12760
|
}),
|
|
12593
|
-
role_id:
|
|
12761
|
+
role_id: useSelectField10({
|
|
12594
12762
|
label: { en: "Role", es: "Rol" },
|
|
12595
12763
|
required: true,
|
|
12596
12764
|
table: "roles",
|
|
@@ -13534,7 +13702,7 @@ var init_users = __esm({
|
|
|
13534
13702
|
});
|
|
13535
13703
|
|
|
13536
13704
|
// src/modules/auth/auth.entity.ts
|
|
13537
|
-
import { useIdField as useIdField5, useTextField as
|
|
13705
|
+
import { useIdField as useIdField5, useTextField as useTextField10, useSelectField as useSelectField11, useDatetimeField as useDatetimeField4, useEmailField as useEmailField2, useMetadataField as useMetadataField3, useExpiresAtField } from "@gzl10/nexus-sdk/fields";
|
|
13538
13706
|
var refreshTokenEntity, authIdentitiesEntity;
|
|
13539
13707
|
var init_auth_entity = __esm({
|
|
13540
13708
|
"src/modules/auth/auth.entity.ts"() {
|
|
@@ -13549,7 +13717,7 @@ var init_auth_entity = __esm({
|
|
|
13549
13717
|
expose: false,
|
|
13550
13718
|
fields: {
|
|
13551
13719
|
id: useIdField5(),
|
|
13552
|
-
token:
|
|
13720
|
+
token: useTextField10({
|
|
13553
13721
|
label: { en: "Token", es: "Token" },
|
|
13554
13722
|
hidden: true,
|
|
13555
13723
|
size: 255,
|
|
@@ -13576,14 +13744,14 @@ var init_auth_entity = __esm({
|
|
|
13576
13744
|
nullable: true,
|
|
13577
13745
|
meta: { sortable: true }
|
|
13578
13746
|
}),
|
|
13579
|
-
device_id:
|
|
13747
|
+
device_id: useTextField10({
|
|
13580
13748
|
label: { en: "Device ID", es: "ID de dispositivo" },
|
|
13581
13749
|
size: 64,
|
|
13582
13750
|
index: true,
|
|
13583
13751
|
nullable: true,
|
|
13584
13752
|
meta: { searchable: true }
|
|
13585
13753
|
}),
|
|
13586
|
-
device_name:
|
|
13754
|
+
device_name: useTextField10({
|
|
13587
13755
|
label: { en: "Device", es: "Dispositivo" },
|
|
13588
13756
|
size: 100,
|
|
13589
13757
|
nullable: true,
|
|
@@ -13615,7 +13783,7 @@ var init_auth_entity = __esm({
|
|
|
13615
13783
|
order: 5,
|
|
13616
13784
|
fields: {
|
|
13617
13785
|
id: useIdField5(),
|
|
13618
|
-
user_id:
|
|
13786
|
+
user_id: useSelectField11({
|
|
13619
13787
|
label: { en: "User", es: "Usuario" },
|
|
13620
13788
|
table: "users",
|
|
13621
13789
|
column: "id",
|
|
@@ -13627,7 +13795,7 @@ var init_auth_entity = __esm({
|
|
|
13627
13795
|
labelField: "name",
|
|
13628
13796
|
meta: { searchable: true }
|
|
13629
13797
|
}),
|
|
13630
|
-
provider:
|
|
13798
|
+
provider: useTextField10({
|
|
13631
13799
|
label: { en: "Provider", es: "Proveedor" },
|
|
13632
13800
|
required: true,
|
|
13633
13801
|
size: 50,
|
|
@@ -13636,7 +13804,7 @@ var init_auth_entity = __esm({
|
|
|
13636
13804
|
hint: { en: "e.g. pocketid, google, microsoft", es: "ej. pocketid, google, microsoft" },
|
|
13637
13805
|
meta: { sortable: true, searchable: true }
|
|
13638
13806
|
}),
|
|
13639
|
-
provider_user_id:
|
|
13807
|
+
provider_user_id: useTextField10({
|
|
13640
13808
|
label: { en: "Provider User ID", es: "ID de usuario del proveedor" },
|
|
13641
13809
|
required: true,
|
|
13642
13810
|
size: 255,
|
|
@@ -13931,7 +14099,7 @@ var init_auth_middleware = __esm({
|
|
|
13931
14099
|
});
|
|
13932
14100
|
|
|
13933
14101
|
// src/modules/auth/auth.pat.entity.ts
|
|
13934
|
-
import { useIdField as useIdField6, useTextField as
|
|
14102
|
+
import { useIdField as useIdField6, useTextField as useTextField11, useSelectField as useSelectField12, useDatetimeField as useDatetimeField5, useExpiresAtField as useExpiresAtField2 } from "@gzl10/nexus-sdk/fields";
|
|
13935
14103
|
var personalTokenEntity;
|
|
13936
14104
|
var init_auth_pat_entity = __esm({
|
|
13937
14105
|
"src/modules/auth/auth.pat.entity.ts"() {
|
|
@@ -13948,7 +14116,7 @@ var init_auth_pat_entity = __esm({
|
|
|
13948
14116
|
routePrefix: "/personal-tokens",
|
|
13949
14117
|
fields: {
|
|
13950
14118
|
id: useIdField6(),
|
|
13951
|
-
user_id:
|
|
14119
|
+
user_id: useSelectField12({
|
|
13952
14120
|
label: { en: "User", es: "Usuario" },
|
|
13953
14121
|
table: "users",
|
|
13954
14122
|
column: "id",
|
|
@@ -13960,7 +14128,7 @@ var init_auth_pat_entity = __esm({
|
|
|
13960
14128
|
labelField: "name",
|
|
13961
14129
|
meta: { searchable: true }
|
|
13962
14130
|
}),
|
|
13963
|
-
name:
|
|
14131
|
+
name: useTextField11({
|
|
13964
14132
|
label: { en: "Name", es: "Nombre" },
|
|
13965
14133
|
required: true,
|
|
13966
14134
|
size: 100,
|
|
@@ -13968,14 +14136,14 @@ var init_auth_pat_entity = __esm({
|
|
|
13968
14136
|
hint: { en: "Descriptive name for this token", es: "Nombre descriptivo para este token" },
|
|
13969
14137
|
meta: { searchable: true }
|
|
13970
14138
|
}),
|
|
13971
|
-
token_prefix:
|
|
14139
|
+
token_prefix: useTextField11({
|
|
13972
14140
|
label: { en: "Token", es: "Token" },
|
|
13973
14141
|
size: 20,
|
|
13974
14142
|
disabled: true,
|
|
13975
14143
|
nullable: false,
|
|
13976
14144
|
hint: { en: "Partial token for identification", es: "Token parcial para identificaci\xF3n" }
|
|
13977
14145
|
}),
|
|
13978
|
-
token_hash:
|
|
14146
|
+
token_hash: useTextField11({
|
|
13979
14147
|
label: { en: "Token Hash", es: "Hash del token" },
|
|
13980
14148
|
size: 64,
|
|
13981
14149
|
hidden: true,
|
|
@@ -13983,7 +14151,7 @@ var init_auth_pat_entity = __esm({
|
|
|
13983
14151
|
unique: true,
|
|
13984
14152
|
meta: { exportable: false }
|
|
13985
14153
|
}),
|
|
13986
|
-
scope:
|
|
14154
|
+
scope: useSelectField12({
|
|
13987
14155
|
label: { en: "Permission", es: "Permiso" },
|
|
13988
14156
|
required: true,
|
|
13989
14157
|
options: [
|
|
@@ -15739,7 +15907,7 @@ var init_mail_service = __esm({
|
|
|
15739
15907
|
});
|
|
15740
15908
|
|
|
15741
15909
|
// src/modules/mail/mail.entity.ts
|
|
15742
|
-
import { useIdField as useIdField7, useTextField as
|
|
15910
|
+
import { useIdField as useIdField7, useTextField as useTextField12, useSelectField as useSelectField13, useNumberField as useNumberField5, useSwitchField as useSwitchField4, useEmailField as useEmailField3, usePasswordField as usePasswordField2, useTextareaField as useTextareaField3, useTagsField as useTagsField2, useDatetimeField as useDatetimeField6 } from "@gzl10/nexus-sdk/fields";
|
|
15743
15911
|
import nodemailer2 from "nodemailer";
|
|
15744
15912
|
async function getMailConfigFromDB(ctx) {
|
|
15745
15913
|
const configService = ctx.services["config"];
|
|
@@ -15802,7 +15970,7 @@ var init_mail_entity = __esm({
|
|
|
15802
15970
|
},
|
|
15803
15971
|
fields: {
|
|
15804
15972
|
id: useIdField7(),
|
|
15805
|
-
host:
|
|
15973
|
+
host: useTextField12({
|
|
15806
15974
|
label: { en: "SMTP Host", es: "Host SMTP" },
|
|
15807
15975
|
size: 255,
|
|
15808
15976
|
nullable: false,
|
|
@@ -15822,7 +15990,7 @@ var init_mail_entity = __esm({
|
|
|
15822
15990
|
nullable: false,
|
|
15823
15991
|
hint: { en: "Default: SMTP_FROM env var", es: "Por defecto: variable SMTP_FROM" }
|
|
15824
15992
|
}),
|
|
15825
|
-
auth_user:
|
|
15993
|
+
auth_user: useTextField12({
|
|
15826
15994
|
label: { en: "Auth User", es: "Usuario de autenticaci\xF3n" },
|
|
15827
15995
|
size: 255,
|
|
15828
15996
|
nullable: true,
|
|
@@ -15854,12 +16022,12 @@ var init_mail_entity = __esm({
|
|
|
15854
16022
|
required: true,
|
|
15855
16023
|
validation: { format: "email" }
|
|
15856
16024
|
}),
|
|
15857
|
-
subject:
|
|
16025
|
+
subject: useTextField12({
|
|
15858
16026
|
label: { en: "Subject", es: "Asunto" },
|
|
15859
16027
|
required: true,
|
|
15860
16028
|
validation: { min: 1, max: 255 }
|
|
15861
16029
|
}),
|
|
15862
|
-
title:
|
|
16030
|
+
title: useTextField12({
|
|
15863
16031
|
label: { en: "Title", es: "T\xEDtulo" },
|
|
15864
16032
|
hint: { en: "Large title in email header", es: "T\xEDtulo grande en la cabecera del correo" }
|
|
15865
16033
|
}),
|
|
@@ -16003,20 +16171,20 @@ var init_mail_entity = __esm({
|
|
|
16003
16171
|
nullable: false,
|
|
16004
16172
|
meta: { sortable: true }
|
|
16005
16173
|
}),
|
|
16006
|
-
to:
|
|
16174
|
+
to: useTextField12({
|
|
16007
16175
|
label: { en: "Recipient(s)", es: "Destinatario(s)" },
|
|
16008
16176
|
size: 1e3,
|
|
16009
16177
|
nullable: false,
|
|
16010
16178
|
meta: { searchable: true }
|
|
16011
16179
|
}),
|
|
16012
|
-
subject:
|
|
16180
|
+
subject: useTextField12({
|
|
16013
16181
|
label: { en: "Subject", es: "Asunto" },
|
|
16014
16182
|
size: 255,
|
|
16015
16183
|
nullable: false,
|
|
16016
16184
|
meta: { searchable: true, sortable: true }
|
|
16017
16185
|
}),
|
|
16018
16186
|
status: {
|
|
16019
|
-
...
|
|
16187
|
+
...useSelectField13({
|
|
16020
16188
|
label: { en: "Status", es: "Estado" },
|
|
16021
16189
|
options: [
|
|
16022
16190
|
{ value: "pending", label: { en: "Pending", es: "Pendiente" } },
|
|
@@ -16030,7 +16198,7 @@ var init_mail_entity = __esm({
|
|
|
16030
16198
|
}),
|
|
16031
16199
|
validation: { enum: ["pending", "sent", "failed", "bounced"] }
|
|
16032
16200
|
},
|
|
16033
|
-
message_id:
|
|
16201
|
+
message_id: useTextField12({
|
|
16034
16202
|
label: { en: "Message ID", es: "ID de mensaje" },
|
|
16035
16203
|
hidden: true,
|
|
16036
16204
|
size: 255,
|
|
@@ -16040,7 +16208,7 @@ var init_mail_entity = __esm({
|
|
|
16040
16208
|
label: { en: "Error", es: "Error" },
|
|
16041
16209
|
nullable: true
|
|
16042
16210
|
}),
|
|
16043
|
-
sent_by:
|
|
16211
|
+
sent_by: useSelectField13({
|
|
16044
16212
|
label: { en: "Sent by", es: "Enviado por" },
|
|
16045
16213
|
table: "users",
|
|
16046
16214
|
column: "id",
|
|
@@ -16646,7 +16814,7 @@ var init_toggle_plugin_action = __esm({
|
|
|
16646
16814
|
});
|
|
16647
16815
|
|
|
16648
16816
|
// src/modules/plugins/plugins.entity.ts
|
|
16649
|
-
import { useTextField as
|
|
16817
|
+
import { useTextField as useTextField13, useSelectField as useSelectField14, useCheckboxField as useCheckboxField5 } from "@gzl10/nexus-sdk/fields";
|
|
16650
16818
|
import { OFFICIAL_PLUGINS } from "@gzl10/nexus-sdk";
|
|
16651
16819
|
var allowPluginManagement, pluginsEntity;
|
|
16652
16820
|
var init_plugins_entity = __esm({
|
|
@@ -16665,30 +16833,30 @@ var init_plugins_entity = __esm({
|
|
|
16665
16833
|
routePrefix: "/",
|
|
16666
16834
|
defaultSort: { field: "name", order: "asc" },
|
|
16667
16835
|
fields: {
|
|
16668
|
-
name:
|
|
16836
|
+
name: useTextField13({
|
|
16669
16837
|
label: { en: "Name", es: "Nombre" },
|
|
16670
16838
|
size: 50,
|
|
16671
16839
|
nullable: false,
|
|
16672
16840
|
meta: { sortable: true, searchable: true }
|
|
16673
16841
|
}),
|
|
16674
|
-
code:
|
|
16842
|
+
code: useTextField13({
|
|
16675
16843
|
label: { en: "Code", es: "C\xF3digo" },
|
|
16676
16844
|
size: 10,
|
|
16677
16845
|
nullable: false,
|
|
16678
16846
|
meta: { sortable: true }
|
|
16679
16847
|
}),
|
|
16680
|
-
label:
|
|
16848
|
+
label: useTextField13({
|
|
16681
16849
|
label: { en: "Label", es: "Etiqueta" },
|
|
16682
16850
|
size: 100,
|
|
16683
16851
|
nullable: false,
|
|
16684
16852
|
meta: { sortable: true }
|
|
16685
16853
|
}),
|
|
16686
|
-
version:
|
|
16854
|
+
version: useTextField13({
|
|
16687
16855
|
label: { en: "Version", es: "Versi\xF3n" },
|
|
16688
16856
|
size: 20,
|
|
16689
16857
|
nullable: false
|
|
16690
16858
|
}),
|
|
16691
|
-
category:
|
|
16859
|
+
category: useSelectField14({
|
|
16692
16860
|
label: { en: "Category", es: "Categor\xEDa" },
|
|
16693
16861
|
options: [
|
|
16694
16862
|
{ value: "content", label: { en: "Content", es: "Contenido" } },
|
|
@@ -16829,8 +16997,8 @@ var init_plugins = __esm({
|
|
|
16829
16997
|
// src/modules/audit/audit.entity.ts
|
|
16830
16998
|
import {
|
|
16831
16999
|
useIdField as useIdField8,
|
|
16832
|
-
useTextField as
|
|
16833
|
-
useSelectField as
|
|
17000
|
+
useTextField as useTextField14,
|
|
17001
|
+
useSelectField as useSelectField15,
|
|
16834
17002
|
useTextareaField as useTextareaField4,
|
|
16835
17003
|
useJsonField as useJsonField3,
|
|
16836
17004
|
useDatetimeField as useDatetimeField7,
|
|
@@ -16853,7 +17021,7 @@ var init_audit_entity = __esm({
|
|
|
16853
17021
|
fields: {
|
|
16854
17022
|
id: useIdField8(),
|
|
16855
17023
|
source: {
|
|
16856
|
-
...
|
|
17024
|
+
...useTextField14({
|
|
16857
17025
|
label: { en: "Source", es: "Origen" },
|
|
16858
17026
|
size: 100,
|
|
16859
17027
|
nullable: false,
|
|
@@ -16863,7 +17031,7 @@ var init_audit_entity = __esm({
|
|
|
16863
17031
|
validation: { min: 1, max: 100 }
|
|
16864
17032
|
},
|
|
16865
17033
|
action: {
|
|
16866
|
-
...
|
|
17034
|
+
...useTextField14({
|
|
16867
17035
|
label: { en: "Action", es: "Acci\xF3n" },
|
|
16868
17036
|
size: 100,
|
|
16869
17037
|
nullable: false,
|
|
@@ -16872,7 +17040,7 @@ var init_audit_entity = __esm({
|
|
|
16872
17040
|
}),
|
|
16873
17041
|
validation: { min: 1, max: 100 }
|
|
16874
17042
|
},
|
|
16875
|
-
actor_id:
|
|
17043
|
+
actor_id: useSelectField15({
|
|
16876
17044
|
label: { en: "Actor", es: "Actor" },
|
|
16877
17045
|
table: "users",
|
|
16878
17046
|
column: "id",
|
|
@@ -16889,20 +17057,20 @@ var init_audit_entity = __esm({
|
|
|
16889
17057
|
nullable: true,
|
|
16890
17058
|
meta: { searchable: true }
|
|
16891
17059
|
}),
|
|
16892
|
-
resource_type:
|
|
17060
|
+
resource_type: useTextField14({
|
|
16893
17061
|
label: { en: "Resource Type", es: "Tipo de recurso" },
|
|
16894
17062
|
size: 100,
|
|
16895
17063
|
nullable: true,
|
|
16896
17064
|
index: true,
|
|
16897
17065
|
meta: { searchable: true }
|
|
16898
17066
|
}),
|
|
16899
|
-
resource_id:
|
|
17067
|
+
resource_id: useTextField14({
|
|
16900
17068
|
label: { en: "Resource ID", es: "ID del recurso" },
|
|
16901
17069
|
size: 100,
|
|
16902
17070
|
nullable: true,
|
|
16903
17071
|
meta: { searchable: true }
|
|
16904
17072
|
}),
|
|
16905
|
-
ip_address:
|
|
17073
|
+
ip_address: useTextField14({
|
|
16906
17074
|
label: { en: "IP Address", es: "Direcci\xF3n IP" },
|
|
16907
17075
|
size: 45,
|
|
16908
17076
|
nullable: true,
|
|
@@ -17655,6 +17823,7 @@ var init_error_codes = __esm({
|
|
|
17655
17823
|
DB_CONSTRAINT_UNIQUE: "DB_CONSTRAINT_UNIQUE",
|
|
17656
17824
|
DB_CONSTRAINT_FK: "DB_CONSTRAINT_FK",
|
|
17657
17825
|
DB_CONNECTION_ERROR: "DB_CONNECTION_ERROR",
|
|
17826
|
+
DATABASE_NOT_READY: "DATABASE_NOT_READY",
|
|
17658
17827
|
// System
|
|
17659
17828
|
SYSTEM_INTERNAL_ERROR: "SYSTEM_INTERNAL_ERROR"
|
|
17660
17829
|
};
|
|
@@ -17962,7 +18131,7 @@ var init_env = __esm({
|
|
|
17962
18131
|
envSchema = z8.object({
|
|
17963
18132
|
NODE_ENV: z8.enum(["development", "production", "test"]).default("development"),
|
|
17964
18133
|
PORT: z8.coerce.number().default(3e3),
|
|
17965
|
-
CORS_ORIGIN: z8.string().default("
|
|
18134
|
+
CORS_ORIGIN: z8.string().default("*"),
|
|
17966
18135
|
BACKEND_URL: z8.string().optional(),
|
|
17967
18136
|
DATABASE_URL: z8.string().default("file:./dev.db"),
|
|
17968
18137
|
REDIS_URL: z8.string().url().optional(),
|
|
@@ -20231,10 +20400,31 @@ var init_base_service = __esm({
|
|
|
20231
20400
|
* Override in subclasses for entity-specific search
|
|
20232
20401
|
*/
|
|
20233
20402
|
applySearch(qb, search) {
|
|
20403
|
+
const searchTerm = `%${search}%`;
|
|
20404
|
+
const searchableFields = [];
|
|
20405
|
+
const fields = "fields" in this.definition ? this.definition.fields : {};
|
|
20406
|
+
for (const [name, field] of Object.entries(fields)) {
|
|
20407
|
+
if (field.meta?.searchable) {
|
|
20408
|
+
searchableFields.push(name);
|
|
20409
|
+
}
|
|
20410
|
+
}
|
|
20234
20411
|
if ("labelField" in this.definition && this.definition.labelField) {
|
|
20235
|
-
const
|
|
20236
|
-
|
|
20412
|
+
const lf = this.definition.labelField;
|
|
20413
|
+
if (!searchableFields.includes(lf)) {
|
|
20414
|
+
searchableFields.unshift(lf);
|
|
20415
|
+
}
|
|
20237
20416
|
}
|
|
20417
|
+
if (searchableFields.length === 0) return qb;
|
|
20418
|
+
qb.where(function() {
|
|
20419
|
+
for (const fieldName of searchableFields) {
|
|
20420
|
+
const field = fields[fieldName];
|
|
20421
|
+
if (field?.db?.type === "json") {
|
|
20422
|
+
this.orWhereRaw(`CAST(?? AS TEXT) LIKE ?`, [fieldName, searchTerm]);
|
|
20423
|
+
} else {
|
|
20424
|
+
this.orWhere(fieldName, "like", searchTerm);
|
|
20425
|
+
}
|
|
20426
|
+
}
|
|
20427
|
+
});
|
|
20238
20428
|
return qb;
|
|
20239
20429
|
}
|
|
20240
20430
|
/**
|
|
@@ -23693,15 +23883,6 @@ var init_ensure_system_tables = __esm({
|
|
|
23693
23883
|
}
|
|
23694
23884
|
});
|
|
23695
23885
|
|
|
23696
|
-
// src/cli/shared.ts
|
|
23697
|
-
import { consola } from "consola";
|
|
23698
|
-
var init_shared = __esm({
|
|
23699
|
-
"src/cli/shared.ts"() {
|
|
23700
|
-
"use strict";
|
|
23701
|
-
init_logger();
|
|
23702
|
-
}
|
|
23703
|
-
});
|
|
23704
|
-
|
|
23705
23886
|
// src/db/migration-sources.ts
|
|
23706
23887
|
function buildMigrationSources() {
|
|
23707
23888
|
const sources = [
|
|
@@ -23721,9 +23902,7 @@ function buildMigrationSources() {
|
|
|
23721
23902
|
var init_migration_sources = __esm({
|
|
23722
23903
|
"src/db/migration-sources.ts"() {
|
|
23723
23904
|
"use strict";
|
|
23724
|
-
init_shared();
|
|
23725
23905
|
init_paths();
|
|
23726
|
-
init_plugin_ops();
|
|
23727
23906
|
init_module_store();
|
|
23728
23907
|
}
|
|
23729
23908
|
});
|
|
@@ -25001,6 +25180,10 @@ function handleDbError(err) {
|
|
|
25001
25180
|
{ path: "foreignKey", message: "Foreign key constraint violation" }
|
|
25002
25181
|
]);
|
|
25003
25182
|
}
|
|
25183
|
+
if (code === "42P01" || code === "ER_NO_SUCH_TABLE" || dbErr.errno === 1146 || msg.includes("no such table")) {
|
|
25184
|
+
logger.error({ err }, "Database table not found \u2014 database may need migration or was wiped");
|
|
25185
|
+
throw new AppError({ code: ErrorCodes.DATABASE_NOT_READY, message: "Database not ready" }, 503);
|
|
25186
|
+
}
|
|
25004
25187
|
logger.error({ err }, "Unexpected database error");
|
|
25005
25188
|
throw new AppError({ code: ErrorCodes.SYSTEM_INTERNAL_ERROR, message: "Internal database error" }, 500);
|
|
25006
25189
|
}
|
|
@@ -27283,6 +27466,33 @@ async function setupModuleRoutes(app) {
|
|
|
27283
27466
|
}
|
|
27284
27467
|
}
|
|
27285
27468
|
const caslRegistry = /* @__PURE__ */ new Map();
|
|
27469
|
+
function mergeActionPermissions(existing, incoming) {
|
|
27470
|
+
const merged = { ...existing };
|
|
27471
|
+
for (const [role, perm] of Object.entries(incoming)) {
|
|
27472
|
+
if (!merged[role]) {
|
|
27473
|
+
merged[role] = perm;
|
|
27474
|
+
} else {
|
|
27475
|
+
const existingArr = Array.isArray(merged[role]) ? merged[role] : [merged[role]];
|
|
27476
|
+
const incomingArr = Array.isArray(perm) ? perm : [perm];
|
|
27477
|
+
merged[role] = [...existingArr, ...incomingArr];
|
|
27478
|
+
}
|
|
27479
|
+
}
|
|
27480
|
+
return merged;
|
|
27481
|
+
}
|
|
27482
|
+
function registerActionCasl(action) {
|
|
27483
|
+
const casl = action.casl;
|
|
27484
|
+
if (!casl || !("subject" in casl) || !casl.subject || !("permissions" in casl) || !casl.permissions) return;
|
|
27485
|
+
const subject2 = casl.subject;
|
|
27486
|
+
const existing = caslRegistry.get(subject2);
|
|
27487
|
+
if (existing) {
|
|
27488
|
+
existing.permissions = mergeActionPermissions(existing.permissions, casl.permissions);
|
|
27489
|
+
} else {
|
|
27490
|
+
caslRegistry.set(subject2, {
|
|
27491
|
+
subject: subject2,
|
|
27492
|
+
permissions: casl.permissions ?? {}
|
|
27493
|
+
});
|
|
27494
|
+
}
|
|
27495
|
+
}
|
|
27286
27496
|
for (const mod of modules) {
|
|
27287
27497
|
for (const def of mod.definitions ?? []) {
|
|
27288
27498
|
const casl = def.casl;
|
|
@@ -27292,6 +27502,12 @@ async function setupModuleRoutes(app) {
|
|
|
27292
27502
|
subject: casl.subject,
|
|
27293
27503
|
permissions: casl.permissions ?? {}
|
|
27294
27504
|
});
|
|
27505
|
+
for (const action of def.actions ?? []) {
|
|
27506
|
+
registerActionCasl(action);
|
|
27507
|
+
}
|
|
27508
|
+
}
|
|
27509
|
+
for (const action of mod.actions ?? []) {
|
|
27510
|
+
registerActionCasl(action);
|
|
27295
27511
|
}
|
|
27296
27512
|
}
|
|
27297
27513
|
setEntityDefinitions(caslRegistry);
|
|
@@ -27670,7 +27886,7 @@ function isFrpcInstalled() {
|
|
|
27670
27886
|
return false;
|
|
27671
27887
|
}
|
|
27672
27888
|
}
|
|
27673
|
-
function startTunnel(config3) {
|
|
27889
|
+
async function startTunnel(config3) {
|
|
27674
27890
|
if (tunnelProcess) return true;
|
|
27675
27891
|
if (!isFrpcInstalled()) {
|
|
27676
27892
|
logger.warn("frpc binary not found \u2014 tunnel disabled. Install with: brew install frp");
|
|
@@ -27682,24 +27898,49 @@ function startTunnel(config3) {
|
|
|
27682
27898
|
tunnelProcess = spawn("frpc", ["-c", tmpConfigPath], {
|
|
27683
27899
|
stdio: ["ignore", "pipe", "pipe"]
|
|
27684
27900
|
});
|
|
27685
|
-
|
|
27686
|
-
|
|
27687
|
-
|
|
27688
|
-
|
|
27689
|
-
|
|
27690
|
-
|
|
27691
|
-
|
|
27692
|
-
|
|
27693
|
-
|
|
27694
|
-
|
|
27695
|
-
|
|
27696
|
-
|
|
27697
|
-
|
|
27698
|
-
|
|
27901
|
+
outputBuffer = "";
|
|
27902
|
+
const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
27903
|
+
return new Promise((resolve2) => {
|
|
27904
|
+
let settled = false;
|
|
27905
|
+
const collectOutput = (data) => {
|
|
27906
|
+
const msg = stripAnsi(data.toString()).trim();
|
|
27907
|
+
if (!msg) return;
|
|
27908
|
+
outputBuffer += msg + "\n";
|
|
27909
|
+
logger.debug({ component: "tunnel" }, msg);
|
|
27910
|
+
if (!settled && msg.includes("start proxy success")) {
|
|
27911
|
+
settled = true;
|
|
27912
|
+
const url = getTunnelUrl(config3.subdomain, config3.server);
|
|
27913
|
+
logger.info({ url, component: "tunnel" }, `Tunnel active \u2192 ${url}`);
|
|
27914
|
+
resolve2(true);
|
|
27915
|
+
}
|
|
27916
|
+
};
|
|
27917
|
+
tunnelProcess.stdout?.on("data", collectOutput);
|
|
27918
|
+
tunnelProcess.stderr?.on("data", collectOutput);
|
|
27919
|
+
tunnelProcess.on("exit", (code) => {
|
|
27920
|
+
if (code !== 0 && code !== null) {
|
|
27921
|
+
const output = outputBuffer.trim();
|
|
27922
|
+
const hint = output.includes("authorization failed") || output.includes("auth failed") || output.includes("invalid token") ? " \u2014 check FRPC_TOKEN is correct" : output.includes("login to the server failed") ? ` \u2014 ${output.split("\n").pop()}` : "";
|
|
27923
|
+
logger.error(
|
|
27924
|
+
{ code, reason: output || void 0, component: "tunnel" },
|
|
27925
|
+
`frpc failed to start${hint}`
|
|
27926
|
+
);
|
|
27927
|
+
}
|
|
27928
|
+
tunnelProcess = null;
|
|
27929
|
+
outputBuffer = "";
|
|
27930
|
+
cleanupConfig();
|
|
27931
|
+
if (!settled) {
|
|
27932
|
+
settled = true;
|
|
27933
|
+
resolve2(false);
|
|
27934
|
+
}
|
|
27935
|
+
});
|
|
27936
|
+
setTimeout(() => {
|
|
27937
|
+
if (!settled) {
|
|
27938
|
+
settled = true;
|
|
27939
|
+
logger.warn({ component: "tunnel" }, "frpc connection timeout (5s) \u2014 tunnel may not be active");
|
|
27940
|
+
resolve2(false);
|
|
27941
|
+
}
|
|
27942
|
+
}, 5e3);
|
|
27699
27943
|
});
|
|
27700
|
-
const url = getTunnelUrl(config3.subdomain, config3.server);
|
|
27701
|
-
logger.info({ url, component: "tunnel" }, `Tunnel enabled \u2192 ${url}`);
|
|
27702
|
-
return true;
|
|
27703
27944
|
}
|
|
27704
27945
|
function stopTunnel() {
|
|
27705
27946
|
if (tunnelProcess) {
|
|
@@ -27717,13 +27958,244 @@ function cleanupConfig() {
|
|
|
27717
27958
|
tmpConfigPath = null;
|
|
27718
27959
|
}
|
|
27719
27960
|
}
|
|
27720
|
-
var tunnelProcess, tmpConfigPath;
|
|
27961
|
+
var tunnelProcess, tmpConfigPath, outputBuffer;
|
|
27721
27962
|
var init_tunnel = __esm({
|
|
27722
27963
|
"src/core/tunnel.ts"() {
|
|
27723
27964
|
"use strict";
|
|
27724
27965
|
init_core();
|
|
27725
27966
|
tunnelProcess = null;
|
|
27726
27967
|
tmpConfigPath = null;
|
|
27968
|
+
outputBuffer = "";
|
|
27969
|
+
}
|
|
27970
|
+
});
|
|
27971
|
+
|
|
27972
|
+
// src/cli/shared.ts
|
|
27973
|
+
import { consola } from "consola";
|
|
27974
|
+
function initCli() {
|
|
27975
|
+
const config3 = getLoggerConfig();
|
|
27976
|
+
initLoggerService({ ...config3, level: "error", sentry: void 0 });
|
|
27977
|
+
setLoggerInstance(getPinoLogger());
|
|
27978
|
+
}
|
|
27979
|
+
var init_shared = __esm({
|
|
27980
|
+
"src/cli/shared.ts"() {
|
|
27981
|
+
"use strict";
|
|
27982
|
+
init_logger();
|
|
27983
|
+
}
|
|
27984
|
+
});
|
|
27985
|
+
|
|
27986
|
+
// src/cli/migrate-commands.ts
|
|
27987
|
+
import { readFileSync as readFileSync8, existsSync as existsSync12 } from "fs";
|
|
27988
|
+
import { join as join14 } from "path";
|
|
27989
|
+
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
27990
|
+
import Table from "cli-table3";
|
|
27991
|
+
import { consola as consola2 } from "consola";
|
|
27992
|
+
async function loadSelfPlugin() {
|
|
27993
|
+
const projectPath2 = getProjectPath();
|
|
27994
|
+
const pkgPath = join14(projectPath2, "package.json");
|
|
27995
|
+
if (!existsSync12(pkgPath)) return;
|
|
27996
|
+
try {
|
|
27997
|
+
const pkg2 = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
27998
|
+
const pkgName = pkg2?.name;
|
|
27999
|
+
if (!pkgName || !/nexus-plugin-/.test(pkgName)) return;
|
|
28000
|
+
const srcEntry = join14(projectPath2, "src", "index.ts");
|
|
28001
|
+
const distEntry = join14(projectPath2, "dist", "index.js");
|
|
28002
|
+
if (existsSync12(srcEntry)) {
|
|
28003
|
+
try {
|
|
28004
|
+
const { tsImport } = await import("tsx/esm/api");
|
|
28005
|
+
const mod = await tsImport(
|
|
28006
|
+
pathToFileURL3(srcEntry).href,
|
|
28007
|
+
import.meta.url
|
|
28008
|
+
);
|
|
28009
|
+
const manifest = extractPluginManifest(mod);
|
|
28010
|
+
if (manifest) {
|
|
28011
|
+
if (!manifest.migrationsDir) {
|
|
28012
|
+
manifest.migrationsDir = join14(projectPath2, "migrations");
|
|
28013
|
+
}
|
|
28014
|
+
registerPlugin(manifest);
|
|
28015
|
+
return;
|
|
28016
|
+
}
|
|
28017
|
+
} catch (err) {
|
|
28018
|
+
console.error(` \u26A0 Failed to load plugin src/index.ts: ${err.message}`);
|
|
28019
|
+
}
|
|
28020
|
+
}
|
|
28021
|
+
if (existsSync12(distEntry)) {
|
|
28022
|
+
try {
|
|
28023
|
+
const mod = await import(pathToFileURL3(distEntry).href);
|
|
28024
|
+
const manifest = extractPluginManifest(mod);
|
|
28025
|
+
if (manifest) {
|
|
28026
|
+
if (!manifest.migrationsDir) {
|
|
28027
|
+
manifest.migrationsDir = join14(projectPath2, "migrations");
|
|
28028
|
+
}
|
|
28029
|
+
registerPlugin(manifest);
|
|
28030
|
+
return;
|
|
28031
|
+
}
|
|
28032
|
+
} catch (err) {
|
|
28033
|
+
console.error(` \u26A0 Failed to load plugin dist/index.js: ${err.message}`);
|
|
28034
|
+
}
|
|
28035
|
+
}
|
|
28036
|
+
} catch {
|
|
28037
|
+
}
|
|
28038
|
+
}
|
|
28039
|
+
async function loadModulesForMigration() {
|
|
28040
|
+
loadCoreModules();
|
|
28041
|
+
await loadSelfPlugin();
|
|
28042
|
+
const config3 = await loadNexusConfig();
|
|
28043
|
+
if (config3.plugins?.length) {
|
|
28044
|
+
const sorted = topologicalSortPlugins(config3.plugins);
|
|
28045
|
+
for (const plugin of sorted) {
|
|
28046
|
+
registerPlugin(plugin);
|
|
28047
|
+
}
|
|
28048
|
+
}
|
|
28049
|
+
const coreNames = new Set(getOrderedModules().map((m) => m.name));
|
|
28050
|
+
for (const mod of config3.modules ?? []) {
|
|
28051
|
+
if (!coreNames.has(mod.name)) {
|
|
28052
|
+
registerModule(mod, { source: "standalone" });
|
|
28053
|
+
}
|
|
28054
|
+
}
|
|
28055
|
+
}
|
|
28056
|
+
var init_migrate_commands = __esm({
|
|
28057
|
+
"src/cli/migrate-commands.ts"() {
|
|
28058
|
+
"use strict";
|
|
28059
|
+
init_database();
|
|
28060
|
+
init_engine();
|
|
28061
|
+
init_load_config();
|
|
28062
|
+
init_shared();
|
|
28063
|
+
init_paths();
|
|
28064
|
+
init_connection();
|
|
28065
|
+
init_ensure_system_tables();
|
|
28066
|
+
init_migration_generator();
|
|
28067
|
+
init_migration_runner();
|
|
28068
|
+
}
|
|
28069
|
+
});
|
|
28070
|
+
|
|
28071
|
+
// src/cli/seed-commands.ts
|
|
28072
|
+
var seed_commands_exports = {};
|
|
28073
|
+
__export(seed_commands_exports, {
|
|
28074
|
+
handleSeedExport: () => handleSeedExport,
|
|
28075
|
+
importSeedFiles: () => importSeedFiles
|
|
28076
|
+
});
|
|
28077
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, writeFileSync as writeFileSync3, readdirSync as readdirSync2, readFileSync as readFileSync9 } from "fs";
|
|
28078
|
+
import { join as join15, basename as basename4 } from "path";
|
|
28079
|
+
import { consola as consola3 } from "consola";
|
|
28080
|
+
function deserializeJsonFields(record, fields) {
|
|
28081
|
+
const result = { ...record };
|
|
28082
|
+
for (const [name, field] of Object.entries(fields)) {
|
|
28083
|
+
if (field.db?.type === "json" && typeof result[name] === "string") {
|
|
28084
|
+
try {
|
|
28085
|
+
result[name] = JSON.parse(result[name]);
|
|
28086
|
+
} catch {
|
|
28087
|
+
}
|
|
28088
|
+
}
|
|
28089
|
+
}
|
|
28090
|
+
return result;
|
|
28091
|
+
}
|
|
28092
|
+
function serializeJsonFields(record, fields) {
|
|
28093
|
+
const result = { ...record };
|
|
28094
|
+
for (const [name, field] of Object.entries(fields)) {
|
|
28095
|
+
if (field.db?.type === "json" && typeof result[name] === "object" && result[name] !== null) {
|
|
28096
|
+
result[name] = JSON.stringify(result[name]);
|
|
28097
|
+
}
|
|
28098
|
+
}
|
|
28099
|
+
return result;
|
|
28100
|
+
}
|
|
28101
|
+
async function handleSeedExport(entity) {
|
|
28102
|
+
initCli();
|
|
28103
|
+
await loadModulesForMigration();
|
|
28104
|
+
const db2 = getDb();
|
|
28105
|
+
try {
|
|
28106
|
+
const modules = getOrderedModules();
|
|
28107
|
+
const seedDir = join15(getProjectPath(), "data", "seeds");
|
|
28108
|
+
const seedableEntities = [];
|
|
28109
|
+
for (const mod of modules) {
|
|
28110
|
+
for (const def of mod.definitions ?? []) {
|
|
28111
|
+
if (!("seedable" in def) || !def.seedable) continue;
|
|
28112
|
+
if (entity && def.table !== entity) continue;
|
|
28113
|
+
seedableEntities.push({
|
|
28114
|
+
module: mod.name,
|
|
28115
|
+
table: def.table,
|
|
28116
|
+
fields: def.fields
|
|
28117
|
+
});
|
|
28118
|
+
}
|
|
28119
|
+
}
|
|
28120
|
+
if (seedableEntities.length === 0) {
|
|
28121
|
+
if (entity) {
|
|
28122
|
+
consola3.warn(`No seedable entity found with table "${entity}"`);
|
|
28123
|
+
} else {
|
|
28124
|
+
consola3.warn("No seedable entities found");
|
|
28125
|
+
}
|
|
28126
|
+
return;
|
|
28127
|
+
}
|
|
28128
|
+
if (!existsSync13(seedDir)) {
|
|
28129
|
+
mkdirSync6(seedDir, { recursive: true });
|
|
28130
|
+
}
|
|
28131
|
+
for (const { module: modName, table, fields } of seedableEntities) {
|
|
28132
|
+
const rows = await db2(table).orderBy("id");
|
|
28133
|
+
if (rows.length === 0) {
|
|
28134
|
+
consola3.info(`${table}: no records, skipping`);
|
|
28135
|
+
continue;
|
|
28136
|
+
}
|
|
28137
|
+
const exported = rows.map(
|
|
28138
|
+
(row) => deserializeJsonFields(row, fields)
|
|
28139
|
+
);
|
|
28140
|
+
const filePath = join15(seedDir, `${table}.json`);
|
|
28141
|
+
writeFileSync3(filePath, JSON.stringify(exported, null, 2) + "\n", "utf-8");
|
|
28142
|
+
consola3.success(`${table}: exported ${rows.length} records to data/seeds/${table}.json (module: ${modName})`);
|
|
28143
|
+
}
|
|
28144
|
+
} catch (err) {
|
|
28145
|
+
consola3.error("Seed export failed:", err);
|
|
28146
|
+
} finally {
|
|
28147
|
+
await db2.destroy();
|
|
28148
|
+
process.exit(0);
|
|
28149
|
+
}
|
|
28150
|
+
}
|
|
28151
|
+
async function importSeedFiles(db2, modules, logger2) {
|
|
28152
|
+
const seedDir = join15(getProjectPath(), "data", "seeds");
|
|
28153
|
+
if (!existsSync13(seedDir)) return;
|
|
28154
|
+
const files = readdirSync2(seedDir).filter((f) => f.endsWith(".json"));
|
|
28155
|
+
if (files.length === 0) return;
|
|
28156
|
+
const seedableDefs = /* @__PURE__ */ new Map();
|
|
28157
|
+
for (const mod of modules) {
|
|
28158
|
+
for (const rawDef of mod.definitions ?? []) {
|
|
28159
|
+
const def = rawDef;
|
|
28160
|
+
if (!def["seedable"] || !def["table"] || !def["fields"]) continue;
|
|
28161
|
+
seedableDefs.set(
|
|
28162
|
+
def["table"],
|
|
28163
|
+
{ fields: def["fields"], module: mod.name }
|
|
28164
|
+
);
|
|
28165
|
+
}
|
|
28166
|
+
}
|
|
28167
|
+
for (const file of files) {
|
|
28168
|
+
const table = basename4(file, ".json");
|
|
28169
|
+
const defInfo = seedableDefs.get(table);
|
|
28170
|
+
if (!defInfo) {
|
|
28171
|
+
logger2.debug(`data/seeds/${file}: skipped (entity "${table}" is not seedable)`);
|
|
28172
|
+
continue;
|
|
28173
|
+
}
|
|
28174
|
+
const filePath = join15(seedDir, file);
|
|
28175
|
+
const raw = readFileSync9(filePath, "utf-8");
|
|
28176
|
+
let records;
|
|
28177
|
+
try {
|
|
28178
|
+
records = JSON.parse(raw);
|
|
28179
|
+
} catch {
|
|
28180
|
+
logger2.info(`data/seeds/${file}: skipped (invalid JSON)`);
|
|
28181
|
+
continue;
|
|
28182
|
+
}
|
|
28183
|
+
if (!Array.isArray(records) || records.length === 0) continue;
|
|
28184
|
+
const rows = records.map((r) => serializeJsonFields(r, defInfo.fields));
|
|
28185
|
+
for (const row of rows) {
|
|
28186
|
+
await db2(table).insert(row).onConflict("id").merge();
|
|
28187
|
+
}
|
|
28188
|
+
logger2.info(`Seeded ${rows.length} records into ${table} from data/seeds/${file}`);
|
|
28189
|
+
}
|
|
28190
|
+
}
|
|
28191
|
+
var init_seed_commands = __esm({
|
|
28192
|
+
"src/cli/seed-commands.ts"() {
|
|
28193
|
+
"use strict";
|
|
28194
|
+
init_engine();
|
|
28195
|
+
init_paths();
|
|
28196
|
+
init_connection();
|
|
28197
|
+
init_shared();
|
|
28198
|
+
init_migrate_commands();
|
|
27727
28199
|
}
|
|
27728
28200
|
});
|
|
27729
28201
|
|
|
@@ -27990,6 +28462,15 @@ ${dirs}`);
|
|
|
27990
28462
|
}
|
|
27991
28463
|
const allDefinitions = modules.flatMap((m) => m.definitions ?? []);
|
|
27992
28464
|
await createMemoryTables(allDefinitions);
|
|
28465
|
+
try {
|
|
28466
|
+
const { importSeedFiles: importSeedFiles2 } = await Promise.resolve().then(() => (init_seed_commands(), seed_commands_exports));
|
|
28467
|
+
await importSeedFiles2(ctx.db.knex, modules, {
|
|
28468
|
+
info: (msg) => logger.info(msg),
|
|
28469
|
+
debug: (msg) => logger.debug(msg)
|
|
28470
|
+
});
|
|
28471
|
+
} catch (err) {
|
|
28472
|
+
logger.debug({ err }, "Seed file import skipped (no data/seeds/ or error)");
|
|
28473
|
+
}
|
|
27993
28474
|
logger.debug("Running seeds...");
|
|
27994
28475
|
for (const mod of modules) {
|
|
27995
28476
|
try {
|
|
@@ -28031,8 +28512,8 @@ async function start(config3) {
|
|
|
28031
28512
|
}
|
|
28032
28513
|
currentConfig = config3;
|
|
28033
28514
|
setLocales(config3?.locales ?? DEFAULT_LOCALES2);
|
|
28034
|
-
if (env.NODE_ENV === "development" && env.FRPC_SERVER &&
|
|
28035
|
-
process.env["
|
|
28515
|
+
if (env.NODE_ENV === "development" && env.FRPC_SERVER && !env.TRUST_PROXY) {
|
|
28516
|
+
process.env["TRUST_PROXY"] = "true";
|
|
28036
28517
|
}
|
|
28037
28518
|
const resolved = resolveConfig();
|
|
28038
28519
|
if (resolved.port > 0) {
|
|
@@ -28091,14 +28572,18 @@ async function start(config3) {
|
|
|
28091
28572
|
eventBridge.init();
|
|
28092
28573
|
const addr = server.address();
|
|
28093
28574
|
const actualPort = typeof addr === "object" && addr ? addr.port : resolved.port;
|
|
28575
|
+
let tunnelActive = false;
|
|
28094
28576
|
if (env.NODE_ENV === "development" && env.FRPC_SERVER && env.FRPC_SUBDOMAIN) {
|
|
28095
|
-
startTunnel({
|
|
28577
|
+
tunnelActive = await startTunnel({
|
|
28096
28578
|
server: env.FRPC_SERVER,
|
|
28097
28579
|
serverPort: env.FRPC_SERVER_PORT,
|
|
28098
28580
|
token: env.FRPC_TOKEN,
|
|
28099
28581
|
subdomain: env.FRPC_SUBDOMAIN,
|
|
28100
28582
|
localPort: actualPort
|
|
28101
28583
|
});
|
|
28584
|
+
if (tunnelActive && !env.BACKEND_URL) {
|
|
28585
|
+
process.env["BACKEND_URL"] = getTunnelUrl(env.FRPC_SUBDOMAIN, env.FRPC_SERVER);
|
|
28586
|
+
}
|
|
28102
28587
|
}
|
|
28103
28588
|
const baseUrl = env.BACKEND_URL || `http://localhost:${actualPort}`;
|
|
28104
28589
|
logger.debug({ libPath: getLibPath(), projectPath: getProjectPath() }, "Paths");
|