@flusys/nestjs-core 9.1.2 → 9.2.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 +39 -6
- package/config/env-config.service.d.ts +4 -2
- package/fesm/229.js +189 -135
- package/fesm/config/index.js +41 -19
- package/fesm/docs/index.js +81 -166
- package/fesm/index.js +1 -1
- package/fesm/migration/index.js +1 -1
- package/fesm/utils/index.js +15 -26
- package/migration/migration.runner.d.ts +10 -1
- package/package.json +1 -2
package/fesm/config/index.js
CHANGED
|
@@ -14,10 +14,20 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
14
14
|
;// CONCATENATED MODULE: ./projects/nestjs-core/src/config/env-config.service.ts
|
|
15
15
|
|
|
16
16
|
__rspack_external_dotenv.config();
|
|
17
|
+
const DATABASE_TYPES = [
|
|
18
|
+
'mysql',
|
|
19
|
+
'postgres',
|
|
20
|
+
'mariadb',
|
|
21
|
+
'sqlite',
|
|
22
|
+
'mssql'
|
|
23
|
+
];
|
|
24
|
+
const DEFAULT_DB_PORTS = {
|
|
25
|
+
postgres: 5432,
|
|
26
|
+
mssql: 1433
|
|
27
|
+
};
|
|
17
28
|
let env_config_service_EnvConfigService = class EnvConfigService {
|
|
18
29
|
env;
|
|
19
30
|
restrictedKeys = {
|
|
20
|
-
FRONTEND_URL: 'getFrontendUrl',
|
|
21
31
|
ALLOW_ORIGINS: 'getOrigins',
|
|
22
32
|
PORT: 'getPort',
|
|
23
33
|
MODE: 'isProduction',
|
|
@@ -33,10 +43,13 @@ let env_config_service_EnvConfigService = class EnvConfigService {
|
|
|
33
43
|
}
|
|
34
44
|
getValue(key, throwOnMissing = true) {
|
|
35
45
|
const value = this.env[key];
|
|
36
|
-
if (!value
|
|
37
|
-
|
|
46
|
+
if (!value?.trim()) {
|
|
47
|
+
if (throwOnMissing) {
|
|
48
|
+
throw new Error(`Config error - missing env.${key}`);
|
|
49
|
+
}
|
|
50
|
+
return '';
|
|
38
51
|
}
|
|
39
|
-
return value
|
|
52
|
+
return value;
|
|
40
53
|
}
|
|
41
54
|
tryGetValue(key, throwOnMissing = false) {
|
|
42
55
|
if (this.restrictedKeys[key]) {
|
|
@@ -45,30 +58,39 @@ let env_config_service_EnvConfigService = class EnvConfigService {
|
|
|
45
58
|
return this.getValue(key, throwOnMissing);
|
|
46
59
|
}
|
|
47
60
|
getNumber(key, throwOnMissing = true) {
|
|
48
|
-
|
|
61
|
+
const raw = this.getValue(key, throwOnMissing).trim();
|
|
62
|
+
if (!raw) return undefined;
|
|
63
|
+
const value = Number(raw);
|
|
64
|
+
if (Number.isFinite(value)) return value;
|
|
65
|
+
if (throwOnMissing) {
|
|
66
|
+
throw new Error(`Config error - env.${key} must be a number, got "${raw}"`);
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
49
69
|
}
|
|
50
70
|
getBoolean(key, throwOnMissing = true) {
|
|
51
|
-
return this.getValue(key, throwOnMissing).toLowerCase() === 'true';
|
|
71
|
+
return this.getValue(key, throwOnMissing).trim().toLowerCase() === 'true';
|
|
52
72
|
}
|
|
53
73
|
getPort() {
|
|
54
74
|
return this.getNumber('PORT', false) || 3000;
|
|
55
75
|
}
|
|
56
76
|
isProduction() {
|
|
57
|
-
return this.getValue('MODE', false).toUpperCase() !== 'DEV';
|
|
77
|
+
return this.getValue('MODE', false).trim().toUpperCase() !== 'DEV';
|
|
58
78
|
}
|
|
59
79
|
getOrigins() {
|
|
60
|
-
|
|
61
|
-
return origins ? origins.split(',').map((o)=>o.trim()) : [];
|
|
80
|
+
return this.getValue('ALLOW_ORIGINS').split(',').map((o)=>o.trim()).filter(Boolean);
|
|
62
81
|
}
|
|
63
82
|
getTypeOrmConfig() {
|
|
64
|
-
const
|
|
65
|
-
|
|
83
|
+
const rawType = this.getValue('DB_TYPE', false).trim().toLowerCase() || 'mysql';
|
|
84
|
+
if (!DATABASE_TYPES.includes(rawType)) {
|
|
85
|
+
throw new Error(`Config error - unsupported env.DB_TYPE "${rawType}". Expected one of: ${DATABASE_TYPES.join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
const type = rawType;
|
|
66
88
|
return {
|
|
67
89
|
type,
|
|
68
90
|
host: this.getValue('DB_HOST', false) || 'localhost',
|
|
69
|
-
port: this.getNumber('DB_PORT', false) ||
|
|
91
|
+
port: this.getNumber('DB_PORT', false) || DEFAULT_DB_PORTS[type] || 3306,
|
|
70
92
|
username: this.getValue('DB_USER', false) || 'root',
|
|
71
|
-
password: this.getValue('DB_PASSWORD', false)
|
|
93
|
+
password: this.getValue('DB_PASSWORD', false),
|
|
72
94
|
database: this.getValue('DB_NAME', false) || 'flusys_main'
|
|
73
95
|
};
|
|
74
96
|
}
|
|
@@ -85,15 +107,15 @@ let env_config_service_EnvConfigService = class EnvConfigService {
|
|
|
85
107
|
}
|
|
86
108
|
getMailConfig() {
|
|
87
109
|
return {
|
|
88
|
-
MAIL_FROM: this.getValue('MAIL_FROM', false)
|
|
89
|
-
MAIL_APP_PASSWORD: this.getValue('MAIL_APP_PASSWORD', false)
|
|
110
|
+
MAIL_FROM: this.getValue('MAIL_FROM', false),
|
|
111
|
+
MAIL_APP_PASSWORD: this.getValue('MAIL_APP_PASSWORD', false)
|
|
90
112
|
};
|
|
91
113
|
}
|
|
92
114
|
getTenantId() {
|
|
93
|
-
return this.getValue('TENANT_ID', false) || null;
|
|
115
|
+
return this.getValue('TENANT_ID', false).trim() || null;
|
|
94
116
|
}
|
|
95
117
|
useTenantMode() {
|
|
96
|
-
return this.
|
|
118
|
+
return this.getBoolean('USE_TENANT_MODE', false);
|
|
97
119
|
}
|
|
98
120
|
getLogConfig() {
|
|
99
121
|
return {
|
|
@@ -101,11 +123,11 @@ let env_config_service_EnvConfigService = class EnvConfigService {
|
|
|
101
123
|
level: this.getValue('LOG_LEVEL', false) || (this.isProduction() ? 'info' : 'debug'),
|
|
102
124
|
maxSize: this.getValue('LOG_MAX_SIZE', false) || '20m',
|
|
103
125
|
maxFiles: this.getValue('LOG_MAX_FILES', false) || '14d',
|
|
104
|
-
disableHttpLogging: this.
|
|
126
|
+
disableHttpLogging: this.getBoolean('DISABLE_HTTP_LOGGING', false)
|
|
105
127
|
};
|
|
106
128
|
}
|
|
107
129
|
getEnv() {
|
|
108
|
-
return
|
|
130
|
+
return this.env;
|
|
109
131
|
}
|
|
110
132
|
};
|
|
111
133
|
const envConfig = new env_config_service_EnvConfigService(process.env);
|
package/fesm/docs/index.js
CHANGED
|
@@ -14,6 +14,23 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
14
14
|
|
|
15
15
|
;// CONCATENATED MODULE: ./projects/nestjs-core/src/docs/docs.config.ts
|
|
16
16
|
|
|
17
|
+
const HTTP_METHODS = new Set([
|
|
18
|
+
'get',
|
|
19
|
+
'put',
|
|
20
|
+
'post',
|
|
21
|
+
'delete',
|
|
22
|
+
'options',
|
|
23
|
+
'head',
|
|
24
|
+
'patch',
|
|
25
|
+
'trace'
|
|
26
|
+
]);
|
|
27
|
+
function escapeRegex(value) {
|
|
28
|
+
return value.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
29
|
+
}
|
|
30
|
+
function pathMatchesPattern(path, pattern) {
|
|
31
|
+
const regexPattern = pattern.split('**').map((part)=>part.split('*').map(escapeRegex).join('[^/]+')).join('.*');
|
|
32
|
+
return new RegExp(`^${regexPattern}$`).test(path);
|
|
33
|
+
}
|
|
17
34
|
function filterSchemaProperties(document, exclusions) {
|
|
18
35
|
if (!exclusions?.length || !document.components?.schemas) {
|
|
19
36
|
return document;
|
|
@@ -23,23 +40,22 @@ function filterSchemaProperties(document, exclusions) {
|
|
|
23
40
|
};
|
|
24
41
|
for (const exclusion of exclusions){
|
|
25
42
|
const schema = schemas[exclusion.schemaName];
|
|
26
|
-
if (schema
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
// Also remove from required array if present
|
|
34
|
-
const filteredRequired = schema.required?.filter((r)=>!exclusion.properties.includes(r));
|
|
35
|
-
schemas[exclusion.schemaName] = {
|
|
36
|
-
...schema,
|
|
37
|
-
properties: filteredProperties,
|
|
38
|
-
...filteredRequired?.length ? {
|
|
39
|
-
required: filteredRequired
|
|
40
|
-
} : {}
|
|
41
|
-
};
|
|
43
|
+
if (!schema || typeof schema !== 'object' || !('properties' in schema)) continue;
|
|
44
|
+
const properties = {
|
|
45
|
+
...schema.properties
|
|
46
|
+
};
|
|
47
|
+
for (const prop of exclusion.properties){
|
|
48
|
+
delete properties[prop];
|
|
42
49
|
}
|
|
50
|
+
const { required, ...rest } = schema;
|
|
51
|
+
const filteredRequired = Array.isArray(required) ? required.filter((r)=>!exclusion.properties.includes(r)) : undefined;
|
|
52
|
+
schemas[exclusion.schemaName] = {
|
|
53
|
+
...rest,
|
|
54
|
+
properties,
|
|
55
|
+
...filteredRequired?.length ? {
|
|
56
|
+
required: filteredRequired
|
|
57
|
+
} : {}
|
|
58
|
+
};
|
|
43
59
|
}
|
|
44
60
|
return {
|
|
45
61
|
...document,
|
|
@@ -49,183 +65,98 @@ function filterSchemaProperties(document, exclusions) {
|
|
|
49
65
|
}
|
|
50
66
|
};
|
|
51
67
|
}
|
|
52
|
-
function
|
|
68
|
+
function transformMatchingOperations(document, exclusions, transform) {
|
|
53
69
|
if (!exclusions?.length || !document.paths) {
|
|
54
70
|
return document;
|
|
55
71
|
}
|
|
56
|
-
const
|
|
72
|
+
const paths = {};
|
|
57
73
|
for (const [path, pathItem] of Object.entries(document.paths)){
|
|
58
|
-
const
|
|
74
|
+
const nextPathItem = {};
|
|
59
75
|
for (const [method, operation] of Object.entries(pathItem)){
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
filteredPathItem[method] = operation;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
// Check if this endpoint matches any exclusion pattern
|
|
66
|
-
const matchingExclusions = exclusions.filter((exclusion)=>{
|
|
67
|
-
const pathMatches = pathMatchesPattern(path, exclusion.pathPattern);
|
|
68
|
-
const methodMatches = !exclusion.method || exclusion.method === method;
|
|
69
|
-
return pathMatches && methodMatches;
|
|
70
|
-
});
|
|
71
|
-
if (matchingExclusions.length > 0) {
|
|
72
|
-
// Collect all parameters to exclude
|
|
73
|
-
const paramsToExclude = new Set();
|
|
74
|
-
matchingExclusions.forEach((exclusion)=>{
|
|
75
|
-
exclusion.parameters.forEach((param)=>paramsToExclude.add(param));
|
|
76
|
-
});
|
|
77
|
-
// Filter out excluded query parameters
|
|
78
|
-
const filteredOperation = {
|
|
79
|
-
...operation
|
|
80
|
-
};
|
|
81
|
-
if (Array.isArray(filteredOperation.parameters)) {
|
|
82
|
-
filteredOperation.parameters = filteredOperation.parameters.filter((param)=>{
|
|
83
|
-
return !(param.in === 'query' && paramsToExclude.has(param.name));
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
filteredPathItem[method] = filteredOperation;
|
|
87
|
-
} else {
|
|
88
|
-
filteredPathItem[method] = operation;
|
|
89
|
-
}
|
|
76
|
+
const matching = operation && typeof operation === 'object' && HTTP_METHODS.has(method) ? exclusions.filter((exclusion)=>pathMatchesPattern(path, exclusion.pathPattern) && (!exclusion.method || exclusion.method.toLowerCase() === method)) : [];
|
|
77
|
+
nextPathItem[method] = matching.length ? transform(operation, matching) : operation;
|
|
90
78
|
}
|
|
91
|
-
|
|
79
|
+
paths[path] = nextPathItem;
|
|
92
80
|
}
|
|
93
81
|
return {
|
|
94
82
|
...document,
|
|
95
|
-
paths
|
|
83
|
+
paths
|
|
96
84
|
};
|
|
97
85
|
}
|
|
86
|
+
function filterQueryParameters(document, exclusions) {
|
|
87
|
+
return transformMatchingOperations(document, exclusions, (operation, matching)=>{
|
|
88
|
+
const excluded = new Set(matching.flatMap((exclusion)=>exclusion.parameters));
|
|
89
|
+
if (!Array.isArray(operation.parameters)) return {
|
|
90
|
+
...operation
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
...operation,
|
|
94
|
+
parameters: operation.parameters.filter((param)=>!(param.in === 'query' && excluded.has(param.name)))
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
98
|
function filterExamples(document, exclusions) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (!operation || typeof operation !== 'object') {
|
|
108
|
-
filteredPathItem[method] = operation;
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
// Check if this endpoint matches any exclusion pattern
|
|
112
|
-
const matchingExclusions = exclusions.filter((exclusion)=>{
|
|
113
|
-
const pathMatches = pathMatchesPattern(path, exclusion.pathPattern);
|
|
114
|
-
const methodMatches = !exclusion.method || exclusion.method === method;
|
|
115
|
-
return pathMatches && methodMatches;
|
|
116
|
-
});
|
|
117
|
-
if (matchingExclusions.length > 0) {
|
|
118
|
-
// Collect all examples to exclude
|
|
119
|
-
const examplesToExclude = new Set();
|
|
120
|
-
matchingExclusions.forEach((exclusion)=>{
|
|
121
|
-
exclusion.examples.forEach((example)=>examplesToExclude.add(example));
|
|
122
|
-
});
|
|
123
|
-
// Deep clone the operation to avoid mutating original
|
|
124
|
-
const filteredOperation = JSON.parse(JSON.stringify(operation));
|
|
125
|
-
// Filter examples from responses
|
|
126
|
-
if (filteredOperation.responses) {
|
|
127
|
-
for (const [statusCode, response] of Object.entries(filteredOperation.responses)){
|
|
128
|
-
const responseObj = response;
|
|
129
|
-
if (responseObj?.content) {
|
|
130
|
-
const content = responseObj.content;
|
|
131
|
-
for (const [mediaType, mediaTypeObj] of Object.entries(content)){
|
|
132
|
-
const media = mediaTypeObj;
|
|
133
|
-
if (media?.examples && typeof media.examples === 'object') {
|
|
134
|
-
const examples = media.examples;
|
|
135
|
-
for (const exampleName of examplesToExclude){
|
|
136
|
-
delete examples[exampleName];
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
99
|
+
return transformMatchingOperations(document, exclusions, (operation, matching)=>{
|
|
100
|
+
const excluded = new Set(matching.flatMap((exclusion)=>exclusion.examples));
|
|
101
|
+
const cloned = structuredClone(operation);
|
|
102
|
+
for (const response of Object.values(cloned.responses ?? {})){
|
|
103
|
+
for (const media of Object.values(response?.content ?? {})){
|
|
104
|
+
if (media?.examples && typeof media.examples === 'object') {
|
|
105
|
+
for (const name of excluded){
|
|
106
|
+
delete media.examples[name];
|
|
141
107
|
}
|
|
142
108
|
}
|
|
143
|
-
filteredPathItem[method] = filteredOperation;
|
|
144
|
-
} else {
|
|
145
|
-
filteredPathItem[method] = operation;
|
|
146
109
|
}
|
|
147
110
|
}
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
...document,
|
|
152
|
-
paths: filteredPaths
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function pathMatchesPattern(path, pattern) {
|
|
156
|
-
// Convert wildcard pattern to regex
|
|
157
|
-
const regexPattern = pattern.replace(/\*/g, '[^/]+') // * matches any characters except /
|
|
158
|
-
.replace(/\*\*/g, '.*'); // ** matches any characters including /
|
|
159
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
160
|
-
return regex.test(path);
|
|
111
|
+
return cloned;
|
|
112
|
+
});
|
|
161
113
|
}
|
|
162
114
|
function filterPaths(document, excludePaths) {
|
|
163
115
|
if (!excludePaths?.length || !document.paths) {
|
|
164
116
|
return document;
|
|
165
117
|
}
|
|
166
|
-
const
|
|
118
|
+
const paths = {};
|
|
167
119
|
for (const [path, pathItem] of Object.entries(document.paths)){
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
filteredPaths[path] = pathItem;
|
|
120
|
+
if (!excludePaths.some((pattern)=>pathMatchesPattern(path, pattern))) {
|
|
121
|
+
paths[path] = pathItem;
|
|
171
122
|
}
|
|
172
123
|
}
|
|
173
124
|
return {
|
|
174
125
|
...document,
|
|
175
|
-
paths
|
|
126
|
+
paths
|
|
176
127
|
};
|
|
177
128
|
}
|
|
178
129
|
function filterDocumentByTags(document, excludeTags) {
|
|
179
|
-
if (!excludeTags?.length) {
|
|
130
|
+
if (!excludeTags?.length || !document.paths) {
|
|
180
131
|
return document;
|
|
181
132
|
}
|
|
182
133
|
const excludeTagsSet = new Set(excludeTags.map((tag)=>tag.toLowerCase()));
|
|
183
|
-
|
|
184
|
-
const filteredPaths = {};
|
|
134
|
+
const paths = {};
|
|
185
135
|
for (const [path, pathItem] of Object.entries(document.paths)){
|
|
186
|
-
const
|
|
136
|
+
const nextPathItem = {};
|
|
187
137
|
for (const [method, operation] of Object.entries(pathItem)){
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
const operationTags = operation.tags || [];
|
|
194
|
-
const hasExcludedTag = operationTags.some((tag)=>excludeTagsSet.has(tag.toLowerCase()));
|
|
195
|
-
if (!hasExcludedTag) {
|
|
196
|
-
filteredPathItem[method] = operation;
|
|
138
|
+
const tags = operation && typeof operation === 'object' ? operation.tags : undefined;
|
|
139
|
+
const excluded = Array.isArray(tags) && tags.some((tag)=>excludeTagsSet.has(String(tag).toLowerCase()));
|
|
140
|
+
if (!excluded) {
|
|
141
|
+
nextPathItem[method] = operation;
|
|
197
142
|
}
|
|
198
143
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
'get',
|
|
202
|
-
'post',
|
|
203
|
-
'put',
|
|
204
|
-
'patch',
|
|
205
|
-
'delete',
|
|
206
|
-
'options',
|
|
207
|
-
'head'
|
|
208
|
-
].includes(key));
|
|
209
|
-
if (hasOperations) {
|
|
210
|
-
filteredPaths[path] = filteredPathItem;
|
|
144
|
+
if (Object.keys(nextPathItem).some((key)=>HTTP_METHODS.has(key))) {
|
|
145
|
+
paths[path] = nextPathItem;
|
|
211
146
|
}
|
|
212
147
|
}
|
|
213
|
-
// Filter out excluded tags from the tags array
|
|
214
|
-
const filteredTags = document.tags?.filter((tag)=>!excludeTagsSet.has(tag.name.toLowerCase()));
|
|
215
148
|
return {
|
|
216
149
|
...document,
|
|
217
|
-
paths
|
|
218
|
-
tags:
|
|
150
|
+
paths,
|
|
151
|
+
tags: document.tags?.filter((tag)=>!excludeTagsSet.has(tag.name.toLowerCase()))
|
|
219
152
|
};
|
|
220
153
|
}
|
|
221
154
|
function setupModuleSwaggerDocs(app, configs) {
|
|
222
155
|
configs.forEach((config)=>{
|
|
223
156
|
const builder = new DocumentBuilder().setTitle(config.title).setDescription(config.description).setVersion(config.version || '1.0');
|
|
224
|
-
// Add bearer auth
|
|
225
157
|
if (config.bearerAuth) {
|
|
226
158
|
builder.addBearerAuth();
|
|
227
159
|
}
|
|
228
|
-
// Add custom global headers
|
|
229
160
|
if (config.globalHeaders?.length) {
|
|
230
161
|
config.globalHeaders.forEach((header)=>{
|
|
231
162
|
builder.addGlobalParameters({
|
|
@@ -240,31 +171,15 @@ function setupModuleSwaggerDocs(app, configs) {
|
|
|
240
171
|
});
|
|
241
172
|
});
|
|
242
173
|
}
|
|
243
|
-
// Only filter by modules if specified
|
|
244
174
|
const createDocOptions = config.modules?.length ? {
|
|
245
175
|
include: config.modules
|
|
246
176
|
} : {};
|
|
247
177
|
let document = SwaggerModule.createDocument(app, builder.build(), createDocOptions);
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (config.excludeTags?.length) {
|
|
254
|
-
document = filterDocumentByTags(document, config.excludeTags);
|
|
255
|
-
}
|
|
256
|
-
// Filter out excluded schema properties
|
|
257
|
-
if (config.excludeSchemaProperties?.length) {
|
|
258
|
-
document = filterSchemaProperties(document, config.excludeSchemaProperties);
|
|
259
|
-
}
|
|
260
|
-
// Filter out excluded query parameters
|
|
261
|
-
if (config.excludeQueryParameters?.length) {
|
|
262
|
-
document = filterQueryParameters(document, config.excludeQueryParameters);
|
|
263
|
-
}
|
|
264
|
-
// Filter out excluded examples
|
|
265
|
-
if (config.excludeExamples?.length) {
|
|
266
|
-
document = filterExamples(document, config.excludeExamples);
|
|
267
|
-
}
|
|
178
|
+
document = filterPaths(document, config.excludePaths ?? []);
|
|
179
|
+
document = filterDocumentByTags(document, config.excludeTags ?? []);
|
|
180
|
+
document = filterSchemaProperties(document, config.excludeSchemaProperties ?? []);
|
|
181
|
+
document = filterQueryParameters(document, config.excludeQueryParameters ?? []);
|
|
182
|
+
document = filterExamples(document, config.excludeExamples ?? []);
|
|
268
183
|
SwaggerModule.setup(config.path, app, document);
|
|
269
184
|
});
|
|
270
185
|
}
|
package/fesm/index.js
CHANGED
|
@@ -62,7 +62,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
62
62
|
256(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
63
63
|
/* import */ var _datasource_factory_js__rspack_import_0 = __webpack_require__(193);
|
|
64
64
|
/* import */ var _migration_cli_js__rspack_import_1 = __webpack_require__(164);
|
|
65
|
-
/* import */ var _migration_runner_js__rspack_import_2 = __webpack_require__(
|
|
65
|
+
/* import */ var _migration_runner_js__rspack_import_2 = __webpack_require__(989);
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
|
package/fesm/migration/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export const __webpack_modules__ = {
|
|
|
4
4
|
256(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5
5
|
/* import */ var _datasource_factory_js__rspack_import_0 = __webpack_require__(193);
|
|
6
6
|
/* import */ var _migration_cli_js__rspack_import_1 = __webpack_require__(164);
|
|
7
|
-
/* import */ var _migration_runner_js__rspack_import_2 = __webpack_require__(
|
|
7
|
+
/* import */ var _migration_runner_js__rspack_import_2 = __webpack_require__(989);
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
package/fesm/utils/index.js
CHANGED
|
@@ -2,9 +2,7 @@ export const __rspack_esm_id = 152;
|
|
|
2
2
|
export const __rspack_esm_ids = [152];
|
|
3
3
|
export const __webpack_modules__ = {
|
|
4
4
|
722(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5
|
-
|
|
6
|
-
* Build DataSource options from database config
|
|
7
|
-
*/ function buildDataSourceOptions(config, entities, migrationsPath, migrationsTableName = 'migrations') {
|
|
5
|
+
function buildDataSourceOptions(config, entities, migrationsPath, migrationsTableName = 'migrations') {
|
|
8
6
|
return {
|
|
9
7
|
type: config.type,
|
|
10
8
|
host: config.host,
|
|
@@ -20,24 +18,20 @@ export const __webpack_modules__ = {
|
|
|
20
18
|
synchronize: false
|
|
21
19
|
};
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
* Get migration folder path for a tenant
|
|
25
|
-
*/ function getMigrationsFolderPath(basePath, tenantId) {
|
|
21
|
+
function getMigrationsFolderPath(basePath, tenantId) {
|
|
26
22
|
const folder = tenantId || 'default';
|
|
27
23
|
return `${basePath}/${folder}`;
|
|
28
24
|
}
|
|
29
|
-
|
|
30
|
-
* Get migrations glob pattern for a tenant
|
|
31
|
-
*/ function getMigrationsGlobPattern(basePath, tenantId) {
|
|
25
|
+
function getMigrationsGlobPattern(basePath, tenantId) {
|
|
32
26
|
return `${getMigrationsFolderPath(basePath, tenantId)}/*{.ts,.js}`;
|
|
33
27
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const tenant = config.tenants.find((t)=>t.id === tenantId);
|
|
28
|
+
function getDatabaseForTenant(config, tenantId) {
|
|
29
|
+
if (tenantId) {
|
|
30
|
+
const tenants = config.tenants ?? [];
|
|
31
|
+
const tenant = tenants.find((t)=>t.id === tenantId);
|
|
39
32
|
if (!tenant) {
|
|
40
|
-
|
|
33
|
+
const available = tenants.map((t)=>t.id).join(', ') || 'none';
|
|
34
|
+
throw new Error(`Tenant '${tenantId}' not found. Available: ${available}`);
|
|
41
35
|
}
|
|
42
36
|
return {
|
|
43
37
|
database: tenant.database,
|
|
@@ -45,21 +39,20 @@ export const __webpack_modules__ = {
|
|
|
45
39
|
tenantConfig: tenant
|
|
46
40
|
};
|
|
47
41
|
}
|
|
48
|
-
// Default config - use bootstrapAppConfig for feature flags
|
|
49
42
|
const defaultTenantConfig = {
|
|
50
43
|
id: 'default',
|
|
51
44
|
database: config.defaultDatabaseConfig.database || 'default',
|
|
52
45
|
enableCompanyFeature: config.bootstrapAppConfig?.enableCompanyFeature ?? false,
|
|
53
|
-
permissionMode: config.bootstrapAppConfig?.permissionMode ?? 'FULL'
|
|
46
|
+
permissionMode: config.bootstrapAppConfig?.permissionMode ?? 'FULL',
|
|
47
|
+
enableEmailVerification: config.bootstrapAppConfig?.enableEmailVerification,
|
|
48
|
+
enableSignUp: config.bootstrapAppConfig?.enableSignUp
|
|
54
49
|
};
|
|
55
50
|
return {
|
|
56
51
|
database: defaultTenantConfig.database,
|
|
57
52
|
tenantConfig: defaultTenantConfig
|
|
58
53
|
};
|
|
59
54
|
}
|
|
60
|
-
|
|
61
|
-
* Resolve full connection details for a tenant.
|
|
62
|
-
*/ function resolveDatabaseConnection(config, tenantId) {
|
|
55
|
+
function resolveDatabaseConnection(config, tenantId) {
|
|
63
56
|
const { database, tenant } = getDatabaseForTenant(config, tenantId);
|
|
64
57
|
return tenant ? {
|
|
65
58
|
...config.defaultDatabaseConfig,
|
|
@@ -73,17 +66,13 @@ export const __webpack_modules__ = {
|
|
|
73
66
|
database
|
|
74
67
|
};
|
|
75
68
|
}
|
|
76
|
-
|
|
77
|
-
* Resolve entities based on tenant config
|
|
78
|
-
*/ function resolveEntities(config, tenantConfig) {
|
|
69
|
+
function resolveEntities(config, tenantConfig) {
|
|
79
70
|
if (typeof config.entities === 'function') {
|
|
80
71
|
return config.entities(tenantConfig);
|
|
81
72
|
}
|
|
82
73
|
return config.entities;
|
|
83
74
|
}
|
|
84
|
-
|
|
85
|
-
* Get active tenants from config
|
|
86
|
-
*/ function getActiveTenants(config) {
|
|
75
|
+
function getActiveTenants(config) {
|
|
87
76
|
return config.tenants || [];
|
|
88
77
|
}
|
|
89
78
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type IMigrationConfig, type IMigrationResult } from '../interfaces/migration.interface.js';
|
|
2
|
+
export declare function assertValidMigrationName(name: string): void;
|
|
2
3
|
export declare function ensureMigrationsFolder(basePath: string, tenantId?: string): string;
|
|
3
4
|
export declare function generateMigration(config: IMigrationConfig, name: string, tenantId?: string, datasourcePath?: string): Promise<void>;
|
|
4
5
|
export declare function stripIgnoredTableStatements(folder: string, name: string, ignoreTable: (tableName: string) => boolean): number;
|
|
@@ -6,4 +7,12 @@ export declare function runMigrations(config: IMigrationConfig, tenantId?: strin
|
|
|
6
7
|
export declare function revertMigration(config: IMigrationConfig, tenantId?: string): Promise<IMigrationResult>;
|
|
7
8
|
export declare function resetDatabase(config: IMigrationConfig, tenantId?: string): Promise<IMigrationResult>;
|
|
8
9
|
export declare function migrationStatus(config: IMigrationConfig, tenantId?: string): Promise<IMigrationResult>;
|
|
9
|
-
|
|
10
|
+
declare const TENANT_ACTIONS: {
|
|
11
|
+
readonly run: typeof runMigrations;
|
|
12
|
+
readonly revert: typeof revertMigration;
|
|
13
|
+
readonly status: typeof migrationStatus;
|
|
14
|
+
};
|
|
15
|
+
export type TenantMigrationAction = keyof typeof TENANT_ACTIONS;
|
|
16
|
+
export declare function isTenantMigrationAction(action: string): action is TenantMigrationAction;
|
|
17
|
+
export declare function runForAllTenants(config: IMigrationConfig, command: TenantMigrationAction): Promise<IMigrationResult[]>;
|
|
18
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/nestjs-core",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.2.0",
|
|
4
4
|
"description": "Core types, interfaces, and constants for Flusys NestJS packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./fesm/index.js",
|
|
@@ -53,7 +53,6 @@
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@faker-js/faker": "^10.0.0",
|
|
57
56
|
"@nestjs/common": "^12.0.0",
|
|
58
57
|
"@nestjs/config": "^12.0.0",
|
|
59
58
|
"@nestjs/core": "^12.0.0",
|