@flusys/nestjs-core 1.1.0 → 1.2.0-rc.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/README.md +113 -581
- package/cjs/config/env-config.service.js +13 -9
- package/cjs/docs/docs.config.js +25 -15
- package/cjs/index.js +0 -1
- package/config/env-config.service.d.ts +3 -1
- package/docs/docs.config.d.ts +1 -0
- package/fesm/config/env-config.service.js +13 -9
- package/fesm/docs/docs.config.js +27 -21
- package/fesm/index.js +0 -2
- package/index.d.ts +0 -1
- package/interfaces/base-entity.interface.d.ts +0 -3
- package/interfaces/database.interface.d.ts +1 -1
- package/package.json +8 -8
- package/cjs/seeders/base-seeder.js +0 -76
- package/cjs/seeders/cli.js +0 -291
- package/cjs/seeders/data-generator.js +0 -215
- package/cjs/seeders/entity-reader.js +0 -151
- package/cjs/seeders/field-patterns.js +0 -176
- package/cjs/seeders/index.js +0 -85
- package/cjs/seeders/seed-config.js +0 -62
- package/cjs/seeders/seed-runner.js +0 -314
- package/fesm/seeders/base-seeder.js +0 -66
- package/fesm/seeders/cli.js +0 -249
- package/fesm/seeders/data-generator.js +0 -210
- package/fesm/seeders/entity-reader.js +0 -153
- package/fesm/seeders/field-patterns.js +0 -147
- package/fesm/seeders/index.js +0 -7
- package/fesm/seeders/seed-config.js +0 -35
- package/fesm/seeders/seed-runner.js +0 -317
- package/seeders/base-seeder.d.ts +0 -14
- package/seeders/cli.d.ts +0 -3
- package/seeders/data-generator.d.ts +0 -15
- package/seeders/entity-reader.d.ts +0 -44
- package/seeders/field-patterns.d.ts +0 -12
- package/seeders/index.d.ts +0 -7
- package/seeders/seed-config.d.ts +0 -12
- package/seeders/seed-runner.d.ts +0 -48
package/README.md
CHANGED
|
@@ -1,639 +1,171 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @flusys/nestjs-core
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> **Version:** 1.1.0
|
|
5
|
-
> **Type:** Pure TypeScript foundation (zero NestJS dependencies)
|
|
3
|
+
Foundation infrastructure for NestJS applications — environment config, TypeORM migrations, and Swagger setup.
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## Table of Contents
|
|
10
|
-
|
|
11
|
-
- [Package Architecture](#package-architecture)
|
|
12
|
-
- [Environment Configuration](#environment-configuration)
|
|
13
|
-
- [Database Interfaces](#database-interfaces)
|
|
14
|
-
- [Migration System](#migration-system)
|
|
15
|
-
- [Seed System](#seed-system)
|
|
16
|
-
- [Field Pattern Detection](#field-pattern-detection)
|
|
17
|
-
- [Swagger Documentation](#swagger-documentation)
|
|
18
|
-
- [API Reference](#api-reference)
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Package Architecture
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
nestjs-core/src/
|
|
26
|
-
├── config/
|
|
27
|
-
│ └── env-config.service.ts # Environment configuration singleton
|
|
28
|
-
├── constants/
|
|
29
|
-
│ └── database.constants.ts # MODULE_OPTIONS, DEFAULT_TENANT_HEADER
|
|
30
|
-
├── interfaces/
|
|
31
|
-
│ ├── app-config.interfaces.ts # IBootstrapAppConfig, IDynamicModuleConfig
|
|
32
|
-
│ ├── base-entity.interface.ts # IBaseEntity, ISoftDeletable, ITimestampable
|
|
33
|
-
│ ├── database.interface.ts # IDatabaseConfig, ITenantDatabaseConfig
|
|
34
|
-
│ └── migration.interface.ts # IMigrationConfig, IMigrationResult
|
|
35
|
-
├── utils/
|
|
36
|
-
│ └── datasource-config.builder.ts # DataSource utilities
|
|
37
|
-
├── migration/
|
|
38
|
-
│ ├── cli.ts # CLI entry point
|
|
39
|
-
│ ├── migration.cli.ts # Migration CLI commands
|
|
40
|
-
│ ├── datasource.factory.ts # DataSource factory
|
|
41
|
-
│ └── migration.runner.ts # Migration execution
|
|
42
|
-
├── seeders/
|
|
43
|
-
│ ├── cli.ts # Seed CLI entry point
|
|
44
|
-
│ ├── base-seeder.ts # Abstract base seeder class
|
|
45
|
-
│ ├── seed-runner.ts # Seed orchestration
|
|
46
|
-
│ ├── seed-config.ts # Global seed configuration
|
|
47
|
-
│ ├── entity-reader.ts # TypeORM metadata extraction
|
|
48
|
-
│ ├── data-generator.ts # Faker.js data generation
|
|
49
|
-
│ ├── field-patterns.ts # Intelligent field pattern detection
|
|
50
|
-
│ └── template-generator.ts # Seeder template generation
|
|
51
|
-
├── docs/
|
|
52
|
-
│ └── docs.config.ts # Swagger setup utilities
|
|
53
|
-
└── index.ts
|
|
54
|
-
```
|
|
5
|
+
[](https://www.npmjs.com/package/@flusys/nestjs-core)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
55
7
|
|
|
56
8
|
---
|
|
57
9
|
|
|
58
|
-
##
|
|
10
|
+
## Installation
|
|
59
11
|
|
|
60
|
-
```
|
|
61
|
-
|
|
12
|
+
```bash
|
|
13
|
+
npm install @flusys/nestjs-core
|
|
14
|
+
npm install typeorm typeorm-naming-strategies dotenv
|
|
15
|
+
npm install -D ts-node tsconfig-paths
|
|
62
16
|
```
|
|
63
17
|
|
|
64
|
-
### Available Methods
|
|
65
|
-
|
|
66
|
-
| Method | Description |
|
|
67
|
-
|--------|-------------|
|
|
68
|
-
| `tryGetValue(key)` | Get env value (throws for restricted keys) |
|
|
69
|
-
| `getValue(key, throwOnMissing?)` | Raw string access |
|
|
70
|
-
| `getNumber(key, throwOnMissing?)` | Get env value as number |
|
|
71
|
-
| `getBoolean(key, throwOnMissing?)` | Get env value as boolean |
|
|
72
|
-
| `getPort()` | Get PORT (default: 3000) |
|
|
73
|
-
| `isProduction()` | Check if MODE !== 'DEV' |
|
|
74
|
-
| `getFrontendUrl()` | Get FRONTEND_URL |
|
|
75
|
-
| `getOrigins()` | Get ALLOW_ORIGINS as comma-separated array |
|
|
76
|
-
| `getTypeOrmConfig()` | Get database config |
|
|
77
|
-
| `getJwtConfig()` | Get JWT secret + expiration |
|
|
78
|
-
| `getRedisUrl()` | Get Redis connection URL (default: redis://localhost:6379) |
|
|
79
|
-
| `getMailConfig()` | Get mail configuration (MAIL_FROM, MAIL_APP_PASSWORD) |
|
|
80
|
-
| `getTenantId()` | Get TENANT_ID |
|
|
81
|
-
| `useTenantMode()` | Check USE_TENANT_MODE |
|
|
82
|
-
| `getLogConfig()` | Get logging configuration |
|
|
83
|
-
| `getEnv()` | Get all env vars as Record |
|
|
84
|
-
|
|
85
|
-
### Restricted Keys
|
|
86
|
-
|
|
87
|
-
The following keys require using specific methods (prevents misuse):
|
|
88
|
-
|
|
89
|
-
| Key | Use Instead |
|
|
90
|
-
|-----|-------------|
|
|
91
|
-
| `FRONTEND_URL` | `getFrontendUrl()` |
|
|
92
|
-
| `ALLOW_ORIGINS` | `getOrigins()` |
|
|
93
|
-
| `PORT` | `getPort()` |
|
|
94
|
-
| `MODE` | `isProduction()` |
|
|
95
|
-
| `DB_HOST/PORT/USER/PASSWORD` | `getTypeOrmConfig()` |
|
|
96
|
-
|
|
97
18
|
---
|
|
98
19
|
|
|
99
|
-
##
|
|
100
|
-
|
|
101
|
-
### Core Interfaces
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
type DatabaseType = 'mysql' | 'postgres' | 'mariadb' | 'sqlite' | 'mssql';
|
|
105
|
-
type DatabaseMode = 'single' | 'multi-tenant';
|
|
106
|
-
|
|
107
|
-
interface IDatabaseConfig {
|
|
108
|
-
type: DatabaseType;
|
|
109
|
-
host?: string;
|
|
110
|
-
port?: number;
|
|
111
|
-
username?: string;
|
|
112
|
-
password?: string;
|
|
113
|
-
database?: string;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
interface ITenantDatabaseConfig {
|
|
117
|
-
id: string;
|
|
118
|
-
database: string;
|
|
119
|
-
name?: string;
|
|
120
|
-
host?: string;
|
|
121
|
-
port?: number;
|
|
122
|
-
username?: string;
|
|
123
|
-
password?: string;
|
|
124
|
-
enableCompanyFeature?: boolean;
|
|
125
|
-
permissionMode?: 'FULL' | 'RBAC' | 'DIRECT';
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
interface IBootstrapAppConfig {
|
|
129
|
-
databaseMode: 'single' | 'multi-tenant';
|
|
130
|
-
enableCompanyFeature: boolean;
|
|
131
|
-
permissionMode?: 'FULL' | 'RBAC' | 'DIRECT';
|
|
132
|
-
}
|
|
133
|
-
```
|
|
20
|
+
## 1. Environment Config
|
|
134
21
|
|
|
135
|
-
|
|
22
|
+
Access typed environment variables via the `envConfig` singleton — no class instantiation needed.
|
|
136
23
|
|
|
137
24
|
```typescript
|
|
138
|
-
|
|
139
|
-
id: string;
|
|
140
|
-
createdAt: Date;
|
|
141
|
-
updatedAt: Date;
|
|
142
|
-
deletedAt?: Date | null;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
interface ISoftDeletable {
|
|
146
|
-
deletedAt?: Date | null;
|
|
147
|
-
}
|
|
25
|
+
import { envConfig } from '@flusys/nestjs-core';
|
|
148
26
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
serial?: number;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
interface IMetadata {
|
|
159
|
-
metadata?: Record<string, any> | null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
interface ICompanyOwned {
|
|
163
|
-
companyId?: string | null;
|
|
164
|
-
}
|
|
27
|
+
const port = envConfig.getPort(); // number
|
|
28
|
+
const db = envConfig.getTypeOrmConfig(); // { host, port, username, password, database }
|
|
29
|
+
const jwt = envConfig.getJwtConfig(); // { secret, expiration, refreshSecret, ... }
|
|
30
|
+
const origins = envConfig.getOrigins(); // string[]
|
|
31
|
+
const isProd = envConfig.isProduction(); // boolean
|
|
32
|
+
public tryGetValue(key: string, throwOnMissing = false): string // get env value
|
|
165
33
|
```
|
|
166
34
|
|
|
167
35
|
---
|
|
168
36
|
|
|
169
|
-
##
|
|
37
|
+
## 2. Migrations
|
|
170
38
|
|
|
171
|
-
###
|
|
39
|
+
### Create `src/persistence/migration.config.ts`
|
|
172
40
|
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
TENANT_ID=tenant1 npm run migration:run # Specific tenant
|
|
179
|
-
npm run migration:run:all # All tenants
|
|
180
|
-
npm run migration:revert:all # Revert all tenants
|
|
181
|
-
npm run migration:status:all # Status all tenants
|
|
182
|
-
```
|
|
41
|
+
```typescript
|
|
42
|
+
import { createMigrationDataSource, IMigrationConfig } from '@flusys/nestjs-core';
|
|
43
|
+
import { envConfig } from '@flusys/nestjs-core/config';
|
|
44
|
+
import { getAuthEntitiesByConfig } from '@flusys/nestjs-auth';
|
|
45
|
+
import { getIAMEntitiesByConfig } from '@flusys/nestjs-iam';
|
|
183
46
|
|
|
184
|
-
|
|
47
|
+
const bootstrapConfig = {
|
|
48
|
+
databaseMode: 'single' as const,
|
|
49
|
+
enableCompanyFeature: true,
|
|
50
|
+
permissionMode: 'FULL' as const,
|
|
51
|
+
};
|
|
185
52
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
username: 'user',
|
|
195
|
-
password: 'password',
|
|
196
|
-
database: 'app_db',
|
|
197
|
-
},
|
|
198
|
-
bootstrapAppConfig: {
|
|
199
|
-
databaseMode: 'multi-tenant',
|
|
200
|
-
enableCompanyFeature: true,
|
|
201
|
-
},
|
|
202
|
-
tenants: [
|
|
203
|
-
{ id: 'tenant1', database: 'tenant1_db' },
|
|
204
|
-
{ id: 'tenant2', database: 'tenant2_db', host: 'different-server.com' },
|
|
53
|
+
export const migrationConfig: IMigrationConfig = {
|
|
54
|
+
defaultDatabaseConfig: envConfig.getTypeOrmConfig(),
|
|
55
|
+
bootstrapAppConfig: bootstrapConfig,
|
|
56
|
+
migrationsPath: `${__dirname}/migrations`,
|
|
57
|
+
migrationsTableName: 'migrations',
|
|
58
|
+
entities: [
|
|
59
|
+
...getAuthEntitiesByConfig(bootstrapConfig),
|
|
60
|
+
...getIAMEntitiesByConfig(bootstrapConfig),
|
|
205
61
|
],
|
|
206
|
-
migrationsPath: './src/persistence/migrations',
|
|
207
|
-
entities: (tenantConfig) => {
|
|
208
|
-
// Dynamic entity resolution per tenant
|
|
209
|
-
return tenantConfig?.enableCompanyFeature
|
|
210
|
-
? [UserWithCompany, RoleWithCompany]
|
|
211
|
-
: [User, Role];
|
|
212
|
-
},
|
|
213
|
-
migrationsTableName: 'typeorm_migrations',
|
|
214
62
|
};
|
|
215
|
-
```
|
|
216
63
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
generateMigration,
|
|
222
|
-
runMigrations,
|
|
223
|
-
revertMigration,
|
|
224
|
-
migrationStatus,
|
|
225
|
-
runForAllTenants,
|
|
226
|
-
createMigrationDataSource,
|
|
227
|
-
} from '@flusys/nestjs-core/migration';
|
|
228
|
-
|
|
229
|
-
// Generate new migration
|
|
230
|
-
await generateMigration(config, 'CreateUsersTable', tenantId?);
|
|
231
|
-
|
|
232
|
-
// Run pending migrations
|
|
233
|
-
const result: IMigrationResult = await runMigrations(config, tenantId?);
|
|
234
|
-
|
|
235
|
-
// Revert last migration
|
|
236
|
-
const result: IMigrationResult = await revertMigration(config, tenantId?);
|
|
237
|
-
|
|
238
|
-
// Check status
|
|
239
|
-
await migrationStatus(config, tenantId?);
|
|
240
|
-
|
|
241
|
-
// Multi-tenant operations
|
|
242
|
-
const results: IMigrationResult[] = await runForAllTenants(config, 'run');
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## Seed System
|
|
248
|
-
|
|
249
|
-
### CLI Commands
|
|
250
|
-
|
|
251
|
-
```bash
|
|
252
|
-
npm run seed:run # Seed all entities
|
|
253
|
-
npm run seed:run -- --entity=User --count=100 # Specific entity
|
|
254
|
-
npm run seed:run -- --count=50 --clear # Clear before seeding
|
|
255
|
-
npm run seed:clear # Clear all data
|
|
256
|
-
npm run seed:clear -- --hard # Hard delete
|
|
257
|
-
npm run seed:status # Show status
|
|
258
|
-
npm run seed:run:all # Multi-tenant
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
### Seed Configuration
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
import { configureSeedConfig, seedConfig, ISeedConfig } from '@flusys/nestjs-core/seeders';
|
|
265
|
-
|
|
266
|
-
interface ISeedConfig {
|
|
267
|
-
counts: Record<string, number>; // Per-entity counts
|
|
268
|
-
order: string[]; // Preferred seeding order
|
|
269
|
-
skipEntities: string[]; // Entities to skip
|
|
270
|
-
locale: string; // Faker locale
|
|
271
|
-
respectSoftDelete: boolean; // Default clear behavior
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Configure before running seeders
|
|
275
|
-
configureSeedConfig({
|
|
276
|
-
counts: { User: 50, Product: 100, Order: 200 },
|
|
277
|
-
order: ['User', 'Company', 'Product', 'Order'],
|
|
278
|
-
skipEntities: ['migrations', 'typeorm_metadata', 'Migration'],
|
|
279
|
-
locale: 'en',
|
|
280
|
-
respectSoftDelete: true,
|
|
64
|
+
// Required for TypeORM CLI
|
|
65
|
+
export default createMigrationDataSource({
|
|
66
|
+
config: migrationConfig,
|
|
67
|
+
tenantId: process.env.TENANT_ID,
|
|
281
68
|
});
|
|
282
69
|
```
|
|
283
70
|
|
|
284
|
-
###
|
|
285
|
-
|
|
286
|
-
The main orchestrator for seed operations:
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
import { SeedRunner, ISeedOptions, ISeedResult } from '@flusys/nestjs-core/seeders';
|
|
290
|
-
|
|
291
|
-
const runner = new SeedRunner(dataSource, logger?);
|
|
292
|
-
|
|
293
|
-
// Register custom seeders (take precedence over generic)
|
|
294
|
-
runner.registerCustomSeeder('User', new UserSeeder(dataSource));
|
|
295
|
-
|
|
296
|
-
// Run all entities in dependency order
|
|
297
|
-
const results: ISeedResult[] = await runner.runAll({
|
|
298
|
-
count: 50, // Records per entity
|
|
299
|
-
clear: true, // Clear before seeding
|
|
300
|
-
skipIfExists: false, // Skip if data exists
|
|
301
|
-
dryRun: false, // Preview without executing
|
|
302
|
-
continueOnError: true, // Continue on failures
|
|
303
|
-
batchSize: 1000, // Batch size for bulk inserts
|
|
304
|
-
onProgress: (current, total, entity) => { },
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
// Run single entity
|
|
308
|
-
const result: ISeedResult = await runner.runSingle('User', options);
|
|
309
|
-
|
|
310
|
-
// Clear all data (reverse dependency order)
|
|
311
|
-
const results = await runner.clearAll(hard?, continueOnError?);
|
|
312
|
-
|
|
313
|
-
// Get status
|
|
314
|
-
const status = await runner.getStatus();
|
|
315
|
-
// Returns: [{ entity, tableName, count, isEmpty, hasSoftDelete }]
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
### Custom Seeders
|
|
319
|
-
|
|
320
|
-
```typescript
|
|
321
|
-
import { BaseSeeder, DataGenerator } from '@flusys/nestjs-core/seeders';
|
|
71
|
+
### Add scripts to `package.json`
|
|
322
72
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
users.push(this.repository.create({
|
|
335
|
-
email: faker.internet.email(),
|
|
336
|
-
name: faker.person.fullName(),
|
|
337
|
-
password: await bcrypt.hash('password123', 12),
|
|
338
|
-
}));
|
|
339
|
-
}
|
|
340
|
-
return this.repository.save(users);
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"scripts": {
|
|
76
|
+
"migration": "ts-node -r tsconfig-paths/register ./node_modules/@flusys/nestjs-core/migration/cli --config=src/persistence/migration.config.ts",
|
|
77
|
+
"migration:generate": "npm run migration -- generate",
|
|
78
|
+
"migration:run": "npm run migration -- run",
|
|
79
|
+
"migration:revert": "npm run migration -- revert",
|
|
80
|
+
"migration:status": "npm run migration -- status",
|
|
81
|
+
"migration:run:all": "npm run migration -- run:all",
|
|
82
|
+
"migration:revert:all": "npm run migration -- revert:all",
|
|
83
|
+
"migration:status:all": "npm run migration -- status:all"
|
|
341
84
|
}
|
|
342
85
|
}
|
|
343
|
-
|
|
344
|
-
// Register before running
|
|
345
|
-
const runner = new SeedRunner(dataSource);
|
|
346
|
-
runner.registerCustomSeeder('User', new UserSeeder(dataSource));
|
|
347
|
-
await runner.runAll({ count: 50, clear: true });
|
|
348
86
|
```
|
|
349
87
|
|
|
350
|
-
###
|
|
88
|
+
### Run
|
|
351
89
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
// Get all entities
|
|
360
|
-
const entities = reader.getAllEntities();
|
|
361
|
-
|
|
362
|
-
// Get detailed entity info
|
|
363
|
-
const info: IEntityInfo = reader.getEntityInfo('User');
|
|
364
|
-
// Returns: { name, tableName, columns, relations, hasSoftDelete, hasCompany }
|
|
365
|
-
|
|
366
|
-
// Get seeding order (topological sort by FK dependencies)
|
|
367
|
-
const order: string[] = reader.getSeedingOrder(skipEntities?);
|
|
368
|
-
// Independent entities first, then dependents
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
### DataGenerator
|
|
372
|
-
|
|
373
|
-
Generates realistic sample data using Faker.js:
|
|
374
|
-
|
|
375
|
-
```typescript
|
|
376
|
-
import { DataGenerator, IColumnInfo } from '@flusys/nestjs-core/seeders';
|
|
377
|
-
|
|
378
|
-
const generator = new DataGenerator('en');
|
|
379
|
-
|
|
380
|
-
// Generate value for a column
|
|
381
|
-
const value = generator.generateValue(columnInfo);
|
|
90
|
+
```bash
|
|
91
|
+
# Single database
|
|
92
|
+
npm run migration:generate -- --name=CreateUsersTable
|
|
93
|
+
npm run migration:run
|
|
94
|
+
npm run migration:revert
|
|
95
|
+
npm run migration:status
|
|
382
96
|
|
|
383
|
-
|
|
384
|
-
|
|
97
|
+
# Tenant-specific (prefix with TENANT_ID)
|
|
98
|
+
TENANT_ID=tenant-1 npm run migration:generate -- --name=CreateUsersTable
|
|
99
|
+
TENANT_ID=tenant-1 npm run migration:run
|
|
100
|
+
TENANT_ID=tenant-1 npm run migration:revert
|
|
101
|
+
TENANT_ID=tenant-1 npm run migration:status
|
|
385
102
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
103
|
+
# All tenants at once
|
|
104
|
+
npm run migration:run:all
|
|
105
|
+
npm run migration:revert:all
|
|
106
|
+
npm run migration:status:all
|
|
389
107
|
```
|
|
390
108
|
|
|
391
109
|
---
|
|
392
110
|
|
|
393
|
-
##
|
|
394
|
-
|
|
395
|
-
Intelligent field pattern detection for realistic data generation.
|
|
111
|
+
## 3. Swagger
|
|
396
112
|
|
|
397
|
-
|
|
113
|
+
`setupSwaggerDocs` and `setupModuleSwaggerDocs` accept the same `IModuleSwaggerOptions` shape.
|
|
398
114
|
|
|
399
115
|
```typescript
|
|
400
|
-
import {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
type FieldPatternType =
|
|
404
|
-
| 'skip' | 'null' | 'boolean' | 'token'
|
|
405
|
-
| 'firstName' | 'lastName' | 'fullName'
|
|
406
|
-
| 'email' | 'phone'
|
|
407
|
-
| 'address' | 'street' | 'city' | 'state' | 'country' | 'zipCode'
|
|
408
|
-
| 'url' | 'domain' | 'slug'
|
|
409
|
-
| 'description' | 'summary' | 'content' | 'title'
|
|
410
|
-
| 'username' | 'password'
|
|
411
|
-
| 'birthdate' | 'futureDate' | 'recentDateOrNull'
|
|
412
|
-
| 'serial' | 'company'
|
|
413
|
-
| /* ...more */;
|
|
414
|
-
|
|
415
|
-
// Detect pattern for a column
|
|
416
|
-
const pattern = detectFieldPattern(column);
|
|
417
|
-
```
|
|
116
|
+
import { NestFactory } from '@nestjs/core';
|
|
117
|
+
import { setupSwaggerDocs, setupModuleSwaggerDocs } from '@flusys/nestjs-core/docs';
|
|
118
|
+
import { AuthModule } from '@flusys/nestjs-auth';
|
|
418
119
|
|
|
419
|
-
|
|
120
|
+
async function bootstrap() {
|
|
121
|
+
const app = await NestFactory.create(AppModule);
|
|
420
122
|
|
|
421
|
-
|
|
123
|
+
// All available options (one entry showing every field)
|
|
124
|
+
setupModuleSwaggerDocs(app, [
|
|
125
|
+
{
|
|
126
|
+
title: 'Auth API', // required
|
|
127
|
+
description: 'Auth endpoints', // required
|
|
128
|
+
version: '1.0', // optional, default '1.0'
|
|
129
|
+
path: 'api/docs/auth', // required — URL where docs are served
|
|
130
|
+
bearerAuth: true, // adds Authorization header to Swagger UI
|
|
131
|
+
modules: [AuthModule], // scope to specific NestJS modules only
|
|
422
132
|
|
|
423
|
-
|
|
424
|
-
|
|
133
|
+
// Exclude controllers by @ApiTags name
|
|
134
|
+
excludeTags: ['Internal', 'Health'],
|
|
425
135
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
IDENTITY_FIELDS = ['id', 'createdat', 'updatedat', 'deletedat'];
|
|
429
|
-
BOOLEAN_KEYWORDS = ['verified', 'active', 'enabled', 'public', 'readonly', 'valid'];
|
|
430
|
-
```
|
|
136
|
+
// Exclude specific paths (supports * and ** wildcards)
|
|
137
|
+
excludePaths: ['/api/auth/internal/*', '/api/health'],
|
|
431
138
|
|
|
432
|
-
|
|
139
|
+
// Exclude properties from a DTO schema
|
|
140
|
+
excludeSchemaProperties: [
|
|
141
|
+
{ schemaName: 'CreateUserDto', properties: ['passwordHash', 'salt'] },
|
|
142
|
+
],
|
|
433
143
|
|
|
434
|
-
|
|
435
|
-
|
|
144
|
+
// Exclude query parameters from specific endpoints
|
|
145
|
+
excludeQueryParameters: [
|
|
146
|
+
{ pathPattern: '/api/auth/*', method: 'post', parameters: ['debug'] },
|
|
147
|
+
],
|
|
436
148
|
|
|
437
|
-
//
|
|
438
|
-
|
|
439
|
-
|
|
149
|
+
// Exclude named examples from responses
|
|
150
|
+
excludeExamples: [
|
|
151
|
+
{ pathPattern: '/api/auth/login', examples: ['AdminExample'] },
|
|
152
|
+
],
|
|
440
153
|
|
|
441
|
-
//
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
```
|
|
154
|
+
// Add a custom header to every request in Swagger UI
|
|
155
|
+
globalHeaders: [
|
|
156
|
+
{ name: 'x-tenant-id', description: 'Tenant identifier', required: false, example: 'tenant-1' },
|
|
157
|
+
],
|
|
158
|
+
},
|
|
447
159
|
|
|
448
|
-
|
|
160
|
+
// Minimal entry
|
|
161
|
+
{ title: 'IAM API', description: 'Roles and permissions', path: 'api/docs/iam' },
|
|
162
|
+
]);
|
|
449
163
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
### Setup Functions
|
|
453
|
-
|
|
454
|
-
```typescript
|
|
455
|
-
import { setupSwaggerDocs, setupModuleSwaggerDocs, IModuleSwaggerOptions } from '@flusys/nestjs-core/docs';
|
|
456
|
-
|
|
457
|
-
// Variadic API for multiple configs
|
|
458
|
-
setupSwaggerDocs(app, authConfig, adminConfig, iamConfig);
|
|
459
|
-
|
|
460
|
-
// Array API for module docs
|
|
461
|
-
setupModuleSwaggerDocs(app, [
|
|
462
|
-
{ title: 'Auth API', path: 'auth/docs', bearerAuth: true },
|
|
463
|
-
{ title: 'Admin API', path: 'admin/docs', excludeTags: ['public'] },
|
|
464
|
-
]);
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
### Configuration Options
|
|
468
|
-
|
|
469
|
-
```typescript
|
|
470
|
-
interface IModuleSwaggerOptions {
|
|
471
|
-
modules?: Type<unknown>[]; // Include specific modules
|
|
472
|
-
title: string;
|
|
473
|
-
description: string;
|
|
474
|
-
version?: string; // Default: '1.0'
|
|
475
|
-
path: string; // Swagger UI path
|
|
476
|
-
bearerAuth?: boolean; // Add JWT auth
|
|
477
|
-
globalHeaders?: ISwaggerGlobalHeader[];
|
|
478
|
-
excludeTags?: string[]; // Hide endpoints by tag
|
|
479
|
-
excludeSchemaProperties?: ISchemaPropertyExclusion[];
|
|
480
|
-
excludeQueryParameters?: IQueryParameterExclusion[];
|
|
481
|
-
excludeExamples?: IExampleExclusion[];
|
|
164
|
+
await app.listen(3000);
|
|
482
165
|
}
|
|
483
|
-
|
|
484
|
-
interface ISchemaPropertyExclusion {
|
|
485
|
-
schemaName: string;
|
|
486
|
-
properties: string[];
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
interface IQueryParameterExclusion {
|
|
490
|
-
pathPattern: string; // Supports wildcards: /iam/permissions/*
|
|
491
|
-
method?: string; // Optional: 'post', 'get', etc.
|
|
492
|
-
parameters: string[];
|
|
493
|
-
}
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
### Conditional Schema Exclusion
|
|
497
|
-
|
|
498
|
-
```typescript
|
|
499
|
-
setupModuleSwaggerDocs(app, [{
|
|
500
|
-
title: 'Auth API',
|
|
501
|
-
path: 'auth/docs',
|
|
502
|
-
bearerAuth: true,
|
|
503
|
-
excludeSchemaProperties: enableCompanyFeature ? undefined : [
|
|
504
|
-
{ schemaName: 'LoginResponseDto', properties: ['company', 'branch'] },
|
|
505
|
-
{ schemaName: 'UserDto', properties: ['companyId'] },
|
|
506
|
-
],
|
|
507
|
-
excludeTags: enableCompanyFeature ? undefined : ['Companies', 'Branches'],
|
|
508
|
-
}]);
|
|
509
166
|
```
|
|
510
167
|
|
|
511
|
-
---
|
|
512
|
-
|
|
513
|
-
## API Reference
|
|
514
|
-
|
|
515
|
-
### Interfaces
|
|
516
|
-
|
|
517
|
-
```typescript
|
|
518
|
-
import {
|
|
519
|
-
IDatabaseConfig,
|
|
520
|
-
ITenantDatabaseConfig,
|
|
521
|
-
IBootstrapAppConfig,
|
|
522
|
-
IDynamicModuleConfig,
|
|
523
|
-
IDataSourceServiceOptions,
|
|
524
|
-
IModuleOptionsFactory,
|
|
525
|
-
IAsyncModuleOptions,
|
|
526
|
-
IMigrationConfig,
|
|
527
|
-
IMigrationResult,
|
|
528
|
-
IBaseEntity,
|
|
529
|
-
ISoftDeletable,
|
|
530
|
-
ITimestampable,
|
|
531
|
-
IOrderable,
|
|
532
|
-
ICompanyOwned,
|
|
533
|
-
IMetadata,
|
|
534
|
-
} from '@flusys/nestjs-core';
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
### Constants
|
|
538
|
-
|
|
539
|
-
```typescript
|
|
540
|
-
import { MODULE_OPTIONS, DEFAULT_TENANT_HEADER } from '@flusys/nestjs-core';
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### Config
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
import { envConfig } from '@flusys/nestjs-core/config';
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
### Utils
|
|
550
|
-
|
|
551
|
-
```typescript
|
|
552
|
-
import {
|
|
553
|
-
buildDataSourceOptions,
|
|
554
|
-
getDatabaseForTenant,
|
|
555
|
-
resolveEntities,
|
|
556
|
-
getActiveTenants,
|
|
557
|
-
getMigrationsFolderPath,
|
|
558
|
-
getMigrationsGlobPattern,
|
|
559
|
-
} from '@flusys/nestjs-core/utils';
|
|
560
|
-
```
|
|
561
168
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
```typescript
|
|
565
|
-
import {
|
|
566
|
-
createMigrationDataSource,
|
|
567
|
-
initializeDataSource,
|
|
568
|
-
runMigrationCli,
|
|
569
|
-
generateMigration,
|
|
570
|
-
runMigrations,
|
|
571
|
-
revertMigration,
|
|
572
|
-
migrationStatus,
|
|
573
|
-
runForAllTenants,
|
|
574
|
-
ensureMigrationsFolder,
|
|
575
|
-
} from '@flusys/nestjs-core/migration';
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
### Seeders
|
|
579
|
-
|
|
580
|
-
```typescript
|
|
581
|
-
import {
|
|
582
|
-
// Classes
|
|
583
|
-
BaseSeeder,
|
|
584
|
-
SeedRunner,
|
|
585
|
-
EntityReader,
|
|
586
|
-
DataGenerator,
|
|
587
|
-
// Interfaces
|
|
588
|
-
ISeedResult,
|
|
589
|
-
ISeedOptions,
|
|
590
|
-
ISeederLogger,
|
|
591
|
-
IEntityInfo,
|
|
592
|
-
IColumnInfo,
|
|
593
|
-
IRelationInfo,
|
|
594
|
-
ISeedConfig,
|
|
595
|
-
// Functions
|
|
596
|
-
defaultLogger,
|
|
597
|
-
seedConfig,
|
|
598
|
-
configureSeedConfig,
|
|
599
|
-
runSeedCli,
|
|
600
|
-
getEntityCount,
|
|
601
|
-
shouldSkipEntity,
|
|
602
|
-
getSeedingOrder,
|
|
603
|
-
// Field pattern functions
|
|
604
|
-
detectFieldPattern,
|
|
605
|
-
detectTypeCategory,
|
|
606
|
-
isSystemField,
|
|
607
|
-
// Constants
|
|
608
|
-
SYSTEM_FIELDS,
|
|
609
|
-
} from '@flusys/nestjs-core/seeders';
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
> **Note:** `FieldPatternType`, `AUDIT_FIELDS`, `IDENTITY_FIELDS`, `BOOLEAN_KEYWORDS`, `getStringLengthCategory`, and `getTokenLength` are internal utilities available in `field-patterns.ts` but not exported from the public API.
|
|
613
|
-
|
|
614
|
-
### Swagger
|
|
615
|
-
|
|
616
|
-
```typescript
|
|
617
|
-
import {
|
|
618
|
-
setupSwaggerDocs,
|
|
619
|
-
setupModuleSwaggerDocs,
|
|
620
|
-
IModuleSwaggerOptions,
|
|
621
|
-
ISchemaPropertyExclusion,
|
|
622
|
-
IQueryParameterExclusion,
|
|
623
|
-
ISwaggerGlobalHeader,
|
|
624
|
-
IExampleExclusion,
|
|
625
|
-
} from '@flusys/nestjs-core/docs';
|
|
626
|
-
```
|
|
627
|
-
|
|
628
|
-
---
|
|
629
|
-
|
|
630
|
-
## Dependencies
|
|
631
|
-
|
|
632
|
-
- `dotenv` - Environment variable loading
|
|
633
|
-
- `typeorm` - Migration/seeder utilities (DataSource, EntityMetadata)
|
|
634
|
-
- `@faker-js/faker` - Seed data generation
|
|
635
|
-
- `@nestjs/common`, `@nestjs/swagger` - Swagger documentation setup only
|
|
636
|
-
|
|
637
|
-
---
|
|
169
|
+
## License
|
|
638
170
|
|
|
639
|
-
|
|
171
|
+
MIT © FLUSYS
|