@gzl10/nexus-sdk 0.4.0 → 0.4.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/index.d.ts CHANGED
@@ -11,6 +11,8 @@ import { Logger } from 'pino';
11
11
  * que pueden ser escritos a archivos o usados en runtime.
12
12
  */
13
13
 
14
+ /** Directorio estándar para código generado */
15
+ declare const GENERATED_DIR = "__generated__";
14
16
  /**
15
17
  * Entidades que persisten en BD local con tabla propia
16
18
  * Excluye: action, external, virtual, computed, single (usa tabla compartida)
@@ -130,6 +132,15 @@ declare function generateSchemasFile(definitions: EntityDefinition[]): string;
130
132
  * writeFileSync('users.models.ts', code)
131
133
  */
132
134
  declare function generateModelsFile(definitions: EntityDefinition[]): string;
135
+ /**
136
+ * Genera archivo completo de migración Knex para múltiples entidades
137
+ * Consolida todas las entidades de un módulo en un solo archivo de migración
138
+ *
139
+ * @example
140
+ * const code = generateMigrationsFile([userEntity, roleEntity])
141
+ * writeFileSync('users.migrate.ts', code)
142
+ */
143
+ declare function generateMigrationsFile(definitions: EntityDefinition[]): string;
133
144
 
134
145
  /**
135
146
  * @gzl10/nexus-sdk
@@ -634,21 +645,6 @@ interface ModuleAbilities {
634
645
  * Usa BaseUser y AbilityLike para tipado básico sin depender del backend
635
646
  */
636
647
  type PluginAuthRequest = AuthRequest<BaseUser, AbilityLike>;
637
- /**
638
- * Resolver de usuarios para plugins
639
- * Permite acceder a usuarios sin conocer la implementación interna
640
- */
641
- interface UsersResolver {
642
- findById: (id: string) => Promise<BaseUser | null>;
643
- findByIds: (ids: string[]) => Promise<BaseUser[]>;
644
- }
645
- /**
646
- * Servicios core inyectados por el backend
647
- * Los plugins acceden a estos servicios via ctx.services
648
- */
649
- interface CoreServices {
650
- users?: UsersResolver;
651
- }
652
648
  /**
653
649
  * Helpers para migraciones de base de datos
654
650
  */
@@ -713,8 +709,8 @@ interface ModuleContext {
713
709
  data?: Record<string, unknown>;
714
710
  }) => Promise<unknown>;
715
711
  };
716
- /** Servicios de módulos core (users, etc.) */
717
- services: CoreServices & Record<string, unknown>;
712
+ /** Servicios de módulos (inyectados por backend) */
713
+ services: Record<string, unknown>;
718
714
  }
719
715
  /**
720
716
  * Manifest de un módulo Nexus
@@ -722,8 +718,6 @@ interface ModuleContext {
722
718
  interface ModuleManifest {
723
719
  /** Identificador único del módulo (ej: 'users', 'posts') */
724
720
  name: string;
725
- /** Código único del módulo (ej: 'USR', 'PST'). Opcional si pertenece a un plugin */
726
- code?: string;
727
721
  /** Nombre para mostrar en UI. Opcional si pertenece a un plugin */
728
722
  label?: string;
729
723
  /** Icono del módulo (Iconify MDI: 'mdi:account-group') */
