@gzl10/nexus-backend 0.18.0 → 0.19.1

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/cli.js CHANGED
@@ -47,7 +47,7 @@ var init_env = __esm({
47
47
  envSchema = z.object({
48
48
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
49
49
  PORT: z.coerce.number().default(3e3),
50
- CORS_ORIGIN: z.string().default("http://localhost:3001"),
50
+ CORS_ORIGIN: z.string().default("*"),
51
51
  BACKEND_URL: z.string().optional(),
52
52
  DATABASE_URL: z.string().default("file:./dev.db"),
53
53
  REDIS_URL: z.string().url().optional(),
@@ -764,6 +764,14 @@ async function isWorkspacePackage(name) {
764
764
  }
765
765
  }
766
766
  async function installPlugin(name, opts) {
767
+ const projectPath2 = opts?.projectPath ?? process.cwd();
768
+ const pkgPath = join5(projectPath2, "package.json");
769
+ if (existsSync4(pkgPath)) {
770
+ const pkg4 = JSON.parse(readFileSync3(pkgPath, "utf-8"));
771
+ if (pkg4.name === "@gzl10/nexus-backend") {
772
+ throw new Error("Cannot install plugins inside @gzl10/nexus-backend. Run this command from a Nexus project directory.");
773
+ }
774
+ }
767
775
  const isWorkspace = await isWorkspacePackage(name);
768
776
  let pkg3;
769
777
  if (opts?.version) {
@@ -780,11 +788,28 @@ async function installPlugin(name, opts) {
780
788
  plugins[name] = { enabled: true };
781
789
  writePluginsFile(plugins, filePath);
782
790
  }
791
+ function isPackageInstalled(name, projectPath2) {
792
+ const base = projectPath2 || process.cwd();
793
+ const pkgPath = join5(base, "package.json");
794
+ try {
795
+ const pkg3 = JSON.parse(readFileSync3(pkgPath, "utf-8"));
796
+ return !!(pkg3.dependencies?.[name] || pkg3.devDependencies?.[name]);
797
+ } catch {
798
+ return false;
799
+ }
800
+ }
783
801
  async function uninstallPlugin(name, projectPath2) {
784
- await execAsync(`pnpm remove ${name}`);
785
802
  const filePath = getPluginsFilePath(projectPath2);
786
803
  const plugins = readPluginsFile(filePath);
787
- if (name in plugins) {
804
+ const isRegistered = name in plugins;
805
+ const isInstalled = isPackageInstalled(name, projectPath2);
806
+ if (!isRegistered && !isInstalled) {
807
+ throw new Error(`Plugin ${shortPluginName(name)} is not installed`);
808
+ }
809
+ if (isInstalled) {
810
+ await execAsync(`pnpm remove ${name}`);
811
+ }
812
+ if (isRegistered) {
788
813
  delete plugins[name];
789
814
  writePluginsFile(plugins, filePath);
790
815
  }
@@ -823,26 +848,10 @@ function initCli() {
823
848
  initLoggerService({ ...config3, level: "error", sentry: void 0 });
824
849
  setLoggerInstance(getPinoLogger());
825
850
  }
826
- function handleCliError(err) {
827
- if (err instanceof CliError) {
828
- consola.error(err.message);
829
- if (err.hint) consola.info(err.hint);
830
- process.exit(1);
831
- }
832
- throw err;
833
- }
834
- var CliError;
835
851
  var init_shared = __esm({
836
852
  "src/cli/shared.ts"() {
837
853
  "use strict";
838
854
  init_logger();
839
- CliError = class extends Error {
840
- constructor(message, hint) {
841
- super(message);
842
- this.hint = hint;
843
- this.name = "CliError";
844
- }
845
- };
846
855
  }
847
856
  });
848
857
 
@@ -856,13 +865,17 @@ import { readFileSync as readFileSync4 } from "fs";
856
865
  import { dirname as dirname5, join as join6 } from "path";
857
866
  import { fileURLToPath as fileURLToPath2 } from "url";
858
867
  function getVersion() {
859
- const __dir = dirname5(fileURLToPath2(import.meta.url));
860
- try {
861
- const pkg3 = JSON.parse(readFileSync4(join6(__dir, "..", "..", "package.json"), "utf-8"));
862
- return pkg3.version;
863
- } catch {
864
- return "unknown";
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);
865
877
  }
878
+ return "unknown";
866
879
  }
867
880
  async function collectInfo() {
868
881
  const config3 = resolveConfig();
@@ -1520,6 +1533,7 @@ var init_definitions = __esm({
1520
1533
  };
1521
1534
  mastersEntity = {
1522
1535
  table: "masters",
1536
+ seedable: true,
1523
1537
  routePrefix: "/",
1524
1538
  label: { en: "Master", es: "Maestro" },
1525
1539
  labelPlural: { en: "Masters", es: "Maestros" },
@@ -1551,14 +1565,15 @@ var init_definitions = __esm({
1551
1565
  meta: { sortable: true, searchable: true }
1552
1566
  }),
1553
1567
  label: useLocalizedField({ label: { en: "Name", es: "Nombre" } }),
1554
- order: orderField,
1568
+ order: { ...orderField, meta: { ...orderField.meta, showInDisplay: false } },
1555
1569
  is_active: isActiveField,
1556
1570
  metadata: useJsonField({
1557
1571
  label: { en: "Metadata", es: "Metadatos" },
1558
1572
  hint: {
1559
1573
  en: "Type-specific fields (symbol, flag, etc.)",
1560
1574
  es: "Campos espec\xEDficos del tipo"
1561
- }
1575
+ },
1576
+ meta: { showInDisplay: false }
1562
1577
  })
1563
1578
  },
1564
1579
  hooks: () => ({
@@ -1567,6 +1582,12 @@ var init_definitions = __esm({
1567
1582
  data["id"] = `${data["type"]}:${data["code"]}`;
1568
1583
  }
1569
1584
  return data;
1585
+ },
1586
+ beforeUpdate: async (_id, data) => {
1587
+ if ("type" in data || "code" in data) {
1588
+ throw new Error("Cannot update type or code of a master record. Delete and recreate instead.");
1589
+ }
1590
+ return data;
1570
1591
  }
1571
1592
  }),
1572
1593
  defaultSort: { field: "order", order: "asc" },
@@ -1595,8 +1616,8 @@ function createMasterRegistry() {
1595
1616
  */
1596
1617
  async seed(ctx) {
1597
1618
  for (const reg of registrations) {
1598
- const { type: type2, entries, seed: seed5 } = reg;
1599
- if (seed5 === "if-empty") {
1619
+ const { type: type2, entries, seed: seed6 } = reg;
1620
+ if (seed6 === "if-empty") {
1600
1621
  const existing = await ctx.db.knex("masters").where({ type: type2 }).first();
1601
1622
  if (existing) continue;
1602
1623
  }
@@ -1609,12 +1630,12 @@ function createMasterRegistry() {
1609
1630
  is_active: entry.is_active ?? true,
1610
1631
  metadata: entry.metadata ? JSON.stringify(entry.metadata) : null
1611
1632
  }));
1612
- if (seed5 === "always") {
1633
+ if (seed6 === "always") {
1613
1634
  for (const row of rows) {
1614
1635
  await ctx.db.knex("masters").insert(row).onConflict(["type", "code"]).merge();
1615
1636
  }
1616
1637
  } else {
1617
- await ctx.db.knex("masters").insert(rows);
1638
+ await ctx.db.knex("masters").insert(rows).onConflict(["type", "code"]).ignore();
1618
1639
  }
1619
1640
  }
1620
1641
  },
@@ -8047,15 +8068,12 @@ var init_document_types = __esm({
8047
8068
  }
8048
8069
  });
8049
8070
 
8050
- // src/modules/masters/index.ts
8051
- var PREDEFINED_MASTERS, mastersModule;
8052
- var init_masters = __esm({
8053
- "src/modules/masters/index.ts"() {
8071
+ // src/modules/masters/constants.ts
8072
+ var DEFAULT_MASTER_TYPES, PREDEFINED_MASTERS;
8073
+ var init_constants = __esm({
8074
+ "src/modules/masters/constants.ts"() {
8054
8075
  "use strict";
8055
- init_definitions();
8056
- init_registry2();
8057
- init_definitions();
8058
- init_registry2();
8076
+ DEFAULT_MASTER_TYPES = ["languages", "timezones"];
8059
8077
  PREDEFINED_MASTERS = {
8060
8078
  currencies: () => Promise.resolve().then(() => (init_currencies(), currencies_exports)).then((m) => m.default),
8061
8079
  languages: () => Promise.resolve().then(() => (init_languages(), languages_exports)).then((m) => m.default),
@@ -8072,15 +8090,137 @@ var init_masters = __esm({
8072
8090
  "phone-prefixes": () => Promise.resolve().then(() => (init_phone_prefixes(), phone_prefixes_exports)).then((m) => m.default),
8073
8091
  "document-types": () => Promise.resolve().then(() => (init_document_types(), document_types_exports)).then((m) => m.default)
8074
8092
  };
8093
+ }
8094
+ });
8095
+
8096
+ // src/modules/masters/actions/install-type.ts
8097
+ import { useSelectField as useSelectField2 } from "@gzl10/nexus-sdk/fields";
8098
+ var installTypeAction;
8099
+ var init_install_type = __esm({
8100
+ "src/modules/masters/actions/install-type.ts"() {
8101
+ "use strict";
8102
+ init_constants();
8103
+ installTypeAction = {
8104
+ key: "install-type",
8105
+ scope: "module",
8106
+ label: { en: "Install Master Type", es: "Instalar Tipo de Maestro" },
8107
+ icon: "mdi:database-plus",
8108
+ variant: "primary",
8109
+ output: {},
8110
+ input: {
8111
+ type: useSelectField2({
8112
+ label: { en: "Master Type", es: "Tipo de Maestro" },
8113
+ required: true,
8114
+ options: Object.keys(PREDEFINED_MASTERS).filter((t) => !DEFAULT_MASTER_TYPES.includes(t)).map((t) => ({
8115
+ value: t,
8116
+ label: t.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
8117
+ }))
8118
+ })
8119
+ },
8120
+ handler: async (ctx, input) => {
8121
+ if (process.env["NODE_ENV"] === "production") {
8122
+ throw new ctx.core.errors.ForbiddenError("Master type management is only available in development");
8123
+ }
8124
+ const { type: type2 } = input;
8125
+ const loader = PREDEFINED_MASTERS[type2];
8126
+ if (!loader) {
8127
+ throw new ctx.core.errors.AppError(`Unknown predefined master type: ${type2}`, 400);
8128
+ }
8129
+ const existing = await ctx.db.knex("masters").where({ type: type2 }).first();
8130
+ if (existing) {
8131
+ throw new ctx.core.errors.ConflictError(`Master type "${type2}" is already installed`);
8132
+ }
8133
+ const entries = await loader();
8134
+ const rows = entries.map((entry, i) => ({
8135
+ id: `${type2}:${entry.code}`,
8136
+ type: type2,
8137
+ code: entry.code,
8138
+ label: JSON.stringify(typeof entry.label === "string" ? { en: entry.label } : entry.label),
8139
+ order: entry.order ?? i,
8140
+ is_active: entry.is_active ?? true,
8141
+ metadata: entry.metadata ? JSON.stringify(entry.metadata) : null
8142
+ }));
8143
+ await ctx.db.knex("masters").insert(rows).onConflict(["type", "code"]).ignore();
8144
+ return { installed: type2, count: rows.length };
8145
+ }
8146
+ };
8147
+ }
8148
+ });
8149
+
8150
+ // src/modules/masters/actions/uninstall-type.ts
8151
+ import { useTextField as useTextField3 } from "@gzl10/nexus-sdk/fields";
8152
+ var uninstallTypeAction;
8153
+ var init_uninstall_type = __esm({
8154
+ "src/modules/masters/actions/uninstall-type.ts"() {
8155
+ "use strict";
8156
+ init_constants();
8157
+ uninstallTypeAction = {
8158
+ key: "uninstall-type",
8159
+ scope: "module",
8160
+ label: { en: "Uninstall Master Type", es: "Desinstalar Tipo de Maestro" },
8161
+ icon: "mdi:database-minus",
8162
+ variant: "danger",
8163
+ output: {},
8164
+ confirm: {
8165
+ type: "simple",
8166
+ title: { en: "Uninstall Master Type", es: "Desinstalar Tipo de Maestro" },
8167
+ message: {
8168
+ en: "This will delete ALL records of the selected type. This action cannot be undone.",
8169
+ es: "Esto eliminar\xE1 TODOS los registros del tipo seleccionado. Esta acci\xF3n no se puede deshacer."
8170
+ }
8171
+ },
8172
+ input: {
8173
+ type: useTextField3({
8174
+ label: { en: "Type slug to uninstall", es: "Slug del tipo a desinstalar" },
8175
+ required: true,
8176
+ hint: {
8177
+ en: 'Enter the master type slug (e.g., "currencies", "countries")',
8178
+ es: 'Introduce el slug del tipo (ej: "currencies", "countries")'
8179
+ }
8180
+ })
8181
+ },
8182
+ handler: async (ctx, input) => {
8183
+ if (process.env["NODE_ENV"] === "production") {
8184
+ throw new ctx.core.errors.ForbiddenError("Master type management is only available in development");
8185
+ }
8186
+ const { type: type2 } = input;
8187
+ if (DEFAULT_MASTER_TYPES.includes(type2)) {
8188
+ throw new ctx.core.errors.AppError(`Cannot uninstall default master type "${type2}" (required by core)`, 400);
8189
+ }
8190
+ const existing = await ctx.db.knex("masters").where({ type: type2 }).first();
8191
+ if (!existing) {
8192
+ throw new ctx.core.errors.NotFoundError(`Master type "${type2}" is not installed`);
8193
+ }
8194
+ const deleted = await ctx.db.knex("masters").where({ type: type2 }).del();
8195
+ return { uninstalled: type2, count: deleted };
8196
+ }
8197
+ };
8198
+ }
8199
+ });
8200
+
8201
+ // src/modules/masters/index.ts
8202
+ var mastersModule;
8203
+ var init_masters = __esm({
8204
+ "src/modules/masters/index.ts"() {
8205
+ "use strict";
8206
+ init_definitions();
8207
+ init_registry2();
8208
+ init_constants();
8209
+ init_install_type();
8210
+ init_uninstall_type();
8211
+ init_definitions();
8212
+ init_registry2();
8213
+ init_constants();
8075
8214
  mastersModule = {
8076
8215
  name: "masters",
8077
8216
  type: "core",
8078
- label: { en: "Master Data", es: "Datos maestros" },
8217
+ label: { en: "Masters", es: "Maestros" },
8079
8218
  icon: "mdi:database-outline",
8080
8219
  description: { en: "Reference data catalogs", es: "Cat\xE1logos de datos de referencia" },
8081
- category: "data",
8220
+ category: "settings",
8082
8221
  routePrefix: "/masters",
8083
8222
  definitions: [mastersEntity],
8223
+ actions: [installTypeAction, uninstallTypeAction],
8084
8224
  init: (ctx) => {
8085
8225
  if (!ctx.services.has("masters")) {
8086
8226
  ctx.services.register("masters", createMasterRegistry());
@@ -8091,13 +8231,14 @@ var init_masters = __esm({
8091
8231
  ctx.services.register("masters", createMasterRegistry());
8092
8232
  }
8093
8233
  const registry2 = ctx.services.get("masters");
8094
- const configMasters = ctx.config.resolved["masters"];
8095
- const typesToSeed = !configMasters || configMasters === "*" ? Object.keys(PREDEFINED_MASTERS) : configMasters.filter((t) => t in PREDEFINED_MASTERS);
8096
- for (const type2 of typesToSeed) {
8097
- const loader = PREDEFINED_MASTERS[type2];
8098
- if (!loader) continue;
8099
- const entries = await loader();
8100
- registry2.register(type2, entries, { seed: "if-empty" });
8234
+ const existing = await ctx.db.knex("masters").first();
8235
+ if (!existing) {
8236
+ for (const type2 of DEFAULT_MASTER_TYPES) {
8237
+ const loader = PREDEFINED_MASTERS[type2];
8238
+ if (!loader) continue;
8239
+ const entries = await loader();
8240
+ registry2.register(type2, entries, { seed: "if-empty" });
8241
+ }
8101
8242
  }
8102
8243
  await registry2.seed(ctx);
8103
8244
  }
@@ -8361,6 +8502,7 @@ function toPageDTO(page) {
8361
8502
  dataSource: page.dataSource,
8362
8503
  widgets: page.widgets,
8363
8504
  component: page.component,
8505
+ contentEndpoint: page.contentEndpoint,
8364
8506
  meta: page.meta,
8365
8507
  layout: page.layout
8366
8508
  };
@@ -8624,7 +8766,7 @@ var init_system_routes = __esm({
8624
8766
 
8625
8767
  // src/modules/system/system.entity.ts
8626
8768
  import * as os from "os";
8627
- import { useIconField, useTextField as useTextField3, useSelectField as useSelectField2, useNumberField as useNumberField2, useCheckboxField, useTagsField, useNameField, useDescriptionField } from "@gzl10/nexus-sdk/fields";
8769
+ import { useIconField, useTextField as useTextField4, useSelectField as useSelectField3, useNumberField as useNumberField2, useCheckboxField, useTagsField, useNameField, useDescriptionField } from "@gzl10/nexus-sdk/fields";
8628
8770
  var moduleEntity, osEntity;
8629
8771
  var init_system_entity = __esm({
8630
8772
  "src/modules/system/system.entity.ts"() {
@@ -8642,7 +8784,7 @@ var init_system_entity = __esm({
8642
8784
  name: useNameField({
8643
8785
  size: 50
8644
8786
  }),
8645
- label: useTextField3({
8787
+ label: useTextField4({
8646
8788
  label: { en: "Label", es: "Etiqueta" },
8647
8789
  size: 100,
8648
8790
  nullable: false,
@@ -8650,7 +8792,7 @@ var init_system_entity = __esm({
8650
8792
  }),
8651
8793
  icon: useIconField({ label: { en: "Icon", es: "Icono" }, size: 50 }),
8652
8794
  type: {
8653
- ...useSelectField2({
8795
+ ...useSelectField3({
8654
8796
  label: { en: "Type", es: "Tipo" },
8655
8797
  options: [
8656
8798
  { value: "core", label: { en: "Core", es: "Core" } },
@@ -8666,7 +8808,7 @@ var init_system_entity = __esm({
8666
8808
  description: useDescriptionField({
8667
8809
  mode: "text"
8668
8810
  }),
8669
- routePrefix: useTextField3({
8811
+ routePrefix: useTextField4({
8670
8812
  label: { en: "Route", es: "Ruta" },
8671
8813
  size: 50,
8672
8814
  nullable: true
@@ -8724,14 +8866,14 @@ var init_system_entity = __esm({
8724
8866
  order: 1,
8725
8867
  refreshInterval: 5e3,
8726
8868
  fields: {
8727
- hostname: useTextField3({
8869
+ hostname: useTextField4({
8728
8870
  label: { en: "Hostname", es: "Nombre de servidor" },
8729
8871
  size: 100,
8730
8872
  nullable: false,
8731
8873
  inputProps: { order: 1 }
8732
8874
  }),
8733
8875
  platform: {
8734
- ...useSelectField2({
8876
+ ...useSelectField3({
8735
8877
  label: { en: "Platform", es: "Plataforma" },
8736
8878
  options: [
8737
8879
  { value: "darwin", label: { en: "macOS", es: "macOS" } },
@@ -8745,7 +8887,7 @@ var init_system_entity = __esm({
8745
8887
  inputProps: { order: 2 }
8746
8888
  },
8747
8889
  arch: {
8748
- ...useSelectField2({
8890
+ ...useSelectField3({
8749
8891
  label: { en: "Architecture", es: "Arquitectura" },
8750
8892
  options: [
8751
8893
  { value: "x64", label: { en: "x64", es: "x64" } },
@@ -8758,7 +8900,7 @@ var init_system_entity = __esm({
8758
8900
  inputProps: { order: 3 }
8759
8901
  },
8760
8902
  type: {
8761
- ...useTextField3({
8903
+ ...useTextField4({
8762
8904
  label: { en: "Type", es: "Tipo" },
8763
8905
  size: 30,
8764
8906
  nullable: false
@@ -8766,7 +8908,7 @@ var init_system_entity = __esm({
8766
8908
  inputProps: { order: 4 }
8767
8909
  },
8768
8910
  release: {
8769
- ...useTextField3({
8911
+ ...useTextField4({
8770
8912
  label: { en: "Release", es: "Versi\xF3n" },
8771
8913
  size: 50,
8772
8914
  nullable: false
@@ -8789,7 +8931,7 @@ var init_system_entity = __esm({
8789
8931
  inputProps: { order: 7, format: "duration" }
8790
8932
  },
8791
8933
  cpuModel: {
8792
- ...useTextField3({
8934
+ ...useTextField4({
8793
8935
  label: { en: "CPU Model", es: "Modelo de CPU" },
8794
8936
  size: 100,
8795
8937
  nullable: false
@@ -8855,7 +8997,7 @@ var init_system_entity = __esm({
8855
8997
  });
8856
8998
 
8857
8999
  // src/modules/system/migration-history.entity.ts
8858
- import { useIdField as useIdField2, useTextField as useTextField4, useNumberField as useNumberField3, useSelectField as useSelectField3, useDatetimeField as useDatetimeField2, useTextareaField as useTextareaField2 } from "@gzl10/nexus-sdk/fields";
9000
+ import { useIdField as useIdField2, useTextField as useTextField5, useNumberField as useNumberField3, useSelectField as useSelectField4, useDatetimeField as useDatetimeField2, useTextareaField as useTextareaField2 } from "@gzl10/nexus-sdk/fields";
8859
9001
  var migrationHistoryEntity;
8860
9002
  var init_migration_history_entity = __esm({
8861
9003
  "src/modules/system/migration-history.entity.ts"() {
@@ -8872,9 +9014,9 @@ var init_migration_history_entity = __esm({
8872
9014
  calendarFrom: "executed_at",
8873
9015
  fields: {
8874
9016
  id: useIdField2(),
8875
- name: useTextField4({ label: { en: "Migration Name", es: "Nombre de la Migraci\xF3n" }, required: true, size: 255, unique: true, meta: { sortable: true, searchable: true } }),
9017
+ name: useTextField5({ label: { en: "Migration Name", es: "Nombre de la Migraci\xF3n" }, required: true, size: 255, unique: true, meta: { sortable: true, searchable: true } }),
8876
9018
  batch: useNumberField3({ label: { en: "Batch", es: "Lote" }, required: true, meta: { sortable: true } }),
8877
- status: useSelectField3({
9019
+ status: useSelectField4({
8878
9020
  label: { en: "Status", es: "Estado" },
8879
9021
  options: [
8880
9022
  { value: "running", label: { en: "Running", es: "Ejecutando" } },
@@ -8906,7 +9048,7 @@ var init_migration_history_entity = __esm({
8906
9048
  });
8907
9049
 
8908
9050
  // src/modules/system/env-config.entity.ts
8909
- import { useTextField as useTextField5, useSelectField as useSelectField4, useCheckboxField as useCheckboxField2 } from "@gzl10/nexus-sdk/fields";
9051
+ import { useTextField as useTextField6, useSelectField as useSelectField5, useCheckboxField as useCheckboxField2 } from "@gzl10/nexus-sdk/fields";
8910
9052
  function maskValue(value, sensitive) {
8911
9053
  if (!sensitive) return value;
8912
9054
  try {
@@ -8931,14 +9073,14 @@ var init_env_config_entity = __esm({
8931
9073
  routePrefix: "/env-config",
8932
9074
  defaultSort: { field: "category", order: "asc" },
8933
9075
  fields: {
8934
- name: useTextField5({
9076
+ name: useTextField6({
8935
9077
  label: { en: "Variable", es: "Variable" },
8936
9078
  size: 100,
8937
9079
  nullable: false,
8938
9080
  meta: { sortable: true, searchable: true }
8939
9081
  }),
8940
9082
  category: {
8941
- ...useSelectField4({
9083
+ ...useSelectField5({
8942
9084
  label: { en: "Category", es: "Categor\xEDa" },
8943
9085
  options: [
8944
9086
  { value: "server", label: { en: "Server", es: "Servidor" } },
@@ -8953,18 +9095,18 @@ var init_env_config_entity = __esm({
8953
9095
  meta: { sortable: true }
8954
9096
  })
8955
9097
  },
8956
- source: useTextField5({
9098
+ source: useTextField6({
8957
9099
  label: { en: "Source", es: "Origen" },
8958
9100
  size: 50,
8959
9101
  nullable: false,
8960
9102
  meta: { sortable: true }
8961
9103
  }),
8962
- value: useTextField5({
9104
+ value: useTextField6({
8963
9105
  label: { en: "Value", es: "Valor" },
8964
9106
  size: 255,
8965
9107
  nullable: true
8966
9108
  }),
8967
- default: useTextField5({
9109
+ default: useTextField6({
8968
9110
  label: { en: "Default", es: "Por defecto" },
8969
9111
  size: 100,
8970
9112
  nullable: true
@@ -9670,7 +9812,7 @@ var init_system = __esm({
9670
9812
  });
9671
9813
 
9672
9814
  // src/modules/ui-settings/ui-branding.entity.ts
9673
- import { useTextField as useTextField6, useImageField } from "@gzl10/nexus-sdk/fields";
9815
+ import { useTextField as useTextField7, useImageField } from "@gzl10/nexus-sdk/fields";
9674
9816
  var uiBrandingEntity;
9675
9817
  var init_ui_branding_entity = __esm({
9676
9818
  "src/modules/ui-settings/ui-branding.entity.ts"() {
@@ -9690,7 +9832,7 @@ var init_ui_branding_entity = __esm({
9690
9832
  favicon: null
9691
9833
  },
9692
9834
  fields: {
9693
- appName: useTextField6({
9835
+ appName: useTextField7({
9694
9836
  label: { en: "App Name", es: "Nombre de la App" },
9695
9837
  hint: { en: "Displayed in the header, browser tab and emails", es: "Se muestra en el header, pesta\xF1a del navegador y emails" },
9696
9838
  size: 100,
@@ -9731,7 +9873,7 @@ var init_ui_branding_entity = __esm({
9731
9873
  });
9732
9874
 
9733
9875
  // src/modules/ui-settings/ui-theme.entity.ts
9734
- import { useSelectField as useSelectField5, useColorField } from "@gzl10/nexus-sdk/fields";
9876
+ import { useSelectField as useSelectField6, useColorField } from "@gzl10/nexus-sdk/fields";
9735
9877
  var uiThemeEntity;
9736
9878
  var init_ui_theme_entity = __esm({
9737
9879
  "src/modules/ui-settings/ui-theme.entity.ts"() {
@@ -9756,7 +9898,7 @@ var init_ui_theme_entity = __esm({
9756
9898
  },
9757
9899
  fields: {
9758
9900
  // === Typography ===
9759
- font: useSelectField5({
9901
+ font: useSelectField6({
9760
9902
  label: { en: "Font", es: "Fuente" },
9761
9903
  hint: { en: "Primary font for headings and UI elements", es: "Fuente principal para t\xEDtulos y elementos de interfaz" },
9762
9904
  options: [
@@ -9769,7 +9911,7 @@ var init_ui_theme_entity = __esm({
9769
9911
  ]
9770
9912
  }),
9771
9913
  // === Theme & Colors ===
9772
- theme: useSelectField5({
9914
+ theme: useSelectField6({
9773
9915
  label: { en: "Theme", es: "Tema" },
9774
9916
  hint: { en: "System follows your device preferences", es: "Sistema sigue las preferencias de tu dispositivo" },
9775
9917
  options: [
@@ -9778,7 +9920,7 @@ var init_ui_theme_entity = __esm({
9778
9920
  { value: "system", label: { en: "System", es: "Sistema" } }
9779
9921
  ]
9780
9922
  }),
9781
- dopamineTheme: useSelectField5({
9923
+ dopamineTheme: useSelectField6({
9782
9924
  label: { en: "Dopamine Theme", es: "Tema Dopamina" },
9783
9925
  hint: { en: "Vibrant color presets optimized for light and dark modes (2025/2026 trends)", es: "Presets de colores vibrantes optimizados para modo claro y oscuro (tendencias 2025/2026)" },
9784
9926
  options: [
@@ -9796,7 +9938,7 @@ var init_ui_theme_entity = __esm({
9796
9938
  ]
9797
9939
  }),
9798
9940
  // === Login Layout ===
9799
- loginLayout: useSelectField5({
9941
+ loginLayout: useSelectField6({
9800
9942
  label: { en: "Login Layout", es: "Dise\xF1o de Login" },
9801
9943
  hint: { en: "Visual layout for authentication pages", es: "Dise\xF1o visual para p\xE1ginas de autenticaci\xF3n" },
9802
9944
  options: [
@@ -9827,7 +9969,7 @@ var init_ui_theme_entity = __esm({
9827
9969
  });
9828
9970
 
9829
9971
  // src/modules/ui-settings/ui-effects.entity.ts
9830
- import { useSelectField as useSelectField6, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
9972
+ import { useSelectField as useSelectField7, useSwitchField as useSwitchField2 } from "@gzl10/nexus-sdk/fields";
9831
9973
  var uiEffectsEntity;
9832
9974
  var init_ui_effects_entity = __esm({
9833
9975
  "src/modules/ui-settings/ui-effects.entity.ts"() {
@@ -9847,7 +9989,7 @@ var init_ui_effects_entity = __esm({
9847
9989
  enableOrganicShapes: false
9848
9990
  },
9849
9991
  fields: {
9850
- glassIntensity: useSelectField6({
9992
+ glassIntensity: useSelectField7({
9851
9993
  label: { en: "Glass Intensity", es: "Intensidad Glass" },
9852
9994
  hint: { en: "Glassmorphism blur effect on cards and modals", es: "Efecto de desenfoque glassmorphism en cards y modales" },
9853
9995
  options: [
@@ -9857,7 +9999,7 @@ var init_ui_effects_entity = __esm({
9857
9999
  { value: "high", label: { en: "High", es: "Alta" } }
9858
10000
  ]
9859
10001
  }),
9860
- borderStyle: useSelectField6({
10002
+ borderStyle: useSelectField7({
9861
10003
  label: { en: "Border Style", es: "Estilo de Bordes" },
9862
10004
  hint: { en: "Corner radius for buttons, cards and inputs", es: "Radio de esquinas para botones, cards e inputs" },
9863
10005
  options: [
@@ -9891,7 +10033,7 @@ var init_ui_effects_entity = __esm({
9891
10033
  });
9892
10034
 
9893
10035
  // src/modules/ui-settings/ui-accessibility.entity.ts
9894
- import { useSelectField as useSelectField7, useSwitchField as useSwitchField3 } from "@gzl10/nexus-sdk/fields";
10036
+ import { useSelectField as useSelectField8, useSwitchField as useSwitchField3 } from "@gzl10/nexus-sdk/fields";
9895
10037
  var uiAccessibilityEntity;
9896
10038
  var init_ui_accessibility_entity = __esm({
9897
10039
  "src/modules/ui-settings/ui-accessibility.entity.ts"() {
@@ -9910,7 +10052,7 @@ var init_ui_accessibility_entity = __esm({
9910
10052
  highContrast: false
9911
10053
  },
9912
10054
  fields: {
9913
- typographyScale: useSelectField7({
10055
+ typographyScale: useSelectField8({
9914
10056
  label: { en: "Typography Scale", es: "Escala Tipogr\xE1fica" },
9915
10057
  hint: { en: "Adjusts font sizes for better readability (WCAG 1.4.4)", es: "Ajusta tama\xF1os de fuente para mejor legibilidad (WCAG 1.4.4)" },
9916
10058
  options: [
@@ -10901,7 +11043,7 @@ var init_storage_service = __esm({
10901
11043
  });
10902
11044
 
10903
11045
  // src/modules/storage/storage.entity.ts
10904
- import { useIdField as useIdField3, useTextField as useTextField7, useSelectField as useSelectField8, useUrlField, useNumberField as useNumberField4, useCheckboxField as useCheckboxField3, useJsonField as useJsonField2, useMetadataField, usePublicField } from "@gzl10/nexus-sdk/fields";
11046
+ 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";
10905
11047
  var DEFAULT_MAX_SIZE2, storageConfigEntity, storageFilesEntity;
10906
11048
  var init_storage_entity = __esm({
10907
11049
  "src/modules/storage/storage.entity.ts"() {
@@ -10927,7 +11069,7 @@ var init_storage_entity = __esm({
10927
11069
  },
10928
11070
  fields: {
10929
11071
  id: useIdField3(),
10930
- scope: useTextField7({
11072
+ scope: useTextField8({
10931
11073
  label: { en: "Scope", es: "\xC1mbito" },
10932
11074
  disabled: true,
10933
11075
  size: 100,
@@ -10936,7 +11078,7 @@ var init_storage_entity = __esm({
10936
11078
  hint: { en: "Unique identifier (e.g. default_filesystem, default_s3)", es: "Identificador \xFAnico (ej: default_filesystem, default_s3)" }
10937
11079
  }),
10938
11080
  driver: {
10939
- ...useSelectField8({
11081
+ ...useSelectField9({
10940
11082
  label: { en: "Driver", es: "Controlador" },
10941
11083
  required: true,
10942
11084
  hint: { en: "Storage backend", es: "Backend de almacenamiento" },
@@ -10959,7 +11101,7 @@ var init_storage_entity = __esm({
10959
11101
  nullable: false,
10960
11102
  displayProps: { format: "bytes" }
10961
11103
  }),
10962
- allowed_mime_types: useTextField7({
11104
+ allowed_mime_types: useTextField8({
10963
11105
  label: { en: "Allowed MIME Types", es: "Tipos MIME permitidos" },
10964
11106
  hint: { en: "Allowed types separated by comma (e.g. image/*,application/pdf)", es: "Tipos permitidos separados por coma (ej: image/*,application/pdf)" },
10965
11107
  size: 1e3,
@@ -11124,21 +11266,21 @@ var init_storage_entity = __esm({
11124
11266
  ],
11125
11267
  fields: {
11126
11268
  id: useIdField3(),
11127
- filename: useTextField7({
11269
+ filename: useTextField8({
11128
11270
  label: { en: "Original Filename", es: "Nombre original" },
11129
11271
  required: true,
11130
11272
  size: 255,
11131
11273
  nullable: false,
11132
11274
  meta: { sortable: true, searchable: true }
11133
11275
  }),
11134
- disk_filename: useTextField7({
11276
+ disk_filename: useTextField8({
11135
11277
  label: { en: "Disk Filename", es: "Nombre en disco" },
11136
11278
  required: true,
11137
11279
  hidden: true,
11138
11280
  size: 255,
11139
11281
  nullable: false
11140
11282
  }),
11141
- mimetype: useTextField7({
11283
+ mimetype: useTextField8({
11142
11284
  label: { en: "MIME Type", es: "Tipo MIME" },
11143
11285
  required: true,
11144
11286
  size: 100,
@@ -11154,14 +11296,14 @@ var init_storage_entity = __esm({
11154
11296
  meta: { sortable: true },
11155
11297
  displayProps: { format: "bytes" }
11156
11298
  }),
11157
- folder: useTextField7({
11299
+ folder: useTextField8({
11158
11300
  label: { en: "Folder", es: "Carpeta" },
11159
11301
  size: 100,
11160
11302
  nullable: true,
11161
11303
  index: true,
11162
11304
  meta: { searchable: true }
11163
11305
  }),
11164
- scope: useTextField7({
11306
+ scope: useTextField8({
11165
11307
  label: { en: "Storage Scope", es: "\xC1mbito de almacenamiento" },
11166
11308
  hidden: true,
11167
11309
  size: 50,
@@ -11172,7 +11314,7 @@ var init_storage_entity = __esm({
11172
11314
  es: "\xC1mbito de configuraci\xF3n de almacenamiento usado para este archivo"
11173
11315
  }
11174
11316
  }),
11175
- path: useTextField7({
11317
+ path: useTextField8({
11176
11318
  label: { en: "Full Path", es: "Ruta completa" },
11177
11319
  required: true,
11178
11320
  hidden: true,
@@ -11185,13 +11327,13 @@ var init_storage_entity = __esm({
11185
11327
  nullable: true,
11186
11328
  meta: { exportable: true, showInDisplay: false }
11187
11329
  }),
11188
- thumbnail_path: useTextField7({
11330
+ thumbnail_path: useTextField8({
11189
11331
  label: { en: "Thumbnail Path", es: "Ruta de miniatura" },
11190
11332
  size: 500,
11191
11333
  nullable: true,
11192
11334
  meta: { showInDisplay: false }
11193
11335
  }),
11194
- hash: useTextField7({
11336
+ hash: useTextField8({
11195
11337
  label: { en: "SHA256 Hash", es: "Hash SHA256" },
11196
11338
  hidden: true,
11197
11339
  size: 64,
@@ -11680,15 +11822,15 @@ var init_storage = __esm({
11680
11822
  routes: (ctx) => createStorageRoutes(ctx),
11681
11823
  // Import dinámico para evitar ciclos
11682
11824
  seed: async (ctx) => {
11683
- const { seed: seed5 } = await Promise.resolve().then(() => (init_storage_seed(), storage_seed_exports));
11684
- await seed5(ctx);
11825
+ const { seed: seed6 } = await Promise.resolve().then(() => (init_storage_seed(), storage_seed_exports));
11826
+ await seed6(ctx);
11685
11827
  }
11686
11828
  };
11687
11829
  }
11688
11830
  });
11689
11831
 
11690
11832
  // src/modules/users/users.entity.ts
11691
- import { useIdField as useIdField4, useSelectField as useSelectField9, useEmailField, usePasswordField, useTextField as useTextField8, useDatetimeField as useDatetimeField3, useCheckboxField as useCheckboxField4, useImageField as useImageField2, useNameField as useNameField2, useMetadataField as useMetadataField2, useDescriptionField as useDescriptionField2 } from "@gzl10/nexus-sdk/fields";
11833
+ 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";
11692
11834
  import { z as z3 } from "zod";
11693
11835
  var userEntity, roleEntity, userRoleEntity;
11694
11836
  var init_users_entity = __esm({
@@ -11751,7 +11893,7 @@ var init_users_entity = __esm({
11751
11893
  nullable: true,
11752
11894
  meta: { exportable: true, showInForm: false, showInDisplay: false }
11753
11895
  }),
11754
- consent_version: useTextField8({
11896
+ consent_version: useTextField9({
11755
11897
  label: { en: "Consent Version", es: "Versi\xF3n de consentimiento" },
11756
11898
  hidden: true,
11757
11899
  size: 20,
@@ -11762,7 +11904,7 @@ var init_users_entity = __esm({
11762
11904
  label: { en: "Marketing Opt-in", es: "Aceptar marketing" },
11763
11905
  meta: { exportable: true, showInForm: false, showInDisplay: false }
11764
11906
  }),
11765
- locale: useSelectField9({
11907
+ locale: useSelectField10({
11766
11908
  label: { en: "Language", es: "Idioma" },
11767
11909
  options: [
11768
11910
  { value: "es", label: { en: "Spanish", es: "Espa\xF1ol" } },
@@ -11772,13 +11914,13 @@ var init_users_entity = __esm({
11772
11914
  meta: { sortable: true },
11773
11915
  defaultValue: "en"
11774
11916
  }),
11775
- timezone: useSelectField9({
11917
+ timezone: useSelectField10({
11776
11918
  label: { en: "Timezone", es: "Zona horaria" },
11777
11919
  master: "timezones",
11778
11920
  meta: { sortable: true },
11779
11921
  defaultValue: "timezones:Europe/Madrid"
11780
11922
  }),
11781
- type: useSelectField9({
11923
+ type: useSelectField10({
11782
11924
  label: { en: "Type", es: "Tipo" },
11783
11925
  defaultValue: "human",
11784
11926
  options: [
@@ -11947,7 +12089,7 @@ var init_users_entity = __esm({
11947
12089
  expose: false,
11948
12090
  fields: {
11949
12091
  id: useIdField4(),
11950
- user_id: useSelectField9({
12092
+ user_id: useSelectField10({
11951
12093
  label: { en: "User", es: "Usuario" },
11952
12094
  required: true,
11953
12095
  table: "users",
@@ -11958,7 +12100,7 @@ var init_users_entity = __esm({
11958
12100
  labelField: "name",
11959
12101
  meta: { searchable: true }
11960
12102
  }),
11961
- role_id: useSelectField9({
12103
+ role_id: useSelectField10({
11962
12104
  label: { en: "Role", es: "Rol" },
11963
12105
  required: true,
11964
12106
  table: "roles",
@@ -12886,8 +13028,8 @@ var init_users = __esm({
12886
13028
  dependencies: ["logger"],
12887
13029
  // Import dinámico para evitar posibles ciclos
12888
13030
  seed: async (ctx) => {
12889
- const { seed: seed5 } = await Promise.resolve().then(() => (init_users_seed(), users_seed_exports));
12890
- await seed5(ctx);
13031
+ const { seed: seed6 } = await Promise.resolve().then(() => (init_users_seed(), users_seed_exports));
13032
+ await seed6(ctx);
12891
13033
  },
12892
13034
  init: (ctx) => {
12893
13035
  ctx.services.register("users", createUsersService(ctx));
@@ -12902,7 +13044,7 @@ var init_users = __esm({
12902
13044
  });
12903
13045
 
12904
13046
  // src/modules/auth/auth.entity.ts
12905
- import { useIdField as useIdField5, useTextField as useTextField9, useSelectField as useSelectField10, useDatetimeField as useDatetimeField4, useEmailField as useEmailField2, useMetadataField as useMetadataField3, useExpiresAtField } from "@gzl10/nexus-sdk/fields";
13047
+ 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";
12906
13048
  var refreshTokenEntity, authIdentitiesEntity;
12907
13049
  var init_auth_entity = __esm({
12908
13050
  "src/modules/auth/auth.entity.ts"() {
@@ -12917,7 +13059,7 @@ var init_auth_entity = __esm({
12917
13059
  expose: false,
12918
13060
  fields: {
12919
13061
  id: useIdField5(),
12920
- token: useTextField9({
13062
+ token: useTextField10({
12921
13063
  label: { en: "Token", es: "Token" },
12922
13064
  hidden: true,
12923
13065
  size: 255,
@@ -12944,14 +13086,14 @@ var init_auth_entity = __esm({
12944
13086
  nullable: true,
12945
13087
  meta: { sortable: true }
12946
13088
  }),
12947
- device_id: useTextField9({
13089
+ device_id: useTextField10({
12948
13090
  label: { en: "Device ID", es: "ID de dispositivo" },
12949
13091
  size: 64,
12950
13092
  index: true,
12951
13093
  nullable: true,
12952
13094
  meta: { searchable: true }
12953
13095
  }),
12954
- device_name: useTextField9({
13096
+ device_name: useTextField10({
12955
13097
  label: { en: "Device", es: "Dispositivo" },
12956
13098
  size: 100,
12957
13099
  nullable: true,
@@ -12983,7 +13125,7 @@ var init_auth_entity = __esm({
12983
13125
  order: 5,
12984
13126
  fields: {
12985
13127
  id: useIdField5(),
12986
- user_id: useSelectField10({
13128
+ user_id: useSelectField11({
12987
13129
  label: { en: "User", es: "Usuario" },
12988
13130
  table: "users",
12989
13131
  column: "id",
@@ -12995,7 +13137,7 @@ var init_auth_entity = __esm({
12995
13137
  labelField: "name",
12996
13138
  meta: { searchable: true }
12997
13139
  }),
12998
- provider: useTextField9({
13140
+ provider: useTextField10({
12999
13141
  label: { en: "Provider", es: "Proveedor" },
13000
13142
  required: true,
13001
13143
  size: 50,
@@ -13004,7 +13146,7 @@ var init_auth_entity = __esm({
13004
13146
  hint: { en: "e.g. pocketid, google, microsoft", es: "ej. pocketid, google, microsoft" },
13005
13147
  meta: { sortable: true, searchable: true }
13006
13148
  }),
13007
- provider_user_id: useTextField9({
13149
+ provider_user_id: useTextField10({
13008
13150
  label: { en: "Provider User ID", es: "ID de usuario del proveedor" },
13009
13151
  required: true,
13010
13152
  size: 255,
@@ -13299,7 +13441,7 @@ var init_auth_middleware = __esm({
13299
13441
  });
13300
13442
 
13301
13443
  // src/modules/auth/auth.pat.entity.ts
13302
- import { useIdField as useIdField6, useTextField as useTextField10, useSelectField as useSelectField11, useDatetimeField as useDatetimeField5, useExpiresAtField as useExpiresAtField2 } from "@gzl10/nexus-sdk/fields";
13444
+ import { useIdField as useIdField6, useTextField as useTextField11, useSelectField as useSelectField12, useDatetimeField as useDatetimeField5, useExpiresAtField as useExpiresAtField2 } from "@gzl10/nexus-sdk/fields";
13303
13445
  var personalTokenEntity;
13304
13446
  var init_auth_pat_entity = __esm({
13305
13447
  "src/modules/auth/auth.pat.entity.ts"() {
@@ -13316,7 +13458,7 @@ var init_auth_pat_entity = __esm({
13316
13458
  routePrefix: "/personal-tokens",
13317
13459
  fields: {
13318
13460
  id: useIdField6(),
13319
- user_id: useSelectField11({
13461
+ user_id: useSelectField12({
13320
13462
  label: { en: "User", es: "Usuario" },
13321
13463
  table: "users",
13322
13464
  column: "id",
@@ -13328,7 +13470,7 @@ var init_auth_pat_entity = __esm({
13328
13470
  labelField: "name",
13329
13471
  meta: { searchable: true }
13330
13472
  }),
13331
- name: useTextField10({
13473
+ name: useTextField11({
13332
13474
  label: { en: "Name", es: "Nombre" },
13333
13475
  required: true,
13334
13476
  size: 100,
@@ -13336,14 +13478,14 @@ var init_auth_pat_entity = __esm({
13336
13478
  hint: { en: "Descriptive name for this token", es: "Nombre descriptivo para este token" },
13337
13479
  meta: { searchable: true }
13338
13480
  }),
13339
- token_prefix: useTextField10({
13481
+ token_prefix: useTextField11({
13340
13482
  label: { en: "Token", es: "Token" },
13341
13483
  size: 20,
13342
13484
  disabled: true,
13343
13485
  nullable: false,
13344
13486
  hint: { en: "Partial token for identification", es: "Token parcial para identificaci\xF3n" }
13345
13487
  }),
13346
- token_hash: useTextField10({
13488
+ token_hash: useTextField11({
13347
13489
  label: { en: "Token Hash", es: "Hash del token" },
13348
13490
  size: 64,
13349
13491
  hidden: true,
@@ -13351,7 +13493,7 @@ var init_auth_pat_entity = __esm({
13351
13493
  unique: true,
13352
13494
  meta: { exportable: false }
13353
13495
  }),
13354
- scope: useSelectField11({
13496
+ scope: useSelectField12({
13355
13497
  label: { en: "Permission", es: "Permiso" },
13356
13498
  required: true,
13357
13499
  options: [
@@ -14940,8 +15082,8 @@ var init_auth = __esm({
14940
15082
  routePrefix: "/auth",
14941
15083
  // Import dinámico para evitar ciclos
14942
15084
  seed: async (ctx) => {
14943
- const { seed: seed5 } = await Promise.resolve().then(() => (init_auth_seed(), auth_seed_exports));
14944
- await seed5(ctx);
15085
+ const { seed: seed6 } = await Promise.resolve().then(() => (init_auth_seed(), auth_seed_exports));
15086
+ await seed6(ctx);
14945
15087
  },
14946
15088
  injectActions: [
14947
15089
  { target: { module: "users", entity: "users" }, action: impersonateAction }
@@ -15107,7 +15249,7 @@ var init_mail_service = __esm({
15107
15249
  });
15108
15250
 
15109
15251
  // src/modules/mail/mail.entity.ts
15110
- import { useIdField as useIdField7, useTextField as useTextField11, useSelectField as useSelectField12, 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";
15252
+ 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";
15111
15253
  import nodemailer2 from "nodemailer";
15112
15254
  async function getMailConfigFromDB(ctx) {
15113
15255
  const configService = ctx.services["config"];
@@ -15170,7 +15312,7 @@ var init_mail_entity = __esm({
15170
15312
  },
15171
15313
  fields: {
15172
15314
  id: useIdField7(),
15173
- host: useTextField11({
15315
+ host: useTextField12({
15174
15316
  label: { en: "SMTP Host", es: "Host SMTP" },
15175
15317
  size: 255,
15176
15318
  nullable: false,
@@ -15190,7 +15332,7 @@ var init_mail_entity = __esm({
15190
15332
  nullable: false,
15191
15333
  hint: { en: "Default: SMTP_FROM env var", es: "Por defecto: variable SMTP_FROM" }
15192
15334
  }),
15193
- auth_user: useTextField11({
15335
+ auth_user: useTextField12({
15194
15336
  label: { en: "Auth User", es: "Usuario de autenticaci\xF3n" },
15195
15337
  size: 255,
15196
15338
  nullable: true,
@@ -15222,12 +15364,12 @@ var init_mail_entity = __esm({
15222
15364
  required: true,
15223
15365
  validation: { format: "email" }
15224
15366
  }),
15225
- subject: useTextField11({
15367
+ subject: useTextField12({
15226
15368
  label: { en: "Subject", es: "Asunto" },
15227
15369
  required: true,
15228
15370
  validation: { min: 1, max: 255 }
15229
15371
  }),
15230
- title: useTextField11({
15372
+ title: useTextField12({
15231
15373
  label: { en: "Title", es: "T\xEDtulo" },
15232
15374
  hint: { en: "Large title in email header", es: "T\xEDtulo grande en la cabecera del correo" }
15233
15375
  }),
@@ -15371,20 +15513,20 @@ var init_mail_entity = __esm({
15371
15513
  nullable: false,
15372
15514
  meta: { sortable: true }
15373
15515
  }),
15374
- to: useTextField11({
15516
+ to: useTextField12({
15375
15517
  label: { en: "Recipient(s)", es: "Destinatario(s)" },
15376
15518
  size: 1e3,
15377
15519
  nullable: false,
15378
15520
  meta: { searchable: true }
15379
15521
  }),
15380
- subject: useTextField11({
15522
+ subject: useTextField12({
15381
15523
  label: { en: "Subject", es: "Asunto" },
15382
15524
  size: 255,
15383
15525
  nullable: false,
15384
15526
  meta: { searchable: true, sortable: true }
15385
15527
  }),
15386
15528
  status: {
15387
- ...useSelectField12({
15529
+ ...useSelectField13({
15388
15530
  label: { en: "Status", es: "Estado" },
15389
15531
  options: [
15390
15532
  { value: "pending", label: { en: "Pending", es: "Pendiente" } },
@@ -15398,7 +15540,7 @@ var init_mail_entity = __esm({
15398
15540
  }),
15399
15541
  validation: { enum: ["pending", "sent", "failed", "bounced"] }
15400
15542
  },
15401
- message_id: useTextField11({
15543
+ message_id: useTextField12({
15402
15544
  label: { en: "Message ID", es: "ID de mensaje" },
15403
15545
  hidden: true,
15404
15546
  size: 255,
@@ -15408,7 +15550,7 @@ var init_mail_entity = __esm({
15408
15550
  label: { en: "Error", es: "Error" },
15409
15551
  nullable: true
15410
15552
  }),
15411
- sent_by: useSelectField12({
15553
+ sent_by: useSelectField13({
15412
15554
  label: { en: "Sent by", es: "Enviado por" },
15413
15555
  table: "users",
15414
15556
  column: "id",
@@ -15531,8 +15673,8 @@ var init_mail = __esm({
15531
15673
  },
15532
15674
  // Import dinámico para evitar ciclos
15533
15675
  seed: async (ctx) => {
15534
- const { seed: seed5 } = await Promise.resolve().then(() => (init_mail_seed(), mail_seed_exports));
15535
- await seed5(ctx);
15676
+ const { seed: seed6 } = await Promise.resolve().then(() => (init_mail_seed(), mail_seed_exports));
15677
+ await seed6(ctx);
15536
15678
  }
15537
15679
  };
15538
15680
  }
@@ -16034,7 +16176,7 @@ var init_toggle_plugin_action = __esm({
16034
16176
  });
16035
16177
 
16036
16178
  // src/modules/plugins/plugins.entity.ts
16037
- import { useTextField as useTextField12, useSelectField as useSelectField13, useCheckboxField as useCheckboxField5 } from "@gzl10/nexus-sdk/fields";
16179
+ import { useTextField as useTextField13, useSelectField as useSelectField14, useCheckboxField as useCheckboxField5 } from "@gzl10/nexus-sdk/fields";
16038
16180
  import { OFFICIAL_PLUGINS } from "@gzl10/nexus-sdk";
16039
16181
  var allowPluginManagement, pluginsEntity;
16040
16182
  var init_plugins_entity = __esm({
@@ -16053,30 +16195,30 @@ var init_plugins_entity = __esm({
16053
16195
  routePrefix: "/",
16054
16196
  defaultSort: { field: "name", order: "asc" },
16055
16197
  fields: {
16056
- name: useTextField12({
16198
+ name: useTextField13({
16057
16199
  label: { en: "Name", es: "Nombre" },
16058
16200
  size: 50,
16059
16201
  nullable: false,
16060
16202
  meta: { sortable: true, searchable: true }
16061
16203
  }),
16062
- code: useTextField12({
16204
+ code: useTextField13({
16063
16205
  label: { en: "Code", es: "C\xF3digo" },
16064
16206
  size: 10,
16065
16207
  nullable: false,
16066
16208
  meta: { sortable: true }
16067
16209
  }),
16068
- label: useTextField12({
16210
+ label: useTextField13({
16069
16211
  label: { en: "Label", es: "Etiqueta" },
16070
16212
  size: 100,
16071
16213
  nullable: false,
16072
16214
  meta: { sortable: true }
16073
16215
  }),
16074
- version: useTextField12({
16216
+ version: useTextField13({
16075
16217
  label: { en: "Version", es: "Versi\xF3n" },
16076
16218
  size: 20,
16077
16219
  nullable: false
16078
16220
  }),
16079
- category: useSelectField13({
16221
+ category: useSelectField14({
16080
16222
  label: { en: "Category", es: "Categor\xEDa" },
16081
16223
  options: [
16082
16224
  { value: "content", label: { en: "Content", es: "Contenido" } },
@@ -16217,8 +16359,8 @@ var init_plugins = __esm({
16217
16359
  // src/modules/audit/audit.entity.ts
16218
16360
  import {
16219
16361
  useIdField as useIdField8,
16220
- useTextField as useTextField13,
16221
- useSelectField as useSelectField14,
16362
+ useTextField as useTextField14,
16363
+ useSelectField as useSelectField15,
16222
16364
  useTextareaField as useTextareaField4,
16223
16365
  useJsonField as useJsonField3,
16224
16366
  useDatetimeField as useDatetimeField7,
@@ -16241,7 +16383,7 @@ var init_audit_entity = __esm({
16241
16383
  fields: {
16242
16384
  id: useIdField8(),
16243
16385
  source: {
16244
- ...useTextField13({
16386
+ ...useTextField14({
16245
16387
  label: { en: "Source", es: "Origen" },
16246
16388
  size: 100,
16247
16389
  nullable: false,
@@ -16251,7 +16393,7 @@ var init_audit_entity = __esm({
16251
16393
  validation: { min: 1, max: 100 }
16252
16394
  },
16253
16395
  action: {
16254
- ...useTextField13({
16396
+ ...useTextField14({
16255
16397
  label: { en: "Action", es: "Acci\xF3n" },
16256
16398
  size: 100,
16257
16399
  nullable: false,
@@ -16260,7 +16402,7 @@ var init_audit_entity = __esm({
16260
16402
  }),
16261
16403
  validation: { min: 1, max: 100 }
16262
16404
  },
16263
- actor_id: useSelectField14({
16405
+ actor_id: useSelectField15({
16264
16406
  label: { en: "Actor", es: "Actor" },
16265
16407
  table: "users",
16266
16408
  column: "id",
@@ -16277,20 +16419,20 @@ var init_audit_entity = __esm({
16277
16419
  nullable: true,
16278
16420
  meta: { searchable: true }
16279
16421
  }),
16280
- resource_type: useTextField13({
16422
+ resource_type: useTextField14({
16281
16423
  label: { en: "Resource Type", es: "Tipo de recurso" },
16282
16424
  size: 100,
16283
16425
  nullable: true,
16284
16426
  index: true,
16285
16427
  meta: { searchable: true }
16286
16428
  }),
16287
- resource_id: useTextField13({
16429
+ resource_id: useTextField14({
16288
16430
  label: { en: "Resource ID", es: "ID del recurso" },
16289
16431
  size: 100,
16290
16432
  nullable: true,
16291
16433
  meta: { searchable: true }
16292
16434
  }),
16293
- ip_address: useTextField13({
16435
+ ip_address: useTextField14({
16294
16436
  label: { en: "IP Address", es: "Direcci\xF3n IP" },
16295
16437
  size: 45,
16296
16438
  nullable: true,
@@ -17225,33 +17367,10 @@ function buildMigrationSources() {
17225
17367
  sources.push({ id: "project", dir: getProjectMigrationsDir(), prefix: "" });
17226
17368
  return sources;
17227
17369
  }
17228
- function resolvePluginSource(source) {
17229
- if (!source.startsWith("plugin:")) return source;
17230
- const identifier = source.slice("plugin:".length);
17231
- if (/^[a-z]{3}$/.test(identifier)) {
17232
- for (const [name, plugin2] of moduleStore.plugins) {
17233
- if (plugin2.code === identifier) return `plugin:${name}`;
17234
- }
17235
- const available = [...moduleStore.plugins.values()].map((p) => p.code).sort().join(", ");
17236
- throw new CliError(
17237
- `Plugin code '${identifier}' not found`,
17238
- available ? `Available codes: ${available}` : "No plugins registered"
17239
- );
17240
- }
17241
- return `plugin:${normalizePluginName(identifier)}`;
17242
- }
17243
- function normalizeScope(raw) {
17244
- if (!raw) return void 0;
17245
- if (raw === "core" || raw === "project" || raw === "all") return raw;
17246
- const prefixed = raw.startsWith("plugin:") ? raw : `plugin:${raw}`;
17247
- return resolvePluginSource(prefixed);
17248
- }
17249
17370
  var init_migration_sources = __esm({
17250
17371
  "src/db/migration-sources.ts"() {
17251
17372
  "use strict";
17252
- init_shared();
17253
17373
  init_paths();
17254
- init_plugin_ops();
17255
17374
  init_module_store();
17256
17375
  }
17257
17376
  });
@@ -19574,15 +19693,10 @@ async function loadModulesForMigration() {
19574
19693
  }
19575
19694
  }
19576
19695
  }
19577
- async function handleCreate(name, options) {
19696
+ async function handleCreate(name) {
19578
19697
  initCli();
19579
19698
  await loadModulesForMigration();
19580
- let scope;
19581
- try {
19582
- scope = normalizeScope(options.source);
19583
- } catch (err) {
19584
- handleCliError(err);
19585
- }
19699
+ const scope = detectDefaultScope();
19586
19700
  const db3 = getDb();
19587
19701
  try {
19588
19702
  await ensureMigrationTables(db3);
@@ -19595,19 +19709,13 @@ async function handleCreate(name, options) {
19595
19709
  process.exit(0);
19596
19710
  }
19597
19711
  }
19598
- async function handleDev(name, options) {
19712
+ async function handleDev(name) {
19599
19713
  initCli();
19600
19714
  await loadModulesForMigration();
19601
- let scope;
19602
- try {
19603
- scope = normalizeScope(options.source);
19604
- } catch (err) {
19605
- handleCliError(err);
19606
- }
19607
19715
  const db3 = getDb();
19608
19716
  try {
19609
19717
  await ensureMigrationTables(db3);
19610
- await devMigration(name, scope);
19718
+ await devMigration(name);
19611
19719
  } catch (err) {
19612
19720
  console.error("Migration dev failed:", err);
19613
19721
  process.exit(1);
@@ -19669,17 +19777,9 @@ async function handleDeploy(options) {
19669
19777
  }
19670
19778
  }
19671
19779
  async function handleDown(options) {
19672
- if (!options?.source && !options?.name) {
19673
- handleCliError(new CliError("Specify -s <source> or --name <migration>", "Sources: core, project, plugin:<code|name>, or all"));
19674
- }
19675
19780
  initCli();
19676
19781
  await loadModulesForMigration();
19677
- let source;
19678
- try {
19679
- source = normalizeScope(options?.source);
19680
- } catch (err) {
19681
- handleCliError(err);
19682
- }
19782
+ const scope = detectDefaultScope();
19683
19783
  const db3 = getDb();
19684
19784
  try {
19685
19785
  await ensureMigrationTables(db3);
@@ -19687,8 +19787,8 @@ async function handleDown(options) {
19687
19787
  consola2.start(`Rolling back migration: ${options.name}`);
19688
19788
  await rollbackByName(options.name);
19689
19789
  } else {
19690
- const sourceId = scopeToSourceId(source);
19691
- consola2.start(source ? `Rolling back last batch [${source}]` : "Rolling back last batch");
19790
+ const sourceId = scopeToSourceId(scope);
19791
+ consola2.start(`Rolling back last batch [${scope}]`);
19692
19792
  await rollbackLastBatch(void 0, sourceId);
19693
19793
  }
19694
19794
  consola2.success("Rollback completed successfully");
@@ -19702,17 +19802,12 @@ async function handleDown(options) {
19702
19802
  }
19703
19803
  async function handleUndo(options) {
19704
19804
  if (process.env["NODE_ENV"] === "production") {
19705
- consola2.error("Cannot undo migrations in production");
19706
- process.exit(1);
19805
+ consola2.warn("Cannot undo migrations in production.");
19806
+ return;
19707
19807
  }
19708
19808
  initCli();
19709
19809
  await loadModulesForMigration();
19710
- let scope;
19711
- try {
19712
- scope = normalizeScope(options?.source);
19713
- } catch (err) {
19714
- handleCliError(err);
19715
- }
19810
+ const scope = detectDefaultScope();
19716
19811
  const sourceId = scopeToSourceId(scope);
19717
19812
  const db3 = getDb();
19718
19813
  try {
@@ -19721,7 +19816,7 @@ async function handleUndo(options) {
19721
19816
  if (sourceId) previewQuery.where({ source: sourceId });
19722
19817
  const target = await previewQuery.orderBy("executed_at", "desc").orderBy("batch", "desc").first();
19723
19818
  if (!target) {
19724
- consola2.info(scope ? `No completed migrations to undo [${scope}]` : "No completed migrations to undo");
19819
+ consola2.info(`No completed migrations to undo [${scope}]`);
19725
19820
  process.exit(0);
19726
19821
  }
19727
19822
  consola2.warn(`This will rollback AND DELETE migration: ${target.name}`);
@@ -19795,21 +19890,28 @@ async function handleStatus() {
19795
19890
  }
19796
19891
  async function handleReset(options) {
19797
19892
  if (process.env["NODE_ENV"] === "production") {
19798
- consola2.error("Cannot reset database in production");
19799
- process.exit(1);
19893
+ consola2.warn("Cannot reset database in production.");
19894
+ return;
19800
19895
  }
19801
19896
  initCli();
19802
19897
  await loadModulesForMigration();
19803
- let scope;
19804
- try {
19805
- scope = normalizeScope(options?.source);
19806
- } catch (err) {
19807
- handleCliError(err);
19808
- }
19898
+ const scope = detectDefaultScope();
19809
19899
  const sourceId = scopeToSourceId(scope);
19810
19900
  const db3 = getDb();
19811
19901
  try {
19812
- consola2.warn(scope ? `Resetting database [${scope}] \u2014 rollback all + re-run` : "Resetting database \u2014 rollback all + re-run");
19902
+ consola2.warn(`Resetting database [${scope}] \u2014 rollback all + re-run`);
19903
+ if (!options?.force) {
19904
+ const readline = await import("readline");
19905
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
19906
+ const answer = await new Promise((resolve) => {
19907
+ rl.question("Continue? (y/N) ", resolve);
19908
+ });
19909
+ rl.close();
19910
+ if (answer.toLowerCase() !== "y") {
19911
+ consola2.info("Aborted");
19912
+ process.exit(0);
19913
+ }
19914
+ }
19813
19915
  await ensureMigrationTables(db3);
19814
19916
  await resetDatabase(void 0, sourceId);
19815
19917
  consola2.success("Database reset complete");
@@ -19823,24 +19925,29 @@ async function handleReset(options) {
19823
19925
  }
19824
19926
  async function handleDrop(options) {
19825
19927
  if (process.env["NODE_ENV"] === "production") {
19826
- consola2.error("Cannot drop migrations in production");
19827
- process.exit(1);
19928
+ consola2.warn("Cannot drop migrations in production.");
19929
+ return;
19828
19930
  }
19829
19931
  initCli();
19830
19932
  await loadModulesForMigration();
19831
- let scope;
19832
- try {
19833
- scope = normalizeScope(options.source);
19834
- } catch (err) {
19835
- handleCliError(err);
19836
- }
19837
- if (scope === "all") {
19838
- handleCliError(new CliError("Cannot drop all sources", 'Use "nexus db wipe" to drop all tables'));
19839
- }
19933
+ const scope = detectDefaultScope();
19840
19934
  const sourceId = scopeToSourceId(scope);
19841
19935
  const db3 = getDb();
19842
19936
  try {
19843
19937
  await ensureMigrationTables(db3);
19938
+ consola2.warn(`This will DROP ALL migrations for source: ${sourceId}`);
19939
+ if (!options?.force) {
19940
+ const readline = await import("readline");
19941
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
19942
+ const answer = await new Promise((resolve) => {
19943
+ rl.question("Continue? (y/N) ", resolve);
19944
+ });
19945
+ rl.close();
19946
+ if (answer.toLowerCase() !== "y") {
19947
+ consola2.info("Aborted");
19948
+ process.exit(0);
19949
+ }
19950
+ }
19844
19951
  consola2.start(`Dropping all migrations for source: ${sourceId}`);
19845
19952
  await rollbackAll(db3, sourceId);
19846
19953
  consola2.success(`All migrations dropped for source: ${sourceId}`);
@@ -19864,7 +19971,6 @@ var init_migrate_commands = __esm({
19864
19971
  init_ensure_system_tables();
19865
19972
  init_migration_generator();
19866
19973
  init_migration_runner();
19867
- init_migration_sources();
19868
19974
  }
19869
19975
  });
19870
19976
 
@@ -19879,10 +19985,11 @@ __export(db_commands_exports, {
19879
19985
  import { spawn as spawn2 } from "child_process";
19880
19986
  import { isAbsolute as isAbsolute3, join as join15 } from "path";
19881
19987
  import { statSync as statSync2 } from "fs";
19988
+ import { consola as consola3 } from "consola";
19882
19989
  async function handleDbWipe(options) {
19883
19990
  if (process.env["NODE_ENV"] === "production") {
19884
- console.error("Cannot wipe database in production");
19885
- process.exit(1);
19991
+ consola3.warn("Cannot wipe database in production.");
19992
+ return;
19886
19993
  }
19887
19994
  initCli();
19888
19995
  const db3 = getDb();
@@ -20069,7 +20176,7 @@ __export(plugin_commands_exports, {
20069
20176
  import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
20070
20177
  import { join as join16 } from "path";
20071
20178
  import Table2 from "cli-table3";
20072
- import { consola as consola3 } from "consola";
20179
+ import { consola as consola4 } from "consola";
20073
20180
  import { OFFICIAL_PLUGINS as OFFICIAL_PLUGINS2 } from "@gzl10/nexus-sdk";
20074
20181
  function pluginLabel(name) {
20075
20182
  return shortPluginName(name).split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
@@ -20133,7 +20240,7 @@ async function handlePluginList(options = {}) {
20133
20240
  }
20134
20241
  console.log(table.toString());
20135
20242
  } else {
20136
- consola3.info("No plugins installed.");
20243
+ consola4.info("No plugins installed.");
20137
20244
  }
20138
20245
  const available = OFFICIAL_PLUGINS2.filter((name) => !installedNames.has(name));
20139
20246
  if (available.length > 0) {
@@ -20149,34 +20256,33 @@ async function handlePluginList(options = {}) {
20149
20256
  }
20150
20257
  async function handlePluginAdd(name, options) {
20151
20258
  if (process.env["NEXUS_ALLOW_PLUGIN_INSTALL"] === "false") {
20152
- consola3.error("Plugin installation is disabled (NEXUS_ALLOW_PLUGIN_INSTALL=false)");
20153
- process.exit(1);
20259
+ consola4.warn("Plugin installation is disabled (NEXUS_ALLOW_PLUGIN_INSTALL=false)");
20260
+ return;
20154
20261
  }
20155
20262
  initCli();
20156
20263
  const projectPath2 = getProjectPath();
20157
20264
  const discovered = await discoverPlugins(projectPath2);
20158
20265
  const fullName = resolvePluginName(name, discovered);
20159
20266
  try {
20160
- consola3.start(`Installing ${fullName}${options.version ? `@${options.version}` : ""}...`);
20267
+ consola4.start(`Installing ${fullName}${options.version ? `@${options.version}` : ""}...`);
20161
20268
  await installPlugin(fullName, { version: options.version });
20162
- consola3.success(`Plugin ${fullName} installed and enabled.`);
20269
+ consola4.success(`Plugin ${fullName} installed and enabled.`);
20163
20270
  } catch (err) {
20164
- consola3.error(`Failed to install plugin: ${err.message}`);
20165
- process.exit(1);
20271
+ consola4.error(`Failed to install plugin: ${err.message}`);
20166
20272
  }
20167
20273
  }
20168
20274
  async function handlePluginRemove(name, options = {}) {
20169
20275
  if (process.env["NEXUS_ALLOW_PLUGIN_INSTALL"] === "false") {
20170
- consola3.error("Plugin management is disabled (NEXUS_ALLOW_PLUGIN_INSTALL=false)");
20171
- process.exit(1);
20276
+ consola4.warn("Plugin management is disabled (NEXUS_ALLOW_PLUGIN_INSTALL=false)");
20277
+ return;
20172
20278
  }
20173
20279
  if (!name && !options.all) {
20174
- consola3.error("Provide a plugin name or use -a to remove all.");
20175
- process.exit(1);
20280
+ consola4.warn("Provide a plugin name or use -a to remove all.");
20281
+ return;
20176
20282
  }
20177
20283
  if (name && options.all) {
20178
- consola3.error("Cannot combine plugin name with -a flag.");
20179
- process.exit(1);
20284
+ consola4.warn("Cannot combine plugin name with -a flag.");
20285
+ return;
20180
20286
  }
20181
20287
  initCli();
20182
20288
  const projectPath2 = getProjectPath();
@@ -20185,7 +20291,7 @@ async function handlePluginRemove(name, options = {}) {
20185
20291
  const states = getAllPluginStates(projectPath2);
20186
20292
  const names = Object.keys(states);
20187
20293
  if (names.length === 0) {
20188
- consola3.info("No plugins installed.");
20294
+ consola4.info("No plugins installed.");
20189
20295
  return;
20190
20296
  }
20191
20297
  const table = new Table2({ head: ["Name", "Enabled"] });
@@ -20195,54 +20301,57 @@ async function handlePluginRemove(name, options = {}) {
20195
20301
  console.log("\n Plugins to remove:");
20196
20302
  console.log(table.toString());
20197
20303
  console.log(`
20198
- Tip: run "nexus migrate drop -s plugin:<name>" for each plugin first to drop their tables.`);
20199
- const confirmed2 = await consola3.prompt(
20304
+ Tip: run "nexus migrate drop" from each plugin directory first to drop their tables.`);
20305
+ const confirmed2 = await consola4.prompt(
20200
20306
  `Remove ALL ${names.length} plugins? This cannot be undone.`,
20201
20307
  { type: "confirm", initial: false }
20202
20308
  );
20203
20309
  if (!confirmed2 || typeof confirmed2 === "symbol") {
20204
- consola3.info("Aborted.");
20310
+ consola4.info("Aborted.");
20205
20311
  return;
20206
20312
  }
20207
20313
  for (const n of names) {
20208
20314
  try {
20209
- consola3.start(`Removing ${shortPluginName(n)}...`);
20315
+ consola4.start(`Removing ${shortPluginName(n)}...`);
20210
20316
  await uninstallPlugin(n);
20211
- consola3.success(`${shortPluginName(n)} removed.`);
20317
+ consola4.success(`${shortPluginName(n)} removed.`);
20212
20318
  } catch (err) {
20213
- consola3.error(`Failed to remove ${shortPluginName(n)}: ${err.message}`);
20319
+ consola4.error(`Failed to remove ${shortPluginName(n)}: ${err.message}`);
20214
20320
  }
20215
20321
  }
20216
20322
  return;
20217
20323
  }
20218
20324
  const fullName = resolvePluginName(name, discovered);
20219
20325
  const short = shortPluginName(fullName);
20220
- const confirmed = await consola3.prompt(
20326
+ if (!isPackageInstalled(fullName) && !getPluginState(fullName)) {
20327
+ consola4.warn(`Plugin "${short}" is not installed.`);
20328
+ return;
20329
+ }
20330
+ const confirmed = await consola4.prompt(
20221
20331
  `Remove plugin "${short}"? This will uninstall the dependency.
20222
- Tip: run "nexus migrate drop -s plugin:${fullName}" first to drop its tables.`,
20332
+ Tip: run "nexus migrate drop" from the plugin directory first to drop its tables.`,
20223
20333
  { type: "confirm", initial: false }
20224
20334
  );
20225
20335
  if (!confirmed || typeof confirmed === "symbol") {
20226
- consola3.info("Aborted.");
20336
+ consola4.info("Aborted.");
20227
20337
  return;
20228
20338
  }
20229
20339
  try {
20230
- consola3.start(`Removing ${fullName}...`);
20340
+ consola4.start(`Removing ${fullName}...`);
20231
20341
  await uninstallPlugin(fullName);
20232
- consola3.success(`Plugin ${short} removed.`);
20342
+ consola4.success(`Plugin ${short} removed.`);
20233
20343
  } catch (err) {
20234
- consola3.error(`Failed to remove plugin: ${err.message}`);
20235
- process.exit(1);
20344
+ consola4.error(`Failed to remove plugin: ${err.message}`);
20236
20345
  }
20237
20346
  }
20238
20347
  async function handlePluginEnable(name, options = {}) {
20239
20348
  if (!name && !options.all) {
20240
- consola3.error("Provide a plugin name or use -a to enable all.");
20241
- process.exit(1);
20349
+ consola4.warn("Provide a plugin name or use -a to enable all.");
20350
+ return;
20242
20351
  }
20243
20352
  if (name && options.all) {
20244
- consola3.error("Cannot combine plugin name with -a flag.");
20245
- process.exit(1);
20353
+ consola4.warn("Cannot combine plugin name with -a flag.");
20354
+ return;
20246
20355
  }
20247
20356
  initCli();
20248
20357
  const projectPath2 = getProjectPath();
@@ -20250,34 +20359,33 @@ async function handlePluginEnable(name, options = {}) {
20250
20359
  const states = getAllPluginStates(projectPath2);
20251
20360
  const disabled = Object.entries(states).filter(([, s]) => !s.enabled);
20252
20361
  if (disabled.length === 0) {
20253
- consola3.info("All plugins are already enabled.");
20362
+ consola4.info("All plugins are already enabled.");
20254
20363
  return;
20255
20364
  }
20256
20365
  for (const [n] of disabled) {
20257
20366
  enablePlugin(n, projectPath2);
20258
- consola3.success(`${shortPluginName(n)} enabled.`);
20367
+ consola4.success(`${shortPluginName(n)} enabled.`);
20259
20368
  }
20260
- consola3.info("Restart server to apply.");
20369
+ consola4.info("Restart server to apply.");
20261
20370
  return;
20262
20371
  }
20263
20372
  const discovered = await discoverPlugins(projectPath2);
20264
20373
  const fullName = resolvePluginName(name, discovered);
20265
20374
  try {
20266
20375
  enablePlugin(fullName);
20267
- consola3.success(`Plugin ${shortPluginName(fullName)} enabled. Restart server to apply.`);
20376
+ consola4.success(`Plugin ${shortPluginName(fullName)} enabled. Restart server to apply.`);
20268
20377
  } catch (err) {
20269
- consola3.error(err.message);
20270
- process.exit(1);
20378
+ consola4.error(err.message);
20271
20379
  }
20272
20380
  }
20273
20381
  async function handlePluginDisable(name, options = {}) {
20274
20382
  if (!name && !options.all) {
20275
- consola3.error("Provide a plugin name or use -a to disable all.");
20276
- process.exit(1);
20383
+ consola4.warn("Provide a plugin name or use -a to disable all.");
20384
+ return;
20277
20385
  }
20278
20386
  if (name && options.all) {
20279
- consola3.error("Cannot combine plugin name with -a flag.");
20280
- process.exit(1);
20387
+ consola4.warn("Cannot combine plugin name with -a flag.");
20388
+ return;
20281
20389
  }
20282
20390
  initCli();
20283
20391
  const projectPath2 = getProjectPath();
@@ -20285,24 +20393,23 @@ async function handlePluginDisable(name, options = {}) {
20285
20393
  const states = getAllPluginStates(projectPath2);
20286
20394
  const enabled = Object.entries(states).filter(([, s]) => s.enabled);
20287
20395
  if (enabled.length === 0) {
20288
- consola3.info("All plugins are already disabled.");
20396
+ consola4.info("All plugins are already disabled.");
20289
20397
  return;
20290
20398
  }
20291
20399
  for (const [n] of enabled) {
20292
20400
  disablePlugin(n, projectPath2);
20293
- consola3.success(`${shortPluginName(n)} disabled.`);
20401
+ consola4.success(`${shortPluginName(n)} disabled.`);
20294
20402
  }
20295
- consola3.info("Restart server to apply.");
20403
+ consola4.info("Restart server to apply.");
20296
20404
  return;
20297
20405
  }
20298
20406
  const discovered = await discoverPlugins(projectPath2);
20299
20407
  const fullName = resolvePluginName(name, discovered);
20300
20408
  try {
20301
20409
  disablePlugin(fullName);
20302
- consola3.success(`Plugin ${shortPluginName(fullName)} disabled. Restart server to apply.`);
20410
+ consola4.success(`Plugin ${shortPluginName(fullName)} disabled. Restart server to apply.`);
20303
20411
  } catch (err) {
20304
- consola3.error(err.message);
20305
- process.exit(1);
20412
+ consola4.error(err.message);
20306
20413
  }
20307
20414
  }
20308
20415
  async function handlePluginInfo(name) {
@@ -20313,11 +20420,11 @@ async function handlePluginInfo(name) {
20313
20420
  const manifest = discovered.find((p) => p.name === fullName);
20314
20421
  const state = getPluginState(fullName, projectPath2);
20315
20422
  if (!manifest && !state) {
20316
- consola3.error(`Plugin ${fullName} not found (not in package.json nor nexus.plugins.json)`);
20317
- process.exit(1);
20423
+ consola4.warn(`Plugin "${shortPluginName(fullName)}" not found.`);
20424
+ return;
20318
20425
  }
20319
20426
  console.log("");
20320
- consola3.info(`Plugin: ${fullName}`);
20427
+ consola4.info(`Plugin: ${fullName}`);
20321
20428
  if (manifest) {
20322
20429
  console.log(` Code: ${manifest.code}`);
20323
20430
  console.log(` Version: ${manifest.version}`);
@@ -20372,9 +20479,9 @@ async function handleSyncCommands(options) {
20372
20479
  const sourceDir = join17(getLibPath(), "claude-commands");
20373
20480
  const targetDir = join17(homedir(), ".claude", "commands");
20374
20481
  if (!existsSync13(sourceDir)) {
20375
- logger2.error(`Commands source not found: ${sourceDir}`);
20482
+ logger2.warn(`Commands source not found: ${sourceDir}`);
20376
20483
  logger2.info("Make sure @gzl10/nexus-backend is properly installed.");
20377
- process.exit(1);
20484
+ return;
20378
20485
  }
20379
20486
  if (!existsSync13(targetDir)) {
20380
20487
  if (options.dryRun) {
@@ -20440,6 +20547,137 @@ var init_sync_commands = __esm({
20440
20547
  }
20441
20548
  });
20442
20549
 
20550
+ // src/cli/seed-commands.ts
20551
+ var seed_commands_exports = {};
20552
+ __export(seed_commands_exports, {
20553
+ handleSeedExport: () => handleSeedExport,
20554
+ importSeedFiles: () => importSeedFiles
20555
+ });
20556
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, writeFileSync as writeFileSync4, readdirSync as readdirSync3, readFileSync as readFileSync11 } from "fs";
20557
+ import { join as join18, basename as basename5 } from "path";
20558
+ import { consola as consola5 } from "consola";
20559
+ function deserializeJsonFields(record, fields) {
20560
+ const result = { ...record };
20561
+ for (const [name, field] of Object.entries(fields)) {
20562
+ if (field.db?.type === "json" && typeof result[name] === "string") {
20563
+ try {
20564
+ result[name] = JSON.parse(result[name]);
20565
+ } catch {
20566
+ }
20567
+ }
20568
+ }
20569
+ return result;
20570
+ }
20571
+ function serializeJsonFields(record, fields) {
20572
+ const result = { ...record };
20573
+ for (const [name, field] of Object.entries(fields)) {
20574
+ if (field.db?.type === "json" && typeof result[name] === "object" && result[name] !== null) {
20575
+ result[name] = JSON.stringify(result[name]);
20576
+ }
20577
+ }
20578
+ return result;
20579
+ }
20580
+ async function handleSeedExport(entity) {
20581
+ initCli();
20582
+ await loadModulesForMigration();
20583
+ const db3 = getDb();
20584
+ try {
20585
+ const modules = getOrderedModules();
20586
+ const seedDir = join18(getProjectPath(), "data", "seeds");
20587
+ const seedableEntities = [];
20588
+ for (const mod of modules) {
20589
+ for (const def of mod.definitions ?? []) {
20590
+ if (!("seedable" in def) || !def.seedable) continue;
20591
+ if (entity && def.table !== entity) continue;
20592
+ seedableEntities.push({
20593
+ module: mod.name,
20594
+ table: def.table,
20595
+ fields: def.fields
20596
+ });
20597
+ }
20598
+ }
20599
+ if (seedableEntities.length === 0) {
20600
+ if (entity) {
20601
+ consola5.warn(`No seedable entity found with table "${entity}"`);
20602
+ } else {
20603
+ consola5.warn("No seedable entities found");
20604
+ }
20605
+ return;
20606
+ }
20607
+ if (!existsSync14(seedDir)) {
20608
+ mkdirSync7(seedDir, { recursive: true });
20609
+ }
20610
+ for (const { module: modName, table, fields } of seedableEntities) {
20611
+ const rows = await db3(table).orderBy("id");
20612
+ if (rows.length === 0) {
20613
+ consola5.info(`${table}: no records, skipping`);
20614
+ continue;
20615
+ }
20616
+ const exported = rows.map(
20617
+ (row) => deserializeJsonFields(row, fields)
20618
+ );
20619
+ const filePath = join18(seedDir, `${table}.json`);
20620
+ writeFileSync4(filePath, JSON.stringify(exported, null, 2) + "\n", "utf-8");
20621
+ consola5.success(`${table}: exported ${rows.length} records to data/seeds/${table}.json (module: ${modName})`);
20622
+ }
20623
+ } catch (err) {
20624
+ consola5.error("Seed export failed:", err);
20625
+ } finally {
20626
+ await db3.destroy();
20627
+ process.exit(0);
20628
+ }
20629
+ }
20630
+ async function importSeedFiles(db3, modules, logger3) {
20631
+ const seedDir = join18(getProjectPath(), "data", "seeds");
20632
+ if (!existsSync14(seedDir)) return;
20633
+ const files = readdirSync3(seedDir).filter((f) => f.endsWith(".json"));
20634
+ if (files.length === 0) return;
20635
+ const seedableDefs = /* @__PURE__ */ new Map();
20636
+ for (const mod of modules) {
20637
+ for (const rawDef of mod.definitions ?? []) {
20638
+ const def = rawDef;
20639
+ if (!def["seedable"] || !def["table"] || !def["fields"]) continue;
20640
+ seedableDefs.set(
20641
+ def["table"],
20642
+ { fields: def["fields"], module: mod.name }
20643
+ );
20644
+ }
20645
+ }
20646
+ for (const file of files) {
20647
+ const table = basename5(file, ".json");
20648
+ const defInfo = seedableDefs.get(table);
20649
+ if (!defInfo) {
20650
+ logger3.debug(`data/seeds/${file}: skipped (entity "${table}" is not seedable)`);
20651
+ continue;
20652
+ }
20653
+ const filePath = join18(seedDir, file);
20654
+ const raw = readFileSync11(filePath, "utf-8");
20655
+ let records;
20656
+ try {
20657
+ records = JSON.parse(raw);
20658
+ } catch {
20659
+ logger3.info(`data/seeds/${file}: skipped (invalid JSON)`);
20660
+ continue;
20661
+ }
20662
+ if (!Array.isArray(records) || records.length === 0) continue;
20663
+ const rows = records.map((r) => serializeJsonFields(r, defInfo.fields));
20664
+ for (const row of rows) {
20665
+ await db3(table).insert(row).onConflict("id").merge();
20666
+ }
20667
+ logger3.info(`Seeded ${rows.length} records into ${table} from data/seeds/${file}`);
20668
+ }
20669
+ }
20670
+ var init_seed_commands = __esm({
20671
+ "src/cli/seed-commands.ts"() {
20672
+ "use strict";
20673
+ init_engine();
20674
+ init_paths();
20675
+ init_connection();
20676
+ init_shared();
20677
+ init_migrate_commands();
20678
+ }
20679
+ });
20680
+
20443
20681
  // src/env-loader.ts
20444
20682
  import { existsSync } from "fs";
20445
20683
  import { join, dirname } from "path";
@@ -20460,12 +20698,12 @@ if (!nodeEnv || nodeEnv === "development") {
20460
20698
  }
20461
20699
 
20462
20700
  // src/cli.ts
20463
- import { readFileSync as readFileSync11 } from "fs";
20701
+ import { readFileSync as readFileSync12 } from "fs";
20464
20702
  import { fileURLToPath as fileURLToPath3 } from "url";
20465
- import { dirname as dirname8, join as join18 } from "path";
20703
+ import { dirname as dirname8, join as join19 } from "path";
20466
20704
  import { Command } from "commander";
20467
20705
  var __dirname2 = dirname8(fileURLToPath3(import.meta.url));
20468
- var pkg2 = JSON.parse(readFileSync11(join18(__dirname2, "..", "package.json"), "utf-8"));
20706
+ var pkg2 = JSON.parse(readFileSync12(join19(__dirname2, "..", "package.json"), "utf-8"));
20469
20707
  var program = new Command();
20470
20708
  program.name("nexus").description("Nexus Backend CLI").version(pkg2.version);
20471
20709
  program.command("info").description("Show Nexus environment, database, plugins, and paths").option("--json", "Output as JSON").action(async (options) => {
@@ -20473,13 +20711,13 @@ program.command("info").description("Show Nexus environment, database, plugins,
20473
20711
  await handleInfo2(options);
20474
20712
  });
20475
20713
  var migrate = program.command("migrate").description("Database migration management");
20476
- migrate.command("create <name>").description("Generate migration by comparing entities vs current schema").option("-s, --source <scope>", "Migration scope: core, project, plugin:<code|name>, or all", "core").action(async (name, options) => {
20714
+ migrate.command("create <name>").description("Generate migration by comparing entities vs current schema (scope auto-detected from CWD)").action(async (name) => {
20477
20715
  const { handleCreate: handleCreate2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20478
- await handleCreate2(name, options);
20716
+ await handleCreate2(name);
20479
20717
  });
20480
- migrate.command("dev [name]").description('Generate and apply migration automatically (auto-detects plugin scope). Name defaults to "auto" if omitted').option("-s, --source <scope>", "Override scope: project, plugin:<code|name>").action(async (name, options) => {
20718
+ migrate.command("dev [name]").description('Generate and apply migration automatically (scope auto-detected from CWD). Name defaults to "auto" if omitted').action(async (name) => {
20481
20719
  const { handleDev: handleDev2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20482
- await handleDev2(name, options);
20720
+ await handleDev2(name);
20483
20721
  });
20484
20722
  migrate.command("up").description("Run all pending migrations").action(async () => {
20485
20723
  const { handleUp: handleUp2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
@@ -20489,11 +20727,11 @@ migrate.command("deploy").description("Apply pending migrations (production-safe
20489
20727
  const { handleDeploy: handleDeploy2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20490
20728
  await handleDeploy2(options);
20491
20729
  });
20492
- migrate.command("down").description("Rollback last batch of migrations (or a specific migration with --name)").option("--name <migration_name>", "Rollback a specific migration by name").option("-s, --source <scope>", "Filter by source: core, project, plugin:<code|name>").action(async (options) => {
20730
+ migrate.command("down").description("Rollback last batch of migrations (scope auto-detected from CWD, or specific migration with --name)").option("--name <migration_name>", "Rollback a specific migration by name").action(async (options) => {
20493
20731
  const { handleDown: handleDown2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20494
20732
  await handleDown2(options);
20495
20733
  });
20496
- migrate.command("undo").description("Rollback last migration AND delete its file (DEV ONLY)").requiredOption("-s, --source <scope>", "Source: core, project, plugin:<code|name>, or all").option("--force", "Skip confirmation prompt").action(async (options) => {
20734
+ migrate.command("undo").description("Rollback last migration AND delete its file (DEV ONLY, scope auto-detected from CWD)").option("--force", "Skip confirmation prompt").action(async (options) => {
20497
20735
  const { handleUndo: handleUndo2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20498
20736
  await handleUndo2(options);
20499
20737
  });
@@ -20501,11 +20739,11 @@ migrate.command("status").description("Show migration status and schema drift").
20501
20739
  const { handleStatus: handleStatus2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20502
20740
  await handleStatus2();
20503
20741
  });
20504
- migrate.command("reset").description("Rollback all migrations and re-run (DEV ONLY)").requiredOption("-s, --source <scope>", "Source: core, project, plugin:<code|name>, or all").action(async (options) => {
20742
+ migrate.command("reset").description("Rollback all migrations and re-run (DEV ONLY, scope auto-detected from CWD)").option("--force", "Skip confirmation prompt").action(async (options) => {
20505
20743
  const { handleReset: handleReset2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20506
20744
  await handleReset2(options);
20507
20745
  });
20508
- migrate.command("drop").description("Rollback ALL batches of a source and remove records (DEV ONLY)").requiredOption("-s, --source <scope>", "Source: core, project, or plugin:<code|name>").action(async (options) => {
20746
+ migrate.command("drop").description("Rollback ALL batches of a source and remove records (DEV ONLY, scope auto-detected from CWD)").option("--force", "Skip confirmation prompt").action(async (options) => {
20509
20747
  const { handleDrop: handleDrop2 } = await Promise.resolve().then(() => (init_migrate_commands(), migrate_commands_exports));
20510
20748
  await handleDrop2(options);
20511
20749
  });
@@ -20551,5 +20789,10 @@ program.command("sync:commands").description("Sync Nexus Claude Code commands to
20551
20789
  const { handleSyncCommands: handleSyncCommands2 } = await Promise.resolve().then(() => (init_sync_commands(), sync_commands_exports));
20552
20790
  await handleSyncCommands2(options);
20553
20791
  });
20792
+ var seed5 = program.command("seed").description("Seed data management");
20793
+ seed5.command("export [entity]").description("Export seedable entity data from DB to data/seeds/ JSONs").action(async (entity) => {
20794
+ const { handleSeedExport: handleSeedExport2 } = await Promise.resolve().then(() => (init_seed_commands(), seed_commands_exports));
20795
+ await handleSeedExport2(entity);
20796
+ });
20554
20797
  program.parse();
20555
20798
  //# sourceMappingURL=cli.js.map