Member Junction
    Preparing search index...

    Main entry point for the MemberJunction CodeGen Library.

    This package provides comprehensive code generation capabilities for the MemberJunction platform, including:

    Configuration Management:

    • Configuration file parsing and validation
    • Database connection management

    Database Operations:

    • Schema introspection and metadata management
    • SQL script generation (views, procedures, indexes)
    • Database schema JSON export

    Code Generation:

    • TypeScript entity classes with Zod validation
    • Angular components and forms
    • GraphQL resolvers and schemas
    • Action subclasses for business logic

    Utilities:

    • Status logging and error handling
    • Command execution
    • System integrity checks
    import { RunCodeGenBase, initializeConfig } from '@memberjunction/codegen-lib';

    // Initialize configuration
    const config = initializeConfig(process.cwd());

    // Run code generation
    const codeGen = new RunCodeGenBase();
    await codeGen.Run();
    • Initializes configuration from the specified working directory

      Parameters

      • cwd: string

        The current working directory to search for config files

      Returns {
          additionalSchemaInfo?: string;
          advancedGeneration?:
              | {
                  allowFullTextSearchAutoUpdate: boolean;
                  batchSize: number;
                  enableAdvancedGeneration: boolean;
                  features: {
                      description?: string
                      | null;
                      enabled: boolean;
                      name: string;
                      options?: { name: string; value?: unknown }[] | null;
                      systemPrompt?: string | null;
                      userMessage?: string | null;
                  }[];
              }
              | null;
          allowCrossSchemaCascadeDeletes: boolean;
          baseViewExcludedFields: string[];
          codeGenLogin: string;
          codeGenPassword: string;
          codegenPool?: {
              connectionTimeoutMillis?: number;
              idleTimeoutMillis?: number;
              max?: number;
              min?: number;
              ssl?: boolean
              | Record<string, unknown>;
              statementTimeoutMs?: number;
          };
          commands: {
              args: string[];
              command: string;
              isDaemon?: boolean
              | null;
              timeout?: number | null;
              when: string;
              workingDirectory: string;
          }[];
          customSQLScripts: { scriptFile: string; when: string }[];
          dbDatabase: string;
          dbHost: string;
          dbInstanceName?: string | null;
          dbPlatform: "sqlserver" | "postgresql";
          dbPort: number;
          dbRequestTimeout?: number;
          dbSchemaJSONOutput: {
              bundles: {
                  excludeEntities: string[];
                  excludeSchemas: string[];
                  name: string;
                  schemas: string[];
              }[];
              excludeEntities: string[];
              excludeSchemas: string[];
          };
          dbTrustServerCertificate: "Y"
          | "N";
          entityImportPackages?: Record<string, string>;
          entityNaming: {
              additionalDomainWords: string[];
              normalizeAllCaps: boolean;
              normalizeFieldNames: boolean;
              splitCompoundWords: boolean;
          };
          entityPackageName: string
          | Record<string, string>;
          excludeSchemas: string[];
          excludeTables: ExcludeTableEntry[];
          fileEmit: {
              concurrency: number;
              dirtySchemaOnly: boolean;
              parallel: boolean;
              perSchema: boolean;
              sqlEntityBatchSize: number;
              writeIfChanged: boolean;
          };
          forceRegeneration: {
              allStoredProcedures: boolean;
              baseViews: boolean;
              enabled: boolean;
              entityWhereClause?: string;
              fullTextSearch: boolean;
              indexes: boolean;
              spCreate: boolean;
              spDelete: boolean;
              spUpdate: boolean;
          };
          graphqlPort: number;
          includeSchemas?: string[];
          integrityChecks: { enabled: boolean; entityFieldsSequenceCheck: boolean };
          logging: { console: boolean; log: boolean; logFile: string };
          metadataDirectory?: string;
          metadataInsertBatchSize: number;
          mjCoreSchema: string;
          newEntityDefaults: {
              AddToApplicationWithSchemaName: boolean;
              AllowAllRowsAPI: boolean;
              AllowCaching: boolean;
              AllowCachingBySchema: { AllowCaching: boolean; SchemaName: string }[];
              AllowCreateAPI: boolean;
              AllowDeleteAPI: boolean;
              AllowUpdateAPI: boolean;
              AllowUserSearchAPI: boolean;
              AuditRecordAccess: boolean;
              AuditViewRuns: boolean;
              CascadeDeletes: boolean;
              IncludeFirstNFieldsAsDefaultInView: number;
              NameRulesBySchema: {
                  EntityNamePrefix: string;
                  EntityNameSuffix: string;
                  SchemaName: string;
              }[];
              PermissionDefaults: {
                  AutoAddPermissionsForNewEntities: boolean;
                  Permissions: {
                      CanCreate: boolean;
                      CanDelete: boolean;
                      CanRead: boolean;
                      CanUpdate: boolean;
                      RoleName: string;
                  }[];
              };
              TrackRecordChanges: boolean;
              UserViewMaxRows: number;
          };
          newEntityRelationshipDefaults: {
              AutomaticallyCreateRelationships: boolean;
              CreateOneToManyRelationships: boolean;
          };
          newSchemaDefaults: {
              ApplicationRoleDefaults: {
                  AutoAddRolesForNewApplications: boolean;
                  Roles: { CanAccess: boolean; CanAdmin: boolean; RoleName: string }[];
              };
              CreateNewApplicationWithSchemaName: boolean;
          };
          newUserSetup?: | {
              CreateUserApplicationRecords: boolean;
              Email: string;
              FirstName: string;
              LastName: string;
              Roles: string[];
              UserApplications: string[];
              UserName: string;
          }
          | null;
          output: {
              appendOutputCode?: boolean;
              directory: string;
              options?: { name: string; value?: any }[];
              type: string;
          }[];
          outputCode?: string
          | null;
          schemaOutput?: {
              Angular?: string;
              EntitySubClasses?: string;
              GraphQLServer?: string;
              schema: string;
              skip?: ("EntitySubClasses" | "GraphQLServer" | "Angular" | "SQL")[];
          }[];
          settings: { name: string; value?: any }[];
          SQLOutput: {
              appendToFile: boolean;
              convertCoreSchemaToFlywayMigrationFile: boolean;
              enabled: boolean;
              fileName?: string;
              folderPath: string;
              omitRecurringScriptsFromLog: boolean;
              schemaPlaceholders?: { placeholder: string; schema: string }[];
          };
          startup?: { mode?: "full"
          | "task" };
          verboseOutput: boolean;
      }

      Parsed configuration object

      • OptionaladditionalSchemaInfo?: string

        Path to JSON file containing soft PK/FK definitions for tables without database constraints

      • OptionaladvancedGeneration?:
            | {
                allowFullTextSearchAutoUpdate: boolean;
                batchSize: number;
                enableAdvancedGeneration: boolean;
                features: {
                    description?: string
                    | null;
                    enabled: boolean;
                    name: string;
                    options?: { name: string; value?: unknown }[] | null;
                    systemPrompt?: string | null;
                    userMessage?: string | null;
                }[];
            }
            | null
      • allowCrossSchemaCascadeDeletes: boolean

        When true, CodeGen cascade-delete SQL walks FKs pointing at the entity in EVERY schema in metadata. Default false: only same-schema children. Turning this on (and CascadeDeletes on an entity) will bake consumer schemas into a publisher's delete proc — a dangerous escape hatch. Leave off for Open Apps.

      • baseViewExcludedFields: string[]

        Field names to KEEP OUT of generated base views. Empty by default, and an empty list changes nothing: the base view is emitted as SELECT alias.* exactly as before, byte for byte.

        WHAT THIS IS FOR. A base view is what every read goes through — RunView, BaseEntity.Load, every grid and form. SELECT alias.* means a column no component ever reads is still fetched, deserialised and held in memory on every one of those reads. Measured on one integration mirror: a single JSON bookkeeping column was 52–70% of the table's stored bytes (96 MB of one table's 137 MB), and nothing in the UI read it.

        Entries are matched case-insensitively and may be either a bare field name (applies to every entity that has a column of that name) or EntityName.FieldName (that entity only). An entity with no matching column is emitted unchanged — the explicit column list appears ONLY for entities that actually have something excluded, so the blast radius is exactly the entities you name and nothing else.

        TWO THINGS TO KNOW BEFORE SETTING IT.

        1. An excluded column is GONE from every MJ read of that entity. entity.Get('Field') returns undefined. Writes are unaffected (they go through the CRUD routines against the base table), but any code path that reads the column through metadata must be repointed first.
        2. CodeGen's own field prune (spDeleteUnneededEntityFields) asks "is this column in the base VIEW?", so an excluded column's EntityField row would be deleted on the next run. CodeGen passes the exclusions to the prune as a protected list to prevent that — and REFUSES to apply an exclusion at all on a database whose prune routine does not accept that list, rather than trading a memory win for silent metadata loss. Watch the run log: an exclusion that was refused says so.

        The view also stops auto-absorbing NEW physical columns for the entities that carry an exclusion, because an explicit column list is enumerated at generation time. CodeGen re-enumerates on every run, so a new column appears after the next run rather than immediately.

      • codeGenLogin: string
      • codeGenPassword: string
      • OptionalcodegenPool?: {
            connectionTimeoutMillis?: number;
            idleTimeoutMillis?: number;
            max?: number;
            min?: number;
            ssl?: boolean | Record<string, unknown>;
            statementTimeoutMs?: number;
        }

        Optional CodeGen-time database connection pool configuration.

        Per-provider applicability — not all fields apply to both providers today:

        Field SQL Server PostgreSQL
        statementTimeoutMs ✅ mssql requestTimeout ✅ libpq -c statement_timeout
        max / min / idleTimeoutMillis / connectionTimeoutMillis ❌ ignored ✅ pg.Pool config
        ssl ❌ ignored (SQL Server uses dbTrustServerCertificate + mssql's own SSL) ✅ pg.Pool ssl

        The PG-only pool-sizing knobs reflect the asymmetry between mssql and pg.Pool configurability today; they'll converge in a follow-up. When omitted, each driver's own defaults apply (mssql: 10 max; PGConnectionManager: 20 max, 2 min).

        For runtime (MJAPI) pool settings, see @memberjunction/server's databaseSettings.connectionPool — that is a separate, long-lived service pool and is independent of CodeGen.

        • OptionalconnectionTimeoutMillis?: number

          PostgreSQL only today. New-connection acquisition timeout in ms.

        • OptionalidleTimeoutMillis?: number

          PostgreSQL only today. Idle timeout in ms before a pooled connection is closed.

        • Optionalmax?: number

          PostgreSQL only today. Max pool connections; pg.Pool default 20 when unset.

        • Optionalmin?: number

          PostgreSQL only today. Min idle connections kept open; pg.Pool default 2.

        • Optionalssl?: boolean | Record<string, unknown>

          PostgreSQL only. SSL configuration for the codegen pool. Defaults to false (matches the pre-multi-provider-refactor inline pg.Pool behavior that ran codegen plaintext locally). Set to true for managed PostgreSQL with default trust (e.g. AWS Aurora rds.force_ssl=1); pass an object for full control (e.g. { rejectUnauthorized: true, ca: <CA bundle> }).

          Note: the runtime MJAPI pool (databaseSettings.connectionPool) has its own SSL handling that defaults ON in NODE_ENV=production — this field only governs the short-lived codegen pool.

        • OptionalstatementTimeoutMs?: number

          Per-statement timeout in milliseconds, applied to both providers:

          • SQL Server: mapped to mssql's requestTimeout on the pool config. Takes precedence over the legacy top-level dbRequestTimeout when both are set; falls back to dbRequestTimeout (and ultimately mssql's 120000ms default) when unset.
          • PostgreSQL: applied via the libpq startup option -c statement_timeout=<ms> (carried in pg's connection startup packet), so every backend — including the verify-SELECT-1 connection — honors it from the very first query. When unset, PostgreSQL applies no statement timeout (its default).
      • commands: {
            args: string[];
            command: string;
            isDaemon?: boolean | null;
            timeout?: number | null;
            when: string;
            workingDirectory: string;
        }[]
      • customSQLScripts: { scriptFile: string; when: string }[]
      • dbDatabase: string
      • dbHost: string
      • OptionaldbInstanceName?: string | null
      • dbPlatform: "sqlserver" | "postgresql"

        Database platform: 'sqlserver' or 'postgresql'.

      • dbPort: number
      • OptionaldbRequestTimeout?: number

        Legacy — SQL Server request timeout in milliseconds applied to the CodeGen connection pool. Set in mj.config.cjs or via the MJ_CODEGEN_REQUEST_TIMEOUT environment variable when long-running CodeGen steps (e.g. spUpdateExistingEntityFieldsFromSchema) exceed the default of 120000 (2 minutes).

        Prefer the cross-platform codegenPool.statementTimeoutMs for new configs — it applies to both SQL Server (as requestTimeout) and PostgreSQL (as the per-connection statement_timeout GUC). When both are set on a SQL Server install, codegenPool.statementTimeoutMs wins; dbRequestTimeout remains as a backward-compatible fallback so existing configs keep working unchanged.

      • dbSchemaJSONOutput: {
            bundles: {
                excludeEntities: string[];
                excludeSchemas: string[];
                name: string;
                schemas: string[];
            }[];
            excludeEntities: string[];
            excludeSchemas: string[];
        }
      • dbTrustServerCertificate: "Y" | "N"
      • OptionalentityImportPackages?: Record<string, string>

        Schema → npm package map for peer entity classes this emit does not generate (cross-schema embedded records and related-record collections).

        This is a different knob from entityPackageName and includeSchemas:

        • includeSchemas — what this run generates
        • string entityPackageName — the npm package this run writes those classes into
        • Record entityPackageName — install-time host map; those schemas are also skipped for local generation (getExternalEntitySchemas). Do not overload it on an Open App under development: listing a sibling schema there would skip generating this app if you also listed your own schema, and converting a custom string entityPackageName into a Record silently re-routes every unmapped schema.
        • entityImportPackages — where to import { PeerEntity } from when the peer's schema is not in this file

        Publishers (Open Apps under development) use string entityPackageName + includeSchemas and must list sibling app schemas here. Hosts that already use Record entityPackageName do not need this — that map is the fallback after this one. Case-insensitive schema keys. Mapping a foreign schema to this emit's own package is an error (that would self-import a class this file does not emit).

        resolveEntityImportPackage

      • entityNaming: {
            additionalDomainWords: string[];
            normalizeAllCaps: boolean;
            normalizeFieldNames: boolean;
            splitCompoundWords: boolean;
        }

        Entity and field name normalization settings for ALL CAPS database identifiers

        • additionalDomainWords: string[]

          Additional domain-specific words for the compound word splitter

        • normalizeAllCaps: boolean

          Normalize ALL CAPS table/entity names to Title Case (e.g., PAYMENT -> Payment). Default: true

        • normalizeFieldNames: boolean

          Normalize ALL CAPS column/field names the same way. Default: true

        • splitCompoundWords: boolean

          Split compound ALL CAPS words using dictionary matching (e.g., INDIVIDUALDESIGNATION -> Individual Designation). Default: true

      • entityPackageName: string | Record<string, string>
      • excludeSchemas: string[]
      • excludeTables: ExcludeTableEntry[]
      • fileEmit: {
            concurrency: number;
            dirtySchemaOnly: boolean;
            parallel: boolean;
            perSchema: boolean;
            sqlEntityBatchSize: number;
            writeIfChanged: boolean;
        }

        File-emit behaviour for entity subclasses and GraphQL resolvers. Schema is the incremental unit — see guides/CODEGEN_LARGE_SCHEMA_GUIDE.md.

        • concurrency: number

          Max schemas assembled at once when parallel is true. Default 8.

        • dirtySchemaOnly: boolean

          Rebuild only schemas that contain a new/modified entity (plus any schema whose file is missing). --skipdb file-only runs ignore this and rebuild every schema, still gated by write-if-changed. Default true.

        • parallel: boolean

          Assemble independent schema files in parallel. Default true.

        • perSchema: boolean

          Emit one TypeScript file per schema plus a barrel. Default true.

        • sqlEntityBatchSize: number

          SQL Server per-entity SQL generation width. PostgreSQL stays serial (1) regardless — catalog deadlocks under parallel phased DDL. Default 8.

        • writeIfChanged: boolean

          Skip the disk write when generated bytes are identical. Default true.

      • forceRegeneration: {
            allStoredProcedures: boolean;
            baseViews: boolean;
            enabled: boolean;
            entityWhereClause?: string;
            fullTextSearch: boolean;
            indexes: boolean;
            spCreate: boolean;
            spDelete: boolean;
            spUpdate: boolean;
        }
        • allStoredProcedures: boolean

          Force regeneration of all stored procedures

        • baseViews: boolean

          Force regeneration of base views

        • enabled: boolean

          Force regeneration of all SQL objects even if no schema changes are detected

        • OptionalentityWhereClause?: string

          Optional SQL WHERE clause to filter entities for forced regeneration Example: "SchemaName = 'dbo' AND Name LIKE 'User%'"

        • fullTextSearch: boolean

          Force regeneration of full text search components

        • indexes: boolean

          Force regeneration of indexes for foreign keys

        • spCreate: boolean

          Force regeneration of spCreate procedures

        • spDelete: boolean

          Force regeneration of spDelete procedures

        • spUpdate: boolean

          Force regeneration of spUpdate procedures

      • graphqlPort: number
      • OptionalincludeSchemas?: string[]

        Opt-in POSITIVE scope list. When set (non-empty), CodeGen processes ONLY these schemas — every other schema present in the DATABASE is treated as excluded, including schemas MJ has never seen before. It is pure sugar over excludeSchemas: it is resolved into excludeSchemas (see applyIncludeSchemaScope) before metadata management and again before file generation, so nothing downstream changes. In-scope ⇔ named in includeSchemas AND not in excludeSchemas (include shrinks the addressable space; exclude overlays on top). No hidden auto-includes — a schema, including the MJ core schema, is in scope ONLY if listed explicitly. Leave undefined/empty for the classic exclude-only behavior (unchanged).

        Primary use: scope an Open App's CodeGen to just its own schema without hand-maintaining an exclude list naming every other installed app — a list that is O(N²) to maintain and, more importantly, cannot name schemas the app does not know about (such as a client's own schemas in a deployed instance).

        The in-memory compile into excludeSchemas is for THIS CodeGen run only (which entities to generate). Heal stored-procedure EXEC statements logged into migrations use authored excludeSchemas plus @IncludedSchemaNames from this list — they must not snapshot sibling apps that happened to be installed on the publisher database.

      • integrityChecks: { enabled: boolean; entityFieldsSequenceCheck: boolean }
        • enabled: boolean

          Master switch for the integrity checks. When false no check runs, and runCodeGen warns rather than ticking green — nothing was measured, which is not the same claim as "everything passed".

          There is deliberately NO failOnError knob here. A failing integrity check always fails the run (see runCodeGen): these checks report EntityField Sequence drift, which corrupts the column ordering that spCreate/spUpdate depend on, so there is no state of the world in which a caller wants the finding reported and the run still green. Turning the checks off is the supported way to opt out, and it says so in the output instead of passing silently.

        • entityFieldsSequenceCheck: boolean
      • logging: { console: boolean; log: boolean; logFile: string }
        • console: boolean

          Whether to also log to console

        • log: boolean

          Whether logging is enabled

        • logFile: string

          File path for log output

      • OptionalmetadataDirectory?: string

        Root directory containing metadata files for sync (e.g. './metadata')

      • metadataInsertBatchSize: number

        Number of metadata INSERT statements CodeGen joins into a single batched round-trip when syncing newly-discovered entity fields into the metadata tables (createNewEntityFieldsFromSchema). Each row's INSERT SQL is unchanged and conflict-guarded; this knob only controls how many are terminated, joined, and sent — plus logged to the migration file — per DB round-trip.

        Larger values mean fewer round-trips but a larger SQL string per batch; smaller values trade throughput for smaller batches. These are independent statements (not a multi-row VALUES), so no SQL Server row/parameter limit bounds the value. Defaults to 250, a good balance on large-schema installs (thousands of tables). Applies to both SQL Server and PostgreSQL.

      • mjCoreSchema: string
      • newEntityDefaults: {
            AddToApplicationWithSchemaName: boolean;
            AllowAllRowsAPI: boolean;
            AllowCaching: boolean;
            AllowCachingBySchema: { AllowCaching: boolean; SchemaName: string }[];
            AllowCreateAPI: boolean;
            AllowDeleteAPI: boolean;
            AllowUpdateAPI: boolean;
            AllowUserSearchAPI: boolean;
            AuditRecordAccess: boolean;
            AuditViewRuns: boolean;
            CascadeDeletes: boolean;
            IncludeFirstNFieldsAsDefaultInView: number;
            NameRulesBySchema: {
                EntityNamePrefix: string;
                EntityNameSuffix: string;
                SchemaName: string;
            }[];
            PermissionDefaults: {
                AutoAddPermissionsForNewEntities: boolean;
                Permissions: {
                    CanCreate: boolean;
                    CanDelete: boolean;
                    CanRead: boolean;
                    CanUpdate: boolean;
                    RoleName: string;
                }[];
            };
            TrackRecordChanges: boolean;
            UserViewMaxRows: number;
        }
        • AddToApplicationWithSchemaName: boolean
        • AllowAllRowsAPI: boolean
        • AllowCaching: boolean
        • AllowCachingBySchema: { AllowCaching: boolean; SchemaName: string }[]

          Per-schema overrides for the AllowCaching default. When CodeGen creates a new Entity row, the schema is matched (case-insensitive) against this list and the matching entry's AllowCaching value wins over the global AllowCaching default. Schema names support the ${mj_core_schema} placeholder. Defaults to enabling caching for the MJ core schema.

        • AllowCreateAPI: boolean
        • AllowDeleteAPI: boolean
        • AllowUpdateAPI: boolean
        • AllowUserSearchAPI: boolean
        • AuditRecordAccess: boolean
        • AuditViewRuns: boolean
        • CascadeDeletes: boolean
        • IncludeFirstNFieldsAsDefaultInView: number
        • NameRulesBySchema: { EntityNamePrefix: string; EntityNameSuffix: string; SchemaName: string }[]
        • PermissionDefaults: {
              AutoAddPermissionsForNewEntities: boolean;
              Permissions: {
                  CanCreate: boolean;
                  CanDelete: boolean;
                  CanRead: boolean;
                  CanUpdate: boolean;
                  RoleName: string;
              }[];
          }
        • TrackRecordChanges: boolean
        • UserViewMaxRows: number
      • newEntityRelationshipDefaults: {
            AutomaticallyCreateRelationships: boolean;
            CreateOneToManyRelationships: boolean;
        }
      • newSchemaDefaults: {
            ApplicationRoleDefaults: {
                AutoAddRolesForNewApplications: boolean;
                Roles: { CanAccess: boolean; CanAdmin: boolean; RoleName: string }[];
            };
            CreateNewApplicationWithSchemaName: boolean;
        }
      • OptionalnewUserSetup?:
            | {
                CreateUserApplicationRecords: boolean;
                Email: string;
                FirstName: string;
                LastName: string;
                Roles: string[];
                UserApplications: string[];
                UserName: string;
            }
            | null
      • output: {
            appendOutputCode?: boolean;
            directory: string;
            options?: { name: string; value?: any }[];
            type: string;
        }[]
      • OptionaloutputCode?: string | null
      • OptionalschemaOutput?: {
            Angular?: string;
            EntitySubClasses?: string;
            GraphQLServer?: string;
            schema: string;
            skip?: ("EntitySubClasses" | "GraphQLServer" | "Angular" | "SQL")[];
        }[]

        Route (or skip) generated artifacts for matching schemas to a directory other than the default output.* entry. First match wins.

      • settings: { name: string; value?: any }[]
      • SQLOutput: {
            appendToFile: boolean;
            convertCoreSchemaToFlywayMigrationFile: boolean;
            enabled: boolean;
            fileName?: string;
            folderPath: string;
            omitRecurringScriptsFromLog: boolean;
            schemaPlaceholders?: { placeholder: string; schema: string }[];
        }
        • appendToFile: boolean

          If set to true, then we append to the existing file, if one exists, otherwise we create a new file.

        • convertCoreSchemaToFlywayMigrationFile: boolean

          If true, all mention of the core schema within the log file will be replaced with the flyway schema, ${flyway:defaultSchema}

        • enabled: boolean

          Whether or not sql statements generated while managing metadata should be written to a file

        • OptionalfileName?: string

          Optional, the file name that will be written WITHIN the folderPath specified.

        • folderPath: string

          The path of the folder to use when logging is enabled. If provided, a file will be created with the format "CodeGen_Run_yyyy-mm-dd_hh-mm-ss.sql"

        • omitRecurringScriptsFromLog: boolean

          If true, scripts that are being emitted via SQL logging that are marked by CodeGen as recurring will be SKIPPED. Defaults to true

        • OptionalschemaPlaceholders?: { placeholder: string; schema: string }[]

          Optional array of schema-to-placeholder mappings for Flyway migrations. Each mapping specifies a database schema name and its corresponding Flyway placeholder. If not provided, defaults to replacing the MJ core schema with ${flyway:defaultSchema}.

          Example: [ { schema: '__mj', placeholder: '${mjSchema}' }, { schema: '__BCSaaS', placeholder: '${flyway:defaultSchema}' } ]

      • Optionalstartup?: { mode?: "full" | "task" }

        Startup mode for engine pre-warm during CodeGen's provider bootstrap: 'full' pre-warms all

        engines; 'task' (CodeGen's entry-point default) skips pre-warm — engines lazy-load on first touch. Because mj.config.cjs is shared by every process in a repo, the MJ_STARTUP_MODE env var overrides this per invocation (highest precedence).

      • verboseOutput: boolean

      Error if no configuration is found