@@ -736,7 +730,7 @@ interface ModuleManifest {
736
730
  dependencies?: string[];
737
731
  /** Requisitos para activar el módulo */
738
732
  required?: ModuleRequirements;
739
- /** Función de migración de base de datos */
733
+ /** Función de migración de base de datos. Normalmente se genera desde definitions (EntityDefinition) */
740
734
  migrate?: (ctx: ModuleContext) => Promise<void>;
741
735
  /** Función de seed de datos iniciales */
742
736
  seed?: (ctx: ModuleContext) => Promise<void>;
@@ -781,4 +775,4 @@ interface PluginManifest {
781
775
  modules: ModuleManifest[];
782
776
  }
783
777
 
784
- export { type AbilityLike, type ActionEntityDefinition, type AuthRequest, type BaseUser, type CaslAction, type CollectionEntityDefinition, type ComputedEntityDefinition, type ConfigEntityDefinition, type CoreServices, type DbType, type EntityCaslConfig, type EntityDefinition, type EntityIndex, type EventEntityDefinition, type ExternalEntityDefinition, type FieldCaslAccess, type FieldDbConfig, type FieldDefinition, type FieldMeta, type FieldOptions, type FieldRelation, type FieldValidation, type FieldValidationConfig, type ForbiddenErrorConstructor, type ForbiddenErrorInstance, type FormField, type FormFieldType, type GeneratedPermission, type InputType, type KnexAlterTableBuilder, type KnexCreateTableBuilder, type KnexTransaction, type ListType, type MigrationHelpers, type ModuleAbilities, type ModuleContext, type ModuleManifest, type ModuleMiddlewares, type ModuleRequirements, type NonPersistentEntityDefinition, type OwnershipCondition, type PaginatedResult, type PaginationParams, type PersistentEntityDefinition, type PluginAuthRequest, type PluginCategory, type PluginManifest, type ReferenceEntityDefinition, type RolePermission, type SingleEntityDefinition, type TempEntityDefinition, type UsersResolver, type ValidateSchemas, type ValidationSchema, type ViewEntityDefinition, type VirtualEntityDefinition, generateCaslPermissions, generateCaslSeed, generateMigration, generateModel, generateModelsFile, generateReadOnlyModel, generateReadOnlySchema, generateSchemasFile, generateZodSchema, getEntityName, getEntitySubject, hasTable, isPersistentEntity, isSingletonEntity };
778
+ export { type AbilityLike, type ActionEntityDefinition, type AuthRequest, type BaseUser, type CaslAction, type CollectionEntityDefinition, type ComputedEntityDefinition, type ConfigEntityDefinition, type DbType, type EntityCaslConfig, type EntityDefinition, type EntityIndex, type EventEntityDefinition, type ExternalEntityDefinition, type FieldCaslAccess, type FieldDbConfig, type FieldDefinition, type FieldMeta, type FieldOptions, type FieldRelation, type FieldValidation, type FieldValidationConfig, type ForbiddenErrorConstructor, type ForbiddenErrorInstance, type FormField, type FormFieldType, GENERATED_DIR, type GeneratedPermission, type InputType, type KnexAlterTableBuilder, type KnexCreateTableBuilder, type KnexTransaction, type ListType, type MigrationHelpers, type ModuleAbilities, type ModuleContext, type ModuleManifest, type ModuleMiddlewares, type ModuleRequirements, type NonPersistentEntityDefinition, type OwnershipCondition, type PaginatedResult, type PaginationParams, type PersistentEntityDefinition, type PluginAuthRequest, type PluginCategory, type PluginManifest, type ReferenceEntityDefinition, type RolePermission, type SingleEntityDefinition, type TempEntityDefinition, type ValidateSchemas, type ValidationSchema, type ViewEntityDefinition, type VirtualEntityDefinition, generateCaslPermissions, generateCaslSeed, generateMigration, generateMigrationsFile, generateModel, generateModelsFile, generateReadOnlyModel, generateReadOnlySchema, generateSchemasFile, generateZodSchema, getEntityName, getEntitySubject, hasTable, isPersistentEntity, isSingletonEntity };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/generators.ts
2
+ var GENERATED_DIR = "__generated__";
2
3
  function isPersistentEntity(entity) {
3
4
  const withoutOwnTable = ["action", "external", "virtual", "computed", "single"];
4
5
  return !withoutOwnTable.includes(entity.type ?? "collection");
@@ -648,10 +649,148 @@ function generateModelsFile(definitions) {
648
649
  }
649
650
  return lines.join("\n");
650
651
  }
652
+ function generateMigrationsFile(definitions) {
653
+ const persistentEntities = definitions.filter(isPersistentEntity);
654
+ if (persistentEntities.length === 0) {
655
+ return [
656
+ "/**",
657
+ " * AUTO-GENERATED - Do not edit manually",
658
+ " * Generated from EntityDefinition via @gzl10/nexus-sdk generators",
659
+ " */",
660
+ "",
661
+ "import type { ModuleContext } from '@gzl10/nexus-sdk'",
662
+ "",
663
+ "// No persistent entities to migrate",
664
+ "export async function migrate(_ctx: ModuleContext): Promise<void> {}",
665
+ ""
666
+ ].join("\n");
667
+ }
668
+ const lines = [
669
+ "/**",
670
+ " * AUTO-GENERATED - Do not edit manually",
671
+ " * Generated from EntityDefinition via @gzl10/nexus-sdk generators",
672
+ " */",
673
+ "",
674
+ "import type { ModuleContext, Knex } from '@gzl10/nexus-sdk'",
675
+ "",
676
+ "export async function migrate(ctx: ModuleContext): Promise<void> {",
677
+ " const { db, logger, helpers } = ctx",
678
+ " const { addTimestamps, addAuditFieldsIfMissing } = helpers",
679
+ ""
680
+ ];
681
+ for (const entity of persistentEntities) {
682
+ const { table, fields } = entity;
683
+ const timestamps = "timestamps" in entity ? entity.timestamps : false;
684
+ const audit = "audit" in entity ? entity.audit : false;
685
+ const indexes = "indexes" in entity ? entity.indexes : void 0;
686
+ const name = getEntityName(entity);
687
+ lines.push(` // === ${name.toUpperCase()} ===`);
688
+ lines.push(` if (!(await db.schema.hasTable('${table}'))) {`);
689
+ lines.push(` await db.schema.createTable('${table}', (table: Knex.CreateTableBuilder) => {`);
690
+ for (const [fieldName, field] of Object.entries(fields)) {
691
+ const columnCode = generateColumnCodeInline(fieldName, field);
692
+ lines.push(` ${columnCode}`);
693
+ }
694
+ if (timestamps) {
695
+ lines.push(` addTimestamps(table, db)`);
696
+ }
697
+ if (indexes?.length) {
698
+ lines.push("");
699
+ for (const idx of indexes) {
700
+ if (idx.unique) {
701
+ lines.push(` table.unique([${idx.columns.map((c) => `'${c}'`).join(", ")}])`);
702
+ } else {
703
+ lines.push(` table.index([${idx.columns.map((c) => `'${c}'`).join(", ")}])`);
704
+ }
705
+ }
706
+ }
707
+ lines.push(` })`);
708
+ lines.push(` logger.info('Created table: ${table}')`);
709
+ lines.push(` }`);
710
+ if (audit) {
711
+ lines.push(` await addAuditFieldsIfMissing(db, '${table}')`);
712
+ }
713
+ lines.push("");
714
+ }
715
+ lines.push("}");
716
+ lines.push("");
717
+ return lines.join("\n");
718
+ }
719
+ function generateColumnCodeInline(name, field) {
720
+ const { db } = field;
721
+ let code = "";
722
+ switch (db.type) {
723
+ case "string":
724
+ code = db.size ? `table.string('${name}', ${db.size})` : `table.string('${name}')`;
725
+ break;
726
+ case "text":
727
+ code = `table.text('${name}')`;
728
+ break;
729
+ case "integer":
730
+ code = `table.integer('${name}')`;
731
+ break;
732
+ case "decimal":
733
+ if (db.precision) {
734
+ code = `table.decimal('${name}', ${db.precision[0]}, ${db.precision[1]})`;
735
+ } else {
736
+ code = `table.decimal('${name}')`;
737
+ }
738
+ break;
739
+ case "boolean":
740
+ code = `table.boolean('${name}')`;
741
+ break;
742
+ case "date":
743
+ code = `table.date('${name}')`;
744
+ break;
745
+ case "datetime":
746
+ code = `table.datetime('${name}')`;
747
+ break;
748
+ case "json":
749
+ code = `table.json('${name}')`;
750
+ break;
751
+ case "uuid":
752
+ code = `table.uuid('${name}')`;
753
+ break;
754
+ default:
755
+ code = `table.string('${name}')`;
756
+ }
757
+ if (name === "id") {
758
+ code += ".primary()";
759
+ }
760
+ if (!db.nullable) {
761
+ code += ".notNullable()";
762
+ } else {
763
+ code += ".nullable()";
764
+ }
765
+ if (db.unique) {
766
+ code += ".unique()";
767
+ }
768
+ if (db.default !== void 0) {
769
+ if (typeof db.default === "string") {
770
+ code += `.defaultTo('${db.default}')`;
771
+ } else if (typeof db.default === "boolean") {
772
+ code += `.defaultTo(${db.default})`;
773
+ } else {
774
+ code += `.defaultTo(${db.default})`;
775
+ }
776
+ }
777
+ if (db.index) {
778
+ code += ".index()";
779
+ }
780
+ if (field.relation) {
781
+ code += `.references('${field.relation.column ?? "id"}').inTable('${field.relation.table}')`;
782
+ if (field.relation.onDelete) {
783
+ code += `.onDelete('${field.relation.onDelete}')`;
784
+ }
785
+ }
786
+ return code;
787
+ }
651
788
  export {
789
+ GENERATED_DIR,
652
790
  generateCaslPermissions,
653
791
  generateCaslSeed,
654
792
  generateMigration,
793
+ generateMigrationsFile,
655
794
  generateModel,
656
795
  generateModelsFile,
657
796
  generateReadOnlyModel,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gzl10/nexus-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "SDK types for creating Nexus plugins and modules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",