@memberjunction/codegen-lib 6.2.0-edge.0 → 6.2.0-edge.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/dist/Angular/angular-codegen.d.ts +6 -0
- package/dist/Angular/angular-codegen.d.ts.map +1 -1
- package/dist/Angular/angular-codegen.js +26 -14
- package/dist/Angular/angular-codegen.js.map +1 -1
- package/dist/Config/config.d.ts +45 -2
- package/dist/Config/config.d.ts.map +1 -1
- package/dist/Config/config.js +116 -39
- package/dist/Config/config.js.map +1 -1
- package/dist/Config/db-connection.d.ts +4 -0
- package/dist/Config/db-connection.d.ts.map +1 -1
- package/dist/Config/db-connection.js +11 -3
- package/dist/Config/db-connection.js.map +1 -1
- package/dist/Config/pg-connection.d.ts +2 -0
- package/dist/Config/pg-connection.d.ts.map +1 -1
- package/dist/Config/pg-connection.js +5 -1
- package/dist/Config/pg-connection.js.map +1 -1
- package/dist/Config/schema-output.d.ts +8 -0
- package/dist/Config/schema-output.d.ts.map +1 -1
- package/dist/Config/schema-output.js +19 -7
- package/dist/Config/schema-output.js.map +1 -1
- package/dist/Database/__tests__/exclude-schema-permissions.test.js +3 -3
- package/dist/Database/codeGenDatabaseProvider.d.ts +16 -1
- package/dist/Database/codeGenDatabaseProvider.d.ts.map +1 -1
- package/dist/Database/codeGenDatabaseProvider.js +37 -9
- package/dist/Database/codeGenDatabaseProvider.js.map +1 -1
- package/dist/Database/dbSchema.d.ts +4 -0
- package/dist/Database/dbSchema.d.ts.map +1 -1
- package/dist/Database/dbSchema.js +17 -9
- package/dist/Database/dbSchema.js.map +1 -1
- package/dist/Database/entity-field-change-tracking.d.ts +4 -0
- package/dist/Database/entity-field-change-tracking.d.ts.map +1 -1
- package/dist/Database/entity-field-change-tracking.js +12 -4
- package/dist/Database/entity-field-change-tracking.js.map +1 -1
- package/dist/Database/exclude-tables.d.ts +2 -0
- package/dist/Database/exclude-tables.d.ts.map +1 -1
- package/dist/Database/exclude-tables.js +5 -1
- package/dist/Database/exclude-tables.js.map +1 -1
- package/dist/Database/field-metadata-lock.d.ts +8 -6
- package/dist/Database/field-metadata-lock.d.ts.map +1 -1
- package/dist/Database/field-metadata-lock.js +29 -25
- package/dist/Database/field-metadata-lock.js.map +1 -1
- package/dist/Database/heal-schema-params.d.ts +14 -2
- package/dist/Database/heal-schema-params.d.ts.map +1 -1
- package/dist/Database/heal-schema-params.js +21 -5
- package/dist/Database/heal-schema-params.js.map +1 -1
- package/dist/Database/manage-metadata.d.ts +119 -3
- package/dist/Database/manage-metadata.d.ts.map +1 -1
- package/dist/Database/manage-metadata.js +529 -364
- package/dist/Database/manage-metadata.js.map +1 -1
- package/dist/Database/materializationAnalysis.d.ts +61 -2
- package/dist/Database/materializationAnalysis.d.ts.map +1 -1
- package/dist/Database/materializationAnalysis.js +43 -23
- package/dist/Database/materializationAnalysis.js.map +1 -1
- package/dist/Database/materializationBroadRender.d.ts +5 -3
- package/dist/Database/materializationBroadRender.d.ts.map +1 -1
- package/dist/Database/materializationBroadRender.js +17 -13
- package/dist/Database/materializationBroadRender.js.map +1 -1
- package/dist/Database/materializationDrift.d.ts +2 -0
- package/dist/Database/materializationDrift.d.ts.map +1 -1
- package/dist/Database/materializationDrift.js +5 -1
- package/dist/Database/materializationDrift.js.map +1 -1
- package/dist/Database/materializationParamClassifier.d.ts +17 -2
- package/dist/Database/materializationParamClassifier.d.ts.map +1 -1
- package/dist/Database/materializationParamClassifier.js +22 -10
- package/dist/Database/materializationParamClassifier.js.map +1 -1
- package/dist/Database/materializationParamVerifier.d.ts +2 -0
- package/dist/Database/materializationParamVerifier.d.ts.map +1 -1
- package/dist/Database/materializationParamVerifier.js +18 -14
- package/dist/Database/materializationParamVerifier.js.map +1 -1
- package/dist/Database/materializationSqlAst.d.ts +19 -1
- package/dist/Database/materializationSqlAst.d.ts.map +1 -1
- package/dist/Database/materializationSqlAst.js +53 -17
- package/dist/Database/materializationSqlAst.js.map +1 -1
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js +30 -30
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js.map +1 -1
- package/dist/Database/providers/postgresql/metadataSupportObjects.d.ts +2 -0
- package/dist/Database/providers/postgresql/metadataSupportObjects.d.ts.map +1 -1
- package/dist/Database/providers/postgresql/metadataSupportObjects.js +5 -1
- package/dist/Database/providers/postgresql/metadataSupportObjects.js.map +1 -1
- package/dist/Database/providers/postgresql/viewDependencyCapture.d.ts +10 -0
- package/dist/Database/providers/postgresql/viewDependencyCapture.d.ts.map +1 -1
- package/dist/Database/providers/postgresql/viewDependencyCapture.js +25 -5
- package/dist/Database/providers/postgresql/viewDependencyCapture.js.map +1 -1
- package/dist/Database/providers/postgresql/viewFallback.d.ts +11 -7
- package/dist/Database/providers/postgresql/viewFallback.d.ts.map +1 -1
- package/dist/Database/providers/postgresql/viewFallback.js +18 -12
- package/dist/Database/providers/postgresql/viewFallback.js.map +1 -1
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js +13 -13
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js.map +1 -1
- package/dist/Database/reconcileFieldLevelSecurity.d.ts +2 -0
- package/dist/Database/reconcileFieldLevelSecurity.d.ts.map +1 -1
- package/dist/Database/reconcileFieldLevelSecurity.js +5 -1
- package/dist/Database/reconcileFieldLevelSecurity.js.map +1 -1
- package/dist/Database/reorder-columns.d.ts +2 -0
- package/dist/Database/reorder-columns.d.ts.map +1 -1
- package/dist/Database/reorder-columns.js +5 -1
- package/dist/Database/reorder-columns.js.map +1 -1
- package/dist/Database/schema-filters.d.ts +6 -0
- package/dist/Database/schema-filters.d.ts.map +1 -1
- package/dist/Database/schema-filters.js +17 -5
- package/dist/Database/schema-filters.js.map +1 -1
- package/dist/Database/schema-scope.d.ts +4 -0
- package/dist/Database/schema-scope.d.ts.map +1 -1
- package/dist/Database/schema-scope.js +13 -5
- package/dist/Database/schema-scope.js.map +1 -1
- package/dist/Database/search-guardrails.d.ts +42 -0
- package/dist/Database/search-guardrails.d.ts.map +1 -1
- package/dist/Database/search-guardrails.js +57 -17
- package/dist/Database/search-guardrails.js.map +1 -1
- package/dist/Database/sql.d.ts +20 -0
- package/dist/Database/sql.d.ts.map +1 -1
- package/dist/Database/sql.js +72 -32
- package/dist/Database/sql.js.map +1 -1
- package/dist/Database/sql_codegen.d.ts +92 -0
- package/dist/Database/sql_codegen.d.ts.map +1 -1
- package/dist/Database/sql_codegen.js +197 -113
- package/dist/Database/sql_codegen.js.map +1 -1
- package/dist/EntityNameScanner/EntityNameScanner.d.ts +16 -0
- package/dist/EntityNameScanner/EntityNameScanner.d.ts.map +1 -1
- package/dist/EntityNameScanner/EntityNameScanner.js +47 -15
- package/dist/EntityNameScanner/EntityNameScanner.js.map +1 -1
- package/dist/EntityNameScanner/HtmlEntityNameScanner.d.ts +6 -0
- package/dist/EntityNameScanner/HtmlEntityNameScanner.d.ts.map +1 -1
- package/dist/EntityNameScanner/HtmlEntityNameScanner.js +19 -7
- package/dist/EntityNameScanner/HtmlEntityNameScanner.js.map +1 -1
- package/dist/EntityNameScanner/MetadataNameScanner.d.ts +6 -0
- package/dist/EntityNameScanner/MetadataNameScanner.d.ts.map +1 -1
- package/dist/EntityNameScanner/MetadataNameScanner.js +19 -7
- package/dist/EntityNameScanner/MetadataNameScanner.js.map +1 -1
- package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts +6 -0
- package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts.map +1 -1
- package/dist/Manifest/GenerateClassRegistrationsManifest.js +16 -4
- package/dist/Manifest/GenerateClassRegistrationsManifest.js.map +1 -1
- package/dist/Misc/action_subclasses_codegen.d.ts +4 -0
- package/dist/Misc/action_subclasses_codegen.d.ts.map +1 -1
- package/dist/Misc/action_subclasses_codegen.js +11 -3
- package/dist/Misc/action_subclasses_codegen.js.map +1 -1
- package/dist/Misc/advanced_generation.d.ts +48 -2
- package/dist/Misc/advanced_generation.d.ts.map +1 -1
- package/dist/Misc/advanced_generation.js +53 -15
- package/dist/Misc/advanced_generation.js.map +1 -1
- package/dist/Misc/codegen-reporter.d.ts +53 -0
- package/dist/Misc/codegen-reporter.d.ts.map +1 -1
- package/dist/Misc/codegen-reporter.js +106 -22
- package/dist/Misc/codegen-reporter.js.map +1 -1
- package/dist/Misc/createNewUser.d.ts +6 -0
- package/dist/Misc/createNewUser.d.ts.map +1 -1
- package/dist/Misc/createNewUser.js +5 -1
- package/dist/Misc/createNewUser.js.map +1 -1
- package/dist/Misc/entity_subclasses_codegen.d.ts +8 -0
- package/dist/Misc/entity_subclasses_codegen.d.ts.map +1 -1
- package/dist/Misc/entity_subclasses_codegen.js +52 -36
- package/dist/Misc/entity_subclasses_codegen.js.map +1 -1
- package/dist/Misc/externalTypeMapping.d.ts +2 -0
- package/dist/Misc/externalTypeMapping.d.ts.map +1 -1
- package/dist/Misc/externalTypeMapping.js +5 -1
- package/dist/Misc/externalTypeMapping.js.map +1 -1
- package/dist/Misc/file-write.d.ts +2 -0
- package/dist/Misc/file-write.d.ts.map +1 -1
- package/dist/Misc/file-write.js +5 -1
- package/dist/Misc/file-write.js.map +1 -1
- package/dist/Misc/graphql_server_codegen.d.ts +10 -0
- package/dist/Misc/graphql_server_codegen.d.ts.map +1 -1
- package/dist/Misc/graphql_server_codegen.js +46 -26
- package/dist/Misc/graphql_server_codegen.js.map +1 -1
- package/dist/Misc/remote_operations_codegen.d.ts +12 -0
- package/dist/Misc/remote_operations_codegen.d.ts.map +1 -1
- package/dist/Misc/remote_operations_codegen.js +21 -5
- package/dist/Misc/remote_operations_codegen.js.map +1 -1
- package/dist/Misc/runCommand.d.ts +6 -0
- package/dist/Misc/runCommand.d.ts.map +1 -1
- package/dist/Misc/runCommand.js +16 -4
- package/dist/Misc/runCommand.js.map +1 -1
- package/dist/Misc/schema-emit.d.ts +28 -0
- package/dist/Misc/schema-emit.d.ts.map +1 -1
- package/dist/Misc/schema-emit.js +75 -23
- package/dist/Misc/schema-emit.js.map +1 -1
- package/dist/Misc/sql_logging.d.ts +31 -9
- package/dist/Misc/sql_logging.d.ts.map +1 -1
- package/dist/Misc/sql_logging.js +95 -51
- package/dist/Misc/sql_logging.js.map +1 -1
- package/dist/Misc/sql_text.d.ts +4 -0
- package/dist/Misc/sql_text.d.ts.map +1 -1
- package/dist/Misc/sql_text.js +10 -2
- package/dist/Misc/sql_text.js.map +1 -1
- package/dist/Misc/status_logging.d.ts +36 -0
- package/dist/Misc/status_logging.d.ts.map +1 -1
- package/dist/Misc/status_logging.js +95 -23
- package/dist/Misc/status_logging.js.map +1 -1
- package/dist/Misc/system_integrity.js +4 -4
- package/dist/Misc/system_integrity.js.map +1 -1
- package/dist/Misc/temp_batch_file.d.ts +12 -0
- package/dist/Misc/temp_batch_file.d.ts.map +1 -1
- package/dist/Misc/temp_batch_file.js +35 -11
- package/dist/Misc/temp_batch_file.js.map +1 -1
- package/dist/Misc/util.d.ts +33 -0
- package/dist/Misc/util.d.ts.map +1 -1
- package/dist/Misc/util.js +53 -13
- package/dist/Misc/util.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.d.ts +11 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +9 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/runCodeGen.d.ts +6 -0
- package/dist/runCodeGen.d.ts.map +1 -1
- package/dist/runCodeGen.js +150 -138
- package/dist/runCodeGen.js.map +1 -1
- package/package.json +29 -29
package/dist/runCodeGen.js
CHANGED
|
@@ -10,25 +10,25 @@ import { GraphQLServerGeneratorBase } from './Misc/graphql_server_codegen.js';
|
|
|
10
10
|
import { SQLCodeGenBase } from './Database/sql_codegen.js';
|
|
11
11
|
import { EntitySubClassGeneratorBase } from './Misc/entity_subclasses_codegen.js';
|
|
12
12
|
import { ManageMetadataBase } from './Database/manage-metadata.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
13
|
+
import { ApplyIncludeSchemaScope } from './Database/schema-scope.js';
|
|
14
|
+
import { PartitionEntitiesByOutputDirectory } from './Config/schema-output.js';
|
|
15
|
+
import { OutputDir, Commands, configInfo, GetSettingValue, DbPlatform, GetExternalEntitySchemas, InitializeConfig, ApplyInProcessAdvancedGenerationPolicy, IN_PROCESS_ADVANCED_GENERATION_ENV } from './Config/config.js';
|
|
16
|
+
import { ResolveDirtySchemasForEmit, SchemaKey } from './Misc/schema-emit.js';
|
|
17
17
|
import { EmitStats } from './Misc/emit-stats.js';
|
|
18
|
-
import { logError, logStatus,
|
|
18
|
+
import { logError, logStatus, LogWarning, StartSpinner, UpdateSpinner, SucceedSpinner, FailSpinner, WarnSpinner } from './Misc/status_logging.js';
|
|
19
19
|
import { CodeGenReporter } from './Misc/codegen-reporter.js';
|
|
20
20
|
import * as MJ from '@memberjunction/core';
|
|
21
|
-
import { RunCommandsBase,
|
|
21
|
+
import { RunCommandsBase, FormatCommandFailureDetail } from './Misc/runCommand.js';
|
|
22
22
|
import { DBSchemaGeneratorBase } from './Database/dbSchema.js';
|
|
23
23
|
import { AngularClientGeneratorBase } from './Angular/angular-codegen.js';
|
|
24
24
|
import { CreateNewUserBase } from './Misc/createNewUser.js';
|
|
25
25
|
import { MJGlobal } from '@memberjunction/global';
|
|
26
26
|
import { ActionSubClassGeneratorBase } from './Misc/action_subclasses_codegen.js';
|
|
27
|
-
import { RemoteOperationGeneratorBase,
|
|
27
|
+
import { RemoteOperationGeneratorBase, ResolveRemoteOperationSchema } from './Misc/remote_operations_codegen.js';
|
|
28
28
|
import { SQLLogging } from './Misc/sql_logging.js';
|
|
29
|
-
import {
|
|
29
|
+
import { ResolveCodeGenDatabaseProvider } from './Database/codeGenDatabaseProvider.js';
|
|
30
30
|
import { SystemIntegrityBase } from './Misc/system_integrity.js';
|
|
31
|
-
import {
|
|
31
|
+
import { ReconcileFieldLevelSecurity } from './Database/reconcileFieldLevelSecurity.js';
|
|
32
32
|
import { ActionEngineBase } from '@memberjunction/actions-base';
|
|
33
33
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
34
34
|
// Import pre-built MJ class registrations manifest (covers all @memberjunction/* packages)
|
|
@@ -60,7 +60,7 @@ export class RunCodeGenBase {
|
|
|
60
60
|
if (!r.success) {
|
|
61
61
|
const cmd = cmds[i];
|
|
62
62
|
const cmdText = cmd ? [cmd.command, ...(cmd.args ?? [])].join(' ').trim() : `command #${i + 1}`;
|
|
63
|
-
const detail =
|
|
63
|
+
const detail = FormatCommandFailureDetail(r);
|
|
64
64
|
const failure = {
|
|
65
65
|
context: `${phase} command`,
|
|
66
66
|
message: detail ? `\`${cmdText}\` failed: ${detail}` : `\`${cmdText}\` failed`,
|
|
@@ -85,8 +85,12 @@ export class RunCodeGenBase {
|
|
|
85
85
|
* `ClassFactory.CreateInstance` returns the abstract base on a missed
|
|
86
86
|
* lookup, so we disambiguate by constructor identity.
|
|
87
87
|
*/
|
|
88
|
+
async SetupDataSource() {
|
|
89
|
+
return ResolveCodeGenDatabaseProvider(DbPlatform()).SetupDataSource();
|
|
90
|
+
}
|
|
91
|
+
/** @deprecated Use {@link SetupDataSource}. */
|
|
88
92
|
async setupDataSource() {
|
|
89
|
-
return
|
|
93
|
+
return this.SetupDataSource();
|
|
90
94
|
}
|
|
91
95
|
/**
|
|
92
96
|
* Main entry point for the complete code generation process.
|
|
@@ -101,7 +105,7 @@ export class RunCodeGenBase {
|
|
|
101
105
|
// Re-initialize config from the specified working directory (e.g. repo root)
|
|
102
106
|
// so CodeGen picks up the correct mj.config.cjs with output directories
|
|
103
107
|
if (workingDirectory) {
|
|
104
|
-
|
|
108
|
+
InitializeConfig(workingDirectory);
|
|
105
109
|
}
|
|
106
110
|
// Drop the process-static soft-PK/FK cache so this run re-reads additionalSchemaInfo from disk.
|
|
107
111
|
// RSU rewrites that file (WriteAdditionalSchemaInfo) immediately before invoking this in-process
|
|
@@ -112,7 +116,7 @@ export class RunCodeGenBase {
|
|
|
112
116
|
// In-process runs are the runtime schema-update path, where the CLI's full AI profile turns a
|
|
113
117
|
// minutes-class step into an hours-class one and a bad AI answer can drop a table. Off unless the
|
|
114
118
|
// operator opts in; see applyInProcessAdvancedGenerationPolicy for the reasoning.
|
|
115
|
-
const advancedGeneration =
|
|
119
|
+
const advancedGeneration = ApplyInProcessAdvancedGenerationPolicy(configInfo);
|
|
116
120
|
if (advancedGeneration.disabled) {
|
|
117
121
|
logStatus(`In-process CodeGen: advanced (AI) generation is off for this run; set ${IN_PROCESS_ADVANCED_GENERATION_ENV}=1 to keep it on`);
|
|
118
122
|
}
|
|
@@ -144,9 +148,9 @@ export class RunCodeGenBase {
|
|
|
144
148
|
const startMs = Date.now();
|
|
145
149
|
try {
|
|
146
150
|
const startTime = new Date();
|
|
147
|
-
const platform =
|
|
148
|
-
|
|
149
|
-
const dataSource = await this.
|
|
151
|
+
const platform = DbPlatform();
|
|
152
|
+
StartSpinner('Starting MemberJunction CodeGen (' + platform + ') @ ' + startTime.toLocaleString());
|
|
153
|
+
const dataSource = await this.SetupDataSource();
|
|
150
154
|
const success = await this.executeCodeGenPipeline(dataSource, skipDatabaseGeneration, skipFileGeneration);
|
|
151
155
|
let entityCount = 0;
|
|
152
156
|
try {
|
|
@@ -168,15 +172,15 @@ export class RunCodeGenBase {
|
|
|
168
172
|
durationSeconds: (Date.now() - startMs) / 1000,
|
|
169
173
|
data: {
|
|
170
174
|
entityCount,
|
|
171
|
-
skippedDb: skipDatabaseGeneration ||
|
|
172
|
-
skippedFiles: skipFileGeneration ||
|
|
175
|
+
skippedDb: skipDatabaseGeneration || GetSettingValue('skip_database_generation', false),
|
|
176
|
+
skippedFiles: skipFileGeneration || GetSettingValue('skip_file_generation', false),
|
|
173
177
|
},
|
|
174
178
|
errors,
|
|
175
179
|
};
|
|
176
180
|
}
|
|
177
181
|
catch (e) {
|
|
178
182
|
const message = e instanceof Error ? (e.stack ?? e.message) : String(e);
|
|
179
|
-
|
|
183
|
+
FailSpinner('CodeGen failed: ' + e);
|
|
180
184
|
logError(message);
|
|
181
185
|
return {
|
|
182
186
|
success: false,
|
|
@@ -196,8 +200,8 @@ export class RunCodeGenBase {
|
|
|
196
200
|
ManageMetadataBase.clearFieldTracking();
|
|
197
201
|
const reporter = CodeGenReporter.Instance;
|
|
198
202
|
reporter.startRun();
|
|
199
|
-
reporter.mark('platform',
|
|
200
|
-
reporter.mark('skipDB', skipDatabaseGeneration ||
|
|
203
|
+
reporter.mark('platform', DbPlatform());
|
|
204
|
+
reporter.mark('skipDB', skipDatabaseGeneration || GetSettingValue('skip_database_generation', false));
|
|
201
205
|
let pipelineSuccess = true;
|
|
202
206
|
this.commandFailures = [];
|
|
203
207
|
try {
|
|
@@ -208,9 +212,9 @@ export class RunCodeGenBase {
|
|
|
208
212
|
}
|
|
209
213
|
logStatus('Loaded ' + m.Entities.length + ' entities from metadata');
|
|
210
214
|
if (configInfo.advancedGeneration?.enableAdvancedGeneration) {
|
|
211
|
-
|
|
215
|
+
StartSpinner('Initializing AI Engine for advanced generation...');
|
|
212
216
|
await AIEngine.Instance.Config(false, currentUser);
|
|
213
|
-
|
|
217
|
+
SucceedSpinner('AI Engine initialized');
|
|
214
218
|
}
|
|
215
219
|
return m;
|
|
216
220
|
});
|
|
@@ -220,16 +224,16 @@ export class RunCodeGenBase {
|
|
|
220
224
|
// so the scope still applies on the `--skipdb` path, which skips manageMetadata entirely but
|
|
221
225
|
// still generates files from configInfo.excludeSchemas. applyIncludeSchemaScope is idempotent, so
|
|
222
226
|
// running both is safe and the second pass is a no-op when the first already ran.
|
|
223
|
-
|
|
227
|
+
ApplyIncludeSchemaScope(Array.from(new Set(md.Entities.map((e) => e.SchemaName))), configInfo);
|
|
224
228
|
const runCommandsObject = MJGlobal.Instance.ClassFactory.CreateInstance(RunCommandsBase);
|
|
225
229
|
const sqlCodeGenObject = MJGlobal.Instance.ClassFactory.CreateInstance(SQLCodeGenBase);
|
|
226
|
-
const skipDB = skipDatabaseGeneration ||
|
|
230
|
+
const skipDB = skipDatabaseGeneration || GetSettingValue('skip_database_generation', false);
|
|
227
231
|
if (!skipDB) {
|
|
228
|
-
|
|
232
|
+
StartSpinner('Handling SQL Script Execution, Metadata Maintenance, and SQL Object Generation...');
|
|
229
233
|
SQLLogging.initSQLLogging();
|
|
230
|
-
const beforeCommands =
|
|
234
|
+
const beforeCommands = Commands('BEFORE');
|
|
231
235
|
if (beforeCommands && beforeCommands.length > 0) {
|
|
232
|
-
|
|
236
|
+
UpdateSpinner('Executing BEFORE commands...');
|
|
233
237
|
const results = await runCommandsObject.runCommands(beforeCommands);
|
|
234
238
|
if (results.some((r) => !r.success)) {
|
|
235
239
|
logError('ERROR running one or more BEFORE commands');
|
|
@@ -241,12 +245,12 @@ export class RunCodeGenBase {
|
|
|
241
245
|
}
|
|
242
246
|
}
|
|
243
247
|
}
|
|
244
|
-
|
|
248
|
+
UpdateSpinner('Executing before-all SQL Scripts...');
|
|
245
249
|
if (!(await sqlCodeGenObject.runCustomSQLScripts(conn, 'before-all')))
|
|
246
250
|
logError('ERROR running before-all SQL Scripts');
|
|
247
251
|
const newUserSetup = configInfo.newUserSetup;
|
|
248
252
|
if (newUserSetup) {
|
|
249
|
-
|
|
253
|
+
UpdateSpinner('Setting up new user...');
|
|
250
254
|
const newUserObject = MJGlobal.Instance.ClassFactory.CreateInstance(CreateNewUserBase);
|
|
251
255
|
const result = await newUserObject.createNewUser(newUserSetup);
|
|
252
256
|
if (!result.Success) {
|
|
@@ -255,12 +259,12 @@ export class RunCodeGenBase {
|
|
|
255
259
|
logError(' ' + result.Message);
|
|
256
260
|
}
|
|
257
261
|
else {
|
|
258
|
-
|
|
262
|
+
LogWarning('Warning: (New User Setup) ' + result.Message);
|
|
259
263
|
}
|
|
260
264
|
}
|
|
261
265
|
}
|
|
262
266
|
const manageMD = MJGlobal.Instance.ClassFactory.CreateInstance(ManageMetadataBase);
|
|
263
|
-
|
|
267
|
+
UpdateSpinner('Managing Metadata...');
|
|
264
268
|
const metadataSuccess = await reporter.phase('manageMetadata', () => manageMD.manageMetadata(conn, currentUser));
|
|
265
269
|
// Refresh in-memory metadata UNCONDITIONALLY after manageMetadata, even when it returned
|
|
266
270
|
// false. manageMetadata can return false on non-fatal sub-failures (e.g. failed validator
|
|
@@ -270,34 +274,34 @@ export class RunCodeGenBase {
|
|
|
270
274
|
// 3-bug chain, observed first-run on PG for entities like SystemEvent.
|
|
271
275
|
await provider.Refresh();
|
|
272
276
|
if (!metadataSuccess) {
|
|
273
|
-
|
|
277
|
+
FailSpinner('ERROR managing metadata (refresh applied; downstream will use latest available state)');
|
|
274
278
|
pipelineSuccess = false;
|
|
275
279
|
}
|
|
276
280
|
else {
|
|
277
|
-
|
|
281
|
+
SucceedSpinner('Metadata management completed');
|
|
278
282
|
}
|
|
279
283
|
// Field-level security reconciliation. Runs AFTER the refresh above so it sees the
|
|
280
284
|
// EntityField rows manageMetadata just created for newly-discovered columns: on an
|
|
281
285
|
// FLS-enabled entity a field with no permission rows is DENIED, so a column added
|
|
282
286
|
// without this step would be invisible to every user until something else reconciled.
|
|
283
287
|
// It also removes rows orphaned by a dropped column or a revoked role.
|
|
284
|
-
await reporter.phase('reconcileFieldPermissions', () =>
|
|
285
|
-
const sqlOutputDir =
|
|
288
|
+
await reporter.phase('reconcileFieldPermissions', () => ReconcileFieldLevelSecurity(provider, currentUser));
|
|
289
|
+
const sqlOutputDir = OutputDir('SQL', true);
|
|
286
290
|
let sqlGenerationSucceeded = true;
|
|
287
291
|
if (sqlOutputDir) {
|
|
288
|
-
|
|
292
|
+
StartSpinner('Managing SQL Scripts and Execution...');
|
|
289
293
|
const sqlSuccess = await reporter.phase('manageSQLScriptsAndExecution', () => sqlCodeGenObject.manageSQLScriptsAndExecution(conn, md.Entities, sqlOutputDir, currentUser));
|
|
290
294
|
if (!sqlSuccess) {
|
|
291
|
-
|
|
295
|
+
FailSpinner('Error managing SQL scripts and execution');
|
|
292
296
|
sqlGenerationSucceeded = false;
|
|
293
297
|
pipelineSuccess = false;
|
|
294
298
|
}
|
|
295
299
|
else {
|
|
296
|
-
|
|
300
|
+
SucceedSpinner('SQL scripts and execution completed');
|
|
297
301
|
}
|
|
298
302
|
}
|
|
299
303
|
else {
|
|
300
|
-
|
|
304
|
+
WarnSpinner('SQL output directory NOT found in config file, skipping...');
|
|
301
305
|
}
|
|
302
306
|
// ── Post-run CRUD validator ─────────────────────────────────────────
|
|
303
307
|
// Runs UNCONDITIONALLY even when the SQL pipeline reported failure so
|
|
@@ -314,10 +318,10 @@ export class RunCodeGenBase {
|
|
|
314
318
|
// but the default behavior is to fail loudly and exit non-zero.
|
|
315
319
|
const skipCRUDValidation = process.env.MJ_CODEGEN_SKIP_CRUD_VALIDATION === 'true';
|
|
316
320
|
if (skipCRUDValidation) {
|
|
317
|
-
|
|
321
|
+
LogWarning('Skipping post-CodeGen CRUD function validation (MJ_CODEGEN_SKIP_CRUD_VALIDATION=true)');
|
|
318
322
|
}
|
|
319
323
|
else {
|
|
320
|
-
|
|
324
|
+
StartSpinner('Validating expected CRUD routines exist in database...');
|
|
321
325
|
try {
|
|
322
326
|
// Use the same baseline filter as manageSQLScriptsAndExecution: only
|
|
323
327
|
// entities flagged IncludeInAPI=true are expected to have routines.
|
|
@@ -372,7 +376,7 @@ export class RunCodeGenBase {
|
|
|
372
376
|
const list = missing
|
|
373
377
|
.map(m => ` - [${m.schema}] ${m.entity} → missing ${m.type} routine: ${m.expectedRoutine}`)
|
|
374
378
|
.join('\n');
|
|
375
|
-
|
|
379
|
+
FailSpinner(`Post-CodeGen CRUD validation FAILED: ${missing.length} expected routine(s) missing`);
|
|
376
380
|
logError(`Post-CodeGen validation detected ${missing.length} CRUD routine(s) the runtime expects but the database is missing.\n` +
|
|
377
381
|
`These entities are configured (AllowCreateAPI/AllowUpdateAPI/AllowDeleteAPI=true) to expose mutations via the API,\n` +
|
|
378
382
|
`but the underlying database routine wasn't emitted/applied by CodeGen — runtime saves/deletes on these entities will throw:\n` +
|
|
@@ -385,11 +389,11 @@ export class RunCodeGenBase {
|
|
|
385
389
|
return false;
|
|
386
390
|
}
|
|
387
391
|
else {
|
|
388
|
-
|
|
392
|
+
SucceedSpinner(`Post-CodeGen CRUD validation passed (${md.Entities.length} entities checked)`);
|
|
389
393
|
}
|
|
390
394
|
}
|
|
391
395
|
catch (e) {
|
|
392
|
-
|
|
396
|
+
FailSpinner('Post-CodeGen CRUD validation errored');
|
|
393
397
|
logError(`CRUD validator threw: ${e instanceof Error ? e.message : String(e)}`);
|
|
394
398
|
return false;
|
|
395
399
|
}
|
|
@@ -410,7 +414,7 @@ export class RunCodeGenBase {
|
|
|
410
414
|
// Set MJ_CODEGEN_STRICT_FIELD_RESOLUTION=true to make it a hard gate; that is the
|
|
411
415
|
// intended default once fleets are clean.
|
|
412
416
|
try {
|
|
413
|
-
|
|
417
|
+
StartSpinner('Validating entity fields resolve against their base views...');
|
|
414
418
|
const baseline = md.Entities.filter(e => e.IncludeInAPI);
|
|
415
419
|
const gaps = await sqlCodeGenObject.DBProvider.validateEntityFieldsResolve(conn, baseline);
|
|
416
420
|
if (gaps.length > 0) {
|
|
@@ -429,21 +433,21 @@ export class RunCodeGenBase {
|
|
|
429
433
|
`Fix: rebuild the affected base view(s). PostgreSQL permits appending columns in place via\n` +
|
|
430
434
|
`CREATE OR REPLACE VIEW, so no DROP/CASCADE is required.`;
|
|
431
435
|
if (strict) {
|
|
432
|
-
|
|
436
|
+
FailSpinner(`Field-resolution validation FAILED: ${gaps.length} unreadable field(s)`);
|
|
433
437
|
logError(summary);
|
|
434
438
|
return false;
|
|
435
439
|
}
|
|
436
|
-
|
|
437
|
-
|
|
440
|
+
WarnSpinner(`Field-resolution validation found ${gaps.length} unreadable field(s)`);
|
|
441
|
+
LogWarning(summary);
|
|
438
442
|
}
|
|
439
443
|
else {
|
|
440
|
-
|
|
444
|
+
SucceedSpinner('Entity fields all resolve against their base views');
|
|
441
445
|
}
|
|
442
446
|
}
|
|
443
447
|
catch (e) {
|
|
444
448
|
// Never fail the run on the validator's own error — it is a reporter.
|
|
445
|
-
|
|
446
|
-
|
|
449
|
+
WarnSpinner('Field-resolution validation could not run');
|
|
450
|
+
LogWarning(`Field-resolution validator threw: ${e instanceof Error ? e.message : String(e)}`);
|
|
447
451
|
}
|
|
448
452
|
// Surface upstream SQL-pipeline failure even if validator passed: a
|
|
449
453
|
// green validator just means whatever DID get generated is consistent;
|
|
@@ -453,7 +457,7 @@ export class RunCodeGenBase {
|
|
|
453
457
|
}
|
|
454
458
|
}
|
|
455
459
|
else {
|
|
456
|
-
|
|
460
|
+
WarnSpinner('Skipping database generation (skip_database_generation = true)');
|
|
457
461
|
}
|
|
458
462
|
// Persisted validators must reach file generation on EVERY path, not just the skip-DB one.
|
|
459
463
|
//
|
|
@@ -474,10 +478,10 @@ export class RunCodeGenBase {
|
|
|
474
478
|
// deduplicates by `functionName` over a deterministic sort, so a validator both freshly
|
|
475
479
|
// generated and read back from `GeneratedCode` yields one emission, not two.
|
|
476
480
|
const manageMD = MJGlobal.Instance.ClassFactory.CreateInstance(ManageMetadataBase);
|
|
477
|
-
|
|
481
|
+
StartSpinner('Checking/Loading AI Generated Code from Metadata...');
|
|
478
482
|
const metadataSuccess = await reporter.phase('loadGeneratedCode', () => manageMD.loadGeneratedCode(conn, currentUser));
|
|
479
483
|
if (!metadataSuccess) {
|
|
480
|
-
|
|
484
|
+
FailSpinner('ERROR checking/loading AI Generated Code from Metadata');
|
|
481
485
|
pipelineSuccess = false;
|
|
482
486
|
return false;
|
|
483
487
|
}
|
|
@@ -488,22 +492,22 @@ export class RunCodeGenBase {
|
|
|
488
492
|
// whatever was committed. Both times that regression shipped, the log said exactly this
|
|
489
493
|
// line and nothing else. A number here makes the next one visible in CI output.
|
|
490
494
|
const loadedValidators = ManageMetadataBase.generatedValidators.length;
|
|
491
|
-
|
|
495
|
+
SucceedSpinner(`AI Generated Code loaded from Metadata (${loadedValidators} validator${loadedValidators === 1 ? '' : 's'})`);
|
|
492
496
|
}
|
|
493
|
-
const skipFiles = skipFileGeneration ||
|
|
497
|
+
const skipFiles = skipFileGeneration || GetSettingValue('skip_file_generation', false);
|
|
494
498
|
if (skipFiles) {
|
|
495
|
-
|
|
499
|
+
WarnSpinner('Skipping file generation (skip_file_generation = true)');
|
|
496
500
|
SQLLogging.finishSQLLogging();
|
|
497
501
|
}
|
|
498
502
|
else if (!(await this.runFileGenerationPhase(conn, currentUser, md, skipDB))) {
|
|
499
503
|
pipelineSuccess = false;
|
|
500
504
|
return false;
|
|
501
505
|
}
|
|
502
|
-
|
|
506
|
+
StartSpinner('Running system integrity checks...');
|
|
503
507
|
const integrityResults = await SystemIntegrityBase.RunIntegrityChecks(conn, true);
|
|
504
508
|
const integrityFailures = integrityResults.filter((r) => !r.Success);
|
|
505
509
|
if (integrityFailures.length > 0) {
|
|
506
|
-
|
|
510
|
+
FailSpinner(`System integrity checks FAILED: ${integrityFailures.length} check(s) failed`);
|
|
507
511
|
pipelineSuccess = false;
|
|
508
512
|
for (const failure of integrityFailures) {
|
|
509
513
|
const msg = `Integrity check '${failure.Name}' failed: ${failure.Message}`;
|
|
@@ -513,14 +517,14 @@ export class RunCodeGenBase {
|
|
|
513
517
|
}
|
|
514
518
|
}
|
|
515
519
|
else {
|
|
516
|
-
|
|
520
|
+
SucceedSpinner('System integrity checks completed');
|
|
517
521
|
}
|
|
518
|
-
const afterCommands =
|
|
522
|
+
const afterCommands = Commands('AFTER');
|
|
519
523
|
if (afterCommands && afterCommands.length > 0) {
|
|
520
|
-
|
|
524
|
+
StartSpinner('Executing AFTER commands...');
|
|
521
525
|
const results = await runCommandsObject.runCommands(afterCommands);
|
|
522
526
|
if (results.some((r) => !r.success)) {
|
|
523
|
-
|
|
527
|
+
FailSpinner('ERROR running one or more AFTER commands');
|
|
524
528
|
const recorded = this.recordCommandFailures('AFTER', afterCommands, results);
|
|
525
529
|
pipelineSuccess = false;
|
|
526
530
|
for (const failure of recorded) {
|
|
@@ -529,21 +533,21 @@ export class RunCodeGenBase {
|
|
|
529
533
|
}
|
|
530
534
|
}
|
|
531
535
|
else
|
|
532
|
-
|
|
536
|
+
SucceedSpinner('AFTER commands completed');
|
|
533
537
|
}
|
|
534
538
|
if (!skipDB) {
|
|
535
|
-
|
|
539
|
+
StartSpinner('Executing after-all SQL Scripts...');
|
|
536
540
|
if (!(await sqlCodeGenObject.runCustomSQLScripts(conn, 'after-all')))
|
|
537
|
-
|
|
541
|
+
FailSpinner('ERROR running after-all SQL Scripts');
|
|
538
542
|
else
|
|
539
|
-
|
|
543
|
+
SucceedSpinner('After-all SQL Scripts completed');
|
|
540
544
|
}
|
|
541
545
|
const endTime = new Date();
|
|
542
546
|
const totalSeconds = (endTime.getTime() - startTime.getTime()) / 1000;
|
|
543
547
|
// Visible final summary (succeedSpinner persists a ✔ line in both verbose and
|
|
544
548
|
// non-verbose modes). The detailed/timestamped form stays on logStatus for the
|
|
545
549
|
// verbose log + report.
|
|
546
|
-
|
|
550
|
+
SucceedSpinner(`MJ CodeGen complete — ${md.Entities.length} entities in ${totalSeconds.toFixed(2)}s`);
|
|
547
551
|
logStatus('MJ CodeGen Complete! ' + md.Entities.length + ' entities processed in ' + totalSeconds + 's @ ' + endTime.toLocaleString());
|
|
548
552
|
// A BEFORE/AFTER command failure fails the run (success=false, exit 1) so it
|
|
549
553
|
// isn't silently swallowed — details flow into the structured result below.
|
|
@@ -584,7 +588,7 @@ export class RunCodeGenBase {
|
|
|
584
588
|
buildSchemaEmitOptions(entities, skipDB) {
|
|
585
589
|
const fileEmit = configInfo.fileEmit;
|
|
586
590
|
return {
|
|
587
|
-
dirtySchemas:
|
|
591
|
+
dirtySchemas: ResolveDirtySchemasForEmit(entities, [...ManageMetadataBase.newEntityList, ...ManageMetadataBase.modifiedEntityList], skipDB, fileEmit?.dirtySchemaOnly !== false, ManageMetadataBase.deletedEntitySchemaList),
|
|
588
592
|
};
|
|
589
593
|
}
|
|
590
594
|
/**
|
|
@@ -600,12 +604,12 @@ export class RunCodeGenBase {
|
|
|
600
604
|
const reporter = CodeGenReporter.Instance;
|
|
601
605
|
EmitStats.Reset();
|
|
602
606
|
const apiEntities = md.Entities.filter((e) => e.IncludeInAPI);
|
|
603
|
-
const excludedSchemaNames = configInfo.excludeSchemas.map(s =>
|
|
604
|
-
const includedEntities = apiEntities.filter((e) => !excludedSchemaNames.includes(
|
|
607
|
+
const excludedSchemaNames = configInfo.excludeSchemas.map(s => SchemaKey(s));
|
|
608
|
+
const includedEntities = apiEntities.filter((e) => !excludedSchemaNames.includes(SchemaKey(e.SchemaName)));
|
|
605
609
|
const excludedCount = apiEntities.length - includedEntities.length;
|
|
606
610
|
if (excludedCount > 0) {
|
|
607
611
|
const excludedBySchema = apiEntities
|
|
608
|
-
.filter((e) => excludedSchemaNames.includes(
|
|
612
|
+
.filter((e) => excludedSchemaNames.includes(SchemaKey(e.SchemaName)))
|
|
609
613
|
.reduce((acc, e) => {
|
|
610
614
|
const schema = (e.SchemaName ?? '').trim() || '(none)';
|
|
611
615
|
acc[schema] = (acc[schema] || 0) + 1;
|
|
@@ -616,42 +620,42 @@ export class RunCodeGenBase {
|
|
|
616
620
|
.join(', ');
|
|
617
621
|
logStatus('Excluded ' + excludedCount + ' entities from code generation by schema: ' + schemaDetails);
|
|
618
622
|
}
|
|
619
|
-
const coreEntities = includedEntities.filter((e) =>
|
|
620
|
-
const nonCoreEntities = includedEntities.filter((e) =>
|
|
623
|
+
const coreEntities = includedEntities.filter((e) => SchemaKey(e.SchemaName) === SchemaKey(mjCoreSchema));
|
|
624
|
+
const nonCoreEntities = includedEntities.filter((e) => SchemaKey(e.SchemaName) !== SchemaKey(mjCoreSchema));
|
|
621
625
|
// Entities whose schemas are owned by OTHER packages (see entityPackageName map). They must be
|
|
622
626
|
// excluded from every artifact this package emits — GraphQL ObjectTypes included. If two packages
|
|
623
627
|
// both emit an ObjectType for the same entity, graphql-js rejects the unified schema at boot with
|
|
624
628
|
// "Schema must contain uniquely named types but contains multiple types named ..." and the API
|
|
625
629
|
// crash-loops.
|
|
626
|
-
const externalSchemas =
|
|
630
|
+
const externalSchemas = GetExternalEntitySchemas().map(s => s.toLowerCase());
|
|
627
631
|
const localNonCoreEntities = externalSchemas.length > 0
|
|
628
|
-
? nonCoreEntities.filter(e => !externalSchemas.includes(
|
|
632
|
+
? nonCoreEntities.filter(e => !externalSchemas.includes(SchemaKey(e.SchemaName)))
|
|
629
633
|
: nonCoreEntities;
|
|
630
634
|
const isVerbose = configInfo?.verboseOutput ?? false;
|
|
631
635
|
if (!isVerbose)
|
|
632
|
-
|
|
633
|
-
const graphQLCoreResolversOutputDir =
|
|
636
|
+
StartSpinner('Generating TypeScript code...');
|
|
637
|
+
const graphQLCoreResolversOutputDir = OutputDir('GraphQLCoreEntityResolvers', false);
|
|
634
638
|
if (graphQLCoreResolversOutputDir) {
|
|
635
639
|
if (isVerbose)
|
|
636
|
-
|
|
640
|
+
StartSpinner('Generating CORE Entity GraphQL Resolver Code...');
|
|
637
641
|
const graphQLGenerator = MJGlobal.Instance.ClassFactory.CreateInstance(GraphQLServerGeneratorBase);
|
|
638
642
|
const ok = await reporter.phase('generateGraphQLCore', async () => graphQLGenerator.generateGraphQLServerCode(coreEntities, graphQLCoreResolversOutputDir, '@memberjunction/core-entities', true, this.buildSchemaEmitOptions(coreEntities, skipDB)));
|
|
639
643
|
if (!ok) {
|
|
640
|
-
|
|
644
|
+
FailSpinner('Error generating GraphQL server code');
|
|
641
645
|
return false;
|
|
642
646
|
}
|
|
643
647
|
else if (isVerbose)
|
|
644
|
-
|
|
648
|
+
SucceedSpinner('CORE Entity GraphQL Resolver Code generated');
|
|
645
649
|
}
|
|
646
|
-
const graphqlOutputDir =
|
|
650
|
+
const graphqlOutputDir = OutputDir('GraphQLServer', true);
|
|
647
651
|
if (graphqlOutputDir) {
|
|
648
652
|
if (isVerbose)
|
|
649
|
-
|
|
653
|
+
StartSpinner('Generating GraphQL Resolver Code...');
|
|
650
654
|
const graphQLGenerator = MJGlobal.Instance.ClassFactory.CreateInstance(GraphQLServerGeneratorBase);
|
|
651
655
|
const entityPackageName = typeof configInfo.entityPackageName === 'string'
|
|
652
656
|
? (configInfo.entityPackageName || 'mj_generatedentities')
|
|
653
657
|
: 'mj_generatedentities';
|
|
654
|
-
const graphqlGroups =
|
|
658
|
+
const graphqlGroups = PartitionEntitiesByOutputDirectory(localNonCoreEntities, 'GraphQLServer', graphqlOutputDir, configInfo.schemaOutput);
|
|
655
659
|
const ok = await reporter.phase('generateGraphQL', async () => {
|
|
656
660
|
for (const [dir, group] of graphqlGroups) {
|
|
657
661
|
const groupOk = graphQLGenerator.generateGraphQLServerCode(group, dir, entityPackageName, false, this.buildSchemaEmitOptions(group, skipDB));
|
|
@@ -662,33 +666,33 @@ export class RunCodeGenBase {
|
|
|
662
666
|
return true;
|
|
663
667
|
});
|
|
664
668
|
if (!ok) {
|
|
665
|
-
|
|
669
|
+
FailSpinner('Error generating GraphQL Resolver code');
|
|
666
670
|
return false;
|
|
667
671
|
}
|
|
668
672
|
else if (isVerbose)
|
|
669
|
-
|
|
673
|
+
SucceedSpinner('GraphQL Resolver Code generated');
|
|
670
674
|
}
|
|
671
675
|
else if (isVerbose)
|
|
672
|
-
|
|
673
|
-
const coreEntitySubClassOutputDir =
|
|
676
|
+
WarnSpinner('GraphQL server output directory NOT found in config file, skipping...');
|
|
677
|
+
const coreEntitySubClassOutputDir = OutputDir('CoreEntitySubClasses', false);
|
|
674
678
|
if (coreEntitySubClassOutputDir && coreEntitySubClassOutputDir.length > 0) {
|
|
675
679
|
if (isVerbose)
|
|
676
|
-
|
|
680
|
+
StartSpinner('Generating CORE Entity Subclass Code...');
|
|
677
681
|
const entitySubClassGeneratorObject = MJGlobal.Instance.ClassFactory.CreateInstance(EntitySubClassGeneratorBase);
|
|
678
682
|
const ok = await reporter.phase('generateEntitySubclassesCore', () => entitySubClassGeneratorObject.generateAllEntitySubClasses(conn, coreEntities, coreEntitySubClassOutputDir, skipDB, this.buildSchemaEmitOptions(coreEntities, skipDB)));
|
|
679
683
|
if (!ok) {
|
|
680
|
-
|
|
684
|
+
FailSpinner('Error generating entity subclass code');
|
|
681
685
|
return false;
|
|
682
686
|
}
|
|
683
687
|
else if (isVerbose)
|
|
684
|
-
|
|
688
|
+
SucceedSpinner('CORE Entity Subclass Code generated');
|
|
685
689
|
}
|
|
686
|
-
const entitySubClassOutputDir =
|
|
690
|
+
const entitySubClassOutputDir = OutputDir('EntitySubClasses', true);
|
|
687
691
|
if (entitySubClassOutputDir) {
|
|
688
692
|
if (isVerbose)
|
|
689
|
-
|
|
693
|
+
StartSpinner('Generating Entity Subclass Code...');
|
|
690
694
|
const entitySubClassGeneratorObject = MJGlobal.Instance.ClassFactory.CreateInstance(EntitySubClassGeneratorBase);
|
|
691
|
-
const entityGroups =
|
|
695
|
+
const entityGroups = PartitionEntitiesByOutputDirectory(localNonCoreEntities, 'EntitySubClasses', entitySubClassOutputDir, configInfo.schemaOutput);
|
|
692
696
|
const ok = await reporter.phase('generateEntitySubclasses', async () => {
|
|
693
697
|
for (const [dir, group] of entityGroups) {
|
|
694
698
|
const groupOk = await entitySubClassGeneratorObject.generateAllEntitySubClasses(conn, group, dir, skipDB, this.buildSchemaEmitOptions(group, skipDB));
|
|
@@ -699,33 +703,33 @@ export class RunCodeGenBase {
|
|
|
699
703
|
return true;
|
|
700
704
|
});
|
|
701
705
|
if (!ok) {
|
|
702
|
-
|
|
706
|
+
FailSpinner('Error generating entity subclass code');
|
|
703
707
|
return false;
|
|
704
708
|
}
|
|
705
709
|
else if (isVerbose)
|
|
706
|
-
|
|
710
|
+
SucceedSpinner('Entity Subclass Code generated');
|
|
707
711
|
}
|
|
708
712
|
else if (isVerbose)
|
|
709
|
-
|
|
710
|
-
const angularCoreEntitiesOutputDir =
|
|
713
|
+
WarnSpinner('Entity subclass output directory NOT found in config file, skipping...');
|
|
714
|
+
const angularCoreEntitiesOutputDir = OutputDir('AngularCoreEntities', false);
|
|
711
715
|
if (angularCoreEntitiesOutputDir) {
|
|
712
716
|
if (isVerbose)
|
|
713
|
-
|
|
717
|
+
StartSpinner('Generating Angular CORE Entities Code...');
|
|
714
718
|
const angularGenerator = MJGlobal.Instance.ClassFactory.CreateInstance(AngularClientGeneratorBase);
|
|
715
719
|
const ok = await reporter.phase('generateAngularCore', () => angularGenerator.generateAngularCode(coreEntities, angularCoreEntitiesOutputDir, 'Core', currentUser, 'AngularCoreEntities'));
|
|
716
720
|
if (!ok) {
|
|
717
|
-
|
|
721
|
+
FailSpinner('Error generating Angular CORE Entities code');
|
|
718
722
|
return false;
|
|
719
723
|
}
|
|
720
724
|
else if (isVerbose)
|
|
721
|
-
|
|
725
|
+
SucceedSpinner('Angular CORE Entities Code generated');
|
|
722
726
|
}
|
|
723
|
-
const angularOutputDir =
|
|
727
|
+
const angularOutputDir = OutputDir('Angular', false);
|
|
724
728
|
if (angularOutputDir) {
|
|
725
729
|
if (isVerbose)
|
|
726
|
-
|
|
730
|
+
StartSpinner('Generating Angular Code...');
|
|
727
731
|
const angularGenerator = MJGlobal.Instance.ClassFactory.CreateInstance(AngularClientGeneratorBase);
|
|
728
|
-
const angularGroups =
|
|
732
|
+
const angularGroups = PartitionEntitiesByOutputDirectory(localNonCoreEntities, 'Angular', angularOutputDir, configInfo.schemaOutput);
|
|
729
733
|
const ok = await reporter.phase('generateAngular', async () => {
|
|
730
734
|
for (const [dir, group] of angularGroups) {
|
|
731
735
|
const groupOk = angularGenerator.generateAngularCode(group, dir, '', currentUser, 'Angular');
|
|
@@ -736,64 +740,64 @@ export class RunCodeGenBase {
|
|
|
736
740
|
return true;
|
|
737
741
|
});
|
|
738
742
|
if (!ok) {
|
|
739
|
-
|
|
743
|
+
FailSpinner('Error generating Angular code');
|
|
740
744
|
return false;
|
|
741
745
|
}
|
|
742
746
|
else if (isVerbose)
|
|
743
|
-
|
|
747
|
+
SucceedSpinner('Angular Code generated');
|
|
744
748
|
}
|
|
745
749
|
else if (isVerbose)
|
|
746
|
-
|
|
747
|
-
const dbSchemaOutputDir =
|
|
750
|
+
WarnSpinner('Angular output directory NOT found in config file, skipping...');
|
|
751
|
+
const dbSchemaOutputDir = OutputDir('DBSchemaJSON', false);
|
|
748
752
|
if (dbSchemaOutputDir) {
|
|
749
753
|
if (isVerbose)
|
|
750
|
-
|
|
754
|
+
StartSpinner('Generating Database Schema JSON Output...');
|
|
751
755
|
const schemaGeneratorObject = MJGlobal.Instance.ClassFactory.CreateInstance(DBSchemaGeneratorBase);
|
|
752
756
|
await reporter.phase('generateDBSchema', async () => {
|
|
753
757
|
if (!schemaGeneratorObject.generateDBSchemaJSONOutput(md.Entities, dbSchemaOutputDir)) {
|
|
754
|
-
|
|
758
|
+
FailSpinner('Error generating Database Schema JSON Output, non-fatal, continuing...');
|
|
755
759
|
}
|
|
756
760
|
else if (isVerbose)
|
|
757
|
-
|
|
761
|
+
SucceedSpinner('Database Schema JSON Output generated');
|
|
758
762
|
});
|
|
759
763
|
}
|
|
760
764
|
else if (isVerbose)
|
|
761
|
-
|
|
762
|
-
const coreActionsOutputDir =
|
|
765
|
+
WarnSpinner('DB Schema output directory NOT found in config file, skipping...');
|
|
766
|
+
const coreActionsOutputDir = OutputDir('CoreActionSubclasses', false);
|
|
763
767
|
await ActionEngineBase.Instance.Config(false, currentUser);
|
|
764
768
|
if (coreActionsOutputDir) {
|
|
765
769
|
if (isVerbose)
|
|
766
|
-
|
|
770
|
+
StartSpinner('Generating CORE Actions Code...');
|
|
767
771
|
const actionsGenerator = MJGlobal.Instance.ClassFactory.CreateInstance(ActionSubClassGeneratorBase);
|
|
768
772
|
const ok = await reporter.phase('generateActionsCore', () => actionsGenerator.generateActions(ActionEngineBase.Instance.CoreActions, coreActionsOutputDir));
|
|
769
773
|
if (!ok) {
|
|
770
|
-
|
|
774
|
+
FailSpinner('Error generating CORE Actions code');
|
|
771
775
|
return false;
|
|
772
776
|
}
|
|
773
777
|
else if (isVerbose)
|
|
774
|
-
|
|
778
|
+
SucceedSpinner('CORE Actions Code generated');
|
|
775
779
|
}
|
|
776
|
-
const actionsOutputDir =
|
|
780
|
+
const actionsOutputDir = OutputDir('ActionSubclasses', false);
|
|
777
781
|
if (actionsOutputDir) {
|
|
778
782
|
if (isVerbose)
|
|
779
|
-
|
|
783
|
+
StartSpinner('Generating Actions Code...');
|
|
780
784
|
const actionsGenerator = MJGlobal.Instance.ClassFactory.CreateInstance(ActionSubClassGeneratorBase);
|
|
781
785
|
const ok = await reporter.phase('generateActions', () => actionsGenerator.generateActions(ActionEngineBase.Instance.NonCoreActions, actionsOutputDir));
|
|
782
786
|
if (!ok) {
|
|
783
|
-
|
|
787
|
+
FailSpinner('Error generating Actions code');
|
|
784
788
|
return false;
|
|
785
789
|
}
|
|
786
790
|
else if (isVerbose)
|
|
787
|
-
|
|
791
|
+
SucceedSpinner('Actions Code generated');
|
|
788
792
|
}
|
|
789
793
|
else if (isVerbose)
|
|
790
|
-
|
|
794
|
+
WarnSpinner('Actions output directory NOT found in config file, skipping...');
|
|
791
795
|
// Remote Operations — emit the typed BaseRemotableOperation subclass for each MJ: Remote Operations row.
|
|
792
796
|
// Two output targets, parallel to the entity-subclass split: `CoreRemoteOperations` (MJ core ops, shipped
|
|
793
797
|
// in @memberjunction/core-entities) and `RemoteOperations` (downstream/user ops, their GeneratedEntities).
|
|
794
798
|
// Remote operations are scoped to includeSchemas / excludeSchemas and partitioned between core and non-core.
|
|
795
|
-
const coreRemoteOpsDir =
|
|
796
|
-
const nonCoreRemoteOpsDir =
|
|
799
|
+
const coreRemoteOpsDir = OutputDir('CoreRemoteOperations', false);
|
|
800
|
+
const nonCoreRemoteOpsDir = OutputDir('RemoteOperations', false);
|
|
797
801
|
if (coreRemoteOpsDir || nonCoreRemoteOpsDir) {
|
|
798
802
|
const remoteOpsResult = await new MJ.RunView().RunView({ EntityName: 'MJ: Remote Operations', ResultType: 'entity_object' }, currentUser);
|
|
799
803
|
const allRemoteOps = remoteOpsResult.Results ?? [];
|
|
@@ -804,17 +808,17 @@ export class RunCodeGenBase {
|
|
|
804
808
|
])).filter(Boolean);
|
|
805
809
|
const opsWithSchema = allRemoteOps.map((op) => ({
|
|
806
810
|
op,
|
|
807
|
-
schema:
|
|
811
|
+
schema: ResolveRemoteOperationSchema(op, md.Entities, allCandidateSchemas, mjCoreSchema),
|
|
808
812
|
}));
|
|
809
813
|
// Filter operations by excludedSchemaNames (compiled includeSchemas/excludeSchemas scope)
|
|
810
814
|
// and by includeSchemas (if explicitly configured).
|
|
811
815
|
const inScopeOpsWithSchema = opsWithSchema.filter(({ schema }) => {
|
|
812
|
-
const key =
|
|
816
|
+
const key = SchemaKey(schema);
|
|
813
817
|
if (excludedSchemaNames.includes(key)) {
|
|
814
818
|
return false;
|
|
815
819
|
}
|
|
816
820
|
if (configInfo.includeSchemas && configInfo.includeSchemas.length > 0) {
|
|
817
|
-
const includeKeys = configInfo.includeSchemas.map((s) =>
|
|
821
|
+
const includeKeys = configInfo.includeSchemas.map((s) => SchemaKey(s));
|
|
818
822
|
if (!includeKeys.includes(key)) {
|
|
819
823
|
return false;
|
|
820
824
|
}
|
|
@@ -825,11 +829,11 @@ export class RunCodeGenBase {
|
|
|
825
829
|
if (excludedOpsCount > 0) {
|
|
826
830
|
const excludedBySchema = opsWithSchema
|
|
827
831
|
.filter(({ schema }) => {
|
|
828
|
-
const key =
|
|
832
|
+
const key = SchemaKey(schema);
|
|
829
833
|
if (excludedSchemaNames.includes(key))
|
|
830
834
|
return true;
|
|
831
835
|
if (configInfo.includeSchemas && configInfo.includeSchemas.length > 0) {
|
|
832
|
-
return !configInfo.includeSchemas.map((s) =>
|
|
836
|
+
return !configInfo.includeSchemas.map((s) => SchemaKey(s)).includes(key);
|
|
833
837
|
}
|
|
834
838
|
return false;
|
|
835
839
|
})
|
|
@@ -844,10 +848,10 @@ export class RunCodeGenBase {
|
|
|
844
848
|
logStatus(`Excluded ${excludedOpsCount} remote operation(s) from code generation by schema: ${details}`);
|
|
845
849
|
}
|
|
846
850
|
const coreRemoteOps = inScopeOpsWithSchema
|
|
847
|
-
.filter(({ schema }) =>
|
|
851
|
+
.filter(({ schema }) => SchemaKey(schema) === SchemaKey(mjCoreSchema))
|
|
848
852
|
.map(({ op }) => op);
|
|
849
853
|
const nonCoreRemoteOps = inScopeOpsWithSchema
|
|
850
|
-
.filter(({ schema }) =>
|
|
854
|
+
.filter(({ schema }) => SchemaKey(schema) !== SchemaKey(mjCoreSchema))
|
|
851
855
|
.map(({ op }) => op);
|
|
852
856
|
const remoteOpsGenerator = MJGlobal.Instance.ClassFactory.CreateInstance(RemoteOperationGeneratorBase);
|
|
853
857
|
for (const target of [
|
|
@@ -857,18 +861,18 @@ export class RunCodeGenBase {
|
|
|
857
861
|
if (!target.dir)
|
|
858
862
|
continue;
|
|
859
863
|
if (isVerbose)
|
|
860
|
-
|
|
864
|
+
StartSpinner(`Generating ${target.label} typed bases...`);
|
|
861
865
|
const ok = await reporter.phase(target.phase, () => remoteOpsGenerator.generateRemoteOperations(target.ops, target.dir));
|
|
862
866
|
if (!ok) {
|
|
863
|
-
|
|
867
|
+
FailSpinner(`Error generating ${target.label} code`);
|
|
864
868
|
return false;
|
|
865
869
|
}
|
|
866
870
|
else if (isVerbose)
|
|
867
|
-
|
|
871
|
+
SucceedSpinner(`${target.label} typed bases generated`);
|
|
868
872
|
}
|
|
869
873
|
}
|
|
870
874
|
else if (isVerbose)
|
|
871
|
-
|
|
875
|
+
WarnSpinner('Remote Operations output directory NOT found in config file, skipping...');
|
|
872
876
|
const emit = EmitStats.Snapshot();
|
|
873
877
|
reporter.counter('filesWritten', emit.filesWritten);
|
|
874
878
|
reporter.counter('filesSkipped', emit.filesSkipped);
|
|
@@ -880,25 +884,33 @@ export class RunCodeGenBase {
|
|
|
880
884
|
`(assemble ${emit.assembleMs}ms)`);
|
|
881
885
|
SQLLogging.finishSQLLogging();
|
|
882
886
|
if (!isVerbose)
|
|
883
|
-
|
|
887
|
+
SucceedSpinner('TypeScript code generation completed');
|
|
884
888
|
return true;
|
|
885
889
|
}
|
|
886
890
|
}
|
|
887
891
|
/**
|
|
888
892
|
* Convenience function to run the MemberJunction code generation process.
|
|
889
893
|
*/
|
|
890
|
-
export async function
|
|
894
|
+
export async function RunMemberJunctionCodeGeneration(skipDatabaseGeneration = false, skipFileGeneration = false) {
|
|
891
895
|
const runObject = MJGlobal.Instance.ClassFactory.CreateInstance(RunCodeGenBase);
|
|
892
896
|
return await runObject.Run(skipDatabaseGeneration, skipFileGeneration);
|
|
893
897
|
}
|
|
898
|
+
/** @deprecated Use {@link RunMemberJunctionCodeGeneration}. */
|
|
899
|
+
export async function runMemberJunctionCodeGeneration(skipDatabaseGeneration = false, skipFileGeneration = false) {
|
|
900
|
+
return RunMemberJunctionCodeGeneration(skipDatabaseGeneration, skipFileGeneration);
|
|
901
|
+
}
|
|
894
902
|
/**
|
|
895
903
|
* Like {@link runMemberJunctionCodeGeneration}, but returns a structured
|
|
896
904
|
* {@link MJCLIResult} instead of calling `process.exit()`. The pluggable
|
|
897
905
|
* `mj codegen` plugin uses this so the runtime host can emit the result
|
|
898
906
|
* (e.g. `--format=json`) before the CLI exits.
|
|
899
907
|
*/
|
|
900
|
-
export async function
|
|
908
|
+
export async function RunMemberJunctionCodeGenerationWithResult(skipDatabaseGeneration = false, skipFileGeneration = false) {
|
|
901
909
|
const runObject = MJGlobal.Instance.ClassFactory.CreateInstance(RunCodeGenBase);
|
|
902
910
|
return await runObject.RunWithResult(skipDatabaseGeneration, skipFileGeneration);
|
|
903
911
|
}
|
|
912
|
+
/** @deprecated Use {@link RunMemberJunctionCodeGenerationWithResult}. */
|
|
913
|
+
export async function runMemberJunctionCodeGenerationWithResult(skipDatabaseGeneration = false, skipFileGeneration = false) {
|
|
914
|
+
return RunMemberJunctionCodeGenerationWithResult(skipDatabaseGeneration, skipFileGeneration);
|
|
915
|
+
}
|
|
904
916
|
//# sourceMappingURL=runCodeGen.js.map
|