@memberjunction/schema-engine 0.0.1 → 5.17.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/DDLGenerator.d.ts +48 -0
- package/dist/DDLGenerator.d.ts.map +1 -0
- package/dist/DDLGenerator.js +159 -0
- package/dist/DDLGenerator.js.map +1 -0
- package/dist/MigrationFileWriter.d.ts +32 -0
- package/dist/MigrationFileWriter.d.ts.map +1 -0
- package/dist/MigrationFileWriter.js +69 -0
- package/dist/MigrationFileWriter.js.map +1 -0
- package/dist/RSUMetrics.d.ts +48 -0
- package/dist/RSUMetrics.d.ts.map +1 -0
- package/dist/RSUMetrics.js +102 -0
- package/dist/RSUMetrics.js.map +1 -0
- package/dist/RuntimeSchemaManager.d.ts +454 -0
- package/dist/RuntimeSchemaManager.d.ts.map +1 -0
- package/dist/RuntimeSchemaManager.js +1395 -0
- package/dist/RuntimeSchemaManager.js.map +1 -0
- package/dist/SchemaEngine.d.ts +51 -0
- package/dist/SchemaEngine.d.ts.map +1 -0
- package/dist/SchemaEngine.js +100 -0
- package/dist/SchemaEngine.js.map +1 -0
- package/dist/SchemaEvolution.d.ts +30 -0
- package/dist/SchemaEvolution.d.ts.map +1 -0
- package/dist/SchemaEvolution.js +95 -0
- package/dist/SchemaEvolution.js.map +1 -0
- package/dist/SchemaValidator.d.ts +22 -0
- package/dist/SchemaValidator.d.ts.map +1 -0
- package/dist/SchemaValidator.js +93 -0
- package/dist/SchemaValidator.js.map +1 -0
- package/dist/SoftFKConfigEmitter.d.ts +59 -0
- package/dist/SoftFKConfigEmitter.d.ts.map +1 -0
- package/dist/SoftFKConfigEmitter.js +87 -0
- package/dist/SoftFKConfigEmitter.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +175 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +9 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +16 -0
- package/dist/utils.js.map +1 -0
- package/package.json +31 -7
- package/README.md +0 -45
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDLGenerator — platform-agnostic DDL generation powered by SQLDialect.
|
|
3
|
+
*
|
|
4
|
+
* All platform-specific behavior lives in SQLDialect implementations
|
|
5
|
+
* from @memberjunction/sql-dialect. DDLGenerator orchestrates the
|
|
6
|
+
* generation of CREATE TABLE, ALTER TABLE, and description metadata
|
|
7
|
+
* without any platform branching.
|
|
8
|
+
*/
|
|
9
|
+
import type { ColumnDefinition, ColumnModification, DatabasePlatform, TableDefinition } from './interfaces.js';
|
|
10
|
+
import { SQLDialect } from '@memberjunction/sql-dialect';
|
|
11
|
+
/**
|
|
12
|
+
* Get the SQLDialect for a given platform string.
|
|
13
|
+
* Throws if the platform is not supported.
|
|
14
|
+
*/
|
|
15
|
+
export declare function GetDialect(platform: DatabasePlatform | string): SQLDialect;
|
|
16
|
+
/**
|
|
17
|
+
* Generates platform-correct DDL SQL for creating and altering tables.
|
|
18
|
+
* Delegates all platform-specific syntax to SQLDialect.
|
|
19
|
+
*/
|
|
20
|
+
export declare class DDLGenerator {
|
|
21
|
+
/**
|
|
22
|
+
* Generate CREATE SCHEMA IF NOT EXISTS statement.
|
|
23
|
+
*/
|
|
24
|
+
GenerateCreateSchema(schemaName: string, platform: DatabasePlatform): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generate a full CREATE TABLE statement.
|
|
27
|
+
*/
|
|
28
|
+
GenerateCreateTable(def: TableDefinition, platform: DatabasePlatform): string;
|
|
29
|
+
/**
|
|
30
|
+
* Generate description metadata for table + columns.
|
|
31
|
+
*/
|
|
32
|
+
GenerateDescriptions(def: TableDefinition, dialect: SQLDialect): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Generate ALTER TABLE ADD COLUMN statement.
|
|
35
|
+
*/
|
|
36
|
+
GenerateAlterTableAddColumn(schemaName: string, tableName: string, column: ColumnDefinition, platform: DatabasePlatform): string;
|
|
37
|
+
/**
|
|
38
|
+
* Generate ALTER TABLE ALTER COLUMN statement for type/nullability changes.
|
|
39
|
+
*/
|
|
40
|
+
GenerateAlterTableAlterColumn(schemaName: string, tableName: string, mod: ColumnModification, platform: DatabasePlatform): string;
|
|
41
|
+
private capPKColumnType;
|
|
42
|
+
private renderColumnLine;
|
|
43
|
+
private renderColumnBody;
|
|
44
|
+
}
|
|
45
|
+
export { ValidateIdentifier, EscapeSqlString } from './utils.js';
|
|
46
|
+
/** Resolve the SQL type for a column via SQLDialect. */
|
|
47
|
+
export declare function resolveSqlType(col: ColumnDefinition, platform: DatabasePlatform): string;
|
|
48
|
+
//# sourceMappingURL=DDLGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DDLGenerator.d.ts","sourceRoot":"","sources":["../src/DDLGenerator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/G,OAAO,EAAE,UAAU,EAAuC,MAAM,6BAA6B,CAAC;AAU9F;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAM1E;AAID;;;GAGG;AACH,qBAAa,YAAY;IACvB;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM;IAK5E;;OAEG;IACH,mBAAmB,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM;IAiD7E;;OAEG;IACH,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE;IAiBzE;;OAEG;IACH,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM;IAkBhI;;OAEG;IACH,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM;IAkBjI,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,gBAAgB;CAWzB;AAGD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEjE,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAOxF"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { SQLServerDialect, PostgreSQLDialect } from '@memberjunction/sql-dialect';
|
|
2
|
+
import { ValidateIdentifier } from './utils.js';
|
|
3
|
+
// ─── Dialect Lookup ─────────────────────────────────────────────────
|
|
4
|
+
const DIALECT_MAP = {
|
|
5
|
+
sqlserver: () => new SQLServerDialect(),
|
|
6
|
+
postgresql: () => new PostgreSQLDialect(),
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Get the SQLDialect for a given platform string.
|
|
10
|
+
* Throws if the platform is not supported.
|
|
11
|
+
*/
|
|
12
|
+
export function GetDialect(platform) {
|
|
13
|
+
const factory = DIALECT_MAP[platform];
|
|
14
|
+
if (!factory) {
|
|
15
|
+
throw new Error(`No SQLDialect registered for "${platform}". Supported: ${Object.keys(DIALECT_MAP).join(', ')}`);
|
|
16
|
+
}
|
|
17
|
+
return factory();
|
|
18
|
+
}
|
|
19
|
+
// ─── DDLGenerator ───────────────────────────────────────────────────
|
|
20
|
+
/**
|
|
21
|
+
* Generates platform-correct DDL SQL for creating and altering tables.
|
|
22
|
+
* Delegates all platform-specific syntax to SQLDialect.
|
|
23
|
+
*/
|
|
24
|
+
export class DDLGenerator {
|
|
25
|
+
/**
|
|
26
|
+
* Generate CREATE SCHEMA IF NOT EXISTS statement.
|
|
27
|
+
*/
|
|
28
|
+
GenerateCreateSchema(schemaName, platform) {
|
|
29
|
+
ValidateIdentifier(schemaName, 'schema');
|
|
30
|
+
return GetDialect(platform).CreateSchemaDDL(schemaName);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Generate a full CREATE TABLE statement.
|
|
34
|
+
*/
|
|
35
|
+
GenerateCreateTable(def, platform) {
|
|
36
|
+
ValidateIdentifier(def.SchemaName, 'schema');
|
|
37
|
+
ValidateIdentifier(def.TableName, 'table');
|
|
38
|
+
const d = GetDialect(platform);
|
|
39
|
+
const q = d.QuoteIdentifier.bind(d);
|
|
40
|
+
const fullTable = `${q(def.SchemaName)}.${q(def.TableName)}`;
|
|
41
|
+
// PK columns in a UNIQUE constraint may need type capping (e.g. SQL Server NVARCHAR(MAX) → 450)
|
|
42
|
+
const pkFieldSet = new Set((def.SoftPrimaryKeys ?? []).map(f => f.toLowerCase()));
|
|
43
|
+
const lines = [];
|
|
44
|
+
for (const col of def.Columns) {
|
|
45
|
+
lines.push(this.renderColumnLine(this.capPKColumnType(col, pkFieldSet, d), d));
|
|
46
|
+
}
|
|
47
|
+
for (const col of def.AdditionalColumns ?? []) {
|
|
48
|
+
lines.push(this.renderColumnLine(this.capPKColumnType(col, pkFieldSet, d), d));
|
|
49
|
+
}
|
|
50
|
+
if (def.SoftPrimaryKeys && def.SoftPrimaryKeys.length > 0) {
|
|
51
|
+
const pkColNames = def.SoftPrimaryKeys.map((f) => {
|
|
52
|
+
ValidateIdentifier(f, 'soft-pk column');
|
|
53
|
+
return q(f);
|
|
54
|
+
}).join(', ');
|
|
55
|
+
const uqName = `UQ_${def.SchemaName}_${def.TableName}_PK`;
|
|
56
|
+
lines.push(` CONSTRAINT ${q(uqName)} UNIQUE (${pkColNames})`);
|
|
57
|
+
}
|
|
58
|
+
for (const fk of def.ForeignKeys?.filter((f) => !f.IsSoft) ?? []) {
|
|
59
|
+
ValidateIdentifier(fk.ColumnName, 'fk column');
|
|
60
|
+
const constraintName = `FK_${def.TableName}_${fk.ColumnName}`;
|
|
61
|
+
lines.push(` CONSTRAINT ${q(constraintName)} FOREIGN KEY (${q(fk.ColumnName)}) ` +
|
|
62
|
+
`REFERENCES ${q(fk.ReferencedSchema)}.${q(fk.ReferencedTable)}(${q(fk.ReferencedColumn)})`);
|
|
63
|
+
}
|
|
64
|
+
const body = lines.join(',\n');
|
|
65
|
+
const createTable = `CREATE TABLE ${fullTable} (\n${body}\n);`;
|
|
66
|
+
const descStatements = this.GenerateDescriptions(def, d);
|
|
67
|
+
if (descStatements.length > 0) {
|
|
68
|
+
return createTable + '\n\n' + descStatements.join('\n\n');
|
|
69
|
+
}
|
|
70
|
+
return createTable;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Generate description metadata for table + columns.
|
|
74
|
+
*/
|
|
75
|
+
GenerateDescriptions(def, dialect) {
|
|
76
|
+
const statements = [];
|
|
77
|
+
const allColumns = [...def.Columns, ...(def.AdditionalColumns ?? [])];
|
|
78
|
+
if (def.Description) {
|
|
79
|
+
statements.push(dialect.CommentOnObject('TABLE', def.SchemaName, def.TableName, def.Description) + ';');
|
|
80
|
+
}
|
|
81
|
+
for (const col of allColumns) {
|
|
82
|
+
if (col.Description) {
|
|
83
|
+
statements.push(dialect.CommentOnColumn(def.SchemaName, def.TableName, col.Name, col.Description));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return statements;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Generate ALTER TABLE ADD COLUMN statement.
|
|
90
|
+
*/
|
|
91
|
+
GenerateAlterTableAddColumn(schemaName, tableName, column, platform) {
|
|
92
|
+
ValidateIdentifier(schemaName, 'schema');
|
|
93
|
+
ValidateIdentifier(tableName, 'table');
|
|
94
|
+
ValidateIdentifier(column.Name, 'column');
|
|
95
|
+
const d = GetDialect(platform);
|
|
96
|
+
const q = d.QuoteIdentifier.bind(d);
|
|
97
|
+
const fullTable = `${q(schemaName)}.${q(tableName)}`;
|
|
98
|
+
const sqlType = column.RawSqlType ?? d.ResolveAbstractType({
|
|
99
|
+
type: column.Type,
|
|
100
|
+
maxLength: column.MaxLength,
|
|
101
|
+
precision: column.Precision,
|
|
102
|
+
scale: column.Scale,
|
|
103
|
+
});
|
|
104
|
+
return `ALTER TABLE ${fullTable}\n ${d.AddColumnClause({ name: column.Name, sqlType, nullable: column.IsNullable, defaultValue: column.DefaultValue ?? undefined })};`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Generate ALTER TABLE ALTER COLUMN statement for type/nullability changes.
|
|
108
|
+
*/
|
|
109
|
+
GenerateAlterTableAlterColumn(schemaName, tableName, mod, platform) {
|
|
110
|
+
ValidateIdentifier(schemaName, 'schema');
|
|
111
|
+
ValidateIdentifier(tableName, 'table');
|
|
112
|
+
ValidateIdentifier(mod.ColumnName, 'column');
|
|
113
|
+
const d = GetDialect(platform);
|
|
114
|
+
const q = d.QuoteIdentifier.bind(d);
|
|
115
|
+
const fullTable = `${q(schemaName)}.${q(tableName)}`;
|
|
116
|
+
return d.AlterColumnDDL(fullTable, {
|
|
117
|
+
columnName: mod.ColumnName,
|
|
118
|
+
newType: mod.NewType,
|
|
119
|
+
newNullable: mod.NewNullable,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// ─── Private helpers ─────────────────────────────────────────────
|
|
123
|
+
capPKColumnType(col, pkFieldSet, dialect) {
|
|
124
|
+
if (pkFieldSet.has(col.Name.toLowerCase()) && col.RawSqlType) {
|
|
125
|
+
const capped = dialect.CapIndexableType(col.RawSqlType);
|
|
126
|
+
if (capped !== col.RawSqlType) {
|
|
127
|
+
return { ...col, RawSqlType: capped };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return col;
|
|
131
|
+
}
|
|
132
|
+
renderColumnLine(col, dialect) {
|
|
133
|
+
ValidateIdentifier(col.Name, 'column');
|
|
134
|
+
return ` ${dialect.QuoteIdentifier(col.Name)} ${this.renderColumnBody(col, dialect)}`;
|
|
135
|
+
}
|
|
136
|
+
renderColumnBody(col, dialect) {
|
|
137
|
+
const sqlType = col.RawSqlType ?? dialect.ResolveAbstractType({
|
|
138
|
+
type: col.Type,
|
|
139
|
+
maxLength: col.MaxLength,
|
|
140
|
+
precision: col.Precision,
|
|
141
|
+
scale: col.Scale,
|
|
142
|
+
});
|
|
143
|
+
const nullable = col.IsNullable ? 'NULL' : 'NOT NULL';
|
|
144
|
+
const defaultExpr = col.DefaultValue != null ? ` DEFAULT ${col.DefaultValue}` : '';
|
|
145
|
+
return `${sqlType} ${nullable}${defaultExpr}`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ─── Re-exports (backward compatibility) ────────────────────────────
|
|
149
|
+
export { ValidateIdentifier, EscapeSqlString } from './utils.js';
|
|
150
|
+
/** Resolve the SQL type for a column via SQLDialect. */
|
|
151
|
+
export function resolveSqlType(col, platform) {
|
|
152
|
+
return col.RawSqlType ?? GetDialect(platform).ResolveAbstractType({
|
|
153
|
+
type: col.Type,
|
|
154
|
+
maxLength: col.MaxLength,
|
|
155
|
+
precision: col.Precision,
|
|
156
|
+
scale: col.Scale,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=DDLGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DDLGenerator.js","sourceRoot":"","sources":["../src/DDLGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MigrationFileWriter — wraps DDL in properly-named Flyway migration files.
|
|
3
|
+
* Generic: no integration-specific assumptions.
|
|
4
|
+
* File-emission only — returns EmittedFile objects, never writes to disk.
|
|
5
|
+
*/
|
|
6
|
+
import type { EmittedFile, MigrationMetadata } from './interfaces.js';
|
|
7
|
+
/**
|
|
8
|
+
* Produces Flyway-compatible migration file names and content.
|
|
9
|
+
*/
|
|
10
|
+
export declare class MigrationFileWriter {
|
|
11
|
+
/**
|
|
12
|
+
* Generate a Flyway-compatible migration file name.
|
|
13
|
+
* Format: {migrationsDir}/V{YYYYMMDDHHMM}__v{VERSION}.x_{Consumer}_{ObjectName}_{Action}.sql
|
|
14
|
+
*
|
|
15
|
+
* Example: migrations/v5/V202603120230__v5.10.x_Integration_HubSpot_CreateTables.sql
|
|
16
|
+
*/
|
|
17
|
+
GenerateMigrationFileName(objectName: string, action: string, mjVersion: string, migrationsDir: string, timestamp: Date, consumer?: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Wrap DDL content in a migration file with a standard header comment.
|
|
20
|
+
*/
|
|
21
|
+
WrapInMigrationFile(ddl: string, metadata: MigrationMetadata, filePath: string): EmittedFile;
|
|
22
|
+
/**
|
|
23
|
+
* Generate a sequence of timestamps, each 1 minute apart,
|
|
24
|
+
* for ordering multiple migrations produced in a single pass.
|
|
25
|
+
*/
|
|
26
|
+
GenerateTimestampSequence(count: number, startTime?: Date): Date[];
|
|
27
|
+
}
|
|
28
|
+
/** Format a Date as YYYYMMDDHHMM for Flyway versioning. */
|
|
29
|
+
export declare function FormatTimestamp(date: Date): string;
|
|
30
|
+
/** Remove characters unsafe for Flyway file names. */
|
|
31
|
+
export declare function SanitizeForFileName(input: string): string;
|
|
32
|
+
//# sourceMappingURL=MigrationFileWriter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationFileWriter.d.ts","sourceRoot":"","sources":["../src/MigrationFileWriter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtE;;GAEG;AACH,qBAAa,mBAAmB;IAC5B;;;;;OAKG;IACH,yBAAyB,CACrB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,IAAI,EACf,QAAQ,SAAW,GACpB,MAAM;IAQT;;OAEG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW;IAwB5F;;;OAGG;IACH,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,IAAiB,GAAG,IAAI,EAAE;CAOjF;AAID,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAOlD;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Produces Flyway-compatible migration file names and content.
|
|
3
|
+
*/
|
|
4
|
+
export class MigrationFileWriter {
|
|
5
|
+
/**
|
|
6
|
+
* Generate a Flyway-compatible migration file name.
|
|
7
|
+
* Format: {migrationsDir}/V{YYYYMMDDHHMM}__v{VERSION}.x_{Consumer}_{ObjectName}_{Action}.sql
|
|
8
|
+
*
|
|
9
|
+
* Example: migrations/v5/V202603120230__v5.10.x_Integration_HubSpot_CreateTables.sql
|
|
10
|
+
*/
|
|
11
|
+
GenerateMigrationFileName(objectName, action, mjVersion, migrationsDir, timestamp, consumer = 'Schema') {
|
|
12
|
+
const ts = FormatTimestamp(timestamp);
|
|
13
|
+
const safeObj = SanitizeForFileName(objectName);
|
|
14
|
+
const safeAction = SanitizeForFileName(action);
|
|
15
|
+
const safeConsumer = SanitizeForFileName(consumer);
|
|
16
|
+
return `${migrationsDir}/V${ts}__v${mjVersion}.x_${safeConsumer}_${safeObj}_${safeAction}.sql`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Wrap DDL content in a migration file with a standard header comment.
|
|
20
|
+
*/
|
|
21
|
+
WrapInMigrationFile(ddl, metadata, filePath) {
|
|
22
|
+
const header = [
|
|
23
|
+
`-- ============================================================`,
|
|
24
|
+
`-- Auto-generated by MJ SchemaEngine`,
|
|
25
|
+
`-- Consumer: ${metadata.SourceType} | Object: ${metadata.ObjectName}`,
|
|
26
|
+
`-- Action: ${metadata.Action}`,
|
|
27
|
+
`-- Generated: ${metadata.Timestamp}`,
|
|
28
|
+
`-- Generated By: ${metadata.GeneratedBy}`,
|
|
29
|
+
`-- ============================================================`,
|
|
30
|
+
`-- NOTE: __mj_CreatedAt, __mj_UpdatedAt, FK indexes, views, and SPs`,
|
|
31
|
+
`-- are created by CodeGen — do NOT add them here.`,
|
|
32
|
+
`-- NOTE: Soft foreign keys are defined in additionalSchemaInfo,`,
|
|
33
|
+
`-- applied by CodeGen — no FK constraints needed in this migration.`,
|
|
34
|
+
`-- ============================================================`,
|
|
35
|
+
``,
|
|
36
|
+
].join('\n');
|
|
37
|
+
return {
|
|
38
|
+
FilePath: filePath,
|
|
39
|
+
Content: header + ddl + '\n',
|
|
40
|
+
Description: `Migration: ${metadata.Action} for ${metadata.SourceType}.${metadata.ObjectName}`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Generate a sequence of timestamps, each 1 minute apart,
|
|
45
|
+
* for ordering multiple migrations produced in a single pass.
|
|
46
|
+
*/
|
|
47
|
+
GenerateTimestampSequence(count, startTime = new Date()) {
|
|
48
|
+
const result = [];
|
|
49
|
+
for (let i = 0; i < count; i++) {
|
|
50
|
+
result.push(new Date(startTime.getTime() + i * 60_000));
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ─── Helpers ────────────────────────────────────────────────────────
|
|
56
|
+
/** Format a Date as YYYYMMDDHHMM for Flyway versioning. */
|
|
57
|
+
export function FormatTimestamp(date) {
|
|
58
|
+
const y = date.getUTCFullYear();
|
|
59
|
+
const mo = String(date.getUTCMonth() + 1).padStart(2, '0');
|
|
60
|
+
const d = String(date.getUTCDate()).padStart(2, '0');
|
|
61
|
+
const h = String(date.getUTCHours()).padStart(2, '0');
|
|
62
|
+
const mi = String(date.getUTCMinutes()).padStart(2, '0');
|
|
63
|
+
return `${y}${mo}${d}${h}${mi}`;
|
|
64
|
+
}
|
|
65
|
+
/** Remove characters unsafe for Flyway file names. */
|
|
66
|
+
export function SanitizeForFileName(input) {
|
|
67
|
+
return input.replace(/[^A-Za-z0-9_]/g, '');
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=MigrationFileWriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationFileWriter.js","sourceRoot":"","sources":["../src/MigrationFileWriter.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAC5B;;;;;OAKG;IACH,yBAAyB,CACrB,UAAkB,EAClB,MAAc,EACd,SAAiB,EACjB,aAAqB,EACrB,SAAe,EACf,QAAQ,GAAG,QAAQ;QAEnB,MAAM,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACnD,OAAO,GAAG,aAAa,KAAK,EAAE,MAAM,SAAS,MAAM,YAAY,IAAI,OAAO,IAAI,UAAU,MAAM,CAAC;IACnG,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,GAAW,EAAE,QAA2B,EAAE,QAAgB;QAC1E,MAAM,MAAM,GAAG;YACX,iEAAiE;YACjE,sCAAsC;YACtC,gBAAgB,QAAQ,CAAC,UAAU,cAAc,QAAQ,CAAC,UAAU,EAAE;YACtE,cAAc,QAAQ,CAAC,MAAM,EAAE;YAC/B,iBAAiB,QAAQ,CAAC,SAAS,EAAE;YACrC,oBAAoB,QAAQ,CAAC,WAAW,EAAE;YAC1C,iEAAiE;YACjE,qEAAqE;YACrE,yDAAyD;YACzD,iEAAiE;YACjE,2EAA2E;YAC3E,iEAAiE;YACjE,EAAE;SACL,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,OAAO;YACH,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;YAC5B,WAAW,EAAE,cAAc,QAAQ,CAAC,MAAM,QAAQ,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,UAAU,EAAE;SACjG,CAAC;IACN,CAAC;IAED;;;OAGG;IACH,yBAAyB,CAAC,KAAa,EAAE,YAAkB,IAAI,IAAI,EAAE;QACjE,MAAM,MAAM,GAAW,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ;AAED,uEAAuE;AAEvE,2DAA2D;AAC3D,MAAM,UAAU,eAAe,CAAC,IAAU;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IAChC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACrD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACzD,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC;AACpC,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC7C,OAAO,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RSU Pipeline Metrics — tracks pipeline execution statistics for observability.
|
|
3
|
+
* Singleton that accumulates metrics across pipeline runs.
|
|
4
|
+
*/
|
|
5
|
+
import { BaseSingleton } from '@memberjunction/global';
|
|
6
|
+
export interface PipelineRunMetric {
|
|
7
|
+
Timestamp: Date;
|
|
8
|
+
DurationMs: number;
|
|
9
|
+
Success: boolean;
|
|
10
|
+
StepDurations: Record<string, number>;
|
|
11
|
+
ErrorStep?: string;
|
|
12
|
+
Description: string;
|
|
13
|
+
AffectedTables: string[];
|
|
14
|
+
RetryCount: number;
|
|
15
|
+
}
|
|
16
|
+
export interface RSUMetricsSummary {
|
|
17
|
+
TotalRuns: number;
|
|
18
|
+
SuccessfulRuns: number;
|
|
19
|
+
FailedRuns: number;
|
|
20
|
+
SuccessRate: number;
|
|
21
|
+
AverageDurationMs: number;
|
|
22
|
+
MedianDurationMs: number;
|
|
23
|
+
P95DurationMs: number;
|
|
24
|
+
MostCommonErrorStep: string | null;
|
|
25
|
+
RecentRuns: PipelineRunMetric[];
|
|
26
|
+
StepAverageDurations: Record<string, number>;
|
|
27
|
+
}
|
|
28
|
+
export declare class RSUMetrics extends BaseSingleton<RSUMetrics> {
|
|
29
|
+
protected constructor();
|
|
30
|
+
static get Instance(): RSUMetrics;
|
|
31
|
+
private runs;
|
|
32
|
+
private readonly MAX_HISTORY;
|
|
33
|
+
/**
|
|
34
|
+
* Record a completed pipeline run.
|
|
35
|
+
*/
|
|
36
|
+
RecordRun(metric: PipelineRunMetric): void;
|
|
37
|
+
/**
|
|
38
|
+
* Get a summary of all recorded metrics.
|
|
39
|
+
*/
|
|
40
|
+
GetSummary(): RSUMetricsSummary;
|
|
41
|
+
private FindMostCommonErrorStep;
|
|
42
|
+
private ComputeStepAverages;
|
|
43
|
+
/** Clear all recorded metrics. */
|
|
44
|
+
Clear(): void;
|
|
45
|
+
/** Get raw run history. */
|
|
46
|
+
GetHistory(): ReadonlyArray<PipelineRunMetric>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=RSUMetrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RSUMetrics.d.ts","sourceRoot":"","sources":["../src/RSUMetrics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD;AAED,qBAAa,UAAW,SAAQ,aAAa,CAAC,UAAU,CAAC;IACrD,SAAS;IAIT,WAAkB,QAAQ,IAAI,UAAU,CAEvC;IAED,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAO;IAEnC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAO1C;;OAEG;IACH,UAAU,IAAI,iBAAiB;IAqC/B,OAAO,CAAC,uBAAuB;IAkB/B,OAAO,CAAC,mBAAmB;IAiB3B,kCAAkC;IAClC,KAAK,IAAI,IAAI;IAIb,2BAA2B;IAC3B,UAAU,IAAI,aAAa,CAAC,iBAAiB,CAAC;CAGjD"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RSU Pipeline Metrics — tracks pipeline execution statistics for observability.
|
|
3
|
+
* Singleton that accumulates metrics across pipeline runs.
|
|
4
|
+
*/
|
|
5
|
+
import { BaseSingleton } from '@memberjunction/global';
|
|
6
|
+
export class RSUMetrics extends BaseSingleton {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.runs = [];
|
|
10
|
+
this.MAX_HISTORY = 100;
|
|
11
|
+
}
|
|
12
|
+
static get Instance() {
|
|
13
|
+
return super.getInstance();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Record a completed pipeline run.
|
|
17
|
+
*/
|
|
18
|
+
RecordRun(metric) {
|
|
19
|
+
this.runs.push(metric);
|
|
20
|
+
if (this.runs.length > this.MAX_HISTORY) {
|
|
21
|
+
this.runs = this.runs.slice(-this.MAX_HISTORY);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get a summary of all recorded metrics.
|
|
26
|
+
*/
|
|
27
|
+
GetSummary() {
|
|
28
|
+
const total = this.runs.length;
|
|
29
|
+
if (total === 0) {
|
|
30
|
+
return {
|
|
31
|
+
TotalRuns: 0,
|
|
32
|
+
SuccessfulRuns: 0,
|
|
33
|
+
FailedRuns: 0,
|
|
34
|
+
SuccessRate: 0,
|
|
35
|
+
AverageDurationMs: 0,
|
|
36
|
+
MedianDurationMs: 0,
|
|
37
|
+
P95DurationMs: 0,
|
|
38
|
+
MostCommonErrorStep: null,
|
|
39
|
+
RecentRuns: [],
|
|
40
|
+
StepAverageDurations: {},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const successful = this.runs.filter(r => r.Success).length;
|
|
44
|
+
const durations = this.runs.map(r => r.DurationMs).sort((a, b) => a - b);
|
|
45
|
+
const mostCommonErrorStep = this.FindMostCommonErrorStep();
|
|
46
|
+
const stepAverageDurations = this.ComputeStepAverages();
|
|
47
|
+
return {
|
|
48
|
+
TotalRuns: total,
|
|
49
|
+
SuccessfulRuns: successful,
|
|
50
|
+
FailedRuns: total - successful,
|
|
51
|
+
SuccessRate: Math.round((successful / total) * 100) / 100,
|
|
52
|
+
AverageDurationMs: Math.round(durations.reduce((a, b) => a + b, 0) / total),
|
|
53
|
+
MedianDurationMs: durations[Math.floor(total / 2)],
|
|
54
|
+
P95DurationMs: durations[Math.floor(total * 0.95)],
|
|
55
|
+
MostCommonErrorStep: mostCommonErrorStep,
|
|
56
|
+
RecentRuns: this.runs.slice(-10).reverse(),
|
|
57
|
+
StepAverageDurations: stepAverageDurations,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
FindMostCommonErrorStep() {
|
|
61
|
+
const counts = new Map();
|
|
62
|
+
for (const run of this.runs) {
|
|
63
|
+
if (run.ErrorStep) {
|
|
64
|
+
counts.set(run.ErrorStep, (counts.get(run.ErrorStep) ?? 0) + 1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
let best = null;
|
|
68
|
+
let bestCount = 0;
|
|
69
|
+
for (const [step, count] of counts) {
|
|
70
|
+
if (count > bestCount) {
|
|
71
|
+
bestCount = count;
|
|
72
|
+
best = step;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return best;
|
|
76
|
+
}
|
|
77
|
+
ComputeStepAverages() {
|
|
78
|
+
const totals = new Map();
|
|
79
|
+
for (const run of this.runs) {
|
|
80
|
+
for (const [step, duration] of Object.entries(run.StepDurations)) {
|
|
81
|
+
const existing = totals.get(step) ?? { sum: 0, count: 0 };
|
|
82
|
+
existing.sum += duration;
|
|
83
|
+
existing.count += 1;
|
|
84
|
+
totals.set(step, existing);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const result = {};
|
|
88
|
+
for (const [step, data] of totals) {
|
|
89
|
+
result[step] = Math.round(data.sum / data.count);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/** Clear all recorded metrics. */
|
|
94
|
+
Clear() {
|
|
95
|
+
this.runs = [];
|
|
96
|
+
}
|
|
97
|
+
/** Get raw run history. */
|
|
98
|
+
GetHistory() {
|
|
99
|
+
return this.runs;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=RSUMetrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RSUMetrics.js","sourceRoot":"","sources":["../src/RSUMetrics.ts"],"names":[],"mappings":"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"}
|