@memberjunction/codegen-lib 2.7.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Angular/angular-codegen.js +3 -3
- package/dist/Angular/angular-codegen.js.map +1 -1
- package/dist/Config/config.d.ts +7 -7
- package/dist/Config/config.d.ts.map +1 -1
- package/dist/Config/config.js +2 -2
- package/dist/Config/config.js.map +1 -1
- package/dist/Database/dbSchema.js +2 -2
- package/dist/Database/dbSchema.js.map +1 -1
- package/dist/Database/manage-metadata.d.ts +7 -13
- package/dist/Database/manage-metadata.d.ts.map +1 -1
- package/dist/Database/manage-metadata.js +146 -196
- package/dist/Database/manage-metadata.js.map +1 -1
- package/dist/Database/sql.js +5 -5
- package/dist/Database/sql.js.map +1 -1
- package/dist/Database/sql_codegen.js +26 -26
- package/dist/Database/sql_codegen.js.map +1 -1
- package/dist/Misc/action_subclasses_codegen.d.ts.map +1 -0
- package/dist/{action_subclasses_codegen.js → Misc/action_subclasses_codegen.js} +4 -4
- package/dist/Misc/action_subclasses_codegen.js.map +1 -0
- package/dist/Misc/createNewUser.js +6 -6
- package/dist/Misc/createNewUser.js.map +1 -1
- package/dist/Misc/entity_subclasses_codegen.d.ts.map +1 -0
- package/dist/{entity_subclasses_codegen.js → Misc/entity_subclasses_codegen.js} +4 -4
- package/dist/Misc/entity_subclasses_codegen.js.map +1 -0
- package/dist/Misc/graphql_server_codegen.d.ts.map +1 -0
- package/dist/{graphql_server_codegen.js → Misc/graphql_server_codegen.js} +10 -12
- package/dist/Misc/graphql_server_codegen.js.map +1 -0
- package/dist/Misc/runCommand.js +10 -10
- package/dist/Misc/runCommand.js.map +1 -1
- package/dist/Misc/sql_logging.d.ts +21 -0
- package/dist/Misc/sql_logging.d.ts.map +1 -0
- package/dist/Misc/sql_logging.js +128 -0
- package/dist/Misc/sql_logging.js.map +1 -0
- package/dist/Misc/{logging.d.ts → status_logging.d.ts} +1 -1
- package/dist/Misc/status_logging.d.ts.map +1 -0
- package/dist/Misc/{logging.js → status_logging.js} +1 -1
- package/dist/Misc/status_logging.js.map +1 -0
- package/dist/Misc/util.js +2 -2
- package/dist/Misc/util.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/runCodeGen.d.ts.map +1 -1
- package/dist/runCodeGen.js +54 -52
- package/dist/runCodeGen.js.map +1 -1
- package/package.json +8 -7
- package/dist/Misc/logging.d.ts.map +0 -1
- package/dist/Misc/logging.js.map +0 -1
- package/dist/action_subclasses_codegen.d.ts.map +0 -1
- package/dist/action_subclasses_codegen.js.map +0 -1
- package/dist/entity_subclasses_codegen.d.ts.map +0 -1
- package/dist/entity_subclasses_codegen.js.map +0 -1
- package/dist/graphql_server_codegen.d.ts.map +0 -1
- package/dist/graphql_server_codegen.js.map +0 -1
- /package/dist/{action_subclasses_codegen.d.ts → Misc/action_subclasses_codegen.d.ts} +0 -0
- /package/dist/{entity_subclasses_codegen.d.ts → Misc/entity_subclasses_codegen.d.ts} +0 -0
- /package/dist/{graphql_server_codegen.d.ts → Misc/graphql_server_codegen.d.ts} +0 -0
|
@@ -36,12 +36,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.ManageMetadataBase = void 0;
|
|
37
37
|
const config_1 = require("../Config/config");
|
|
38
38
|
const core_1 = require("@memberjunction/core");
|
|
39
|
-
const
|
|
39
|
+
const status_logging_1 = require("../Misc/status_logging");
|
|
40
40
|
const sql_1 = require("./sql");
|
|
41
41
|
const advanced_generation_1 = require("../Misc/advanced_generation");
|
|
42
42
|
const global_1 = require("@memberjunction/global");
|
|
43
|
+
const uuid_1 = require("uuid");
|
|
43
44
|
const fs = __importStar(require("fs"));
|
|
44
45
|
const path_1 = __importDefault(require("path"));
|
|
46
|
+
const sql_logging_1 = require("../Misc/sql_logging");
|
|
45
47
|
/**
|
|
46
48
|
* Base class for managing metadata within the CodeGen system. This class can be sub-classed to extend/override base class functionality. Make sure to use the RegisterClass decorator from the @memberjunction/global package
|
|
47
49
|
* to properly register your subclass with a priority of 1+ to ensure it gets instantiated.
|
|
@@ -56,73 +58,6 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
56
58
|
static get newEntityList() {
|
|
57
59
|
return this._newEntityList;
|
|
58
60
|
}
|
|
59
|
-
async manageMetaDataLogging(config) {
|
|
60
|
-
if (!config) {
|
|
61
|
-
(0, logging_1.logError)("MetadataLoggingConfig is required to enable metadata logging");
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
if (!config.folderPath && !config.filePath) {
|
|
65
|
-
(0, logging_1.logError)("Either folderPath or filePath is required to enable metadata logging");
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
if (config.folderPath) {
|
|
69
|
-
const dirExists = fs.existsSync(config.folderPath);
|
|
70
|
-
if (!dirExists) {
|
|
71
|
-
fs.mkdirSync(config.folderPath, { recursive: true });
|
|
72
|
-
}
|
|
73
|
-
const fileName = this.createFileName();
|
|
74
|
-
this.FilePath = path_1.default.join(config.folderPath, `${fileName}.sql`);
|
|
75
|
-
//create an empty file
|
|
76
|
-
fs.writeFileSync(this.FilePath, '');
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
this.FilePath = config.filePath;
|
|
80
|
-
if (this.FilePath && config.overwriteFile) {
|
|
81
|
-
//append to the file
|
|
82
|
-
fs.writeFileSync(this.FilePath, '');
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
this.Config = config;
|
|
86
|
-
(0, core_1.LogStatus)(`Metadata logging enabled. File path: ${this.FilePath}`);
|
|
87
|
-
}
|
|
88
|
-
createFileName() {
|
|
89
|
-
const date = new Date();
|
|
90
|
-
const year = date.getUTCFullYear();
|
|
91
|
-
const month = String(date.getUTCMonth() + 1).padStart(2, '0'); // Month is 0-based
|
|
92
|
-
const day = String(date.getUTCDate()).padStart(2, '0');
|
|
93
|
-
const hour = String(date.getUTCHours()).padStart(2, '0');
|
|
94
|
-
const minute = String(date.getUTCMinutes()).padStart(2, '0');
|
|
95
|
-
const second = String(date.getUTCSeconds()).padStart(2, '0');
|
|
96
|
-
const fileName = `CodeGen_Run_${year}-${month}-${day}_${hour}-${minute}-${second}`;
|
|
97
|
-
return fileName;
|
|
98
|
-
}
|
|
99
|
-
async appendToFile(contents, description) {
|
|
100
|
-
try {
|
|
101
|
-
if (!contents || !this.FilePath) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (description) {
|
|
105
|
-
const comment = `/* ${description} */\n`;
|
|
106
|
-
contents = `${comment}${contents}`;
|
|
107
|
-
}
|
|
108
|
-
contents = `${contents}\n\n`;
|
|
109
|
-
fs.appendFileSync(this.FilePath, contents);
|
|
110
|
-
}
|
|
111
|
-
catch (ex) {
|
|
112
|
-
(0, logging_1.logError)("Unable to log metadata SQL text to file", ex);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
convertCoreSchemaToFlywaySchema() {
|
|
116
|
-
if (!this.FilePath) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const coreSchema = (0, config_1.mj_core_schema)();
|
|
120
|
-
const regex = new RegExp(coreSchema, 'g');
|
|
121
|
-
const data = fs.readFileSync(`${this.FilePath}`, 'utf-8');
|
|
122
|
-
const replacedData = data.replace(regex, "${flyway:defaultSchema}");
|
|
123
|
-
fs.writeFileSync(`${this.FilePath}`, replacedData);
|
|
124
|
-
(0, logging_1.logStatus)(`Replaced all instances of ${coreSchema} with \${flyway:defaultSchema} in the metadata log file`);
|
|
125
|
-
}
|
|
126
61
|
/**
|
|
127
62
|
* Primary function to manage metadata within the CodeGen system. This function will call a series of sub-functions to manage the metadata.
|
|
128
63
|
* @param ds - the DataSource object to use for querying and updating the database
|
|
@@ -133,62 +68,59 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
133
68
|
const excludeSchemas = config_1.configInfo.excludeSchemas ? config_1.configInfo.excludeSchemas : [];
|
|
134
69
|
let bSuccess = true;
|
|
135
70
|
let start = new Date();
|
|
136
|
-
(0,
|
|
71
|
+
(0, status_logging_1.logStatus)(' Creating new entities...');
|
|
137
72
|
if (!await this.createNewEntities(ds)) {
|
|
138
|
-
(0,
|
|
73
|
+
(0, status_logging_1.logError)(' Error creating new entities');
|
|
139
74
|
bSuccess = false;
|
|
140
75
|
}
|
|
141
|
-
(0,
|
|
76
|
+
(0, status_logging_1.logStatus)(` > Created new entities in ${(new Date().getTime() - start.getTime()) / 1000} seconds`);
|
|
142
77
|
start = new Date();
|
|
143
|
-
(0,
|
|
78
|
+
(0, status_logging_1.logStatus)(' Updating existing entities...');
|
|
144
79
|
if (!await this.updateExistingEntitiesFromSchema(ds, excludeSchemas)) {
|
|
145
|
-
(0,
|
|
80
|
+
(0, status_logging_1.logError)(' Error updating existing entities');
|
|
146
81
|
bSuccess = false;
|
|
147
82
|
}
|
|
148
|
-
(0,
|
|
83
|
+
(0, status_logging_1.logStatus)(` > Updated existing entities in ${(new Date().getTime() - start.getTime()) / 1000} seconds`);
|
|
149
84
|
start = new Date();
|
|
150
|
-
(0,
|
|
85
|
+
(0, status_logging_1.logStatus)(' Scanning for tables that were deleted where entity metadata still exists...');
|
|
151
86
|
if (!await this.checkAndRemoveMetadataForDeletedTables(ds, excludeSchemas)) {
|
|
152
|
-
(0,
|
|
87
|
+
(0, status_logging_1.logError)(' Error removing metadata for tables that were removed');
|
|
153
88
|
bSuccess = false;
|
|
154
89
|
}
|
|
155
|
-
(0,
|
|
90
|
+
(0, status_logging_1.logStatus)(` > Removed metadata for deleted tables in ${(new Date().getTime() - start.getTime()) / 1000} seconds`);
|
|
156
91
|
start = new Date();
|
|
157
|
-
(0,
|
|
92
|
+
(0, status_logging_1.logStatus)(' Recompiling base views...');
|
|
158
93
|
const sqlUtility = global_1.MJGlobal.Instance.ClassFactory.CreateInstance(sql_1.SQLUtilityBase);
|
|
159
94
|
if (!await sqlUtility.recompileAllBaseViews(ds, excludeSchemas, true)) {
|
|
160
|
-
(0,
|
|
95
|
+
(0, status_logging_1.logMessage)(' Warning: Non-Fatal error recompiling base views', core_1.SeverityType.Warning, false);
|
|
161
96
|
// many times the former versions of base views will NOT succesfully recompile, so don't consider that scenario to be a
|
|
162
97
|
// failure for this entire function
|
|
163
98
|
}
|
|
164
|
-
(0,
|
|
99
|
+
(0, status_logging_1.logStatus)(` > Recompiled base views in ${(new Date().getTime() - start.getTime()) / 1000} seconds`);
|
|
165
100
|
start = new Date();
|
|
166
|
-
(0,
|
|
101
|
+
(0, status_logging_1.logStatus)(' Managing entity fields...');
|
|
167
102
|
if (!await this.manageEntityFields(ds, excludeSchemas, false, false)) {
|
|
168
|
-
(0,
|
|
103
|
+
(0, status_logging_1.logError)(' Error managing entity fields');
|
|
169
104
|
bSuccess = false;
|
|
170
105
|
}
|
|
171
|
-
(0,
|
|
106
|
+
(0, status_logging_1.logStatus)(` > Managed entity fields in ${(new Date().getTime() - start.getTime()) / 1000} seconds`);
|
|
172
107
|
start = new Date();
|
|
173
|
-
(0,
|
|
108
|
+
(0, status_logging_1.logStatus)(' Managing entity relationships...');
|
|
174
109
|
if (!await this.manageEntityRelationships(ds, excludeSchemas, md)) {
|
|
175
|
-
(0,
|
|
110
|
+
(0, status_logging_1.logError)(' Error managing entity relationships');
|
|
176
111
|
bSuccess = false;
|
|
177
112
|
}
|
|
178
|
-
(0,
|
|
113
|
+
(0, status_logging_1.logStatus)(` > Managed entity relationships in ${(new Date().getTime() - start.getTime()) / 1000} seconds`);
|
|
179
114
|
if (ManageMetadataBase_1.newEntityList.length > 0) {
|
|
180
115
|
await this.generateNewEntityDescriptions(ds, md); // don't pass excludeSchemas becuase by definition this is the NEW entities we created
|
|
181
116
|
}
|
|
182
117
|
const veResult = await this.manageVirtualEntities(ds);
|
|
183
118
|
if (!veResult.success) {
|
|
184
|
-
(0,
|
|
119
|
+
(0, status_logging_1.logError)(' Error managing virtual entities');
|
|
185
120
|
bSuccess = false;
|
|
186
121
|
}
|
|
187
122
|
// now - we need to tell our metadata object to refresh itself
|
|
188
123
|
await md.Refresh();
|
|
189
|
-
if (this.Config && this.Config.convertCoreSchemaToFlywaySchema) {
|
|
190
|
-
this.convertCoreSchemaToFlywaySchema();
|
|
191
|
-
}
|
|
192
124
|
return bSuccess;
|
|
193
125
|
}
|
|
194
126
|
async manageVirtualEntities(ds) {
|
|
@@ -205,7 +137,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
205
137
|
const { success, updatedEntity } = await this.manageSingleVirtualEntity(ds, ve);
|
|
206
138
|
anyUpdates = anyUpdates || updatedEntity;
|
|
207
139
|
if (!success) {
|
|
208
|
-
(0,
|
|
140
|
+
(0, status_logging_1.logError)(` Error managing virtual entity ${ve.Name}`);
|
|
209
141
|
bSuccess = false;
|
|
210
142
|
}
|
|
211
143
|
}
|
|
@@ -246,7 +178,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
246
178
|
if (removeList.length > 0) {
|
|
247
179
|
const sqlRemove = `DELETE FROM [${(0, config_1.mj_core_schema)()}].EntityField WHERE ID IN (${removeList.map(removeId => `'${removeId}'`).join(',')})`;
|
|
248
180
|
// this removes the fields that shouldn't be there anymore
|
|
249
|
-
this.
|
|
181
|
+
this.LogSQLAndExecute(ds, sqlRemove, `SQL text to remove fields from entity ${virtualEntity.Name}`);
|
|
250
182
|
bUpdated = true;
|
|
251
183
|
}
|
|
252
184
|
// check to see if any of the fields in the virtual entity have Pkey attribute set. If not, we will default to the first field
|
|
@@ -258,7 +190,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
258
190
|
const { success, updatedField } = await this.manageSingleVirtualEntityField(ds, virtualEntity, vef, i + 1, !hasPkey && i === 0);
|
|
259
191
|
bUpdated = bUpdated || updatedField;
|
|
260
192
|
if (!success) {
|
|
261
|
-
(0,
|
|
193
|
+
(0, status_logging_1.logError)(`Error managing virtual entity field ${vef.FieldName} for virtual entity ${virtualEntity.Name}`);
|
|
262
194
|
bSuccess = false;
|
|
263
195
|
}
|
|
264
196
|
}
|
|
@@ -267,12 +199,12 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
267
199
|
if (bUpdated) {
|
|
268
200
|
// finally make sure we update the UpdatedAt field for the entity if we made changes to its fields
|
|
269
201
|
const sqlUpdate = `UPDATE [${(0, config_1.mj_core_schema)()}].Entity SET [${core_1.EntityInfo.UpdatedAtFieldName}]=GETUTCDATE() WHERE ID='${virtualEntity.ID}'`;
|
|
270
|
-
await
|
|
202
|
+
await this.LogSQLAndExecute(ds, sqlUpdate, `SQL text to update virtual entity updated date for ${virtualEntity.Name}`);
|
|
271
203
|
}
|
|
272
204
|
return { success: bSuccess, updatedEntity: bUpdated };
|
|
273
205
|
}
|
|
274
206
|
catch (e) {
|
|
275
|
-
(0,
|
|
207
|
+
(0, status_logging_1.logError)(e);
|
|
276
208
|
return { success: false, updatedEntity: bUpdated };
|
|
277
209
|
}
|
|
278
210
|
}
|
|
@@ -282,6 +214,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
282
214
|
// first, get the entity definition
|
|
283
215
|
const md = new core_1.Metadata();
|
|
284
216
|
const entity = md.EntityByName(virtualEntity.Name);
|
|
217
|
+
let newEntityFieldUUID = null;
|
|
285
218
|
let didUpdate = false;
|
|
286
219
|
if (entity) {
|
|
287
220
|
const field = entity.Fields.find(f => f.Name.trim().toLowerCase() === veField.FieldName.trim().toLowerCase());
|
|
@@ -307,25 +240,26 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
307
240
|
Scale=${veField.Scale}
|
|
308
241
|
WHERE
|
|
309
242
|
ID = '${field.ID}'`; // don't need to update the __mj_UpdatedAt field here, that happens automatically via the trigger
|
|
310
|
-
await this.
|
|
243
|
+
await this.LogSQLAndExecute(ds, sqlUpdate, `SQL text to update virtual entity field ${veField.FieldName} for entity ${virtualEntity.Name}`);
|
|
311
244
|
didUpdate = true;
|
|
312
245
|
}
|
|
313
246
|
}
|
|
314
247
|
else {
|
|
315
248
|
// this means that we do NOT have a match so the field does not exist in the entity definition, so we need to add it
|
|
249
|
+
newEntityFieldUUID = this.createNewUUID();
|
|
316
250
|
const sqlAdd = `INSERT INTO [${(0, config_1.mj_core_schema)()}].EntityField (
|
|
317
|
-
EntityID, Name, Type, AllowsNull,
|
|
251
|
+
ID, EntityID, Name, Type, AllowsNull,
|
|
318
252
|
Length, Precision, Scale,
|
|
319
253
|
Sequence, IsPrimaryKey, IsUnique )
|
|
320
|
-
VALUES ( '${entity.ID}', '${veField.FieldName}', '${veField.Type}', ${veField.AllowsNull ? 1 : 0},
|
|
254
|
+
VALUES ( '${newEntityFieldUUID}', '${entity.ID}', '${veField.FieldName}', '${veField.Type}', ${veField.AllowsNull ? 1 : 0},
|
|
321
255
|
${veField.Length}, ${veField.Precision}, ${veField.Scale},
|
|
322
256
|
${fieldSequence}, ${makePrimaryKey ? 1 : 0}, ${makePrimaryKey ? 1 : 0}
|
|
323
257
|
)`;
|
|
324
|
-
await this.
|
|
258
|
+
await this.LogSQLAndExecute(ds, sqlAdd, `SQL text to add virtual entity field ${veField.FieldName} for entity ${virtualEntity.Name}`);
|
|
325
259
|
didUpdate = true;
|
|
326
260
|
}
|
|
327
261
|
}
|
|
328
|
-
return { success: true, updatedField: didUpdate };
|
|
262
|
+
return { success: true, updatedField: didUpdate, newFieldID: newEntityFieldUUID };
|
|
329
263
|
}
|
|
330
264
|
/**
|
|
331
265
|
* This method creates and updates relationships in the metadata based on foreign key relationships in the database.
|
|
@@ -392,15 +326,16 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
392
326
|
// calculate the sequence by getting the count of existing relationships for the entity and adding 1 and then increment the count for future inserts in this loop
|
|
393
327
|
const relCount = relationshipCountMap.get(f.EntityID) || 0;
|
|
394
328
|
const sequence = relCount + 1;
|
|
395
|
-
|
|
396
|
-
|
|
329
|
+
const newEntityRelationshipUUID = this.createNewUUID();
|
|
330
|
+
batchSQL += `INSERT INTO ${(0, config_1.mj_core_schema)()}.EntityRelationship (ID, EntityID, RelatedEntityID, RelatedEntityJoinField, Type, BundleInAPI, DisplayInForm, DisplayName, Sequence)
|
|
331
|
+
VALUES ('${newEntityRelationshipUUID}', '${f.RelatedEntityID}', '${f.EntityID}', '${f.Name}', 'One To Many', 1, 1, '${e.Name}', ${sequence});
|
|
397
332
|
`;
|
|
398
333
|
// now update the map for the relationship count
|
|
399
334
|
relationshipCountMap.set(f.EntityID, sequence);
|
|
400
335
|
}
|
|
401
336
|
});
|
|
402
337
|
if (batchSQL.length > 0) {
|
|
403
|
-
await this.
|
|
338
|
+
await this.LogSQLAndExecute(ds, batchSQL, `SQL text to create Entitiy Relationships`);
|
|
404
339
|
}
|
|
405
340
|
};
|
|
406
341
|
// Split entityFields into batches and process each batch
|
|
@@ -411,7 +346,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
411
346
|
return true;
|
|
412
347
|
}
|
|
413
348
|
catch (e) {
|
|
414
|
-
(0,
|
|
349
|
+
(0, status_logging_1.logError)(e);
|
|
415
350
|
return false;
|
|
416
351
|
}
|
|
417
352
|
}
|
|
@@ -432,8 +367,8 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
432
367
|
// for the admin to handle manually
|
|
433
368
|
try {
|
|
434
369
|
const sqlDelete = `__mj.spDeleteEntityWithCoreDependencies @EntityID='${e.ID}'`;
|
|
435
|
-
await
|
|
436
|
-
(0,
|
|
370
|
+
await this.LogSQLAndExecute(ds, sqlDelete, `SQL text to remove entity ${e.Name}`);
|
|
371
|
+
(0, status_logging_1.logStatus)(` > Removed metadata for table ${e.SchemaName}.${e.BaseTable}`);
|
|
437
372
|
// next up we need to remove the spCreate, spDelete, spUpdate, BaseView, and FullTextSearchFunction, if provided.
|
|
438
373
|
// We only remoe these artifcacts when they are generated which is info we have in the BaseViewGenerated, spCreateGenerated, etc. fields
|
|
439
374
|
await this.checkDropSQLObject(ds, e.BaseViewGenerated, 'view', e.SchemaName, e.BaseView);
|
|
@@ -443,7 +378,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
443
378
|
await this.checkDropSQLObject(ds, e.FullTextSearchFunctionGenerated, 'function', e.SchemaName, e.FullTextSearchFunction);
|
|
444
379
|
}
|
|
445
380
|
catch (ex) {
|
|
446
|
-
(0,
|
|
381
|
+
(0, status_logging_1.logError)(`Error removing metadata for entity ${ex.Name}, error: ${ex}`);
|
|
447
382
|
}
|
|
448
383
|
}
|
|
449
384
|
// if we get here we now need to refresh our metadata object
|
|
@@ -453,7 +388,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
453
388
|
return true;
|
|
454
389
|
}
|
|
455
390
|
catch (e) {
|
|
456
|
-
(0,
|
|
391
|
+
(0, status_logging_1.logError)(e);
|
|
457
392
|
return false;
|
|
458
393
|
}
|
|
459
394
|
}
|
|
@@ -461,7 +396,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
461
396
|
try {
|
|
462
397
|
if (proceed && schemaName && name && schemaName.trim().length > 0 && name.trim().length > 0) {
|
|
463
398
|
const sqlDelete = `DROP ${type} IF EXISTS [${schemaName}].[${name}]`;
|
|
464
|
-
await
|
|
399
|
+
await this.LogSQLAndExecute(ds, sqlDelete, `SQL text to remove ${type} ${schemaName}.${name}`);
|
|
465
400
|
// next up, we need to clean up the cache of saved DB objects that may exist for this entity in the appropriate sub-directory.
|
|
466
401
|
const sqlOutputDir = (0, config_1.outputDir)('SQL', true);
|
|
467
402
|
if (sqlOutputDir) {
|
|
@@ -475,11 +410,11 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
475
410
|
if (fs.existsSync(filePathPermissions))
|
|
476
411
|
fs.unlinkSync(filePathPermissions);
|
|
477
412
|
}
|
|
478
|
-
(0,
|
|
413
|
+
(0, status_logging_1.logStatus)(` > Removed ${type} ${schemaName}.${name}`);
|
|
479
414
|
}
|
|
480
415
|
}
|
|
481
416
|
catch (e) {
|
|
482
|
-
(0,
|
|
417
|
+
(0, status_logging_1.logError)(` > Error removing ${type} ${schemaName}.${name}, error: ${e}`);
|
|
483
418
|
}
|
|
484
419
|
}
|
|
485
420
|
/**
|
|
@@ -505,51 +440,51 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
505
440
|
if (!skipCreatedAtUpdatedAtDeletedAtFieldValidation) {
|
|
506
441
|
if (!await this.ensureCreatedAtUpdatedAtFieldsExist(ds, excludeSchemas) ||
|
|
507
442
|
!await this.ensureDeletedAtFieldsExist(ds, excludeSchemas)) {
|
|
508
|
-
(0,
|
|
443
|
+
(0, status_logging_1.logError)(`Error ensuring ${core_1.EntityInfo.CreatedAtFieldName}, ${core_1.EntityInfo.UpdatedAtFieldName} and ${core_1.EntityInfo.DeletedAtFieldName} fields exist`);
|
|
509
444
|
bSuccess = false;
|
|
510
445
|
}
|
|
511
|
-
(0,
|
|
446
|
+
(0, status_logging_1.logStatus)(` Ensured ${core_1.EntityInfo.CreatedAtFieldName}/${core_1.EntityInfo.UpdatedAtFieldName}/${core_1.EntityInfo.DeletedAtFieldName} fields exist in ${(new Date().getTime() - startTime.getTime()) / 1000} seconds`);
|
|
512
447
|
}
|
|
513
448
|
const step1StartTime = new Date();
|
|
514
449
|
if (!await this.deleteUnneededEntityFields(ds, excludeSchemas)) {
|
|
515
|
-
(0,
|
|
450
|
+
(0, status_logging_1.logError)('Error deleting unneeded entity fields');
|
|
516
451
|
bSuccess = false;
|
|
517
452
|
}
|
|
518
|
-
(0,
|
|
453
|
+
(0, status_logging_1.logStatus)(` Deleted unneeded entity fields in ${(new Date().getTime() - step1StartTime.getTime()) / 1000} seconds`);
|
|
519
454
|
const step2StartTime = new Date();
|
|
520
455
|
if (!await this.updateExistingEntityFieldsFromSchema(ds, excludeSchemas)) {
|
|
521
|
-
(0,
|
|
456
|
+
(0, status_logging_1.logError)('Error updating existing entity fields from schema');
|
|
522
457
|
bSuccess = false;
|
|
523
458
|
}
|
|
524
|
-
(0,
|
|
459
|
+
(0, status_logging_1.logStatus)(` Updated existing entity fields from schema in ${(new Date().getTime() - step2StartTime.getTime()) / 1000} seconds`);
|
|
525
460
|
const step3StartTime = new Date();
|
|
526
461
|
if (!await this.createNewEntityFieldsFromSchema(ds)) { // has its own internal filtering for exclude schema/table so don't pass in
|
|
527
|
-
(0,
|
|
462
|
+
(0, status_logging_1.logError)('Error creating new entity fields from schema');
|
|
528
463
|
bSuccess = false;
|
|
529
464
|
}
|
|
530
|
-
(0,
|
|
465
|
+
(0, status_logging_1.logStatus)(` Created new entity fields from schema in ${(new Date().getTime() - step3StartTime.getTime()) / 1000} seconds`);
|
|
531
466
|
const step4StartTime = new Date();
|
|
532
467
|
if (!await this.setDefaultColumnWidthWhereNeeded(ds, excludeSchemas)) {
|
|
533
|
-
(0,
|
|
468
|
+
(0, status_logging_1.logError)('Error setting default column width where needed');
|
|
534
469
|
bSuccess = false;
|
|
535
470
|
}
|
|
536
|
-
(0,
|
|
471
|
+
(0, status_logging_1.logStatus)(` Set default column width where needed in ${(new Date().getTime() - step4StartTime.getTime()) / 1000} seconds`);
|
|
537
472
|
const step5StartTime = new Date();
|
|
538
473
|
if (!await this.updateEntityFieldDisplayNameWhereNull(ds, excludeSchemas)) {
|
|
539
|
-
(0,
|
|
474
|
+
(0, status_logging_1.logError)('Error updating entity field display name where null');
|
|
540
475
|
bSuccess = false;
|
|
541
476
|
}
|
|
542
|
-
(0,
|
|
477
|
+
(0, status_logging_1.logStatus)(` Updated entity field display name where null in ${(new Date().getTime() - step5StartTime.getTime()) / 1000} seconds`);
|
|
543
478
|
if (!skipEntityFieldValues) {
|
|
544
479
|
const step6StartTime = new Date();
|
|
545
|
-
(0,
|
|
480
|
+
(0, status_logging_1.logStatus)(` Starting to manage entity field values...`);
|
|
546
481
|
if (!await this.manageEntityFieldValues(ds, excludeSchemas)) {
|
|
547
|
-
(0,
|
|
482
|
+
(0, status_logging_1.logError)('Error managing entity field values');
|
|
548
483
|
bSuccess = false;
|
|
549
484
|
}
|
|
550
|
-
(0,
|
|
485
|
+
(0, status_logging_1.logStatus)(` Managed entity field values in ${(new Date().getTime() - step6StartTime.getTime()) / 1000} seconds`);
|
|
551
486
|
}
|
|
552
|
-
(0,
|
|
487
|
+
(0, status_logging_1.logStatus)(` Total time to manage entity fields: ${(new Date().getTime() - startTime.getTime()) / 1000} seconds`);
|
|
553
488
|
return bSuccess;
|
|
554
489
|
}
|
|
555
490
|
/**
|
|
@@ -587,7 +522,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
587
522
|
return overallResult;
|
|
588
523
|
}
|
|
589
524
|
catch (e) {
|
|
590
|
-
(0,
|
|
525
|
+
(0, status_logging_1.logError)(e);
|
|
591
526
|
return false;
|
|
592
527
|
}
|
|
593
528
|
}
|
|
@@ -633,7 +568,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
633
568
|
return overallResult;
|
|
634
569
|
}
|
|
635
570
|
catch (e) {
|
|
636
|
-
(0,
|
|
571
|
+
(0, status_logging_1.logError)(e);
|
|
637
572
|
return false;
|
|
638
573
|
}
|
|
639
574
|
}
|
|
@@ -649,7 +584,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
649
584
|
if (!currentFieldData) {
|
|
650
585
|
// field doesn't exist, let's create it
|
|
651
586
|
const sql = `ALTER TABLE [${entity.SchemaName}].[${entity.BaseTable}] ADD ${fieldName} DATETIMEOFFSET ${allowNull ? 'NULL' : 'NOT NULL DEFAULT GETUTCDATE()'}`;
|
|
652
|
-
await this.
|
|
587
|
+
await this.LogSQLAndExecute(ds, sql, `SQL text to add special date field ${fieldName} to entity ${entity.SchemaName}.${entity.BaseTable}`);
|
|
653
588
|
}
|
|
654
589
|
else {
|
|
655
590
|
// field does exist, let's first check the data type/nullability
|
|
@@ -660,7 +595,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
660
595
|
// modifying the column, and finally adding the default constraint back in.
|
|
661
596
|
await this.dropExistingDefaultConstraint(ds, entity, fieldName);
|
|
662
597
|
const sql = `ALTER TABLE [${entity.SchemaName}].[${entity.BaseTable}] ALTER COLUMN ${fieldName} DATETIMEOFFSET ${allowNull ? 'NULL' : 'NOT NULL'}`;
|
|
663
|
-
await this.
|
|
598
|
+
await this.LogSQLAndExecute(ds, sql, `SQL text to update special date field ${fieldName} in entity ${entity.SchemaName}.${entity.BaseTable}`);
|
|
664
599
|
if (!allowNull)
|
|
665
600
|
await this.createDefaultConstraintForSpecialDateField(ds, entity, fieldName);
|
|
666
601
|
}
|
|
@@ -680,7 +615,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
680
615
|
return true;
|
|
681
616
|
}
|
|
682
617
|
catch (e) {
|
|
683
|
-
(0,
|
|
618
|
+
(0, status_logging_1.logError)(e);
|
|
684
619
|
return false;
|
|
685
620
|
}
|
|
686
621
|
}
|
|
@@ -690,10 +625,10 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
690
625
|
async createDefaultConstraintForSpecialDateField(ds, entity, fieldName) {
|
|
691
626
|
try {
|
|
692
627
|
const sqlAddDefaultConstraint = `ALTER TABLE [${entity.SchemaName}].[${entity.BaseTable}] ADD CONSTRAINT DF_${entity.SchemaName}_${(0, core_1.CodeNameFromString)(entity.BaseTable)}_${fieldName} DEFAULT GETUTCDATE() FOR [${fieldName}]`;
|
|
693
|
-
await this.
|
|
628
|
+
await this.LogSQLAndExecute(ds, sqlAddDefaultConstraint, `SQL text to add default constraint for special date field ${fieldName} in entity ${entity.SchemaName}.${entity.BaseTable}`);
|
|
694
629
|
}
|
|
695
630
|
catch (e) {
|
|
696
|
-
(0,
|
|
631
|
+
(0, status_logging_1.logError)(e);
|
|
697
632
|
}
|
|
698
633
|
}
|
|
699
634
|
/**
|
|
@@ -734,10 +669,10 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
734
669
|
EXEC('ALTER TABLE [${entity.SchemaName}].[${entity.BaseTable}] DROP CONSTRAINT ' + @constraintName);
|
|
735
670
|
END
|
|
736
671
|
`;
|
|
737
|
-
this.
|
|
672
|
+
this.LogSQLAndExecute(ds, sqlDropDefaultConstraint, `SQL text to drop default existing default constraints in entity ${entity.SchemaName}.${entity.BaseTable}`);
|
|
738
673
|
}
|
|
739
674
|
catch (e) {
|
|
740
|
-
(0,
|
|
675
|
+
(0, status_logging_1.logError)(e);
|
|
741
676
|
}
|
|
742
677
|
}
|
|
743
678
|
/**
|
|
@@ -782,8 +717,8 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
782
717
|
try {
|
|
783
718
|
const structuredResult = JSON.parse(resultText);
|
|
784
719
|
if (structuredResult?.entityDescription && structuredResult.entityDescription.length > 0) {
|
|
785
|
-
const
|
|
786
|
-
await this.
|
|
720
|
+
const sSQL = `UPDATE [${(0, config_1.mj_core_schema)()}].Entity SET Description = '${structuredResult.entityDescription}' WHERE Name = '${e}'`;
|
|
721
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to update entity description for entity ${e}`);
|
|
787
722
|
}
|
|
788
723
|
else {
|
|
789
724
|
console.warn(' >>> Advanced Generation Error: LLM returned a blank entity description, skipping entity description for entity ' + e);
|
|
@@ -829,13 +764,13 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
829
764
|
const sDisplayName = this.stripTrailingChars(this.convertCamelCaseToHaveSpaces(field.Name), 'ID', true).trim();
|
|
830
765
|
if (sDisplayName.length > 0 && sDisplayName.toLowerCase().trim() !== field.Name.toLowerCase().trim()) {
|
|
831
766
|
const sSQL = `UPDATE [${(0, config_1.mj_core_schema)()}].EntityField SET ${core_1.EntityInfo.UpdatedAtFieldName}=GETUTCDATE(), DisplayName = '${sDisplayName}' WHERE ID = '${field.ID}'`;
|
|
832
|
-
await this.
|
|
767
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to update display name for field ${field.Name}`);
|
|
833
768
|
}
|
|
834
769
|
}
|
|
835
770
|
return true;
|
|
836
771
|
}
|
|
837
772
|
catch (e) {
|
|
838
|
-
(0,
|
|
773
|
+
(0, status_logging_1.logError)(e);
|
|
839
774
|
return false;
|
|
840
775
|
}
|
|
841
776
|
}
|
|
@@ -849,11 +784,12 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
849
784
|
*/
|
|
850
785
|
async setDefaultColumnWidthWhereNeeded(ds, excludeSchemas) {
|
|
851
786
|
try {
|
|
852
|
-
|
|
787
|
+
const sSQL = `EXEC ${(0, config_1.mj_core_schema)()}.spSetDefaultColumnWidthWhereNeeded @ExcludedSchemaNames='${excludeSchemas.join(',')}'`;
|
|
788
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to set default column width where needed`);
|
|
853
789
|
return true;
|
|
854
790
|
}
|
|
855
791
|
catch (e) {
|
|
856
|
-
(0,
|
|
792
|
+
(0, status_logging_1.logError)(e);
|
|
857
793
|
return false;
|
|
858
794
|
}
|
|
859
795
|
}
|
|
@@ -941,7 +877,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
941
877
|
* @param n - the new field
|
|
942
878
|
* @returns
|
|
943
879
|
*/
|
|
944
|
-
getPendingEntityFieldINSERTSQL(n) {
|
|
880
|
+
getPendingEntityFieldINSERTSQL(newEntityFieldUUID, n) {
|
|
945
881
|
const bDefaultInView = (n.FieldName?.trim().toLowerCase() === 'id' ||
|
|
946
882
|
n.FieldName?.trim().toLowerCase() === 'name' ||
|
|
947
883
|
n.Sequence <= config_1.configInfo.newEntityDefaults?.IncludeFirstNFieldsAsDefaultInView ||
|
|
@@ -965,6 +901,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
965
901
|
return `
|
|
966
902
|
INSERT INTO [${(0, config_1.mj_core_schema)()}].EntityField
|
|
967
903
|
(
|
|
904
|
+
ID,
|
|
968
905
|
EntityID,
|
|
969
906
|
Sequence,
|
|
970
907
|
Name,
|
|
@@ -991,6 +928,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
991
928
|
)
|
|
992
929
|
VALUES
|
|
993
930
|
(
|
|
931
|
+
'${newEntityFieldUUID}',
|
|
994
932
|
'${n.EntityID}',
|
|
995
933
|
${n.Sequence},
|
|
996
934
|
'${n.FieldName}',
|
|
@@ -1050,8 +988,9 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1050
988
|
if (n.EntityID !== null && n.EntityID !== undefined && n.EntityID.length > 0) {
|
|
1051
989
|
// need to check for null entity id = that is because the above query can return candidate Entity Fields but the entities may not have been created if the entities
|
|
1052
990
|
// that would have been created violate rules - such as not having an ID column, etc.
|
|
1053
|
-
const
|
|
1054
|
-
|
|
991
|
+
const newEntityFieldUUID = this.createNewUUID();
|
|
992
|
+
const sSQLInsert = this.getPendingEntityFieldINSERTSQL(newEntityFieldUUID, n);
|
|
993
|
+
await this.LogSQLAndExecute(ds, sSQLInsert, `SQL text to insert new entity field`);
|
|
1055
994
|
// if we get here, we're okay, otherwise we have an exception, which we want as it blows up transaction
|
|
1056
995
|
}
|
|
1057
996
|
}
|
|
@@ -1059,7 +998,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1059
998
|
return true;
|
|
1060
999
|
}
|
|
1061
1000
|
catch (e) {
|
|
1062
|
-
(0,
|
|
1001
|
+
(0, status_logging_1.logError)(e);
|
|
1063
1002
|
return false;
|
|
1064
1003
|
}
|
|
1065
1004
|
}
|
|
@@ -1075,41 +1014,44 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1075
1014
|
const sSQL = `EXEC [${(0, config_1.mj_core_schema)()}].spUpdateEntityFieldRelatedEntityNameFieldMap
|
|
1076
1015
|
@EntityFieldID='${entityFieldID}',
|
|
1077
1016
|
@RelatedEntityNameFieldMap='${relatedEntityNameFieldMap}'`;
|
|
1078
|
-
await
|
|
1017
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to update entity field related entity name field map for entity field ID ${entityFieldID}`);
|
|
1079
1018
|
return true;
|
|
1080
1019
|
}
|
|
1081
1020
|
catch (e) {
|
|
1082
|
-
(0,
|
|
1021
|
+
(0, status_logging_1.logError)(e);
|
|
1083
1022
|
return false;
|
|
1084
1023
|
}
|
|
1085
1024
|
}
|
|
1086
1025
|
async updateExistingEntitiesFromSchema(ds, excludeSchemas) {
|
|
1087
1026
|
try {
|
|
1088
|
-
|
|
1027
|
+
const sSQL = `EXEC [${(0, config_1.mj_core_schema)()}].spUpdateExistingEntitiesFromSchema @ExcludedSchemaNames='${excludeSchemas.join(',')}'`;
|
|
1028
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to update existing entities from schema`);
|
|
1089
1029
|
return true;
|
|
1090
1030
|
}
|
|
1091
1031
|
catch (e) {
|
|
1092
|
-
(0,
|
|
1032
|
+
(0, status_logging_1.logError)(e);
|
|
1093
1033
|
return false;
|
|
1094
1034
|
}
|
|
1095
1035
|
}
|
|
1096
1036
|
async updateExistingEntityFieldsFromSchema(ds, excludeSchemas) {
|
|
1097
1037
|
try {
|
|
1098
|
-
|
|
1038
|
+
const sSQL = `EXEC [${(0, config_1.mj_core_schema)()}].spUpdateExistingEntityFieldsFromSchema @ExcludedSchemaNames='${excludeSchemas.join(',')}'`;
|
|
1039
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to update existingg entity fields from schema`);
|
|
1099
1040
|
return true;
|
|
1100
1041
|
}
|
|
1101
1042
|
catch (e) {
|
|
1102
|
-
(0,
|
|
1043
|
+
(0, status_logging_1.logError)(e);
|
|
1103
1044
|
return false;
|
|
1104
1045
|
}
|
|
1105
1046
|
}
|
|
1106
1047
|
async deleteUnneededEntityFields(ds, excludeSchemas) {
|
|
1107
1048
|
try {
|
|
1108
|
-
|
|
1049
|
+
const sSQL = `EXEC [${(0, config_1.mj_core_schema)()}].spDeleteUnneededEntityFields @ExcludedSchemaNames='${excludeSchemas.join(',')}'`;
|
|
1050
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to delete unneeded entity fields`);
|
|
1109
1051
|
return true;
|
|
1110
1052
|
}
|
|
1111
1053
|
catch (e) {
|
|
1112
|
-
(0,
|
|
1054
|
+
(0, status_logging_1.logError)(e);
|
|
1113
1055
|
return false;
|
|
1114
1056
|
}
|
|
1115
1057
|
}
|
|
@@ -1134,15 +1076,20 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1134
1076
|
// we have parsed values from the check constraint, so sync them with the entity field values
|
|
1135
1077
|
await this.syncEntityFieldValues(ds, r.EntityFieldID, parsedValues, allEntityFieldValues);
|
|
1136
1078
|
// finally, make sure the ValueListType column within the EntityField table is set to "List" because for check constraints we only allow the values specified in the list.
|
|
1137
|
-
|
|
1138
|
-
|
|
1079
|
+
// check to see if the ValueListType is already set to "List", if not, update it
|
|
1080
|
+
const sSQLCheck = `SELECT ValueListType FROM [${(0, config_1.mj_core_schema)()}].EntityField WHERE ID='${r.EntityFieldID}'`;
|
|
1081
|
+
const checkResult = await ds.query(sSQLCheck);
|
|
1082
|
+
if (checkResult && checkResult.length > 0 && checkResult[0].ValueListType.trim().toLowerCase() !== 'list') {
|
|
1083
|
+
const sSQL = `UPDATE [${(0, config_1.mj_core_schema)()}].EntityField SET ValueListType='List' WHERE ID='${r.EntityFieldID}'`;
|
|
1084
|
+
await this.LogSQLAndExecute(ds, sSQL, `SQL text to update ValueListType for entity field ID ${r.EntityFieldID}`);
|
|
1085
|
+
}
|
|
1139
1086
|
}
|
|
1140
1087
|
}
|
|
1141
1088
|
}
|
|
1142
1089
|
return true;
|
|
1143
1090
|
}
|
|
1144
1091
|
catch (e) {
|
|
1145
|
-
(0,
|
|
1092
|
+
(0, status_logging_1.logError)(e);
|
|
1146
1093
|
return false;
|
|
1147
1094
|
}
|
|
1148
1095
|
}
|
|
@@ -1158,7 +1105,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1158
1105
|
if (!possibleValues.find(v => v === ev.Value)) {
|
|
1159
1106
|
// delete the value from the database
|
|
1160
1107
|
const sSQLDelete = `DELETE FROM [${(0, config_1.mj_core_schema)()}].EntityFieldValue WHERE ID='${ev.ID}'`;
|
|
1161
|
-
await this.
|
|
1108
|
+
await this.LogSQLAndExecute(ds, sSQLDelete, `SQL text to delete entity field value ID ${ev.ID}`);
|
|
1162
1109
|
numRemoved++;
|
|
1163
1110
|
}
|
|
1164
1111
|
}
|
|
@@ -1171,7 +1118,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1171
1118
|
(EntityFieldID, Sequence, Value, Code)
|
|
1172
1119
|
VALUES
|
|
1173
1120
|
('${entityFieldID}', ${1 + possibleValues.indexOf(v)}, '${v}', '${v}')`;
|
|
1174
|
-
await this.
|
|
1121
|
+
await this.LogSQLAndExecute(ds, sSQLInsert, `SQL text to insert entity field values`);
|
|
1175
1122
|
numAdded++;
|
|
1176
1123
|
}
|
|
1177
1124
|
}
|
|
@@ -1182,7 +1129,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1182
1129
|
if (ev && ev.Sequence !== 1 + possibleValues.indexOf(v)) {
|
|
1183
1130
|
// update the sequence to match the order in the possible values list, if it doesn't already match
|
|
1184
1131
|
const sSQLUpdate = `UPDATE [${(0, config_1.mj_core_schema)()}].EntityFieldValue SET Sequence=${1 + possibleValues.indexOf(v)} WHERE ID='${ev.ID}'`;
|
|
1185
|
-
await this.
|
|
1132
|
+
await this.LogSQLAndExecute(ds, sSQLUpdate, `SQL text to update entity field value sequence`);
|
|
1186
1133
|
numUpdated++;
|
|
1187
1134
|
}
|
|
1188
1135
|
}
|
|
@@ -1190,7 +1137,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1190
1137
|
return true;
|
|
1191
1138
|
}
|
|
1192
1139
|
catch (e) {
|
|
1193
|
-
(0,
|
|
1140
|
+
(0, status_logging_1.logError)(e);
|
|
1194
1141
|
return false;
|
|
1195
1142
|
}
|
|
1196
1143
|
}
|
|
@@ -1201,7 +1148,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1201
1148
|
// Note: Assuming fieldName does not contain regex special characters; otherwise, it needs to be escaped as well.
|
|
1202
1149
|
const structureRegex = new RegExp(`^\\(\\[${fieldName}\\]='[^']+'(?: OR \\[${fieldName}\\]='[^']+?')+\\)$`);
|
|
1203
1150
|
if (!structureRegex.test(constraintDefinition)) {
|
|
1204
|
-
(0,
|
|
1151
|
+
(0, status_logging_1.logWarning)(` Can't extract value list from [${entityName}].[${fieldName}]. The check constraint does not match the simple OR condition pattern or field name does not match: ${constraintDefinition}`);
|
|
1205
1152
|
return null;
|
|
1206
1153
|
}
|
|
1207
1154
|
// Regular expression to match the values within the single quotes specifically for the field
|
|
@@ -1341,6 +1288,9 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1341
1288
|
simpleNewEntityName(tableName) {
|
|
1342
1289
|
return this.convertCamelCaseToHaveSpaces(this.generatePluralName(tableName));
|
|
1343
1290
|
}
|
|
1291
|
+
createNewUUID() {
|
|
1292
|
+
return (0, uuid_1.v4)();
|
|
1293
|
+
}
|
|
1344
1294
|
async createNewEntity(ds, newEntity, md) {
|
|
1345
1295
|
try {
|
|
1346
1296
|
const { shouldCreate, validationMessage } = await this.shouldCreateNewEntity(ds, newEntity);
|
|
@@ -1358,41 +1308,46 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1358
1308
|
(0, core_1.LogError)(` >>>> WARNING: Entity name already exists, so using ${newEntityName} instead. If you did not intend for this, please rename the ${newEntity.SchemaName}.${newEntity.TableName} table in the database.`);
|
|
1359
1309
|
}
|
|
1360
1310
|
const isNewSchema = await this.isSchemaNew(ds, newEntity.SchemaName);
|
|
1361
|
-
const
|
|
1362
|
-
const
|
|
1363
|
-
|
|
1364
|
-
if (!newEntityID) {
|
|
1365
|
-
throw new Error(`Failed to create new entity ${newEntityName} for table ${newEntity.SchemaName}.${newEntity.TableName}`);
|
|
1366
|
-
}
|
|
1311
|
+
const newEntityID = this.createNewUUID();
|
|
1312
|
+
const sSQLInsert = this.createNewEntityInsertSQL(newEntityID, newEntityName, newEntity, suffix);
|
|
1313
|
+
await this.LogSQLAndExecute(ds, sSQLInsert, `SQL generated to create new entity ${newEntityName}`);
|
|
1367
1314
|
// if we get here we created a new entity safely, otherwise we get exception
|
|
1368
1315
|
// add it to the new entity list
|
|
1369
1316
|
ManageMetadataBase_1.newEntityList.push(newEntityName);
|
|
1370
1317
|
// next, check if this entity is in a schema that is new (e.g. no other entities have been added to this schema yet), if so and if
|
|
1371
1318
|
// our config option is set to create new applications from new schemas, then create a new application for this schema
|
|
1319
|
+
let appUUID = '';
|
|
1372
1320
|
if (isNewSchema && config_1.configInfo.newSchemaDefaults.CreateNewApplicationWithSchemaName) {
|
|
1373
1321
|
// new schema and config option is to create a new application from the schema name so do that
|
|
1374
|
-
if
|
|
1375
|
-
|
|
1322
|
+
// check to see if the app already exists
|
|
1323
|
+
appUUID = await this.getApplicationIDForSchema(ds, newEntity.SchemaName);
|
|
1324
|
+
if (!appUUID || appUUID.length === 0 || appUUID.trim().length === 0) {
|
|
1325
|
+
// doesn't already exist, so create it
|
|
1326
|
+
appUUID = this.createNewUUID();
|
|
1327
|
+
await this.createNewApplication(ds, appUUID, newEntity.SchemaName);
|
|
1376
1328
|
await md.Refresh(); // refresh now since we've added a new application, not super efficient to do this for each new application but that won't happen super
|
|
1377
|
-
// often so not a huge deal, would be more efficient do this in batch after all new apps are created but
|
|
1329
|
+
// often so not a huge deal, would be more efficient do this in batch after all new apps are created but that would be an over optimization IMO
|
|
1378
1330
|
}
|
|
1379
1331
|
}
|
|
1380
1332
|
else {
|
|
1381
1333
|
// not a new schema, attempt to look up the application for this schema
|
|
1382
|
-
await this.getApplicationIDForSchema(ds, newEntity.SchemaName);
|
|
1334
|
+
appUUID = await this.getApplicationIDForSchema(ds, newEntity.SchemaName);
|
|
1383
1335
|
}
|
|
1384
|
-
if (
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
const app = md.Applications.find(a => a.Name.trim().toLowerCase() === appName.trim().toLowerCase());
|
|
1388
|
-
if (app) {
|
|
1336
|
+
if (appUUID && appUUID.length > 0) {
|
|
1337
|
+
if (config_1.configInfo.newEntityDefaults.AddToApplicationWithSchemaName) {
|
|
1338
|
+
// only do this if the configuration setting is set to add new entities to applications for schema names
|
|
1389
1339
|
const sSQLInsertApplicationEntity = `INSERT INTO ${(0, config_1.mj_core_schema)()}.ApplicationEntity
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
this.
|
|
1340
|
+
(ApplicationID, EntityID, Sequence) VALUES
|
|
1341
|
+
('${appUUID}', '${newEntityID}', (SELECT ISNULL(MAX(Sequence),0)+1 FROM ${(0, config_1.mj_core_schema)()}.ApplicationEntity WHERE ApplicationID = '${appUUID}'))`;
|
|
1342
|
+
this.LogSQLAndExecute(ds, sSQLInsertApplicationEntity, `SQL generated to add new entity ${newEntityName} to application ID: '${appUUID}'`);
|
|
1343
|
+
}
|
|
1344
|
+
else {
|
|
1345
|
+
// this is NOT an error condition, we do have an application UUID, but the configuration setting is to NOT add new entities to applications for schema names
|
|
1393
1346
|
}
|
|
1394
|
-
|
|
1395
|
-
|
|
1347
|
+
}
|
|
1348
|
+
else {
|
|
1349
|
+
// this is an error condition, we should have an application for this schema, if we don't, log an error, non fatal, but should be logged
|
|
1350
|
+
(0, core_1.LogError)(` >>>> ERROR: Unable to add new entity ${newEntityName} to an application because an Application record for schema ${newEntity.SchemaName} does not exist.`);
|
|
1396
1351
|
}
|
|
1397
1352
|
// next up, we need to check if we're configured to add permissions for new entities, and if so, add them
|
|
1398
1353
|
if (config_1.configInfo.newEntityDefaults.PermissionDefaults && config_1.configInfo.newEntityDefaults.PermissionDefaults.AutoAddPermissionsForNewEntities) {
|
|
@@ -1404,7 +1359,7 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1404
1359
|
const sSQLInsertPermission = `INSERT INTO ${(0, config_1.mj_core_schema)()}.EntityPermission
|
|
1405
1360
|
(EntityID, RoleID, CanRead, CanCreate, CanUpdate, CanDelete) VALUES
|
|
1406
1361
|
('${newEntityID}', '${RoleID}', ${p.CanRead ? 1 : 0}, ${p.CanCreate ? 1 : 0}, ${p.CanUpdate ? 1 : 0}, ${p.CanDelete ? 1 : 0})`;
|
|
1407
|
-
await this.
|
|
1362
|
+
await this.LogSQLAndExecute(ds, sSQLInsertPermission, `SQL generated to add new permission for entity ${newEntityName} for role ${p.RoleName}`);
|
|
1408
1363
|
}
|
|
1409
1364
|
else
|
|
1410
1365
|
(0, core_1.LogError)(` >>>> ERROR: Unable to find Role ID for role ${p.RoleName} to add permissions for new entity ${newEntityName}`);
|
|
@@ -1427,9 +1382,9 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1427
1382
|
const result = await ds.query(sSQL);
|
|
1428
1383
|
return result && result.length > 0 ? result[0].Count === 0 : true;
|
|
1429
1384
|
}
|
|
1430
|
-
async createNewApplication(ds, appName) {
|
|
1431
|
-
const sSQL = "INSERT INTO [" + (0, config_1.mj_core_schema)() + "].Application (Name, Description) VALUES ('" + appName + "', 'Generated for
|
|
1432
|
-
const result = await this.
|
|
1385
|
+
async createNewApplication(ds, appID, appName) {
|
|
1386
|
+
const sSQL = "INSERT INTO [" + (0, config_1.mj_core_schema)() + "].Application (ID, Name, Description) VALUES ('" + appID + "', '" + appName + "', 'Generated for schema')";
|
|
1387
|
+
const result = await this.LogSQLAndExecute(ds, sSQL, `SQL generated to create new application ${appName}`);
|
|
1433
1388
|
return result && result.length > 0 ? result[0].ID : null;
|
|
1434
1389
|
}
|
|
1435
1390
|
async applicationExists(ds, applicationName) {
|
|
@@ -1442,12 +1397,12 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1442
1397
|
const result = await ds.query(sSQL);
|
|
1443
1398
|
return result && result.length > 0 ? result[0].ID : null;
|
|
1444
1399
|
}
|
|
1445
|
-
createNewEntityInsertSQL(newEntityName, newEntity, newEntitySuffix) {
|
|
1400
|
+
createNewEntityInsertSQL(newEntityUUID, newEntityName, newEntity, newEntitySuffix) {
|
|
1446
1401
|
const newEntityDefaults = config_1.configInfo.newEntityDefaults;
|
|
1447
1402
|
const newEntityDescriptionEscaped = newEntity.Description ? `'${newEntity.Description.replace(/'/g, "''")}` : null;
|
|
1448
1403
|
const sSQLInsert = `
|
|
1449
|
-
DECLARE @InsertedRow TABLE ([ID] UNIQUEIDENTIFIER)
|
|
1450
1404
|
INSERT INTO [${(0, config_1.mj_core_schema)()}].Entity (
|
|
1405
|
+
ID,
|
|
1451
1406
|
Name,
|
|
1452
1407
|
Description,
|
|
1453
1408
|
NameSuffix,
|
|
@@ -1465,8 +1420,8 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1465
1420
|
${newEntityDefaults.AllowDeleteAPI === undefined ? '' : ', AllowDeleteAPI'}
|
|
1466
1421
|
${newEntityDefaults.UserViewMaxRows === undefined ? '' : ', UserViewMaxRows'}
|
|
1467
1422
|
)
|
|
1468
|
-
OUTPUT INSERTED.[ID] INTO @InsertedRow
|
|
1469
1423
|
VALUES (
|
|
1424
|
+
'${newEntityUUID}',
|
|
1470
1425
|
'${newEntityName}',
|
|
1471
1426
|
${newEntityDescriptionEscaped ? newEntityDescriptionEscaped : 'NULL' /*if no description, then null*/},
|
|
1472
1427
|
${newEntitySuffix && newEntitySuffix.length > 0 ? `'${newEntitySuffix}'` : 'NULL'},
|
|
@@ -1484,7 +1439,6 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1484
1439
|
${newEntityDefaults.AllowDeleteAPI === undefined ? '' : ', ' + (newEntityDefaults.AllowDeleteAPI ? '1' : '0')}
|
|
1485
1440
|
${newEntityDefaults.UserViewMaxRows === undefined ? '' : ', ' + (newEntityDefaults.UserViewMaxRows)}
|
|
1486
1441
|
)
|
|
1487
|
-
SELECT * FROM [__mj].vwEntities WHERE [ID] = (SELECT [ID] FROM @InsertedRow)
|
|
1488
1442
|
`;
|
|
1489
1443
|
return sSQLInsert;
|
|
1490
1444
|
}
|
|
@@ -1551,15 +1505,11 @@ let ManageMetadataBase = ManageMetadataBase_1 = class ManageMetadataBase {
|
|
|
1551
1505
|
* Note that in order to append to the log file, ManageMetadataBase.manageMetaDataLogging must be called first.
|
|
1552
1506
|
* @param ds - The DataSource object to use to execute the query.
|
|
1553
1507
|
* @param query - The SQL query to execute.
|
|
1554
|
-
* @param appendToLogFile - If true, the query will be appended to the log file.
|
|
1555
1508
|
* @param description - A description of the query to append to the log file.
|
|
1556
1509
|
* @returns - The result of the query execution.
|
|
1557
1510
|
*/
|
|
1558
|
-
async
|
|
1559
|
-
|
|
1560
|
-
this.appendToFile(query, description);
|
|
1561
|
-
}
|
|
1562
|
-
return ds.query(query);
|
|
1511
|
+
async LogSQLAndExecute(ds, query, description) {
|
|
1512
|
+
sql_logging_1.SQLLogging.LogSQLAndExecute(ds, query, description);
|
|
1563
1513
|
}
|
|
1564
1514
|
};
|
|
1565
1515
|
exports.ManageMetadataBase = ManageMetadataBase;
|