@flusys/nestjs-core 1.1.0-beta ā 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 +136 -162
- package/cjs/config/env-config.service.js +14 -10
- package/cjs/docs/docs.config.js +99 -15
- package/cjs/docs/index.js +0 -1
- package/cjs/index.js +0 -1
- package/cjs/interfaces/base-entity.interface.js +5 -3
- package/cjs/interfaces/database.interface.js +1 -3
- package/cjs/migration/datasource.factory.js +1 -3
- package/cjs/migration/index.js +0 -12
- package/cjs/migration/migration.cli.js +1 -17
- package/cjs/migration/migration.runner.js +37 -65
- package/cjs/utils/datasource-config.builder.js +2 -14
- package/config/env-config.service.d.ts +3 -1
- package/docs/docs.config.d.ts +8 -0
- package/docs/index.d.ts +0 -1
- package/fesm/config/env-config.service.js +14 -10
- package/fesm/docs/docs.config.js +89 -15
- package/fesm/docs/index.js +0 -1
- package/fesm/index.js +0 -2
- package/fesm/interfaces/app-config.interfaces.js +1 -3
- package/fesm/interfaces/base-entity.interface.js +5 -5
- package/fesm/interfaces/database.interface.js +1 -5
- package/fesm/migration/cli.js +1 -20
- package/fesm/migration/datasource.factory.js +3 -20
- package/fesm/migration/index.js +0 -14
- package/fesm/migration/migration.cli.js +1 -17
- package/fesm/migration/migration.runner.js +43 -132
- package/fesm/utils/datasource-config.builder.js +2 -13
- package/index.d.ts +0 -1
- package/interfaces/app-config.interfaces.d.ts +1 -0
- package/interfaces/base-entity.interface.d.ts +2 -2
- package/interfaces/database.interface.d.ts +2 -1
- package/package.json +9 -9
- package/utils/datasource-config.builder.d.ts +0 -1
- package/cjs/docs/docs.setup.js +0 -14
- package/cjs/seeders/base-seeder.js +0 -95
- package/cjs/seeders/cli.js +0 -398
- package/cjs/seeders/data-generator.js +0 -247
- package/cjs/seeders/entity-reader.js +0 -168
- package/cjs/seeders/index.js +0 -77
- package/cjs/seeders/seed-config.js +0 -101
- package/cjs/seeders/seed-runner.js +0 -320
- package/cjs/seeders/template-generator.js +0 -297
- package/docs/docs.setup.d.ts +0 -3
- package/fesm/docs/docs.setup.js +0 -4
- package/fesm/seeders/base-seeder.js +0 -110
- package/fesm/seeders/cli.js +0 -366
- package/fesm/seeders/data-generator.js +0 -249
- package/fesm/seeders/entity-reader.js +0 -170
- package/fesm/seeders/index.js +0 -11
- package/fesm/seeders/seed-config.js +0 -85
- package/fesm/seeders/seed-runner.js +0 -323
- package/fesm/seeders/template-generator.js +0 -257
- 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 -45
- package/seeders/index.d.ts +0 -7
- package/seeders/seed-config.d.ts +0 -11
- package/seeders/seed-runner.d.ts +0 -47
- package/seeders/template-generator.d.ts +0 -16
|
@@ -75,6 +75,36 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
75
75
|
}
|
|
76
76
|
return newObj;
|
|
77
77
|
}
|
|
78
|
+
function getLabel(tenantId) {
|
|
79
|
+
return tenantId ? `[${tenantId}]` : '[default]';
|
|
80
|
+
}
|
|
81
|
+
async function withDataSource(config, tenantId, operation) {
|
|
82
|
+
const { database } = (0, _utils.getDatabaseForTenant)(config, tenantId);
|
|
83
|
+
const label = getLabel(tenantId);
|
|
84
|
+
try {
|
|
85
|
+
const ds = await (0, _datasourcefactory.initializeDataSource)({
|
|
86
|
+
config,
|
|
87
|
+
tenantId
|
|
88
|
+
});
|
|
89
|
+
const partial = await operation(ds, label);
|
|
90
|
+
await ds.destroy();
|
|
91
|
+
return {
|
|
92
|
+
tenantId,
|
|
93
|
+
database,
|
|
94
|
+
success: true,
|
|
95
|
+
...partial
|
|
96
|
+
};
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
99
|
+
console.error(`${label} ā Failed: ${errorMessage}`);
|
|
100
|
+
return {
|
|
101
|
+
tenantId,
|
|
102
|
+
database,
|
|
103
|
+
success: false,
|
|
104
|
+
error: errorMessage
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
78
108
|
function ensureMigrationsFolder(basePath, tenantId) {
|
|
79
109
|
const folder = (0, _utils.getMigrationsFolderPath)(basePath, tenantId);
|
|
80
110
|
if (!_fs.existsSync(folder)) {
|
|
@@ -116,15 +146,8 @@ function findDatasourcePath() {
|
|
|
116
146
|
throw new Error('Could not find datasource file. Specify with --datasource=<path>');
|
|
117
147
|
}
|
|
118
148
|
async function runMigrations(config, tenantId) {
|
|
119
|
-
|
|
120
|
-
const label = tenantId ? `[${tenantId}]` : '[default]';
|
|
121
|
-
try {
|
|
122
|
-
const ds = await (0, _datasourcefactory.initializeDataSource)({
|
|
123
|
-
config,
|
|
124
|
-
tenantId
|
|
125
|
-
});
|
|
149
|
+
return withDataSource(config, tenantId, async (ds, label)=>{
|
|
126
150
|
const migrations = await ds.runMigrations();
|
|
127
|
-
await ds.destroy();
|
|
128
151
|
if (migrations.length === 0) {
|
|
129
152
|
console.log(`${label} No pending migrations.`);
|
|
130
153
|
} else {
|
|
@@ -132,78 +155,27 @@ async function runMigrations(config, tenantId) {
|
|
|
132
155
|
migrations.forEach((m)=>console.log(` - ${m.name}`));
|
|
133
156
|
}
|
|
134
157
|
return {
|
|
135
|
-
tenantId,
|
|
136
|
-
database,
|
|
137
|
-
success: true,
|
|
138
158
|
migrationsRun: migrations.map((m)=>m.name)
|
|
139
159
|
};
|
|
140
|
-
}
|
|
141
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
142
|
-
console.error(`${label} ā Failed: ${errorMessage}`);
|
|
143
|
-
return {
|
|
144
|
-
tenantId,
|
|
145
|
-
database,
|
|
146
|
-
success: false,
|
|
147
|
-
error: errorMessage
|
|
148
|
-
};
|
|
149
|
-
}
|
|
160
|
+
});
|
|
150
161
|
}
|
|
151
162
|
async function revertMigration(config, tenantId) {
|
|
152
|
-
|
|
153
|
-
const label = tenantId ? `[${tenantId}]` : '[default]';
|
|
154
|
-
try {
|
|
155
|
-
const ds = await (0, _datasourcefactory.initializeDataSource)({
|
|
156
|
-
config,
|
|
157
|
-
tenantId
|
|
158
|
-
});
|
|
163
|
+
return withDataSource(config, tenantId, async (ds, label)=>{
|
|
159
164
|
await ds.undoLastMigration();
|
|
160
|
-
await ds.destroy();
|
|
161
165
|
console.log(`${label} ā Reverted!`);
|
|
162
|
-
return {
|
|
163
|
-
|
|
164
|
-
database,
|
|
165
|
-
success: true
|
|
166
|
-
};
|
|
167
|
-
} catch (error) {
|
|
168
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
169
|
-
console.error(`${label} ā Failed: ${errorMessage}`);
|
|
170
|
-
return {
|
|
171
|
-
tenantId,
|
|
172
|
-
database,
|
|
173
|
-
success: false,
|
|
174
|
-
error: errorMessage
|
|
175
|
-
};
|
|
176
|
-
}
|
|
166
|
+
return {};
|
|
167
|
+
});
|
|
177
168
|
}
|
|
178
169
|
async function migrationStatus(config, tenantId) {
|
|
179
|
-
|
|
180
|
-
const label = tenantId ? `[${tenantId}]` : '[default]';
|
|
181
|
-
try {
|
|
182
|
-
const ds = await (0, _datasourcefactory.initializeDataSource)({
|
|
183
|
-
config,
|
|
184
|
-
tenantId
|
|
185
|
-
});
|
|
170
|
+
return withDataSource(config, tenantId, async (ds, label)=>{
|
|
186
171
|
const hasPending = await ds.showMigrations();
|
|
187
|
-
await ds.destroy();
|
|
188
172
|
console.log(`${label} Pending: ${hasPending ? 'Yes' : 'No'}`);
|
|
189
173
|
return {
|
|
190
|
-
tenantId,
|
|
191
|
-
database,
|
|
192
|
-
success: true,
|
|
193
174
|
migrationsRun: [
|
|
194
175
|
hasPending ? 'Has pending' : 'Up to date'
|
|
195
176
|
]
|
|
196
177
|
};
|
|
197
|
-
}
|
|
198
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
199
|
-
console.error(`${label} ā Failed: ${errorMessage}`);
|
|
200
|
-
return {
|
|
201
|
-
tenantId,
|
|
202
|
-
database,
|
|
203
|
-
success: false,
|
|
204
|
-
error: errorMessage
|
|
205
|
-
};
|
|
206
|
-
}
|
|
178
|
+
});
|
|
207
179
|
}
|
|
208
180
|
async function runForAllTenants(config, command) {
|
|
209
181
|
const tenants = (0, _utils.getActiveTenants)(config);
|
|
@@ -12,9 +12,6 @@ _export(exports, {
|
|
|
12
12
|
get buildDataSourceOptions () {
|
|
13
13
|
return buildDataSourceOptions;
|
|
14
14
|
},
|
|
15
|
-
get buildTenantDatabaseConfig () {
|
|
16
|
-
return buildTenantDatabaseConfig;
|
|
17
|
-
},
|
|
18
15
|
get getActiveTenants () {
|
|
19
16
|
return getActiveTenants;
|
|
20
17
|
},
|
|
@@ -70,7 +67,8 @@ function getDatabaseForTenant(config, tenantId) {
|
|
|
70
67
|
const defaultTenantConfig = {
|
|
71
68
|
id: 'default',
|
|
72
69
|
database: config.defaultDatabaseConfig.database || 'default',
|
|
73
|
-
enableCompanyFeature: config.bootstrapAppConfig?.enableCompanyFeature ?? false
|
|
70
|
+
enableCompanyFeature: config.bootstrapAppConfig?.enableCompanyFeature ?? false,
|
|
71
|
+
permissionMode: config.bootstrapAppConfig?.permissionMode ?? 'FULL'
|
|
74
72
|
};
|
|
75
73
|
return {
|
|
76
74
|
database: defaultTenantConfig.database,
|
|
@@ -83,16 +81,6 @@ function resolveEntities(config, tenantConfig) {
|
|
|
83
81
|
}
|
|
84
82
|
return config.entities;
|
|
85
83
|
}
|
|
86
|
-
function buildTenantDatabaseConfig(baseConfig, tenant) {
|
|
87
|
-
return {
|
|
88
|
-
type: baseConfig.type,
|
|
89
|
-
host: tenant.host ?? baseConfig.host,
|
|
90
|
-
port: tenant.port ?? baseConfig.port,
|
|
91
|
-
username: tenant.username ?? baseConfig.username,
|
|
92
|
-
password: tenant.password ?? baseConfig.password,
|
|
93
|
-
database: tenant.database
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
84
|
function getActiveTenants(config) {
|
|
97
85
|
return config.tenants || [];
|
|
98
86
|
}
|
|
@@ -10,13 +10,14 @@ declare class EnvConfigService {
|
|
|
10
10
|
getBoolean(key: string, throwOnMissing?: boolean): boolean;
|
|
11
11
|
getPort(): number;
|
|
12
12
|
isProduction(): boolean;
|
|
13
|
-
getFrontendUrl(): string;
|
|
14
13
|
getOrigins(): string[];
|
|
15
14
|
getTypeOrmConfig(): {
|
|
15
|
+
type: "mysql" | "postgres" | "mariadb" | "sqlite" | "mssql";
|
|
16
16
|
host: string;
|
|
17
17
|
port: number;
|
|
18
18
|
username: string;
|
|
19
19
|
password: string;
|
|
20
|
+
database: string;
|
|
20
21
|
};
|
|
21
22
|
getJwtConfig(): {
|
|
22
23
|
secret: string;
|
|
@@ -36,6 +37,7 @@ declare class EnvConfigService {
|
|
|
36
37
|
level: string;
|
|
37
38
|
maxSize: string;
|
|
38
39
|
maxFiles: string;
|
|
40
|
+
disableHttpLogging: boolean;
|
|
39
41
|
};
|
|
40
42
|
getEnv(): Record<string, string>;
|
|
41
43
|
}
|
package/docs/docs.config.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export interface IQueryParameterExclusion {
|
|
|
14
14
|
method?: string;
|
|
15
15
|
parameters: string[];
|
|
16
16
|
}
|
|
17
|
+
export interface IExampleExclusion {
|
|
18
|
+
pathPattern: string;
|
|
19
|
+
method?: string;
|
|
20
|
+
examples: string[];
|
|
21
|
+
}
|
|
17
22
|
export interface IModuleSwaggerOptions {
|
|
18
23
|
modules?: Type<unknown>[];
|
|
19
24
|
title: string;
|
|
@@ -25,5 +30,8 @@ export interface IModuleSwaggerOptions {
|
|
|
25
30
|
excludeTags?: string[];
|
|
26
31
|
excludeSchemaProperties?: ISchemaPropertyExclusion[];
|
|
27
32
|
excludeQueryParameters?: IQueryParameterExclusion[];
|
|
33
|
+
excludeExamples?: IExampleExclusion[];
|
|
34
|
+
excludePaths?: string[];
|
|
28
35
|
}
|
|
29
36
|
export declare function setupModuleSwaggerDocs(app: INestApplication, configs: IModuleSwaggerOptions[]): void;
|
|
37
|
+
export declare function setupSwaggerDocs(app: INestApplication, ...modules: IModuleSwaggerOptions[]): void;
|
package/docs/index.d.ts
CHANGED
|
@@ -34,24 +34,25 @@ let EnvConfigService = class EnvConfigService {
|
|
|
34
34
|
return this.getValue(key, throwOnMissing).toLowerCase() === 'true';
|
|
35
35
|
}
|
|
36
36
|
getPort() {
|
|
37
|
-
return this.getNumber('PORT', false);
|
|
37
|
+
return this.getNumber('PORT', false) || 3000;
|
|
38
38
|
}
|
|
39
39
|
isProduction() {
|
|
40
40
|
return this.getValue('MODE', false).toUpperCase() !== 'DEV';
|
|
41
41
|
}
|
|
42
|
-
getFrontendUrl() {
|
|
43
|
-
return this.getValue('FRONTEND_URL');
|
|
44
|
-
}
|
|
45
42
|
getOrigins() {
|
|
46
43
|
const origins = this.getValue('ALLOW_ORIGINS');
|
|
47
44
|
return origins ? origins.split(',').map((o)=>o.trim()) : [];
|
|
48
45
|
}
|
|
49
46
|
getTypeOrmConfig() {
|
|
47
|
+
const type = this.getValue('DB_TYPE', false) || 'mysql';
|
|
48
|
+
const defaultPort = type === 'postgres' ? 5432 : 3306;
|
|
50
49
|
return {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
type,
|
|
51
|
+
host: this.getValue('DB_HOST', false) || 'localhost',
|
|
52
|
+
port: this.getNumber('DB_PORT', false) || defaultPort,
|
|
53
|
+
username: this.getValue('DB_USER', false) || 'root',
|
|
54
|
+
password: this.getValue('DB_PASSWORD', false) || '',
|
|
55
|
+
database: this.getValue('DB_NAME', false) || 'flusys_main'
|
|
55
56
|
};
|
|
56
57
|
}
|
|
57
58
|
getJwtConfig() {
|
|
@@ -82,7 +83,8 @@ let EnvConfigService = class EnvConfigService {
|
|
|
82
83
|
dir: this.getValue('LOG_DIR', false) || 'logs',
|
|
83
84
|
level: this.getValue('LOG_LEVEL', false) || (this.isProduction() ? 'info' : 'debug'),
|
|
84
85
|
maxSize: this.getValue('LOG_MAX_SIZE', false) || '20m',
|
|
85
|
-
maxFiles: this.getValue('LOG_MAX_FILES', false) || '14d'
|
|
86
|
+
maxFiles: this.getValue('LOG_MAX_FILES', false) || '14d',
|
|
87
|
+
disableHttpLogging: this.getValue('DISABLE_HTTP_LOGGING', false).toLowerCase() === 'true'
|
|
86
88
|
};
|
|
87
89
|
}
|
|
88
90
|
getEnv() {
|
|
@@ -97,10 +99,12 @@ let EnvConfigService = class EnvConfigService {
|
|
|
97
99
|
ALLOW_ORIGINS: 'getOrigins',
|
|
98
100
|
PORT: 'getPort',
|
|
99
101
|
MODE: 'isProduction',
|
|
102
|
+
DB_TYPE: 'getTypeOrmConfig',
|
|
100
103
|
DB_HOST: 'getTypeOrmConfig',
|
|
101
104
|
DB_PORT: 'getTypeOrmConfig',
|
|
102
105
|
DB_USER: 'getTypeOrmConfig',
|
|
103
|
-
DB_PASSWORD: 'getTypeOrmConfig'
|
|
106
|
+
DB_PASSWORD: 'getTypeOrmConfig',
|
|
107
|
+
DB_NAME: 'getTypeOrmConfig'
|
|
104
108
|
};
|
|
105
109
|
}
|
|
106
110
|
};
|
package/fesm/docs/docs.config.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
2
|
-
|
|
3
|
-
* Filter OpenAPI document to exclude schema properties
|
|
4
|
-
*/ function filterSchemaProperties(document, exclusions) {
|
|
2
|
+
function filterSchemaProperties(document, exclusions) {
|
|
5
3
|
if (!exclusions?.length || !document.components?.schemas) {
|
|
6
4
|
return document;
|
|
7
5
|
}
|
|
@@ -36,9 +34,7 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
|
36
34
|
}
|
|
37
35
|
};
|
|
38
36
|
}
|
|
39
|
-
|
|
40
|
-
* Filter OpenAPI document to exclude query parameters from specific endpoints
|
|
41
|
-
*/ function filterQueryParameters(document, exclusions) {
|
|
37
|
+
function filterQueryParameters(document, exclusions) {
|
|
42
38
|
if (!exclusions?.length || !document.paths) {
|
|
43
39
|
return document;
|
|
44
40
|
}
|
|
@@ -84,18 +80,87 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
|
84
80
|
paths: filteredPaths
|
|
85
81
|
};
|
|
86
82
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
function filterExamples(document, exclusions) {
|
|
84
|
+
if (!exclusions?.length || !document.paths) {
|
|
85
|
+
return document;
|
|
86
|
+
}
|
|
87
|
+
const filteredPaths = {};
|
|
88
|
+
for (const [path, pathItem] of Object.entries(document.paths)){
|
|
89
|
+
const filteredPathItem = {};
|
|
90
|
+
for (const [method, operation] of Object.entries(pathItem)){
|
|
91
|
+
// Skip non-operation properties
|
|
92
|
+
if (!operation || typeof operation !== 'object') {
|
|
93
|
+
filteredPathItem[method] = operation;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// Check if this endpoint matches any exclusion pattern
|
|
97
|
+
const matchingExclusions = exclusions.filter((exclusion)=>{
|
|
98
|
+
const pathMatches = pathMatchesPattern(path, exclusion.pathPattern);
|
|
99
|
+
const methodMatches = !exclusion.method || exclusion.method === method;
|
|
100
|
+
return pathMatches && methodMatches;
|
|
101
|
+
});
|
|
102
|
+
if (matchingExclusions.length > 0) {
|
|
103
|
+
// Collect all examples to exclude
|
|
104
|
+
const examplesToExclude = new Set();
|
|
105
|
+
matchingExclusions.forEach((exclusion)=>{
|
|
106
|
+
exclusion.examples.forEach((example)=>examplesToExclude.add(example));
|
|
107
|
+
});
|
|
108
|
+
// Deep clone the operation to avoid mutating original
|
|
109
|
+
const filteredOperation = JSON.parse(JSON.stringify(operation));
|
|
110
|
+
// Filter examples from responses
|
|
111
|
+
if (filteredOperation.responses) {
|
|
112
|
+
for (const [statusCode, response] of Object.entries(filteredOperation.responses)){
|
|
113
|
+
const responseObj = response;
|
|
114
|
+
if (responseObj?.content) {
|
|
115
|
+
const content = responseObj.content;
|
|
116
|
+
for (const [mediaType, mediaTypeObj] of Object.entries(content)){
|
|
117
|
+
const media = mediaTypeObj;
|
|
118
|
+
if (media?.examples && typeof media.examples === 'object') {
|
|
119
|
+
const examples = media.examples;
|
|
120
|
+
for (const exampleName of examplesToExclude){
|
|
121
|
+
delete examples[exampleName];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
filteredPathItem[method] = filteredOperation;
|
|
129
|
+
} else {
|
|
130
|
+
filteredPathItem[method] = operation;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
filteredPaths[path] = filteredPathItem;
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
...document,
|
|
137
|
+
paths: filteredPaths
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function pathMatchesPattern(path, pattern) {
|
|
90
141
|
// Convert wildcard pattern to regex
|
|
91
142
|
const regexPattern = pattern.replace(/\*/g, '[^/]+') // * matches any characters except /
|
|
92
143
|
.replace(/\*\*/g, '.*'); // ** matches any characters including /
|
|
93
144
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
94
145
|
return regex.test(path);
|
|
95
146
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
147
|
+
function filterPaths(document, excludePaths) {
|
|
148
|
+
if (!excludePaths?.length || !document.paths) {
|
|
149
|
+
return document;
|
|
150
|
+
}
|
|
151
|
+
const filteredPaths = {};
|
|
152
|
+
for (const [path, pathItem] of Object.entries(document.paths)){
|
|
153
|
+
const isExcluded = excludePaths.some((pattern)=>pathMatchesPattern(path, pattern));
|
|
154
|
+
if (!isExcluded) {
|
|
155
|
+
filteredPaths[path] = pathItem;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
...document,
|
|
160
|
+
paths: filteredPaths
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function filterDocumentByTags(document, excludeTags) {
|
|
99
164
|
if (!excludeTags?.length) {
|
|
100
165
|
return document;
|
|
101
166
|
}
|
|
@@ -138,9 +203,7 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
|
138
203
|
tags: filteredTags
|
|
139
204
|
};
|
|
140
205
|
}
|
|
141
|
-
|
|
142
|
-
* Setup Swagger documentation for multiple modules
|
|
143
|
-
*/ export function setupModuleSwaggerDocs(app, configs) {
|
|
206
|
+
export function setupModuleSwaggerDocs(app, configs) {
|
|
144
207
|
configs.forEach((config)=>{
|
|
145
208
|
const builder = new DocumentBuilder().setTitle(config.title).setDescription(config.description).setVersion(config.version || '1.0');
|
|
146
209
|
// Add bearer auth
|
|
@@ -167,6 +230,10 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
|
167
230
|
include: config.modules
|
|
168
231
|
} : {};
|
|
169
232
|
let document = SwaggerModule.createDocument(app, builder.build(), createDocOptions);
|
|
233
|
+
// Filter out excluded paths
|
|
234
|
+
if (config.excludePaths?.length) {
|
|
235
|
+
document = filterPaths(document, config.excludePaths);
|
|
236
|
+
}
|
|
170
237
|
// Filter out excluded tags
|
|
171
238
|
if (config.excludeTags?.length) {
|
|
172
239
|
document = filterDocumentByTags(document, config.excludeTags);
|
|
@@ -179,6 +246,13 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
|
179
246
|
if (config.excludeQueryParameters?.length) {
|
|
180
247
|
document = filterQueryParameters(document, config.excludeQueryParameters);
|
|
181
248
|
}
|
|
249
|
+
// Filter out excluded examples
|
|
250
|
+
if (config.excludeExamples?.length) {
|
|
251
|
+
document = filterExamples(document, config.excludeExamples);
|
|
252
|
+
}
|
|
182
253
|
SwaggerModule.setup(config.path, app, document);
|
|
183
254
|
});
|
|
184
255
|
}
|
|
256
|
+
export function setupSwaggerDocs(app, ...modules) {
|
|
257
|
+
setupModuleSwaggerDocs(app, modules);
|
|
258
|
+
}
|
package/fesm/docs/index.js
CHANGED
package/fesm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
*/ export { };
|
|
2
|
+
* Entity Contract Interfaces
|
|
3
|
+
*
|
|
4
|
+
* These interfaces define the standard fields that entities should have.
|
|
5
|
+
* Use them as contracts when implementing new entities.
|
|
6
|
+
*/ /** Base entity with UUID, timestamps, and soft delete */ /** Entity with company relation (for multi-company support) */ export { };
|
package/fesm/migration/cli.js
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
* Migration CLI Entry Point
|
|
4
|
-
*
|
|
5
|
-
* Main executable for running TypeORM migrations via npm scripts.
|
|
6
|
-
*
|
|
7
|
-
* Usage (via package.json scripts):
|
|
8
|
-
* - npm run migration generate --name=CreateUsers
|
|
9
|
-
* - npm run migration run
|
|
10
|
-
* - npm run migration revert
|
|
11
|
-
* - npm run migration status
|
|
12
|
-
* - npm run migration run:all (multi-tenant)
|
|
13
|
-
* - npm run migration revert:all (multi-tenant)
|
|
14
|
-
* - npm run migration status:all (multi-tenant)
|
|
15
|
-
*
|
|
16
|
-
* Environment Variables:
|
|
17
|
-
* - TENANT_ID: Target specific tenant (optional)
|
|
18
|
-
*
|
|
19
|
-
* This file is the executable entry point referenced in package.json.
|
|
20
|
-
* The actual CLI logic is in migration.cli.ts (runMigrationCli function).
|
|
21
|
-
*/ import { runMigrationCli } from './migration.cli';
|
|
2
|
+
import { runMigrationCli } from './migration.cli';
|
|
22
3
|
runMigrationCli().catch((err)=>{
|
|
23
4
|
console.error('CLI Error:', err.message);
|
|
24
5
|
process.exit(1);
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import { DataSource } from 'typeorm';
|
|
2
2
|
import { SnakeNamingStrategy } from 'typeorm-naming-strategies';
|
|
3
3
|
import { buildDataSourceOptions, getDatabaseForTenant, getMigrationsGlobPattern, resolveEntities } from '../utils/datasource-config.builder';
|
|
4
|
-
|
|
5
|
-
* Create a DataSource for migrations
|
|
6
|
-
*
|
|
7
|
-
* @param options - Configuration options
|
|
8
|
-
* @param options.config - Migration configuration
|
|
9
|
-
* @param options.tenantId - Optional tenant ID for multi-tenant mode
|
|
10
|
-
* @returns DataSource instance (not initialized)
|
|
11
|
-
*/ export function createMigrationDataSource(options) {
|
|
4
|
+
export function createMigrationDataSource(options) {
|
|
12
5
|
const { config, tenantId } = options;
|
|
13
6
|
const { database, tenant, tenantConfig } = getDatabaseForTenant(config, tenantId);
|
|
14
|
-
// Log target info
|
|
15
7
|
console.log(`\nš¦ Database: ${database}${tenant ? ` [${tenant.name}]` : ' [default]'}`);
|
|
16
8
|
console.log(`š Migrations: migrations/${tenantId || 'default'}/`);
|
|
17
|
-
if (config.bootstrapAppConfig?.databaseMode
|
|
9
|
+
if (config.bootstrapAppConfig?.databaseMode === 'multi-tenant' && !tenantId && config.tenants && config.tenants.length > 0) {
|
|
18
10
|
console.log(`\nš” Multi-tenant mode. Available tenants:`);
|
|
19
11
|
config.tenants.forEach((t)=>console.log(` - TENANT_ID=${t.id} ā ${t.database}`));
|
|
20
12
|
}
|
|
@@ -29,7 +21,6 @@ import { buildDataSourceOptions, getDatabaseForTenant, getMigrationsGlobPattern,
|
|
|
29
21
|
...config.defaultDatabaseConfig,
|
|
30
22
|
database
|
|
31
23
|
};
|
|
32
|
-
// Resolve entities based on tenant config
|
|
33
24
|
const entities = resolveEntities(config, tenantConfig);
|
|
34
25
|
const dsOptions = buildDataSourceOptions(dbConfig, entities, getMigrationsGlobPattern(config.migrationsPath, tenantId), config.migrationsTableName);
|
|
35
26
|
return new DataSource({
|
|
@@ -37,15 +28,7 @@ import { buildDataSourceOptions, getDatabaseForTenant, getMigrationsGlobPattern,
|
|
|
37
28
|
namingStrategy: new SnakeNamingStrategy()
|
|
38
29
|
});
|
|
39
30
|
}
|
|
40
|
-
|
|
41
|
-
* Initialize and return a DataSource
|
|
42
|
-
*
|
|
43
|
-
* Creates a DataSource and initializes the connection.
|
|
44
|
-
* The connection should be destroyed after use with `ds.destroy()`.
|
|
45
|
-
*
|
|
46
|
-
* @param options - Configuration options
|
|
47
|
-
* @returns Initialized DataSource instance
|
|
48
|
-
*/ export async function initializeDataSource(options) {
|
|
31
|
+
export async function initializeDataSource(options) {
|
|
49
32
|
const ds = createMigrationDataSource(options);
|
|
50
33
|
await ds.initialize();
|
|
51
34
|
return ds;
|
package/fesm/migration/index.js
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Migration Module Exports
|
|
3
|
-
*
|
|
4
|
-
* Public API for TypeORM migration management in single and multi-tenant databases.
|
|
5
|
-
*
|
|
6
|
-
* Main exports:
|
|
7
|
-
* - createMigrationDataSource: Create DataSource for migrations
|
|
8
|
-
* - initializeDataSource: Create and initialize DataSource
|
|
9
|
-
* - runMigrationCli: Programmatic CLI execution
|
|
10
|
-
*
|
|
11
|
-
* The CLI entry point is at ./cli.ts (used by npm scripts)
|
|
12
|
-
*/ // DataSource factory for migration config files
|
|
13
1
|
export { createMigrationDataSource, initializeDataSource } from './datasource.factory';
|
|
14
|
-
// CLI service for programmatic usage
|
|
15
2
|
export { runMigrationCli } from './migration.cli';
|
|
16
|
-
// Migration runner functions (optional, for advanced usage)
|
|
17
3
|
export { generateMigration, runMigrations, revertMigration, migrationStatus, runForAllTenants, ensureMigrationsFolder } from './migration.runner';
|
|
@@ -2,23 +2,7 @@ import * as path from 'path';
|
|
|
2
2
|
import { envConfig } from '../config';
|
|
3
3
|
import { getDatabaseForTenant, getMigrationsFolderPath } from '../utils';
|
|
4
4
|
import { generateMigration, migrationStatus, revertMigration, runForAllTenants, runMigrations } from './migration.runner';
|
|
5
|
-
|
|
6
|
-
* Migration CLI Service
|
|
7
|
-
*
|
|
8
|
-
* Handles migration command execution for single and multi-tenant databases.
|
|
9
|
-
*
|
|
10
|
-
* Commands:
|
|
11
|
-
* - generate: Create new migration
|
|
12
|
-
* - run: Execute pending migrations
|
|
13
|
-
* - revert: Rollback last migration
|
|
14
|
-
* - status: Check migration status
|
|
15
|
-
* - run:all/revert:all/status:all: Batch operations for all tenants
|
|
16
|
-
*
|
|
17
|
-
* Configuration:
|
|
18
|
-
* - TENANT_ID: Target tenant (optional, defaults to default database)
|
|
19
|
-
* - --config=<path>: Migration config file path
|
|
20
|
-
* - --datasource=<path>: DataSource file path for TypeORM CLI
|
|
21
|
-
*/ function showHelp() {
|
|
5
|
+
function showHelp() {
|
|
22
6
|
console.log(`
|
|
23
7
|
Migration CLI
|
|
24
8
|
|