@flusys/nestjs-entity-builder 9.0.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 +111 -0
- package/config/entity-builder.constants.d.ts +6 -0
- package/config/event-actions.d.ts +8 -0
- package/config/index.d.ts +3 -0
- package/config/message-keys.d.ts +542 -0
- package/controllers/entity-definition.controller.d.ts +40 -0
- package/controllers/field-definition.controller.d.ts +22 -0
- package/controllers/flow-definition.controller.d.ts +51 -0
- package/controllers/flow-execution.controller.d.ts +21 -0
- package/controllers/flow-runtime.controller.d.ts +24 -0
- package/controllers/index.d.ts +5 -0
- package/docs/entity-builder-swagger.config.d.ts +3 -0
- package/docs/index.d.ts +1 -0
- package/dtos/entity-definition.dto.d.ts +58 -0
- package/dtos/field-definition.dto.d.ts +42 -0
- package/dtos/flow.dto.d.ts +76 -0
- package/dtos/index.d.ts +3 -0
- package/dtos/schema-change.dto.d.ts +53 -0
- package/entities/entity-definition.entity.d.ts +15 -0
- package/entities/field-definition.entity.d.ts +23 -0
- package/entities/flow-definition.entity.d.ts +14 -0
- package/entities/flow-execution.entity.d.ts +19 -0
- package/entities/flow-version.entity.d.ts +10 -0
- package/entities/index.d.ts +14 -0
- package/entities/schema-change-log.entity.d.ts +15 -0
- package/enums/ddl-operation.enum.d.ts +13 -0
- package/enums/entity-status.enum.d.ts +5 -0
- package/enums/field-type.enum.d.ts +15 -0
- package/enums/index.d.ts +3 -0
- package/fesm/21.js +576 -0
- package/fesm/362.js +1074 -0
- package/fesm/458.js +649 -0
- package/fesm/582.js +1247 -0
- package/fesm/677.js +7534 -0
- package/fesm/719.js +3597 -0
- package/fesm/794.js +979 -0
- package/fesm/913.js +1620 -0
- package/fesm/config/index.js +126 -0
- package/fesm/controllers/index.js +27 -0
- package/fesm/docs/index.js +82 -0
- package/fesm/dtos/index.js +327 -0
- package/fesm/entities/index.js +18 -0
- package/fesm/enums/index.js +97 -0
- package/fesm/guards/index.js +226 -0
- package/fesm/index.js +548 -0
- package/fesm/interfaces/index.js +80 -0
- package/fesm/modules/index.js +25 -0
- package/fesm/rule-engine/index.js +21 -0
- package/fesm/runtime.js +85 -0
- package/fesm/services/index.js +526 -0
- package/flow-engine/flow-api-key.d.ts +6 -0
- package/flow-engine/flow-code-sandbox.d.ts +5 -0
- package/flow-engine/flow-engine.d.ts +22 -0
- package/flow-engine/flow-graph.validator.d.ts +20 -0
- package/flow-engine/flow-http.client.d.ts +15 -0
- package/flow-engine/flow-input.validator.d.ts +7 -0
- package/flow-engine/flow-node-handlers.d.ts +5 -0
- package/flow-engine/flow-rate-limiter.d.ts +8 -0
- package/flow-engine/flow-reference.d.ts +7 -0
- package/flow-engine/flow-run.types.d.ts +131 -0
- package/flow-engine/flow.errors.d.ts +27 -0
- package/flow-engine/flow.types.d.ts +315 -0
- package/flow-engine/index.d.ts +4 -0
- package/flow-engine/redact.d.ts +3 -0
- package/flow-engine/ssrf-guard.d.ts +6 -0
- package/guards/flow-access.guard.d.ts +11 -0
- package/guards/index.d.ts +1 -0
- package/index.d.ts +11 -0
- package/interfaces/entity-builder-module.interface.d.ts +28 -0
- package/interfaces/field-definition.interface.d.ts +33 -0
- package/interfaces/flow-definition.interface.d.ts +24 -0
- package/interfaces/generic-record.interface.d.ts +15 -0
- package/interfaces/index.d.ts +5 -0
- package/interfaces/reference-provider.interface.d.ts +8 -0
- package/interfaces/schema-dialect-adapter.interface.d.ts +15 -0
- package/modules/entity-builder.module.d.ts +10 -0
- package/modules/index.d.ts +1 -0
- package/package.json +93 -0
- package/rule-engine/index.d.ts +3 -0
- package/rule-engine/rule-engine.service.d.ts +40 -0
- package/rule-engine/rule-evaluation-context.interface.d.ts +28 -0
- package/rule-engine/rule-ip.d.ts +3 -0
- package/rule-engine/rule-permission.d.ts +10 -0
- package/rule-engine/rule-regex.d.ts +4 -0
- package/rule-engine/rule-values.d.ts +5 -0
- package/rule-engine/rule.interface.d.ts +79 -0
- package/services/database-error.mapper.d.ts +2 -0
- package/services/definition-cache.service.d.ts +8 -0
- package/services/entity-builder-config.service.d.ts +12 -0
- package/services/entity-builder-datasource.provider.d.ts +24 -0
- package/services/entity-definition.service.d.ts +17 -0
- package/services/entity-flow-scaffold.d.ts +27 -0
- package/services/entity-permission.service.d.ts +8 -0
- package/services/field-definition.service.d.ts +17 -0
- package/services/field-type-conversion.d.ts +15 -0
- package/services/field-value-validator.d.ts +17 -0
- package/services/flow-definition.service.d.ts +62 -0
- package/services/flow-execution.service.d.ts +38 -0
- package/services/flow-executor.service.d.ts +41 -0
- package/services/flow-reference.provider.d.ts +13 -0
- package/services/flow-runtime.service.d.ts +30 -0
- package/services/generic-entity-service.factory.d.ts +12 -0
- package/services/generic-entity.service.d.ts +67 -0
- package/services/identifier-rules.d.ts +9 -0
- package/services/index.d.ts +26 -0
- package/services/reference-rewrite.d.ts +7 -0
- package/services/reference-scanner.service.d.ts +10 -0
- package/services/schema-change-executor.service.d.ts +39 -0
- package/services/schema-change.types.d.ts +59 -0
- package/services/schema-columns.d.ts +26 -0
- package/services/schema-dialect-adapter.service.d.ts +13 -0
- package/services/schema-evolution.service.d.ts +67 -0
- package/services/schema-registry.service.d.ts +13 -0
- package/services/schema-sync.service.d.ts +28 -0
package/fesm/719.js
ADDED
|
@@ -0,0 +1,3597 @@
|
|
|
1
|
+
export const __rspack_esm_id = 719;
|
|
2
|
+
export const __rspack_esm_ids = [719];
|
|
3
|
+
export const __webpack_modules__ = {
|
|
4
|
+
2492(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5
|
+
const FLOW_REFERENCE_PROVIDER = 'FLOW_REFERENCE_PROVIDER';
|
|
6
|
+
|
|
7
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
8
|
+
}, {
|
|
9
|
+
$: FLOW_REFERENCE_PROVIDER
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
},
|
|
14
|
+
2931(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
15
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
16
|
+
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(1236);
|
|
17
|
+
/* import */ var _nestjs_common__rspack_import_2 = __webpack_require__(6157);
|
|
18
|
+
/* import */ var _config_event_actions_js__rspack_import_3 = __webpack_require__(982);
|
|
19
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
20
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
21
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
22
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
23
|
+
} else {
|
|
24
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
25
|
+
if (d = decorators[i]) {
|
|
26
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
31
|
+
}
|
|
32
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
33
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
34
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function _ts_param(paramIndex, decorator) {
|
|
38
|
+
return function(target, key) {
|
|
39
|
+
decorator(target, key, paramIndex);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/** Every cached definition list/get. Schema changes write these rows inside a transaction, past the cached services. */ const CACHED_DEFINITIONS = [
|
|
47
|
+
_config_event_actions_js__rspack_import_3/* .ENTITY_BUILDER_EVENT_ENTITIES.ENTITY_DEFINITION */.P.ENTITY_DEFINITION,
|
|
48
|
+
_config_event_actions_js__rspack_import_3/* .ENTITY_BUILDER_EVENT_ENTITIES.FIELD_DEFINITION */.P.FIELD_DEFINITION,
|
|
49
|
+
_config_event_actions_js__rspack_import_3/* .ENTITY_BUILDER_EVENT_ENTITIES.FLOW_DEFINITION */.P.FLOW_DEFINITION
|
|
50
|
+
];
|
|
51
|
+
class DefinitionCacheService {
|
|
52
|
+
cacheManager;
|
|
53
|
+
utilsService;
|
|
54
|
+
constructor(cacheManager, utilsService){
|
|
55
|
+
this.cacheManager = cacheManager;
|
|
56
|
+
this.utilsService = utilsService;
|
|
57
|
+
}
|
|
58
|
+
/** `tenantId` is the tenant whose definitions changed (see `cacheTenantId`); caches are keyed per tenant. */ async clearAll(tenantId) {
|
|
59
|
+
await Promise.all(CACHED_DEFINITIONS.map((name)=>this.utilsService.clearCache(name, this.cacheManager, undefined, tenantId)));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
DefinitionCacheService = _ts_decorate([
|
|
63
|
+
(0,_nestjs_common__rspack_import_2.Injectable)(),
|
|
64
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_2.Inject)('CACHE_INSTANCE')),
|
|
65
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_2.Inject)(_flusys_nestjs_shared_modules__rspack_import_1.UtilsService)),
|
|
66
|
+
_ts_metadata("design:type", Function),
|
|
67
|
+
_ts_metadata("design:paramtypes", [
|
|
68
|
+
typeof _flusys_nestjs_shared_classes__rspack_import_0.HybridCache === "undefined" ? Object : _flusys_nestjs_shared_classes__rspack_import_0.HybridCache,
|
|
69
|
+
typeof _flusys_nestjs_shared_modules__rspack_import_1.UtilsService === "undefined" ? Object : _flusys_nestjs_shared_modules__rspack_import_1.UtilsService
|
|
70
|
+
])
|
|
71
|
+
], DefinitionCacheService);
|
|
72
|
+
|
|
73
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
74
|
+
V: () => (DefinitionCacheService)
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
},
|
|
79
|
+
1296(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
80
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
81
|
+
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(1236);
|
|
82
|
+
/* import */ var _nestjs_common__rspack_import_2 = __webpack_require__(6157);
|
|
83
|
+
/* import */ var _config_event_actions_js__rspack_import_5 = __webpack_require__(982);
|
|
84
|
+
/* import */ var _entities_entity_definition_entity_js__rspack_import_3 = __webpack_require__(3189);
|
|
85
|
+
/* import */ var _entity_builder_datasource_provider_js__rspack_import_4 = __webpack_require__(424);
|
|
86
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
87
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
88
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
89
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
90
|
+
} else {
|
|
91
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
92
|
+
if (d = decorators[i]) {
|
|
93
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
98
|
+
}
|
|
99
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
100
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
101
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function _ts_param(paramIndex, decorator) {
|
|
105
|
+
return function(target, key) {
|
|
106
|
+
decorator(target, key, paramIndex);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class EntityDefinitionService extends _flusys_nestjs_shared_classes__rspack_import_0.ApiService {
|
|
116
|
+
cacheManager;
|
|
117
|
+
utilsService;
|
|
118
|
+
constructor(cacheManager, utilsService, dataSourceProvider){
|
|
119
|
+
super(_config_event_actions_js__rspack_import_5/* .ENTITY_BUILDER_EVENT_ENTITIES.ENTITY_DEFINITION */.P.ENTITY_DEFINITION, cacheManager, utilsService, EntityDefinitionService.name, true, _config_event_actions_js__rspack_import_5/* .ENTITY_BUILDER_EVENT_MODULE */.S, dataSourceProvider, _entities_entity_definition_entity_js__rspack_import_3/* .EntityDefinition */.f), this.cacheManager = cacheManager, this.utilsService = utilsService;
|
|
120
|
+
}
|
|
121
|
+
// Schema changes send the loaded `updatedAt` back as `expectedUpdatedAt`; Identity hides it by default.
|
|
122
|
+
async getSelectQuery(query, user, select) {
|
|
123
|
+
const result = await super.getSelectQuery(query, user, select);
|
|
124
|
+
result.query.addSelect(`${this.entityName}.updatedAt`);
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
EntityDefinitionService = _ts_decorate([
|
|
129
|
+
(0,_nestjs_common__rspack_import_2.Injectable)({
|
|
130
|
+
scope: _nestjs_common__rspack_import_2.Scope.REQUEST
|
|
131
|
+
}),
|
|
132
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_2.Inject)('CACHE_INSTANCE')),
|
|
133
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_2.Inject)(_flusys_nestjs_shared_modules__rspack_import_1.UtilsService)),
|
|
134
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_2.Inject)(_entity_builder_datasource_provider_js__rspack_import_4/* .EntityBuilderDataSourceProvider */.D)),
|
|
135
|
+
_ts_metadata("design:type", Function),
|
|
136
|
+
_ts_metadata("design:paramtypes", [
|
|
137
|
+
typeof _flusys_nestjs_shared_classes__rspack_import_0.HybridCache === "undefined" ? Object : _flusys_nestjs_shared_classes__rspack_import_0.HybridCache,
|
|
138
|
+
typeof _flusys_nestjs_shared_modules__rspack_import_1.UtilsService === "undefined" ? Object : _flusys_nestjs_shared_modules__rspack_import_1.UtilsService,
|
|
139
|
+
typeof _entity_builder_datasource_provider_js__rspack_import_4/* .EntityBuilderDataSourceProvider */.D === "undefined" ? Object : _entity_builder_datasource_provider_js__rspack_import_4/* .EntityBuilderDataSourceProvider */.D
|
|
140
|
+
])
|
|
141
|
+
], EntityDefinitionService);
|
|
142
|
+
|
|
143
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
144
|
+
o: () => (EntityDefinitionService)
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
},
|
|
149
|
+
8271(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
150
|
+
/* import */ var _config_message_keys_js__rspack_import_2 = __webpack_require__(5732);
|
|
151
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_1 = __webpack_require__(9614);
|
|
152
|
+
/* import */ var _flow_engine_flow_types_js__rspack_import_0 = __webpack_require__(6256);
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
/** The path of each endpoint's Request step: `api-flows/<entity>/<path>`. */ const ENTITY_FLOW_PATHS = {
|
|
157
|
+
insert: 'insert',
|
|
158
|
+
insertMany: 'insert-many',
|
|
159
|
+
getById: 'get-by-id',
|
|
160
|
+
getByIds: 'get-by-ids',
|
|
161
|
+
getAll: 'get-all',
|
|
162
|
+
getByFilter: 'get-by-filter',
|
|
163
|
+
update: 'update',
|
|
164
|
+
updateMany: 'update-many',
|
|
165
|
+
bulkUpsert: 'bulk-upsert',
|
|
166
|
+
delete: 'delete'
|
|
167
|
+
};
|
|
168
|
+
const DEFAULT_ENDPOINT_NAME = {
|
|
169
|
+
insert: 'Insert',
|
|
170
|
+
insertMany: 'Insert many',
|
|
171
|
+
getById: 'Get by id',
|
|
172
|
+
getByIds: 'Get by ids',
|
|
173
|
+
getAll: 'Get all',
|
|
174
|
+
getByFilter: 'Get by filter',
|
|
175
|
+
update: 'Update',
|
|
176
|
+
updateMany: 'Update many',
|
|
177
|
+
bulkUpsert: 'Bulk upsert',
|
|
178
|
+
delete: 'Delete'
|
|
179
|
+
};
|
|
180
|
+
const DEFAULT_INPUT_LABEL = {
|
|
181
|
+
id: 'Id',
|
|
182
|
+
ids: 'Ids',
|
|
183
|
+
search: 'Search'
|
|
184
|
+
};
|
|
185
|
+
const DEFAULT_NO_MATCH_MESSAGE = 'No record matches the filter.';
|
|
186
|
+
const MAX_NAME_LENGTH = 255;
|
|
187
|
+
/** A supplied text when it has content, the English default otherwise. */ const textOr = (value, fallback)=>value?.trim() || fallback;
|
|
188
|
+
const INPUT_TYPE = {
|
|
189
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.TEXT */.P.TEXT]: 'string',
|
|
190
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.LONG_TEXT */.P.LONG_TEXT]: 'text',
|
|
191
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER]: 'integer',
|
|
192
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL]: 'number',
|
|
193
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.BOOLEAN */.P.BOOLEAN]: 'boolean',
|
|
194
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.DATE */.P.DATE]: 'date',
|
|
195
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.DATETIME */.P.DATETIME]: 'datetime',
|
|
196
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.EMAIL */.P.EMAIL]: 'email',
|
|
197
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT]: 'choice',
|
|
198
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT]: 'array',
|
|
199
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.RELATION */.P.RELATION]: 'uuid',
|
|
200
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.JSON */.P.JSON]: 'object',
|
|
201
|
+
[_enums_field_type_enum_js__rspack_import_1/* .FieldType.FILE */.P.FILE]: 'uuid'
|
|
202
|
+
};
|
|
203
|
+
const LIST_LIMIT = 50;
|
|
204
|
+
const READ_ENDPOINTS = new Set([
|
|
205
|
+
'getById',
|
|
206
|
+
'getByIds',
|
|
207
|
+
'getAll',
|
|
208
|
+
'getByFilter'
|
|
209
|
+
]);
|
|
210
|
+
const COLUMN = {
|
|
211
|
+
x: 40,
|
|
212
|
+
gap: 300
|
|
213
|
+
};
|
|
214
|
+
const ROW = {
|
|
215
|
+
y: 60,
|
|
216
|
+
gap: 160
|
|
217
|
+
};
|
|
218
|
+
const ref = (path)=>({
|
|
219
|
+
type: 'field_ref',
|
|
220
|
+
ref: path
|
|
221
|
+
});
|
|
222
|
+
const lit = (value)=>({
|
|
223
|
+
type: 'literal',
|
|
224
|
+
value
|
|
225
|
+
});
|
|
226
|
+
/** `customer_ticket` -> `customer-ticket`: an entity code always fits a flow URL name. */ const entityFlowSlug = (entityCode)=>entityCode.replace(/_/g, '-');
|
|
227
|
+
function optionValues(options) {
|
|
228
|
+
return (options ?? []).map((o)=>o && typeof o === 'object' && 'value' in o ? String(o.value) : String(o));
|
|
229
|
+
}
|
|
230
|
+
const NUMERIC_TYPES = new Set([
|
|
231
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER,
|
|
232
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL
|
|
233
|
+
]);
|
|
234
|
+
const TEXT_TYPES = new Set([
|
|
235
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.TEXT */.P.TEXT,
|
|
236
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.LONG_TEXT */.P.LONG_TEXT,
|
|
237
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.EMAIL */.P.EMAIL
|
|
238
|
+
]);
|
|
239
|
+
/** The field's rules a Request body checks the same way the record write does. */ function inputRules(field) {
|
|
240
|
+
const rules = field.validationRules ?? {};
|
|
241
|
+
const keys = NUMERIC_TYPES.has(field.fieldType) ? [
|
|
242
|
+
'min',
|
|
243
|
+
'max'
|
|
244
|
+
] : TEXT_TYPES.has(field.fieldType) ? [
|
|
245
|
+
'minLength',
|
|
246
|
+
'maxLength'
|
|
247
|
+
] : [];
|
|
248
|
+
return Object.fromEntries(keys.filter((key)=>typeof rules[key] === 'number' && Number.isFinite(rules[key])).map((key)=>[
|
|
249
|
+
key,
|
|
250
|
+
rules[key]
|
|
251
|
+
]));
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The Request body input of a field: a choice carries its options, a multi-select is a list of
|
|
255
|
+
* those choices, a relation or file is an id. `rules`: a write also checks the field's own value rules.
|
|
256
|
+
*/ function fieldInput(field, required, rules = true) {
|
|
257
|
+
const options = optionValues(field.selectOptions);
|
|
258
|
+
const base = {
|
|
259
|
+
name: field.code,
|
|
260
|
+
label: field.label || field.code,
|
|
261
|
+
...required ? {
|
|
262
|
+
required: true
|
|
263
|
+
} : {},
|
|
264
|
+
...rules ? inputRules(field) : {}
|
|
265
|
+
};
|
|
266
|
+
if (field.fieldType === _enums_field_type_enum_js__rspack_import_1/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT) return {
|
|
267
|
+
...base,
|
|
268
|
+
type: 'array',
|
|
269
|
+
...options.length ? {
|
|
270
|
+
itemType: 'choice',
|
|
271
|
+
options
|
|
272
|
+
} : {
|
|
273
|
+
itemType: 'string'
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const type = INPUT_TYPE[field.fieldType] === 'choice' && !options.length ? 'string' : INPUT_TYPE[field.fieldType];
|
|
277
|
+
return {
|
|
278
|
+
...base,
|
|
279
|
+
type,
|
|
280
|
+
...type === 'choice' ? {
|
|
281
|
+
options
|
|
282
|
+
} : {}
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const isRequiredOnInsert = (field)=>field.nullable === false && (field.defaultValue === null || field.defaultValue === undefined);
|
|
286
|
+
const fieldMap = (fields, scope)=>Object.fromEntries(fields.map((f)=>[
|
|
287
|
+
f.code,
|
|
288
|
+
ref(`${scope}.${f.code}`)
|
|
289
|
+
]));
|
|
290
|
+
const optionalFieldInputs = (fields)=>fields.map((f)=>fieldInput(f, false));
|
|
291
|
+
/** Inputs of a read filter: only the value's type is checked, never the write rules. */ const filterInputs = (fields)=>fields.map((f)=>fieldInput(f, false, false));
|
|
292
|
+
/** Fields an equality filter can match - a list or JSON value cannot be compared as one value. */ const filterableFields = (entity)=>entity.fields.filter((f)=>f.fieldType !== _enums_field_type_enum_js__rspack_import_1/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT && f.fieldType !== _enums_field_type_enum_js__rspack_import_1/* .FieldType.JSON */.P.JSON);
|
|
293
|
+
const idInput = (t)=>({
|
|
294
|
+
name: 'id',
|
|
295
|
+
label: t.inputLabels.id,
|
|
296
|
+
type: 'uuid',
|
|
297
|
+
required: true
|
|
298
|
+
});
|
|
299
|
+
const idsInput = (t)=>({
|
|
300
|
+
name: 'ids',
|
|
301
|
+
label: t.inputLabels.ids,
|
|
302
|
+
type: 'array',
|
|
303
|
+
itemType: 'uuid',
|
|
304
|
+
required: true
|
|
305
|
+
});
|
|
306
|
+
const respond = (id, column, statusCode, body, row)=>({
|
|
307
|
+
id,
|
|
308
|
+
type: 'respond',
|
|
309
|
+
column,
|
|
310
|
+
row,
|
|
311
|
+
config: 'type' in body ? {
|
|
312
|
+
statusCode,
|
|
313
|
+
bodyExpression: body
|
|
314
|
+
} : {
|
|
315
|
+
statusCode,
|
|
316
|
+
body
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
/**
|
|
320
|
+
* The steps of one endpoint. Its step ids are `<endpoint>_<step>` (`id()`), so the endpoints of one
|
|
321
|
+
* flow never share a step. A bulk body is the list itself (`itemSchema` checks each item), written by
|
|
322
|
+
* one step that walks it (`target: many`, each item read as `loop.item`), all or nothing, and
|
|
323
|
+
* answered with the saved records in order.
|
|
324
|
+
*/ function endpointGraph(entity, endpoint, texts) {
|
|
325
|
+
const id = (step)=>`${endpoint}_${step}`;
|
|
326
|
+
const entityCode = entity.code;
|
|
327
|
+
const single = (inputSchema, step, statusCode = 200)=>({
|
|
328
|
+
inputSchema,
|
|
329
|
+
steps: [
|
|
330
|
+
{
|
|
331
|
+
...step,
|
|
332
|
+
id: id('record'),
|
|
333
|
+
column: 1
|
|
334
|
+
},
|
|
335
|
+
respond(id('respond'), 2, statusCode, ref(`context.${id('record')}`))
|
|
336
|
+
],
|
|
337
|
+
edges: [
|
|
338
|
+
[
|
|
339
|
+
id('record'),
|
|
340
|
+
'out',
|
|
341
|
+
id('respond')
|
|
342
|
+
]
|
|
343
|
+
]
|
|
344
|
+
});
|
|
345
|
+
const bulk = (itemSchema, step, statusCode)=>({
|
|
346
|
+
bodyType: 'list',
|
|
347
|
+
inputSchema: itemSchema,
|
|
348
|
+
steps: [
|
|
349
|
+
{
|
|
350
|
+
...step,
|
|
351
|
+
id: id('records'),
|
|
352
|
+
column: 1,
|
|
353
|
+
config: {
|
|
354
|
+
...step.config,
|
|
355
|
+
target: 'many',
|
|
356
|
+
items: ref('input')
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
respond(id('respond'), 2, statusCode, ref(`context.${id('records')}.items`))
|
|
360
|
+
],
|
|
361
|
+
edges: [
|
|
362
|
+
[
|
|
363
|
+
id('records'),
|
|
364
|
+
'out',
|
|
365
|
+
id('respond')
|
|
366
|
+
]
|
|
367
|
+
]
|
|
368
|
+
});
|
|
369
|
+
const filterFields = filterableFields(entity);
|
|
370
|
+
const insertInputs = entity.fields.map((f)=>fieldInput(f, isRequiredOnInsert(f)));
|
|
371
|
+
switch(endpoint){
|
|
372
|
+
case 'insert':
|
|
373
|
+
return single(insertInputs, {
|
|
374
|
+
type: 'entity_insert',
|
|
375
|
+
config: {
|
|
376
|
+
entityCode,
|
|
377
|
+
fields: fieldMap(entity.fields, 'input')
|
|
378
|
+
}
|
|
379
|
+
}, 201);
|
|
380
|
+
case 'insertMany':
|
|
381
|
+
return bulk(insertInputs, {
|
|
382
|
+
type: 'entity_insert',
|
|
383
|
+
config: {
|
|
384
|
+
entityCode,
|
|
385
|
+
fields: fieldMap(entity.fields, 'loop.item')
|
|
386
|
+
}
|
|
387
|
+
}, 201);
|
|
388
|
+
case 'getById':
|
|
389
|
+
return single([
|
|
390
|
+
idInput(texts)
|
|
391
|
+
], {
|
|
392
|
+
type: 'entity_get',
|
|
393
|
+
config: {
|
|
394
|
+
entityCode,
|
|
395
|
+
id: ref('input.id')
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
case 'getByIds':
|
|
399
|
+
return single([
|
|
400
|
+
idsInput(texts)
|
|
401
|
+
], {
|
|
402
|
+
type: 'entity_query',
|
|
403
|
+
config: {
|
|
404
|
+
entityCode,
|
|
405
|
+
filter: {
|
|
406
|
+
id: {
|
|
407
|
+
op: 'in',
|
|
408
|
+
value: ref('input.ids')
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
limit: _flow_engine_flow_types_js__rspack_import_0/* .FLOW_LIMITS.MAX_QUERY_LIMIT */.Or.MAX_QUERY_LIMIT
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
case 'getAll':
|
|
415
|
+
return single([
|
|
416
|
+
{
|
|
417
|
+
name: 'search',
|
|
418
|
+
label: texts.inputLabels.search,
|
|
419
|
+
type: 'string'
|
|
420
|
+
},
|
|
421
|
+
...filterInputs(filterFields)
|
|
422
|
+
], {
|
|
423
|
+
type: 'entity_query',
|
|
424
|
+
config: {
|
|
425
|
+
entityCode,
|
|
426
|
+
search: ref('input.search'),
|
|
427
|
+
filter: fieldMap(filterFields, 'input'),
|
|
428
|
+
limit: LIST_LIMIT
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
case 'getByFilter':
|
|
432
|
+
return {
|
|
433
|
+
inputSchema: [
|
|
434
|
+
{
|
|
435
|
+
...idInput(texts),
|
|
436
|
+
required: false
|
|
437
|
+
},
|
|
438
|
+
...filterInputs(filterFields)
|
|
439
|
+
],
|
|
440
|
+
steps: [
|
|
441
|
+
{
|
|
442
|
+
id: id('records'),
|
|
443
|
+
type: 'entity_query',
|
|
444
|
+
column: 1,
|
|
445
|
+
config: {
|
|
446
|
+
entityCode,
|
|
447
|
+
filter: {
|
|
448
|
+
id: ref('input.id'),
|
|
449
|
+
...fieldMap(filterFields, 'input')
|
|
450
|
+
},
|
|
451
|
+
limit: 1
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
id: id('found'),
|
|
456
|
+
type: 'condition',
|
|
457
|
+
column: 2,
|
|
458
|
+
config: {
|
|
459
|
+
rule: {
|
|
460
|
+
operator: 'AND',
|
|
461
|
+
conditions: [
|
|
462
|
+
{
|
|
463
|
+
field: `context.${id('records')}.items`,
|
|
464
|
+
comparison: 'is_not_empty'
|
|
465
|
+
}
|
|
466
|
+
]
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
respond(id('respond'), 3, 200, ref(`context.${id('records')}.items.0`)),
|
|
471
|
+
respond(id('not_found'), 3, 404, {
|
|
472
|
+
success: lit(false),
|
|
473
|
+
message: lit(texts.noMatchMessage),
|
|
474
|
+
messageKey: lit(_config_message_keys_js__rspack_import_2/* .GENERIC_RECORD_MESSAGES.NO_MATCH */.j4.NO_MATCH)
|
|
475
|
+
}, 1)
|
|
476
|
+
],
|
|
477
|
+
edges: [
|
|
478
|
+
[
|
|
479
|
+
id('records'),
|
|
480
|
+
'out',
|
|
481
|
+
id('found')
|
|
482
|
+
],
|
|
483
|
+
[
|
|
484
|
+
id('found'),
|
|
485
|
+
'true',
|
|
486
|
+
id('respond')
|
|
487
|
+
],
|
|
488
|
+
[
|
|
489
|
+
id('found'),
|
|
490
|
+
'false',
|
|
491
|
+
id('not_found')
|
|
492
|
+
]
|
|
493
|
+
]
|
|
494
|
+
};
|
|
495
|
+
case 'update':
|
|
496
|
+
return single([
|
|
497
|
+
idInput(texts),
|
|
498
|
+
...optionalFieldInputs(entity.fields)
|
|
499
|
+
], {
|
|
500
|
+
type: 'entity_update',
|
|
501
|
+
config: {
|
|
502
|
+
entityCode,
|
|
503
|
+
id: ref('input.id'),
|
|
504
|
+
fields: fieldMap(entity.fields, 'input')
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
case 'updateMany':
|
|
508
|
+
return bulk([
|
|
509
|
+
idInput(texts),
|
|
510
|
+
...optionalFieldInputs(entity.fields)
|
|
511
|
+
], {
|
|
512
|
+
type: 'entity_update',
|
|
513
|
+
config: {
|
|
514
|
+
entityCode,
|
|
515
|
+
fields: fieldMap(entity.fields, 'loop.item')
|
|
516
|
+
}
|
|
517
|
+
}, 200);
|
|
518
|
+
case 'bulkUpsert':
|
|
519
|
+
return bulk([
|
|
520
|
+
{
|
|
521
|
+
...idInput(texts),
|
|
522
|
+
required: false
|
|
523
|
+
},
|
|
524
|
+
...optionalFieldInputs(entity.fields)
|
|
525
|
+
], {
|
|
526
|
+
type: 'entity_update',
|
|
527
|
+
config: {
|
|
528
|
+
entityCode,
|
|
529
|
+
fields: fieldMap(entity.fields, 'loop.item'),
|
|
530
|
+
onNotFound: 'insert'
|
|
531
|
+
}
|
|
532
|
+
}, 200);
|
|
533
|
+
case 'delete':
|
|
534
|
+
return single([
|
|
535
|
+
idInput(texts)
|
|
536
|
+
], {
|
|
537
|
+
type: 'entity_delete',
|
|
538
|
+
config: {
|
|
539
|
+
entityCode,
|
|
540
|
+
id: ref('input.id')
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* The ready-made flow of an entity: `api-flows/<entity>` with one Request step per endpoint of the
|
|
547
|
+
* generic API controller, each on its own path (`ENTITY_FLOW_PATHS`) with its own body, laid out
|
|
548
|
+
* one below the other. Each runs as the caller, so the entity permissions still decide who may use
|
|
549
|
+
* it, and it is an ordinary flow afterwards - the user can change or delete it like any other. A
|
|
550
|
+
* write endpoint is transactional: a bulk endpoint writes its whole list in one step, so a failing
|
|
551
|
+
* item rolls back the whole request; a read endpoint opens none. A bulk body holds at most
|
|
552
|
+
* FLOW_LIMITS.MAX_WRITE_ITEMS items.
|
|
553
|
+
*/ function buildEntityFlow(entity, endpoints, texts = {}) {
|
|
554
|
+
const resolved = {
|
|
555
|
+
inputLabels: {
|
|
556
|
+
id: textOr(texts.inputLabels?.id, DEFAULT_INPUT_LABEL.id),
|
|
557
|
+
ids: textOr(texts.inputLabels?.ids, DEFAULT_INPUT_LABEL.ids),
|
|
558
|
+
search: textOr(texts.inputLabels?.search, DEFAULT_INPUT_LABEL.search)
|
|
559
|
+
},
|
|
560
|
+
noMatchMessage: textOr(texts.noMatchMessage, DEFAULT_NO_MATCH_MESSAGE)
|
|
561
|
+
};
|
|
562
|
+
const nodes = [];
|
|
563
|
+
const edges = [];
|
|
564
|
+
let band = 0;
|
|
565
|
+
for (const endpoint of endpoints){
|
|
566
|
+
const graph = endpointGraph(entity, endpoint, resolved);
|
|
567
|
+
const at = (column, row = 0)=>({
|
|
568
|
+
x: COLUMN.x + column * COLUMN.gap,
|
|
569
|
+
y: ROW.y + (band + row) * ROW.gap
|
|
570
|
+
});
|
|
571
|
+
const config = {
|
|
572
|
+
path: ENTITY_FLOW_PATHS[endpoint],
|
|
573
|
+
bodyType: graph.bodyType ?? 'object',
|
|
574
|
+
inputSchema: graph.inputSchema,
|
|
575
|
+
...READ_ENDPOINTS.has(endpoint) ? {} : {
|
|
576
|
+
isTransactional: true
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
nodes.push({
|
|
580
|
+
id: endpoint,
|
|
581
|
+
type: 'trigger',
|
|
582
|
+
name: textOr(texts.names?.[endpoint], DEFAULT_ENDPOINT_NAME[endpoint]).slice(0, MAX_NAME_LENGTH),
|
|
583
|
+
position: at(0),
|
|
584
|
+
config
|
|
585
|
+
}, ...graph.steps.map(({ column, row, ...step })=>({
|
|
586
|
+
...step,
|
|
587
|
+
name: '',
|
|
588
|
+
position: at(column, row)
|
|
589
|
+
})));
|
|
590
|
+
edges.push(...[
|
|
591
|
+
[
|
|
592
|
+
endpoint,
|
|
593
|
+
'out',
|
|
594
|
+
graph.steps[0].id
|
|
595
|
+
],
|
|
596
|
+
...graph.edges
|
|
597
|
+
].map(([from, port, to])=>({
|
|
598
|
+
id: `e_${from}_${port}_${to}`,
|
|
599
|
+
from,
|
|
600
|
+
port,
|
|
601
|
+
to
|
|
602
|
+
})));
|
|
603
|
+
band += 1 + Math.max(0, ...graph.steps.map((step)=>step.row ?? 0));
|
|
604
|
+
}
|
|
605
|
+
return {
|
|
606
|
+
name: entity.label.slice(0, MAX_NAME_LENGTH),
|
|
607
|
+
slug: entityFlowSlug(entity.code),
|
|
608
|
+
isActive: true,
|
|
609
|
+
nodes,
|
|
610
|
+
edges
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
615
|
+
CO: () => (buildEntityFlow)
|
|
616
|
+
}, {
|
|
617
|
+
IP: ENTITY_FLOW_PATHS,
|
|
618
|
+
x2: entityFlowSlug
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
},
|
|
623
|
+
1462(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
624
|
+
/* import */ var _flusys_nestjs_shared__rspack_import_0 = __webpack_require__(3422);
|
|
625
|
+
/* import */ var _nestjs_common__rspack_import_1 = __webpack_require__(6157);
|
|
626
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
627
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
628
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
629
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
630
|
+
} else {
|
|
631
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
632
|
+
if (d = decorators[i]) {
|
|
633
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
638
|
+
}
|
|
639
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
640
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
641
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
function _ts_param(paramIndex, decorator) {
|
|
645
|
+
return function(target, key) {
|
|
646
|
+
decorator(target, key, paramIndex);
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
const CRUD_ACTIONS = [
|
|
652
|
+
'create',
|
|
653
|
+
'read',
|
|
654
|
+
'update',
|
|
655
|
+
'delete'
|
|
656
|
+
];
|
|
657
|
+
class EntityPermissionService {
|
|
658
|
+
actionRegistry;
|
|
659
|
+
constructor(actionRegistry){
|
|
660
|
+
this.actionRegistry = actionRegistry;
|
|
661
|
+
}
|
|
662
|
+
async provisionForEntity(definition) {
|
|
663
|
+
if (!this.actionRegistry) return;
|
|
664
|
+
const parentCode = (0,_flusys_nestjs_shared__rspack_import_0.dynamicEntityPermissionParent)(definition.code);
|
|
665
|
+
await this.actionRegistry.registerActions(CRUD_ACTIONS.map((op)=>({
|
|
666
|
+
code: (0,_flusys_nestjs_shared__rspack_import_0.dynamicEntityPermission)(definition.code, op),
|
|
667
|
+
name: `${definition.label} - ${op}`,
|
|
668
|
+
parentCode,
|
|
669
|
+
actionType: 'BACKEND'
|
|
670
|
+
})));
|
|
671
|
+
}
|
|
672
|
+
async deprovisionForEntity(definition) {
|
|
673
|
+
if (!this.actionRegistry) return;
|
|
674
|
+
await this.actionRegistry.removeActionsByCodes([
|
|
675
|
+
(0,_flusys_nestjs_shared__rspack_import_0.dynamicEntityPermissionParent)(definition.code),
|
|
676
|
+
...CRUD_ACTIONS.map((op)=>(0,_flusys_nestjs_shared__rspack_import_0.dynamicEntityPermission)(definition.code, op))
|
|
677
|
+
]);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
EntityPermissionService = _ts_decorate([
|
|
681
|
+
(0,_nestjs_common__rspack_import_1.Injectable)(),
|
|
682
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_1.Optional)()),
|
|
683
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_1.Inject)(_flusys_nestjs_shared__rspack_import_0.PERMISSION_ACTION_REGISTRY)),
|
|
684
|
+
_ts_metadata("design:type", Function),
|
|
685
|
+
_ts_metadata("design:paramtypes", [
|
|
686
|
+
typeof IPermissionActionRegistry === "undefined" ? Object : IPermissionActionRegistry
|
|
687
|
+
])
|
|
688
|
+
], EntityPermissionService);
|
|
689
|
+
|
|
690
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
691
|
+
u: () => (EntityPermissionService)
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
},
|
|
696
|
+
9487(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
697
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
698
|
+
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(1236);
|
|
699
|
+
/* import */ var _nestjs_common__rspack_import_2 = __webpack_require__(6157);
|
|
700
|
+
/* import */ var _config_event_actions_js__rspack_import_5 = __webpack_require__(982);
|
|
701
|
+
/* import */ var _entities_field_definition_entity_js__rspack_import_3 = __webpack_require__(2206);
|
|
702
|
+
/* import */ var _entity_builder_datasource_provider_js__rspack_import_4 = __webpack_require__(424);
|
|
703
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
704
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
705
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
706
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
707
|
+
} else {
|
|
708
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
709
|
+
if (d = decorators[i]) {
|
|
710
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
715
|
+
}
|
|
716
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
717
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
718
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
function _ts_param(paramIndex, decorator) {
|
|
722
|
+
return function(target, key) {
|
|
723
|
+
decorator(target, key, paramIndex);
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
class FieldDefinitionService extends _flusys_nestjs_shared_classes__rspack_import_0.ApiService {
|
|
733
|
+
cacheManager;
|
|
734
|
+
utilsService;
|
|
735
|
+
constructor(cacheManager, utilsService, dataSourceProvider){
|
|
736
|
+
super(_config_event_actions_js__rspack_import_5/* .ENTITY_BUILDER_EVENT_ENTITIES.FIELD_DEFINITION */.P.FIELD_DEFINITION, cacheManager, utilsService, FieldDefinitionService.name, true, _config_event_actions_js__rspack_import_5/* .ENTITY_BUILDER_EVENT_MODULE */.S, dataSourceProvider, _entities_field_definition_entity_js__rspack_import_3/* .FieldDefinition */.c), this.cacheManager = cacheManager, this.utilsService = utilsService;
|
|
737
|
+
}
|
|
738
|
+
// Schema changes send the loaded `updatedAt` back as `expectedUpdatedAt`; Identity hides it by default.
|
|
739
|
+
async getSelectQuery(query, user, select) {
|
|
740
|
+
const result = await super.getSelectQuery(query, user, select);
|
|
741
|
+
result.query.addSelect(`${this.entityName}.updatedAt`);
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
FieldDefinitionService = _ts_decorate([
|
|
746
|
+
(0,_nestjs_common__rspack_import_2.Injectable)({
|
|
747
|
+
scope: _nestjs_common__rspack_import_2.Scope.REQUEST
|
|
748
|
+
}),
|
|
749
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_2.Inject)('CACHE_INSTANCE')),
|
|
750
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_2.Inject)(_flusys_nestjs_shared_modules__rspack_import_1.UtilsService)),
|
|
751
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_2.Inject)(_entity_builder_datasource_provider_js__rspack_import_4/* .EntityBuilderDataSourceProvider */.D)),
|
|
752
|
+
_ts_metadata("design:type", Function),
|
|
753
|
+
_ts_metadata("design:paramtypes", [
|
|
754
|
+
typeof _flusys_nestjs_shared_classes__rspack_import_0.HybridCache === "undefined" ? Object : _flusys_nestjs_shared_classes__rspack_import_0.HybridCache,
|
|
755
|
+
typeof _flusys_nestjs_shared_modules__rspack_import_1.UtilsService === "undefined" ? Object : _flusys_nestjs_shared_modules__rspack_import_1.UtilsService,
|
|
756
|
+
typeof _entity_builder_datasource_provider_js__rspack_import_4/* .EntityBuilderDataSourceProvider */.D === "undefined" ? Object : _entity_builder_datasource_provider_js__rspack_import_4/* .EntityBuilderDataSourceProvider */.D
|
|
757
|
+
])
|
|
758
|
+
], FieldDefinitionService);
|
|
759
|
+
|
|
760
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
761
|
+
J: () => (FieldDefinitionService)
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
},
|
|
766
|
+
4984(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
767
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_0 = __webpack_require__(9216);
|
|
768
|
+
/* import */ var _config_message_keys_js__rspack_import_2 = __webpack_require__(5732);
|
|
769
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_1 = __webpack_require__(9614);
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
const TEXT_LIKE = new Set([
|
|
774
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.TEXT */.P.TEXT,
|
|
775
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.EMAIL */.P.EMAIL,
|
|
776
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT
|
|
777
|
+
]);
|
|
778
|
+
const SCALAR_TO_TEXT = new Set([
|
|
779
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER,
|
|
780
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL,
|
|
781
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.BOOLEAN */.P.BOOLEAN,
|
|
782
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.DATE */.P.DATE,
|
|
783
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.DATETIME */.P.DATETIME
|
|
784
|
+
]);
|
|
785
|
+
const EMAIL_PG = `'^[^[:space:]@]+@[^[:space:]@]+\\.[^[:space:]@]+$'`;
|
|
786
|
+
const regexFail = (column, driver, pattern)=>driver === 'postgres' ? `${column} !~ '${pattern}'` : `${column} NOT REGEXP '${pattern}'`;
|
|
787
|
+
const SELECT_KINDS = new Set([
|
|
788
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT,
|
|
789
|
+
_enums_field_type_enum_js__rspack_import_1/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT
|
|
790
|
+
]);
|
|
791
|
+
const unsupported = (from, to)=>({
|
|
792
|
+
supported: false,
|
|
793
|
+
prechecks: [],
|
|
794
|
+
reason: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_BLOCKER_MESSAGES.CONVERSION_UNSUPPORTED */.M3.CONVERSION_UNSUPPORTED, {
|
|
795
|
+
from,
|
|
796
|
+
to
|
|
797
|
+
})
|
|
798
|
+
});
|
|
799
|
+
function planTypeConversion(from, to, driver) {
|
|
800
|
+
if (from === to) return {
|
|
801
|
+
supported: true,
|
|
802
|
+
noDbChange: true,
|
|
803
|
+
prechecks: []
|
|
804
|
+
};
|
|
805
|
+
// MySQL has no USING clause: MODIFY casts implicitly, which rejects text as JSON or boolean and would keep a JSON array as its text.
|
|
806
|
+
const textLike = TEXT_LIKE.has(from) || from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.LONG_TEXT */.P.LONG_TEXT;
|
|
807
|
+
if (driver === 'mysql' && (SELECT_KINDS.has(from) && SELECT_KINDS.has(to) || textLike && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.BOOLEAN */.P.BOOLEAN)) return unsupported(from, to);
|
|
808
|
+
// Same physical column (varchar(255)): only the meaning changes.
|
|
809
|
+
if (TEXT_LIKE.has(from) && TEXT_LIKE.has(to)) {
|
|
810
|
+
const checks = [];
|
|
811
|
+
if (to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.EMAIL */.P.EMAIL) {
|
|
812
|
+
checks.push({
|
|
813
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_EMAIL */.NE.NOT_EMAIL),
|
|
814
|
+
badRowsWhere: (c, d)=>d === 'postgres' ? `${c} !~ ${EMAIL_PG}` : `${c} NOT REGEXP '^[^ @]+@[^ @]+\\\\.[^ @]+$'`
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
return {
|
|
818
|
+
supported: true,
|
|
819
|
+
noDbChange: true,
|
|
820
|
+
prechecks: checks
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.RELATION */.P.RELATION && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.FILE */.P.FILE || from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.FILE */.P.FILE && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.RELATION */.P.RELATION) {
|
|
824
|
+
return {
|
|
825
|
+
supported: true,
|
|
826
|
+
noDbChange: true,
|
|
827
|
+
prechecks: []
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
// -> LONG_TEXT (text): widening from everything scalar/text-like
|
|
831
|
+
if (to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.LONG_TEXT */.P.LONG_TEXT && (TEXT_LIKE.has(from) || SCALAR_TO_TEXT.has(from))) {
|
|
832
|
+
return {
|
|
833
|
+
supported: true,
|
|
834
|
+
using: (c)=>`${c}::text`,
|
|
835
|
+
prechecks: []
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
// LONG_TEXT -> varchar(255) kinds: narrowing, blocked if any value is too long
|
|
839
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.LONG_TEXT */.P.LONG_TEXT && TEXT_LIKE.has(to)) {
|
|
840
|
+
const checks = [
|
|
841
|
+
{
|
|
842
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.TOO_LONG */.NE.TOO_LONG),
|
|
843
|
+
badRowsWhere: (c, d)=>d === 'postgres' ? `char_length(${c}) > 255` : `CHAR_LENGTH(${c}) > 255`
|
|
844
|
+
}
|
|
845
|
+
];
|
|
846
|
+
if (to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.EMAIL */.P.EMAIL) {
|
|
847
|
+
checks.push({
|
|
848
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_EMAIL */.NE.NOT_EMAIL),
|
|
849
|
+
badRowsWhere: (c, d)=>d === 'postgres' ? `${c} !~ ${EMAIL_PG}` : `${c} NOT REGEXP '^[^ @]+@[^ @]+\\\\.[^ @]+$'`
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
return {
|
|
853
|
+
supported: true,
|
|
854
|
+
using: (c)=>`${c}::varchar(255)`,
|
|
855
|
+
prechecks: checks
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
// scalar -> text-like: always representable
|
|
859
|
+
if (SCALAR_TO_TEXT.has(from) && TEXT_LIKE.has(to)) {
|
|
860
|
+
const checks = [];
|
|
861
|
+
if (to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.EMAIL */.P.EMAIL) {
|
|
862
|
+
checks.push({
|
|
863
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_EMAIL */.NE.NOT_EMAIL),
|
|
864
|
+
badRowsWhere: (c, d)=>d === 'postgres' ? `${c}::text !~ ${EMAIL_PG}` : `CAST(${c} AS CHAR) NOT REGEXP '^[^ @]+@[^ @]+\\\\.[^ @]+$'`
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
return {
|
|
868
|
+
supported: true,
|
|
869
|
+
using: (c)=>`${c}::text`,
|
|
870
|
+
prechecks: checks
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
// text-like / long text -> scalar: every existing value must parse
|
|
874
|
+
if (textLike) {
|
|
875
|
+
switch(to){
|
|
876
|
+
case _enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER:
|
|
877
|
+
return {
|
|
878
|
+
supported: true,
|
|
879
|
+
using: (c)=>`${c}::integer`,
|
|
880
|
+
prechecks: [
|
|
881
|
+
{
|
|
882
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_WHOLE_NUMBER */.NE.NOT_WHOLE_NUMBER),
|
|
883
|
+
badRowsWhere: (c, d)=>regexFail(c, d, '^-?[0-9]{1,10}$')
|
|
884
|
+
}
|
|
885
|
+
]
|
|
886
|
+
};
|
|
887
|
+
case _enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL:
|
|
888
|
+
return {
|
|
889
|
+
supported: true,
|
|
890
|
+
using: (c)=>`${c}::numeric(18,4)`,
|
|
891
|
+
prechecks: [
|
|
892
|
+
{
|
|
893
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_NUMBER */.NE.NOT_NUMBER),
|
|
894
|
+
badRowsWhere: (c, d)=>regexFail(c, d, '^-?[0-9]{1,14}(\\.[0-9]+)?$')
|
|
895
|
+
}
|
|
896
|
+
]
|
|
897
|
+
};
|
|
898
|
+
case _enums_field_type_enum_js__rspack_import_1/* .FieldType.BOOLEAN */.P.BOOLEAN:
|
|
899
|
+
return {
|
|
900
|
+
supported: true,
|
|
901
|
+
using: (c)=>`(lower(${c}))::boolean`,
|
|
902
|
+
prechecks: [
|
|
903
|
+
{
|
|
904
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_BOOLEAN_TEXT */.NE.NOT_BOOLEAN_TEXT),
|
|
905
|
+
badRowsWhere: (c)=>`lower(${c}) NOT IN ('true','false')`
|
|
906
|
+
}
|
|
907
|
+
]
|
|
908
|
+
};
|
|
909
|
+
case _enums_field_type_enum_js__rspack_import_1/* .FieldType.DATE */.P.DATE:
|
|
910
|
+
return {
|
|
911
|
+
supported: true,
|
|
912
|
+
using: (c)=>`${c}::date`,
|
|
913
|
+
prechecks: [
|
|
914
|
+
{
|
|
915
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_DATE */.NE.NOT_DATE),
|
|
916
|
+
badRowsWhere: (c, d)=>regexFail(c, d, '^[0-9]{4}-[0-9]{2}-[0-9]{2}$')
|
|
917
|
+
}
|
|
918
|
+
]
|
|
919
|
+
};
|
|
920
|
+
case _enums_field_type_enum_js__rspack_import_1/* .FieldType.DATETIME */.P.DATETIME:
|
|
921
|
+
return {
|
|
922
|
+
supported: true,
|
|
923
|
+
using: (c)=>`${c}::timestamptz`,
|
|
924
|
+
prechecks: [
|
|
925
|
+
{
|
|
926
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_DATETIME */.NE.NOT_DATETIME),
|
|
927
|
+
badRowsWhere: (c, d)=>regexFail(c, d, d === 'postgres' ? '^[0-9]{4}-[0-9]{2}-[0-9]{2}([T ][0-9:.]+)?(Z|[+-][0-9:]+)?$' : '^[0-9]{4}-[0-9]{2}-[0-9]{2}([T ][0-9]{2}:[0-9]{2}(:[0-9]{2}(\\.[0-9]+)?)?)?$')
|
|
928
|
+
}
|
|
929
|
+
]
|
|
930
|
+
};
|
|
931
|
+
default:
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
// numeric conversions
|
|
936
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL) return {
|
|
937
|
+
supported: true,
|
|
938
|
+
using: (c)=>`${c}::numeric(18,4)`,
|
|
939
|
+
prechecks: []
|
|
940
|
+
};
|
|
941
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER) {
|
|
942
|
+
return {
|
|
943
|
+
supported: true,
|
|
944
|
+
using: (c)=>`round(${c})::integer`,
|
|
945
|
+
lossy: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_WARNING_MESSAGES.LOSSY_ROUNDING */.Uu.LOSSY_ROUNDING),
|
|
946
|
+
prechecks: [
|
|
947
|
+
{
|
|
948
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.OUT_OF_INTEGER_RANGE */.NE.OUT_OF_INTEGER_RANGE),
|
|
949
|
+
badRowsWhere: (c)=>`abs(${c}) > 2147483647`
|
|
950
|
+
}
|
|
951
|
+
]
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
if ((from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER || from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL) && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.BOOLEAN */.P.BOOLEAN) {
|
|
955
|
+
return {
|
|
956
|
+
supported: true,
|
|
957
|
+
using: (c)=>`(${c} <> 0)`,
|
|
958
|
+
prechecks: [
|
|
959
|
+
{
|
|
960
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.NOT_ZERO_OR_ONE */.NE.NOT_ZERO_OR_ONE),
|
|
961
|
+
badRowsWhere: (c)=>`${c} NOT IN (0,1)`
|
|
962
|
+
}
|
|
963
|
+
]
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.BOOLEAN */.P.BOOLEAN && (to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER || to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DECIMAL */.P.DECIMAL)) {
|
|
967
|
+
return {
|
|
968
|
+
supported: true,
|
|
969
|
+
using: (c)=>to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.INTEGER */.P.INTEGER ? `${c}::integer` : `${c}::integer::numeric(18,4)`,
|
|
970
|
+
prechecks: []
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
// dates
|
|
974
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DATE */.P.DATE && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DATETIME */.P.DATETIME) return {
|
|
975
|
+
supported: true,
|
|
976
|
+
using: (c)=>`${c}::timestamptz`,
|
|
977
|
+
prechecks: []
|
|
978
|
+
};
|
|
979
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DATETIME */.P.DATETIME && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.DATE */.P.DATE) {
|
|
980
|
+
return {
|
|
981
|
+
supported: true,
|
|
982
|
+
using: (c)=>`${c}::date`,
|
|
983
|
+
lossy: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_WARNING_MESSAGES.LOSSY_TIME_DROPPED */.Uu.LOSSY_TIME_DROPPED),
|
|
984
|
+
prechecks: []
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
// select <-> multi select
|
|
988
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT) {
|
|
989
|
+
return {
|
|
990
|
+
supported: true,
|
|
991
|
+
using: (c)=>`CASE WHEN ${c} IS NULL THEN NULL ELSE jsonb_build_array(${c}) END`,
|
|
992
|
+
prechecks: []
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
if (from === _enums_field_type_enum_js__rspack_import_1/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT && to === _enums_field_type_enum_js__rspack_import_1/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT) {
|
|
996
|
+
return {
|
|
997
|
+
supported: true,
|
|
998
|
+
using: (c)=>`${c}->>0`,
|
|
999
|
+
prechecks: [
|
|
1000
|
+
{
|
|
1001
|
+
description: (0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .SCHEMA_PRECHECK_MESSAGES.MULTIPLE_SELECTED */.NE.MULTIPLE_SELECTED),
|
|
1002
|
+
badRowsWhere: (c)=>`jsonb_array_length(${c}) > 1`
|
|
1003
|
+
}
|
|
1004
|
+
]
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
return unsupported(from, to);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1011
|
+
I: () => (planTypeConversion)
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
},
|
|
1016
|
+
413(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1017
|
+
/* import */ var _nestjs_common__rspack_import_0 = __webpack_require__(6157);
|
|
1018
|
+
/* import */ var _config_message_keys_js__rspack_import_3 = __webpack_require__(5732);
|
|
1019
|
+
/* import */ var _config_entity_builder_constants_js__rspack_import_2 = __webpack_require__(6576);
|
|
1020
|
+
/* import */ var _config_event_actions_js__rspack_import_4 = __webpack_require__(982);
|
|
1021
|
+
/* import */ var _schema_columns_js__rspack_import_1 = __webpack_require__(5313);
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* SQL reserved words relevant to table/column identifiers (ANSI/Postgres/MySQL keywords most
|
|
1029
|
+
* likely to collide with a user-chosen code). Not exhaustive - the `eb_` table prefix, the
|
|
1030
|
+
* identifier pattern and the live "table exists" check are defense in depth.
|
|
1031
|
+
*/ const RESERVED_WORDS = new Set([
|
|
1032
|
+
'select',
|
|
1033
|
+
'insert',
|
|
1034
|
+
'update',
|
|
1035
|
+
'delete',
|
|
1036
|
+
'from',
|
|
1037
|
+
'where',
|
|
1038
|
+
'table',
|
|
1039
|
+
'index',
|
|
1040
|
+
'key',
|
|
1041
|
+
'primary',
|
|
1042
|
+
'foreign',
|
|
1043
|
+
'references',
|
|
1044
|
+
'default',
|
|
1045
|
+
'null',
|
|
1046
|
+
'true',
|
|
1047
|
+
'false',
|
|
1048
|
+
'user',
|
|
1049
|
+
'role',
|
|
1050
|
+
'grant',
|
|
1051
|
+
'revoke',
|
|
1052
|
+
'database',
|
|
1053
|
+
'schema',
|
|
1054
|
+
'view',
|
|
1055
|
+
'trigger',
|
|
1056
|
+
'function',
|
|
1057
|
+
'procedure',
|
|
1058
|
+
'constraint',
|
|
1059
|
+
'unique',
|
|
1060
|
+
'check',
|
|
1061
|
+
'and',
|
|
1062
|
+
'or',
|
|
1063
|
+
'not',
|
|
1064
|
+
'in',
|
|
1065
|
+
'exists',
|
|
1066
|
+
'between',
|
|
1067
|
+
'like',
|
|
1068
|
+
'is',
|
|
1069
|
+
'as',
|
|
1070
|
+
'on',
|
|
1071
|
+
'into',
|
|
1072
|
+
'values',
|
|
1073
|
+
'set',
|
|
1074
|
+
'alter',
|
|
1075
|
+
'drop',
|
|
1076
|
+
'create',
|
|
1077
|
+
'cascade',
|
|
1078
|
+
'limit',
|
|
1079
|
+
'offset',
|
|
1080
|
+
'union',
|
|
1081
|
+
'all',
|
|
1082
|
+
'distinct',
|
|
1083
|
+
'having',
|
|
1084
|
+
'case',
|
|
1085
|
+
'when',
|
|
1086
|
+
'then',
|
|
1087
|
+
'else',
|
|
1088
|
+
'end',
|
|
1089
|
+
'order',
|
|
1090
|
+
'group',
|
|
1091
|
+
'by',
|
|
1092
|
+
'join',
|
|
1093
|
+
'left',
|
|
1094
|
+
'right',
|
|
1095
|
+
'inner',
|
|
1096
|
+
'outer',
|
|
1097
|
+
'id'
|
|
1098
|
+
]);
|
|
1099
|
+
/** Throws a 400 with a specific reason if `code` cannot safely be a table/column identifier. */ function assertValidIdentifier(code, kind) {
|
|
1100
|
+
if (!_config_entity_builder_constants_js__rspack_import_2/* .ENTITY_CODE_PATTERN.test */.vs.test(code) || code.length > (/* inlined export .ENTITY_CODE_MAX_LENGTH */63)) {
|
|
1101
|
+
throw new _nestjs_common__rspack_import_0.BadRequestException({
|
|
1102
|
+
message: `'${code}' is not a valid ${kind} code. Use lowercase letters, digits and underscores, starting with a letter (3-60 characters).`,
|
|
1103
|
+
messageKey: _config_message_keys_js__rspack_import_3/* .SCHEMA_MESSAGES.INVALID_CODE_PATTERN */.Hu.INVALID_CODE_PATTERN,
|
|
1104
|
+
messageVariables: {
|
|
1105
|
+
code,
|
|
1106
|
+
kind
|
|
1107
|
+
}
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
// An entity's events are published as entity-builder.<code>.*, so it cannot share a name with
|
|
1111
|
+
// the module's own definition events.
|
|
1112
|
+
const reservedForKind = kind === 'entity' && Object.values(_config_event_actions_js__rspack_import_4/* .ENTITY_BUILDER_EVENT_ENTITIES */.P).includes(code);
|
|
1113
|
+
if (RESERVED_WORDS.has(code.toLowerCase()) || reservedForKind) {
|
|
1114
|
+
throw new _nestjs_common__rspack_import_0.BadRequestException({
|
|
1115
|
+
message: `'${code}' is a reserved word and cannot be used as a ${kind} code.`,
|
|
1116
|
+
messageKey: _config_message_keys_js__rspack_import_3/* .SCHEMA_MESSAGES.RESERVED_WORD */.Hu.RESERVED_WORD,
|
|
1117
|
+
messageVariables: {
|
|
1118
|
+
code,
|
|
1119
|
+
kind
|
|
1120
|
+
}
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
if (kind === 'field' && _schema_columns_js__rspack_import_1/* .SYSTEM_COLUMN_NAMES.includes */.mq.includes(code)) {
|
|
1124
|
+
throw new _nestjs_common__rspack_import_0.BadRequestException({
|
|
1125
|
+
message: `'${code}' is a system column and cannot be used as a field code.`,
|
|
1126
|
+
messageKey: _config_message_keys_js__rspack_import_3/* .SCHEMA_MESSAGES.SYSTEM_COLUMN_CODE */.Hu.SYSTEM_COLUMN_CODE,
|
|
1127
|
+
messageVariables: {
|
|
1128
|
+
code
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
/** Throws a 400 when a long text / JSON / multi select field is made unique or indexed. */ function assertIndexableField(field) {
|
|
1134
|
+
if ((field.unique === true || field.isIndexed === true) && !(0,_schema_columns_js__rspack_import_1/* .isIndexableFieldType */.d4)(field.fieldType)) {
|
|
1135
|
+
throw new _nestjs_common__rspack_import_0.BadRequestException({
|
|
1136
|
+
message: `'${field.code}' is a ${field.fieldType} field, which cannot be unique or indexed.`,
|
|
1137
|
+
messageKey: _config_message_keys_js__rspack_import_3/* .SCHEMA_MESSAGES.NOT_INDEXABLE */.Hu.NOT_INDEXABLE,
|
|
1138
|
+
messageVariables: {
|
|
1139
|
+
field: field.code,
|
|
1140
|
+
fieldType: field.fieldType
|
|
1141
|
+
}
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1147
|
+
fY: () => (assertIndexableField),
|
|
1148
|
+
kV: () => (assertValidIdentifier)
|
|
1149
|
+
}, {
|
|
1150
|
+
xJ: RESERVED_WORDS
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
},
|
|
1155
|
+
921(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1156
|
+
/* import */ var _nestjs_common__rspack_import_0 = __webpack_require__(6157);
|
|
1157
|
+
/* import */ var _interfaces_reference_provider_interface_js__rspack_import_1 = __webpack_require__(2492);
|
|
1158
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
1159
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1160
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
1161
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1162
|
+
} else {
|
|
1163
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
1164
|
+
if (d = decorators[i]) {
|
|
1165
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1170
|
+
}
|
|
1171
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
1172
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
1173
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
function _ts_param(paramIndex, decorator) {
|
|
1177
|
+
return function(target, key) {
|
|
1178
|
+
decorator(target, key, paramIndex);
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
class ReferenceScannerService {
|
|
1184
|
+
flowReferences;
|
|
1185
|
+
constructor(flowReferences){
|
|
1186
|
+
this.flowReferences = flowReferences;
|
|
1187
|
+
}
|
|
1188
|
+
async forEntity(entityCode) {
|
|
1189
|
+
return this.flowReferences ? this.flowReferences.findEntityReferences(entityCode) : [];
|
|
1190
|
+
}
|
|
1191
|
+
async forField(entityCode, fieldCode) {
|
|
1192
|
+
return this.flowReferences ? this.flowReferences.findFieldReferences(entityCode, fieldCode) : [];
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Rewrites every reference after a field rename. Pass the schema change's own `manager` so
|
|
1196
|
+
* the rewrite is part of the same transaction. Returns how many definitions changed.
|
|
1197
|
+
*/ async rewriteFieldCode(entityCode, from, to, manager) {
|
|
1198
|
+
return this.flowReferences ? this.flowReferences.rewriteFieldReferences(entityCode, from, to, manager) : 0;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
ReferenceScannerService = _ts_decorate([
|
|
1202
|
+
(0,_nestjs_common__rspack_import_0.Injectable)({
|
|
1203
|
+
scope: _nestjs_common__rspack_import_0.Scope.REQUEST
|
|
1204
|
+
}),
|
|
1205
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_0.Optional)()),
|
|
1206
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_0.Inject)(_interfaces_reference_provider_interface_js__rspack_import_1/* .FLOW_REFERENCE_PROVIDER */.$)),
|
|
1207
|
+
_ts_metadata("design:type", Function),
|
|
1208
|
+
_ts_metadata("design:paramtypes", [
|
|
1209
|
+
typeof IEntityReferenceProvider === "undefined" ? Object : IEntityReferenceProvider
|
|
1210
|
+
])
|
|
1211
|
+
], ReferenceScannerService);
|
|
1212
|
+
|
|
1213
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1214
|
+
t: () => (ReferenceScannerService)
|
|
1215
|
+
});
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
},
|
|
1219
|
+
6605(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1220
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_0 = __webpack_require__(9216);
|
|
1221
|
+
/* import */ var _nestjs_common__rspack_import_1 = __webpack_require__(6157);
|
|
1222
|
+
/* import */ var typeorm__rspack_import_2 = __webpack_require__(7158);
|
|
1223
|
+
/* import */ var _config_message_keys_js__rspack_import_11 = __webpack_require__(5732);
|
|
1224
|
+
/* import */ var _flow_engine_flow_errors_js__rspack_import_3 = __webpack_require__(8542);
|
|
1225
|
+
/* import */ var _entities_entity_definition_entity_js__rspack_import_4 = __webpack_require__(3189);
|
|
1226
|
+
/* import */ var _entities_schema_change_log_entity_js__rspack_import_5 = __webpack_require__(875);
|
|
1227
|
+
/* import */ var _enums_ddl_operation_enum_js__rspack_import_12 = __webpack_require__(9949);
|
|
1228
|
+
/* import */ var _database_error_mapper_js__rspack_import_6 = __webpack_require__(8323);
|
|
1229
|
+
/* import */ var _definition_cache_service_js__rspack_import_7 = __webpack_require__(2931);
|
|
1230
|
+
/* import */ var _entity_builder_datasource_provider_js__rspack_import_8 = __webpack_require__(424);
|
|
1231
|
+
/* import */ var _schema_dialect_adapter_service_js__rspack_import_9 = __webpack_require__(7259);
|
|
1232
|
+
/* import */ var _schema_registry_service_js__rspack_import_10 = __webpack_require__(2134);
|
|
1233
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
1234
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1235
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
1236
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1237
|
+
} else {
|
|
1238
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
1239
|
+
if (d = decorators[i]) {
|
|
1240
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1245
|
+
}
|
|
1246
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
1247
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
1248
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
function _ts_param(paramIndex, decorator) {
|
|
1252
|
+
return function(target, key) {
|
|
1253
|
+
decorator(target, key, paramIndex);
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
/** Codes of the entities `ids` point at: locked with a change, so none of them can be dropped meanwhile. */ async function relationTargetCodes(provider, ids) {
|
|
1270
|
+
const unique = [
|
|
1271
|
+
...new Set(ids.filter((id)=>!!id))
|
|
1272
|
+
];
|
|
1273
|
+
if (!unique.length) return [];
|
|
1274
|
+
const targets = await (await provider.getRepository(_entities_entity_definition_entity_js__rspack_import_4/* .EntityDefinition */.f)).find({
|
|
1275
|
+
select: {
|
|
1276
|
+
id: true,
|
|
1277
|
+
code: true
|
|
1278
|
+
},
|
|
1279
|
+
where: {
|
|
1280
|
+
id: (0,typeorm__rspack_import_2.In)(unique)
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1283
|
+
return targets.map((t)=>t.code);
|
|
1284
|
+
}
|
|
1285
|
+
const hasMessage = (list, message)=>list.some((m)=>JSON.stringify(m) === JSON.stringify(message));
|
|
1286
|
+
const isReadOrSession = (sql)=>/^\s*(SELECT|SET|SHOW|BEGIN|COMMIT|ROLLBACK|START)/i.test(sql);
|
|
1287
|
+
const formatSql = (sql, params)=>params?.length ? `${sql.trim()} -- params: ${JSON.stringify(params)}` : sql.trim();
|
|
1288
|
+
const format = (statement)=>formatSql(statement.query, statement.parameters);
|
|
1289
|
+
class SchemaChangeExecutor {
|
|
1290
|
+
dataSourceProvider;
|
|
1291
|
+
dialectAdapter;
|
|
1292
|
+
schemaRegistry;
|
|
1293
|
+
definitionCache;
|
|
1294
|
+
logger = new _nestjs_common__rspack_import_1.Logger(SchemaChangeExecutor.name);
|
|
1295
|
+
constructor(dataSourceProvider, dialectAdapter, schemaRegistry, definitionCache){
|
|
1296
|
+
this.dataSourceProvider = dataSourceProvider;
|
|
1297
|
+
this.dialectAdapter = dialectAdapter;
|
|
1298
|
+
this.schemaRegistry = schemaRegistry;
|
|
1299
|
+
this.definitionCache = definitionCache;
|
|
1300
|
+
}
|
|
1301
|
+
async simulate(target, run, impact = []) {
|
|
1302
|
+
const driver = await this.dataSourceProvider.getDriver();
|
|
1303
|
+
// A dedicated connection: memory mode also mutates TypeORM's cached table metadata, which
|
|
1304
|
+
// must never leak into the connection that later applies the change for real.
|
|
1305
|
+
const qr = await this.dataSourceProvider.getQueryRunner();
|
|
1306
|
+
await qr.connect();
|
|
1307
|
+
qr.enableSqlMemory();
|
|
1308
|
+
const state = this.newState(target, impact);
|
|
1309
|
+
try {
|
|
1310
|
+
const ctx = this.buildContext(qr, driver, true, state);
|
|
1311
|
+
await run(ctx);
|
|
1312
|
+
if (driver === 'mysql' && state.steps.some((s)=>s.sql.length > 0)) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_11/* .SCHEMA_WARNING_MESSAGES.MYSQL_NO_ROLLBACK */.Uu.MYSQL_NO_ROLLBACK));
|
|
1313
|
+
return this.toPlan(target, state);
|
|
1314
|
+
} finally{
|
|
1315
|
+
qr.disableSqlMemory();
|
|
1316
|
+
await qr.release();
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
async apply(target, run, options = {}) {
|
|
1320
|
+
const plan = await this.simulate(target, run, options.impact ?? []);
|
|
1321
|
+
if (plan.blockers.length > 0) {
|
|
1322
|
+
throw new _nestjs_common__rspack_import_1.ConflictException({
|
|
1323
|
+
message: 'This change cannot be applied.',
|
|
1324
|
+
messageKey: _config_message_keys_js__rspack_import_11/* .SCHEMA_MESSAGES.BLOCKED */.Hu.BLOCKED,
|
|
1325
|
+
blockers: plan.blockers,
|
|
1326
|
+
plan
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
if (plan.destructive && !options.confirm) {
|
|
1330
|
+
throw new _nestjs_common__rspack_import_1.BadRequestException({
|
|
1331
|
+
message: 'This change loses data or information. Review the plan and resend with confirm: true.',
|
|
1332
|
+
messageKey: _config_message_keys_js__rspack_import_11/* .SCHEMA_MESSAGES.CONFIRMATION_REQUIRED */.Hu.CONFIRMATION_REQUIRED,
|
|
1333
|
+
plan
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
const driver = await this.dataSourceProvider.getDriver();
|
|
1337
|
+
// Sorted, so two changes that lock the same entities always take them in the same order.
|
|
1338
|
+
const lockKeys = [
|
|
1339
|
+
...new Set([
|
|
1340
|
+
target.entityCode,
|
|
1341
|
+
...target.lockCodes ?? []
|
|
1342
|
+
])
|
|
1343
|
+
].toSorted().map((code)=>`eb_entity:${code}`);
|
|
1344
|
+
const heldLocks = [];
|
|
1345
|
+
const qr = await this.dataSourceProvider.getQueryRunner();
|
|
1346
|
+
await qr.connect();
|
|
1347
|
+
await qr.startTransaction();
|
|
1348
|
+
const state = this.newState(target, options.impact ?? []);
|
|
1349
|
+
let committed = false;
|
|
1350
|
+
try {
|
|
1351
|
+
for (const key of lockKeys){
|
|
1352
|
+
await this.dialectAdapter.acquireEntityLock(qr, key, driver);
|
|
1353
|
+
heldLocks.push(key);
|
|
1354
|
+
}
|
|
1355
|
+
const ctx = this.buildContext(qr, driver, false, state);
|
|
1356
|
+
const outcome = await run(ctx);
|
|
1357
|
+
if (state.blockers.length > 0) {
|
|
1358
|
+
// The data changed between the dry-run and the lock - re-checked under the lock.
|
|
1359
|
+
throw new _nestjs_common__rspack_import_1.ConflictException({
|
|
1360
|
+
message: 'This change can no longer be applied.',
|
|
1361
|
+
messageKey: _config_message_keys_js__rspack_import_11/* .SCHEMA_MESSAGES.NO_LONGER_APPLICABLE */.Hu.NO_LONGER_APPLICABLE,
|
|
1362
|
+
blockers: state.blockers
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
if (target.entityDefinitionId && outcome.bumpVersion !== false) {
|
|
1366
|
+
const repo = qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_4/* .EntityDefinition */.f);
|
|
1367
|
+
const current = await repo.findOne({
|
|
1368
|
+
where: {
|
|
1369
|
+
id: target.entityDefinitionId
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
if (current) await repo.update(current.id, {
|
|
1373
|
+
schemaVersion: current.schemaVersion + 1
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
await qr.manager.save(_entities_schema_change_log_entity_js__rspack_import_5/* .SchemaChangeLog */.W, qr.manager.getRepository(_entities_schema_change_log_entity_js__rspack_import_5/* .SchemaChangeLog */.W).create({
|
|
1377
|
+
entityDefinitionId: outcome.entityDefinitionId ?? target.entityDefinitionId,
|
|
1378
|
+
entityCode: target.entityCode,
|
|
1379
|
+
operation: outcome.operation,
|
|
1380
|
+
tableName: target.tableName,
|
|
1381
|
+
fieldDefinitionId: outcome.fieldDefinitionId ?? null,
|
|
1382
|
+
diff: outcome.diff,
|
|
1383
|
+
generatedSql: state.steps.flatMap((s)=>s.sql),
|
|
1384
|
+
downSql: state.downSql,
|
|
1385
|
+
status: 'SUCCESS',
|
|
1386
|
+
errorMessage: null,
|
|
1387
|
+
performedById: target.user?.id ?? null
|
|
1388
|
+
}));
|
|
1389
|
+
await qr.commitTransaction();
|
|
1390
|
+
committed = true;
|
|
1391
|
+
const entityId = outcome.entityDefinitionId ?? target.entityDefinitionId;
|
|
1392
|
+
if (entityId) this.schemaRegistry.invalidate(entityId);
|
|
1393
|
+
await this.definitionCache.clearAll((0,_flusys_nestjs_shared_utils__rspack_import_0.cacheTenantId)(this.dataSourceProvider));
|
|
1394
|
+
try {
|
|
1395
|
+
await outcome.afterCommit?.();
|
|
1396
|
+
} catch (postCommitError) {
|
|
1397
|
+
// The change is already committed - reporting a failure now would be a lie.
|
|
1398
|
+
this.logger.error(`Post-commit step failed after '${target.action}' on '${target.entityCode}': ${postCommitError.message}`);
|
|
1399
|
+
state.warnings.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_11/* .SCHEMA_WARNING_MESSAGES.FOLLOW_UP_FAILED */.Uu.FOLLOW_UP_FAILED, {
|
|
1400
|
+
detail: (0,_flow_engine_flow_errors_js__rspack_import_3/* .errorRef */.O$)(postCommitError)
|
|
1401
|
+
}));
|
|
1402
|
+
}
|
|
1403
|
+
return {
|
|
1404
|
+
plan: this.toPlan(target, state),
|
|
1405
|
+
outcome
|
|
1406
|
+
};
|
|
1407
|
+
} catch (error) {
|
|
1408
|
+
if (!committed) await qr.rollbackTransaction().catch(()=>undefined);
|
|
1409
|
+
const undo = !committed && driver === 'mysql' && state.undo.length > 0 ? await this.compensate(qr, target, state) : null;
|
|
1410
|
+
await this.logFailure(target, error, state.steps, undo);
|
|
1411
|
+
throw this.withUndo((0,_database_error_mapper_js__rspack_import_6/* .mapSchemaError */.i)(error), undo);
|
|
1412
|
+
} finally{
|
|
1413
|
+
for (const key of heldLocks)await this.dialectAdapter.releaseEntityLock(qr, key, driver).catch(()=>undefined);
|
|
1414
|
+
await qr.release();
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* MySQL only: runs the reverse of every DDL statement that had run, newest first, still under
|
|
1419
|
+
* the entity lock. Stops at the first undo statement that fails - running later ones against an
|
|
1420
|
+
* unknown state could make it worse - and reports the rest as pending.
|
|
1421
|
+
*/ async compensate(qr, target, state) {
|
|
1422
|
+
const statements = state.undo.toReversed().flat();
|
|
1423
|
+
const pending = [];
|
|
1424
|
+
for (const statement of statements){
|
|
1425
|
+
if (pending.length) {
|
|
1426
|
+
pending.push(statement);
|
|
1427
|
+
continue;
|
|
1428
|
+
}
|
|
1429
|
+
try {
|
|
1430
|
+
await qr.query(statement.query, statement.parameters);
|
|
1431
|
+
} catch (undoError) {
|
|
1432
|
+
this.logger.error(`Could not undo '${format(statement)}' after the failed '${target.action}' on '${target.entityCode}': ${undoError.message}`);
|
|
1433
|
+
pending.push(statement);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
const report = {
|
|
1437
|
+
reverted: pending.length === 0,
|
|
1438
|
+
pendingSql: pending.map(format),
|
|
1439
|
+
dataNotReverted: state.dataSteps > 0
|
|
1440
|
+
};
|
|
1441
|
+
const ran = statements.length - pending.length;
|
|
1442
|
+
const summary = `'${target.action}' on '${target.entityCode}' failed on MySQL after ${statements.length} DDL statement(s) had committed; ${ran} undone`;
|
|
1443
|
+
if (report.reverted) this.logger.warn(`${summary}.${report.dataNotReverted ? ' Backfilled values were not undone.' : ''}`);
|
|
1444
|
+
else this.logger.error(`${summary}, ${pending.length} still pending - the table and its metadata may disagree until they are run or the entity is repaired.`);
|
|
1445
|
+
return report;
|
|
1446
|
+
}
|
|
1447
|
+
withUndo(mapped, undo) {
|
|
1448
|
+
if (!undo) return mapped;
|
|
1449
|
+
const status = mapped instanceof _nestjs_common__rspack_import_1.HttpException ? mapped.getStatus() : 500;
|
|
1450
|
+
const original = mapped instanceof _nestjs_common__rspack_import_1.HttpException ? mapped.getResponse() : null;
|
|
1451
|
+
const body = typeof original === 'object' && original !== null ? original : {};
|
|
1452
|
+
if (undo.reverted && mapped instanceof _nestjs_common__rspack_import_1.HttpException) {
|
|
1453
|
+
return new _nestjs_common__rspack_import_1.HttpException({
|
|
1454
|
+
...body,
|
|
1455
|
+
undo
|
|
1456
|
+
}, status);
|
|
1457
|
+
}
|
|
1458
|
+
if (undo.reverted) {
|
|
1459
|
+
return new _nestjs_common__rspack_import_1.InternalServerErrorException({
|
|
1460
|
+
message: 'The schema change failed and was rolled back',
|
|
1461
|
+
messageKey: _config_message_keys_js__rspack_import_11/* .SCHEMA_MESSAGES.FAILED */.Hu.FAILED,
|
|
1462
|
+
undo
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
return new _nestjs_common__rspack_import_1.HttpException({
|
|
1466
|
+
message: 'The schema change failed and could not be fully undone.',
|
|
1467
|
+
messageKey: _config_message_keys_js__rspack_import_11/* .SCHEMA_MESSAGES.FAILED_NOT_REVERTED */.Hu.FAILED_NOT_REVERTED,
|
|
1468
|
+
cause: {
|
|
1469
|
+
messageKey: body.messageKey,
|
|
1470
|
+
details: body.details
|
|
1471
|
+
},
|
|
1472
|
+
undo
|
|
1473
|
+
}, status);
|
|
1474
|
+
}
|
|
1475
|
+
/** Written on its own connection - the failed transaction's own writes were rolled back. */ async logFailure(target, error, steps = [], undo = null) {
|
|
1476
|
+
try {
|
|
1477
|
+
const repo = await this.dataSourceProvider.getRepository(_entities_schema_change_log_entity_js__rspack_import_5/* .SchemaChangeLog */.W);
|
|
1478
|
+
const response = error instanceof _nestjs_common__rspack_import_1.HttpException ? error.getResponse() : null;
|
|
1479
|
+
const messageKey = typeof response === 'object' && response !== null ? response.messageKey : undefined;
|
|
1480
|
+
const message = typeof messageKey === 'string' ? messageKey : error instanceof Error ? error.message : String(error);
|
|
1481
|
+
const undoNote = undo ? ` [MySQL: ${undo.reverted ? 'statements that had run were undone' : `${undo.pendingSql.length} undo statement(s) still pending`}]` : '';
|
|
1482
|
+
await repo.save(repo.create({
|
|
1483
|
+
entityDefinitionId: target.entityDefinitionId,
|
|
1484
|
+
entityCode: target.entityCode,
|
|
1485
|
+
operation: this.operationFor(target.action),
|
|
1486
|
+
tableName: target.tableName,
|
|
1487
|
+
fieldDefinitionId: null,
|
|
1488
|
+
diff: undo ? {
|
|
1489
|
+
action: target.action,
|
|
1490
|
+
undo
|
|
1491
|
+
} : {
|
|
1492
|
+
action: target.action
|
|
1493
|
+
},
|
|
1494
|
+
generatedSql: steps.flatMap((s)=>s.sql),
|
|
1495
|
+
downSql: undo?.pendingSql.length ? undo.pendingSql : null,
|
|
1496
|
+
status: 'FAILED',
|
|
1497
|
+
errorMessage: `${message}${undoNote}`.slice(0, 2000),
|
|
1498
|
+
performedById: target.user?.id ?? null
|
|
1499
|
+
}));
|
|
1500
|
+
} catch (logError) {
|
|
1501
|
+
this.logger.error(`Could not record failed schema change: ${logError.message}`);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
operationFor(action) {
|
|
1505
|
+
const map = {
|
|
1506
|
+
create_entity: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.CREATE_TABLE */.i.CREATE_TABLE,
|
|
1507
|
+
add_field: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.ADD_COLUMN */.i.ADD_COLUMN,
|
|
1508
|
+
update_field: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.ALTER_FIELD */.i.ALTER_FIELD,
|
|
1509
|
+
restore_field: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.RESTORE_FIELD */.i.RESTORE_FIELD,
|
|
1510
|
+
deprecate_field: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.MARK_DEPRECATED */.i.MARK_DEPRECATED,
|
|
1511
|
+
purge_field: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.DROP_COLUMN */.i.DROP_COLUMN,
|
|
1512
|
+
update_entity: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.ALTER_ENTITY */.i.ALTER_ENTITY,
|
|
1513
|
+
drop_entity: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.DROP_TABLE */.i.DROP_TABLE,
|
|
1514
|
+
repair: _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.REPAIR */.i.REPAIR
|
|
1515
|
+
};
|
|
1516
|
+
return map[action] ?? _enums_ddl_operation_enum_js__rspack_import_12/* .DdlOperation.ALTER_ENTITY */.i.ALTER_ENTITY;
|
|
1517
|
+
}
|
|
1518
|
+
// ── internals ─────────────────────────────────────────────────────────────────────
|
|
1519
|
+
newState(target, impact) {
|
|
1520
|
+
return {
|
|
1521
|
+
target,
|
|
1522
|
+
impact,
|
|
1523
|
+
steps: [],
|
|
1524
|
+
downSql: [],
|
|
1525
|
+
/** Per DDL step that ran for real, its reverse statements in the order to run them. */ undo: [],
|
|
1526
|
+
dataSteps: 0,
|
|
1527
|
+
warnings: [],
|
|
1528
|
+
blockers: [],
|
|
1529
|
+
affectedRows: null,
|
|
1530
|
+
destructive: false
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
toPlan(target, state) {
|
|
1534
|
+
return {
|
|
1535
|
+
action: target.action,
|
|
1536
|
+
entityCode: target.entityCode,
|
|
1537
|
+
tableName: target.tableName,
|
|
1538
|
+
steps: state.steps,
|
|
1539
|
+
downSql: state.downSql,
|
|
1540
|
+
warnings: state.warnings,
|
|
1541
|
+
blockers: state.blockers,
|
|
1542
|
+
impact: state.impact,
|
|
1543
|
+
affectedRows: state.affectedRows,
|
|
1544
|
+
destructive: state.destructive,
|
|
1545
|
+
metadataOnly: !state.steps.some((s)=>s.sql.length > 0)
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
buildContext(qr, driver, simulate, state) {
|
|
1549
|
+
const escape = (name)=>qr.connection.driver.escape(name);
|
|
1550
|
+
const recordUndo = (reverse)=>{
|
|
1551
|
+
if (!reverse.length) return;
|
|
1552
|
+
state.undo.push(reverse);
|
|
1553
|
+
state.downSql.unshift(...reverse.map(format));
|
|
1554
|
+
};
|
|
1555
|
+
return {
|
|
1556
|
+
qr,
|
|
1557
|
+
driver,
|
|
1558
|
+
get blocked () {
|
|
1559
|
+
return state.blockers.length > 0;
|
|
1560
|
+
},
|
|
1561
|
+
q: escape,
|
|
1562
|
+
ddl: async (description, fn)=>{
|
|
1563
|
+
// TypeORM records every schema statement and its reverse in the SQL memory in both modes;
|
|
1564
|
+
// only memory mode skips running them.
|
|
1565
|
+
qr.clearSqlMemory();
|
|
1566
|
+
if (simulate) {
|
|
1567
|
+
await fn();
|
|
1568
|
+
const memory = qr.getMemorySql();
|
|
1569
|
+
state.steps.push({
|
|
1570
|
+
description,
|
|
1571
|
+
sql: memory.upQueries.map(format)
|
|
1572
|
+
});
|
|
1573
|
+
state.downSql.unshift(...memory.downQueries.map(format).toReversed());
|
|
1574
|
+
qr.clearSqlMemory();
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
const captured = [];
|
|
1578
|
+
const original = qr.query.bind(qr);
|
|
1579
|
+
let failed = false;
|
|
1580
|
+
qr.query = (sql, params, ...rest)=>{
|
|
1581
|
+
if (!isReadOrSession(sql)) captured.push(formatSql(sql, params));
|
|
1582
|
+
return original(sql, params, ...rest);
|
|
1583
|
+
};
|
|
1584
|
+
try {
|
|
1585
|
+
await fn();
|
|
1586
|
+
} catch (error) {
|
|
1587
|
+
failed = true;
|
|
1588
|
+
throw error;
|
|
1589
|
+
} finally{
|
|
1590
|
+
qr.query = original;
|
|
1591
|
+
const down = qr.getMemorySql().downQueries.map((q)=>({
|
|
1592
|
+
query: q.query,
|
|
1593
|
+
parameters: q.parameters
|
|
1594
|
+
}));
|
|
1595
|
+
qr.clearSqlMemory();
|
|
1596
|
+
// TypeORM pairs each statement with its reverse; on failure the last captured one is the one that failed.
|
|
1597
|
+
const ran = failed ? Math.max(captured.length - 1, 0) : down.length;
|
|
1598
|
+
state.steps.push({
|
|
1599
|
+
description,
|
|
1600
|
+
sql: captured
|
|
1601
|
+
});
|
|
1602
|
+
recordUndo(down.slice(0, ran).toReversed());
|
|
1603
|
+
}
|
|
1604
|
+
},
|
|
1605
|
+
rawDdl: async (description, sql, downSql = [])=>{
|
|
1606
|
+
if (simulate) {
|
|
1607
|
+
state.steps.push({
|
|
1608
|
+
description,
|
|
1609
|
+
sql
|
|
1610
|
+
});
|
|
1611
|
+
state.downSql.unshift(...downSql.toReversed());
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
let ran = 0;
|
|
1615
|
+
try {
|
|
1616
|
+
for (const statement of sql){
|
|
1617
|
+
await qr.query(statement);
|
|
1618
|
+
ran += 1;
|
|
1619
|
+
}
|
|
1620
|
+
} finally{
|
|
1621
|
+
state.steps.push({
|
|
1622
|
+
description,
|
|
1623
|
+
sql: sql.slice(0, ran + (ran < sql.length ? 1 : 0))
|
|
1624
|
+
});
|
|
1625
|
+
recordUndo(downSql.slice(0, ran).toReversed().map((query)=>({
|
|
1626
|
+
query
|
|
1627
|
+
})));
|
|
1628
|
+
}
|
|
1629
|
+
},
|
|
1630
|
+
data: async (description, sqlPreview, fn)=>{
|
|
1631
|
+
if (!simulate) {
|
|
1632
|
+
await fn();
|
|
1633
|
+
state.dataSteps += 1;
|
|
1634
|
+
}
|
|
1635
|
+
state.steps.push({
|
|
1636
|
+
description,
|
|
1637
|
+
sql: [
|
|
1638
|
+
sqlPreview
|
|
1639
|
+
]
|
|
1640
|
+
});
|
|
1641
|
+
},
|
|
1642
|
+
metadata: async (fn)=>{
|
|
1643
|
+
if (!simulate) await fn();
|
|
1644
|
+
},
|
|
1645
|
+
warn: (message)=>{
|
|
1646
|
+
if (!hasMessage(state.warnings, message)) state.warnings.push(message);
|
|
1647
|
+
},
|
|
1648
|
+
block: (message)=>{
|
|
1649
|
+
if (!hasMessage(state.blockers, message)) state.blockers.push(message);
|
|
1650
|
+
},
|
|
1651
|
+
setAffectedRows: (count)=>{
|
|
1652
|
+
state.affectedRows = count;
|
|
1653
|
+
},
|
|
1654
|
+
markDestructive: ()=>{
|
|
1655
|
+
state.destructive = true;
|
|
1656
|
+
}
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
SchemaChangeExecutor = _ts_decorate([
|
|
1661
|
+
(0,_nestjs_common__rspack_import_1.Injectable)({
|
|
1662
|
+
scope: _nestjs_common__rspack_import_1.Scope.REQUEST
|
|
1663
|
+
}),
|
|
1664
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_1.Inject)(_entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D)),
|
|
1665
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_1.Inject)(_schema_dialect_adapter_service_js__rspack_import_9/* .SchemaDialectAdapterService */.I)),
|
|
1666
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_1.Inject)(_schema_registry_service_js__rspack_import_10/* .SchemaRegistryService */.C)),
|
|
1667
|
+
_ts_param(3, (0,_nestjs_common__rspack_import_1.Inject)(_definition_cache_service_js__rspack_import_7/* .DefinitionCacheService */.V)),
|
|
1668
|
+
_ts_metadata("design:type", Function),
|
|
1669
|
+
_ts_metadata("design:paramtypes", [
|
|
1670
|
+
typeof _entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D === "undefined" ? Object : _entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D,
|
|
1671
|
+
typeof _schema_dialect_adapter_service_js__rspack_import_9/* .SchemaDialectAdapterService */.I === "undefined" ? Object : _schema_dialect_adapter_service_js__rspack_import_9/* .SchemaDialectAdapterService */.I,
|
|
1672
|
+
typeof _schema_registry_service_js__rspack_import_10/* .SchemaRegistryService */.C === "undefined" ? Object : _schema_registry_service_js__rspack_import_10/* .SchemaRegistryService */.C,
|
|
1673
|
+
typeof _definition_cache_service_js__rspack_import_7/* .DefinitionCacheService */.V === "undefined" ? Object : _definition_cache_service_js__rspack_import_7/* .DefinitionCacheService */.V
|
|
1674
|
+
])
|
|
1675
|
+
], SchemaChangeExecutor);
|
|
1676
|
+
|
|
1677
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1678
|
+
T: () => (SchemaChangeExecutor),
|
|
1679
|
+
e: () => (relationTargetCodes)
|
|
1680
|
+
});
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
},
|
|
1684
|
+
7827(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1685
|
+
/** `"Name", "Other"` - the impacted flow names; the translated message supplies the word "flows". */ const describeImpact = (impact)=>impact.map((i)=>`"${i.name}"`).join(', ');
|
|
1686
|
+
|
|
1687
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1688
|
+
}, {
|
|
1689
|
+
a: describeImpact
|
|
1690
|
+
});
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
},
|
|
1694
|
+
3606(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1695
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
1696
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_1 = __webpack_require__(9216);
|
|
1697
|
+
/* import */ var _nestjs_common__rspack_import_2 = __webpack_require__(6157);
|
|
1698
|
+
/* import */ var class_transformer__rspack_import_3 = __webpack_require__(5812);
|
|
1699
|
+
/* import */ var class_validator__rspack_import_4 = __webpack_require__(5421);
|
|
1700
|
+
/* import */ var typeorm__rspack_import_5 = __webpack_require__(7158);
|
|
1701
|
+
/* import */ var _config_message_keys_js__rspack_import_19 = __webpack_require__(5732);
|
|
1702
|
+
/* import */ var _dtos_schema_change_dto_js__rspack_import_6 = __webpack_require__(4945);
|
|
1703
|
+
/* import */ var _entities_entity_definition_entity_js__rspack_import_7 = __webpack_require__(3189);
|
|
1704
|
+
/* import */ var _entities_field_definition_entity_js__rspack_import_8 = __webpack_require__(2206);
|
|
1705
|
+
/* import */ var _entities_schema_change_log_entity_js__rspack_import_9 = __webpack_require__(875);
|
|
1706
|
+
/* import */ var _enums_ddl_operation_enum_js__rspack_import_21 = __webpack_require__(9949);
|
|
1707
|
+
/* import */ var _enums_entity_status_enum_js__rspack_import_23 = __webpack_require__(1313);
|
|
1708
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_20 = __webpack_require__(9614);
|
|
1709
|
+
/* import */ var _entity_builder_datasource_provider_js__rspack_import_10 = __webpack_require__(424);
|
|
1710
|
+
/* import */ var _entity_permission_service_js__rspack_import_11 = __webpack_require__(1462);
|
|
1711
|
+
/* import */ var _field_value_validator_js__rspack_import_12 = __webpack_require__(3525);
|
|
1712
|
+
/* import */ var _field_type_conversion_js__rspack_import_13 = __webpack_require__(4984);
|
|
1713
|
+
/* import */ var _identifier_rules_js__rspack_import_14 = __webpack_require__(413);
|
|
1714
|
+
/* import */ var _reference_scanner_service_js__rspack_import_15 = __webpack_require__(921);
|
|
1715
|
+
/* import */ var _schema_change_executor_service_js__rspack_import_16 = __webpack_require__(6605);
|
|
1716
|
+
/* import */ var _schema_change_types_js__rspack_import_22 = __webpack_require__(7827);
|
|
1717
|
+
/* import */ var _schema_columns_js__rspack_import_17 = __webpack_require__(5313);
|
|
1718
|
+
/* import */ var _schema_dialect_adapter_service_js__rspack_import_18 = __webpack_require__(7259);
|
|
1719
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
1720
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1721
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
1722
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1723
|
+
} else {
|
|
1724
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
1725
|
+
if (d = decorators[i]) {
|
|
1726
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1731
|
+
}
|
|
1732
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
1733
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
1734
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
function _ts_param(paramIndex, decorator) {
|
|
1738
|
+
return function(target, key) {
|
|
1739
|
+
decorator(target, key, paramIndex);
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
|
|
1744
|
+
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
|
|
1760
|
+
|
|
1761
|
+
|
|
1762
|
+
|
|
1763
|
+
|
|
1764
|
+
|
|
1765
|
+
|
|
1766
|
+
const entityNotFound = (id)=>new _nestjs_common__rspack_import_2.NotFoundException({
|
|
1767
|
+
message: `Entity definition '${id}' not found.`,
|
|
1768
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .ENTITY_DEFINITION_MESSAGES.NOT_FOUND */.pL.NOT_FOUND,
|
|
1769
|
+
messageVariables: {
|
|
1770
|
+
id
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1773
|
+
const fieldNotFound = (id)=>new _nestjs_common__rspack_import_2.NotFoundException({
|
|
1774
|
+
message: `Field definition '${id}' not found.`,
|
|
1775
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .FIELD_DEFINITION_MESSAGES.NOT_FOUND */.oc.NOT_FOUND,
|
|
1776
|
+
messageVariables: {
|
|
1777
|
+
id
|
|
1778
|
+
}
|
|
1779
|
+
});
|
|
1780
|
+
const DESTRUCTIVE_ACTIONS = [
|
|
1781
|
+
_dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.DROP_ENTITY */.M3.DROP_ENTITY,
|
|
1782
|
+
_dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.PURGE_FIELD */.M3.PURGE_FIELD
|
|
1783
|
+
];
|
|
1784
|
+
const isDestructiveSchemaAction = (action)=>DESTRUCTIVE_ACTIONS.includes(action);
|
|
1785
|
+
const fieldLike = (field)=>({
|
|
1786
|
+
code: field.code,
|
|
1787
|
+
label: field.label ?? field.code,
|
|
1788
|
+
fieldType: field.fieldType,
|
|
1789
|
+
nullable: true,
|
|
1790
|
+
defaultValue: null,
|
|
1791
|
+
selectOptions: field.selectOptions ?? null,
|
|
1792
|
+
validationRules: field.validationRules ?? null
|
|
1793
|
+
});
|
|
1794
|
+
class SchemaEvolutionService {
|
|
1795
|
+
dataSourceProvider;
|
|
1796
|
+
adapter;
|
|
1797
|
+
executor;
|
|
1798
|
+
references;
|
|
1799
|
+
permissions;
|
|
1800
|
+
constructor(dataSourceProvider, adapter, executor, references, permissions){
|
|
1801
|
+
this.dataSourceProvider = dataSourceProvider;
|
|
1802
|
+
this.adapter = adapter;
|
|
1803
|
+
this.executor = executor;
|
|
1804
|
+
this.references = references;
|
|
1805
|
+
this.permissions = permissions;
|
|
1806
|
+
}
|
|
1807
|
+
// ── public API ──────────────────────────────────────────────────────────────────────
|
|
1808
|
+
async plan(request, user) {
|
|
1809
|
+
const prepared = await this.prepare(request, user);
|
|
1810
|
+
return this.executor.simulate(prepared.target, prepared.run, prepared.impact);
|
|
1811
|
+
}
|
|
1812
|
+
async apply(request, user) {
|
|
1813
|
+
const prepared = await this.prepare(request, user);
|
|
1814
|
+
const { plan, outcome } = await this.executor.apply(prepared.target, prepared.run, {
|
|
1815
|
+
confirm: request.confirm === true,
|
|
1816
|
+
impact: prepared.impact
|
|
1817
|
+
});
|
|
1818
|
+
return {
|
|
1819
|
+
...plan,
|
|
1820
|
+
result: outcome.diff
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1823
|
+
/** Compares the metadata with the real table and reports every difference. */ async inspect(entityDefinitionId) {
|
|
1824
|
+
const { definition, fields } = await this.loadEntity(entityDefinitionId);
|
|
1825
|
+
const driver = await this.dataSourceProvider.getDriver();
|
|
1826
|
+
const qr = await this.dataSourceProvider.getQueryRunner();
|
|
1827
|
+
await qr.connect();
|
|
1828
|
+
try {
|
|
1829
|
+
const table = await qr.getTable(definition.tableName);
|
|
1830
|
+
const findings = this.diff(definition, fields, table ?? undefined, driver);
|
|
1831
|
+
let rowCount = null;
|
|
1832
|
+
if (table) {
|
|
1833
|
+
const rows = await qr.query(`SELECT COUNT(*) AS c FROM ${qr.connection.driver.escape(definition.tableName)}`);
|
|
1834
|
+
rowCount = Number(rows[0]?.c ?? 0);
|
|
1835
|
+
}
|
|
1836
|
+
return {
|
|
1837
|
+
entityCode: definition.code,
|
|
1838
|
+
tableName: definition.tableName,
|
|
1839
|
+
healthy: findings.every((f)=>f.severity !== 'error'),
|
|
1840
|
+
rowCount,
|
|
1841
|
+
findings
|
|
1842
|
+
};
|
|
1843
|
+
} finally{
|
|
1844
|
+
await qr.release();
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
/** Newest first. Includes failed attempts, with the SQL that was about to run. */ async history(entityDefinitionId, limit = 50) {
|
|
1848
|
+
const repo = await this.dataSourceProvider.getRepository(_entities_schema_change_log_entity_js__rspack_import_9/* .SchemaChangeLog */.W);
|
|
1849
|
+
return repo.find({
|
|
1850
|
+
select: {
|
|
1851
|
+
id: true,
|
|
1852
|
+
operation: true,
|
|
1853
|
+
status: true,
|
|
1854
|
+
tableName: true,
|
|
1855
|
+
generatedSql: true,
|
|
1856
|
+
downSql: true,
|
|
1857
|
+
errorMessage: true,
|
|
1858
|
+
diff: true,
|
|
1859
|
+
createdAt: true,
|
|
1860
|
+
performedById: true
|
|
1861
|
+
},
|
|
1862
|
+
where: {
|
|
1863
|
+
entityDefinitionId
|
|
1864
|
+
},
|
|
1865
|
+
order: {
|
|
1866
|
+
createdAt: 'DESC'
|
|
1867
|
+
},
|
|
1868
|
+
take: Math.min(Math.max(limit, 1), 200)
|
|
1869
|
+
});
|
|
1870
|
+
}
|
|
1871
|
+
// ── loading ─────────────────────────────────────────────────────────────────────────
|
|
1872
|
+
async loadEntity(entityDefinitionId) {
|
|
1873
|
+
if (!entityDefinitionId) {
|
|
1874
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
1875
|
+
message: 'entityDefinitionId is required for this action.',
|
|
1876
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .ENTITY_DEFINITION_MESSAGES.ID_REQUIRED */.pL.ID_REQUIRED
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
return this.definitions((entity)=>this.dataSourceProvider.getRepository(entity), entityDefinitionId);
|
|
1880
|
+
}
|
|
1881
|
+
async loadField(fieldDefinitionId) {
|
|
1882
|
+
if (!fieldDefinitionId) {
|
|
1883
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
1884
|
+
message: 'fieldDefinitionId is required for this action.',
|
|
1885
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .FIELD_DEFINITION_MESSAGES.ID_REQUIRED */.oc.ID_REQUIRED
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
const field = await (await this.dataSourceProvider.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c)).findOne({
|
|
1889
|
+
where: {
|
|
1890
|
+
id: fieldDefinitionId
|
|
1891
|
+
}
|
|
1892
|
+
});
|
|
1893
|
+
if (!field) throw fieldNotFound(fieldDefinitionId);
|
|
1894
|
+
return {
|
|
1895
|
+
...await this.loadEntity(field.entityDefinitionId),
|
|
1896
|
+
field
|
|
1897
|
+
};
|
|
1898
|
+
}
|
|
1899
|
+
async definitions(repositoryOf, entityDefinitionId, fieldDefinitionId) {
|
|
1900
|
+
const definition = await (await repositoryOf(_entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f)).findOne({
|
|
1901
|
+
where: {
|
|
1902
|
+
id: entityDefinitionId
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
if (!definition) throw entityNotFound(entityDefinitionId);
|
|
1906
|
+
const fields = await (await repositoryOf(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c)).find({
|
|
1907
|
+
where: {
|
|
1908
|
+
entityDefinitionId
|
|
1909
|
+
},
|
|
1910
|
+
order: {
|
|
1911
|
+
order: 'ASC'
|
|
1912
|
+
}
|
|
1913
|
+
});
|
|
1914
|
+
const field = fieldDefinitionId ? fields.find((f)=>f.id === fieldDefinitionId) : undefined;
|
|
1915
|
+
if (fieldDefinitionId && !field) throw fieldNotFound(fieldDefinitionId);
|
|
1916
|
+
return {
|
|
1917
|
+
definition,
|
|
1918
|
+
fields,
|
|
1919
|
+
field
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1922
|
+
rejectUnknownKeys(changes, allowed, what) {
|
|
1923
|
+
const unknown = Object.keys(changes).filter((k)=>!allowed.includes(k));
|
|
1924
|
+
if (unknown.length) {
|
|
1925
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
1926
|
+
message: `Cannot change ${what} property: ${unknown.join(', ')}. Allowed: ${allowed.join(', ')}.`,
|
|
1927
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .SCHEMA_MESSAGES.UNKNOWN_CHANGE_PROPERTY */.Hu.UNKNOWN_CHANGE_PROPERTY,
|
|
1928
|
+
messageVariables: {
|
|
1929
|
+
what,
|
|
1930
|
+
properties: unknown.join(', '),
|
|
1931
|
+
allowed: allowed.join(', ')
|
|
1932
|
+
}
|
|
1933
|
+
});
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
validateChanges(dto, changes) {
|
|
1937
|
+
const errors = (0,class_validator__rspack_import_4.validateSync)((0,class_transformer__rspack_import_3.plainToInstance)(dto, changes), {
|
|
1938
|
+
forbidUnknownValues: false
|
|
1939
|
+
});
|
|
1940
|
+
if (!errors.length) return;
|
|
1941
|
+
const properties = errors.map((e)=>e.property);
|
|
1942
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
1943
|
+
message: `Invalid value for ${properties.map((p)=>`'${p}'`).join(', ')}.`,
|
|
1944
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .SCHEMA_MESSAGES.INVALID_CHANGE_VALUE */.Hu.INVALID_CHANGE_VALUE,
|
|
1945
|
+
messageVariables: {
|
|
1946
|
+
property: properties.join(', ')
|
|
1947
|
+
},
|
|
1948
|
+
errors: properties.map((property)=>({
|
|
1949
|
+
field: property,
|
|
1950
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .SCHEMA_MESSAGES.INVALID_CHANGE_VALUE */.Hu.INVALID_CHANGE_VALUE,
|
|
1951
|
+
messageVariables: {
|
|
1952
|
+
property
|
|
1953
|
+
}
|
|
1954
|
+
}))
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
async current(ctx, request, entityDefinitionId, fieldDefinitionId) {
|
|
1958
|
+
const found = await this.definitions((entity)=>ctx.qr.manager.getRepository(entity), entityDefinitionId, fieldDefinitionId);
|
|
1959
|
+
if (request.expectedUpdatedAt) {
|
|
1960
|
+
await this.assertNotStale(ctx, fieldDefinitionId ? _entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c : _entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f, fieldDefinitionId ?? entityDefinitionId, request.expectedUpdatedAt);
|
|
1961
|
+
}
|
|
1962
|
+
return found;
|
|
1963
|
+
}
|
|
1964
|
+
async assertNotStale(ctx, entity, id, expected) {
|
|
1965
|
+
const row = await ctx.qr.manager.getRepository(entity).findOne({
|
|
1966
|
+
select: {
|
|
1967
|
+
id: true,
|
|
1968
|
+
updatedAt: true
|
|
1969
|
+
},
|
|
1970
|
+
where: {
|
|
1971
|
+
id
|
|
1972
|
+
}
|
|
1973
|
+
});
|
|
1974
|
+
const updatedAt = row?.updatedAt ? new Date(row.updatedAt) : null;
|
|
1975
|
+
if (updatedAt && updatedAt.getTime() !== new Date(expected).getTime()) {
|
|
1976
|
+
throw new _nestjs_common__rspack_import_2.ConflictException({
|
|
1977
|
+
message: 'Someone else changed this definition since you opened it. Reload it and make your change again.',
|
|
1978
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .SCHEMA_MESSAGES.STALE_DEFINITION */.Hu.STALE_DEFINITION,
|
|
1979
|
+
messageVariables: {
|
|
1980
|
+
updatedAt: updatedAt.toISOString()
|
|
1981
|
+
}
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
/** The field was renamed (or deprecated) by a change that committed after this request was checked. */ changedUnderneath(ctx, before, now) {
|
|
1986
|
+
if (now.code === before.code && !!now.deprecatedAt === !!before.deprecatedAt) return false;
|
|
1987
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DEFINITION_CHANGED */.M3.DEFINITION_CHANGED));
|
|
1988
|
+
return true;
|
|
1989
|
+
}
|
|
1990
|
+
// ── dispatch ────────────────────────────────────────────────────────────────────────
|
|
1991
|
+
async prepare(request, user) {
|
|
1992
|
+
switch(request.action){
|
|
1993
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.ADD_FIELD */.M3.ADD_FIELD:
|
|
1994
|
+
return this.prepareAddField(request, user);
|
|
1995
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.UPDATE_FIELD */.M3.UPDATE_FIELD:
|
|
1996
|
+
return this.prepareUpdateField(request, user);
|
|
1997
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.DEPRECATE_FIELD */.M3.DEPRECATE_FIELD:
|
|
1998
|
+
return this.prepareDeprecateField(request, user);
|
|
1999
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.RESTORE_FIELD */.M3.RESTORE_FIELD:
|
|
2000
|
+
return this.prepareRestoreField(request, user);
|
|
2001
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.PURGE_FIELD */.M3.PURGE_FIELD:
|
|
2002
|
+
return this.preparePurgeField(request, user);
|
|
2003
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.UPDATE_ENTITY */.M3.UPDATE_ENTITY:
|
|
2004
|
+
return this.prepareUpdateEntity(request, user);
|
|
2005
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.DROP_ENTITY */.M3.DROP_ENTITY:
|
|
2006
|
+
return this.prepareDropEntity(request, user);
|
|
2007
|
+
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.REPAIR */.M3.REPAIR:
|
|
2008
|
+
return this.prepareRepair(request, user);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
target(action, definition, user, lockCodes = []) {
|
|
2012
|
+
return {
|
|
2013
|
+
action,
|
|
2014
|
+
entityDefinitionId: definition.id,
|
|
2015
|
+
entityCode: definition.code,
|
|
2016
|
+
tableName: definition.tableName,
|
|
2017
|
+
user,
|
|
2018
|
+
lockCodes
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
// ── small SQL helpers (identifiers come from validated metadata and are escaped) ────
|
|
2022
|
+
// No placeholder rewriting here: prechecks embed regexes containing '?', which buildQuery would corrupt.
|
|
2023
|
+
async scalar(ctx, sql, params) {
|
|
2024
|
+
const rows = await ctx.qr.query(sql, params);
|
|
2025
|
+
return Number(Object.values(rows[0] ?? {
|
|
2026
|
+
c: 0
|
|
2027
|
+
})[0]);
|
|
2028
|
+
}
|
|
2029
|
+
/** A count that only feeds a warning: a failure reads as 0 and, thanks to the savepoint, leaves the change's transaction usable. */ advisoryScalar(ctx, sql, params) {
|
|
2030
|
+
return (0,_flusys_nestjs_shared_utils__rspack_import_1.withSavepoint)(ctx.qr, ()=>this.scalar(ctx, sql, params)).catch(()=>0);
|
|
2031
|
+
}
|
|
2032
|
+
paramValue(fieldType, value) {
|
|
2033
|
+
return fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.JSON */.P.JSON || fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT ? JSON.stringify(value) : value;
|
|
2034
|
+
}
|
|
2035
|
+
notNullSql(ctx, table, column, fieldType, notNull) {
|
|
2036
|
+
if (ctx.driver === 'postgres') {
|
|
2037
|
+
return `ALTER TABLE ${ctx.q(table)} ALTER COLUMN ${ctx.q(column)} ${notNull ? 'SET' : 'DROP'} NOT NULL`;
|
|
2038
|
+
}
|
|
2039
|
+
return `ALTER TABLE ${ctx.q(table)} MODIFY ${ctx.q(column)} ${(0,_schema_columns_js__rspack_import_17/* .sqlTypeFor */.cg)(fieldType, ctx.driver, this.adapter)} ${notNull ? 'NOT NULL' : 'NULL'}`;
|
|
2040
|
+
}
|
|
2041
|
+
/** Makes a column NOT NULL (or nullable again), with the reverse statement for the plan. */ setRequired(ctx, table, column, fieldType, required, step = required ? _config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.MAKE_REQUIRED */.EQ.MAKE_REQUIRED : _config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.MAKE_OPTIONAL */.EQ.MAKE_OPTIONAL) {
|
|
2042
|
+
return ctx.rawDdl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(step, {
|
|
2043
|
+
column
|
|
2044
|
+
}), [
|
|
2045
|
+
this.notNullSql(ctx, table, column, fieldType, required)
|
|
2046
|
+
], [
|
|
2047
|
+
this.notNullSql(ctx, table, column, fieldType, !required)
|
|
2048
|
+
]);
|
|
2049
|
+
}
|
|
2050
|
+
checkValue(field, value) {
|
|
2051
|
+
const { errors } = (0,_field_value_validator_js__rspack_import_12/* .validateRecord */.e)([
|
|
2052
|
+
fieldLike(field)
|
|
2053
|
+
], {
|
|
2054
|
+
[field.code]: value
|
|
2055
|
+
}, 'insert');
|
|
2056
|
+
return errors[0] ? (0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(errors[0].messageKey, errors[0].messageVariables) : null;
|
|
2057
|
+
}
|
|
2058
|
+
async requireTable(ctx, tableName) {
|
|
2059
|
+
const table = await ctx.qr.getTable(tableName);
|
|
2060
|
+
if (!table) {
|
|
2061
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.TABLE_MISSING */.M3.TABLE_MISSING, {
|
|
2062
|
+
table: tableName
|
|
2063
|
+
}));
|
|
2064
|
+
}
|
|
2065
|
+
return table ?? undefined;
|
|
2066
|
+
}
|
|
2067
|
+
/** How many values a unique constraint on `code` would clash on. */ countDuplicates(ctx, table, code) {
|
|
2068
|
+
const key = ctx.q(code);
|
|
2069
|
+
return this.scalar(ctx, `SELECT COUNT(*) AS c FROM (SELECT ${key} FROM ${ctx.q(table)} WHERE ${key} IS NOT NULL GROUP BY ${key} HAVING COUNT(*) > 1) d`);
|
|
2070
|
+
}
|
|
2071
|
+
async dropUniques(ctx, table, code) {
|
|
2072
|
+
const drop = (columnNames)=>(0,_schema_columns_js__rspack_import_17/* .sameColumns */.G7)(columnNames, [
|
|
2073
|
+
code
|
|
2074
|
+
]);
|
|
2075
|
+
for (const uq of table.uniques.filter((u)=>drop(u.columnNames)))await ctx.qr.dropUniqueConstraint(table, uq);
|
|
2076
|
+
for (const idx of table.indices.filter((i)=>i.isUnique && drop(i.columnNames)))await ctx.qr.dropIndex(table, idx);
|
|
2077
|
+
}
|
|
2078
|
+
hasUnique(table, code) {
|
|
2079
|
+
if (table.uniques.some((u)=>(0,_schema_columns_js__rspack_import_17/* .sameColumns */.G7)(u.columnNames, [
|
|
2080
|
+
code
|
|
2081
|
+
]))) return true;
|
|
2082
|
+
if (table.indices.some((i)=>i.isUnique && (0,_schema_columns_js__rspack_import_17/* .sameColumns */.G7)(i.columnNames, [
|
|
2083
|
+
code
|
|
2084
|
+
]))) return true;
|
|
2085
|
+
return !!table.findColumnByName(code)?.isUnique;
|
|
2086
|
+
}
|
|
2087
|
+
indexOn(table, column, unique) {
|
|
2088
|
+
return table.indices.filter((i)=>i.columnNames.length === 1 && i.columnNames[0] === column && i.isUnique === unique);
|
|
2089
|
+
}
|
|
2090
|
+
// ── add_field ───────────────────────────────────────────────────────────────────────
|
|
2091
|
+
async prepareAddField(request, user) {
|
|
2092
|
+
const { definition: loaded } = await this.loadEntity(request.entityDefinitionId);
|
|
2093
|
+
const spec = request.field;
|
|
2094
|
+
if (!spec) {
|
|
2095
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
2096
|
+
message: "add_field needs a 'field' definition.",
|
|
2097
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .FIELD_DEFINITION_MESSAGES.DEFINITION_REQUIRED */.oc.DEFINITION_REQUIRED
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
(0,_identifier_rules_js__rspack_import_14/* .assertValidIdentifier */.kV)(spec.code, 'field');
|
|
2101
|
+
(0,_identifier_rules_js__rspack_import_14/* .assertIndexableField */.fY)(spec);
|
|
2102
|
+
const lockCodes = await (0,_schema_change_executor_service_js__rspack_import_16/* .relationTargetCodes */.e)(this.dataSourceProvider, [
|
|
2103
|
+
spec.relationTargetEntityId
|
|
2104
|
+
]);
|
|
2105
|
+
const run = async (ctx)=>{
|
|
2106
|
+
const { definition, fields } = await this.current(ctx, request, loaded.id);
|
|
2107
|
+
const existing = fields.find((f)=>f.code === spec.code);
|
|
2108
|
+
if (existing) {
|
|
2109
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(existing.deprecatedAt ? _config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.FIELD_EXISTS_DEPRECATED */.M3.FIELD_EXISTS_DEPRECATED : _config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.FIELD_EXISTS */.M3.FIELD_EXISTS, {
|
|
2110
|
+
code: spec.code
|
|
2111
|
+
}));
|
|
2112
|
+
}
|
|
2113
|
+
const nullable = spec.nullable ?? true;
|
|
2114
|
+
const unique = spec.unique ?? false;
|
|
2115
|
+
const dbType = this.adapter.mapFieldType(spec.fieldType, ctx.driver);
|
|
2116
|
+
const isRelation = spec.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.RELATION */.P.RELATION;
|
|
2117
|
+
if (isRelation && !spec.relationTargetEntityId) {
|
|
2118
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.RELATION_TARGET_REQUIRED */.M3.RELATION_TARGET_REQUIRED, {
|
|
2119
|
+
field: spec.code
|
|
2120
|
+
}));
|
|
2121
|
+
} else if (isRelation) {
|
|
2122
|
+
const target = await ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f).findOne({
|
|
2123
|
+
where: {
|
|
2124
|
+
id: spec.relationTargetEntityId
|
|
2125
|
+
}
|
|
2126
|
+
});
|
|
2127
|
+
if (!target) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.RELATION_TARGET_MISSING */.M3.RELATION_TARGET_MISSING));
|
|
2128
|
+
}
|
|
2129
|
+
if ((spec.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT || spec.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT) && !spec.selectOptions?.length) {
|
|
2130
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.NO_SELECT_OPTIONS_YET */.Uu.NO_SELECT_OPTIONS_YET));
|
|
2131
|
+
}
|
|
2132
|
+
if (spec.defaultValue !== undefined && spec.defaultValue !== null) {
|
|
2133
|
+
const problem = this.checkValue({
|
|
2134
|
+
...spec,
|
|
2135
|
+
code: spec.code,
|
|
2136
|
+
fieldType: spec.fieldType
|
|
2137
|
+
}, spec.defaultValue);
|
|
2138
|
+
if (problem) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DEFAULT_INVALID */.M3.DEFAULT_INVALID, {
|
|
2139
|
+
problem
|
|
2140
|
+
}));
|
|
2141
|
+
}
|
|
2142
|
+
const table = await this.requireTable(ctx, definition.tableName);
|
|
2143
|
+
const rows = table ? await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)}`) : 0;
|
|
2144
|
+
const backfill = request.backfillValue ?? spec.defaultValue ?? null;
|
|
2145
|
+
if (!nullable && rows > 0) {
|
|
2146
|
+
if (backfill === null) {
|
|
2147
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.REQUIRED_NEEDS_VALUE */.M3.REQUIRED_NEEDS_VALUE, {
|
|
2148
|
+
count: rows
|
|
2149
|
+
}));
|
|
2150
|
+
} else {
|
|
2151
|
+
const problem = this.checkValue({
|
|
2152
|
+
...spec,
|
|
2153
|
+
code: spec.code,
|
|
2154
|
+
fieldType: spec.fieldType
|
|
2155
|
+
}, backfill);
|
|
2156
|
+
if (problem) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.BACKFILL_INVALID */.M3.BACKFILL_INVALID, {
|
|
2157
|
+
problem
|
|
2158
|
+
}));
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
// Only a required field is backfilled; every existing row gets the same value, so two rows or more would clash.
|
|
2162
|
+
if (unique && !nullable && backfill !== null && rows > 1) {
|
|
2163
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.UNIQUE_BACKFILL_CONFLICT */.M3.UNIQUE_BACKFILL_CONFLICT));
|
|
2164
|
+
}
|
|
2165
|
+
if (ctx.blocked || !table) {
|
|
2166
|
+
return {
|
|
2167
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ADD_COLUMN */.i.ADD_COLUMN,
|
|
2168
|
+
diff: {}
|
|
2169
|
+
};
|
|
2170
|
+
}
|
|
2171
|
+
const column = (0,_schema_columns_js__rspack_import_17/* .buildFieldColumn */.fu)({
|
|
2172
|
+
code: spec.code,
|
|
2173
|
+
fieldType: spec.fieldType,
|
|
2174
|
+
dbType,
|
|
2175
|
+
nullable,
|
|
2176
|
+
unique
|
|
2177
|
+
}, ctx.driver, this.adapter, {
|
|
2178
|
+
enforceNotNull: false,
|
|
2179
|
+
withUnique: false
|
|
2180
|
+
});
|
|
2181
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_COLUMN */.EQ.ADD_COLUMN, {
|
|
2182
|
+
column: spec.code
|
|
2183
|
+
}), async ()=>{
|
|
2184
|
+
await ctx.qr.addColumn(table, column);
|
|
2185
|
+
});
|
|
2186
|
+
if (!nullable && rows > 0) {
|
|
2187
|
+
await ctx.data((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.BACKFILL_EXISTING */.EQ.BACKFILL_EXISTING, {
|
|
2188
|
+
count: rows
|
|
2189
|
+
}), `UPDATE ${ctx.q(definition.tableName)} SET ${ctx.q(spec.code)} = ${this.adapter.sqlLiteral(this.paramValue(spec.fieldType, backfill), ctx.driver)}`, async ()=>{
|
|
2190
|
+
await ctx.qr.query((0,_flusys_nestjs_shared_classes__rspack_import_0.buildQuery)(`UPDATE ${ctx.q(definition.tableName)} SET ${ctx.q(spec.code)} = ?`, ctx.driver), [
|
|
2191
|
+
this.paramValue(spec.fieldType, backfill)
|
|
2192
|
+
]);
|
|
2193
|
+
});
|
|
2194
|
+
}
|
|
2195
|
+
if (!nullable) {
|
|
2196
|
+
await this.setRequired(ctx, definition.tableName, spec.code, spec.fieldType, true);
|
|
2197
|
+
}
|
|
2198
|
+
if (unique) {
|
|
2199
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_UNIQUE */.EQ.ADD_UNIQUE, {
|
|
2200
|
+
column: spec.code
|
|
2201
|
+
}), async ()=>{
|
|
2202
|
+
await (0,_schema_columns_js__rspack_import_17/* .addUnique */.$6)(ctx.qr, table, spec.code, ctx.driver, this.adapter);
|
|
2203
|
+
});
|
|
2204
|
+
}
|
|
2205
|
+
if (spec.isIndexed && !unique) {
|
|
2206
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_INDEX */.EQ.ADD_INDEX, {
|
|
2207
|
+
column: spec.code
|
|
2208
|
+
}), async ()=>{
|
|
2209
|
+
await ctx.qr.createIndex(table, (0,_schema_columns_js__rspack_import_17/* .plainIndex */.v7)(definition.tableName, spec.code, ctx.driver, this.adapter));
|
|
2210
|
+
});
|
|
2211
|
+
}
|
|
2212
|
+
let fieldId = null;
|
|
2213
|
+
await ctx.metadata(async ()=>{
|
|
2214
|
+
const repo = ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c);
|
|
2215
|
+
const saved = await repo.save(repo.create({
|
|
2216
|
+
entityDefinitionId: definition.id,
|
|
2217
|
+
code: spec.code,
|
|
2218
|
+
label: spec.label,
|
|
2219
|
+
fieldType: spec.fieldType,
|
|
2220
|
+
dbType,
|
|
2221
|
+
nullable,
|
|
2222
|
+
unique,
|
|
2223
|
+
isIndexed: spec.isIndexed ?? false,
|
|
2224
|
+
defaultValue: spec.defaultValue ?? null,
|
|
2225
|
+
validationRules: spec.validationRules ?? null,
|
|
2226
|
+
selectOptions: spec.selectOptions ?? null,
|
|
2227
|
+
relationTargetEntityId: isRelation ? spec.relationTargetEntityId : null,
|
|
2228
|
+
order: spec.order ?? Math.max(-1, ...fields.map((f)=>f.order)) + 1,
|
|
2229
|
+
uiConfig: spec.uiConfig ?? null,
|
|
2230
|
+
isSearchable: spec.isSearchable ?? false,
|
|
2231
|
+
isSystemField: false,
|
|
2232
|
+
deprecatedAt: null
|
|
2233
|
+
}));
|
|
2234
|
+
fieldId = saved.id;
|
|
2235
|
+
});
|
|
2236
|
+
return {
|
|
2237
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ADD_COLUMN */.i.ADD_COLUMN,
|
|
2238
|
+
fieldDefinitionId: fieldId,
|
|
2239
|
+
diff: {
|
|
2240
|
+
field: {
|
|
2241
|
+
code: spec.code,
|
|
2242
|
+
fieldType: spec.fieldType,
|
|
2243
|
+
nullable,
|
|
2244
|
+
unique
|
|
2245
|
+
},
|
|
2246
|
+
backfilledRows: !nullable ? rows : 0
|
|
2247
|
+
}
|
|
2248
|
+
};
|
|
2249
|
+
};
|
|
2250
|
+
return {
|
|
2251
|
+
target: this.target('add_field', loaded, user, lockCodes),
|
|
2252
|
+
run,
|
|
2253
|
+
impact: []
|
|
2254
|
+
};
|
|
2255
|
+
}
|
|
2256
|
+
// ── update_field ────────────────────────────────────────────────────────────────────
|
|
2257
|
+
async prepareUpdateField(request, user) {
|
|
2258
|
+
const { field: loadedField, definition: loaded } = await this.loadField(request.fieldDefinitionId);
|
|
2259
|
+
const changes = request.changes ?? {};
|
|
2260
|
+
this.rejectUnknownKeys(changes, _dtos_schema_change_dto_js__rspack_import_6/* .FIELD_CHANGE_KEYS */.bD, 'field');
|
|
2261
|
+
this.validateChanges(_dtos_schema_change_dto_js__rspack_import_6/* .FieldChangesDto */.Pr, changes);
|
|
2262
|
+
if (loadedField.deprecatedAt) {
|
|
2263
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
2264
|
+
message: 'A deprecated field cannot be changed. Restore it first.',
|
|
2265
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .FIELD_DEFINITION_MESSAGES.DEPRECATED_LOCKED */.oc.DEPRECATED_LOCKED
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
const newCode = typeof changes.code === 'string' && changes.code !== loadedField.code ? changes.code : null;
|
|
2269
|
+
if (newCode) (0,_identifier_rules_js__rspack_import_14/* .assertValidIdentifier */.kV)(newCode, 'field');
|
|
2270
|
+
const structuralKeys = (field)=>[
|
|
2271
|
+
'fieldType',
|
|
2272
|
+
'nullable',
|
|
2273
|
+
'unique',
|
|
2274
|
+
'isIndexed'
|
|
2275
|
+
].filter((k)=>k in changes && changes[k] !== field[k]);
|
|
2276
|
+
const requested = structuralKeys(loadedField);
|
|
2277
|
+
if (newCode && requested.length) {
|
|
2278
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
2279
|
+
message: `Rename '${loadedField.code}' in its own change - it cannot be combined with: ${requested.join(', ')}.`,
|
|
2280
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .FIELD_DEFINITION_MESSAGES.RENAME_ALONE */.oc.RENAME_ALONE,
|
|
2281
|
+
messageVariables: {
|
|
2282
|
+
field: loadedField.code,
|
|
2283
|
+
changes: requested.join(', ')
|
|
2284
|
+
}
|
|
2285
|
+
});
|
|
2286
|
+
}
|
|
2287
|
+
if ([
|
|
2288
|
+
'fieldType',
|
|
2289
|
+
'unique',
|
|
2290
|
+
'isIndexed'
|
|
2291
|
+
].some((k)=>k in changes)) {
|
|
2292
|
+
(0,_identifier_rules_js__rspack_import_14/* .assertIndexableField */.fY)({
|
|
2293
|
+
...loadedField,
|
|
2294
|
+
...changes,
|
|
2295
|
+
code: loadedField.code
|
|
2296
|
+
});
|
|
2297
|
+
}
|
|
2298
|
+
const targetType = changes.fieldType ?? loadedField.fieldType;
|
|
2299
|
+
const newTargetId = typeof changes.relationTargetEntityId === 'string' ? changes.relationTargetEntityId : null;
|
|
2300
|
+
if (newTargetId && targetType !== _enums_field_type_enum_js__rspack_import_20/* .FieldType.RELATION */.P.RELATION) {
|
|
2301
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
2302
|
+
message: 'relationTargetEntityId can only be set on a RELATION field.',
|
|
2303
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .SCHEMA_MESSAGES.INVALID_CHANGE_VALUE */.Hu.INVALID_CHANGE_VALUE,
|
|
2304
|
+
messageVariables: {
|
|
2305
|
+
property: 'relationTargetEntityId'
|
|
2306
|
+
}
|
|
2307
|
+
});
|
|
2308
|
+
}
|
|
2309
|
+
const lockCodes = await (0,_schema_change_executor_service_js__rspack_import_16/* .relationTargetCodes */.e)(this.dataSourceProvider, [
|
|
2310
|
+
newTargetId
|
|
2311
|
+
]);
|
|
2312
|
+
const impact = newCode || changes.fieldType !== undefined ? await this.references.forField(loaded.code, loadedField.code) : [];
|
|
2313
|
+
const run = async (ctx)=>{
|
|
2314
|
+
const { definition, fields, field } = await this.current(ctx, request, loaded.id, loadedField.id);
|
|
2315
|
+
if (this.changedUnderneath(ctx, loadedField, field)) {
|
|
2316
|
+
return {
|
|
2317
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ALTER_FIELD */.i.ALTER_FIELD,
|
|
2318
|
+
fieldDefinitionId: field.id,
|
|
2319
|
+
diff: {}
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
const structural = structuralKeys(field);
|
|
2323
|
+
const merged = {
|
|
2324
|
+
...field,
|
|
2325
|
+
...changes
|
|
2326
|
+
};
|
|
2327
|
+
const patch = {};
|
|
2328
|
+
const table = structural.length || newCode ? await this.requireTable(ctx, definition.tableName) : undefined;
|
|
2329
|
+
const column = table?.findColumnByName(field.code);
|
|
2330
|
+
if ((structural.length || newCode) && table && !column) {
|
|
2331
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.COLUMN_MISSING */.M3.COLUMN_MISSING, {
|
|
2332
|
+
column: field.code
|
|
2333
|
+
}));
|
|
2334
|
+
}
|
|
2335
|
+
// ── plain metadata ──
|
|
2336
|
+
for (const key of [
|
|
2337
|
+
'label',
|
|
2338
|
+
'order',
|
|
2339
|
+
'uiConfig',
|
|
2340
|
+
'isSearchable'
|
|
2341
|
+
]){
|
|
2342
|
+
if (key in changes) patch[key] = changes[key];
|
|
2343
|
+
}
|
|
2344
|
+
if ('selectOptions' in changes) {
|
|
2345
|
+
patch.selectOptions = changes.selectOptions;
|
|
2346
|
+
if (merged.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT && Array.isArray(changes.selectOptions) && changes.selectOptions.length && !ctx.blocked) {
|
|
2347
|
+
const values = changes.selectOptions.map((o)=>String(o.value));
|
|
2348
|
+
const stray = await this.advisoryScalar(ctx, (0,_flusys_nestjs_shared_classes__rspack_import_0.buildQuery)(`SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)} WHERE ${ctx.q(field.code)} IS NOT NULL AND ${ctx.q(field.code)} NOT IN (${values.map(()=>'?').join(', ')})`, ctx.driver), values);
|
|
2349
|
+
if (stray > 0) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.STRAY_VALUES */.Uu.STRAY_VALUES, {
|
|
2350
|
+
count: stray
|
|
2351
|
+
}));
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
if ('validationRules' in changes) {
|
|
2355
|
+
patch.validationRules = changes.validationRules;
|
|
2356
|
+
const rules = changes.validationRules ?? {};
|
|
2357
|
+
const isNumber = merged.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.INTEGER */.P.INTEGER || merged.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.DECIMAL */.P.DECIMAL;
|
|
2358
|
+
const violating = [];
|
|
2359
|
+
if (isNumber && typeof rules.min === 'number') violating.push(`${ctx.q(field.code)} < ${Number(rules.min)}`);
|
|
2360
|
+
if (isNumber && typeof rules.max === 'number') violating.push(`${ctx.q(field.code)} > ${Number(rules.max)}`);
|
|
2361
|
+
if (!isNumber && typeof rules.minLength === 'number') violating.push(`CHAR_LENGTH(${ctx.q(field.code)}) < ${Number(rules.minLength)}`);
|
|
2362
|
+
if (!isNumber && typeof rules.maxLength === 'number') violating.push(`CHAR_LENGTH(${ctx.q(field.code)}) > ${Number(rules.maxLength)}`);
|
|
2363
|
+
if (violating.length && [
|
|
2364
|
+
_enums_field_type_enum_js__rspack_import_20/* .FieldType.INTEGER */.P.INTEGER,
|
|
2365
|
+
_enums_field_type_enum_js__rspack_import_20/* .FieldType.DECIMAL */.P.DECIMAL,
|
|
2366
|
+
_enums_field_type_enum_js__rspack_import_20/* .FieldType.TEXT */.P.TEXT,
|
|
2367
|
+
_enums_field_type_enum_js__rspack_import_20/* .FieldType.LONG_TEXT */.P.LONG_TEXT,
|
|
2368
|
+
_enums_field_type_enum_js__rspack_import_20/* .FieldType.EMAIL */.P.EMAIL
|
|
2369
|
+
].includes(merged.fieldType)) {
|
|
2370
|
+
const bad = await this.advisoryScalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)} WHERE ${ctx.q(field.code)} IS NOT NULL AND (${violating.join(' OR ')})`);
|
|
2371
|
+
if (bad > 0) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.RULES_VIOLATED */.Uu.RULES_VIOLATED, {
|
|
2372
|
+
count: bad
|
|
2373
|
+
}));
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
// ── relation target ──
|
|
2377
|
+
if (merged.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.RELATION */.P.RELATION) {
|
|
2378
|
+
const targetId = 'relationTargetEntityId' in changes ? changes.relationTargetEntityId : field.relationTargetEntityId;
|
|
2379
|
+
const becomesRelation = field.fieldType !== _enums_field_type_enum_js__rspack_import_20/* .FieldType.RELATION */.P.RELATION;
|
|
2380
|
+
if (!targetId && (becomesRelation || 'relationTargetEntityId' in changes)) {
|
|
2381
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.RELATION_TARGET_REQUIRED */.M3.RELATION_TARGET_REQUIRED, {
|
|
2382
|
+
field: field.code
|
|
2383
|
+
}));
|
|
2384
|
+
} else if (targetId && (becomesRelation || targetId !== field.relationTargetEntityId)) {
|
|
2385
|
+
const target = await ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f).findOne({
|
|
2386
|
+
where: {
|
|
2387
|
+
id: targetId
|
|
2388
|
+
}
|
|
2389
|
+
});
|
|
2390
|
+
if (!target) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.RELATION_TARGET_MISSING */.M3.RELATION_TARGET_MISSING));
|
|
2391
|
+
else if (target.id !== field.relationTargetEntityId) patch.relationTargetEntityId = target.id;
|
|
2392
|
+
}
|
|
2393
|
+
} else if (field.relationTargetEntityId && changes.fieldType !== undefined) {
|
|
2394
|
+
patch.relationTargetEntityId = null;
|
|
2395
|
+
}
|
|
2396
|
+
if ('defaultValue' in changes) {
|
|
2397
|
+
if (changes.defaultValue !== null && changes.defaultValue !== undefined) {
|
|
2398
|
+
const problem = this.checkValue(merged, changes.defaultValue);
|
|
2399
|
+
if (problem) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DEFAULT_INVALID */.M3.DEFAULT_INVALID, {
|
|
2400
|
+
problem
|
|
2401
|
+
}));
|
|
2402
|
+
}
|
|
2403
|
+
patch.defaultValue = changes.defaultValue ?? null;
|
|
2404
|
+
}
|
|
2405
|
+
// ── type change ──
|
|
2406
|
+
const typeChanged = changes.fieldType !== undefined && changes.fieldType !== field.fieldType;
|
|
2407
|
+
if (typeChanged && table && column) {
|
|
2408
|
+
const conversion = (0,_field_type_conversion_js__rspack_import_13/* .planTypeConversion */.I)(field.fieldType, merged.fieldType, ctx.driver);
|
|
2409
|
+
if (!conversion.supported) {
|
|
2410
|
+
ctx.block(conversion.reason);
|
|
2411
|
+
} else {
|
|
2412
|
+
const nonNull = await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)} WHERE ${ctx.q(field.code)} IS NOT NULL`);
|
|
2413
|
+
ctx.setAffectedRows(nonNull);
|
|
2414
|
+
for (const check of conversion.prechecks){
|
|
2415
|
+
const where = check.badRowsWhere(ctx.q(field.code), ctx.driver);
|
|
2416
|
+
const bad = await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)} WHERE ${ctx.q(field.code)} IS NOT NULL AND (${where})`);
|
|
2417
|
+
if (bad > 0) {
|
|
2418
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.CONVERSION_BAD_ROWS */.M3.CONVERSION_BAD_ROWS, {
|
|
2419
|
+
count: bad,
|
|
2420
|
+
check: check.description,
|
|
2421
|
+
from: field.fieldType,
|
|
2422
|
+
to: merged.fieldType
|
|
2423
|
+
}));
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
if (conversion.lossy) {
|
|
2427
|
+
ctx.warn(conversion.lossy);
|
|
2428
|
+
ctx.markDestructive();
|
|
2429
|
+
}
|
|
2430
|
+
const newDefaultProblem = merged.defaultValue !== null && merged.defaultValue !== undefined ? this.checkValue(merged, merged.defaultValue) : null;
|
|
2431
|
+
if (newDefaultProblem) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.CURRENT_DEFAULT_INVALID */.M3.CURRENT_DEFAULT_INVALID, {
|
|
2432
|
+
type: merged.fieldType,
|
|
2433
|
+
problem: newDefaultProblem
|
|
2434
|
+
}));
|
|
2435
|
+
if ((merged.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT || merged.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT) && !merged.selectOptions?.length) {
|
|
2436
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.NO_SELECT_OPTIONS_CONVERT */.Uu.NO_SELECT_OPTIONS_CONVERT));
|
|
2437
|
+
}
|
|
2438
|
+
if (!ctx.blocked) {
|
|
2439
|
+
const newDbType = this.adapter.mapFieldType(merged.fieldType, ctx.driver);
|
|
2440
|
+
if (!conversion.noDbChange) {
|
|
2441
|
+
const from = (0,_schema_columns_js__rspack_import_17/* .sqlTypeFor */.cg)(field.fieldType, ctx.driver, this.adapter);
|
|
2442
|
+
const to = (0,_schema_columns_js__rspack_import_17/* .sqlTypeFor */.cg)(merged.fieldType, ctx.driver, this.adapter);
|
|
2443
|
+
const t = ctx.q(definition.tableName);
|
|
2444
|
+
const c = ctx.q(field.code);
|
|
2445
|
+
const nullSql = column.isNullable ? 'NULL' : 'NOT NULL';
|
|
2446
|
+
const up = ctx.driver === 'postgres' ? `ALTER TABLE ${t} ALTER COLUMN ${c} TYPE ${to} USING ${conversion.using ? conversion.using(c) : `${c}::${to}`}` : `ALTER TABLE ${t} MODIFY ${c} ${to} ${nullSql}`;
|
|
2447
|
+
const down = ctx.driver === 'postgres' ? `ALTER TABLE ${t} ALTER COLUMN ${c} TYPE ${from} USING ${c}::${from}` : `ALTER TABLE ${t} MODIFY ${c} ${from} ${nullSql}`;
|
|
2448
|
+
await ctx.rawDdl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.CONVERT_TYPE */.EQ.CONVERT_TYPE, {
|
|
2449
|
+
column: field.code,
|
|
2450
|
+
from: field.fieldType,
|
|
2451
|
+
to: merged.fieldType
|
|
2452
|
+
}), [
|
|
2453
|
+
up
|
|
2454
|
+
], [
|
|
2455
|
+
down
|
|
2456
|
+
]);
|
|
2457
|
+
}
|
|
2458
|
+
patch.fieldType = merged.fieldType;
|
|
2459
|
+
patch.dbType = newDbType;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
// ── nullable ──
|
|
2464
|
+
if (changes.nullable !== undefined && changes.nullable !== field.nullable && table && column && !ctx.blocked) {
|
|
2465
|
+
if (changes.nullable === false) {
|
|
2466
|
+
const nulls = await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)} WHERE ${ctx.q(field.code)} IS NULL`);
|
|
2467
|
+
const value = request.backfillValue ?? merged.defaultValue ?? null;
|
|
2468
|
+
if (nulls > 0 && value === null) {
|
|
2469
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.NULLS_NEED_VALUE */.M3.NULLS_NEED_VALUE, {
|
|
2470
|
+
count: nulls,
|
|
2471
|
+
field: field.code
|
|
2472
|
+
}));
|
|
2473
|
+
} else if (nulls > 0) {
|
|
2474
|
+
const problem = this.checkValue(merged, value);
|
|
2475
|
+
if (problem) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.BACKFILL_INVALID */.M3.BACKFILL_INVALID, {
|
|
2476
|
+
problem
|
|
2477
|
+
}));
|
|
2478
|
+
else {
|
|
2479
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.BACKFILL_WILL_SET */.Uu.BACKFILL_WILL_SET, {
|
|
2480
|
+
count: nulls,
|
|
2481
|
+
value: JSON.stringify(value)
|
|
2482
|
+
}));
|
|
2483
|
+
await ctx.data((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.BACKFILL_RECORDS */.EQ.BACKFILL_RECORDS, {
|
|
2484
|
+
count: nulls
|
|
2485
|
+
}), `UPDATE ${ctx.q(definition.tableName)} SET ${ctx.q(field.code)} = ${this.adapter.sqlLiteral(this.paramValue(merged.fieldType, value), ctx.driver)} WHERE ${ctx.q(field.code)} IS NULL`, async ()=>{
|
|
2486
|
+
await ctx.qr.query((0,_flusys_nestjs_shared_classes__rspack_import_0.buildQuery)(`UPDATE ${ctx.q(definition.tableName)} SET ${ctx.q(field.code)} = ? WHERE ${ctx.q(field.code)} IS NULL`, ctx.driver), [
|
|
2487
|
+
this.paramValue(merged.fieldType, value)
|
|
2488
|
+
]);
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
if (!ctx.blocked && column.isNullable) {
|
|
2493
|
+
await this.setRequired(ctx, definition.tableName, field.code, merged.fieldType, true);
|
|
2494
|
+
}
|
|
2495
|
+
} else if (!column.isNullable) {
|
|
2496
|
+
await this.setRequired(ctx, definition.tableName, field.code, merged.fieldType, false);
|
|
2497
|
+
}
|
|
2498
|
+
if (!ctx.blocked) patch.nullable = changes.nullable;
|
|
2499
|
+
}
|
|
2500
|
+
// ── unique ──
|
|
2501
|
+
if (changes.unique !== undefined && changes.unique !== field.unique && table && column && !ctx.blocked) {
|
|
2502
|
+
if (changes.unique === true) {
|
|
2503
|
+
const dups = await this.countDuplicates(ctx, definition.tableName, field.code);
|
|
2504
|
+
if (dups > 0) {
|
|
2505
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DUPLICATE_VALUES */.M3.DUPLICATE_VALUES, {
|
|
2506
|
+
count: dups,
|
|
2507
|
+
field: field.code
|
|
2508
|
+
}));
|
|
2509
|
+
} else {
|
|
2510
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_UNIQUE */.EQ.ADD_UNIQUE, {
|
|
2511
|
+
column: field.code
|
|
2512
|
+
}), async ()=>{
|
|
2513
|
+
await (0,_schema_columns_js__rspack_import_17/* .addUnique */.$6)(ctx.qr, table, field.code, ctx.driver, this.adapter);
|
|
2514
|
+
});
|
|
2515
|
+
}
|
|
2516
|
+
} else {
|
|
2517
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.REMOVE_UNIQUE */.EQ.REMOVE_UNIQUE, {
|
|
2518
|
+
column: field.code
|
|
2519
|
+
}), async ()=>this.dropUniques(ctx, table, field.code));
|
|
2520
|
+
}
|
|
2521
|
+
if (!ctx.blocked) patch.unique = changes.unique;
|
|
2522
|
+
}
|
|
2523
|
+
// ── index ──
|
|
2524
|
+
if (changes.isIndexed !== undefined && changes.isIndexed !== field.isIndexed && table && column && !ctx.blocked) {
|
|
2525
|
+
if (changes.isIndexed) {
|
|
2526
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_INDEX */.EQ.ADD_INDEX, {
|
|
2527
|
+
column: field.code
|
|
2528
|
+
}), async ()=>{
|
|
2529
|
+
await ctx.qr.createIndex(table, (0,_schema_columns_js__rspack_import_17/* .plainIndex */.v7)(definition.tableName, field.code, ctx.driver, this.adapter));
|
|
2530
|
+
});
|
|
2531
|
+
} else {
|
|
2532
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.REMOVE_INDEX */.EQ.REMOVE_INDEX, {
|
|
2533
|
+
column: field.code
|
|
2534
|
+
}), async ()=>{
|
|
2535
|
+
for (const idx of this.indexOn(table, field.code, false))await ctx.qr.dropIndex(table, idx);
|
|
2536
|
+
});
|
|
2537
|
+
}
|
|
2538
|
+
patch.isIndexed = changes.isIndexed;
|
|
2539
|
+
}
|
|
2540
|
+
// ── rename ──
|
|
2541
|
+
if (newCode && table && column) {
|
|
2542
|
+
const taken = fields.find((f)=>f.code === newCode);
|
|
2543
|
+
if (taken) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(taken.deprecatedAt ? _config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.FIELD_CODE_TAKEN_DEPRECATED */.M3.FIELD_CODE_TAKEN_DEPRECATED : _config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.FIELD_CODE_TAKEN */.M3.FIELD_CODE_TAKEN, {
|
|
2544
|
+
code: newCode
|
|
2545
|
+
}));
|
|
2546
|
+
if (impact.length && request.rewriteReferences === false) {
|
|
2547
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.RENAME_IN_USE */.M3.RENAME_IN_USE, {
|
|
2548
|
+
field: field.code,
|
|
2549
|
+
references: (0,_schema_change_types_js__rspack_import_22/* .describeImpact */.a)(impact)
|
|
2550
|
+
}));
|
|
2551
|
+
} else if (impact.length) {
|
|
2552
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.REFERENCES_REWRITTEN */.Uu.REFERENCES_REWRITTEN, {
|
|
2553
|
+
count: impact.length,
|
|
2554
|
+
code: newCode
|
|
2555
|
+
}));
|
|
2556
|
+
}
|
|
2557
|
+
if (!ctx.blocked) {
|
|
2558
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RENAME_COLUMN */.EQ.RENAME_COLUMN, {
|
|
2559
|
+
from: field.code,
|
|
2560
|
+
to: newCode
|
|
2561
|
+
}), async ()=>{
|
|
2562
|
+
await ctx.qr.renameColumn(table, field.code, newCode);
|
|
2563
|
+
});
|
|
2564
|
+
// TypeORM moves the index/unique onto the renamed column but keeps its name, which is
|
|
2565
|
+
// derived from the old code - recreate them so a new field with the old code can have its own.
|
|
2566
|
+
if (field.isIndexed && !field.unique) {
|
|
2567
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RENAME_INDEX */.EQ.RENAME_INDEX, {
|
|
2568
|
+
column: field.code
|
|
2569
|
+
}), async ()=>{
|
|
2570
|
+
for (const idx of this.indexOn(table, newCode, false))await ctx.qr.dropIndex(table, idx);
|
|
2571
|
+
await ctx.qr.createIndex(table, (0,_schema_columns_js__rspack_import_17/* .plainIndex */.v7)(definition.tableName, newCode, ctx.driver, this.adapter));
|
|
2572
|
+
});
|
|
2573
|
+
}
|
|
2574
|
+
if (field.unique) {
|
|
2575
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RENAME_INDEX */.EQ.RENAME_INDEX, {
|
|
2576
|
+
column: field.code
|
|
2577
|
+
}), async ()=>{
|
|
2578
|
+
await this.dropUniques(ctx, table, newCode);
|
|
2579
|
+
await (0,_schema_columns_js__rspack_import_17/* .addUnique */.$6)(ctx.qr, table, newCode, ctx.driver, this.adapter);
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
patch.code = newCode;
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
if (ctx.blocked) return {
|
|
2586
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ALTER_FIELD */.i.ALTER_FIELD,
|
|
2587
|
+
fieldDefinitionId: field.id,
|
|
2588
|
+
diff: {}
|
|
2589
|
+
};
|
|
2590
|
+
await ctx.metadata(async ()=>{
|
|
2591
|
+
if (Object.keys(patch).length) await ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c).update(field.id, patch);
|
|
2592
|
+
if (newCode && request.rewriteReferences !== false) {
|
|
2593
|
+
await this.references.rewriteFieldCode(definition.code, field.code, newCode, ctx.qr.manager);
|
|
2594
|
+
}
|
|
2595
|
+
});
|
|
2596
|
+
const metadataOnly = !structural.length && !newCode;
|
|
2597
|
+
return {
|
|
2598
|
+
operation: newCode ? _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.RENAME_FIELD */.i.RENAME_FIELD : _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ALTER_FIELD */.i.ALTER_FIELD,
|
|
2599
|
+
fieldDefinitionId: field.id,
|
|
2600
|
+
diff: {
|
|
2601
|
+
field: field.code,
|
|
2602
|
+
changed: Object.keys(patch),
|
|
2603
|
+
before: Object.fromEntries(Object.keys(patch).map((k)=>[
|
|
2604
|
+
k,
|
|
2605
|
+
field[k]
|
|
2606
|
+
])),
|
|
2607
|
+
after: patch
|
|
2608
|
+
},
|
|
2609
|
+
bumpVersion: !metadataOnly || Object.keys(patch).some((k)=>[
|
|
2610
|
+
'selectOptions',
|
|
2611
|
+
'validationRules',
|
|
2612
|
+
'defaultValue',
|
|
2613
|
+
'label',
|
|
2614
|
+
'relationTargetEntityId'
|
|
2615
|
+
].includes(k))
|
|
2616
|
+
};
|
|
2617
|
+
};
|
|
2618
|
+
return {
|
|
2619
|
+
target: this.target('update_field', loaded, user, lockCodes),
|
|
2620
|
+
run,
|
|
2621
|
+
impact
|
|
2622
|
+
};
|
|
2623
|
+
}
|
|
2624
|
+
// ── deprecate / restore / purge ─────────────────────────────────────────────────────
|
|
2625
|
+
async prepareDeprecateField(request, user) {
|
|
2626
|
+
const { field: loadedField, definition: loaded } = await this.loadField(request.fieldDefinitionId);
|
|
2627
|
+
const impact = await this.references.forField(loaded.code, loadedField.code);
|
|
2628
|
+
const run = async (ctx)=>{
|
|
2629
|
+
const { definition, field } = await this.current(ctx, request, loaded.id, loadedField.id);
|
|
2630
|
+
if (field.code !== loadedField.code) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DEFINITION_CHANGED */.M3.DEFINITION_CHANGED));
|
|
2631
|
+
if (field.deprecatedAt) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.ALREADY_DEPRECATED */.M3.ALREADY_DEPRECATED, {
|
|
2632
|
+
field: field.code
|
|
2633
|
+
}));
|
|
2634
|
+
if (impact.length) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.STILL_REFERENCED */.Uu.STILL_REFERENCED, {
|
|
2635
|
+
references: (0,_schema_change_types_js__rspack_import_22/* .describeImpact */.a)(impact)
|
|
2636
|
+
}));
|
|
2637
|
+
const table = await this.requireTable(ctx, definition.tableName);
|
|
2638
|
+
const column = table?.findColumnByName(field.code);
|
|
2639
|
+
if (ctx.blocked) return {
|
|
2640
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.MARK_DEPRECATED */.i.MARK_DEPRECATED,
|
|
2641
|
+
fieldDefinitionId: field.id,
|
|
2642
|
+
diff: {}
|
|
2643
|
+
};
|
|
2644
|
+
// A hidden NOT NULL column would make every new record fail (nobody supplies it any more).
|
|
2645
|
+
if (column && !column.isNullable) {
|
|
2646
|
+
await this.setRequired(ctx, definition.tableName, field.code, field.fieldType, false, _config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RELAX_DEPRECATED */.EQ.RELAX_DEPRECATED);
|
|
2647
|
+
}
|
|
2648
|
+
await ctx.metadata(async ()=>{
|
|
2649
|
+
await ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c).update(field.id, {
|
|
2650
|
+
deprecatedAt: new Date(),
|
|
2651
|
+
nullable: true
|
|
2652
|
+
});
|
|
2653
|
+
});
|
|
2654
|
+
return {
|
|
2655
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.MARK_DEPRECATED */.i.MARK_DEPRECATED,
|
|
2656
|
+
fieldDefinitionId: field.id,
|
|
2657
|
+
diff: {
|
|
2658
|
+
field: field.code
|
|
2659
|
+
}
|
|
2660
|
+
};
|
|
2661
|
+
};
|
|
2662
|
+
return {
|
|
2663
|
+
target: this.target('deprecate_field', loaded, user),
|
|
2664
|
+
run,
|
|
2665
|
+
impact
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
async prepareRestoreField(request, user) {
|
|
2669
|
+
const { field: loadedField, definition: loaded } = await this.loadField(request.fieldDefinitionId);
|
|
2670
|
+
const run = async (ctx)=>{
|
|
2671
|
+
const { definition, field } = await this.current(ctx, request, loaded.id, loadedField.id);
|
|
2672
|
+
if (!field.deprecatedAt) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.NOT_DEPRECATED */.M3.NOT_DEPRECATED, {
|
|
2673
|
+
field: field.code
|
|
2674
|
+
}));
|
|
2675
|
+
const table = await this.requireTable(ctx, definition.tableName);
|
|
2676
|
+
if (table && !table.findColumnByName(field.code)) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.COLUMN_GONE */.M3.COLUMN_GONE, {
|
|
2677
|
+
column: field.code
|
|
2678
|
+
}));
|
|
2679
|
+
if (ctx.blocked) return {
|
|
2680
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.RESTORE_FIELD */.i.RESTORE_FIELD,
|
|
2681
|
+
fieldDefinitionId: field.id,
|
|
2682
|
+
diff: {}
|
|
2683
|
+
};
|
|
2684
|
+
await ctx.metadata(async ()=>{
|
|
2685
|
+
await ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c).update(field.id, {
|
|
2686
|
+
deprecatedAt: null
|
|
2687
|
+
});
|
|
2688
|
+
});
|
|
2689
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.FIELD_OPTIONAL_AGAIN */.Uu.FIELD_OPTIONAL_AGAIN));
|
|
2690
|
+
return {
|
|
2691
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.RESTORE_FIELD */.i.RESTORE_FIELD,
|
|
2692
|
+
fieldDefinitionId: field.id,
|
|
2693
|
+
diff: {
|
|
2694
|
+
field: field.code
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
};
|
|
2698
|
+
return {
|
|
2699
|
+
target: this.target('restore_field', loaded, user),
|
|
2700
|
+
run,
|
|
2701
|
+
impact: []
|
|
2702
|
+
};
|
|
2703
|
+
}
|
|
2704
|
+
async preparePurgeField(request, user) {
|
|
2705
|
+
const { field: loadedField, definition: loaded } = await this.loadField(request.fieldDefinitionId);
|
|
2706
|
+
const impact = await this.references.forField(loaded.code, loadedField.code);
|
|
2707
|
+
const run = async (ctx)=>{
|
|
2708
|
+
const { definition, field } = await this.current(ctx, request, loaded.id, loadedField.id);
|
|
2709
|
+
if (this.changedUnderneath(ctx, loadedField, field)) return {
|
|
2710
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.DROP_COLUMN */.i.DROP_COLUMN,
|
|
2711
|
+
fieldDefinitionId: field.id,
|
|
2712
|
+
diff: {}
|
|
2713
|
+
};
|
|
2714
|
+
if (!field.deprecatedAt) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.PURGE_REQUIRES_DEPRECATED */.M3.PURGE_REQUIRES_DEPRECATED));
|
|
2715
|
+
if (request.confirmCode !== field.code) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.PURGE_CONFIRM_CODE */.M3.PURGE_CONFIRM_CODE, {
|
|
2716
|
+
code: field.code
|
|
2717
|
+
}));
|
|
2718
|
+
if (impact.length) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.PURGE_IN_USE */.M3.PURGE_IN_USE, {
|
|
2719
|
+
field: field.code,
|
|
2720
|
+
references: (0,_schema_change_types_js__rspack_import_22/* .describeImpact */.a)(impact)
|
|
2721
|
+
}));
|
|
2722
|
+
const table = await this.requireTable(ctx, definition.tableName);
|
|
2723
|
+
const column = table?.findColumnByName(field.code);
|
|
2724
|
+
if (ctx.blocked) return {
|
|
2725
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.DROP_COLUMN */.i.DROP_COLUMN,
|
|
2726
|
+
fieldDefinitionId: field.id,
|
|
2727
|
+
diff: {}
|
|
2728
|
+
};
|
|
2729
|
+
if (table && column) {
|
|
2730
|
+
const values = await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)} WHERE ${ctx.q(field.code)} IS NOT NULL`);
|
|
2731
|
+
ctx.setAffectedRows(values);
|
|
2732
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.VALUES_DELETED */.Uu.VALUES_DELETED, {
|
|
2733
|
+
count: values
|
|
2734
|
+
}));
|
|
2735
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.DROP_COLUMN */.EQ.DROP_COLUMN, {
|
|
2736
|
+
column: field.code
|
|
2737
|
+
}), async ()=>{
|
|
2738
|
+
await ctx.qr.dropColumn(table, column);
|
|
2739
|
+
});
|
|
2740
|
+
} else {
|
|
2741
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.COLUMN_ALREADY_MISSING */.Uu.COLUMN_ALREADY_MISSING));
|
|
2742
|
+
}
|
|
2743
|
+
ctx.markDestructive();
|
|
2744
|
+
await ctx.metadata(async ()=>{
|
|
2745
|
+
await ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c).delete(field.id);
|
|
2746
|
+
});
|
|
2747
|
+
return {
|
|
2748
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.DROP_COLUMN */.i.DROP_COLUMN,
|
|
2749
|
+
fieldDefinitionId: null,
|
|
2750
|
+
diff: {
|
|
2751
|
+
field: field.code,
|
|
2752
|
+
fieldType: field.fieldType
|
|
2753
|
+
}
|
|
2754
|
+
};
|
|
2755
|
+
};
|
|
2756
|
+
return {
|
|
2757
|
+
target: this.target('purge_field', loaded, user),
|
|
2758
|
+
run,
|
|
2759
|
+
impact
|
|
2760
|
+
};
|
|
2761
|
+
}
|
|
2762
|
+
// ── entity level ────────────────────────────────────────────────────────────────────
|
|
2763
|
+
async prepareUpdateEntity(request, user) {
|
|
2764
|
+
const { definition: loaded } = await this.loadEntity(request.entityDefinitionId);
|
|
2765
|
+
const changes = request.changes ?? {};
|
|
2766
|
+
this.rejectUnknownKeys(changes, _dtos_schema_change_dto_js__rspack_import_6/* .ENTITY_CHANGE_KEYS */.Oi, 'entity');
|
|
2767
|
+
if (changes.status !== undefined && ![
|
|
2768
|
+
_enums_entity_status_enum_js__rspack_import_23/* .EntityStatus.ACTIVE */.c.ACTIVE,
|
|
2769
|
+
_enums_entity_status_enum_js__rspack_import_23/* .EntityStatus.DEPRECATED */.c.DEPRECATED
|
|
2770
|
+
].includes(changes.status)) {
|
|
2771
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
2772
|
+
message: "status must be 'ACTIVE' or 'DEPRECATED'.",
|
|
2773
|
+
messageKey: _config_message_keys_js__rspack_import_19/* .ENTITY_DEFINITION_MESSAGES.INVALID_STATUS */.pL.INVALID_STATUS
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
2776
|
+
this.validateChanges(_dtos_schema_change_dto_js__rspack_import_6/* .EntityChangesDto */.OW, changes);
|
|
2777
|
+
const impact = changes.status === _enums_entity_status_enum_js__rspack_import_23/* .EntityStatus.DEPRECATED */.c.DEPRECATED ? await this.references.forEntity(loaded.code) : [];
|
|
2778
|
+
const run = async (ctx)=>{
|
|
2779
|
+
const { definition } = await this.current(ctx, request, loaded.id);
|
|
2780
|
+
const patch = {};
|
|
2781
|
+
for (const key of [
|
|
2782
|
+
'label',
|
|
2783
|
+
'description',
|
|
2784
|
+
'uiConfig',
|
|
2785
|
+
'status'
|
|
2786
|
+
]){
|
|
2787
|
+
if (key in changes) patch[key] = changes[key];
|
|
2788
|
+
}
|
|
2789
|
+
const wantsSoft = changes.isSoftDeleteEnabled;
|
|
2790
|
+
const wantsAudit = changes.isAuditEnabled;
|
|
2791
|
+
const touchesColumns = wantsSoft === true && !definition.isSoftDeleteEnabled || wantsAudit === true && !definition.isAuditEnabled;
|
|
2792
|
+
const table = touchesColumns ? await this.requireTable(ctx, definition.tableName) : undefined;
|
|
2793
|
+
if (ctx.blocked) return {
|
|
2794
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ALTER_ENTITY */.i.ALTER_ENTITY,
|
|
2795
|
+
diff: {}
|
|
2796
|
+
};
|
|
2797
|
+
if (wantsSoft !== undefined && wantsSoft !== definition.isSoftDeleteEnabled) {
|
|
2798
|
+
if (wantsSoft && table) {
|
|
2799
|
+
if (!table.findColumnByName('deleted_at')) {
|
|
2800
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_DELETED_AT */.EQ.ADD_DELETED_AT), async ()=>{
|
|
2801
|
+
await ctx.qr.addColumn(table, (0,_schema_columns_js__rspack_import_17/* .softDeleteColumn */.OG)());
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
} else if (!wantsSoft) {
|
|
2805
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.SOFT_DELETE_OFF */.Uu.SOFT_DELETE_OFF));
|
|
2806
|
+
ctx.markDestructive();
|
|
2807
|
+
}
|
|
2808
|
+
patch.isSoftDeleteEnabled = wantsSoft;
|
|
2809
|
+
}
|
|
2810
|
+
if (wantsAudit !== undefined && wantsAudit !== definition.isAuditEnabled) {
|
|
2811
|
+
if (wantsAudit && table) {
|
|
2812
|
+
const missing = (0,_schema_columns_js__rspack_import_17/* .auditColumns */.HK)(ctx.driver).filter((c)=>!table.findColumnByName(c.name));
|
|
2813
|
+
if (missing.length) {
|
|
2814
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_AUDIT_COLUMNS */.EQ.ADD_AUDIT_COLUMNS), async ()=>{
|
|
2815
|
+
for (const c of missing)await ctx.qr.addColumn(table, c);
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
} else if (!wantsAudit) {
|
|
2819
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.AUDIT_OFF */.Uu.AUDIT_OFF));
|
|
2820
|
+
}
|
|
2821
|
+
patch.isAuditEnabled = wantsAudit;
|
|
2822
|
+
}
|
|
2823
|
+
if (changes.status === _enums_entity_status_enum_js__rspack_import_23/* .EntityStatus.DEPRECATED */.c.DEPRECATED && impact.length) {
|
|
2824
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.ENTITY_REFERENCED */.Uu.ENTITY_REFERENCED, {
|
|
2825
|
+
count: impact.length
|
|
2826
|
+
}));
|
|
2827
|
+
}
|
|
2828
|
+
await ctx.metadata(async ()=>{
|
|
2829
|
+
if (Object.keys(patch).length) await ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f).update(definition.id, patch);
|
|
2830
|
+
});
|
|
2831
|
+
return {
|
|
2832
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ALTER_ENTITY */.i.ALTER_ENTITY,
|
|
2833
|
+
diff: {
|
|
2834
|
+
changed: Object.keys(patch),
|
|
2835
|
+
after: patch
|
|
2836
|
+
}
|
|
2837
|
+
};
|
|
2838
|
+
};
|
|
2839
|
+
return {
|
|
2840
|
+
target: this.target('update_entity', loaded, user),
|
|
2841
|
+
run,
|
|
2842
|
+
impact
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2845
|
+
/** `"orders.customer_id", ...` - relation fields of other entities that point at this one. */ async relationsInto(ctx, definition) {
|
|
2846
|
+
const pointing = (await ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c).find({
|
|
2847
|
+
where: {
|
|
2848
|
+
relationTargetEntityId: definition.id
|
|
2849
|
+
}
|
|
2850
|
+
})).filter((f)=>f.entityDefinitionId !== definition.id);
|
|
2851
|
+
if (!pointing.length) return null;
|
|
2852
|
+
const owners = await ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f).find({
|
|
2853
|
+
where: {
|
|
2854
|
+
id: (0,typeorm__rspack_import_5.In)([
|
|
2855
|
+
...new Set(pointing.map((f)=>f.entityDefinitionId))
|
|
2856
|
+
])
|
|
2857
|
+
}
|
|
2858
|
+
});
|
|
2859
|
+
const codeOf = new Map(owners.map((o)=>[
|
|
2860
|
+
o.id,
|
|
2861
|
+
o.code
|
|
2862
|
+
]));
|
|
2863
|
+
return pointing.map((f)=>`"${codeOf.get(f.entityDefinitionId) ?? f.entityDefinitionId}.${f.code}"`).join(', ');
|
|
2864
|
+
}
|
|
2865
|
+
async prepareDropEntity(request, user) {
|
|
2866
|
+
const { definition: loaded } = await this.loadEntity(request.entityDefinitionId);
|
|
2867
|
+
const impact = await this.references.forEntity(loaded.code);
|
|
2868
|
+
const run = async (ctx)=>{
|
|
2869
|
+
const { definition } = await this.current(ctx, request, loaded.id);
|
|
2870
|
+
if (request.confirmCode !== definition.code) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DROP_CONFIRM_CODE */.M3.DROP_CONFIRM_CODE, {
|
|
2871
|
+
code: definition.code
|
|
2872
|
+
}));
|
|
2873
|
+
if (impact.length) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DROP_IN_USE */.M3.DROP_IN_USE, {
|
|
2874
|
+
references: (0,_schema_change_types_js__rspack_import_22/* .describeImpact */.a)(impact)
|
|
2875
|
+
}));
|
|
2876
|
+
const relations = await this.relationsInto(ctx, definition);
|
|
2877
|
+
if (relations) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_BLOCKER_MESSAGES.DROP_RELATION_IN_USE */.M3.DROP_RELATION_IN_USE, {
|
|
2878
|
+
fields: relations
|
|
2879
|
+
}));
|
|
2880
|
+
const table = await ctx.qr.getTable(definition.tableName);
|
|
2881
|
+
if (ctx.blocked) return {
|
|
2882
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.DROP_TABLE */.i.DROP_TABLE,
|
|
2883
|
+
diff: {}
|
|
2884
|
+
};
|
|
2885
|
+
if (table) {
|
|
2886
|
+
const rows = await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)}`);
|
|
2887
|
+
ctx.setAffectedRows(rows);
|
|
2888
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.RECORDS_DELETED */.Uu.RECORDS_DELETED, {
|
|
2889
|
+
count: rows
|
|
2890
|
+
}));
|
|
2891
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.DROP_TABLE */.EQ.DROP_TABLE, {
|
|
2892
|
+
table: definition.tableName
|
|
2893
|
+
}), async ()=>{
|
|
2894
|
+
await ctx.qr.dropTable(table);
|
|
2895
|
+
});
|
|
2896
|
+
} else {
|
|
2897
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.TABLE_ALREADY_MISSING */.Uu.TABLE_ALREADY_MISSING));
|
|
2898
|
+
}
|
|
2899
|
+
ctx.markDestructive();
|
|
2900
|
+
await ctx.metadata(async ()=>{
|
|
2901
|
+
await ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c).delete({
|
|
2902
|
+
entityDefinitionId: definition.id
|
|
2903
|
+
});
|
|
2904
|
+
await ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f).delete(definition.id);
|
|
2905
|
+
});
|
|
2906
|
+
return {
|
|
2907
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.DROP_TABLE */.i.DROP_TABLE,
|
|
2908
|
+
diff: {
|
|
2909
|
+
entity: definition.code
|
|
2910
|
+
},
|
|
2911
|
+
bumpVersion: false,
|
|
2912
|
+
afterCommit: async ()=>this.permissions.deprovisionForEntity(definition)
|
|
2913
|
+
};
|
|
2914
|
+
};
|
|
2915
|
+
return {
|
|
2916
|
+
target: this.target('drop_entity', loaded, user),
|
|
2917
|
+
run,
|
|
2918
|
+
impact
|
|
2919
|
+
};
|
|
2920
|
+
}
|
|
2921
|
+
// ── inspection and repair ───────────────────────────────────────────────────────────
|
|
2922
|
+
diff(definition, fields, table, driver) {
|
|
2923
|
+
const findings = [];
|
|
2924
|
+
if (!table) {
|
|
2925
|
+
findings.push({
|
|
2926
|
+
kind: 'missing_table',
|
|
2927
|
+
severity: 'error',
|
|
2928
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.MISSING_TABLE */.Vu.MISSING_TABLE, {
|
|
2929
|
+
table: definition.tableName
|
|
2930
|
+
}),
|
|
2931
|
+
repairable: true
|
|
2932
|
+
});
|
|
2933
|
+
return findings;
|
|
2934
|
+
}
|
|
2935
|
+
const known = new Set([
|
|
2936
|
+
'id',
|
|
2937
|
+
'created_at',
|
|
2938
|
+
'updated_at'
|
|
2939
|
+
]);
|
|
2940
|
+
if (definition.isSoftDeleteEnabled) known.add('deleted_at');
|
|
2941
|
+
if (definition.isAuditEnabled) (0,_schema_columns_js__rspack_import_17/* .auditColumns */.HK)(driver).forEach((c)=>known.add(c.name));
|
|
2942
|
+
for (const name of known){
|
|
2943
|
+
if (!table.findColumnByName(name)) {
|
|
2944
|
+
findings.push({
|
|
2945
|
+
kind: 'missing_column',
|
|
2946
|
+
severity: 'error',
|
|
2947
|
+
field: name,
|
|
2948
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.SYSTEM_COLUMN_MISSING */.Vu.SYSTEM_COLUMN_MISSING, {
|
|
2949
|
+
column: name
|
|
2950
|
+
}),
|
|
2951
|
+
repairable: name !== 'id'
|
|
2952
|
+
});
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
for (const field of fields){
|
|
2956
|
+
known.add(field.code);
|
|
2957
|
+
const column = table.findColumnByName(field.code);
|
|
2958
|
+
if (!column) {
|
|
2959
|
+
findings.push({
|
|
2960
|
+
kind: 'missing_column',
|
|
2961
|
+
severity: field.deprecatedAt ? 'warning' : 'error',
|
|
2962
|
+
field: field.code,
|
|
2963
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.COLUMN_MISSING */.Vu.COLUMN_MISSING, {
|
|
2964
|
+
column: field.code
|
|
2965
|
+
}),
|
|
2966
|
+
repairable: true
|
|
2967
|
+
});
|
|
2968
|
+
continue;
|
|
2969
|
+
}
|
|
2970
|
+
const expected = (0,_schema_columns_js__rspack_import_17/* .typeFamily */.jp)(this.adapter.mapFieldType(field.fieldType, driver));
|
|
2971
|
+
const actual = (0,_schema_columns_js__rspack_import_17/* .typeFamily */.jp)(column.type);
|
|
2972
|
+
const uuidAsChar = expected === 'uuid' && actual === 'varchar';
|
|
2973
|
+
if (expected !== actual && !uuidAsChar) {
|
|
2974
|
+
findings.push({
|
|
2975
|
+
kind: 'type_mismatch',
|
|
2976
|
+
severity: 'error',
|
|
2977
|
+
field: field.code,
|
|
2978
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.TYPE_MISMATCH */.Vu.TYPE_MISMATCH, {
|
|
2979
|
+
column: field.code,
|
|
2980
|
+
actual: column.type,
|
|
2981
|
+
fieldType: field.fieldType,
|
|
2982
|
+
expected
|
|
2983
|
+
}),
|
|
2984
|
+
repairable: false
|
|
2985
|
+
});
|
|
2986
|
+
}
|
|
2987
|
+
if (!field.deprecatedAt && !field.nullable && column.isNullable) {
|
|
2988
|
+
findings.push({
|
|
2989
|
+
kind: 'nullability_mismatch',
|
|
2990
|
+
severity: 'warning',
|
|
2991
|
+
field: field.code,
|
|
2992
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.REQUIRED_BUT_NULLABLE */.Vu.REQUIRED_BUT_NULLABLE, {
|
|
2993
|
+
column: field.code
|
|
2994
|
+
}),
|
|
2995
|
+
repairable: true
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
if (field.nullable && !column.isNullable) {
|
|
2999
|
+
findings.push({
|
|
3000
|
+
kind: 'nullability_mismatch',
|
|
3001
|
+
severity: 'warning',
|
|
3002
|
+
field: field.code,
|
|
3003
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.OPTIONAL_BUT_NOT_NULL */.Vu.OPTIONAL_BUT_NOT_NULL, {
|
|
3004
|
+
column: field.code
|
|
3005
|
+
}),
|
|
3006
|
+
repairable: true
|
|
3007
|
+
});
|
|
3008
|
+
}
|
|
3009
|
+
if (field.isIndexed && !field.unique && this.indexOn(table, field.code, false).length === 0) {
|
|
3010
|
+
findings.push({
|
|
3011
|
+
kind: 'missing_index',
|
|
3012
|
+
severity: 'warning',
|
|
3013
|
+
field: field.code,
|
|
3014
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.INDEX_MISSING */.Vu.INDEX_MISSING, {
|
|
3015
|
+
column: field.code
|
|
3016
|
+
}),
|
|
3017
|
+
repairable: true
|
|
3018
|
+
});
|
|
3019
|
+
}
|
|
3020
|
+
if (field.unique && !this.hasUnique(table, field.code)) {
|
|
3021
|
+
findings.push({
|
|
3022
|
+
kind: 'missing_unique',
|
|
3023
|
+
severity: 'warning',
|
|
3024
|
+
field: field.code,
|
|
3025
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.UNIQUE_MISSING */.Vu.UNIQUE_MISSING, {
|
|
3026
|
+
column: field.code
|
|
3027
|
+
}),
|
|
3028
|
+
repairable: true
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
if (field.dbType && field.dbType !== this.adapter.mapFieldType(field.fieldType, driver)) {
|
|
3032
|
+
findings.push({
|
|
3033
|
+
kind: 'stale_metadata',
|
|
3034
|
+
severity: 'warning',
|
|
3035
|
+
field: field.code,
|
|
3036
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.STALE_METADATA */.Vu.STALE_METADATA, {
|
|
3037
|
+
dbType: field.dbType,
|
|
3038
|
+
driver,
|
|
3039
|
+
fieldType: field.fieldType
|
|
3040
|
+
}),
|
|
3041
|
+
repairable: false
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
for (const column of table.columns){
|
|
3046
|
+
if (!known.has(column.name)) {
|
|
3047
|
+
findings.push({
|
|
3048
|
+
kind: 'extra_column',
|
|
3049
|
+
severity: 'warning',
|
|
3050
|
+
field: column.name,
|
|
3051
|
+
...(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_FINDING_MESSAGES.EXTRA_COLUMN */.Vu.EXTRA_COLUMN, {
|
|
3052
|
+
column: column.name
|
|
3053
|
+
}),
|
|
3054
|
+
repairable: false
|
|
3055
|
+
});
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
return findings;
|
|
3059
|
+
}
|
|
3060
|
+
async prepareRepair(request, user) {
|
|
3061
|
+
const { definition: loaded } = await this.loadEntity(request.entityDefinitionId);
|
|
3062
|
+
const run = async (ctx)=>{
|
|
3063
|
+
const { definition, fields } = await this.current(ctx, request, loaded.id);
|
|
3064
|
+
const table = await ctx.qr.getTable(definition.tableName);
|
|
3065
|
+
const findings = this.diff(definition, fields, table ?? undefined, ctx.driver);
|
|
3066
|
+
// Only what a statement actually ran for - a finding that is skipped or only warned about is not "fixed".
|
|
3067
|
+
const fixed = [];
|
|
3068
|
+
if (!table) {
|
|
3069
|
+
const columns = [
|
|
3070
|
+
...(0,_schema_columns_js__rspack_import_17/* .buildSystemColumns */.Rm)(definition, ctx.driver),
|
|
3071
|
+
...fields.map((f)=>(0,_schema_columns_js__rspack_import_17/* .buildFieldColumn */.fu)(f, ctx.driver, this.adapter, {
|
|
3072
|
+
enforceNotNull: false,
|
|
3073
|
+
withUnique: false
|
|
3074
|
+
}))
|
|
3075
|
+
];
|
|
3076
|
+
const uniques = fields.filter((f)=>f.unique).map((f)=>(0,_schema_columns_js__rspack_import_17/* .tableUnique */.uy)(definition.tableName, f.code, ctx.driver, this.adapter));
|
|
3077
|
+
const recreated = new typeorm__rspack_import_5.Table({
|
|
3078
|
+
name: definition.tableName,
|
|
3079
|
+
columns,
|
|
3080
|
+
uniques
|
|
3081
|
+
});
|
|
3082
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RECREATE_TABLE */.EQ.RECREATE_TABLE, {
|
|
3083
|
+
table: definition.tableName
|
|
3084
|
+
}), async ()=>{
|
|
3085
|
+
await ctx.qr.createTable(recreated, false);
|
|
3086
|
+
});
|
|
3087
|
+
fixed.push('missing_table');
|
|
3088
|
+
for (const indexed of fields.filter((f)=>f.isIndexed && !f.unique)){
|
|
3089
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RECREATE_INDEX */.EQ.RECREATE_INDEX, {
|
|
3090
|
+
column: indexed.code
|
|
3091
|
+
}), async ()=>{
|
|
3092
|
+
await ctx.qr.createIndex(recreated, (0,_schema_columns_js__rspack_import_17/* .plainIndex */.v7)(definition.tableName, indexed.code, ctx.driver, this.adapter));
|
|
3093
|
+
});
|
|
3094
|
+
fixed.push(`missing_index:${indexed.code}`);
|
|
3095
|
+
}
|
|
3096
|
+
ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.TABLE_RECREATED_EMPTY */.Uu.TABLE_RECREATED_EMPTY));
|
|
3097
|
+
ctx.markDestructive();
|
|
3098
|
+
return {
|
|
3099
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.REPAIR */.i.REPAIR,
|
|
3100
|
+
diff: {
|
|
3101
|
+
fixed,
|
|
3102
|
+
manual: 0
|
|
3103
|
+
}
|
|
3104
|
+
};
|
|
3105
|
+
}
|
|
3106
|
+
for (const finding of findings){
|
|
3107
|
+
if (!finding.repairable || !finding.field) continue;
|
|
3108
|
+
const field = fields.find((f)=>f.code === finding.field);
|
|
3109
|
+
switch(finding.kind){
|
|
3110
|
+
case 'missing_column':
|
|
3111
|
+
{
|
|
3112
|
+
if (!field) {
|
|
3113
|
+
const sys = [
|
|
3114
|
+
(0,_schema_columns_js__rspack_import_17/* .softDeleteColumn */.OG)(),
|
|
3115
|
+
...(0,_schema_columns_js__rspack_import_17/* .auditColumns */.HK)(ctx.driver)
|
|
3116
|
+
].find((c)=>c.name === finding.field);
|
|
3117
|
+
if (!sys) break;
|
|
3118
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_SYSTEM_COLUMN */.EQ.ADD_SYSTEM_COLUMN, {
|
|
3119
|
+
column: sys.name
|
|
3120
|
+
}), async ()=>ctx.qr.addColumn(table, sys));
|
|
3121
|
+
} else {
|
|
3122
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.ADD_MISSING_COLUMN */.EQ.ADD_MISSING_COLUMN, {
|
|
3123
|
+
column: field.code
|
|
3124
|
+
}), async ()=>{
|
|
3125
|
+
await ctx.qr.addColumn(table, (0,_schema_columns_js__rspack_import_17/* .buildFieldColumn */.fu)(field, ctx.driver, this.adapter, {
|
|
3126
|
+
enforceNotNull: false,
|
|
3127
|
+
withUnique: false
|
|
3128
|
+
}));
|
|
3129
|
+
});
|
|
3130
|
+
// Re-added columns start empty, so a required field stays nullable until its records have values.
|
|
3131
|
+
const rows = !field.nullable && !field.deprecatedAt ? await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)}`) : 0;
|
|
3132
|
+
if (rows > 0) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.REQUIRED_HAS_NULLS */.Uu.REQUIRED_HAS_NULLS, {
|
|
3133
|
+
field: field.code,
|
|
3134
|
+
count: rows
|
|
3135
|
+
}));
|
|
3136
|
+
}
|
|
3137
|
+
fixed.push(`missing_column:${finding.field}`);
|
|
3138
|
+
break;
|
|
3139
|
+
}
|
|
3140
|
+
case 'missing_index':
|
|
3141
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RECREATE_INDEX */.EQ.RECREATE_INDEX, {
|
|
3142
|
+
column: finding.field
|
|
3143
|
+
}), async ()=>{
|
|
3144
|
+
await ctx.qr.createIndex(table, (0,_schema_columns_js__rspack_import_17/* .plainIndex */.v7)(definition.tableName, finding.field, ctx.driver, this.adapter));
|
|
3145
|
+
});
|
|
3146
|
+
fixed.push(`missing_index:${finding.field}`);
|
|
3147
|
+
break;
|
|
3148
|
+
case 'missing_unique':
|
|
3149
|
+
{
|
|
3150
|
+
const code = finding.field;
|
|
3151
|
+
const dups = await this.countDuplicates(ctx, definition.tableName, code);
|
|
3152
|
+
if (dups > 0) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.UNIQUE_NOT_RECREATED */.Uu.UNIQUE_NOT_RECREATED, {
|
|
3153
|
+
field: code,
|
|
3154
|
+
count: dups
|
|
3155
|
+
}));
|
|
3156
|
+
else {
|
|
3157
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_STEP_MESSAGES.RECREATE_UNIQUE */.EQ.RECREATE_UNIQUE, {
|
|
3158
|
+
column: code
|
|
3159
|
+
}), async ()=>{
|
|
3160
|
+
await (0,_schema_columns_js__rspack_import_17/* .addUnique */.$6)(ctx.qr, table, code, ctx.driver, this.adapter);
|
|
3161
|
+
});
|
|
3162
|
+
fixed.push(`missing_unique:${finding.field}`);
|
|
3163
|
+
}
|
|
3164
|
+
break;
|
|
3165
|
+
}
|
|
3166
|
+
case 'nullability_mismatch':
|
|
3167
|
+
{
|
|
3168
|
+
const column = field && table.findColumnByName(field.code);
|
|
3169
|
+
if (!field || !column) break;
|
|
3170
|
+
if (!field.nullable && column.isNullable) {
|
|
3171
|
+
const nulls = await this.scalar(ctx, `SELECT COUNT(*) AS c FROM ${ctx.q(definition.tableName)} WHERE ${ctx.q(field.code)} IS NULL`);
|
|
3172
|
+
if (nulls > 0) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.REQUIRED_HAS_NULLS */.Uu.REQUIRED_HAS_NULLS, {
|
|
3173
|
+
field: field.code,
|
|
3174
|
+
count: nulls
|
|
3175
|
+
}));
|
|
3176
|
+
else {
|
|
3177
|
+
await this.setRequired(ctx, definition.tableName, field.code, field.fieldType, true);
|
|
3178
|
+
fixed.push(`nullability:${field.code}`);
|
|
3179
|
+
}
|
|
3180
|
+
} else if (field.nullable && !column.isNullable) {
|
|
3181
|
+
await this.setRequired(ctx, definition.tableName, field.code, field.fieldType, false);
|
|
3182
|
+
fixed.push(`nullability:${field.code}`);
|
|
3183
|
+
}
|
|
3184
|
+
break;
|
|
3185
|
+
}
|
|
3186
|
+
default:
|
|
3187
|
+
break;
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
const manual = findings.filter((f)=>!f.repairable);
|
|
3191
|
+
for (const f of manual)ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.NEEDS_MANUAL_ATTENTION */.Uu.NEEDS_MANUAL_ATTENTION, {
|
|
3192
|
+
finding: (0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(f.messageKey, f.messageVariables)
|
|
3193
|
+
}));
|
|
3194
|
+
if (fixed.length === 0 && manual.length === 0) ctx.warn((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_19/* .SCHEMA_WARNING_MESSAGES.NOTHING_TO_REPAIR */.Uu.NOTHING_TO_REPAIR));
|
|
3195
|
+
return {
|
|
3196
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.REPAIR */.i.REPAIR,
|
|
3197
|
+
diff: {
|
|
3198
|
+
fixed,
|
|
3199
|
+
manual: manual.length
|
|
3200
|
+
},
|
|
3201
|
+
bumpVersion: fixed.length > 0
|
|
3202
|
+
};
|
|
3203
|
+
};
|
|
3204
|
+
return {
|
|
3205
|
+
target: this.target('repair', loaded, user),
|
|
3206
|
+
run,
|
|
3207
|
+
impact: []
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
SchemaEvolutionService = _ts_decorate([
|
|
3212
|
+
(0,_nestjs_common__rspack_import_2.Injectable)({
|
|
3213
|
+
scope: _nestjs_common__rspack_import_2.Scope.REQUEST
|
|
3214
|
+
}),
|
|
3215
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_2.Inject)(_entity_builder_datasource_provider_js__rspack_import_10/* .EntityBuilderDataSourceProvider */.D)),
|
|
3216
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_2.Inject)(_schema_dialect_adapter_service_js__rspack_import_18/* .SchemaDialectAdapterService */.I)),
|
|
3217
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_2.Inject)(_schema_change_executor_service_js__rspack_import_16/* .SchemaChangeExecutor */.T)),
|
|
3218
|
+
_ts_param(3, (0,_nestjs_common__rspack_import_2.Inject)(_reference_scanner_service_js__rspack_import_15/* .ReferenceScannerService */.t)),
|
|
3219
|
+
_ts_param(4, (0,_nestjs_common__rspack_import_2.Inject)(_entity_permission_service_js__rspack_import_11/* .EntityPermissionService */.u)),
|
|
3220
|
+
_ts_metadata("design:type", Function),
|
|
3221
|
+
_ts_metadata("design:paramtypes", [
|
|
3222
|
+
typeof _entity_builder_datasource_provider_js__rspack_import_10/* .EntityBuilderDataSourceProvider */.D === "undefined" ? Object : _entity_builder_datasource_provider_js__rspack_import_10/* .EntityBuilderDataSourceProvider */.D,
|
|
3223
|
+
typeof _schema_dialect_adapter_service_js__rspack_import_18/* .SchemaDialectAdapterService */.I === "undefined" ? Object : _schema_dialect_adapter_service_js__rspack_import_18/* .SchemaDialectAdapterService */.I,
|
|
3224
|
+
typeof _schema_change_executor_service_js__rspack_import_16/* .SchemaChangeExecutor */.T === "undefined" ? Object : _schema_change_executor_service_js__rspack_import_16/* .SchemaChangeExecutor */.T,
|
|
3225
|
+
typeof _reference_scanner_service_js__rspack_import_15/* .ReferenceScannerService */.t === "undefined" ? Object : _reference_scanner_service_js__rspack_import_15/* .ReferenceScannerService */.t,
|
|
3226
|
+
typeof _entity_permission_service_js__rspack_import_11/* .EntityPermissionService */.u === "undefined" ? Object : _entity_permission_service_js__rspack_import_11/* .EntityPermissionService */.u
|
|
3227
|
+
])
|
|
3228
|
+
], SchemaEvolutionService);
|
|
3229
|
+
|
|
3230
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
3231
|
+
_: () => (SchemaEvolutionService)
|
|
3232
|
+
}, {
|
|
3233
|
+
C: isDestructiveSchemaAction
|
|
3234
|
+
});
|
|
3235
|
+
|
|
3236
|
+
|
|
3237
|
+
},
|
|
3238
|
+
3474(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
3239
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
3240
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_1 = __webpack_require__(9216);
|
|
3241
|
+
/* import */ var _nestjs_common__rspack_import_2 = __webpack_require__(6157);
|
|
3242
|
+
/* import */ var typeorm__rspack_import_3 = __webpack_require__(7158);
|
|
3243
|
+
/* import */ var _config_message_keys_js__rspack_import_17 = __webpack_require__(5732);
|
|
3244
|
+
/* import */ var _entities_entity_definition_entity_js__rspack_import_4 = __webpack_require__(3189);
|
|
3245
|
+
/* import */ var _entities_field_definition_entity_js__rspack_import_5 = __webpack_require__(2206);
|
|
3246
|
+
/* import */ var _entities_flow_definition_entity_js__rspack_import_6 = __webpack_require__(3770);
|
|
3247
|
+
/* import */ var _enums_ddl_operation_enum_js__rspack_import_20 = __webpack_require__(9949);
|
|
3248
|
+
/* import */ var _enums_entity_status_enum_js__rspack_import_21 = __webpack_require__(1313);
|
|
3249
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_19 = __webpack_require__(9614);
|
|
3250
|
+
/* import */ var _flow_engine_flow_errors_js__rspack_import_7 = __webpack_require__(8542);
|
|
3251
|
+
/* import */ var _entity_builder_datasource_provider_js__rspack_import_8 = __webpack_require__(424);
|
|
3252
|
+
/* import */ var _entity_flow_scaffold_js__rspack_import_9 = __webpack_require__(8271);
|
|
3253
|
+
/* import */ var _entity_permission_service_js__rspack_import_10 = __webpack_require__(1462);
|
|
3254
|
+
/* import */ var _field_value_validator_js__rspack_import_11 = __webpack_require__(3525);
|
|
3255
|
+
/* import */ var _flow_definition_service_js__rspack_import_12 = __webpack_require__(4921);
|
|
3256
|
+
/* import */ var _identifier_rules_js__rspack_import_13 = __webpack_require__(413);
|
|
3257
|
+
/* import */ var _schema_change_executor_service_js__rspack_import_14 = __webpack_require__(6605);
|
|
3258
|
+
/* import */ var _schema_columns_js__rspack_import_15 = __webpack_require__(5313);
|
|
3259
|
+
/* import */ var _schema_dialect_adapter_service_js__rspack_import_16 = __webpack_require__(7259);
|
|
3260
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
3261
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3262
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
3263
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
3264
|
+
} else {
|
|
3265
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
3266
|
+
if (d = decorators[i]) {
|
|
3267
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3272
|
+
}
|
|
3273
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
3274
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
3275
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
function _ts_param(paramIndex, decorator) {
|
|
3279
|
+
return function(target, key) {
|
|
3280
|
+
decorator(target, key, paramIndex);
|
|
3281
|
+
};
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
|
|
3285
|
+
|
|
3286
|
+
|
|
3287
|
+
|
|
3288
|
+
|
|
3289
|
+
|
|
3290
|
+
|
|
3291
|
+
|
|
3292
|
+
|
|
3293
|
+
|
|
3294
|
+
|
|
3295
|
+
|
|
3296
|
+
|
|
3297
|
+
|
|
3298
|
+
|
|
3299
|
+
|
|
3300
|
+
|
|
3301
|
+
|
|
3302
|
+
|
|
3303
|
+
|
|
3304
|
+
|
|
3305
|
+
class SchemaSyncService {
|
|
3306
|
+
dataSourceProvider;
|
|
3307
|
+
dialectAdapter;
|
|
3308
|
+
executor;
|
|
3309
|
+
entityPermissionService;
|
|
3310
|
+
flowDefinitionService;
|
|
3311
|
+
logger = new _nestjs_common__rspack_import_2.Logger(SchemaSyncService.name);
|
|
3312
|
+
constructor(dataSourceProvider, dialectAdapter, executor, entityPermissionService, flowDefinitionService){
|
|
3313
|
+
this.dataSourceProvider = dataSourceProvider;
|
|
3314
|
+
this.dialectAdapter = dialectAdapter;
|
|
3315
|
+
this.executor = executor;
|
|
3316
|
+
this.entityPermissionService = entityPermissionService;
|
|
3317
|
+
this.flowDefinitionService = flowDefinitionService;
|
|
3318
|
+
}
|
|
3319
|
+
validateCreateRequest(dto) {
|
|
3320
|
+
(0,_identifier_rules_js__rspack_import_13/* .assertValidIdentifier */.kV)(dto.code, 'entity');
|
|
3321
|
+
const fields = dto.fields ?? [];
|
|
3322
|
+
for (const field of fields){
|
|
3323
|
+
(0,_identifier_rules_js__rspack_import_13/* .assertValidIdentifier */.kV)(field.code, 'field');
|
|
3324
|
+
(0,_identifier_rules_js__rspack_import_13/* .assertIndexableField */.fY)(field);
|
|
3325
|
+
}
|
|
3326
|
+
const duplicate = fields.map((f)=>f.code).find((code, index, all)=>all.indexOf(code) !== index);
|
|
3327
|
+
if (duplicate) {
|
|
3328
|
+
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
3329
|
+
message: `Field code '${duplicate}' is defined more than once.`,
|
|
3330
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .SCHEMA_MESSAGES.DUPLICATE_FIELD_CODE */.Hu.DUPLICATE_FIELD_CODE,
|
|
3331
|
+
messageVariables: {
|
|
3332
|
+
code: duplicate
|
|
3333
|
+
}
|
|
3334
|
+
});
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
async createTarget(dto, user) {
|
|
3338
|
+
const lockCodes = await (0,_schema_change_executor_service_js__rspack_import_14/* .relationTargetCodes */.e)(this.dataSourceProvider, (dto.fields ?? []).map((f)=>f.relationTargetEntityId));
|
|
3339
|
+
return {
|
|
3340
|
+
action: 'create_entity',
|
|
3341
|
+
entityDefinitionId: null,
|
|
3342
|
+
entityCode: dto.code,
|
|
3343
|
+
tableName: `${(/* inlined export .ENTITY_TABLE_PREFIX */"eb_")}${dto.code}`,
|
|
3344
|
+
user,
|
|
3345
|
+
lockCodes
|
|
3346
|
+
};
|
|
3347
|
+
}
|
|
3348
|
+
createRun(dto, user, created) {
|
|
3349
|
+
const tableName = `${(/* inlined export .ENTITY_TABLE_PREFIX */"eb_")}${dto.code}`;
|
|
3350
|
+
const fieldSpecs = dto.fields ?? [];
|
|
3351
|
+
const flowEndpoints = dto.flowEndpoints ?? [];
|
|
3352
|
+
const isSoftDeleteEnabled = dto.isSoftDeleteEnabled ?? true;
|
|
3353
|
+
const isAuditEnabled = dto.isAuditEnabled ?? true;
|
|
3354
|
+
return async (ctx)=>{
|
|
3355
|
+
const schemaExpr = ctx.driver === 'postgres' ? 'current_schema()' : 'DATABASE()';
|
|
3356
|
+
const taken = await ctx.qr.query((0,_flusys_nestjs_shared_classes__rspack_import_0.buildQuery)(`SELECT table_name FROM information_schema.tables WHERE table_schema = ${schemaExpr} AND table_name = ?`, ctx.driver), [
|
|
3357
|
+
tableName
|
|
3358
|
+
]);
|
|
3359
|
+
if (taken.length) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.TABLE_EXISTS */.M3.TABLE_EXISTS, {
|
|
3360
|
+
table: tableName
|
|
3361
|
+
}));
|
|
3362
|
+
const definitions = ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_4/* .EntityDefinition */.f);
|
|
3363
|
+
const known = await definitions.findOne({
|
|
3364
|
+
where: {
|
|
3365
|
+
code: dto.code
|
|
3366
|
+
}
|
|
3367
|
+
});
|
|
3368
|
+
if (known) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.ENTITY_CODE_EXISTS */.M3.ENTITY_CODE_EXISTS, {
|
|
3369
|
+
code: dto.code
|
|
3370
|
+
}));
|
|
3371
|
+
for (const spec of fieldSpecs.filter((f)=>f.fieldType === _enums_field_type_enum_js__rspack_import_19/* .FieldType.RELATION */.P.RELATION)){
|
|
3372
|
+
if (!spec.relationTargetEntityId) {
|
|
3373
|
+
ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.RELATION_TARGET_REQUIRED */.M3.RELATION_TARGET_REQUIRED, {
|
|
3374
|
+
field: spec.code
|
|
3375
|
+
}));
|
|
3376
|
+
continue;
|
|
3377
|
+
}
|
|
3378
|
+
const target = await definitions.findOne({
|
|
3379
|
+
where: {
|
|
3380
|
+
id: spec.relationTargetEntityId
|
|
3381
|
+
}
|
|
3382
|
+
});
|
|
3383
|
+
if (!target) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.RELATION_FIELD_TARGET_MISSING */.M3.RELATION_FIELD_TARGET_MISSING, {
|
|
3384
|
+
field: spec.code
|
|
3385
|
+
}));
|
|
3386
|
+
}
|
|
3387
|
+
const withDefault = fieldSpecs.filter((f)=>f.defaultValue !== undefined && f.defaultValue !== null);
|
|
3388
|
+
const { errors: defaultErrors } = (0,_field_value_validator_js__rspack_import_11/* .validateRecord */.e)(withDefault.map((f)=>({
|
|
3389
|
+
code: f.code,
|
|
3390
|
+
label: f.label,
|
|
3391
|
+
fieldType: f.fieldType,
|
|
3392
|
+
nullable: true,
|
|
3393
|
+
defaultValue: null,
|
|
3394
|
+
selectOptions: f.selectOptions ?? null,
|
|
3395
|
+
validationRules: f.validationRules ?? null
|
|
3396
|
+
})), Object.fromEntries(withDefault.map((f)=>[
|
|
3397
|
+
f.code,
|
|
3398
|
+
f.defaultValue
|
|
3399
|
+
])), 'insert');
|
|
3400
|
+
for (const error of defaultErrors)ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.DEFAULT_INVALID */.M3.DEFAULT_INVALID, {
|
|
3401
|
+
problem: (0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(error.messageKey, error.messageVariables)
|
|
3402
|
+
}));
|
|
3403
|
+
if (flowEndpoints.length) {
|
|
3404
|
+
const slug = (0,_entity_flow_scaffold_js__rspack_import_9/* .entityFlowSlug */.x2)(dto.code);
|
|
3405
|
+
const clash = await ctx.qr.manager.getRepository(_entities_flow_definition_entity_js__rspack_import_6/* .FlowDefinition */.G).findOne({
|
|
3406
|
+
select: {
|
|
3407
|
+
slug: true
|
|
3408
|
+
},
|
|
3409
|
+
where: {
|
|
3410
|
+
slug
|
|
3411
|
+
},
|
|
3412
|
+
withDeleted: true
|
|
3413
|
+
});
|
|
3414
|
+
if (clash) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.FLOW_SLUG_TAKEN */.M3.FLOW_SLUG_TAKEN, {
|
|
3415
|
+
slug
|
|
3416
|
+
}));
|
|
3417
|
+
}
|
|
3418
|
+
if (ctx.blocked) return {
|
|
3419
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_20/* .DdlOperation.CREATE_TABLE */.i.CREATE_TABLE,
|
|
3420
|
+
diff: {}
|
|
3421
|
+
};
|
|
3422
|
+
const columns = fieldSpecs.map((spec)=>(0,_schema_columns_js__rspack_import_15/* .buildFieldColumn */.fu)({
|
|
3423
|
+
code: spec.code,
|
|
3424
|
+
fieldType: spec.fieldType,
|
|
3425
|
+
dbType: '',
|
|
3426
|
+
nullable: spec.nullable ?? true,
|
|
3427
|
+
unique: spec.unique ?? false
|
|
3428
|
+
}, ctx.driver, this.dialectAdapter, {
|
|
3429
|
+
enforceNotNull: true,
|
|
3430
|
+
withUnique: true
|
|
3431
|
+
}));
|
|
3432
|
+
const table = new typeorm__rspack_import_3.Table({
|
|
3433
|
+
name: tableName,
|
|
3434
|
+
columns: [
|
|
3435
|
+
...(0,_schema_columns_js__rspack_import_15/* .buildSystemColumns */.Rm)({
|
|
3436
|
+
isSoftDeleteEnabled,
|
|
3437
|
+
isAuditEnabled
|
|
3438
|
+
}, ctx.driver),
|
|
3439
|
+
...columns
|
|
3440
|
+
]
|
|
3441
|
+
});
|
|
3442
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_STEP_MESSAGES.CREATE_TABLE */.EQ.CREATE_TABLE, {
|
|
3443
|
+
table: tableName
|
|
3444
|
+
}), async ()=>{
|
|
3445
|
+
await ctx.qr.createTable(table, false);
|
|
3446
|
+
});
|
|
3447
|
+
for (const spec of fieldSpecs.filter((f)=>f.isIndexed && !f.unique)){
|
|
3448
|
+
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_STEP_MESSAGES.ADD_INDEX */.EQ.ADD_INDEX, {
|
|
3449
|
+
column: spec.code
|
|
3450
|
+
}), async ()=>{
|
|
3451
|
+
await ctx.qr.createIndex(table, (0,_schema_columns_js__rspack_import_15/* .plainIndex */.v7)(tableName, spec.code, ctx.driver, this.dialectAdapter));
|
|
3452
|
+
});
|
|
3453
|
+
}
|
|
3454
|
+
await ctx.metadata(async ()=>{
|
|
3455
|
+
const definitionRepo = ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_4/* .EntityDefinition */.f);
|
|
3456
|
+
const definition = await definitionRepo.save(definitionRepo.create({
|
|
3457
|
+
code: dto.code,
|
|
3458
|
+
label: dto.label,
|
|
3459
|
+
description: dto.description ?? null,
|
|
3460
|
+
tableName,
|
|
3461
|
+
status: _enums_entity_status_enum_js__rspack_import_21/* .EntityStatus.ACTIVE */.c.ACTIVE,
|
|
3462
|
+
schemaVersion: 1,
|
|
3463
|
+
isSoftDeleteEnabled,
|
|
3464
|
+
isAuditEnabled,
|
|
3465
|
+
uiConfig: dto.uiConfig ?? null
|
|
3466
|
+
}));
|
|
3467
|
+
const fieldRepo = ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_5/* .FieldDefinition */.c);
|
|
3468
|
+
if (fieldSpecs.length) {
|
|
3469
|
+
await fieldRepo.save(fieldSpecs.map((spec, index)=>fieldRepo.create({
|
|
3470
|
+
entityDefinitionId: definition.id,
|
|
3471
|
+
code: spec.code,
|
|
3472
|
+
label: spec.label,
|
|
3473
|
+
fieldType: spec.fieldType,
|
|
3474
|
+
dbType: this.dialectAdapter.mapFieldType(spec.fieldType, ctx.driver),
|
|
3475
|
+
nullable: spec.nullable ?? true,
|
|
3476
|
+
unique: spec.unique ?? false,
|
|
3477
|
+
isIndexed: spec.isIndexed ?? false,
|
|
3478
|
+
defaultValue: spec.defaultValue ?? null,
|
|
3479
|
+
validationRules: spec.validationRules ?? null,
|
|
3480
|
+
selectOptions: spec.selectOptions ?? null,
|
|
3481
|
+
relationTargetEntityId: spec.fieldType === _enums_field_type_enum_js__rspack_import_19/* .FieldType.RELATION */.P.RELATION ? spec.relationTargetEntityId : null,
|
|
3482
|
+
order: spec.order ?? index,
|
|
3483
|
+
uiConfig: spec.uiConfig ?? null,
|
|
3484
|
+
isSearchable: spec.isSearchable ?? false,
|
|
3485
|
+
isSystemField: false,
|
|
3486
|
+
deprecatedAt: null
|
|
3487
|
+
})));
|
|
3488
|
+
}
|
|
3489
|
+
created.definition = definition;
|
|
3490
|
+
});
|
|
3491
|
+
return {
|
|
3492
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_20/* .DdlOperation.CREATE_TABLE */.i.CREATE_TABLE,
|
|
3493
|
+
entityDefinitionId: created.definition?.id ?? null,
|
|
3494
|
+
diff: {
|
|
3495
|
+
fields: fieldSpecs.map((f)=>({
|
|
3496
|
+
code: f.code,
|
|
3497
|
+
fieldType: f.fieldType
|
|
3498
|
+
}))
|
|
3499
|
+
},
|
|
3500
|
+
bumpVersion: false,
|
|
3501
|
+
afterCommit: async ()=>{
|
|
3502
|
+
if (!created.definition) return;
|
|
3503
|
+
try {
|
|
3504
|
+
await this.entityPermissionService.provisionForEntity(created.definition);
|
|
3505
|
+
} finally{
|
|
3506
|
+
if (flowEndpoints.length) created.warnings.push(...await this.createEndpointFlow(dto, flowEndpoints, user));
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
};
|
|
3510
|
+
};
|
|
3511
|
+
}
|
|
3512
|
+
/**
|
|
3513
|
+
* The entity's ready-made flow, one Request step per requested endpoint, saved through
|
|
3514
|
+
* FlowDefinitionService so it is validated like any other flow. The entity is already committed,
|
|
3515
|
+
* so a flow that cannot be saved is reported as a warning.
|
|
3516
|
+
*/ async createEndpointFlow(dto, endpoints, user) {
|
|
3517
|
+
const flow = (0,_entity_flow_scaffold_js__rspack_import_9/* .buildEntityFlow */.CO)({
|
|
3518
|
+
code: dto.code,
|
|
3519
|
+
label: dto.label,
|
|
3520
|
+
fields: dto.fields ?? []
|
|
3521
|
+
}, endpoints, dto.flowTexts);
|
|
3522
|
+
try {
|
|
3523
|
+
await this.flowDefinitionService.insert(flow, user);
|
|
3524
|
+
return [];
|
|
3525
|
+
} catch (error) {
|
|
3526
|
+
this.logger.error(`The flow '${flow.slug}' of entity '${dto.code}' could not be created: ${error.message}`);
|
|
3527
|
+
return [
|
|
3528
|
+
(0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_17/* .SCHEMA_WARNING_MESSAGES.ENDPOINT_FLOW_FAILED */.Uu.ENDPOINT_FLOW_FAILED, {
|
|
3529
|
+
slug: flow.slug,
|
|
3530
|
+
detail: (0,_flow_engine_flow_errors_js__rspack_import_7/* .errorRef */.O$)(error)
|
|
3531
|
+
})
|
|
3532
|
+
];
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
/** Preview of `createEntity`: the CREATE TABLE / CREATE INDEX statements, nothing is created. */ async planCreateEntity(dto, user) {
|
|
3536
|
+
this.validateCreateRequest(dto);
|
|
3537
|
+
return this.executor.simulate(await this.createTarget(dto, user), this.createRun(dto, user, {
|
|
3538
|
+
warnings: []
|
|
3539
|
+
}));
|
|
3540
|
+
}
|
|
3541
|
+
async createEntity(dto, user) {
|
|
3542
|
+
this.validateCreateRequest(dto);
|
|
3543
|
+
if (dto.flowEndpoints?.length) await this.flowDefinitionService.assertMayCreate(user);
|
|
3544
|
+
const created = {
|
|
3545
|
+
warnings: []
|
|
3546
|
+
};
|
|
3547
|
+
let planWarnings;
|
|
3548
|
+
try {
|
|
3549
|
+
({ plan: { warnings: planWarnings } } = await this.executor.apply(await this.createTarget(dto, user), this.createRun(dto, user, created)));
|
|
3550
|
+
} catch (error) {
|
|
3551
|
+
if (error instanceof _nestjs_common__rspack_import_2.ConflictException && error.getResponse().blockers?.some((b)=>b.messageKey === _config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.ENTITY_CODE_EXISTS */.M3.ENTITY_CODE_EXISTS || b.messageKey === _config_message_keys_js__rspack_import_17/* .SCHEMA_BLOCKER_MESSAGES.TABLE_EXISTS */.M3.TABLE_EXISTS)) {
|
|
3552
|
+
throw new _nestjs_common__rspack_import_2.ConflictException({
|
|
3553
|
+
message: `An entity with the code '${dto.code}' already exists.`,
|
|
3554
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .ENTITY_DEFINITION_MESSAGES.CODE_ALREADY_EXISTS */.pL.CODE_ALREADY_EXISTS,
|
|
3555
|
+
messageVariables: {
|
|
3556
|
+
code: dto.code
|
|
3557
|
+
}
|
|
3558
|
+
});
|
|
3559
|
+
}
|
|
3560
|
+
throw error;
|
|
3561
|
+
}
|
|
3562
|
+
return {
|
|
3563
|
+
definition: created.definition,
|
|
3564
|
+
warnings: [
|
|
3565
|
+
...planWarnings,
|
|
3566
|
+
...created.warnings
|
|
3567
|
+
]
|
|
3568
|
+
};
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
SchemaSyncService = _ts_decorate([
|
|
3572
|
+
(0,_nestjs_common__rspack_import_2.Injectable)({
|
|
3573
|
+
scope: _nestjs_common__rspack_import_2.Scope.REQUEST
|
|
3574
|
+
}),
|
|
3575
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_2.Inject)(_entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D)),
|
|
3576
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_2.Inject)(_schema_dialect_adapter_service_js__rspack_import_16/* .SchemaDialectAdapterService */.I)),
|
|
3577
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_2.Inject)(_schema_change_executor_service_js__rspack_import_14/* .SchemaChangeExecutor */.T)),
|
|
3578
|
+
_ts_param(3, (0,_nestjs_common__rspack_import_2.Inject)(_entity_permission_service_js__rspack_import_10/* .EntityPermissionService */.u)),
|
|
3579
|
+
_ts_param(4, (0,_nestjs_common__rspack_import_2.Inject)(_flow_definition_service_js__rspack_import_12/* .FlowDefinitionService */.Tk)),
|
|
3580
|
+
_ts_metadata("design:type", Function),
|
|
3581
|
+
_ts_metadata("design:paramtypes", [
|
|
3582
|
+
typeof _entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D === "undefined" ? Object : _entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D,
|
|
3583
|
+
typeof _schema_dialect_adapter_service_js__rspack_import_16/* .SchemaDialectAdapterService */.I === "undefined" ? Object : _schema_dialect_adapter_service_js__rspack_import_16/* .SchemaDialectAdapterService */.I,
|
|
3584
|
+
typeof _schema_change_executor_service_js__rspack_import_14/* .SchemaChangeExecutor */.T === "undefined" ? Object : _schema_change_executor_service_js__rspack_import_14/* .SchemaChangeExecutor */.T,
|
|
3585
|
+
typeof _entity_permission_service_js__rspack_import_10/* .EntityPermissionService */.u === "undefined" ? Object : _entity_permission_service_js__rspack_import_10/* .EntityPermissionService */.u,
|
|
3586
|
+
typeof _flow_definition_service_js__rspack_import_12/* .FlowDefinitionService */.Tk === "undefined" ? Object : _flow_definition_service_js__rspack_import_12/* .FlowDefinitionService */.Tk
|
|
3587
|
+
])
|
|
3588
|
+
], SchemaSyncService);
|
|
3589
|
+
|
|
3590
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
3591
|
+
W: () => (SchemaSyncService)
|
|
3592
|
+
});
|
|
3593
|
+
|
|
3594
|
+
|
|
3595
|
+
},
|
|
3596
|
+
|
|
3597
|
+
};
|