@flusys/nestjs-entity-builder 9.1.0-rc.1 → 9.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -23
- package/config/entity-builder.constants.d.ts +2 -0
- package/config/message-keys.d.ts +102 -13
- package/controllers/definition-bundle.controller.d.ts +15 -0
- package/controllers/flow-definition.controller.d.ts +7 -1
- package/controllers/flow-runtime.controller.d.ts +16 -8
- package/controllers/index.d.ts +1 -1
- package/dtos/definition-bundle.dto.d.ts +57 -0
- package/dtos/flow.dto.d.ts +13 -20
- package/dtos/index.d.ts +1 -0
- package/entities/flow-definition.entity.d.ts +3 -9
- package/entities/flow-execution.entity.d.ts +3 -0
- package/entities/flow-version.entity.d.ts +10 -0
- package/entities/index.d.ts +3 -3
- package/fesm/21.js +105 -15
- package/fesm/458.js +695 -0
- package/fesm/{489.js → 582.js} +22 -30
- package/fesm/{996.js → 677.js} +1562 -1064
- package/fesm/794.js +135 -240
- package/fesm/{719.js → 870.js} +2065 -324
- package/fesm/{362.js → 897.js} +572 -8
- package/fesm/{606.js → 946.js} +621 -296
- package/fesm/config/index.js +15 -2
- package/fesm/controllers/index.js +9 -9
- package/fesm/docs/index.js +7 -4
- package/fesm/dtos/index.js +451 -256
- package/fesm/entities/index.js +58 -3
- package/fesm/guards/index.js +106 -22
- package/fesm/index.js +429 -937
- package/fesm/interfaces/index.js +19 -2
- package/fesm/modules/index.js +10 -627
- package/fesm/rule-engine/index.js +12 -3
- package/fesm/services/index.js +101 -29
- package/flow-engine/flow-api-key.d.ts +3 -7
- package/flow-engine/flow-graph.validator.d.ts +5 -4
- package/flow-engine/flow-permission-logic.d.ts +2 -0
- package/flow-engine/flow-run.types.d.ts +19 -9
- package/flow-engine/flow.types.d.ts +115 -11
- package/guards/designer-writable.interceptor.d.ts +12 -0
- package/guards/index.d.ts +1 -0
- package/interfaces/definition-bundle.interface.d.ts +111 -0
- package/interfaces/entity-builder-module.interface.d.ts +6 -0
- package/interfaces/flow-definition.interface.d.ts +13 -9
- package/interfaces/index.d.ts +1 -0
- package/package.json +5 -5
- package/rule-engine/rule-engine.service.d.ts +1 -0
- package/rule-engine/rule-permission.d.ts +3 -7
- package/services/definition-bundle.diff.d.ts +62 -0
- package/services/definition-bundle.file.d.ts +7 -0
- package/services/definition-bundle.service.d.ts +32 -0
- package/services/entity-builder-config.service.d.ts +2 -0
- package/services/entity-flow-scaffold.d.ts +4 -3
- package/services/flow-definition.service.d.ts +26 -12
- package/services/flow-execution.service.d.ts +7 -0
- package/services/flow-executor.service.d.ts +9 -8
- package/services/flow-runtime.service.d.ts +2 -1
- package/services/generic-entity.service.d.ts +1 -1
- package/services/index.d.ts +3 -1
- package/services/schema-evolution.service.d.ts +3 -1
- package/services/schema-sync.service.d.ts +6 -2
- package/controllers/flow-api-key.controller.d.ts +0 -14
- package/entities/flow-api-key.entity.d.ts +0 -10
- package/services/flow-api-key.service.d.ts +0 -31
package/fesm/{719.js → 870.js}
RENAMED
|
@@ -1,12 +1,1715 @@
|
|
|
1
|
-
export const __rspack_esm_id =
|
|
2
|
-
export const __rspack_esm_ids = [
|
|
1
|
+
export const __rspack_esm_id = 870;
|
|
2
|
+
export const __rspack_esm_ids = [870];
|
|
3
3
|
export const __webpack_modules__ = {
|
|
4
|
+
6691(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5
|
+
/* import */ var _nestjs_swagger__rspack_import_0 = __webpack_require__(6176);
|
|
6
|
+
/* import */ var class_transformer__rspack_import_1 = __webpack_require__(5812);
|
|
7
|
+
/* import */ var class_validator__rspack_import_2 = __webpack_require__(5421);
|
|
8
|
+
/* import */ var _config_entity_builder_constants_js__rspack_import_4 = __webpack_require__(6576);
|
|
9
|
+
/* import */ var _enums_entity_status_enum_js__rspack_import_6 = __webpack_require__(1313);
|
|
10
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_5 = __webpack_require__(9614);
|
|
11
|
+
/* import */ var _flow_engine_flow_types_js__rspack_import_3 = __webpack_require__(6256);
|
|
12
|
+
/* import */ var _interfaces_definition_bundle_interface_js__rspack_import_7 = __webpack_require__(8835);
|
|
13
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
14
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
15
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
16
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
+
} else {
|
|
18
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
19
|
+
if (d = decorators[i]) {
|
|
20
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
25
|
+
}
|
|
26
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
27
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
28
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
const Nullable = ()=>(0,class_validator__rspack_import_2.ValidateIf)((_object, value)=>value !== null);
|
|
40
|
+
class BundleFieldDto {
|
|
41
|
+
id;
|
|
42
|
+
code;
|
|
43
|
+
label;
|
|
44
|
+
fieldType;
|
|
45
|
+
nullable;
|
|
46
|
+
unique;
|
|
47
|
+
isIndexed;
|
|
48
|
+
defaultValue;
|
|
49
|
+
validationRules;
|
|
50
|
+
selectOptions;
|
|
51
|
+
relationTarget;
|
|
52
|
+
order;
|
|
53
|
+
uiConfig;
|
|
54
|
+
isSearchable;
|
|
55
|
+
deprecated;
|
|
56
|
+
}
|
|
57
|
+
_ts_decorate([
|
|
58
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
59
|
+
(0,class_validator__rspack_import_2.IsUUID)(),
|
|
60
|
+
_ts_metadata("design:type", String)
|
|
61
|
+
], BundleFieldDto.prototype, "id", void 0);
|
|
62
|
+
_ts_decorate([
|
|
63
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
64
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
65
|
+
(0,class_validator__rspack_import_2.MaxLength)((/* inlined export .ENTITY_CODE_MAX_LENGTH */63)),
|
|
66
|
+
(0,class_validator__rspack_import_2.Matches)(_config_entity_builder_constants_js__rspack_import_4/* .ENTITY_CODE_PATTERN */.vs),
|
|
67
|
+
_ts_metadata("design:type", String)
|
|
68
|
+
], BundleFieldDto.prototype, "code", void 0);
|
|
69
|
+
_ts_decorate([
|
|
70
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
71
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
72
|
+
(0,class_validator__rspack_import_2.IsNotEmpty)(),
|
|
73
|
+
(0,class_validator__rspack_import_2.MaxLength)(255),
|
|
74
|
+
_ts_metadata("design:type", String)
|
|
75
|
+
], BundleFieldDto.prototype, "label", void 0);
|
|
76
|
+
_ts_decorate([
|
|
77
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
78
|
+
enum: _enums_field_type_enum_js__rspack_import_5/* .FieldType */.P
|
|
79
|
+
}),
|
|
80
|
+
(0,class_validator__rspack_import_2.IsEnum)(_enums_field_type_enum_js__rspack_import_5/* .FieldType */.P),
|
|
81
|
+
_ts_metadata("design:type", typeof _enums_field_type_enum_js__rspack_import_5/* .FieldType */.P === "undefined" ? Object : _enums_field_type_enum_js__rspack_import_5/* .FieldType */.P)
|
|
82
|
+
], BundleFieldDto.prototype, "fieldType", void 0);
|
|
83
|
+
_ts_decorate([
|
|
84
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
85
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
86
|
+
_ts_metadata("design:type", Boolean)
|
|
87
|
+
], BundleFieldDto.prototype, "nullable", void 0);
|
|
88
|
+
_ts_decorate([
|
|
89
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
90
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
91
|
+
_ts_metadata("design:type", Boolean)
|
|
92
|
+
], BundleFieldDto.prototype, "unique", void 0);
|
|
93
|
+
_ts_decorate([
|
|
94
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
95
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
96
|
+
_ts_metadata("design:type", Boolean)
|
|
97
|
+
], BundleFieldDto.prototype, "isIndexed", void 0);
|
|
98
|
+
_ts_decorate([
|
|
99
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)(),
|
|
100
|
+
(0,class_validator__rspack_import_2.Allow)(),
|
|
101
|
+
_ts_metadata("design:type", Object)
|
|
102
|
+
], BundleFieldDto.prototype, "defaultValue", void 0);
|
|
103
|
+
_ts_decorate([
|
|
104
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
105
|
+
type: Object,
|
|
106
|
+
nullable: true
|
|
107
|
+
}),
|
|
108
|
+
Nullable(),
|
|
109
|
+
(0,class_validator__rspack_import_2.IsObject)(),
|
|
110
|
+
_ts_metadata("design:type", Object)
|
|
111
|
+
], BundleFieldDto.prototype, "validationRules", void 0);
|
|
112
|
+
_ts_decorate([
|
|
113
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
114
|
+
type: [
|
|
115
|
+
Object
|
|
116
|
+
],
|
|
117
|
+
nullable: true
|
|
118
|
+
}),
|
|
119
|
+
Nullable(),
|
|
120
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
121
|
+
_ts_metadata("design:type", Object)
|
|
122
|
+
], BundleFieldDto.prototype, "selectOptions", void 0);
|
|
123
|
+
_ts_decorate([
|
|
124
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
125
|
+
description: 'Code of the entity a RELATION field points to',
|
|
126
|
+
nullable: true
|
|
127
|
+
}),
|
|
128
|
+
Nullable(),
|
|
129
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
130
|
+
(0,class_validator__rspack_import_2.Matches)(_config_entity_builder_constants_js__rspack_import_4/* .ENTITY_CODE_PATTERN */.vs),
|
|
131
|
+
_ts_metadata("design:type", Object)
|
|
132
|
+
], BundleFieldDto.prototype, "relationTarget", void 0);
|
|
133
|
+
_ts_decorate([
|
|
134
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
135
|
+
(0,class_validator__rspack_import_2.IsInt)(),
|
|
136
|
+
(0,class_validator__rspack_import_2.Min)(0),
|
|
137
|
+
_ts_metadata("design:type", Number)
|
|
138
|
+
], BundleFieldDto.prototype, "order", void 0);
|
|
139
|
+
_ts_decorate([
|
|
140
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
141
|
+
type: Object,
|
|
142
|
+
nullable: true
|
|
143
|
+
}),
|
|
144
|
+
Nullable(),
|
|
145
|
+
(0,class_validator__rspack_import_2.IsObject)(),
|
|
146
|
+
_ts_metadata("design:type", Object)
|
|
147
|
+
], BundleFieldDto.prototype, "uiConfig", void 0);
|
|
148
|
+
_ts_decorate([
|
|
149
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
150
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
151
|
+
_ts_metadata("design:type", Boolean)
|
|
152
|
+
], BundleFieldDto.prototype, "isSearchable", void 0);
|
|
153
|
+
_ts_decorate([
|
|
154
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
155
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
156
|
+
_ts_metadata("design:type", Boolean)
|
|
157
|
+
], BundleFieldDto.prototype, "deprecated", void 0);
|
|
158
|
+
class BundleEntityDto {
|
|
159
|
+
id;
|
|
160
|
+
code;
|
|
161
|
+
label;
|
|
162
|
+
description;
|
|
163
|
+
status;
|
|
164
|
+
isSoftDeleteEnabled;
|
|
165
|
+
isAuditEnabled;
|
|
166
|
+
uiConfig;
|
|
167
|
+
fields;
|
|
168
|
+
}
|
|
169
|
+
_ts_decorate([
|
|
170
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
171
|
+
(0,class_validator__rspack_import_2.IsUUID)(),
|
|
172
|
+
_ts_metadata("design:type", String)
|
|
173
|
+
], BundleEntityDto.prototype, "id", void 0);
|
|
174
|
+
_ts_decorate([
|
|
175
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
176
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
177
|
+
(0,class_validator__rspack_import_2.MaxLength)((/* inlined export .ENTITY_CODE_MAX_LENGTH */63)),
|
|
178
|
+
(0,class_validator__rspack_import_2.Matches)(_config_entity_builder_constants_js__rspack_import_4/* .ENTITY_CODE_PATTERN */.vs),
|
|
179
|
+
_ts_metadata("design:type", String)
|
|
180
|
+
], BundleEntityDto.prototype, "code", void 0);
|
|
181
|
+
_ts_decorate([
|
|
182
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
183
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
184
|
+
(0,class_validator__rspack_import_2.IsNotEmpty)(),
|
|
185
|
+
(0,class_validator__rspack_import_2.MaxLength)(255),
|
|
186
|
+
_ts_metadata("design:type", String)
|
|
187
|
+
], BundleEntityDto.prototype, "label", void 0);
|
|
188
|
+
_ts_decorate([
|
|
189
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
190
|
+
nullable: true
|
|
191
|
+
}),
|
|
192
|
+
Nullable(),
|
|
193
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
194
|
+
(0,class_validator__rspack_import_2.MaxLength)(500),
|
|
195
|
+
_ts_metadata("design:type", Object)
|
|
196
|
+
], BundleEntityDto.prototype, "description", void 0);
|
|
197
|
+
_ts_decorate([
|
|
198
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
199
|
+
enum: _enums_entity_status_enum_js__rspack_import_6/* .EntityStatus */.c
|
|
200
|
+
}),
|
|
201
|
+
(0,class_validator__rspack_import_2.IsEnum)(_enums_entity_status_enum_js__rspack_import_6/* .EntityStatus */.c),
|
|
202
|
+
_ts_metadata("design:type", typeof _enums_entity_status_enum_js__rspack_import_6/* .EntityStatus */.c === "undefined" ? Object : _enums_entity_status_enum_js__rspack_import_6/* .EntityStatus */.c)
|
|
203
|
+
], BundleEntityDto.prototype, "status", void 0);
|
|
204
|
+
_ts_decorate([
|
|
205
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
206
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
207
|
+
_ts_metadata("design:type", Boolean)
|
|
208
|
+
], BundleEntityDto.prototype, "isSoftDeleteEnabled", void 0);
|
|
209
|
+
_ts_decorate([
|
|
210
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
211
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
212
|
+
_ts_metadata("design:type", Boolean)
|
|
213
|
+
], BundleEntityDto.prototype, "isAuditEnabled", void 0);
|
|
214
|
+
_ts_decorate([
|
|
215
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
216
|
+
type: Object,
|
|
217
|
+
nullable: true
|
|
218
|
+
}),
|
|
219
|
+
Nullable(),
|
|
220
|
+
(0,class_validator__rspack_import_2.IsObject)(),
|
|
221
|
+
_ts_metadata("design:type", Object)
|
|
222
|
+
], BundleEntityDto.prototype, "uiConfig", void 0);
|
|
223
|
+
_ts_decorate([
|
|
224
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
225
|
+
type: [
|
|
226
|
+
BundleFieldDto
|
|
227
|
+
]
|
|
228
|
+
}),
|
|
229
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
230
|
+
(0,class_validator__rspack_import_2.ValidateNested)({
|
|
231
|
+
each: true
|
|
232
|
+
}),
|
|
233
|
+
(0,class_transformer__rspack_import_1.Type)(()=>BundleFieldDto),
|
|
234
|
+
_ts_metadata("design:type", Array)
|
|
235
|
+
], BundleEntityDto.prototype, "fields", void 0);
|
|
236
|
+
class BundleFlowDto {
|
|
237
|
+
name;
|
|
238
|
+
slug;
|
|
239
|
+
description;
|
|
240
|
+
isActive;
|
|
241
|
+
retainExecutions;
|
|
242
|
+
nodes;
|
|
243
|
+
edges;
|
|
244
|
+
}
|
|
245
|
+
_ts_decorate([
|
|
246
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
247
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
248
|
+
(0,class_validator__rspack_import_2.IsNotEmpty)(),
|
|
249
|
+
(0,class_validator__rspack_import_2.MaxLength)(255),
|
|
250
|
+
_ts_metadata("design:type", String)
|
|
251
|
+
], BundleFlowDto.prototype, "name", void 0);
|
|
252
|
+
_ts_decorate([
|
|
253
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
254
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
255
|
+
(0,class_validator__rspack_import_2.Matches)(_flow_engine_flow_types_js__rspack_import_3/* .FLOW_SLUG_PATTERN */.YD),
|
|
256
|
+
_ts_metadata("design:type", String)
|
|
257
|
+
], BundleFlowDto.prototype, "slug", void 0);
|
|
258
|
+
_ts_decorate([
|
|
259
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
260
|
+
nullable: true
|
|
261
|
+
}),
|
|
262
|
+
Nullable(),
|
|
263
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
264
|
+
(0,class_validator__rspack_import_2.MaxLength)(500),
|
|
265
|
+
_ts_metadata("design:type", Object)
|
|
266
|
+
], BundleFlowDto.prototype, "description", void 0);
|
|
267
|
+
_ts_decorate([
|
|
268
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
269
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
270
|
+
_ts_metadata("design:type", Boolean)
|
|
271
|
+
], BundleFlowDto.prototype, "isActive", void 0);
|
|
272
|
+
_ts_decorate([
|
|
273
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)(),
|
|
274
|
+
(0,class_validator__rspack_import_2.IsInt)(),
|
|
275
|
+
(0,class_validator__rspack_import_2.Min)(0),
|
|
276
|
+
(0,class_validator__rspack_import_2.Max)(10000),
|
|
277
|
+
_ts_metadata("design:type", Number)
|
|
278
|
+
], BundleFlowDto.prototype, "retainExecutions", void 0);
|
|
279
|
+
_ts_decorate([
|
|
280
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
281
|
+
type: [
|
|
282
|
+
Object
|
|
283
|
+
]
|
|
284
|
+
}),
|
|
285
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
286
|
+
(0,class_validator__rspack_import_2.IsObject)({
|
|
287
|
+
each: true
|
|
288
|
+
}),
|
|
289
|
+
_ts_metadata("design:type", Array)
|
|
290
|
+
], BundleFlowDto.prototype, "nodes", void 0);
|
|
291
|
+
_ts_decorate([
|
|
292
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
293
|
+
type: [
|
|
294
|
+
Object
|
|
295
|
+
]
|
|
296
|
+
}),
|
|
297
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
298
|
+
(0,class_validator__rspack_import_2.IsObject)({
|
|
299
|
+
each: true
|
|
300
|
+
}),
|
|
301
|
+
_ts_metadata("design:type", Array)
|
|
302
|
+
], BundleFlowDto.prototype, "edges", void 0);
|
|
303
|
+
class DefinitionBundleDto {
|
|
304
|
+
format;
|
|
305
|
+
version;
|
|
306
|
+
entities;
|
|
307
|
+
flows;
|
|
308
|
+
}
|
|
309
|
+
_ts_decorate([
|
|
310
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
311
|
+
example: _interfaces_definition_bundle_interface_js__rspack_import_7/* .DEFINITION_BUNDLE_FORMAT */.D
|
|
312
|
+
}),
|
|
313
|
+
(0,class_validator__rspack_import_2.Equals)(_interfaces_definition_bundle_interface_js__rspack_import_7/* .DEFINITION_BUNDLE_FORMAT */.D),
|
|
314
|
+
_ts_metadata("design:type", Object)
|
|
315
|
+
], DefinitionBundleDto.prototype, "format", void 0);
|
|
316
|
+
_ts_decorate([
|
|
317
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
318
|
+
example: (/* inlined export .DEFINITION_BUNDLE_VERSION */1)
|
|
319
|
+
}),
|
|
320
|
+
(0,class_validator__rspack_import_2.Equals)((/* inlined export .DEFINITION_BUNDLE_VERSION */1)),
|
|
321
|
+
_ts_metadata("design:type", Object)
|
|
322
|
+
], DefinitionBundleDto.prototype, "version", void 0);
|
|
323
|
+
_ts_decorate([
|
|
324
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
325
|
+
type: [
|
|
326
|
+
BundleEntityDto
|
|
327
|
+
]
|
|
328
|
+
}),
|
|
329
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
330
|
+
(0,class_validator__rspack_import_2.ValidateNested)({
|
|
331
|
+
each: true
|
|
332
|
+
}),
|
|
333
|
+
(0,class_transformer__rspack_import_1.Type)(()=>BundleEntityDto),
|
|
334
|
+
_ts_metadata("design:type", Array)
|
|
335
|
+
], DefinitionBundleDto.prototype, "entities", void 0);
|
|
336
|
+
_ts_decorate([
|
|
337
|
+
(0,_nestjs_swagger__rspack_import_0.ApiProperty)({
|
|
338
|
+
type: [
|
|
339
|
+
BundleFlowDto
|
|
340
|
+
]
|
|
341
|
+
}),
|
|
342
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
343
|
+
(0,class_validator__rspack_import_2.ValidateNested)({
|
|
344
|
+
each: true
|
|
345
|
+
}),
|
|
346
|
+
(0,class_transformer__rspack_import_1.Type)(()=>BundleFlowDto),
|
|
347
|
+
_ts_metadata("design:type", Array)
|
|
348
|
+
], DefinitionBundleDto.prototype, "flows", void 0);
|
|
349
|
+
class ExportBundleDto {
|
|
350
|
+
entityCodes;
|
|
351
|
+
flowSlugs;
|
|
352
|
+
}
|
|
353
|
+
_ts_decorate([
|
|
354
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
355
|
+
type: [
|
|
356
|
+
String
|
|
357
|
+
],
|
|
358
|
+
description: 'Entity codes to export (all when left out)'
|
|
359
|
+
}),
|
|
360
|
+
(0,class_validator__rspack_import_2.IsOptional)(),
|
|
361
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
362
|
+
(0,class_validator__rspack_import_2.ArrayUnique)(),
|
|
363
|
+
(0,class_validator__rspack_import_2.IsString)({
|
|
364
|
+
each: true
|
|
365
|
+
}),
|
|
366
|
+
_ts_metadata("design:type", Array)
|
|
367
|
+
], ExportBundleDto.prototype, "entityCodes", void 0);
|
|
368
|
+
_ts_decorate([
|
|
369
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
370
|
+
type: [
|
|
371
|
+
String
|
|
372
|
+
],
|
|
373
|
+
description: 'Flow slugs to export (every published flow when left out)'
|
|
374
|
+
}),
|
|
375
|
+
(0,class_validator__rspack_import_2.IsOptional)(),
|
|
376
|
+
(0,class_validator__rspack_import_2.IsArray)(),
|
|
377
|
+
(0,class_validator__rspack_import_2.ArrayUnique)(),
|
|
378
|
+
(0,class_validator__rspack_import_2.IsString)({
|
|
379
|
+
each: true
|
|
380
|
+
}),
|
|
381
|
+
_ts_metadata("design:type", Array)
|
|
382
|
+
], ExportBundleDto.prototype, "flowSlugs", void 0);
|
|
383
|
+
/** Form values arrive as text: `true` / `false` become booleans, anything else is left for the validator to refuse. */ const FormBoolean = ()=>(0,class_transformer__rspack_import_1.Transform)(({ value })=>value === 'true' ? true : value === 'false' ? false : value);
|
|
384
|
+
/** The form fields sent with the bundle file to plan-import / apply-import. */ class ImportBundleOptionsDto {
|
|
385
|
+
deprecateMissingFields;
|
|
386
|
+
confirm;
|
|
387
|
+
expectedChecksum;
|
|
388
|
+
expectedPlanChecksum;
|
|
389
|
+
}
|
|
390
|
+
_ts_decorate([
|
|
391
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
392
|
+
description: 'Deprecate fields this environment has and the bundle does not (their columns and data stay)',
|
|
393
|
+
default: false
|
|
394
|
+
}),
|
|
395
|
+
(0,class_validator__rspack_import_2.IsOptional)(),
|
|
396
|
+
FormBoolean(),
|
|
397
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
398
|
+
_ts_metadata("design:type", Boolean)
|
|
399
|
+
], ImportBundleOptionsDto.prototype, "deprecateMissingFields", void 0);
|
|
400
|
+
_ts_decorate([
|
|
401
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
402
|
+
description: 'apply-import: acknowledge steps that lose (or may lose) data',
|
|
403
|
+
default: false
|
|
404
|
+
}),
|
|
405
|
+
(0,class_validator__rspack_import_2.IsOptional)(),
|
|
406
|
+
FormBoolean(),
|
|
407
|
+
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
408
|
+
_ts_metadata("design:type", Boolean)
|
|
409
|
+
], ImportBundleOptionsDto.prototype, "confirm", void 0);
|
|
410
|
+
_ts_decorate([
|
|
411
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
412
|
+
description: 'apply-import: the checksum of the bundle that was reviewed; a different bundle is refused'
|
|
413
|
+
}),
|
|
414
|
+
(0,class_validator__rspack_import_2.IsOptional)(),
|
|
415
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
416
|
+
(0,class_validator__rspack_import_2.Matches)(/^[0-9a-f]{64}$/),
|
|
417
|
+
_ts_metadata("design:type", String)
|
|
418
|
+
], ImportBundleOptionsDto.prototype, "expectedChecksum", void 0);
|
|
419
|
+
_ts_decorate([
|
|
420
|
+
(0,_nestjs_swagger__rspack_import_0.ApiPropertyOptional)({
|
|
421
|
+
description: 'apply-import: the planChecksum of the plan that was reviewed; a changed plan is refused, and it is required with confirm'
|
|
422
|
+
}),
|
|
423
|
+
(0,class_validator__rspack_import_2.IsOptional)(),
|
|
424
|
+
(0,class_validator__rspack_import_2.IsString)(),
|
|
425
|
+
(0,class_validator__rspack_import_2.Matches)(/^[0-9a-f]{64}$/),
|
|
426
|
+
_ts_metadata("design:type", String)
|
|
427
|
+
], ImportBundleOptionsDto.prototype, "expectedPlanChecksum", void 0);
|
|
428
|
+
|
|
429
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
430
|
+
JE: () => (DefinitionBundleDto),
|
|
431
|
+
KH: () => (BundleFlowDto),
|
|
432
|
+
QJ: () => (ExportBundleDto),
|
|
433
|
+
U3: () => (BundleFieldDto),
|
|
434
|
+
hX: () => (BundleEntityDto),
|
|
435
|
+
vS: () => (ImportBundleOptionsDto)
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
},
|
|
440
|
+
8835(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
441
|
+
const DEFINITION_BUNDLE_FORMAT = 'flusys.entity-builder.bundle';
|
|
442
|
+
const DEFINITION_BUNDLE_VERSION = 1;
|
|
443
|
+
|
|
444
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
445
|
+
}, {
|
|
446
|
+
D: DEFINITION_BUNDLE_FORMAT
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
},
|
|
4
451
|
2492(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5
452
|
const FLOW_REFERENCE_PROVIDER = 'FLOW_REFERENCE_PROVIDER';
|
|
6
453
|
|
|
7
454
|
__webpack_require__.d(__webpack_exports__, {
|
|
8
|
-
}, {
|
|
9
|
-
$: FLOW_REFERENCE_PROVIDER
|
|
455
|
+
}, {
|
|
456
|
+
$: FLOW_REFERENCE_PROVIDER
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
},
|
|
461
|
+
3801(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
462
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_0 = __webpack_require__(9216);
|
|
463
|
+
/* import */ var node_crypto__rspack_import_1 = __webpack_require__(2561);
|
|
464
|
+
/* import */ var _config_message_keys_js__rspack_import_2 = __webpack_require__(5732);
|
|
465
|
+
/* import */ var _enums_entity_status_enum_js__rspack_import_3 = __webpack_require__(1313);
|
|
466
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_4 = __webpack_require__(9614);
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
/** JSON with object keys sorted at every level: equal definitions always give the same text. */ function canonicalJson(value) {
|
|
473
|
+
return JSON.stringify(sortKeys(value));
|
|
474
|
+
}
|
|
475
|
+
function sortKeys(value) {
|
|
476
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
477
|
+
if (value && typeof value === 'object' && !(value instanceof Date)) {
|
|
478
|
+
return Object.fromEntries(Object.keys(value).toSorted().filter((key)=>value[key] !== undefined).map((key)=>[
|
|
479
|
+
key,
|
|
480
|
+
sortKeys(value[key])
|
|
481
|
+
]));
|
|
482
|
+
}
|
|
483
|
+
return value;
|
|
484
|
+
}
|
|
485
|
+
const same = (a, b)=>canonicalJson(a ?? null) === canonicalJson(b ?? null);
|
|
486
|
+
/** Code-point order: the same in every locale, so exports and plans read the same everywhere. */ const byCode = (a, b)=>a < b ? -1 : a > b ? 1 : 0;
|
|
487
|
+
/** What a step, extra or result is about: the flow slug, `entity.field` or the entity code. */ const bundleSubject = (item)=>item.flowSlug ?? (item.fieldCode ? `${item.entityCode}.${item.fieldCode}` : item.entityCode ?? '');
|
|
488
|
+
const bundleChecksum = (bundle)=>(0,node_crypto__rspack_import_1.createHash)('sha256').update(canonicalJson(bundle)).digest('hex');
|
|
489
|
+
// ── flows: API keys and environment variables ─────────────────────────────────────────
|
|
490
|
+
/** Request steps without their API keys: a key belongs to one environment and is never promoted. */ function stripApiKeys(nodes) {
|
|
491
|
+
return nodes.map((node)=>{
|
|
492
|
+
if (node?.type !== 'trigger' || node.config?.['apiKey'] === undefined) return node;
|
|
493
|
+
const { apiKey: _apiKey, ...config } = node.config;
|
|
494
|
+
return {
|
|
495
|
+
...node,
|
|
496
|
+
config
|
|
497
|
+
};
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
const VARIABLE_PATTERN = /\$\{var:([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
501
|
+
/** Shorter values would be replaced inside unrelated text. */ const MIN_VARIABLE_VALUE_LENGTH = 4;
|
|
502
|
+
function mapStrings(value, fn) {
|
|
503
|
+
if (typeof value === 'string') return fn(value);
|
|
504
|
+
if (Array.isArray(value)) return value.map((item)=>mapStrings(item, fn));
|
|
505
|
+
if (value && typeof value === 'object') {
|
|
506
|
+
return Object.fromEntries(Object.entries(value).map(([key, item])=>[
|
|
507
|
+
key,
|
|
508
|
+
mapStrings(item, fn)
|
|
509
|
+
]));
|
|
510
|
+
}
|
|
511
|
+
return value;
|
|
512
|
+
}
|
|
513
|
+
/** Only a step's settings hold environment values: its id, type, name and position are never rewritten. */ const mapConfigStrings = (nodes, fn)=>nodes.map((node)=>node?.config ? {
|
|
514
|
+
...node,
|
|
515
|
+
config: mapStrings(node.config, fn)
|
|
516
|
+
} : node);
|
|
517
|
+
const escapeRegExp = (text)=>text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
518
|
+
/**
|
|
519
|
+
* Export: every occurrence of this environment's variable values in a step's settings becomes `${var:NAME}`
|
|
520
|
+
* (longest value first; one pass, so a placeholder already written is never rewritten by a shorter value).
|
|
521
|
+
*/ function extractVariables(nodes, variables) {
|
|
522
|
+
const nameOf = new Map();
|
|
523
|
+
for (const [name, value] of Object.entries(variables).filter(([, text])=>typeof text === 'string' && text.length >= MIN_VARIABLE_VALUE_LENGTH).toSorted(([nameA, a], [nameB, b])=>b.length - a.length || byCode(nameA, nameB))){
|
|
524
|
+
if (!nameOf.has(value)) nameOf.set(value, name);
|
|
525
|
+
}
|
|
526
|
+
if (!nameOf.size) return nodes;
|
|
527
|
+
const pattern = new RegExp([
|
|
528
|
+
...nameOf.keys()
|
|
529
|
+
].map(escapeRegExp).join('|'), 'g');
|
|
530
|
+
return mapConfigStrings(nodes, (text)=>text.replace(pattern, (value)=>`\${var:${nameOf.get(value)}}`));
|
|
531
|
+
}
|
|
532
|
+
/** Import: `${var:NAME}` in a step's settings becomes this environment's value; names it does not define are returned, not replaced. */ function applyVariables(nodes, variables) {
|
|
533
|
+
const missing = new Set();
|
|
534
|
+
const resolved = mapConfigStrings(nodes, (text)=>text.replace(VARIABLE_PATTERN, (token, name)=>{
|
|
535
|
+
if (typeof variables[name] === 'string') return variables[name];
|
|
536
|
+
missing.add(name);
|
|
537
|
+
return token;
|
|
538
|
+
}));
|
|
539
|
+
return {
|
|
540
|
+
nodes: resolved,
|
|
541
|
+
missing: [
|
|
542
|
+
...missing
|
|
543
|
+
].toSorted(byCode)
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
/** Slugs the Call flow steps of a flow run. */ function calledFlowSlugs(nodes) {
|
|
547
|
+
return nodes.filter((node)=>node?.type === 'call_flow' && typeof node.config?.['flowSlug'] === 'string').map((node)=>node.config['flowSlug']);
|
|
548
|
+
}
|
|
549
|
+
/** Called flows before their callers, so each Call flow step finds its flow published; otherwise by slug. */ function orderFlows(flows) {
|
|
550
|
+
const bySlug = new Map(flows.map((flow)=>[
|
|
551
|
+
flow.slug,
|
|
552
|
+
flow
|
|
553
|
+
]));
|
|
554
|
+
const ordered = [];
|
|
555
|
+
const state = new Map();
|
|
556
|
+
const visit = (flow)=>{
|
|
557
|
+
if (state.has(flow.slug)) return;
|
|
558
|
+
state.set(flow.slug, 'visiting');
|
|
559
|
+
for (const slug of calledFlowSlugs(flow.nodes ?? []).toSorted(byCode)){
|
|
560
|
+
const callee = bySlug.get(slug);
|
|
561
|
+
if (callee) visit(callee);
|
|
562
|
+
}
|
|
563
|
+
state.set(flow.slug, 'done');
|
|
564
|
+
ordered.push(flow);
|
|
565
|
+
};
|
|
566
|
+
flows.toSorted((a, b)=>byCode(a.slug, b.slug)).forEach(visit);
|
|
567
|
+
return ordered;
|
|
568
|
+
}
|
|
569
|
+
const FIELD_COMPARED_KEYS = [
|
|
570
|
+
'label',
|
|
571
|
+
'fieldType',
|
|
572
|
+
'nullable',
|
|
573
|
+
'unique',
|
|
574
|
+
'isIndexed',
|
|
575
|
+
'defaultValue',
|
|
576
|
+
'validationRules',
|
|
577
|
+
'selectOptions',
|
|
578
|
+
'relationTarget',
|
|
579
|
+
'order',
|
|
580
|
+
'uiConfig',
|
|
581
|
+
'isSearchable'
|
|
582
|
+
];
|
|
583
|
+
const ENTITY_COMPARED_KEYS = [
|
|
584
|
+
'label',
|
|
585
|
+
'description',
|
|
586
|
+
'uiConfig',
|
|
587
|
+
'isSoftDeleteEnabled',
|
|
588
|
+
'isAuditEnabled',
|
|
589
|
+
'status'
|
|
590
|
+
];
|
|
591
|
+
function changedValues(from, to, keys) {
|
|
592
|
+
return Object.fromEntries(keys.filter((key)=>!same(from[key], to[key])).map((key)=>[
|
|
593
|
+
key,
|
|
594
|
+
to[key] ?? null
|
|
595
|
+
]));
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Pairs each item of the bundle with one of this environment's: by id first (a renamed one keeps
|
|
599
|
+
* its id), then by code among those no id claimed, so a rename never takes a field another item owns.
|
|
600
|
+
*/ function matchDefinitions(items, current) {
|
|
601
|
+
const pairs = new Map();
|
|
602
|
+
const taken = new Set();
|
|
603
|
+
const claim = (item, hit)=>{
|
|
604
|
+
if (!hit) return;
|
|
605
|
+
pairs.set(item, hit);
|
|
606
|
+
taken.add(hit.id);
|
|
607
|
+
};
|
|
608
|
+
for (const item of items)claim(item, current.find((c)=>c.id === item.id && !taken.has(c.id)));
|
|
609
|
+
for (const item of items.filter((i)=>!pairs.has(i)))claim(item, current.find((c)=>c.code === item.code && !taken.has(c.id)));
|
|
610
|
+
return pairs;
|
|
611
|
+
}
|
|
612
|
+
/** The bundle's own problems: duplicates, and relations to an entity neither the bundle nor this environment has. */ function bundleProblems(entities, current) {
|
|
613
|
+
const problems = [];
|
|
614
|
+
const codes = new Set();
|
|
615
|
+
for (const entity of entities){
|
|
616
|
+
if (codes.has(entity.code)) problems.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .BUNDLE_MESSAGES.DUPLICATE_ENTITY */.iX.DUPLICATE_ENTITY, {
|
|
617
|
+
entity: entity.code
|
|
618
|
+
}));
|
|
619
|
+
if (entity.status === _enums_entity_status_enum_js__rspack_import_3/* .EntityStatus.DRAFT */.c.DRAFT) problems.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .BUNDLE_MESSAGES.ENTITY_DRAFT_IN_BUNDLE */.iX.ENTITY_DRAFT_IN_BUNDLE, {
|
|
620
|
+
entity: entity.code
|
|
621
|
+
}));
|
|
622
|
+
codes.add(entity.code);
|
|
623
|
+
const fieldCodes = new Set();
|
|
624
|
+
const fieldIds = new Set();
|
|
625
|
+
for (const field of entity.fields){
|
|
626
|
+
if (fieldCodes.has(field.code) || fieldIds.has(field.id)) problems.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .BUNDLE_MESSAGES.DUPLICATE_FIELD */.iX.DUPLICATE_FIELD, {
|
|
627
|
+
entity: entity.code,
|
|
628
|
+
field: field.code
|
|
629
|
+
}));
|
|
630
|
+
fieldCodes.add(field.code);
|
|
631
|
+
fieldIds.add(field.id);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
const known = new Set([
|
|
635
|
+
...codes,
|
|
636
|
+
...current.map((e)=>e.code)
|
|
637
|
+
]);
|
|
638
|
+
for (const entity of entities){
|
|
639
|
+
for (const field of entity.fields.filter((f)=>f.fieldType === _enums_field_type_enum_js__rspack_import_4/* .FieldType.RELATION */.P.RELATION && !f.deprecated)){
|
|
640
|
+
if (!field.relationTarget || !known.has(field.relationTarget)) {
|
|
641
|
+
problems.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .BUNDLE_MESSAGES.RELATION_TARGET_UNKNOWN */.iX.RELATION_TARGET_UNKNOWN, {
|
|
642
|
+
entity: entity.code,
|
|
643
|
+
field: field.code,
|
|
644
|
+
target: field.relationTarget ?? ''
|
|
645
|
+
}));
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return problems;
|
|
650
|
+
}
|
|
651
|
+
/** A code no field of the entity has or gets, for the temporary step of a rename cycle. */ function temporaryCode(fieldId, taken) {
|
|
652
|
+
const base = `tmp_${fieldId.replace(/[^0-9a-z]/gi, '').toLowerCase().slice(0, 12)}`;
|
|
653
|
+
let code = base;
|
|
654
|
+
for(let n = 2; taken.has(code); n++)code = `${base}_${n}`;
|
|
655
|
+
taken.add(code);
|
|
656
|
+
return code;
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Renames in an order that never takes a code another field still has: a rename waits for the one
|
|
660
|
+
* that frees its new code (a -> b after b -> c), and a cycle (a <-> b) goes through a temporary code
|
|
661
|
+
* first (a -> tmp, b -> a, tmp -> b). Each rename rewrites the references to its field, so the
|
|
662
|
+
* references end up exactly where the bundle has them.
|
|
663
|
+
*/ function orderRenames(entityCode, renames, taken) {
|
|
664
|
+
const ordered = [];
|
|
665
|
+
const pending = renames.map((rename)=>({
|
|
666
|
+
...rename,
|
|
667
|
+
waited: false
|
|
668
|
+
})).toSorted((a, b)=>byCode(a.from, b.from));
|
|
669
|
+
const step = (rename, from, to, dependsOnEarlierStep, warnings)=>({
|
|
670
|
+
kind: 'rename_field',
|
|
671
|
+
entityCode,
|
|
672
|
+
fieldCode: from,
|
|
673
|
+
targetFieldId: rename.targetFieldId,
|
|
674
|
+
details: {
|
|
675
|
+
from,
|
|
676
|
+
to
|
|
677
|
+
},
|
|
678
|
+
dependsOnEarlierStep,
|
|
679
|
+
changes: {
|
|
680
|
+
code: to
|
|
681
|
+
},
|
|
682
|
+
...warnings ? {
|
|
683
|
+
warnings
|
|
684
|
+
} : {}
|
|
685
|
+
});
|
|
686
|
+
while(pending.length){
|
|
687
|
+
const ready = pending.filter((rename)=>!pending.some((other)=>other !== rename && other.from === rename.to));
|
|
688
|
+
if (ready.length) {
|
|
689
|
+
for (const rename of ready){
|
|
690
|
+
ordered.push(step(rename, rename.from, rename.to, rename.restored || rename.waited));
|
|
691
|
+
pending.splice(pending.indexOf(rename), 1);
|
|
692
|
+
}
|
|
693
|
+
for (const rename of pending)rename.waited = true;
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
const first = pending[0];
|
|
697
|
+
const temporary = temporaryCode(first.targetFieldId, taken);
|
|
698
|
+
ordered.push(step(first, first.from, temporary, first.restored || first.waited, [
|
|
699
|
+
(0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .BUNDLE_MESSAGES.RENAME_VIA_TEMPORARY */.iX.RENAME_VIA_TEMPORARY, {
|
|
700
|
+
field: first.from,
|
|
701
|
+
temporary,
|
|
702
|
+
to: first.to
|
|
703
|
+
})
|
|
704
|
+
]));
|
|
705
|
+
const freed = pending.find((rename)=>rename.to === first.from);
|
|
706
|
+
if (freed) freed.waited = true;
|
|
707
|
+
first.from = temporary;
|
|
708
|
+
first.waited = true;
|
|
709
|
+
}
|
|
710
|
+
return ordered;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* What it takes to bring this environment's entities to the bundle's. Entities and fields are
|
|
714
|
+
* matched by id first (a field renamed where it was designed keeps its id), then by code. Nothing
|
|
715
|
+
* the bundle lacks is removed: such definitions are reported as extras, and only with
|
|
716
|
+
* `deprecateMissingFields` are missing fields deprecated (which keeps their column and data).
|
|
717
|
+
*
|
|
718
|
+
* Order: entities switched back on, new entities (their relation fields wait until every new entity
|
|
719
|
+
* exists), field changes of existing entities (per entity: restores, renames, changes, new fields,
|
|
720
|
+
* deprecations), the new entities' relation fields, and entities switched off last. A DRAFT entity
|
|
721
|
+
* (no table) on either side blocks the import.
|
|
722
|
+
*/ function diffEntities(entities, current, options = {}) {
|
|
723
|
+
const result = {
|
|
724
|
+
operations: [],
|
|
725
|
+
unchangedEntities: 0,
|
|
726
|
+
unchangedFields: 0,
|
|
727
|
+
extras: [],
|
|
728
|
+
blockers: bundleProblems(entities, current)
|
|
729
|
+
};
|
|
730
|
+
const entityUpdatesFirst = [];
|
|
731
|
+
const creates = [];
|
|
732
|
+
const fieldOps = [];
|
|
733
|
+
const relationAdds = [];
|
|
734
|
+
const entityUpdatesLast = [];
|
|
735
|
+
const sorted = entities.toSorted((a, b)=>byCode(a.code, b.code));
|
|
736
|
+
const pairs = matchDefinitions(sorted, current);
|
|
737
|
+
const matched = new Set([
|
|
738
|
+
...pairs.values()
|
|
739
|
+
].map((e)=>e.id));
|
|
740
|
+
for (const entity of sorted){
|
|
741
|
+
const target = pairs.get(entity);
|
|
742
|
+
if (target && target.code !== entity.code) {
|
|
743
|
+
result.blockers.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .BUNDLE_MESSAGES.ENTITY_CODE_CHANGED */.iX.ENTITY_CODE_CHANGED, {
|
|
744
|
+
entity: entity.code,
|
|
745
|
+
current: target.code
|
|
746
|
+
}));
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
if (!target) {
|
|
750
|
+
const live = entity.fields.filter((f)=>!f.deprecated);
|
|
751
|
+
creates.push({
|
|
752
|
+
kind: 'create_entity',
|
|
753
|
+
entityCode: entity.code,
|
|
754
|
+
details: {
|
|
755
|
+
fields: live.filter((f)=>f.fieldType !== _enums_field_type_enum_js__rspack_import_4/* .FieldType.RELATION */.P.RELATION).map((f)=>f.code)
|
|
756
|
+
},
|
|
757
|
+
dependsOnEarlierStep: false,
|
|
758
|
+
entity: {
|
|
759
|
+
...entity,
|
|
760
|
+
fields: live.filter((f)=>f.fieldType !== _enums_field_type_enum_js__rspack_import_4/* .FieldType.RELATION */.P.RELATION)
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
for (const field of live.filter((f)=>f.fieldType === _enums_field_type_enum_js__rspack_import_4/* .FieldType.RELATION */.P.RELATION)){
|
|
764
|
+
relationAdds.push({
|
|
765
|
+
kind: 'add_field',
|
|
766
|
+
entityCode: entity.code,
|
|
767
|
+
fieldCode: field.code,
|
|
768
|
+
details: {
|
|
769
|
+
fieldType: field.fieldType,
|
|
770
|
+
relationTarget: field.relationTarget
|
|
771
|
+
},
|
|
772
|
+
dependsOnEarlierStep: true,
|
|
773
|
+
field
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
if (entity.status === _enums_entity_status_enum_js__rspack_import_3/* .EntityStatus.DEPRECATED */.c.DEPRECATED) {
|
|
777
|
+
entityUpdatesLast.push({
|
|
778
|
+
kind: 'update_entity',
|
|
779
|
+
entityCode: entity.code,
|
|
780
|
+
details: {
|
|
781
|
+
changes: [
|
|
782
|
+
'status'
|
|
783
|
+
]
|
|
784
|
+
},
|
|
785
|
+
dependsOnEarlierStep: true,
|
|
786
|
+
changes: {
|
|
787
|
+
status: _enums_entity_status_enum_js__rspack_import_3/* .EntityStatus.DEPRECATED */.c.DEPRECATED
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
793
|
+
if (target.status === _enums_entity_status_enum_js__rspack_import_3/* .EntityStatus.DRAFT */.c.DRAFT) {
|
|
794
|
+
result.blockers.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_2/* .BUNDLE_MESSAGES.ENTITY_DRAFT_HERE */.iX.ENTITY_DRAFT_HERE, {
|
|
795
|
+
entity: entity.code
|
|
796
|
+
}));
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
const entityChanges = changedValues(target, entity, ENTITY_COMPARED_KEYS);
|
|
800
|
+
const deprecating = entityChanges['status'] === _enums_entity_status_enum_js__rspack_import_3/* .EntityStatus.DEPRECATED */.c.DEPRECATED;
|
|
801
|
+
if (Object.keys(entityChanges).length) {
|
|
802
|
+
(deprecating ? entityUpdatesLast : entityUpdatesFirst).push({
|
|
803
|
+
kind: 'update_entity',
|
|
804
|
+
entityCode: entity.code,
|
|
805
|
+
details: {
|
|
806
|
+
changes: Object.keys(entityChanges)
|
|
807
|
+
},
|
|
808
|
+
dependsOnEarlierStep: false,
|
|
809
|
+
changes: entityChanges
|
|
810
|
+
});
|
|
811
|
+
} else {
|
|
812
|
+
result.unchangedEntities++;
|
|
813
|
+
}
|
|
814
|
+
const fields = entity.fields.toSorted((a, b)=>a.order - b.order || byCode(a.code, b.code));
|
|
815
|
+
const fieldPairs = matchDefinitions(fields, target.fields);
|
|
816
|
+
const usedFieldIds = new Set([
|
|
817
|
+
...fieldPairs.values()
|
|
818
|
+
].map((f)=>f.id));
|
|
819
|
+
const restores = [];
|
|
820
|
+
const renames = [];
|
|
821
|
+
const updates = [];
|
|
822
|
+
const adds = [];
|
|
823
|
+
const deprecations = [];
|
|
824
|
+
for (const field of fields){
|
|
825
|
+
const existing = fieldPairs.get(field);
|
|
826
|
+
if (!existing) {
|
|
827
|
+
if (field.deprecated) continue;
|
|
828
|
+
adds.push({
|
|
829
|
+
kind: 'add_field',
|
|
830
|
+
entityCode: entity.code,
|
|
831
|
+
fieldCode: field.code,
|
|
832
|
+
details: {
|
|
833
|
+
fieldType: field.fieldType,
|
|
834
|
+
relationTarget: field.relationTarget
|
|
835
|
+
},
|
|
836
|
+
dependsOnEarlierStep: false,
|
|
837
|
+
field
|
|
838
|
+
});
|
|
839
|
+
continue;
|
|
840
|
+
}
|
|
841
|
+
const at = {
|
|
842
|
+
entityCode: entity.code,
|
|
843
|
+
targetFieldId: existing.id
|
|
844
|
+
};
|
|
845
|
+
let touched = false;
|
|
846
|
+
// A deprecated field cannot be changed until it is restored; a rename does not stop the other changes from being previewed.
|
|
847
|
+
const restored = existing.deprecated && !field.deprecated;
|
|
848
|
+
if (restored) {
|
|
849
|
+
restores.push({
|
|
850
|
+
...at,
|
|
851
|
+
kind: 'restore_field',
|
|
852
|
+
fieldCode: existing.code,
|
|
853
|
+
details: {},
|
|
854
|
+
dependsOnEarlierStep: false
|
|
855
|
+
});
|
|
856
|
+
touched = true;
|
|
857
|
+
}
|
|
858
|
+
if (existing.code !== field.code && !field.deprecated) {
|
|
859
|
+
renames.push({
|
|
860
|
+
targetFieldId: existing.id,
|
|
861
|
+
from: existing.code,
|
|
862
|
+
to: field.code,
|
|
863
|
+
restored
|
|
864
|
+
});
|
|
865
|
+
touched = true;
|
|
866
|
+
}
|
|
867
|
+
const changes = field.deprecated ? {} : changedValues(existing, field, FIELD_COMPARED_KEYS);
|
|
868
|
+
if (Object.keys(changes).length) {
|
|
869
|
+
updates.push({
|
|
870
|
+
...at,
|
|
871
|
+
kind: 'update_field',
|
|
872
|
+
fieldCode: field.code,
|
|
873
|
+
details: {
|
|
874
|
+
changes: Object.keys(changes)
|
|
875
|
+
},
|
|
876
|
+
dependsOnEarlierStep: restored,
|
|
877
|
+
changes
|
|
878
|
+
});
|
|
879
|
+
touched = true;
|
|
880
|
+
}
|
|
881
|
+
if (field.deprecated && !existing.deprecated) {
|
|
882
|
+
deprecations.push({
|
|
883
|
+
...at,
|
|
884
|
+
kind: 'deprecate_field',
|
|
885
|
+
fieldCode: existing.code,
|
|
886
|
+
details: {},
|
|
887
|
+
dependsOnEarlierStep: false
|
|
888
|
+
});
|
|
889
|
+
touched = true;
|
|
890
|
+
}
|
|
891
|
+
if (!touched) result.unchangedFields++;
|
|
892
|
+
}
|
|
893
|
+
// A new field may take a code a rename frees: it is added once that rename has run.
|
|
894
|
+
const freedCodes = new Set(renames.map((r)=>r.from));
|
|
895
|
+
for (const add of adds)if (freedCodes.has(add.fieldCode)) add.dependsOnEarlierStep = true;
|
|
896
|
+
const takenCodes = new Set([
|
|
897
|
+
...target.fields.map((f)=>f.code),
|
|
898
|
+
...fields.map((f)=>f.code)
|
|
899
|
+
]);
|
|
900
|
+
fieldOps.push(...restores, ...orderRenames(entity.code, renames, takenCodes), ...updates, ...adds, ...deprecations);
|
|
901
|
+
for (const extra of target.fields.filter((f)=>!usedFieldIds.has(f.id) && !f.deprecated)){
|
|
902
|
+
if (options.deprecateMissingFields) {
|
|
903
|
+
fieldOps.push({
|
|
904
|
+
kind: 'deprecate_field',
|
|
905
|
+
entityCode: entity.code,
|
|
906
|
+
fieldCode: extra.code,
|
|
907
|
+
targetFieldId: extra.id,
|
|
908
|
+
details: {},
|
|
909
|
+
dependsOnEarlierStep: false
|
|
910
|
+
});
|
|
911
|
+
} else {
|
|
912
|
+
result.extras.push({
|
|
913
|
+
kind: 'field',
|
|
914
|
+
entityCode: entity.code,
|
|
915
|
+
fieldCode: extra.code
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
for (const extra of current.filter((e)=>!matched.has(e.id)))result.extras.push({
|
|
921
|
+
kind: 'entity',
|
|
922
|
+
entityCode: extra.code
|
|
923
|
+
});
|
|
924
|
+
result.operations = [
|
|
925
|
+
...entityUpdatesFirst,
|
|
926
|
+
...creates,
|
|
927
|
+
...fieldOps,
|
|
928
|
+
...relationAdds,
|
|
929
|
+
...entityUpdatesLast
|
|
930
|
+
];
|
|
931
|
+
return result;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
935
|
+
Og: () => (matchDefinitions),
|
|
936
|
+
Q5: () => (calledFlowSlugs),
|
|
937
|
+
dX: () => (stripApiKeys),
|
|
938
|
+
dj: () => (canonicalJson),
|
|
939
|
+
gT: () => (applyVariables),
|
|
940
|
+
lj: () => (extractVariables),
|
|
941
|
+
qG: () => (orderFlows),
|
|
942
|
+
zb: () => (diffEntities)
|
|
943
|
+
}, {
|
|
944
|
+
$I: ENTITY_COMPARED_KEYS,
|
|
945
|
+
VU: byCode,
|
|
946
|
+
bs: bundleSubject,
|
|
947
|
+
i9: bundleChecksum,
|
|
948
|
+
mT: FIELD_COMPARED_KEYS
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
},
|
|
953
|
+
6412(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
954
|
+
/* import */ var _nestjs_common__rspack_import_0 = __webpack_require__(6157);
|
|
955
|
+
/* import */ var class_transformer__rspack_import_1 = __webpack_require__(5812);
|
|
956
|
+
/* import */ var class_validator__rspack_import_2 = __webpack_require__(5421);
|
|
957
|
+
/* import */ var _config_message_keys_js__rspack_import_4 = __webpack_require__(5732);
|
|
958
|
+
/* import */ var _dtos_definition_bundle_dto_js__rspack_import_3 = __webpack_require__(6691);
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
const MAX_REPORTED_PROBLEMS = 50;
|
|
965
|
+
/** Every failed constraint, named by its path in the bundle (`entities.0.fields.2.code`). */ function problems(errors, parent = '') {
|
|
966
|
+
return errors.flatMap((error)=>{
|
|
967
|
+
const field = parent ? `${parent}.${error.property}` : error.property;
|
|
968
|
+
const own = error.constraints ? [
|
|
969
|
+
{
|
|
970
|
+
field,
|
|
971
|
+
message: Object.values(error.constraints).join('; ')
|
|
972
|
+
}
|
|
973
|
+
] : [];
|
|
974
|
+
return [
|
|
975
|
+
...own,
|
|
976
|
+
...problems(error.children ?? [], field)
|
|
977
|
+
];
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
const invalid = (errors = [])=>new _nestjs_common__rspack_import_0.BadRequestException({
|
|
981
|
+
message: 'The file is not a valid entity builder bundle.',
|
|
982
|
+
messageKey: _config_message_keys_js__rspack_import_4/* .BUNDLE_MESSAGES.FILE_INVALID */.iX.FILE_INVALID,
|
|
983
|
+
...errors.length ? {
|
|
984
|
+
errors: errors.slice(0, MAX_REPORTED_PROBLEMS)
|
|
985
|
+
} : {}
|
|
986
|
+
});
|
|
987
|
+
/**
|
|
988
|
+
* The uploaded bundle, parsed and checked as strictly as a request body (unknown keys refused). The
|
|
989
|
+
* bundle travels as a file rather than as JSON so the app's JSON body limit never applies to it: the
|
|
990
|
+
* upload limit is the package's own (`ENTITY_BUNDLE_MAX_BYTES`, enforced by FileInterceptor).
|
|
991
|
+
*/ function readBundleFile(file) {
|
|
992
|
+
if (!file?.buffer?.length) {
|
|
993
|
+
throw new _nestjs_common__rspack_import_0.BadRequestException({
|
|
994
|
+
message: 'Attach the bundle file as the "bundle" form field.',
|
|
995
|
+
messageKey: _config_message_keys_js__rspack_import_4/* .BUNDLE_MESSAGES.FILE_REQUIRED */.iX.FILE_REQUIRED
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
let raw;
|
|
999
|
+
try {
|
|
1000
|
+
raw = JSON.parse(file.buffer.toString('utf8').replace(/^\uFEFF/, ''));
|
|
1001
|
+
} catch {
|
|
1002
|
+
throw invalid();
|
|
1003
|
+
}
|
|
1004
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw invalid();
|
|
1005
|
+
const bundle = (0,class_transformer__rspack_import_1.plainToInstance)(_dtos_definition_bundle_dto_js__rspack_import_3/* .DefinitionBundleDto */.JE, raw);
|
|
1006
|
+
const errors = (0,class_validator__rspack_import_2.validateSync)(bundle, {
|
|
1007
|
+
whitelist: true,
|
|
1008
|
+
forbidNonWhitelisted: true
|
|
1009
|
+
});
|
|
1010
|
+
if (errors.length) throw invalid(problems(errors));
|
|
1011
|
+
return bundle;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1015
|
+
z: () => (readBundleFile)
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
},
|
|
1020
|
+
7463(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1021
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_0 = __webpack_require__(9216);
|
|
1022
|
+
/* import */ var _nestjs_common__rspack_import_1 = __webpack_require__(6157);
|
|
1023
|
+
/* import */ var node_crypto__rspack_import_2 = __webpack_require__(2561);
|
|
1024
|
+
/* import */ var typeorm__rspack_import_3 = __webpack_require__(7158);
|
|
1025
|
+
/* import */ var _config_message_keys_js__rspack_import_17 = __webpack_require__(5732);
|
|
1026
|
+
/* import */ var _dtos_schema_change_dto_js__rspack_import_4 = __webpack_require__(4945);
|
|
1027
|
+
/* import */ var _entities_entity_definition_entity_js__rspack_import_5 = __webpack_require__(3189);
|
|
1028
|
+
/* import */ var _enums_entity_status_enum_js__rspack_import_16 = __webpack_require__(1313);
|
|
1029
|
+
/* import */ var _entities_field_definition_entity_js__rspack_import_6 = __webpack_require__(2206);
|
|
1030
|
+
/* import */ var _entities_flow_definition_entity_js__rspack_import_7 = __webpack_require__(3770);
|
|
1031
|
+
/* import */ var _flow_engine_flow_errors_js__rspack_import_8 = __webpack_require__(8542);
|
|
1032
|
+
/* import */ var _flow_engine_flow_types_js__rspack_import_9 = __webpack_require__(6256);
|
|
1033
|
+
/* import */ var _interfaces_definition_bundle_interface_js__rspack_import_18 = __webpack_require__(8835);
|
|
1034
|
+
/* import */ var _interfaces_flow_definition_interface_js__rspack_import_19 = __webpack_require__(9609);
|
|
1035
|
+
/* import */ var _definition_bundle_diff_js__rspack_import_10 = __webpack_require__(3801);
|
|
1036
|
+
/* import */ var _entity_builder_config_service_js__rspack_import_11 = __webpack_require__(4281);
|
|
1037
|
+
/* import */ var _entity_builder_datasource_provider_js__rspack_import_12 = __webpack_require__(424);
|
|
1038
|
+
/* import */ var _flow_definition_service_js__rspack_import_13 = __webpack_require__(5229);
|
|
1039
|
+
/* import */ var _schema_evolution_service_js__rspack_import_14 = __webpack_require__(3606);
|
|
1040
|
+
/* import */ var _schema_sync_service_js__rspack_import_15 = __webpack_require__(3474);
|
|
1041
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
1042
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1043
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
1044
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1045
|
+
} else {
|
|
1046
|
+
for(var i = decorators.length - 1; i >= 0; i--){
|
|
1047
|
+
if (d = decorators[i]) {
|
|
1048
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1053
|
+
}
|
|
1054
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
1055
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
1056
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
function _ts_param(paramIndex, decorator) {
|
|
1060
|
+
return function(target, key) {
|
|
1061
|
+
decorator(target, key, paramIndex);
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
/** The reasons a failed step gives besides its message: a change's blockers, a flow's validation errors. */ function failureDetails(error) {
|
|
1085
|
+
if (!(error instanceof _nestjs_common__rspack_import_1.HttpException)) return [];
|
|
1086
|
+
const response = error.getResponse();
|
|
1087
|
+
if (typeof response !== 'object') return [];
|
|
1088
|
+
const details = response.blockers ?? response.errors ?? [];
|
|
1089
|
+
return details.filter((d)=>typeof d?.messageKey === 'string').map((d)=>(0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(d.messageKey, d.messageVariables));
|
|
1090
|
+
}
|
|
1091
|
+
/** Structural changes that, unpreviewed, may turn out to lose data (a type conversion, a column made required or unique, audit or soft delete switched off). */ const LOSSY_FIELD_CHANGES = [
|
|
1092
|
+
'fieldType',
|
|
1093
|
+
'nullable',
|
|
1094
|
+
'unique'
|
|
1095
|
+
];
|
|
1096
|
+
const LOSSY_ENTITY_CHANGES = [
|
|
1097
|
+
'isSoftDeleteEnabled',
|
|
1098
|
+
'isAuditEnabled'
|
|
1099
|
+
];
|
|
1100
|
+
function mayLoseData(step) {
|
|
1101
|
+
const changes = Array.isArray(step.details['changes']) ? step.details['changes'] : [];
|
|
1102
|
+
if (step.kind === 'update_field') return changes.some((c)=>LOSSY_FIELD_CHANGES.includes(c));
|
|
1103
|
+
return step.kind === 'update_entity' && changes.some((c)=>LOSSY_ENTITY_CHANGES.includes(c));
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* What was reviewed: the bundle, the options and every step (kind, subject, changes, and whether its
|
|
1107
|
+
* preview loses data). Not the SQL or row counts, which change with every write and would refuse each apply.
|
|
1108
|
+
*/ function planChecksum(bundle, deprecateMissingFields, steps) {
|
|
1109
|
+
const reviewed = steps.map((step)=>({
|
|
1110
|
+
kind: step.kind,
|
|
1111
|
+
subject: (0,_definition_bundle_diff_js__rspack_import_10/* .bundleSubject */.bs)(step),
|
|
1112
|
+
details: step.details,
|
|
1113
|
+
destructive: step.preview?.destructive ?? null
|
|
1114
|
+
}));
|
|
1115
|
+
return (0,node_crypto__rspack_import_2.createHash)('sha256').update((0,_definition_bundle_diff_js__rspack_import_10/* .canonicalJson */.dj)({
|
|
1116
|
+
bundle,
|
|
1117
|
+
deprecateMissingFields,
|
|
1118
|
+
steps: reviewed
|
|
1119
|
+
})).digest('hex');
|
|
1120
|
+
}
|
|
1121
|
+
const newApiKey = ()=>`fk_${(0,node_crypto__rspack_import_2.randomBytes)(4).toString('hex')}_${(0,node_crypto__rspack_import_2.randomBytes)(16).toString('hex')}`;
|
|
1122
|
+
const triggerPath = (node)=>typeof node.config?.['path'] === 'string' && node.config['path'] ? node.config['path'] : null;
|
|
1123
|
+
const needsApiKey = (node)=>node?.type === 'trigger' && node.config?.['authMode'] === 'api_key';
|
|
1124
|
+
/** The stored API keys of a flow's Request steps (published and draft), by step id. */ function storedApiKeys(flow) {
|
|
1125
|
+
const keys = new Map();
|
|
1126
|
+
for (const node of [
|
|
1127
|
+
...flow?.nodes ?? [],
|
|
1128
|
+
...flow?.draft?.nodes ?? []
|
|
1129
|
+
]){
|
|
1130
|
+
if (node?.type === 'trigger' && (0,_flow_engine_flow_types_js__rspack_import_9/* .isStoredApiKey */.xA)(node.config?.['apiKey']) && !keys.has(node.id)) keys.set(node.id, node.config['apiKey']);
|
|
1131
|
+
}
|
|
1132
|
+
return keys;
|
|
1133
|
+
}
|
|
1134
|
+
class DefinitionBundleService {
|
|
1135
|
+
provider;
|
|
1136
|
+
config;
|
|
1137
|
+
schemaSync;
|
|
1138
|
+
evolution;
|
|
1139
|
+
flows;
|
|
1140
|
+
constructor(provider, config, schemaSync, evolution, flows){
|
|
1141
|
+
this.provider = provider;
|
|
1142
|
+
this.config = config;
|
|
1143
|
+
this.schemaSync = schemaSync;
|
|
1144
|
+
this.evolution = evolution;
|
|
1145
|
+
this.flows = flows;
|
|
1146
|
+
}
|
|
1147
|
+
variables() {
|
|
1148
|
+
return this.config.getBundleVariables();
|
|
1149
|
+
}
|
|
1150
|
+
// ── export ──────────────────────────────────────────────────────────────────────────
|
|
1151
|
+
async export(dto) {
|
|
1152
|
+
const current = await this.loadEntities();
|
|
1153
|
+
const selected = dto.entityCodes ? current.filter((e)=>dto.entityCodes.includes(e.code)) : current;
|
|
1154
|
+
// A DRAFT entity has no table where it is designed, so there is nothing to promote yet.
|
|
1155
|
+
const drafts = selected.filter((e)=>e.status === _enums_entity_status_enum_js__rspack_import_16/* .EntityStatus.DRAFT */.c.DRAFT).toSorted((a, b)=>(0,_definition_bundle_diff_js__rspack_import_10/* .byCode */.VU)(a.code, b.code));
|
|
1156
|
+
const entities = selected.filter((e)=>e.status !== _enums_entity_status_enum_js__rspack_import_16/* .EntityStatus.DRAFT */.c.DRAFT).toSorted((a, b)=>(0,_definition_bundle_diff_js__rspack_import_10/* .byCode */.VU)(a.code, b.code)).map((entity)=>({
|
|
1157
|
+
...entity,
|
|
1158
|
+
fields: entity.fields.toSorted((a, b)=>a.order - b.order || (0,_definition_bundle_diff_js__rspack_import_10/* .byCode */.VU)(a.code, b.code))
|
|
1159
|
+
}));
|
|
1160
|
+
const flowRepo = await this.provider.getRepository(_entities_flow_definition_entity_js__rspack_import_7/* .FlowDefinition */.G);
|
|
1161
|
+
const rows = (await flowRepo.find({
|
|
1162
|
+
where: dto.flowSlugs ? {
|
|
1163
|
+
slug: (0,typeorm__rspack_import_3.In)(dto.flowSlugs)
|
|
1164
|
+
} : {}
|
|
1165
|
+
})).toSorted((a, b)=>(0,_definition_bundle_diff_js__rspack_import_10/* .byCode */.VU)(a.slug, b.slug));
|
|
1166
|
+
const warnings = [
|
|
1167
|
+
...drafts.map((entity)=>(0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.ENTITY_DRAFT_SKIPPED */.iX.ENTITY_DRAFT_SKIPPED, {
|
|
1168
|
+
entity: entity.code
|
|
1169
|
+
})),
|
|
1170
|
+
...rows.filter((flow)=>!(0,_flow_definition_service_js__rspack_import_13/* .isPublished */.HF)(flow)).map((flow)=>(0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.FLOW_UNPUBLISHED_SKIPPED */.iX.FLOW_UNPUBLISHED_SKIPPED, {
|
|
1171
|
+
flow: flow.slug
|
|
1172
|
+
}))
|
|
1173
|
+
];
|
|
1174
|
+
const variables = this.variables();
|
|
1175
|
+
const flows = rows.filter(_flow_definition_service_js__rspack_import_13/* .isPublished */.HF).map((flow)=>{
|
|
1176
|
+
const snapshot = (0,_flow_definition_service_js__rspack_import_13/* .snapshotOf */.eY)(flow);
|
|
1177
|
+
return {
|
|
1178
|
+
...snapshot,
|
|
1179
|
+
description: snapshot.description ?? null,
|
|
1180
|
+
nodes: (0,_definition_bundle_diff_js__rspack_import_10/* .extractVariables */.lj)((0,_definition_bundle_diff_js__rspack_import_10/* .stripApiKeys */.dX)(snapshot.nodes ?? []), variables),
|
|
1181
|
+
edges: snapshot.edges ?? []
|
|
1182
|
+
};
|
|
1183
|
+
});
|
|
1184
|
+
// Keys sorted at every level: PostgreSQL and MySQL hand JSON columns back in different key orders.
|
|
1185
|
+
const bundle = JSON.parse((0,_definition_bundle_diff_js__rspack_import_10/* .canonicalJson */.dj)({
|
|
1186
|
+
format: _interfaces_definition_bundle_interface_js__rspack_import_18/* .DEFINITION_BUNDLE_FORMAT */.D,
|
|
1187
|
+
version: (/* inlined export .DEFINITION_BUNDLE_VERSION */1),
|
|
1188
|
+
entities,
|
|
1189
|
+
flows
|
|
1190
|
+
}));
|
|
1191
|
+
return {
|
|
1192
|
+
bundle,
|
|
1193
|
+
checksum: (0,_definition_bundle_diff_js__rspack_import_10/* .bundleChecksum */.i9)(bundle),
|
|
1194
|
+
warnings
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
/** Every entity of this environment with its fields, relations named by target code. */ async loadEntities() {
|
|
1198
|
+
const definitions = await (await this.provider.getRepository(_entities_entity_definition_entity_js__rspack_import_5/* .EntityDefinition */.f)).find();
|
|
1199
|
+
const fields = await (await this.provider.getRepository(_entities_field_definition_entity_js__rspack_import_6/* .FieldDefinition */.c)).find();
|
|
1200
|
+
const codeOf = new Map(definitions.map((d)=>[
|
|
1201
|
+
d.id,
|
|
1202
|
+
d.code
|
|
1203
|
+
]));
|
|
1204
|
+
return definitions.map((definition)=>({
|
|
1205
|
+
id: definition.id,
|
|
1206
|
+
code: definition.code,
|
|
1207
|
+
label: definition.label,
|
|
1208
|
+
description: definition.description ?? null,
|
|
1209
|
+
status: definition.status,
|
|
1210
|
+
isSoftDeleteEnabled: definition.isSoftDeleteEnabled,
|
|
1211
|
+
isAuditEnabled: definition.isAuditEnabled,
|
|
1212
|
+
uiConfig: definition.uiConfig ?? null,
|
|
1213
|
+
fields: fields.filter((f)=>f.entityDefinitionId === definition.id && !f.isSystemField).map((f)=>({
|
|
1214
|
+
id: f.id,
|
|
1215
|
+
code: f.code,
|
|
1216
|
+
label: f.label,
|
|
1217
|
+
fieldType: f.fieldType,
|
|
1218
|
+
nullable: f.nullable,
|
|
1219
|
+
unique: f.unique,
|
|
1220
|
+
isIndexed: f.isIndexed,
|
|
1221
|
+
defaultValue: f.defaultValue ?? null,
|
|
1222
|
+
validationRules: f.validationRules ?? null,
|
|
1223
|
+
selectOptions: f.selectOptions ?? null,
|
|
1224
|
+
relationTarget: f.relationTargetEntityId ? codeOf.get(f.relationTargetEntityId) ?? null : null,
|
|
1225
|
+
order: f.order,
|
|
1226
|
+
uiConfig: f.uiConfig ?? null,
|
|
1227
|
+
isSearchable: f.isSearchable,
|
|
1228
|
+
deprecated: !!f.deprecatedAt
|
|
1229
|
+
}))
|
|
1230
|
+
}));
|
|
1231
|
+
}
|
|
1232
|
+
// ── plan ────────────────────────────────────────────────────────────────────────────
|
|
1233
|
+
async planImport(dto, user) {
|
|
1234
|
+
const { plan } = await this.buildPlan(dto, user);
|
|
1235
|
+
return plan;
|
|
1236
|
+
}
|
|
1237
|
+
/** The plan, with what apply-import runs: the entity operations and the flows, in order. */ async buildPlan(dto, user) {
|
|
1238
|
+
const bundle = dto.bundle;
|
|
1239
|
+
const current = await this.loadEntities();
|
|
1240
|
+
const entityDiff = (0,_definition_bundle_diff_js__rspack_import_10/* .diffEntities */.zb)(bundle.entities, current, {
|
|
1241
|
+
deprecateMissingFields: dto.deprecateMissingFields === true
|
|
1242
|
+
});
|
|
1243
|
+
const flowDiff = await this.diffFlows(bundle.flows);
|
|
1244
|
+
const existingCodes = new Set(current.map((e)=>e.code));
|
|
1245
|
+
const steps = [];
|
|
1246
|
+
for (const operation of entityDiff.operations){
|
|
1247
|
+
const dependent = operation.dependsOnEarlierStep || operation.kind !== 'create_entity' && !existingCodes.has(operation.entityCode) || this.relationNotYetCreated(operation, existingCodes);
|
|
1248
|
+
const step = {
|
|
1249
|
+
kind: operation.kind,
|
|
1250
|
+
entityCode: operation.entityCode,
|
|
1251
|
+
...operation.fieldCode ? {
|
|
1252
|
+
fieldCode: operation.fieldCode
|
|
1253
|
+
} : {},
|
|
1254
|
+
details: operation.details,
|
|
1255
|
+
preview: null,
|
|
1256
|
+
warnings: [
|
|
1257
|
+
...operation.warnings ?? [],
|
|
1258
|
+
...dependent ? [
|
|
1259
|
+
(0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.STEP_AFTER_EARLIER */.iX.STEP_AFTER_EARLIER)
|
|
1260
|
+
] : []
|
|
1261
|
+
],
|
|
1262
|
+
blockers: []
|
|
1263
|
+
};
|
|
1264
|
+
if (!dependent) {
|
|
1265
|
+
try {
|
|
1266
|
+
step.preview = await this.previewEntityStep(operation, current, user);
|
|
1267
|
+
step.blockers.push(...step.preview.blockers);
|
|
1268
|
+
} catch (error) {
|
|
1269
|
+
step.blockers.push((0,_flow_engine_flow_errors_js__rspack_import_8/* .errorRef */.O$)(error));
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
steps.push(step);
|
|
1273
|
+
}
|
|
1274
|
+
const schemaChanges = entityDiff.operations.length > 0;
|
|
1275
|
+
const importedSlugs = new Set(flowDiff.planned.map((p)=>p.flow.slug));
|
|
1276
|
+
for (const planned of flowDiff.planned){
|
|
1277
|
+
const step = {
|
|
1278
|
+
kind: planned.kind,
|
|
1279
|
+
flowSlug: planned.flow.slug,
|
|
1280
|
+
details: planned.details,
|
|
1281
|
+
preview: null,
|
|
1282
|
+
warnings: [
|
|
1283
|
+
...planned.warnings
|
|
1284
|
+
],
|
|
1285
|
+
blockers: [
|
|
1286
|
+
...planned.blockers
|
|
1287
|
+
]
|
|
1288
|
+
};
|
|
1289
|
+
// A flow with a code step needs that permission from whoever imports it, as from whoever saves it.
|
|
1290
|
+
await this.flows.assertMayAuthor((0,_flow_definition_service_js__rspack_import_13/* .toFlowSettings */.RK)(planned.flow), user).catch((error)=>step.blockers.push((0,_flow_engine_flow_errors_js__rspack_import_8/* .errorRef */.O$)(error)));
|
|
1291
|
+
const dependsOnImport = schemaChanges || (0,_definition_bundle_diff_js__rspack_import_10/* .calledFlowSlugs */.Q5)(planned.flow.nodes).some((slug)=>importedSlugs.has(slug));
|
|
1292
|
+
if (dependsOnImport) {
|
|
1293
|
+
step.warnings.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.FLOWS_CHECKED_ON_APPLY */.iX.FLOWS_CHECKED_ON_APPLY));
|
|
1294
|
+
} else if (!step.blockers.length) {
|
|
1295
|
+
const { errors, warnings } = await this.flows.validate((0,_flow_definition_service_js__rspack_import_13/* .toFlowSettings */.RK)(planned.flow));
|
|
1296
|
+
step.blockers.push(...errors);
|
|
1297
|
+
step.warnings.push(...warnings);
|
|
1298
|
+
}
|
|
1299
|
+
steps.push(step);
|
|
1300
|
+
}
|
|
1301
|
+
const checksum = (0,_definition_bundle_diff_js__rspack_import_10/* .bundleChecksum */.i9)(bundle);
|
|
1302
|
+
const plan = {
|
|
1303
|
+
checksum,
|
|
1304
|
+
planChecksum: planChecksum(checksum, dto.deprecateMissingFields === true, steps),
|
|
1305
|
+
steps,
|
|
1306
|
+
unchanged: {
|
|
1307
|
+
entities: entityDiff.unchangedEntities,
|
|
1308
|
+
fields: entityDiff.unchangedFields,
|
|
1309
|
+
flows: flowDiff.unchanged
|
|
1310
|
+
},
|
|
1311
|
+
extras: [
|
|
1312
|
+
...entityDiff.extras,
|
|
1313
|
+
...flowDiff.extras
|
|
1314
|
+
],
|
|
1315
|
+
blockers: [
|
|
1316
|
+
...entityDiff.blockers,
|
|
1317
|
+
...flowDiff.blockers
|
|
1318
|
+
],
|
|
1319
|
+
destructive: steps.some((s)=>s.preview?.destructive),
|
|
1320
|
+
mayLoseData: steps.some((s)=>s.preview?.destructive || !s.preview && mayLoseData(s))
|
|
1321
|
+
};
|
|
1322
|
+
return {
|
|
1323
|
+
plan,
|
|
1324
|
+
operations: entityDiff.operations,
|
|
1325
|
+
flows: flowDiff.planned
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
/** A relation to an entity this import creates: its id is only known once the entity exists. */ relationNotYetCreated(operation, existingCodes) {
|
|
1329
|
+
const target = operation.field?.relationTarget ?? operation.changes?.['relationTarget'];
|
|
1330
|
+
return !!target && !existingCodes.has(target);
|
|
1331
|
+
}
|
|
1332
|
+
async previewEntityStep(operation, current, user) {
|
|
1333
|
+
if (operation.kind === 'create_entity') return this.schemaSync.planCreateEntity(this.createRequest(operation.entity), user);
|
|
1334
|
+
return this.evolution.plan(this.changeRequest(operation, current), user);
|
|
1335
|
+
}
|
|
1336
|
+
async diffFlows(bundleFlows) {
|
|
1337
|
+
const repo = await this.provider.getRepository(_entities_flow_definition_entity_js__rspack_import_7/* .FlowDefinition */.G);
|
|
1338
|
+
const existing = await repo.find();
|
|
1339
|
+
const bySlug = new Map(existing.map((flow)=>[
|
|
1340
|
+
flow.slug,
|
|
1341
|
+
flow
|
|
1342
|
+
]));
|
|
1343
|
+
const slugs = bundleFlows.map((f)=>f.slug);
|
|
1344
|
+
const deleted = slugs.length ? new Set((await repo.find({
|
|
1345
|
+
select: {
|
|
1346
|
+
id: true,
|
|
1347
|
+
slug: true
|
|
1348
|
+
},
|
|
1349
|
+
where: {
|
|
1350
|
+
slug: (0,typeorm__rspack_import_3.In)(slugs)
|
|
1351
|
+
},
|
|
1352
|
+
withDeleted: true
|
|
1353
|
+
})).filter((f)=>!bySlug.has(f.slug)).map((f)=>f.slug)) : new Set();
|
|
1354
|
+
const variables = this.variables();
|
|
1355
|
+
const result = {
|
|
1356
|
+
planned: [],
|
|
1357
|
+
unchanged: 0,
|
|
1358
|
+
extras: [],
|
|
1359
|
+
blockers: []
|
|
1360
|
+
};
|
|
1361
|
+
const seen = new Set();
|
|
1362
|
+
for (const slug of slugs){
|
|
1363
|
+
if (seen.has(slug)) result.blockers.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.DUPLICATE_FLOW */.iX.DUPLICATE_FLOW, {
|
|
1364
|
+
flow: slug
|
|
1365
|
+
}));
|
|
1366
|
+
seen.add(slug);
|
|
1367
|
+
}
|
|
1368
|
+
for (const bundleFlow of (0,_definition_bundle_diff_js__rspack_import_10/* .orderFlows */.qG)(bundleFlows)){
|
|
1369
|
+
const { nodes, missing } = (0,_definition_bundle_diff_js__rspack_import_10/* .applyVariables */.gT)(bundleFlow.nodes ?? [], variables);
|
|
1370
|
+
const flow = {
|
|
1371
|
+
...bundleFlow,
|
|
1372
|
+
nodes,
|
|
1373
|
+
edges: bundleFlow.edges ?? []
|
|
1374
|
+
};
|
|
1375
|
+
const blockers = missing.map((name)=>(0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.VARIABLE_MISSING */.iX.VARIABLE_MISSING, {
|
|
1376
|
+
name,
|
|
1377
|
+
flow: flow.slug
|
|
1378
|
+
}));
|
|
1379
|
+
const target = bySlug.get(flow.slug);
|
|
1380
|
+
if (!target && deleted.has(flow.slug)) blockers.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.FLOW_SLUG_DELETED */.iX.FLOW_SLUG_DELETED, {
|
|
1381
|
+
flow: flow.slug
|
|
1382
|
+
}));
|
|
1383
|
+
const keys = storedApiKeys(target);
|
|
1384
|
+
const warnings = flow.nodes.filter((node)=>needsApiKey(node) && !keys.has(node.id)).map((node)=>(0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.FLOW_API_KEY_GENERATED */.iX.FLOW_API_KEY_GENERATED, {
|
|
1385
|
+
flow: flow.slug,
|
|
1386
|
+
path: triggerPath(node) ?? ''
|
|
1387
|
+
}));
|
|
1388
|
+
if (!target) {
|
|
1389
|
+
result.planned.push({
|
|
1390
|
+
kind: 'create_flow',
|
|
1391
|
+
flow,
|
|
1392
|
+
existingId: null,
|
|
1393
|
+
details: {},
|
|
1394
|
+
warnings,
|
|
1395
|
+
blockers
|
|
1396
|
+
});
|
|
1397
|
+
continue;
|
|
1398
|
+
}
|
|
1399
|
+
const live = (0,_flow_definition_service_js__rspack_import_13/* .snapshotOf */.eY)(target);
|
|
1400
|
+
const changed = _interfaces_flow_definition_interface_js__rspack_import_19/* .FLOW_VERSIONED_FIELDS.filter */.v.filter((key)=>key === 'nodes' ? (0,_definition_bundle_diff_js__rspack_import_10/* .canonicalJson */.dj)((0,_definition_bundle_diff_js__rspack_import_10/* .stripApiKeys */.dX)(live.nodes ?? [])) !== (0,_definition_bundle_diff_js__rspack_import_10/* .canonicalJson */.dj)((0,_definition_bundle_diff_js__rspack_import_10/* .stripApiKeys */.dX)(flow.nodes)) : (0,_definition_bundle_diff_js__rspack_import_10/* .canonicalJson */.dj)(live[key] ?? null) !== (0,_definition_bundle_diff_js__rspack_import_10/* .canonicalJson */.dj)(flow[key] ?? null));
|
|
1401
|
+
if (!changed.length && (0,_flow_definition_service_js__rspack_import_13/* .isPublished */.HF)(target) && !blockers.length) {
|
|
1402
|
+
result.unchanged++;
|
|
1403
|
+
continue;
|
|
1404
|
+
}
|
|
1405
|
+
if (target.draft) warnings.push((0,_flusys_nestjs_shared_utils__rspack_import_0.messageRef)(_config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.FLOW_DRAFT_REPLACED */.iX.FLOW_DRAFT_REPLACED, {
|
|
1406
|
+
flow: flow.slug
|
|
1407
|
+
}));
|
|
1408
|
+
result.planned.push({
|
|
1409
|
+
kind: 'update_flow',
|
|
1410
|
+
flow,
|
|
1411
|
+
existingId: target.id,
|
|
1412
|
+
details: {
|
|
1413
|
+
changes: changed
|
|
1414
|
+
},
|
|
1415
|
+
warnings,
|
|
1416
|
+
blockers
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
for (const extra of existing.filter((flow)=>!seen.has(flow.slug)))result.extras.push({
|
|
1420
|
+
kind: 'flow',
|
|
1421
|
+
flowSlug: extra.slug
|
|
1422
|
+
});
|
|
1423
|
+
return result;
|
|
1424
|
+
}
|
|
1425
|
+
// ── requests for the designer's services ────────────────────────────────────────────
|
|
1426
|
+
fieldSpec(field, relationTargetEntityId) {
|
|
1427
|
+
return {
|
|
1428
|
+
code: field.code,
|
|
1429
|
+
label: field.label,
|
|
1430
|
+
fieldType: field.fieldType,
|
|
1431
|
+
nullable: field.nullable,
|
|
1432
|
+
unique: field.unique,
|
|
1433
|
+
isIndexed: field.isIndexed,
|
|
1434
|
+
defaultValue: field.defaultValue ?? undefined,
|
|
1435
|
+
validationRules: field.validationRules ?? undefined,
|
|
1436
|
+
selectOptions: field.selectOptions ?? undefined,
|
|
1437
|
+
order: field.order,
|
|
1438
|
+
uiConfig: field.uiConfig ?? undefined,
|
|
1439
|
+
isSearchable: field.isSearchable,
|
|
1440
|
+
...relationTargetEntityId ? {
|
|
1441
|
+
relationTargetEntityId
|
|
1442
|
+
} : {}
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
createRequest(entity) {
|
|
1446
|
+
return {
|
|
1447
|
+
code: entity.code,
|
|
1448
|
+
label: entity.label,
|
|
1449
|
+
description: entity.description ?? undefined,
|
|
1450
|
+
isSoftDeleteEnabled: entity.isSoftDeleteEnabled,
|
|
1451
|
+
isAuditEnabled: entity.isAuditEnabled,
|
|
1452
|
+
uiConfig: entity.uiConfig ?? undefined,
|
|
1453
|
+
fields: entity.fields.map((field)=>this.fieldSpec(field))
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
/** The schema change for one step, with this environment's ids (looked up now: earlier steps may have created them). */ changeRequest(operation, current) {
|
|
1457
|
+
const entity = current.find((e)=>e.code === operation.entityCode);
|
|
1458
|
+
const idOf = (code)=>code ? current.find((e)=>e.code === code)?.id : undefined;
|
|
1459
|
+
switch(operation.kind){
|
|
1460
|
+
case 'add_field':
|
|
1461
|
+
return {
|
|
1462
|
+
action: _dtos_schema_change_dto_js__rspack_import_4/* .SchemaChangeAction.ADD_FIELD */.M3.ADD_FIELD,
|
|
1463
|
+
entityDefinitionId: entity?.id,
|
|
1464
|
+
field: this.fieldSpec(operation.field, idOf(operation.field.relationTarget))
|
|
1465
|
+
};
|
|
1466
|
+
case 'rename_field':
|
|
1467
|
+
case 'update_field':
|
|
1468
|
+
{
|
|
1469
|
+
const { relationTarget, ...changes } = operation.changes ?? {};
|
|
1470
|
+
if (relationTarget !== undefined) Object.assign(changes, {
|
|
1471
|
+
relationTargetEntityId: idOf(relationTarget) ?? null
|
|
1472
|
+
});
|
|
1473
|
+
return {
|
|
1474
|
+
action: _dtos_schema_change_dto_js__rspack_import_4/* .SchemaChangeAction.UPDATE_FIELD */.M3.UPDATE_FIELD,
|
|
1475
|
+
fieldDefinitionId: operation.targetFieldId,
|
|
1476
|
+
changes
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
case 'deprecate_field':
|
|
1480
|
+
return {
|
|
1481
|
+
action: _dtos_schema_change_dto_js__rspack_import_4/* .SchemaChangeAction.DEPRECATE_FIELD */.M3.DEPRECATE_FIELD,
|
|
1482
|
+
fieldDefinitionId: operation.targetFieldId
|
|
1483
|
+
};
|
|
1484
|
+
case 'restore_field':
|
|
1485
|
+
return {
|
|
1486
|
+
action: _dtos_schema_change_dto_js__rspack_import_4/* .SchemaChangeAction.RESTORE_FIELD */.M3.RESTORE_FIELD,
|
|
1487
|
+
fieldDefinitionId: operation.targetFieldId
|
|
1488
|
+
};
|
|
1489
|
+
default:
|
|
1490
|
+
return {
|
|
1491
|
+
action: _dtos_schema_change_dto_js__rspack_import_4/* .SchemaChangeAction.UPDATE_ENTITY */.M3.UPDATE_ENTITY,
|
|
1492
|
+
entityDefinitionId: entity?.id,
|
|
1493
|
+
changes: operation.changes
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
// ── apply ───────────────────────────────────────────────────────────────────────────
|
|
1498
|
+
async applyImport(dto, user) {
|
|
1499
|
+
const checksum = (0,_definition_bundle_diff_js__rspack_import_10/* .bundleChecksum */.i9)(dto.bundle);
|
|
1500
|
+
if (dto.expectedChecksum && dto.expectedChecksum !== checksum) {
|
|
1501
|
+
throw new _nestjs_common__rspack_import_1.ConflictException({
|
|
1502
|
+
message: 'The bundle is not the one that was reviewed. Plan the import again.',
|
|
1503
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.CHECKSUM_MISMATCH */.iX.CHECKSUM_MISMATCH,
|
|
1504
|
+
messageVariables: {
|
|
1505
|
+
checksum
|
|
1506
|
+
}
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
const { plan, operations, flows } = await this.buildPlan(dto, user);
|
|
1510
|
+
if (dto.expectedPlanChecksum && dto.expectedPlanChecksum !== plan.planChecksum) {
|
|
1511
|
+
throw new _nestjs_common__rspack_import_1.ConflictException({
|
|
1512
|
+
message: 'The plan changed since it was reviewed. Plan the import again.',
|
|
1513
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.PLAN_CHANGED */.iX.PLAN_CHANGED,
|
|
1514
|
+
messageVariables: {
|
|
1515
|
+
planChecksum: plan.planChecksum
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
// `errors` is what the global exception filter passes on, so the caller sees every reason.
|
|
1520
|
+
const blockers = [
|
|
1521
|
+
...plan.blockers.map((b)=>({
|
|
1522
|
+
field: 'bundle',
|
|
1523
|
+
...b
|
|
1524
|
+
})),
|
|
1525
|
+
...plan.steps.flatMap((s)=>s.blockers.map((b)=>({
|
|
1526
|
+
field: (0,_definition_bundle_diff_js__rspack_import_10/* .bundleSubject */.bs)(s),
|
|
1527
|
+
...b
|
|
1528
|
+
})))
|
|
1529
|
+
];
|
|
1530
|
+
if (blockers.length) {
|
|
1531
|
+
throw new _nestjs_common__rspack_import_1.ConflictException({
|
|
1532
|
+
message: 'The import is blocked. Plan it again to see why.',
|
|
1533
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.APPLY_BLOCKED */.iX.APPLY_BLOCKED,
|
|
1534
|
+
errors: blockers
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
if (plan.mayLoseData && dto.confirm !== true) {
|
|
1538
|
+
const lossy = plan.steps.filter((s)=>s.preview?.destructive || !s.preview && mayLoseData(s)).map((s)=>({
|
|
1539
|
+
field: (0,_definition_bundle_diff_js__rspack_import_10/* .bundleSubject */.bs)(s),
|
|
1540
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.CONFIRM_REQUIRED */.iX.CONFIRM_REQUIRED
|
|
1541
|
+
}));
|
|
1542
|
+
throw new _nestjs_common__rspack_import_1.BadRequestException({
|
|
1543
|
+
message: 'The import loses data or information. Review the plan and resend with confirm: true.',
|
|
1544
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.CONFIRM_REQUIRED */.iX.CONFIRM_REQUIRED,
|
|
1545
|
+
errors: lossy
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1548
|
+
// A confirmation covers the steps that were reviewed, never ones the environment has grown since.
|
|
1549
|
+
if (plan.mayLoseData && !dto.expectedPlanChecksum) {
|
|
1550
|
+
throw new _nestjs_common__rspack_import_1.BadRequestException({
|
|
1551
|
+
message: 'Send the planChecksum of the reviewed plan as expectedPlanChecksum to confirm it.',
|
|
1552
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .BUNDLE_MESSAGES.PLAN_CHECKSUM_REQUIRED */.iX.PLAN_CHECKSUM_REQUIRED
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
const result = {
|
|
1556
|
+
checksum: plan.checksum,
|
|
1557
|
+
completed: true,
|
|
1558
|
+
steps: [],
|
|
1559
|
+
apiKeys: [],
|
|
1560
|
+
warnings: plan.steps.flatMap((s)=>s.warnings)
|
|
1561
|
+
};
|
|
1562
|
+
const note = `Imported from bundle ${plan.checksum.slice(0, 12)}`;
|
|
1563
|
+
const run = async (step, fn)=>{
|
|
1564
|
+
if (!result.completed) return result.steps.push({
|
|
1565
|
+
...step,
|
|
1566
|
+
status: 'skipped'
|
|
1567
|
+
});
|
|
1568
|
+
try {
|
|
1569
|
+
await fn();
|
|
1570
|
+
result.steps.push({
|
|
1571
|
+
...step,
|
|
1572
|
+
status: 'applied'
|
|
1573
|
+
});
|
|
1574
|
+
} catch (error) {
|
|
1575
|
+
result.completed = false;
|
|
1576
|
+
const reasons = failureDetails(error);
|
|
1577
|
+
result.steps.push({
|
|
1578
|
+
...step,
|
|
1579
|
+
status: 'failed',
|
|
1580
|
+
error: (0,_flow_engine_flow_errors_js__rspack_import_8/* .errorRef */.O$)(error),
|
|
1581
|
+
...reasons.length ? {
|
|
1582
|
+
blockers: reasons
|
|
1583
|
+
} : {}
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
};
|
|
1587
|
+
// Entity codes and field ids never change during an import: only a created entity adds ids to look up.
|
|
1588
|
+
let current = await this.loadEntities();
|
|
1589
|
+
for (const operation of operations){
|
|
1590
|
+
await run({
|
|
1591
|
+
kind: operation.kind,
|
|
1592
|
+
entityCode: operation.entityCode,
|
|
1593
|
+
...operation.fieldCode ? {
|
|
1594
|
+
fieldCode: operation.fieldCode
|
|
1595
|
+
} : {}
|
|
1596
|
+
}, ()=>this.applyEntityStep(operation, current, dto.confirm === true, user));
|
|
1597
|
+
if (operation.kind === 'create_entity' && result.completed) current = await this.loadEntities();
|
|
1598
|
+
}
|
|
1599
|
+
for (const planned of flows){
|
|
1600
|
+
await run({
|
|
1601
|
+
kind: planned.kind,
|
|
1602
|
+
flowSlug: planned.flow.slug
|
|
1603
|
+
}, ()=>this.applyFlowStep(planned, note, result.apiKeys, user));
|
|
1604
|
+
}
|
|
1605
|
+
return result;
|
|
1606
|
+
}
|
|
1607
|
+
async applyEntityStep(operation, current, confirm, user) {
|
|
1608
|
+
if (operation.kind === 'create_entity') {
|
|
1609
|
+
const entity = operation.entity;
|
|
1610
|
+
await this.schemaSync.createEntity(this.createRequest(entity), user, {
|
|
1611
|
+
entityId: await this.idIsFree(_entities_entity_definition_entity_js__rspack_import_5/* .EntityDefinition */.f, entity.id) ? entity.id : undefined,
|
|
1612
|
+
fieldIds: Object.fromEntries(await this.freeFieldIds(entity.fields))
|
|
1613
|
+
});
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
const request = {
|
|
1617
|
+
...this.changeRequest(operation, current),
|
|
1618
|
+
confirm
|
|
1619
|
+
};
|
|
1620
|
+
const fieldId = operation.kind === 'add_field' && await this.idIsFree(_entities_field_definition_entity_js__rspack_import_6/* .FieldDefinition */.c, operation.field.id) ? operation.field.id : undefined;
|
|
1621
|
+
await this.evolution.apply(request, user, {
|
|
1622
|
+
fieldId
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
async idIsFree(entity, id) {
|
|
1626
|
+
return !await (await this.provider.getRepository(entity)).exists({
|
|
1627
|
+
where: {
|
|
1628
|
+
id
|
|
1629
|
+
},
|
|
1630
|
+
withDeleted: true
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
async freeFieldIds(fields) {
|
|
1634
|
+
if (!fields.length) return [];
|
|
1635
|
+
const taken = new Set((await (await this.provider.getRepository(_entities_field_definition_entity_js__rspack_import_6/* .FieldDefinition */.c)).find({
|
|
1636
|
+
select: {
|
|
1637
|
+
id: true
|
|
1638
|
+
},
|
|
1639
|
+
where: {
|
|
1640
|
+
id: (0,typeorm__rspack_import_3.In)(fields.map((f)=>f.id))
|
|
1641
|
+
},
|
|
1642
|
+
withDeleted: true
|
|
1643
|
+
})).map((f)=>f.id));
|
|
1644
|
+
return fields.filter((f)=>!taken.has(f.id)).map((f)=>[
|
|
1645
|
+
f.code,
|
|
1646
|
+
f.id
|
|
1647
|
+
]);
|
|
1648
|
+
}
|
|
1649
|
+
/** Saves the flow (a Request step keeps this environment's API key, or gets a new one shown once) and publishes it. */ async applyFlowStep(planned, note, apiKeys, user) {
|
|
1650
|
+
const existing = planned.existingId ? await this.flows.findOrFail(planned.existingId) : undefined;
|
|
1651
|
+
const keys = storedApiKeys(existing);
|
|
1652
|
+
const generated = [];
|
|
1653
|
+
const nodes = planned.flow.nodes.map((node)=>{
|
|
1654
|
+
if (!needsApiKey(node)) return node;
|
|
1655
|
+
const stored = keys.get(node.id);
|
|
1656
|
+
if (stored) return {
|
|
1657
|
+
...node,
|
|
1658
|
+
config: {
|
|
1659
|
+
...node.config,
|
|
1660
|
+
apiKey: stored
|
|
1661
|
+
}
|
|
1662
|
+
};
|
|
1663
|
+
const key = newApiKey();
|
|
1664
|
+
generated.push({
|
|
1665
|
+
flowSlug: planned.flow.slug,
|
|
1666
|
+
nodeId: node.id,
|
|
1667
|
+
path: triggerPath(node),
|
|
1668
|
+
key
|
|
1669
|
+
});
|
|
1670
|
+
return {
|
|
1671
|
+
...node,
|
|
1672
|
+
config: {
|
|
1673
|
+
...node.config,
|
|
1674
|
+
apiKey: key
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
});
|
|
1678
|
+
const values = {
|
|
1679
|
+
...planned.flow,
|
|
1680
|
+
description: planned.flow.description ?? undefined,
|
|
1681
|
+
nodes
|
|
1682
|
+
};
|
|
1683
|
+
const id = existing ? (await this.flows.update({
|
|
1684
|
+
...values,
|
|
1685
|
+
id: existing.id
|
|
1686
|
+
}, user), existing.id) : (await this.flows.insert(values, user)).id;
|
|
1687
|
+
// Saved: these keys are stored now, so they are answered even if publishing fails (the next import reuses them).
|
|
1688
|
+
apiKeys.push(...generated);
|
|
1689
|
+
await this.flows.publish(id, note, user);
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
DefinitionBundleService = _ts_decorate([
|
|
1693
|
+
(0,_nestjs_common__rspack_import_1.Injectable)({
|
|
1694
|
+
scope: _nestjs_common__rspack_import_1.Scope.REQUEST
|
|
1695
|
+
}),
|
|
1696
|
+
_ts_param(0, (0,_nestjs_common__rspack_import_1.Inject)(_entity_builder_datasource_provider_js__rspack_import_12/* .EntityBuilderDataSourceProvider */.D)),
|
|
1697
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_1.Inject)(_entity_builder_config_service_js__rspack_import_11/* .EntityBuilderConfigService */.E)),
|
|
1698
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_1.Inject)(_schema_sync_service_js__rspack_import_15/* .SchemaSyncService */.W)),
|
|
1699
|
+
_ts_param(3, (0,_nestjs_common__rspack_import_1.Inject)(_schema_evolution_service_js__rspack_import_14/* .SchemaEvolutionService */._)),
|
|
1700
|
+
_ts_param(4, (0,_nestjs_common__rspack_import_1.Inject)(_flow_definition_service_js__rspack_import_13/* .FlowDefinitionService */.Tk)),
|
|
1701
|
+
_ts_metadata("design:type", Function),
|
|
1702
|
+
_ts_metadata("design:paramtypes", [
|
|
1703
|
+
typeof _entity_builder_datasource_provider_js__rspack_import_12/* .EntityBuilderDataSourceProvider */.D === "undefined" ? Object : _entity_builder_datasource_provider_js__rspack_import_12/* .EntityBuilderDataSourceProvider */.D,
|
|
1704
|
+
typeof _entity_builder_config_service_js__rspack_import_11/* .EntityBuilderConfigService */.E === "undefined" ? Object : _entity_builder_config_service_js__rspack_import_11/* .EntityBuilderConfigService */.E,
|
|
1705
|
+
typeof _schema_sync_service_js__rspack_import_15/* .SchemaSyncService */.W === "undefined" ? Object : _schema_sync_service_js__rspack_import_15/* .SchemaSyncService */.W,
|
|
1706
|
+
typeof _schema_evolution_service_js__rspack_import_14/* .SchemaEvolutionService */._ === "undefined" ? Object : _schema_evolution_service_js__rspack_import_14/* .SchemaEvolutionService */._,
|
|
1707
|
+
typeof _flow_definition_service_js__rspack_import_13/* .FlowDefinitionService */.Tk === "undefined" ? Object : _flow_definition_service_js__rspack_import_13/* .FlowDefinitionService */.Tk
|
|
1708
|
+
])
|
|
1709
|
+
], DefinitionBundleService);
|
|
1710
|
+
|
|
1711
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1712
|
+
P: () => (DefinitionBundleService)
|
|
10
1713
|
});
|
|
11
1714
|
|
|
12
1715
|
|
|
@@ -147,13 +1850,17 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
147
1850
|
|
|
148
1851
|
},
|
|
149
1852
|
8271(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
150
|
-
/* import */ var
|
|
151
|
-
/* import */ var
|
|
152
|
-
/* import */ var
|
|
1853
|
+
/* import */ var _flusys_nestjs_shared_constants__rspack_import_0 = __webpack_require__(9140);
|
|
1854
|
+
/* import */ var _config_message_keys_js__rspack_import_4 = __webpack_require__(5732);
|
|
1855
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_2 = __webpack_require__(9614);
|
|
1856
|
+
/* import */ var _flow_engine_flow_permission_logic_js__rspack_import_3 = __webpack_require__(8220);
|
|
1857
|
+
/* import */ var _flow_engine_flow_types_js__rspack_import_1 = __webpack_require__(6256);
|
|
1858
|
+
|
|
153
1859
|
|
|
154
1860
|
|
|
155
1861
|
|
|
156
|
-
|
|
1862
|
+
|
|
1863
|
+
/** The path of each endpoint's Request step: `api-flows/<entity>/<path>`. */ const ENTITY_FLOW_PATHS = {
|
|
157
1864
|
insert: 'insert',
|
|
158
1865
|
insertMany: 'insert-many',
|
|
159
1866
|
getById: 'get-by-id',
|
|
@@ -165,7 +1872,7 @@ const SLUG_SUFFIX = {
|
|
|
165
1872
|
bulkUpsert: 'bulk-upsert',
|
|
166
1873
|
delete: 'delete'
|
|
167
1874
|
};
|
|
168
|
-
const
|
|
1875
|
+
const DEFAULT_ENDPOINT_NAME = {
|
|
169
1876
|
insert: 'Insert',
|
|
170
1877
|
insertMany: 'Insert many',
|
|
171
1878
|
getById: 'Get by id',
|
|
@@ -183,26 +1890,71 @@ const DEFAULT_INPUT_LABEL = {
|
|
|
183
1890
|
search: 'Search'
|
|
184
1891
|
};
|
|
185
1892
|
const DEFAULT_NO_MATCH_MESSAGE = 'No record matches the filter.';
|
|
186
|
-
const
|
|
1893
|
+
const MAX_NAME_LENGTH = 255;
|
|
187
1894
|
/** A supplied text when it has content, the English default otherwise. */ const textOr = (value, fallback)=>value?.trim() || fallback;
|
|
188
1895
|
const INPUT_TYPE = {
|
|
189
|
-
[
|
|
190
|
-
[
|
|
191
|
-
[
|
|
192
|
-
[
|
|
193
|
-
[
|
|
194
|
-
[
|
|
195
|
-
[
|
|
196
|
-
[
|
|
197
|
-
[
|
|
198
|
-
[
|
|
199
|
-
[
|
|
200
|
-
[
|
|
201
|
-
[
|
|
1896
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.TEXT */.P.TEXT]: 'string',
|
|
1897
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.LONG_TEXT */.P.LONG_TEXT]: 'text',
|
|
1898
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.INTEGER */.P.INTEGER]: 'integer',
|
|
1899
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.DECIMAL */.P.DECIMAL]: 'number',
|
|
1900
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.BOOLEAN */.P.BOOLEAN]: 'boolean',
|
|
1901
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.DATE */.P.DATE]: 'date',
|
|
1902
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.DATETIME */.P.DATETIME]: 'datetime',
|
|
1903
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.EMAIL */.P.EMAIL]: 'email',
|
|
1904
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.SINGLE_SELECT */.P.SINGLE_SELECT]: 'choice',
|
|
1905
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT]: 'array',
|
|
1906
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.RELATION */.P.RELATION]: 'uuid',
|
|
1907
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.JSON */.P.JSON]: 'object',
|
|
1908
|
+
[_enums_field_type_enum_js__rspack_import_2/* .FieldType.FILE */.P.FILE]: 'uuid'
|
|
202
1909
|
};
|
|
203
|
-
const MAX_SLUG_LENGTH = 63;
|
|
204
1910
|
const LIST_LIMIT = 50;
|
|
205
|
-
|
|
1911
|
+
const READ_ENDPOINTS = new Set([
|
|
1912
|
+
'getById',
|
|
1913
|
+
'getByIds',
|
|
1914
|
+
'getAll',
|
|
1915
|
+
'getByFilter'
|
|
1916
|
+
]);
|
|
1917
|
+
/** The entity permissions each endpoint asks for - the ones created with the entity; an upsert may create and update. */ const ENDPOINT_ACTIONS = {
|
|
1918
|
+
insert: [
|
|
1919
|
+
'create'
|
|
1920
|
+
],
|
|
1921
|
+
insertMany: [
|
|
1922
|
+
'create'
|
|
1923
|
+
],
|
|
1924
|
+
getById: [
|
|
1925
|
+
'read'
|
|
1926
|
+
],
|
|
1927
|
+
getByIds: [
|
|
1928
|
+
'read'
|
|
1929
|
+
],
|
|
1930
|
+
getAll: [
|
|
1931
|
+
'read'
|
|
1932
|
+
],
|
|
1933
|
+
getByFilter: [
|
|
1934
|
+
'read'
|
|
1935
|
+
],
|
|
1936
|
+
update: [
|
|
1937
|
+
'update'
|
|
1938
|
+
],
|
|
1939
|
+
updateMany: [
|
|
1940
|
+
'update'
|
|
1941
|
+
],
|
|
1942
|
+
bulkUpsert: [
|
|
1943
|
+
'create',
|
|
1944
|
+
'update'
|
|
1945
|
+
],
|
|
1946
|
+
delete: [
|
|
1947
|
+
'delete'
|
|
1948
|
+
]
|
|
1949
|
+
};
|
|
1950
|
+
function endpointPermissions(entityCode, endpoint) {
|
|
1951
|
+
const actions = ENDPOINT_ACTIONS[endpoint].map((action)=>(0,_flow_engine_flow_permission_logic_js__rspack_import_3/* .permissionAction */.s)((0,_flusys_nestjs_shared_constants__rspack_import_0.dynamicEntityPermission)(entityCode, action)));
|
|
1952
|
+
return actions.length === 1 ? actions[0] : {
|
|
1953
|
+
type: 'group',
|
|
1954
|
+
operator: 'AND',
|
|
1955
|
+
children: actions
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
206
1958
|
const COLUMN = {
|
|
207
1959
|
x: 40,
|
|
208
1960
|
gap: 300
|
|
@@ -219,24 +1971,60 @@ const lit = (value)=>({
|
|
|
219
1971
|
type: 'literal',
|
|
220
1972
|
value
|
|
221
1973
|
});
|
|
222
|
-
/** `customer_ticket`
|
|
223
|
-
const suffix = SLUG_SUFFIX[endpoint];
|
|
224
|
-
const base = entityCode.replace(/_/g, '-').slice(0, MAX_SLUG_LENGTH - suffix.length - 1).replace(/-+$/, '');
|
|
225
|
-
return `${base}-${suffix}`;
|
|
226
|
-
}
|
|
1974
|
+
/** `customer_ticket` -> `customer-ticket`: an entity code always fits a flow URL name. */ const entityFlowSlug = (entityCode)=>entityCode.replace(/_/g, '-');
|
|
227
1975
|
function optionValues(options) {
|
|
228
1976
|
return (options ?? []).map((o)=>o && typeof o === 'object' && 'value' in o ? String(o.value) : String(o));
|
|
229
1977
|
}
|
|
230
|
-
|
|
1978
|
+
const NUMERIC_TYPES = new Set([
|
|
1979
|
+
_enums_field_type_enum_js__rspack_import_2/* .FieldType.INTEGER */.P.INTEGER,
|
|
1980
|
+
_enums_field_type_enum_js__rspack_import_2/* .FieldType.DECIMAL */.P.DECIMAL
|
|
1981
|
+
]);
|
|
1982
|
+
const TEXT_TYPES = new Set([
|
|
1983
|
+
_enums_field_type_enum_js__rspack_import_2/* .FieldType.TEXT */.P.TEXT,
|
|
1984
|
+
_enums_field_type_enum_js__rspack_import_2/* .FieldType.LONG_TEXT */.P.LONG_TEXT,
|
|
1985
|
+
_enums_field_type_enum_js__rspack_import_2/* .FieldType.EMAIL */.P.EMAIL
|
|
1986
|
+
]);
|
|
1987
|
+
/** The field's rules a Request body checks the same way the record write does. */ function inputRules(field) {
|
|
1988
|
+
const rules = field.validationRules ?? {};
|
|
1989
|
+
const keys = NUMERIC_TYPES.has(field.fieldType) ? [
|
|
1990
|
+
'min',
|
|
1991
|
+
'max'
|
|
1992
|
+
] : TEXT_TYPES.has(field.fieldType) ? [
|
|
1993
|
+
'minLength',
|
|
1994
|
+
'maxLength'
|
|
1995
|
+
] : [];
|
|
1996
|
+
return Object.fromEntries(keys.filter((key)=>typeof rules[key] === 'number' && Number.isFinite(rules[key])).map((key)=>[
|
|
1997
|
+
key,
|
|
1998
|
+
rules[key]
|
|
1999
|
+
]));
|
|
2000
|
+
}
|
|
2001
|
+
/**
|
|
2002
|
+
* The Request body input of a field: a choice carries its options, a multi-select is a list of
|
|
2003
|
+
* those choices, a relation or file is an id. `rules`: a write also checks the field's own value rules.
|
|
2004
|
+
*/ function fieldInput(field, required, rules = true) {
|
|
231
2005
|
const options = optionValues(field.selectOptions);
|
|
232
|
-
const
|
|
233
|
-
return {
|
|
2006
|
+
const base = {
|
|
234
2007
|
name: field.code,
|
|
235
2008
|
label: field.label || field.code,
|
|
236
|
-
type,
|
|
237
2009
|
...required ? {
|
|
238
2010
|
required: true
|
|
239
2011
|
} : {},
|
|
2012
|
+
...rules ? inputRules(field) : {}
|
|
2013
|
+
};
|
|
2014
|
+
if (field.fieldType === _enums_field_type_enum_js__rspack_import_2/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT) return {
|
|
2015
|
+
...base,
|
|
2016
|
+
type: 'array',
|
|
2017
|
+
...options.length ? {
|
|
2018
|
+
itemType: 'choice',
|
|
2019
|
+
options
|
|
2020
|
+
} : {
|
|
2021
|
+
itemType: 'string'
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
const type = INPUT_TYPE[field.fieldType] === 'choice' && !options.length ? 'string' : INPUT_TYPE[field.fieldType];
|
|
2025
|
+
return {
|
|
2026
|
+
...base,
|
|
2027
|
+
type,
|
|
240
2028
|
...type === 'choice' ? {
|
|
241
2029
|
options
|
|
242
2030
|
} : {}
|
|
@@ -248,7 +2036,8 @@ const fieldMap = (fields, scope)=>Object.fromEntries(fields.map((f)=>[
|
|
|
248
2036
|
ref(`${scope}.${f.code}`)
|
|
249
2037
|
]));
|
|
250
2038
|
const optionalFieldInputs = (fields)=>fields.map((f)=>fieldInput(f, false));
|
|
251
|
-
/**
|
|
2039
|
+
/** 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));
|
|
2040
|
+
/** 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_2/* .FieldType.MULTI_SELECT */.P.MULTI_SELECT && f.fieldType !== _enums_field_type_enum_js__rspack_import_2/* .FieldType.JSON */.P.JSON);
|
|
252
2041
|
const idInput = (t)=>({
|
|
253
2042
|
name: 'id',
|
|
254
2043
|
label: t.inputLabels.id,
|
|
@@ -275,56 +2064,53 @@ const respond = (id, column, statusCode, body, row)=>({
|
|
|
275
2064
|
body
|
|
276
2065
|
}
|
|
277
2066
|
});
|
|
278
|
-
/**
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
type: 'foreach',
|
|
286
|
-
column: 1,
|
|
287
|
-
config: {
|
|
288
|
-
items: ref('input'),
|
|
289
|
-
maxItems: BULK_MAX_ITEMS,
|
|
290
|
-
collect
|
|
291
|
-
}
|
|
292
|
-
},
|
|
293
|
-
...body,
|
|
294
|
-
respond('respond', 2, statusCode, ref('context.each.results'))
|
|
295
|
-
],
|
|
296
|
-
edges: [
|
|
297
|
-
[
|
|
298
|
-
'each',
|
|
299
|
-
'each',
|
|
300
|
-
body[0].id
|
|
301
|
-
],
|
|
302
|
-
...bodyEdges,
|
|
303
|
-
[
|
|
304
|
-
'each',
|
|
305
|
-
'done',
|
|
306
|
-
'respond'
|
|
307
|
-
]
|
|
308
|
-
],
|
|
309
|
-
isTransactional: true
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
function endpointGraph(entity, endpoint, texts) {
|
|
2067
|
+
/**
|
|
2068
|
+
* The steps of one endpoint. Its step ids are `<endpoint>_<step>` (`id()`), so the endpoints of one
|
|
2069
|
+
* flow never share a step. A bulk body is the list itself (`itemSchema` checks each item), written by
|
|
2070
|
+
* one step that walks it (`target: many`, each item read as `loop.item`), all or nothing, and
|
|
2071
|
+
* answered with the saved records in order.
|
|
2072
|
+
*/ function endpointGraph(entity, endpoint, texts) {
|
|
2073
|
+
const id = (step)=>`${endpoint}_${step}`;
|
|
313
2074
|
const entityCode = entity.code;
|
|
314
2075
|
const single = (inputSchema, step, statusCode = 200)=>({
|
|
315
2076
|
inputSchema,
|
|
316
2077
|
steps: [
|
|
317
2078
|
{
|
|
318
2079
|
...step,
|
|
2080
|
+
id: id('record'),
|
|
319
2081
|
column: 1
|
|
320
2082
|
},
|
|
321
|
-
respond('respond', 2, statusCode, ref(`context.${
|
|
2083
|
+
respond(id('respond'), 2, statusCode, ref(`context.${id('record')}`))
|
|
2084
|
+
],
|
|
2085
|
+
edges: [
|
|
2086
|
+
[
|
|
2087
|
+
id('record'),
|
|
2088
|
+
'out',
|
|
2089
|
+
id('respond')
|
|
2090
|
+
]
|
|
2091
|
+
]
|
|
2092
|
+
});
|
|
2093
|
+
const bulk = (itemSchema, step, statusCode)=>({
|
|
2094
|
+
bodyType: 'list',
|
|
2095
|
+
inputSchema: itemSchema,
|
|
2096
|
+
steps: [
|
|
2097
|
+
{
|
|
2098
|
+
...step,
|
|
2099
|
+
id: id('records'),
|
|
2100
|
+
column: 1,
|
|
2101
|
+
config: {
|
|
2102
|
+
...step.config,
|
|
2103
|
+
target: 'many',
|
|
2104
|
+
items: ref('input')
|
|
2105
|
+
}
|
|
2106
|
+
},
|
|
2107
|
+
respond(id('respond'), 2, statusCode, ref(`context.${id('records')}.items`))
|
|
322
2108
|
],
|
|
323
2109
|
edges: [
|
|
324
2110
|
[
|
|
325
|
-
|
|
2111
|
+
id('records'),
|
|
326
2112
|
'out',
|
|
327
|
-
'respond'
|
|
2113
|
+
id('respond')
|
|
328
2114
|
]
|
|
329
2115
|
]
|
|
330
2116
|
});
|
|
@@ -333,7 +2119,6 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
333
2119
|
switch(endpoint){
|
|
334
2120
|
case 'insert':
|
|
335
2121
|
return single(insertInputs, {
|
|
336
|
-
id: 'record',
|
|
337
2122
|
type: 'entity_insert',
|
|
338
2123
|
config: {
|
|
339
2124
|
entityCode,
|
|
@@ -341,23 +2126,17 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
341
2126
|
}
|
|
342
2127
|
}, 201);
|
|
343
2128
|
case 'insertMany':
|
|
344
|
-
return
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
row: 1,
|
|
350
|
-
config: {
|
|
351
|
-
entityCode,
|
|
352
|
-
fields: fieldMap(entity.fields, 'loop.item')
|
|
353
|
-
}
|
|
2129
|
+
return bulk(insertInputs, {
|
|
2130
|
+
type: 'entity_insert',
|
|
2131
|
+
config: {
|
|
2132
|
+
entityCode,
|
|
2133
|
+
fields: fieldMap(entity.fields, 'loop.item')
|
|
354
2134
|
}
|
|
355
|
-
|
|
2135
|
+
}, 201);
|
|
356
2136
|
case 'getById':
|
|
357
2137
|
return single([
|
|
358
2138
|
idInput(texts)
|
|
359
2139
|
], {
|
|
360
|
-
id: 'record',
|
|
361
2140
|
type: 'entity_get',
|
|
362
2141
|
config: {
|
|
363
2142
|
entityCode,
|
|
@@ -368,7 +2147,6 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
368
2147
|
return single([
|
|
369
2148
|
idsInput(texts)
|
|
370
2149
|
], {
|
|
371
|
-
id: 'records',
|
|
372
2150
|
type: 'entity_query',
|
|
373
2151
|
config: {
|
|
374
2152
|
entityCode,
|
|
@@ -378,7 +2156,7 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
378
2156
|
value: ref('input.ids')
|
|
379
2157
|
}
|
|
380
2158
|
},
|
|
381
|
-
limit:
|
|
2159
|
+
limit: _flow_engine_flow_types_js__rspack_import_1/* .FLOW_LIMITS.MAX_QUERY_LIMIT */.Or.MAX_QUERY_LIMIT
|
|
382
2160
|
}
|
|
383
2161
|
});
|
|
384
2162
|
case 'getAll':
|
|
@@ -388,9 +2166,8 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
388
2166
|
label: texts.inputLabels.search,
|
|
389
2167
|
type: 'string'
|
|
390
2168
|
},
|
|
391
|
-
...
|
|
2169
|
+
...filterInputs(filterFields)
|
|
392
2170
|
], {
|
|
393
|
-
id: 'records',
|
|
394
2171
|
type: 'entity_query',
|
|
395
2172
|
config: {
|
|
396
2173
|
entityCode,
|
|
@@ -406,11 +2183,11 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
406
2183
|
...idInput(texts),
|
|
407
2184
|
required: false
|
|
408
2185
|
},
|
|
409
|
-
...
|
|
2186
|
+
...filterInputs(filterFields)
|
|
410
2187
|
],
|
|
411
2188
|
steps: [
|
|
412
2189
|
{
|
|
413
|
-
id: 'records',
|
|
2190
|
+
id: id('records'),
|
|
414
2191
|
type: 'entity_query',
|
|
415
2192
|
column: 1,
|
|
416
2193
|
config: {
|
|
@@ -423,7 +2200,7 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
423
2200
|
}
|
|
424
2201
|
},
|
|
425
2202
|
{
|
|
426
|
-
id: 'found',
|
|
2203
|
+
id: id('found'),
|
|
427
2204
|
type: 'condition',
|
|
428
2205
|
column: 2,
|
|
429
2206
|
config: {
|
|
@@ -431,35 +2208,35 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
431
2208
|
operator: 'AND',
|
|
432
2209
|
conditions: [
|
|
433
2210
|
{
|
|
434
|
-
field: '
|
|
2211
|
+
field: `context.${id('records')}.items`,
|
|
435
2212
|
comparison: 'is_not_empty'
|
|
436
2213
|
}
|
|
437
2214
|
]
|
|
438
2215
|
}
|
|
439
2216
|
}
|
|
440
2217
|
},
|
|
441
|
-
respond('respond', 3, 200, ref('
|
|
442
|
-
respond('not_found', 3, 404, {
|
|
2218
|
+
respond(id('respond'), 3, 200, ref(`context.${id('records')}.items.0`)),
|
|
2219
|
+
respond(id('not_found'), 3, 404, {
|
|
443
2220
|
success: lit(false),
|
|
444
2221
|
message: lit(texts.noMatchMessage),
|
|
445
|
-
messageKey: lit(
|
|
2222
|
+
messageKey: lit(_config_message_keys_js__rspack_import_4/* .GENERIC_RECORD_MESSAGES.NO_MATCH */.j4.NO_MATCH)
|
|
446
2223
|
}, 1)
|
|
447
2224
|
],
|
|
448
2225
|
edges: [
|
|
449
2226
|
[
|
|
450
|
-
'records',
|
|
2227
|
+
id('records'),
|
|
451
2228
|
'out',
|
|
452
|
-
'found'
|
|
2229
|
+
id('found')
|
|
453
2230
|
],
|
|
454
2231
|
[
|
|
455
|
-
'found',
|
|
2232
|
+
id('found'),
|
|
456
2233
|
'true',
|
|
457
|
-
'respond'
|
|
2234
|
+
id('respond')
|
|
458
2235
|
],
|
|
459
2236
|
[
|
|
460
|
-
'found',
|
|
2237
|
+
id('found'),
|
|
461
2238
|
'false',
|
|
462
|
-
'not_found'
|
|
2239
|
+
id('not_found')
|
|
463
2240
|
]
|
|
464
2241
|
]
|
|
465
2242
|
};
|
|
@@ -468,7 +2245,6 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
468
2245
|
idInput(texts),
|
|
469
2246
|
...optionalFieldInputs(entity.fields)
|
|
470
2247
|
], {
|
|
471
|
-
id: 'record',
|
|
472
2248
|
type: 'entity_update',
|
|
473
2249
|
config: {
|
|
474
2250
|
entityCode,
|
|
@@ -477,117 +2253,35 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
477
2253
|
}
|
|
478
2254
|
});
|
|
479
2255
|
case 'updateMany':
|
|
480
|
-
return
|
|
2256
|
+
return bulk([
|
|
481
2257
|
idInput(texts),
|
|
482
2258
|
...optionalFieldInputs(entity.fields)
|
|
483
|
-
],
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
row: 1,
|
|
489
|
-
config: {
|
|
490
|
-
entityCode,
|
|
491
|
-
id: ref('loop.item.id'),
|
|
492
|
-
fields: fieldMap(entity.fields, 'loop.item')
|
|
493
|
-
}
|
|
2259
|
+
], {
|
|
2260
|
+
type: 'entity_update',
|
|
2261
|
+
config: {
|
|
2262
|
+
entityCode,
|
|
2263
|
+
fields: fieldMap(entity.fields, 'loop.item')
|
|
494
2264
|
}
|
|
495
|
-
|
|
2265
|
+
}, 200);
|
|
496
2266
|
case 'bulkUpsert':
|
|
497
|
-
return
|
|
2267
|
+
return bulk([
|
|
498
2268
|
{
|
|
499
2269
|
...idInput(texts),
|
|
500
2270
|
required: false
|
|
501
2271
|
},
|
|
502
2272
|
...optionalFieldInputs(entity.fields)
|
|
503
|
-
],
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
config: {
|
|
510
|
-
rule: {
|
|
511
|
-
operator: 'AND',
|
|
512
|
-
conditions: [
|
|
513
|
-
{
|
|
514
|
-
field: 'loop.item.id',
|
|
515
|
-
comparison: 'is_not_empty'
|
|
516
|
-
}
|
|
517
|
-
]
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
},
|
|
521
|
-
{
|
|
522
|
-
id: 'updated',
|
|
523
|
-
type: 'entity_update',
|
|
524
|
-
column: 2,
|
|
525
|
-
row: 1,
|
|
526
|
-
config: {
|
|
527
|
-
entityCode,
|
|
528
|
-
id: ref('loop.item.id'),
|
|
529
|
-
fields: fieldMap(entity.fields, 'loop.item')
|
|
530
|
-
}
|
|
531
|
-
},
|
|
532
|
-
{
|
|
533
|
-
id: 'inserted',
|
|
534
|
-
type: 'entity_insert',
|
|
535
|
-
column: 2,
|
|
536
|
-
row: 2,
|
|
537
|
-
config: {
|
|
538
|
-
entityCode,
|
|
539
|
-
fields: fieldMap(entity.fields, 'loop.item')
|
|
540
|
-
}
|
|
541
|
-
},
|
|
542
|
-
{
|
|
543
|
-
id: 'keep_updated',
|
|
544
|
-
type: 'set',
|
|
545
|
-
column: 3,
|
|
546
|
-
row: 1,
|
|
547
|
-
config: {
|
|
548
|
-
values: {
|
|
549
|
-
saved: ref('context.updated')
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
},
|
|
553
|
-
{
|
|
554
|
-
id: 'keep_inserted',
|
|
555
|
-
type: 'set',
|
|
556
|
-
column: 3,
|
|
557
|
-
row: 2,
|
|
558
|
-
config: {
|
|
559
|
-
values: {
|
|
560
|
-
saved: ref('context.inserted')
|
|
561
|
-
}
|
|
562
|
-
}
|
|
2273
|
+
], {
|
|
2274
|
+
type: 'entity_update',
|
|
2275
|
+
config: {
|
|
2276
|
+
entityCode,
|
|
2277
|
+
fields: fieldMap(entity.fields, 'loop.item'),
|
|
2278
|
+
onNotFound: 'insert'
|
|
563
2279
|
}
|
|
564
|
-
|
|
565
|
-
[
|
|
566
|
-
'has_id',
|
|
567
|
-
'true',
|
|
568
|
-
'updated'
|
|
569
|
-
],
|
|
570
|
-
[
|
|
571
|
-
'has_id',
|
|
572
|
-
'false',
|
|
573
|
-
'inserted'
|
|
574
|
-
],
|
|
575
|
-
[
|
|
576
|
-
'updated',
|
|
577
|
-
'out',
|
|
578
|
-
'keep_updated'
|
|
579
|
-
],
|
|
580
|
-
[
|
|
581
|
-
'inserted',
|
|
582
|
-
'out',
|
|
583
|
-
'keep_inserted'
|
|
584
|
-
]
|
|
585
|
-
], ref('vars.saved'), 200);
|
|
2280
|
+
}, 200);
|
|
586
2281
|
case 'delete':
|
|
587
2282
|
return single([
|
|
588
2283
|
idInput(texts)
|
|
589
2284
|
], {
|
|
590
|
-
id: 'record',
|
|
591
2285
|
type: 'entity_delete',
|
|
592
2286
|
config: {
|
|
593
2287
|
entityCode,
|
|
@@ -597,11 +2291,15 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
597
2291
|
}
|
|
598
2292
|
}
|
|
599
2293
|
/**
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
|
|
2294
|
+
* The ready-made flow of an entity: `api-flows/<entity>` with one Request step per endpoint of the
|
|
2295
|
+
* generic API controller, each on its own path (`ENTITY_FLOW_PATHS`) with its own body, laid out
|
|
2296
|
+
* one below the other. Each asks its caller for the entity's own permission (`entity_builder.entity.<code>.<action>`,
|
|
2297
|
+
* created with the entity), since a flow's access is its only gate, and it is an ordinary flow
|
|
2298
|
+
* afterwards - the user can change or delete it like any other. A
|
|
2299
|
+
* write endpoint is transactional: a bulk endpoint writes its whole list in one step, so a failing
|
|
2300
|
+
* item rolls back the whole request; a read endpoint opens none. A bulk body holds at most
|
|
2301
|
+
* FLOW_LIMITS.MAX_WRITE_ITEMS items.
|
|
2302
|
+
*/ function buildEntityFlow(entity, endpoints, texts = {}) {
|
|
605
2303
|
const resolved = {
|
|
606
2304
|
inputLabels: {
|
|
607
2305
|
id: textOr(texts.inputLabels?.id, DEFAULT_INPUT_LABEL.id),
|
|
@@ -610,57 +2308,65 @@ function endpointGraph(entity, endpoint, texts) {
|
|
|
610
2308
|
},
|
|
611
2309
|
noMatchMessage: textOr(texts.noMatchMessage, DEFAULT_NO_MATCH_MESSAGE)
|
|
612
2310
|
};
|
|
613
|
-
const
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
2311
|
+
const nodes = [];
|
|
2312
|
+
const edges = [];
|
|
2313
|
+
let band = 0;
|
|
2314
|
+
for (const endpoint of endpoints){
|
|
2315
|
+
const graph = endpointGraph(entity, endpoint, resolved);
|
|
2316
|
+
const at = (column, row = 0)=>({
|
|
2317
|
+
x: COLUMN.x + column * COLUMN.gap,
|
|
2318
|
+
y: ROW.y + (band + row) * ROW.gap
|
|
2319
|
+
});
|
|
2320
|
+
const config = {
|
|
2321
|
+
path: ENTITY_FLOW_PATHS[endpoint],
|
|
2322
|
+
bodyType: graph.bodyType ?? 'object',
|
|
2323
|
+
inputSchema: graph.inputSchema,
|
|
2324
|
+
authMode: 'permission',
|
|
2325
|
+
permissions: endpointPermissions(entity.code, endpoint),
|
|
2326
|
+
...READ_ENDPOINTS.has(endpoint) ? {} : {
|
|
2327
|
+
isTransactional: true
|
|
2328
|
+
}
|
|
2329
|
+
};
|
|
2330
|
+
nodes.push({
|
|
2331
|
+
id: endpoint,
|
|
617
2332
|
type: 'trigger',
|
|
618
|
-
name:
|
|
619
|
-
position:
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
},
|
|
623
|
-
config: {}
|
|
624
|
-
},
|
|
625
|
-
...graph.steps.map(({ column, row, ...step })=>({
|
|
2333
|
+
name: textOr(texts.names?.[endpoint], DEFAULT_ENDPOINT_NAME[endpoint]).slice(0, MAX_NAME_LENGTH),
|
|
2334
|
+
position: at(0),
|
|
2335
|
+
config
|
|
2336
|
+
}, ...graph.steps.map(({ column, row, ...step })=>({
|
|
626
2337
|
...step,
|
|
627
2338
|
name: '',
|
|
628
|
-
position:
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
to
|
|
646
|
-
}));
|
|
2339
|
+
position: at(column, row)
|
|
2340
|
+
})));
|
|
2341
|
+
edges.push(...[
|
|
2342
|
+
[
|
|
2343
|
+
endpoint,
|
|
2344
|
+
'out',
|
|
2345
|
+
graph.steps[0].id
|
|
2346
|
+
],
|
|
2347
|
+
...graph.edges
|
|
2348
|
+
].map(([from, port, to])=>({
|
|
2349
|
+
id: `e_${from}_${port}_${to}`,
|
|
2350
|
+
from,
|
|
2351
|
+
port,
|
|
2352
|
+
to
|
|
2353
|
+
})));
|
|
2354
|
+
band += 1 + Math.max(0, ...graph.steps.map((step)=>step.row ?? 0));
|
|
2355
|
+
}
|
|
647
2356
|
return {
|
|
648
|
-
name:
|
|
649
|
-
slug: entityFlowSlug(entity.code
|
|
2357
|
+
name: entity.label.slice(0, MAX_NAME_LENGTH),
|
|
2358
|
+
slug: entityFlowSlug(entity.code),
|
|
650
2359
|
isActive: true,
|
|
651
|
-
authMode: 'jwt',
|
|
652
|
-
runAs: 'caller',
|
|
653
|
-
isTransactional: graph.isTransactional ?? false,
|
|
654
|
-
bodyType: graph.bodyType ?? 'object',
|
|
655
|
-
inputSchema: graph.inputSchema,
|
|
656
2360
|
nodes,
|
|
657
2361
|
edges
|
|
658
2362
|
};
|
|
659
2363
|
}
|
|
660
2364
|
|
|
661
2365
|
__webpack_require__.d(__webpack_exports__, {
|
|
662
|
-
|
|
663
|
-
|
|
2366
|
+
CO: () => (buildEntityFlow)
|
|
2367
|
+
}, {
|
|
2368
|
+
IP: ENTITY_FLOW_PATHS,
|
|
2369
|
+
x2: entityFlowSlug
|
|
664
2370
|
});
|
|
665
2371
|
|
|
666
2372
|
|
|
@@ -1854,8 +3560,8 @@ class SchemaEvolutionService {
|
|
|
1854
3560
|
const prepared = await this.prepare(request, user);
|
|
1855
3561
|
return this.executor.simulate(prepared.target, prepared.run, prepared.impact);
|
|
1856
3562
|
}
|
|
1857
|
-
async apply(request, user) {
|
|
1858
|
-
const prepared = await this.prepare(request, user);
|
|
3563
|
+
/** `options.fieldId`: the id add_field gives the new field (an import keeps the id it has where it was designed). */ async apply(request, user, options = {}) {
|
|
3564
|
+
const prepared = await this.prepare(request, user, options.fieldId);
|
|
1859
3565
|
const { plan, outcome } = await this.executor.apply(prepared.target, prepared.run, {
|
|
1860
3566
|
confirm: request.confirm === true,
|
|
1861
3567
|
impact: prepared.impact
|
|
@@ -2033,10 +3739,10 @@ class SchemaEvolutionService {
|
|
|
2033
3739
|
return true;
|
|
2034
3740
|
}
|
|
2035
3741
|
// ── dispatch ────────────────────────────────────────────────────────────────────────
|
|
2036
|
-
async prepare(request, user) {
|
|
3742
|
+
async prepare(request, user, fieldId) {
|
|
2037
3743
|
switch(request.action){
|
|
2038
3744
|
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.ADD_FIELD */.M3.ADD_FIELD:
|
|
2039
|
-
return this.prepareAddField(request, user);
|
|
3745
|
+
return this.prepareAddField(request, user, fieldId);
|
|
2040
3746
|
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.UPDATE_FIELD */.M3.UPDATE_FIELD:
|
|
2041
3747
|
return this.prepareUpdateField(request, user);
|
|
2042
3748
|
case _dtos_schema_change_dto_js__rspack_import_6/* .SchemaChangeAction.DEPRECATE_FIELD */.M3.DEPRECATE_FIELD:
|
|
@@ -2133,7 +3839,7 @@ class SchemaEvolutionService {
|
|
|
2133
3839
|
return table.indices.filter((i)=>i.columnNames.length === 1 && i.columnNames[0] === column && i.isUnique === unique);
|
|
2134
3840
|
}
|
|
2135
3841
|
// ── add_field ───────────────────────────────────────────────────────────────────────
|
|
2136
|
-
async prepareAddField(request, user) {
|
|
3842
|
+
async prepareAddField(request, user, fieldId) {
|
|
2137
3843
|
const { definition: loaded } = await this.loadEntity(request.entityDefinitionId);
|
|
2138
3844
|
const spec = request.field;
|
|
2139
3845
|
if (!spec) {
|
|
@@ -2158,7 +3864,12 @@ class SchemaEvolutionService {
|
|
|
2158
3864
|
const nullable = spec.nullable ?? true;
|
|
2159
3865
|
const unique = spec.unique ?? false;
|
|
2160
3866
|
const dbType = this.adapter.mapFieldType(spec.fieldType, ctx.driver);
|
|
2161
|
-
|
|
3867
|
+
const isRelation = spec.fieldType === _enums_field_type_enum_js__rspack_import_20/* .FieldType.RELATION */.P.RELATION;
|
|
3868
|
+
if (isRelation && !spec.relationTargetEntityId) {
|
|
3869
|
+
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, {
|
|
3870
|
+
field: spec.code
|
|
3871
|
+
}));
|
|
3872
|
+
} else if (isRelation) {
|
|
2162
3873
|
const target = await ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_7/* .EntityDefinition */.f).findOne({
|
|
2163
3874
|
where: {
|
|
2164
3875
|
id: spec.relationTargetEntityId
|
|
@@ -2198,8 +3909,8 @@ class SchemaEvolutionService {
|
|
|
2198
3909
|
}));
|
|
2199
3910
|
}
|
|
2200
3911
|
}
|
|
2201
|
-
//
|
|
2202
|
-
if (unique && backfill !== null && rows > 1) {
|
|
3912
|
+
// Only a required field is backfilled; every existing row gets the same value, so two rows or more would clash.
|
|
3913
|
+
if (unique && !nullable && backfill !== null && rows > 1) {
|
|
2203
3914
|
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));
|
|
2204
3915
|
}
|
|
2205
3916
|
if (ctx.blocked || !table) {
|
|
@@ -2249,10 +3960,13 @@ class SchemaEvolutionService {
|
|
|
2249
3960
|
await ctx.qr.createIndex(table, (0,_schema_columns_js__rspack_import_17/* .plainIndex */.v7)(definition.tableName, spec.code, ctx.driver, this.adapter));
|
|
2250
3961
|
});
|
|
2251
3962
|
}
|
|
2252
|
-
let
|
|
3963
|
+
let savedFieldId = null;
|
|
2253
3964
|
await ctx.metadata(async ()=>{
|
|
2254
3965
|
const repo = ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_8/* .FieldDefinition */.c);
|
|
2255
3966
|
const saved = await repo.save(repo.create({
|
|
3967
|
+
...fieldId ? {
|
|
3968
|
+
id: fieldId
|
|
3969
|
+
} : {},
|
|
2256
3970
|
entityDefinitionId: definition.id,
|
|
2257
3971
|
code: spec.code,
|
|
2258
3972
|
label: spec.label,
|
|
@@ -2264,18 +3978,18 @@ class SchemaEvolutionService {
|
|
|
2264
3978
|
defaultValue: spec.defaultValue ?? null,
|
|
2265
3979
|
validationRules: spec.validationRules ?? null,
|
|
2266
3980
|
selectOptions: spec.selectOptions ?? null,
|
|
2267
|
-
relationTargetEntityId: spec.relationTargetEntityId
|
|
3981
|
+
relationTargetEntityId: isRelation ? spec.relationTargetEntityId : null,
|
|
2268
3982
|
order: spec.order ?? Math.max(-1, ...fields.map((f)=>f.order)) + 1,
|
|
2269
3983
|
uiConfig: spec.uiConfig ?? null,
|
|
2270
3984
|
isSearchable: spec.isSearchable ?? false,
|
|
2271
3985
|
isSystemField: false,
|
|
2272
3986
|
deprecatedAt: null
|
|
2273
3987
|
}));
|
|
2274
|
-
|
|
3988
|
+
savedFieldId = saved.id;
|
|
2275
3989
|
});
|
|
2276
3990
|
return {
|
|
2277
3991
|
operation: _enums_ddl_operation_enum_js__rspack_import_21/* .DdlOperation.ADD_COLUMN */.i.ADD_COLUMN,
|
|
2278
|
-
fieldDefinitionId:
|
|
3992
|
+
fieldDefinitionId: savedFieldId,
|
|
2279
3993
|
diff: {
|
|
2280
3994
|
field: {
|
|
2281
3995
|
code: spec.code,
|
|
@@ -3280,21 +4994,23 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
3280
4994
|
/* import */ var _flusys_nestjs_shared_utils__rspack_import_1 = __webpack_require__(9216);
|
|
3281
4995
|
/* import */ var _nestjs_common__rspack_import_2 = __webpack_require__(6157);
|
|
3282
4996
|
/* import */ var typeorm__rspack_import_3 = __webpack_require__(7158);
|
|
3283
|
-
/* import */ var
|
|
4997
|
+
/* import */ var _config_message_keys_js__rspack_import_17 = __webpack_require__(5732);
|
|
3284
4998
|
/* import */ var _entities_entity_definition_entity_js__rspack_import_4 = __webpack_require__(3189);
|
|
3285
4999
|
/* import */ var _entities_field_definition_entity_js__rspack_import_5 = __webpack_require__(2206);
|
|
3286
5000
|
/* import */ var _entities_flow_definition_entity_js__rspack_import_6 = __webpack_require__(3770);
|
|
3287
|
-
/* import */ var
|
|
3288
|
-
/* import */ var
|
|
5001
|
+
/* import */ var _enums_ddl_operation_enum_js__rspack_import_20 = __webpack_require__(9949);
|
|
5002
|
+
/* import */ var _enums_entity_status_enum_js__rspack_import_21 = __webpack_require__(1313);
|
|
5003
|
+
/* import */ var _enums_field_type_enum_js__rspack_import_19 = __webpack_require__(9614);
|
|
3289
5004
|
/* import */ var _flow_engine_flow_errors_js__rspack_import_7 = __webpack_require__(8542);
|
|
3290
5005
|
/* import */ var _entity_builder_datasource_provider_js__rspack_import_8 = __webpack_require__(424);
|
|
3291
5006
|
/* import */ var _entity_flow_scaffold_js__rspack_import_9 = __webpack_require__(8271);
|
|
3292
5007
|
/* import */ var _entity_permission_service_js__rspack_import_10 = __webpack_require__(1462);
|
|
3293
|
-
/* import */ var
|
|
3294
|
-
/* import */ var
|
|
3295
|
-
/* import */ var
|
|
3296
|
-
/* import */ var
|
|
3297
|
-
/* import */ var
|
|
5008
|
+
/* import */ var _field_value_validator_js__rspack_import_11 = __webpack_require__(3525);
|
|
5009
|
+
/* import */ var _flow_definition_service_js__rspack_import_12 = __webpack_require__(5229);
|
|
5010
|
+
/* import */ var _identifier_rules_js__rspack_import_13 = __webpack_require__(413);
|
|
5011
|
+
/* import */ var _schema_change_executor_service_js__rspack_import_14 = __webpack_require__(6605);
|
|
5012
|
+
/* import */ var _schema_columns_js__rspack_import_15 = __webpack_require__(5313);
|
|
5013
|
+
/* import */ var _schema_dialect_adapter_service_js__rspack_import_16 = __webpack_require__(7259);
|
|
3298
5014
|
function _ts_decorate(decorators, target, key, desc) {
|
|
3299
5015
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3300
5016
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -3338,6 +5054,11 @@ function _ts_param(paramIndex, decorator) {
|
|
|
3338
5054
|
|
|
3339
5055
|
|
|
3340
5056
|
|
|
5057
|
+
|
|
5058
|
+
|
|
5059
|
+
const presetId = (id)=>id ? {
|
|
5060
|
+
id
|
|
5061
|
+
} : {};
|
|
3341
5062
|
class SchemaSyncService {
|
|
3342
5063
|
dataSourceProvider;
|
|
3343
5064
|
dialectAdapter;
|
|
@@ -3353,17 +5074,17 @@ class SchemaSyncService {
|
|
|
3353
5074
|
this.flowDefinitionService = flowDefinitionService;
|
|
3354
5075
|
}
|
|
3355
5076
|
validateCreateRequest(dto) {
|
|
3356
|
-
(0,
|
|
5077
|
+
(0,_identifier_rules_js__rspack_import_13/* .assertValidIdentifier */.kV)(dto.code, 'entity');
|
|
3357
5078
|
const fields = dto.fields ?? [];
|
|
3358
5079
|
for (const field of fields){
|
|
3359
|
-
(0,
|
|
3360
|
-
(0,
|
|
5080
|
+
(0,_identifier_rules_js__rspack_import_13/* .assertValidIdentifier */.kV)(field.code, 'field');
|
|
5081
|
+
(0,_identifier_rules_js__rspack_import_13/* .assertIndexableField */.fY)(field);
|
|
3361
5082
|
}
|
|
3362
5083
|
const duplicate = fields.map((f)=>f.code).find((code, index, all)=>all.indexOf(code) !== index);
|
|
3363
5084
|
if (duplicate) {
|
|
3364
5085
|
throw new _nestjs_common__rspack_import_2.BadRequestException({
|
|
3365
5086
|
message: `Field code '${duplicate}' is defined more than once.`,
|
|
3366
|
-
messageKey:
|
|
5087
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .SCHEMA_MESSAGES.DUPLICATE_FIELD_CODE */.Hu.DUPLICATE_FIELD_CODE,
|
|
3367
5088
|
messageVariables: {
|
|
3368
5089
|
code: duplicate
|
|
3369
5090
|
}
|
|
@@ -3371,7 +5092,7 @@ class SchemaSyncService {
|
|
|
3371
5092
|
}
|
|
3372
5093
|
}
|
|
3373
5094
|
async createTarget(dto, user) {
|
|
3374
|
-
const lockCodes = await (0,
|
|
5095
|
+
const lockCodes = await (0,_schema_change_executor_service_js__rspack_import_14/* .relationTargetCodes */.e)(this.dataSourceProvider, (dto.fields ?? []).map((f)=>f.relationTargetEntityId));
|
|
3375
5096
|
return {
|
|
3376
5097
|
action: 'create_entity',
|
|
3377
5098
|
entityDefinitionId: null,
|
|
@@ -3381,7 +5102,7 @@ class SchemaSyncService {
|
|
|
3381
5102
|
lockCodes
|
|
3382
5103
|
};
|
|
3383
5104
|
}
|
|
3384
|
-
createRun(dto, user, created) {
|
|
5105
|
+
createRun(dto, user, created, ids = {}) {
|
|
3385
5106
|
const tableName = `${(/* inlined export .ENTITY_TABLE_PREFIX */"eb_")}${dto.code}`;
|
|
3386
5107
|
const fieldSpecs = dto.fields ?? [];
|
|
3387
5108
|
const flowEndpoints = dto.flowEndpoints ?? [];
|
|
@@ -3392,7 +5113,7 @@ class SchemaSyncService {
|
|
|
3392
5113
|
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), [
|
|
3393
5114
|
tableName
|
|
3394
5115
|
]);
|
|
3395
|
-
if (taken.length) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(
|
|
5116
|
+
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, {
|
|
3396
5117
|
table: tableName
|
|
3397
5118
|
}));
|
|
3398
5119
|
const definitions = ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_4/* .EntityDefinition */.f);
|
|
@@ -3401,41 +5122,61 @@ class SchemaSyncService {
|
|
|
3401
5122
|
code: dto.code
|
|
3402
5123
|
}
|
|
3403
5124
|
});
|
|
3404
|
-
if (known) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(
|
|
5125
|
+
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, {
|
|
3405
5126
|
code: dto.code
|
|
3406
5127
|
}));
|
|
3407
|
-
for (const spec of fieldSpecs){
|
|
3408
|
-
if (spec.relationTargetEntityId) {
|
|
3409
|
-
|
|
3410
|
-
where: {
|
|
3411
|
-
id: spec.relationTargetEntityId
|
|
3412
|
-
}
|
|
3413
|
-
});
|
|
3414
|
-
if (!target) ctx.block((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_16/* .SCHEMA_BLOCKER_MESSAGES.RELATION_FIELD_TARGET_MISSING */.M3.RELATION_FIELD_TARGET_MISSING, {
|
|
5128
|
+
for (const spec of fieldSpecs.filter((f)=>f.fieldType === _enums_field_type_enum_js__rspack_import_19/* .FieldType.RELATION */.P.RELATION)){
|
|
5129
|
+
if (!spec.relationTargetEntityId) {
|
|
5130
|
+
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, {
|
|
3415
5131
|
field: spec.code
|
|
3416
5132
|
}));
|
|
5133
|
+
continue;
|
|
3417
5134
|
}
|
|
5135
|
+
const target = await definitions.findOne({
|
|
5136
|
+
where: {
|
|
5137
|
+
id: spec.relationTargetEntityId
|
|
5138
|
+
}
|
|
5139
|
+
});
|
|
5140
|
+
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, {
|
|
5141
|
+
field: spec.code
|
|
5142
|
+
}));
|
|
3418
5143
|
}
|
|
5144
|
+
const withDefault = fieldSpecs.filter((f)=>f.defaultValue !== undefined && f.defaultValue !== null);
|
|
5145
|
+
const { errors: defaultErrors } = (0,_field_value_validator_js__rspack_import_11/* .validateRecord */.e)(withDefault.map((f)=>({
|
|
5146
|
+
code: f.code,
|
|
5147
|
+
label: f.label,
|
|
5148
|
+
fieldType: f.fieldType,
|
|
5149
|
+
nullable: true,
|
|
5150
|
+
defaultValue: null,
|
|
5151
|
+
selectOptions: f.selectOptions ?? null,
|
|
5152
|
+
validationRules: f.validationRules ?? null
|
|
5153
|
+
})), Object.fromEntries(withDefault.map((f)=>[
|
|
5154
|
+
f.code,
|
|
5155
|
+
f.defaultValue
|
|
5156
|
+
])), 'insert');
|
|
5157
|
+
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, {
|
|
5158
|
+
problem: (0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(error.messageKey, error.messageVariables)
|
|
5159
|
+
}));
|
|
3419
5160
|
if (flowEndpoints.length) {
|
|
3420
|
-
const
|
|
3421
|
-
const
|
|
5161
|
+
const slug = (0,_entity_flow_scaffold_js__rspack_import_9/* .entityFlowSlug */.x2)(dto.code);
|
|
5162
|
+
const clash = await ctx.qr.manager.getRepository(_entities_flow_definition_entity_js__rspack_import_6/* .FlowDefinition */.G).findOne({
|
|
3422
5163
|
select: {
|
|
3423
5164
|
slug: true
|
|
3424
5165
|
},
|
|
3425
5166
|
where: {
|
|
3426
|
-
slug
|
|
5167
|
+
slug
|
|
3427
5168
|
},
|
|
3428
5169
|
withDeleted: true
|
|
3429
5170
|
});
|
|
3430
|
-
|
|
3431
|
-
slug
|
|
5171
|
+
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, {
|
|
5172
|
+
slug
|
|
3432
5173
|
}));
|
|
3433
5174
|
}
|
|
3434
5175
|
if (ctx.blocked) return {
|
|
3435
|
-
operation:
|
|
5176
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_20/* .DdlOperation.CREATE_TABLE */.i.CREATE_TABLE,
|
|
3436
5177
|
diff: {}
|
|
3437
5178
|
};
|
|
3438
|
-
const columns = fieldSpecs.map((spec)=>(0,
|
|
5179
|
+
const columns = fieldSpecs.map((spec)=>(0,_schema_columns_js__rspack_import_15/* .buildFieldColumn */.fu)({
|
|
3439
5180
|
code: spec.code,
|
|
3440
5181
|
fieldType: spec.fieldType,
|
|
3441
5182
|
dbType: '',
|
|
@@ -3448,33 +5189,34 @@ class SchemaSyncService {
|
|
|
3448
5189
|
const table = new typeorm__rspack_import_3.Table({
|
|
3449
5190
|
name: tableName,
|
|
3450
5191
|
columns: [
|
|
3451
|
-
...(0,
|
|
5192
|
+
...(0,_schema_columns_js__rspack_import_15/* .buildSystemColumns */.Rm)({
|
|
3452
5193
|
isSoftDeleteEnabled,
|
|
3453
5194
|
isAuditEnabled
|
|
3454
5195
|
}, ctx.driver),
|
|
3455
5196
|
...columns
|
|
3456
5197
|
]
|
|
3457
5198
|
});
|
|
3458
|
-
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(
|
|
5199
|
+
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, {
|
|
3459
5200
|
table: tableName
|
|
3460
5201
|
}), async ()=>{
|
|
3461
5202
|
await ctx.qr.createTable(table, false);
|
|
3462
5203
|
});
|
|
3463
5204
|
for (const spec of fieldSpecs.filter((f)=>f.isIndexed && !f.unique)){
|
|
3464
|
-
await ctx.ddl((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(
|
|
5205
|
+
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, {
|
|
3465
5206
|
column: spec.code
|
|
3466
5207
|
}), async ()=>{
|
|
3467
|
-
await ctx.qr.createIndex(table, (0,
|
|
5208
|
+
await ctx.qr.createIndex(table, (0,_schema_columns_js__rspack_import_15/* .plainIndex */.v7)(tableName, spec.code, ctx.driver, this.dialectAdapter));
|
|
3468
5209
|
});
|
|
3469
5210
|
}
|
|
3470
5211
|
await ctx.metadata(async ()=>{
|
|
3471
5212
|
const definitionRepo = ctx.qr.manager.getRepository(_entities_entity_definition_entity_js__rspack_import_4/* .EntityDefinition */.f);
|
|
3472
5213
|
const definition = await definitionRepo.save(definitionRepo.create({
|
|
5214
|
+
...presetId(ids.entityId),
|
|
3473
5215
|
code: dto.code,
|
|
3474
5216
|
label: dto.label,
|
|
3475
5217
|
description: dto.description ?? null,
|
|
3476
5218
|
tableName,
|
|
3477
|
-
status:
|
|
5219
|
+
status: _enums_entity_status_enum_js__rspack_import_21/* .EntityStatus.ACTIVE */.c.ACTIVE,
|
|
3478
5220
|
schemaVersion: 1,
|
|
3479
5221
|
isSoftDeleteEnabled,
|
|
3480
5222
|
isAuditEnabled,
|
|
@@ -3483,6 +5225,7 @@ class SchemaSyncService {
|
|
|
3483
5225
|
const fieldRepo = ctx.qr.manager.getRepository(_entities_field_definition_entity_js__rspack_import_5/* .FieldDefinition */.c);
|
|
3484
5226
|
if (fieldSpecs.length) {
|
|
3485
5227
|
await fieldRepo.save(fieldSpecs.map((spec, index)=>fieldRepo.create({
|
|
5228
|
+
...presetId(ids.fieldIds?.[spec.code]),
|
|
3486
5229
|
entityDefinitionId: definition.id,
|
|
3487
5230
|
code: spec.code,
|
|
3488
5231
|
label: spec.label,
|
|
@@ -3494,7 +5237,7 @@ class SchemaSyncService {
|
|
|
3494
5237
|
defaultValue: spec.defaultValue ?? null,
|
|
3495
5238
|
validationRules: spec.validationRules ?? null,
|
|
3496
5239
|
selectOptions: spec.selectOptions ?? null,
|
|
3497
|
-
relationTargetEntityId: spec.relationTargetEntityId
|
|
5240
|
+
relationTargetEntityId: spec.fieldType === _enums_field_type_enum_js__rspack_import_19/* .FieldType.RELATION */.P.RELATION ? spec.relationTargetEntityId : null,
|
|
3498
5241
|
order: spec.order ?? index,
|
|
3499
5242
|
uiConfig: spec.uiConfig ?? null,
|
|
3500
5243
|
isSearchable: spec.isSearchable ?? false,
|
|
@@ -3505,7 +5248,7 @@ class SchemaSyncService {
|
|
|
3505
5248
|
created.definition = definition;
|
|
3506
5249
|
});
|
|
3507
5250
|
return {
|
|
3508
|
-
operation:
|
|
5251
|
+
operation: _enums_ddl_operation_enum_js__rspack_import_20/* .DdlOperation.CREATE_TABLE */.i.CREATE_TABLE,
|
|
3509
5252
|
entityDefinitionId: created.definition?.id ?? null,
|
|
3510
5253
|
diff: {
|
|
3511
5254
|
fields: fieldSpecs.map((f)=>({
|
|
@@ -3519,36 +5262,34 @@ class SchemaSyncService {
|
|
|
3519
5262
|
try {
|
|
3520
5263
|
await this.entityPermissionService.provisionForEntity(created.definition);
|
|
3521
5264
|
} finally{
|
|
3522
|
-
created.warnings.push(...await this.
|
|
5265
|
+
if (flowEndpoints.length) created.warnings.push(...await this.createEndpointFlow(dto, flowEndpoints, user));
|
|
3523
5266
|
}
|
|
3524
5267
|
}
|
|
3525
5268
|
};
|
|
3526
5269
|
};
|
|
3527
5270
|
}
|
|
3528
5271
|
/**
|
|
3529
|
-
*
|
|
3530
|
-
* validated like any other flow.
|
|
3531
|
-
*
|
|
3532
|
-
*/ async
|
|
3533
|
-
const
|
|
5272
|
+
* The entity's ready-made flow, one Request step per requested endpoint, saved through
|
|
5273
|
+
* FlowDefinitionService so it is validated like any other flow. The entity is already committed,
|
|
5274
|
+
* so a flow that cannot be saved is reported as a warning.
|
|
5275
|
+
*/ async createEndpointFlow(dto, endpoints, user) {
|
|
5276
|
+
const flow = (0,_entity_flow_scaffold_js__rspack_import_9/* .buildEntityFlow */.CO)({
|
|
3534
5277
|
code: dto.code,
|
|
3535
5278
|
label: dto.label,
|
|
3536
5279
|
fields: dto.fields ?? []
|
|
3537
|
-
};
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
warnings.push((0,_flusys_nestjs_shared_utils__rspack_import_1.messageRef)(_config_message_keys_js__rspack_import_16/* .SCHEMA_WARNING_MESSAGES.ENDPOINT_FLOW_FAILED */.Uu.ENDPOINT_FLOW_FAILED, {
|
|
5280
|
+
}, endpoints, dto.flowTexts);
|
|
5281
|
+
try {
|
|
5282
|
+
await this.flowDefinitionService.insert(flow, user);
|
|
5283
|
+
return [];
|
|
5284
|
+
} catch (error) {
|
|
5285
|
+
this.logger.error(`The flow '${flow.slug}' of entity '${dto.code}' could not be created: ${error.message}`);
|
|
5286
|
+
return [
|
|
5287
|
+
(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, {
|
|
3546
5288
|
slug: flow.slug,
|
|
3547
5289
|
detail: (0,_flow_engine_flow_errors_js__rspack_import_7/* .errorRef */.O$)(error)
|
|
3548
|
-
})
|
|
3549
|
-
|
|
5290
|
+
})
|
|
5291
|
+
];
|
|
3550
5292
|
}
|
|
3551
|
-
return warnings;
|
|
3552
5293
|
}
|
|
3553
5294
|
/** Preview of `createEntity`: the CREATE TABLE / CREATE INDEX statements, nothing is created. */ async planCreateEntity(dto, user) {
|
|
3554
5295
|
this.validateCreateRequest(dto);
|
|
@@ -3556,7 +5297,7 @@ class SchemaSyncService {
|
|
|
3556
5297
|
warnings: []
|
|
3557
5298
|
}));
|
|
3558
5299
|
}
|
|
3559
|
-
async createEntity(dto, user) {
|
|
5300
|
+
async createEntity(dto, user, ids = {}) {
|
|
3560
5301
|
this.validateCreateRequest(dto);
|
|
3561
5302
|
if (dto.flowEndpoints?.length) await this.flowDefinitionService.assertMayCreate(user);
|
|
3562
5303
|
const created = {
|
|
@@ -3564,12 +5305,12 @@ class SchemaSyncService {
|
|
|
3564
5305
|
};
|
|
3565
5306
|
let planWarnings;
|
|
3566
5307
|
try {
|
|
3567
|
-
({ plan: { warnings: planWarnings } } = await this.executor.apply(await this.createTarget(dto, user), this.createRun(dto, user, created)));
|
|
5308
|
+
({ plan: { warnings: planWarnings } } = await this.executor.apply(await this.createTarget(dto, user), this.createRun(dto, user, created, ids)));
|
|
3568
5309
|
} catch (error) {
|
|
3569
|
-
if (error instanceof _nestjs_common__rspack_import_2.ConflictException && error.getResponse().blockers?.some((b)=>b.messageKey ===
|
|
5310
|
+
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)) {
|
|
3570
5311
|
throw new _nestjs_common__rspack_import_2.ConflictException({
|
|
3571
5312
|
message: `An entity with the code '${dto.code}' already exists.`,
|
|
3572
|
-
messageKey:
|
|
5313
|
+
messageKey: _config_message_keys_js__rspack_import_17/* .ENTITY_DEFINITION_MESSAGES.CODE_ALREADY_EXISTS */.pL.CODE_ALREADY_EXISTS,
|
|
3573
5314
|
messageVariables: {
|
|
3574
5315
|
code: dto.code
|
|
3575
5316
|
}
|
|
@@ -3591,17 +5332,17 @@ SchemaSyncService = _ts_decorate([
|
|
|
3591
5332
|
scope: _nestjs_common__rspack_import_2.Scope.REQUEST
|
|
3592
5333
|
}),
|
|
3593
5334
|
_ts_param(0, (0,_nestjs_common__rspack_import_2.Inject)(_entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D)),
|
|
3594
|
-
_ts_param(1, (0,_nestjs_common__rspack_import_2.Inject)(
|
|
3595
|
-
_ts_param(2, (0,_nestjs_common__rspack_import_2.Inject)(
|
|
5335
|
+
_ts_param(1, (0,_nestjs_common__rspack_import_2.Inject)(_schema_dialect_adapter_service_js__rspack_import_16/* .SchemaDialectAdapterService */.I)),
|
|
5336
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_2.Inject)(_schema_change_executor_service_js__rspack_import_14/* .SchemaChangeExecutor */.T)),
|
|
3596
5337
|
_ts_param(3, (0,_nestjs_common__rspack_import_2.Inject)(_entity_permission_service_js__rspack_import_10/* .EntityPermissionService */.u)),
|
|
3597
|
-
_ts_param(4, (0,_nestjs_common__rspack_import_2.Inject)(
|
|
5338
|
+
_ts_param(4, (0,_nestjs_common__rspack_import_2.Inject)(_flow_definition_service_js__rspack_import_12/* .FlowDefinitionService */.Tk)),
|
|
3598
5339
|
_ts_metadata("design:type", Function),
|
|
3599
5340
|
_ts_metadata("design:paramtypes", [
|
|
3600
5341
|
typeof _entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D === "undefined" ? Object : _entity_builder_datasource_provider_js__rspack_import_8/* .EntityBuilderDataSourceProvider */.D,
|
|
3601
|
-
typeof
|
|
3602
|
-
typeof
|
|
5342
|
+
typeof _schema_dialect_adapter_service_js__rspack_import_16/* .SchemaDialectAdapterService */.I === "undefined" ? Object : _schema_dialect_adapter_service_js__rspack_import_16/* .SchemaDialectAdapterService */.I,
|
|
5343
|
+
typeof _schema_change_executor_service_js__rspack_import_14/* .SchemaChangeExecutor */.T === "undefined" ? Object : _schema_change_executor_service_js__rspack_import_14/* .SchemaChangeExecutor */.T,
|
|
3603
5344
|
typeof _entity_permission_service_js__rspack_import_10/* .EntityPermissionService */.u === "undefined" ? Object : _entity_permission_service_js__rspack_import_10/* .EntityPermissionService */.u,
|
|
3604
|
-
typeof
|
|
5345
|
+
typeof _flow_definition_service_js__rspack_import_12/* .FlowDefinitionService */.Tk === "undefined" ? Object : _flow_definition_service_js__rspack_import_12/* .FlowDefinitionService */.Tk
|
|
3605
5346
|
])
|
|
3606
5347
|
], SchemaSyncService);
|
|
3607
5348
|
|