@gzl10/nexus-sdk 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -3
- package/dist/index.d.ts +156 -97
- package/dist/index.js +14 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,17 +98,131 @@ export const projectPlugin: PluginManifest = {
|
|
|
98
98
|
}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
## EntityDefinition (v0.2.0+)
|
|
102
|
+
|
|
103
|
+
Define entities as single source of truth for DB, validation, UI, and CASL:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import type { EntityDefinition } from '@gzl10/nexus-sdk'
|
|
107
|
+
|
|
108
|
+
export const postEntity: EntityDefinition = {
|
|
109
|
+
table: 'cms_posts',
|
|
110
|
+
label: 'Posts',
|
|
111
|
+
labelField: 'title',
|
|
112
|
+
timestamps: true,
|
|
113
|
+
audit: true,
|
|
114
|
+
|
|
115
|
+
fields: {
|
|
116
|
+
id: {
|
|
117
|
+
name: 'id',
|
|
118
|
+
label: 'ID',
|
|
119
|
+
input: 'hidden',
|
|
120
|
+
db: { type: 'uuid', nullable: false, defaultFn: 'uuid' }
|
|
121
|
+
},
|
|
122
|
+
title: {
|
|
123
|
+
name: 'title',
|
|
124
|
+
label: 'Title',
|
|
125
|
+
input: 'text',
|
|
126
|
+
db: { type: 'string', size: 200, nullable: false },
|
|
127
|
+
validation: { required: true, min: 3, max: 200 },
|
|
128
|
+
meta: { searchable: true, sortable: true }
|
|
129
|
+
},
|
|
130
|
+
content: {
|
|
131
|
+
name: 'content',
|
|
132
|
+
label: 'Content',
|
|
133
|
+
input: 'markdown',
|
|
134
|
+
db: { type: 'text', nullable: true }
|
|
135
|
+
},
|
|
136
|
+
status: {
|
|
137
|
+
name: 'status',
|
|
138
|
+
label: 'Status',
|
|
139
|
+
input: 'select',
|
|
140
|
+
db: { type: 'string', nullable: false, default: 'draft' },
|
|
141
|
+
validation: { enum: ['draft', 'published', 'archived'] },
|
|
142
|
+
options: {
|
|
143
|
+
static: [
|
|
144
|
+
{ value: 'draft', label: 'Draft' },
|
|
145
|
+
{ value: 'published', label: 'Published' },
|
|
146
|
+
{ value: 'archived', label: 'Archived' }
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
casl: {
|
|
153
|
+
ownership: { field: 'created_by' },
|
|
154
|
+
permissions: {
|
|
155
|
+
ADMIN: { actions: ['manage'] },
|
|
156
|
+
EDITOR: { actions: ['create', 'read', 'update'] },
|
|
157
|
+
VIEWER: { actions: ['read'] }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Code Generators
|
|
164
|
+
|
|
165
|
+
Generate migrations, Zod schemas, TypeScript models, and CASL permissions:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import {
|
|
169
|
+
generateMigration,
|
|
170
|
+
generateZodSchema,
|
|
171
|
+
generateModel,
|
|
172
|
+
generateCaslPermissions
|
|
173
|
+
} from '@gzl10/nexus-sdk'
|
|
174
|
+
|
|
175
|
+
// Generate Knex migration code
|
|
176
|
+
const migrationCode = generateMigration(postEntity)
|
|
177
|
+
|
|
178
|
+
// Generate Zod validation schemas
|
|
179
|
+
const zodCode = generateZodSchema(postEntity)
|
|
180
|
+
// Creates: createPostSchema, updatePostSchema, postParamsSchema, postQuerySchema
|
|
181
|
+
|
|
182
|
+
// Generate TypeScript interface
|
|
183
|
+
const modelCode = generateModel(postEntity)
|
|
184
|
+
// Creates: export interface Post { ... }
|
|
185
|
+
|
|
186
|
+
// Generate CASL permissions for seeding
|
|
187
|
+
const permissions = generateCaslPermissions(postEntity)
|
|
188
|
+
// Returns: Array<{ role, action, subject, conditions, fields, inverted }>
|
|
189
|
+
```
|
|
190
|
+
|
|
101
191
|
## Main Types
|
|
102
192
|
|
|
103
193
|
### Manifests & Context
|
|
104
194
|
|
|
105
195
|
| Type | Description |
|
|
106
196
|
|------|-------------|
|
|
107
|
-
| `ModuleManifest` | Defines a module: routes, migrations, seeds,
|
|
197
|
+
| `ModuleManifest` | Defines a module: routes, migrations, seeds, entities |
|
|
108
198
|
| `PluginManifest` | Groups modules under a plugin with shared metadata |
|
|
109
199
|
| `ModuleContext` | Context injected by Nexus: `db`, `logger`, `helpers`, `services`, `abilities` |
|
|
110
|
-
|
|
111
|
-
|
|
200
|
+
|
|
201
|
+
### Entity Definition System
|
|
202
|
+
|
|
203
|
+
| Type | Description |
|
|
204
|
+
|------|-------------|
|
|
205
|
+
| `EntityDefinition` | Complete entity definition (DB, UI, validation, CASL) |
|
|
206
|
+
| `FieldDefinition` | Field configuration with DB, UI, and validation settings |
|
|
207
|
+
| `FieldDbConfig` | Database column configuration |
|
|
208
|
+
| `FieldRelation` | Foreign key configuration |
|
|
209
|
+
| `EntityCaslConfig` | CASL authorization configuration |
|
|
210
|
+
|
|
211
|
+
### Entity Types (Discriminated Union)
|
|
212
|
+
|
|
213
|
+
| Type | Description |
|
|
214
|
+
|------|-------------|
|
|
215
|
+
| `CollectionEntity` | Full CRUD (users, posts) |
|
|
216
|
+
| `ReferenceEntity` | Catalogs with admin CRUD (countries) |
|
|
217
|
+
| `SingleEntity` | Singleton, update/read only (site_config) |
|
|
218
|
+
| `ConfigEntity` | Per-module config, singleton |
|
|
219
|
+
| `ExternalEntity` | Read-only from external systems |
|
|
220
|
+
| `VirtualEntity` | Orchestration of multiple sources |
|
|
221
|
+
| `ComputedEntity` | KPIs, calculated stats |
|
|
222
|
+
| `ViewEntity` | Optimized read projections |
|
|
223
|
+
| `EventEntity` | Audit logs, append-only |
|
|
224
|
+
| `TempEntity` | TTL-based (cache, sessions) |
|
|
225
|
+
| `ActionEntity` | Commands without persistence |
|
|
112
226
|
|
|
113
227
|
### Request & Auth
|
|
114
228
|
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ import { Logger } from 'pino';
|
|
|
11
11
|
* que pueden ser escritos a archivos o usados en runtime.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Entidades que persisten en BD local
|
|
16
|
+
* Excluye: action, external, virtual, computed
|
|
17
|
+
*/
|
|
18
|
+
type PersistentEntityDefinition = CollectionEntityDefinition | SingleEntityDefinition | ReferenceEntityDefinition | EventEntityDefinition | ConfigEntityDefinition | TempEntityDefinition | ViewEntityDefinition;
|
|
14
19
|
/**
|
|
15
20
|
* Genera código de migración Knex desde EntityDefinition
|
|
16
21
|
*
|
|
@@ -24,7 +29,7 @@ import { Logger } from 'pino';
|
|
|
24
29
|
* // ...
|
|
25
30
|
* // }
|
|
26
31
|
*/
|
|
27
|
-
declare function generateMigration(entity:
|
|
32
|
+
declare function generateMigration(entity: PersistentEntityDefinition): string;
|
|
28
33
|
/**
|
|
29
34
|
* Genera código de schemas Zod desde EntityDefinition
|
|
30
35
|
*
|
|
@@ -32,7 +37,7 @@ declare function generateMigration(entity: EntityDefinition): string;
|
|
|
32
37
|
* const code = generateZodSchema(postEntity)
|
|
33
38
|
* // Genera createPostSchema, updatePostSchema, postParamsSchema, postQuerySchema
|
|
34
39
|
*/
|
|
35
|
-
declare function generateZodSchema(entity:
|
|
40
|
+
declare function generateZodSchema(entity: PersistentEntityDefinition): string;
|
|
36
41
|
/**
|
|
37
42
|
* Genera interface TypeScript desde EntityDefinition
|
|
38
43
|
*
|
|
@@ -45,7 +50,7 @@ declare function generateZodSchema(entity: EntityDefinition): string;
|
|
|
45
50
|
* // ...
|
|
46
51
|
* // }
|
|
47
52
|
*/
|
|
48
|
-
declare function generateModel(entity:
|
|
53
|
+
declare function generateModel(entity: PersistentEntityDefinition): string;
|
|
49
54
|
/**
|
|
50
55
|
* Estructura de permiso generado para insertar en BD
|
|
51
56
|
*/
|
|
@@ -64,7 +69,7 @@ interface GeneratedPermission {
|
|
|
64
69
|
* const permissions = generateCaslPermissions(postEntity)
|
|
65
70
|
* // Genera array de permisos para insertar en rol_role_permissions
|
|
66
71
|
*/
|
|
67
|
-
declare function generateCaslPermissions(entity:
|
|
72
|
+
declare function generateCaslPermissions(entity: PersistentEntityDefinition): GeneratedPermission[];
|
|
68
73
|
/**
|
|
69
74
|
* Genera código de seed para permisos CASL
|
|
70
75
|
*
|
|
@@ -76,7 +81,7 @@ declare function generateCaslSeed(entities: EntityDefinition[]): string;
|
|
|
76
81
|
/**
|
|
77
82
|
* Obtiene el subject CASL de una entidad
|
|
78
83
|
*/
|
|
79
|
-
declare function getEntitySubject(entity:
|
|
84
|
+
declare function getEntitySubject(entity: PersistentEntityDefinition): string;
|
|
80
85
|
|
|
81
86
|
/**
|
|
82
87
|
* @gzl10/nexus-sdk
|
|
@@ -85,6 +90,23 @@ declare function getEntitySubject(entity: EntityDefinition): string;
|
|
|
85
90
|
* Use this package to define plugin/module manifests without
|
|
86
91
|
* depending on the full @gzl10/nexus-backend package.
|
|
87
92
|
*/
|
|
93
|
+
/**
|
|
94
|
+
* Unión discriminada de todos los tipos de entidad
|
|
95
|
+
*
|
|
96
|
+
* | Type | Persistencia | CRUD | Uso principal |
|
|
97
|
+
* |------------|--------------|-----------------|----------------------------------|
|
|
98
|
+
* | collection | Sí (BD) | Completo | Datos de negocio (users, posts) |
|
|
99
|
+
* | single | Sí (BD) | Update/Read | Config global (site_config) |
|
|
100
|
+
* | external | No | Read | Datos externos (stripe_customers)|
|
|
101
|
+
* | virtual | No | Read | Orquestación (unified_customers) |
|
|
102
|
+
* | computed | No/opcional | Read | KPIs, estadísticas |
|
|
103
|
+
* | view | Sí/virtual | Read | Lectura optimizada (projections) |
|
|
104
|
+
* | reference | Sí | Read (admin) | Catálogos (countries, currencies)|
|
|
105
|
+
* | config | Sí | Update/Read | Config por módulo |
|
|
106
|
+
* | event | Sí | Append | Auditoría (audit_logs) |
|
|
107
|
+
* | temp | No (TTL) | Read/Write | Cache, sesiones (otp_codes) |
|
|
108
|
+
* | action | No | Execute | Operaciones, workflows |
|
|
109
|
+
*/
|
|
88
110
|
|
|
89
111
|
type KnexCreateTableBuilder = Knex.CreateTableBuilder;
|
|
90
112
|
type KnexAlterTableBuilder = Knex.AlterTableBuilder;
|
|
@@ -320,134 +342,178 @@ interface EntityCaslConfig {
|
|
|
320
342
|
sensitiveFields?: string[];
|
|
321
343
|
}
|
|
322
344
|
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
* Contiene toda la información necesaria para:
|
|
326
|
-
* - Generar migraciones Knex
|
|
327
|
-
* - Generar schemas Zod
|
|
328
|
-
* - Generar tipos TypeScript
|
|
329
|
-
* - Configurar UI CRUD
|
|
330
|
-
* - Configurar permisos CASL
|
|
345
|
+
* Propiedades base compartidas por todas las EntityDefinition
|
|
331
346
|
*/
|
|
332
|
-
interface
|
|
347
|
+
interface BaseEntityDefinition {
|
|
348
|
+
/** Nombre de tabla en BD (con prefijo: 'cms_posts') */
|
|
333
349
|
table: string;
|
|
350
|
+
/** Nombre para mostrar en UI */
|
|
334
351
|
label: string;
|
|
335
|
-
|
|
352
|
+
/** Definición de campos */
|
|
336
353
|
fields: Record<string, FieldDefinition>;
|
|
337
|
-
|
|
338
|
-
audit?: boolean;
|
|
339
|
-
indexes?: EntityIndex[];
|
|
354
|
+
/** Autorización CASL */
|
|
340
355
|
casl?: EntityCaslConfig;
|
|
341
356
|
}
|
|
342
|
-
/**
|
|
343
|
-
* Propiedades base compartidas por todas las entidades
|
|
344
|
-
*/
|
|
345
|
-
interface BaseEntity {
|
|
346
|
-
name: string;
|
|
347
|
-
label: string;
|
|
348
|
-
}
|
|
349
357
|
/**
|
|
350
358
|
* Entidad de colección - CRUD completo (users, posts, orders)
|
|
351
359
|
* Default cuando no se especifica type
|
|
352
360
|
*/
|
|
353
|
-
interface
|
|
361
|
+
interface CollectionEntityDefinition extends BaseEntityDefinition {
|
|
354
362
|
type?: 'collection';
|
|
355
|
-
|
|
356
|
-
formFields?: Record<string, FormField>;
|
|
363
|
+
/** Campo para mostrar en selects/referencias */
|
|
357
364
|
labelField: string;
|
|
358
|
-
|
|
359
|
-
|
|
365
|
+
/** Añadir created_at, updated_at */
|
|
366
|
+
timestamps?: boolean;
|
|
367
|
+
/** Añadir created_by, updated_by */
|
|
368
|
+
audit?: boolean;
|
|
369
|
+
/** Índices compuestos */
|
|
370
|
+
indexes?: EntityIndex[];
|
|
360
371
|
}
|
|
361
372
|
/**
|
|
362
|
-
* Entidad
|
|
373
|
+
* Entidad singleton - Solo Update/Read, sin lista (site_config)
|
|
363
374
|
*/
|
|
364
|
-
interface
|
|
365
|
-
type: '
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
listType?: ListType;
|
|
375
|
+
interface SingleEntityDefinition extends BaseEntityDefinition {
|
|
376
|
+
type: 'single';
|
|
377
|
+
/** Añadir updated_at */
|
|
378
|
+
timestamps?: boolean;
|
|
379
|
+
/** Añadir updated_by */
|
|
380
|
+
audit?: boolean;
|
|
371
381
|
}
|
|
372
382
|
/**
|
|
373
|
-
* Entidad
|
|
383
|
+
* Entidad de referencia - Catálogos con CRUD admin (countries, currencies)
|
|
374
384
|
*/
|
|
375
|
-
interface
|
|
376
|
-
type: '
|
|
377
|
-
|
|
378
|
-
formFields?: Record<string, FormField>;
|
|
385
|
+
interface ReferenceEntityDefinition extends BaseEntityDefinition {
|
|
386
|
+
type: 'reference';
|
|
387
|
+
/** Campo para mostrar en selects/referencias */
|
|
379
388
|
labelField: string;
|
|
380
|
-
|
|
381
|
-
|
|
389
|
+
/** Añadir created_at, updated_at */
|
|
390
|
+
timestamps?: boolean;
|
|
391
|
+
/** Índices compuestos */
|
|
392
|
+
indexes?: EntityIndex[];
|
|
382
393
|
}
|
|
383
394
|
/**
|
|
384
|
-
* Entidad
|
|
395
|
+
* Entidad de eventos - Logs de auditoría, append-only
|
|
385
396
|
*/
|
|
386
|
-
interface
|
|
387
|
-
type: '
|
|
388
|
-
|
|
397
|
+
interface EventEntityDefinition extends BaseEntityDefinition {
|
|
398
|
+
type: 'event';
|
|
399
|
+
/** Campo para mostrar en listas */
|
|
400
|
+
labelField: string;
|
|
401
|
+
/** Siempre true para eventos */
|
|
402
|
+
timestamps: true;
|
|
389
403
|
}
|
|
390
404
|
/**
|
|
391
|
-
* Entidad de
|
|
405
|
+
* Entidad de acción - Comandos/operaciones sin persistencia
|
|
392
406
|
*/
|
|
393
|
-
interface
|
|
394
|
-
type: '
|
|
395
|
-
|
|
407
|
+
interface ActionEntityDefinition {
|
|
408
|
+
type: 'action';
|
|
409
|
+
/** Nombre para mostrar en UI */
|
|
410
|
+
label: string;
|
|
411
|
+
/** Solo campos de formulario, sin BD */
|
|
412
|
+
fields: Record<string, FieldDefinition>;
|
|
396
413
|
}
|
|
397
414
|
/**
|
|
398
|
-
* Entidad externa -
|
|
415
|
+
* Entidad externa - Datos de APIs externas (stripe_customers, github_repos)
|
|
416
|
+
* Read-only, sin persistencia local
|
|
399
417
|
*/
|
|
400
|
-
interface
|
|
418
|
+
interface ExternalEntityDefinition {
|
|
401
419
|
type: 'external';
|
|
402
|
-
|
|
420
|
+
/** Nombre para mostrar en UI */
|
|
421
|
+
label: string;
|
|
422
|
+
/** Campo para mostrar en selects/referencias */
|
|
403
423
|
labelField: string;
|
|
404
|
-
|
|
424
|
+
/** Definición de campos (estructura esperada del API externo) */
|
|
425
|
+
fields: Record<string, FieldDefinition>;
|
|
426
|
+
/** Configuración del origen externo */
|
|
427
|
+
source: {
|
|
428
|
+
/** Tipo de origen */
|
|
429
|
+
provider: string;
|
|
430
|
+
/** Endpoint o recurso */
|
|
431
|
+
endpoint?: string;
|
|
432
|
+
};
|
|
433
|
+
/** Autorización CASL */
|
|
434
|
+
casl?: EntityCaslConfig;
|
|
405
435
|
}
|
|
406
436
|
/**
|
|
407
437
|
* Entidad virtual - Orquestación de múltiples fuentes (unified_customers)
|
|
438
|
+
* Read-only, combina datos de varias entidades
|
|
408
439
|
*/
|
|
409
|
-
interface
|
|
440
|
+
interface VirtualEntityDefinition {
|
|
410
441
|
type: 'virtual';
|
|
411
|
-
|
|
442
|
+
/** Nombre para mostrar en UI */
|
|
443
|
+
label: string;
|
|
444
|
+
/** Campo para mostrar en selects/referencias */
|
|
412
445
|
labelField: string;
|
|
413
|
-
|
|
446
|
+
/** Definición de campos (esquema unificado) */
|
|
447
|
+
fields: Record<string, FieldDefinition>;
|
|
448
|
+
/** Fuentes de datos que se combinan */
|
|
449
|
+
sources: string[];
|
|
450
|
+
/** Autorización CASL */
|
|
451
|
+
casl?: EntityCaslConfig;
|
|
414
452
|
}
|
|
415
453
|
/**
|
|
416
|
-
* Entidad
|
|
454
|
+
* Entidad computed - KPIs, estadísticas, métricas calculadas
|
|
455
|
+
* Read-only, puede cachear opcionalmente
|
|
417
456
|
*/
|
|
418
|
-
interface
|
|
457
|
+
interface ComputedEntityDefinition {
|
|
419
458
|
type: 'computed';
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
459
|
+
/** Nombre para mostrar en UI */
|
|
460
|
+
label: string;
|
|
461
|
+
/** Campo para mostrar en selects/referencias */
|
|
462
|
+
labelField?: string;
|
|
463
|
+
/** Definición de campos (estructura del resultado) */
|
|
464
|
+
fields: Record<string, FieldDefinition>;
|
|
465
|
+
/** Tiempo de cache en segundos (0 = sin cache) */
|
|
466
|
+
cacheTtl?: number;
|
|
467
|
+
/** Autorización CASL */
|
|
468
|
+
casl?: EntityCaslConfig;
|
|
423
469
|
}
|
|
424
470
|
/**
|
|
425
|
-
* Entidad
|
|
471
|
+
* Entidad view - Vista optimizada para lectura (projections, denormalizaciones)
|
|
472
|
+
* Read-only, puede ser vista de BD o virtual
|
|
426
473
|
*/
|
|
427
|
-
interface
|
|
474
|
+
interface ViewEntityDefinition {
|
|
428
475
|
type: 'view';
|
|
429
|
-
|
|
476
|
+
/** Tabla o vista en BD (puede ser VIEW SQL) */
|
|
477
|
+
table: string;
|
|
478
|
+
/** Nombre para mostrar en UI */
|
|
479
|
+
label: string;
|
|
480
|
+
/** Campo para mostrar en selects/referencias */
|
|
430
481
|
labelField: string;
|
|
431
|
-
|
|
482
|
+
/** Definición de campos */
|
|
483
|
+
fields: Record<string, FieldDefinition>;
|
|
484
|
+
/** Entidad fuente de la que deriva */
|
|
485
|
+
sourceEntity?: string;
|
|
486
|
+
/** Autorización CASL */
|
|
487
|
+
casl?: EntityCaslConfig;
|
|
432
488
|
}
|
|
433
489
|
/**
|
|
434
|
-
* Entidad
|
|
490
|
+
* Entidad config - Configuración por módulo/tenant
|
|
491
|
+
* Similar a single pero con scope
|
|
435
492
|
*/
|
|
436
|
-
interface
|
|
437
|
-
type: '
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
493
|
+
interface ConfigEntityDefinition extends BaseEntityDefinition {
|
|
494
|
+
type: 'config';
|
|
495
|
+
/** Scope de la configuración */
|
|
496
|
+
scope?: 'global' | 'module' | 'tenant' | 'user';
|
|
497
|
+
/** Añadir updated_at */
|
|
498
|
+
timestamps?: boolean;
|
|
499
|
+
/** Añadir updated_by */
|
|
500
|
+
audit?: boolean;
|
|
441
501
|
}
|
|
442
502
|
/**
|
|
443
|
-
* Entidad
|
|
503
|
+
* Entidad temporal - Cache, sesiones, OTP codes
|
|
504
|
+
* Con TTL automático, sin auditoría
|
|
444
505
|
*/
|
|
445
|
-
interface
|
|
446
|
-
type: '
|
|
447
|
-
|
|
506
|
+
interface TempEntityDefinition extends BaseEntityDefinition {
|
|
507
|
+
type: 'temp';
|
|
508
|
+
/** Tiempo de vida en segundos */
|
|
509
|
+
ttl: number;
|
|
510
|
+
/** Campo para mostrar en listas (opcional) */
|
|
511
|
+
labelField?: string;
|
|
512
|
+
/** Índices para búsqueda rápida */
|
|
513
|
+
indexes?: EntityIndex[];
|
|
448
514
|
}
|
|
449
515
|
/**
|
|
450
|
-
*
|
|
516
|
+
* Union de todas las definiciones de entidad
|
|
451
517
|
*
|
|
452
518
|
* | Type | Persistencia | CRUD | Uso principal |
|
|
453
519
|
* |------------|--------------|-----------------|----------------------------------|
|
|
@@ -463,11 +529,7 @@ interface ActionEntity extends BaseEntity {
|
|
|
463
529
|
* | temp | No (TTL) | Read/Write | Cache, sesiones (otp_codes) |
|
|
464
530
|
* | action | No | Execute | Operaciones, workflows |
|
|
465
531
|
*/
|
|
466
|
-
type
|
|
467
|
-
/**
|
|
468
|
-
* Helper type para extraer el tipo de entidad
|
|
469
|
-
*/
|
|
470
|
-
type EntityType = ModuleEntity['type'];
|
|
532
|
+
type EntityDefinition = CollectionEntityDefinition | SingleEntityDefinition | ExternalEntityDefinition | VirtualEntityDefinition | ComputedEntityDefinition | ViewEntityDefinition | ReferenceEntityDefinition | ConfigEntityDefinition | EventEntityDefinition | TempEntityDefinition | ActionEntityDefinition;
|
|
471
533
|
/**
|
|
472
534
|
* Requisitos para activar un módulo
|
|
473
535
|
*/
|
|
@@ -500,6 +562,10 @@ interface ForbiddenErrorConstructor {
|
|
|
500
562
|
* Permite usar CASL en plugins sin importar @casl/ability directamente
|
|
501
563
|
*/
|
|
502
564
|
interface ModuleAbilities {
|
|
565
|
+
/** Crea una ability CASL para un usuario (acepta argumentos adicionales como permissions) */
|
|
566
|
+
defineAbilityFor: (user: any, ...args: any[]) => any;
|
|
567
|
+
/** Empaqueta reglas CASL para enviar al cliente (recibe ability, retorna reglas) */
|
|
568
|
+
packRules: (ability: any) => unknown[];
|
|
503
569
|
/** Wrapper para verificar permisos contra instancias */
|
|
504
570
|
subject: (type: string, object: Record<string, any>) => unknown;
|
|
505
571
|
/** Error de CASL para throwUnlessCan */
|
|
@@ -567,8 +633,8 @@ interface ModuleContext {
|
|
|
567
633
|
createRouter: () => Router;
|
|
568
634
|
middleware: ModuleMiddlewares;
|
|
569
635
|
registerMiddleware: (name: string, handler: RequestHandler) => void;
|
|
570
|
-
/** Configuración resuelta de la aplicación */
|
|
571
|
-
config:
|
|
636
|
+
/** Configuración resuelta de la aplicación (permite propiedades tipadas del backend) */
|
|
637
|
+
config: any;
|
|
572
638
|
errors: {
|
|
573
639
|
AppError: new (message: string, statusCode?: number) => Error;
|
|
574
640
|
NotFoundError: new (message?: string) => Error;
|
|
@@ -577,10 +643,8 @@ interface ModuleContext {
|
|
|
577
643
|
ConflictError: new (message?: string) => Error;
|
|
578
644
|
};
|
|
579
645
|
abilities: ModuleAbilities;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
on: (event: string, listener: (...args: unknown[]) => void) => unknown;
|
|
583
|
-
};
|
|
646
|
+
/** Sistema de eventos (EventEmitter2 compatible, permite implementaciones tipadas) */
|
|
647
|
+
events: any;
|
|
584
648
|
mail: {
|
|
585
649
|
send: (options: {
|
|
586
650
|
to: string | string[];
|
|
@@ -632,11 +696,6 @@ interface ModuleManifest {
|
|
|
632
696
|
* Sus subjects se registran automáticamente.
|
|
633
697
|
*/
|
|
634
698
|
definitions?: EntityDefinition[];
|
|
635
|
-
/**
|
|
636
|
-
* @deprecated Usar `definitions` en su lugar.
|
|
637
|
-
* Entidades/tablas del módulo con config CRUD para UI.
|
|
638
|
-
*/
|
|
639
|
-
entities?: ModuleEntity[];
|
|
640
699
|
}
|
|
641
700
|
/**
|
|
642
701
|
* Categorías disponibles para plugins
|
|
@@ -664,4 +723,4 @@ interface PluginManifest {
|
|
|
664
723
|
modules: ModuleManifest[];
|
|
665
724
|
}
|
|
666
725
|
|
|
667
|
-
export { type AbilityLike, type
|
|
726
|
+
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 OwnershipCondition, type PaginatedResult, type PaginationParams, 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, generateZodSchema, getEntitySubject };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
// src/generators.ts
|
|
2
|
+
function isPersistentEntity(entity) {
|
|
3
|
+
const nonPersistent = ["action", "external", "virtual", "computed"];
|
|
4
|
+
return !nonPersistent.includes(entity.type ?? "collection");
|
|
5
|
+
}
|
|
2
6
|
function generateMigration(entity) {
|
|
3
|
-
const { table, fields
|
|
7
|
+
const { table, fields } = entity;
|
|
8
|
+
const timestamps = "timestamps" in entity ? entity.timestamps : false;
|
|
9
|
+
const audit = "audit" in entity ? entity.audit : false;
|
|
10
|
+
const indexes = "indexes" in entity ? entity.indexes : void 0;
|
|
4
11
|
const lines = [
|
|
5
12
|
`import type { ModuleContext, Knex } from '@gzl10/nexus-sdk'`,
|
|
6
13
|
``,
|
|
@@ -236,7 +243,9 @@ function dbTypeToZodType(dbType) {
|
|
|
236
243
|
}
|
|
237
244
|
}
|
|
238
245
|
function generateModel(entity) {
|
|
239
|
-
const { table, fields
|
|
246
|
+
const { table, fields } = entity;
|
|
247
|
+
const timestamps = "timestamps" in entity ? entity.timestamps : false;
|
|
248
|
+
const audit = "audit" in entity ? entity.audit : false;
|
|
240
249
|
const entityName = tableToEntityName(table);
|
|
241
250
|
const lines = [
|
|
242
251
|
`/**`,
|
|
@@ -365,7 +374,9 @@ function generateCaslPermissions(entity) {
|
|
|
365
374
|
function generateCaslSeed(entities) {
|
|
366
375
|
const allPermissions = [];
|
|
367
376
|
for (const entity of entities) {
|
|
368
|
-
|
|
377
|
+
if (isPersistentEntity(entity)) {
|
|
378
|
+
allPermissions.push(...generateCaslPermissions(entity));
|
|
379
|
+
}
|
|
369
380
|
}
|
|
370
381
|
if (allPermissions.length === 0) {
|
|
371
382
|
return "// No CASL permissions defined in entities\n";
|