@memberjunction/integration-schema-builder 0.0.1 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AccessControl.d.ts +26 -0
- package/dist/AccessControl.d.ts.map +1 -0
- package/dist/AccessControl.js +68 -0
- package/dist/AccessControl.js.map +1 -0
- package/dist/DDLGenerator.d.ts +37 -0
- package/dist/DDLGenerator.d.ts.map +1 -0
- package/dist/DDLGenerator.js +155 -0
- package/dist/DDLGenerator.js.map +1 -0
- package/dist/MetadataEmitter.d.ts +23 -0
- package/dist/MetadataEmitter.d.ts.map +1 -0
- package/dist/MetadataEmitter.js +52 -0
- package/dist/MetadataEmitter.js.map +1 -0
- package/dist/MigrationFileWriter.d.ts +25 -0
- package/dist/MigrationFileWriter.d.ts.map +1 -0
- package/dist/MigrationFileWriter.js +67 -0
- package/dist/MigrationFileWriter.js.map +1 -0
- package/dist/SchemaBuilder.d.ts +27 -0
- package/dist/SchemaBuilder.d.ts.map +1 -0
- package/dist/SchemaBuilder.js +177 -0
- package/dist/SchemaBuilder.js.map +1 -0
- package/dist/SchemaEvolution.d.ts +27 -0
- package/dist/SchemaEvolution.d.ts.map +1 -0
- package/dist/SchemaEvolution.js +91 -0
- package/dist/SchemaEvolution.js.map +1 -0
- package/dist/SoftFKConfigEmitter.d.ts +53 -0
- package/dist/SoftFKConfigEmitter.d.ts.map +1 -0
- package/dist/SoftFKConfigEmitter.js +140 -0
- package/dist/SoftFKConfigEmitter.js.map +1 -0
- package/dist/TypeMapper.d.ts +25 -0
- package/dist/TypeMapper.d.ts.map +1 -0
- package/dist/TypeMapper.js +72 -0
- package/dist/TypeMapper.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +182 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +8 -0
- package/dist/interfaces.js.map +1 -0
- package/package.json +28 -7
- package/README.md +0 -45
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AccessControl — enforces which MJ entities can be targeted by integrations.
|
|
3
|
+
* Two layers: hardcoded blocklist + EntitySetting check for __mj entities.
|
|
4
|
+
*/
|
|
5
|
+
import type { AccessControlResult } from './interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* Check if an entity is on the hardcoded blocklist.
|
|
8
|
+
*/
|
|
9
|
+
export declare function IsEntityBlocked(entityName: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Check if an integration is allowed to write to a given entity.
|
|
12
|
+
*
|
|
13
|
+
* Rules:
|
|
14
|
+
* 1. Blocked entities → always denied
|
|
15
|
+
* 2. Non-__mj schema entities → always allowed (custom schemas are user-controlled)
|
|
16
|
+
* 3. __mj entities → allowed only if IntegrationWriteAllowed = 'true' in EntitySettings
|
|
17
|
+
*/
|
|
18
|
+
export declare function IsIntegrationWriteAllowed(entityName: string, schemaName: string, entitySettings: Array<{
|
|
19
|
+
Name: string;
|
|
20
|
+
Value: string;
|
|
21
|
+
}>): AccessControlResult;
|
|
22
|
+
/**
|
|
23
|
+
* Get the list of blocked entity names.
|
|
24
|
+
*/
|
|
25
|
+
export declare function GetBlockedEntities(): ReadonlyArray<string>;
|
|
26
|
+
//# sourceMappingURL=AccessControl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessControl.d.ts","sourceRoot":"","sources":["../src/AccessControl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAuB3D;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACrC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GACvD,mBAAmB,CA6BrB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,aAAa,CAAC,MAAM,CAAC,CAE1D"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System entities that can NEVER be integration targets, regardless of settings.
|
|
3
|
+
*/
|
|
4
|
+
const BLOCKED_ENTITIES = [
|
|
5
|
+
'MJ: Entities',
|
|
6
|
+
'MJ: Entity Fields',
|
|
7
|
+
'MJ: Entity Relationships',
|
|
8
|
+
'MJ: Entity Permissions',
|
|
9
|
+
'Users',
|
|
10
|
+
'Roles',
|
|
11
|
+
'User Roles',
|
|
12
|
+
'Role Permissions',
|
|
13
|
+
'Applications',
|
|
14
|
+
'Application Entities',
|
|
15
|
+
'MJ: Entity Settings',
|
|
16
|
+
'MJ: Encryption Keys',
|
|
17
|
+
'MJ: Encryption Algorithms',
|
|
18
|
+
'MJ: Audit Log Types',
|
|
19
|
+
'MJ: Audit Logs',
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Check if an entity is on the hardcoded blocklist.
|
|
23
|
+
*/
|
|
24
|
+
export function IsEntityBlocked(entityName) {
|
|
25
|
+
return BLOCKED_ENTITIES.includes(entityName);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if an integration is allowed to write to a given entity.
|
|
29
|
+
*
|
|
30
|
+
* Rules:
|
|
31
|
+
* 1. Blocked entities → always denied
|
|
32
|
+
* 2. Non-__mj schema entities → always allowed (custom schemas are user-controlled)
|
|
33
|
+
* 3. __mj entities → allowed only if IntegrationWriteAllowed = 'true' in EntitySettings
|
|
34
|
+
*/
|
|
35
|
+
export function IsIntegrationWriteAllowed(entityName, schemaName, entitySettings) {
|
|
36
|
+
if (IsEntityBlocked(entityName)) {
|
|
37
|
+
return {
|
|
38
|
+
Allowed: false,
|
|
39
|
+
Reason: `Entity "${entityName}" is on the system blocklist and cannot be an integration target.`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Non-__mj schemas are always allowed
|
|
43
|
+
if (schemaName !== '__mj') {
|
|
44
|
+
return {
|
|
45
|
+
Allowed: true,
|
|
46
|
+
Reason: `Entity "${entityName}" is in custom schema "${schemaName}" — integration writes allowed.`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// __mj entity — check for IntegrationWriteAllowed setting
|
|
50
|
+
const setting = entitySettings.find(s => s.Name === 'IntegrationWriteAllowed');
|
|
51
|
+
if (setting && setting.Value === 'true') {
|
|
52
|
+
return {
|
|
53
|
+
Allowed: true,
|
|
54
|
+
Reason: `Entity "${entityName}" has IntegrationWriteAllowed=true.`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
Allowed: false,
|
|
59
|
+
Reason: `Entity "${entityName}" is in __mj schema and does not have IntegrationWriteAllowed=true.`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get the list of blocked entity names.
|
|
64
|
+
*/
|
|
65
|
+
export function GetBlockedEntities() {
|
|
66
|
+
return BLOCKED_ENTITIES;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=AccessControl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessControl.js","sourceRoot":"","sources":["../src/AccessControl.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,gBAAgB,GAA0B;IAC5C,cAAc;IACd,mBAAmB;IACnB,0BAA0B;IAC1B,wBAAwB;IACxB,OAAO;IACP,OAAO;IACP,YAAY;IACZ,kBAAkB;IAClB,cAAc;IACd,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,2BAA2B;IAC3B,qBAAqB;IACrB,gBAAgB;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,UAAkB;IAC9C,OAAO,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CACrC,UAAkB,EAClB,UAAkB,EAClB,cAAsD;IAEtD,IAAI,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO;YACH,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,WAAW,UAAU,mEAAmE;SACnG,CAAC;IACN,CAAC;IAED,sCAAsC;IACtC,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO;YACH,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,WAAW,UAAU,0BAA0B,UAAU,iCAAiC;SACrG,CAAC;IACN,CAAC;IAED,0DAA0D;IAC1D,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,yBAAyB,CAAC,CAAC;IAC/E,IAAI,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QACtC,OAAO;YACH,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,WAAW,UAAU,qCAAqC;SACrE,CAAC;IACN,CAAC;IAED,OAAO;QACH,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,WAAW,UAAU,qEAAqE;KACrG,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAC9B,OAAO,gBAAgB,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDLGenerator — produces CREATE TABLE / ALTER TABLE SQL strings.
|
|
3
|
+
* File-emission only — never executes SQL.
|
|
4
|
+
*/
|
|
5
|
+
import type { DatabasePlatform, TargetColumnConfig, TargetTableConfig, ColumnModification } from './interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* Generates DDL SQL for creating and altering integration tables.
|
|
8
|
+
*/
|
|
9
|
+
export declare class DDLGenerator {
|
|
10
|
+
/**
|
|
11
|
+
* Generate CREATE SCHEMA IF NOT EXISTS statement.
|
|
12
|
+
*/
|
|
13
|
+
GenerateCreateSchema(schemaName: string, platform: DatabasePlatform): string;
|
|
14
|
+
/**
|
|
15
|
+
* Generate a full CREATE TABLE statement.
|
|
16
|
+
* PK fields keep their natural names from the source system and get a UNIQUE constraint.
|
|
17
|
+
* Standard integration columns (__mj_integration_*) are added automatically.
|
|
18
|
+
*/
|
|
19
|
+
GenerateCreateTable(config: TargetTableConfig, platform: DatabasePlatform): string;
|
|
20
|
+
/**
|
|
21
|
+
* Generate sp_addextendedproperty calls for table and column descriptions.
|
|
22
|
+
*/
|
|
23
|
+
GenerateExtendedProperties(config: TargetTableConfig): string[];
|
|
24
|
+
private MakeColumnExtendedProperty;
|
|
25
|
+
/**
|
|
26
|
+
* Generate ALTER TABLE ADD COLUMN statement.
|
|
27
|
+
*/
|
|
28
|
+
GenerateAlterTableAddColumn(schemaName: string, tableName: string, column: TargetColumnConfig, platform: DatabasePlatform): string;
|
|
29
|
+
/**
|
|
30
|
+
* Generate ALTER TABLE ALTER COLUMN statement for type/nullability changes.
|
|
31
|
+
*/
|
|
32
|
+
GenerateAlterTableAlterColumn(schemaName: string, tableName: string, mod: ColumnModification, platform: DatabasePlatform): string;
|
|
33
|
+
private StandardColumns;
|
|
34
|
+
}
|
|
35
|
+
/** Validates that an identifier contains only safe characters. */
|
|
36
|
+
export declare function ValidateIdentifier(name: string, kind: string): void;
|
|
37
|
+
//# sourceMappingURL=DDLGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DDLGenerator.d.ts","sourceRoot":"","sources":["../src/DDLGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAKnH;;GAEG;AACH,qBAAa,YAAY;IACrB;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM;IAQ5E;;;;OAIG;IACH,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM;IAyClF;;OAEG;IACH,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,EAAE;IAqC/D,OAAO,CAAC,0BAA0B;IAclC;;OAEG;IACH,2BAA2B,CACvB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,gBAAgB,GAC3B,MAAM;IAgBT;;OAEG;IACH,6BAA6B,CACzB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,gBAAgB,GAC3B,MAAM;IAeT,OAAO,CAAC,eAAe;CAa1B;AAYD,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAInE"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/** Characters allowed in identifiers (schema, table, column names). */
|
|
2
|
+
const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3
|
+
/**
|
|
4
|
+
* Generates DDL SQL for creating and altering integration tables.
|
|
5
|
+
*/
|
|
6
|
+
export class DDLGenerator {
|
|
7
|
+
/**
|
|
8
|
+
* Generate CREATE SCHEMA IF NOT EXISTS statement.
|
|
9
|
+
*/
|
|
10
|
+
GenerateCreateSchema(schemaName, platform) {
|
|
11
|
+
ValidateIdentifier(schemaName, 'schema');
|
|
12
|
+
if (platform === 'sqlserver') {
|
|
13
|
+
return `IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = '${schemaName}')\n EXEC('CREATE SCHEMA [${schemaName}]');\nGO`;
|
|
14
|
+
}
|
|
15
|
+
return `CREATE SCHEMA IF NOT EXISTS "${schemaName}";`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generate a full CREATE TABLE statement.
|
|
19
|
+
* PK fields keep their natural names from the source system and get a UNIQUE constraint.
|
|
20
|
+
* Standard integration columns (__mj_integration_*) are added automatically.
|
|
21
|
+
*/
|
|
22
|
+
GenerateCreateTable(config, platform) {
|
|
23
|
+
ValidateIdentifier(config.SchemaName, 'schema');
|
|
24
|
+
ValidateIdentifier(config.TableName, 'table');
|
|
25
|
+
const q = platform === 'sqlserver' ? QuoteSqlServer : QuotePostgres;
|
|
26
|
+
const fullTable = `${q(config.SchemaName)}.${q(config.TableName)}`;
|
|
27
|
+
const lines = [];
|
|
28
|
+
// User-configured columns (includes PK fields as regular columns)
|
|
29
|
+
for (const col of config.Columns) {
|
|
30
|
+
ValidateIdentifier(col.TargetColumnName, 'column');
|
|
31
|
+
const nullable = col.IsNullable ? 'NULL' : 'NOT NULL';
|
|
32
|
+
const defaultExpr = col.DefaultValue != null ? ` DEFAULT ${col.DefaultValue}` : '';
|
|
33
|
+
lines.push(` ${q(col.TargetColumnName)} ${col.TargetSqlType} ${nullable}${defaultExpr}`);
|
|
34
|
+
}
|
|
35
|
+
// Standard integration columns (prefixed to avoid collisions)
|
|
36
|
+
lines.push(...this.StandardColumns(platform));
|
|
37
|
+
// UNIQUE constraint on PK field(s) — no DB-level PK, soft PK via additionalSchemaInfo
|
|
38
|
+
if (config.PrimaryKeyFields.length > 0) {
|
|
39
|
+
const pkColNames = config.PrimaryKeyFields.map(f => q(f)).join(', ');
|
|
40
|
+
const uqName = `UQ_${config.SchemaName}_${config.TableName}_PK`;
|
|
41
|
+
lines.push(` CONSTRAINT ${q(uqName)} UNIQUE (${pkColNames})`);
|
|
42
|
+
}
|
|
43
|
+
const body = lines.join(',\n');
|
|
44
|
+
const createTable = `CREATE TABLE ${fullTable} (\n${body}\n);`;
|
|
45
|
+
// Generate extended properties for descriptions (SQL Server only)
|
|
46
|
+
if (platform === 'sqlserver') {
|
|
47
|
+
const extProps = this.GenerateExtendedProperties(config);
|
|
48
|
+
if (extProps.length > 0) {
|
|
49
|
+
return createTable + '\n\n' + extProps.join('\n\n');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return createTable;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Generate sp_addextendedproperty calls for table and column descriptions.
|
|
56
|
+
*/
|
|
57
|
+
GenerateExtendedProperties(config) {
|
|
58
|
+
const props = [];
|
|
59
|
+
// Table-level description
|
|
60
|
+
if (config.Description) {
|
|
61
|
+
const escaped = EscapeSqlString(config.Description);
|
|
62
|
+
props.push(`EXEC sp_addextendedproperty\n` +
|
|
63
|
+
` @name = N'MS_Description',\n` +
|
|
64
|
+
` @value = N'${escaped}',\n` +
|
|
65
|
+
` @level0type = N'SCHEMA', @level0name = '${config.SchemaName}',\n` +
|
|
66
|
+
` @level1type = N'TABLE', @level1name = '${config.TableName}';`);
|
|
67
|
+
}
|
|
68
|
+
// Standard column descriptions
|
|
69
|
+
const standardDescriptions = {
|
|
70
|
+
'__mj_integration_SyncStatus': 'Current sync status: Active, Archived, or Error',
|
|
71
|
+
'__mj_integration_LastSyncedAt': 'Timestamp of the last successful sync for this record',
|
|
72
|
+
};
|
|
73
|
+
for (const [colName, desc] of Object.entries(standardDescriptions)) {
|
|
74
|
+
props.push(this.MakeColumnExtendedProperty(config.SchemaName, config.TableName, colName, desc));
|
|
75
|
+
}
|
|
76
|
+
// User-configured column descriptions
|
|
77
|
+
for (const col of config.Columns) {
|
|
78
|
+
if (col.Description) {
|
|
79
|
+
props.push(this.MakeColumnExtendedProperty(config.SchemaName, config.TableName, col.TargetColumnName, col.Description));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return props;
|
|
83
|
+
}
|
|
84
|
+
MakeColumnExtendedProperty(schemaName, tableName, columnName, description) {
|
|
85
|
+
const escaped = EscapeSqlString(description);
|
|
86
|
+
return (`EXEC sp_addextendedproperty\n` +
|
|
87
|
+
` @name = N'MS_Description',\n` +
|
|
88
|
+
` @value = N'${escaped}',\n` +
|
|
89
|
+
` @level0type = N'SCHEMA', @level0name = '${schemaName}',\n` +
|
|
90
|
+
` @level1type = N'TABLE', @level1name = '${tableName}',\n` +
|
|
91
|
+
` @level2type = N'COLUMN', @level2name = '${columnName}';`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Generate ALTER TABLE ADD COLUMN statement.
|
|
95
|
+
*/
|
|
96
|
+
GenerateAlterTableAddColumn(schemaName, tableName, column, platform) {
|
|
97
|
+
ValidateIdentifier(schemaName, 'schema');
|
|
98
|
+
ValidateIdentifier(tableName, 'table');
|
|
99
|
+
ValidateIdentifier(column.TargetColumnName, 'column');
|
|
100
|
+
const q = platform === 'sqlserver' ? QuoteSqlServer : QuotePostgres;
|
|
101
|
+
const fullTable = `${q(schemaName)}.${q(tableName)}`;
|
|
102
|
+
const nullable = column.IsNullable ? 'NULL' : 'NOT NULL';
|
|
103
|
+
const defaultExpr = column.DefaultValue != null ? ` DEFAULT ${column.DefaultValue}` : '';
|
|
104
|
+
if (platform === 'sqlserver') {
|
|
105
|
+
return `ALTER TABLE ${fullTable}\n ADD ${q(column.TargetColumnName)} ${column.TargetSqlType} ${nullable}${defaultExpr};`;
|
|
106
|
+
}
|
|
107
|
+
return `ALTER TABLE ${fullTable}\n ADD COLUMN ${q(column.TargetColumnName)} ${column.TargetSqlType} ${nullable}${defaultExpr};`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Generate ALTER TABLE ALTER COLUMN statement for type/nullability changes.
|
|
111
|
+
*/
|
|
112
|
+
GenerateAlterTableAlterColumn(schemaName, tableName, mod, platform) {
|
|
113
|
+
ValidateIdentifier(schemaName, 'schema');
|
|
114
|
+
ValidateIdentifier(tableName, 'table');
|
|
115
|
+
ValidateIdentifier(mod.ColumnName, 'column');
|
|
116
|
+
const q = platform === 'sqlserver' ? QuoteSqlServer : QuotePostgres;
|
|
117
|
+
const fullTable = `${q(schemaName)}.${q(tableName)}`;
|
|
118
|
+
const nullable = mod.NewNullable ? 'NULL' : 'NOT NULL';
|
|
119
|
+
if (platform === 'sqlserver') {
|
|
120
|
+
return `ALTER TABLE ${fullTable}\n ALTER COLUMN ${q(mod.ColumnName)} ${mod.NewType} ${nullable};`;
|
|
121
|
+
}
|
|
122
|
+
return `ALTER TABLE ${fullTable}\n ALTER COLUMN ${q(mod.ColumnName)} TYPE ${mod.NewType},\n ALTER COLUMN ${q(mod.ColumnName)} ${mod.NewNullable ? 'DROP NOT NULL' : 'SET NOT NULL'};`;
|
|
123
|
+
}
|
|
124
|
+
StandardColumns(platform) {
|
|
125
|
+
const q = platform === 'sqlserver' ? QuoteSqlServer : QuotePostgres;
|
|
126
|
+
if (platform === 'sqlserver') {
|
|
127
|
+
return [
|
|
128
|
+
` ${q('__mj_integration_SyncStatus')} NVARCHAR(50) NOT NULL DEFAULT 'Active'`,
|
|
129
|
+
` ${q('__mj_integration_LastSyncedAt')} DATETIMEOFFSET NULL`,
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
return [
|
|
133
|
+
` ${q('__mj_integration_SyncStatus')} VARCHAR(50) NOT NULL DEFAULT 'Active'`,
|
|
134
|
+
` ${q('__mj_integration_LastSyncedAt')} TIMESTAMPTZ NULL`,
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// ─── Helpers ────────────────────────────────────────────────────────
|
|
139
|
+
function QuoteSqlServer(name) {
|
|
140
|
+
return `[${name}]`;
|
|
141
|
+
}
|
|
142
|
+
function QuotePostgres(name) {
|
|
143
|
+
return `"${name}"`;
|
|
144
|
+
}
|
|
145
|
+
/** Validates that an identifier contains only safe characters. */
|
|
146
|
+
export function ValidateIdentifier(name, kind) {
|
|
147
|
+
if (!IDENTIFIER_RE.test(name)) {
|
|
148
|
+
throw new Error(`Invalid ${kind} name "${name}": must match ${IDENTIFIER_RE.source}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** Escapes single quotes in a string for use in SQL string literals. */
|
|
152
|
+
function EscapeSqlString(value) {
|
|
153
|
+
return value.replace(/'/g, "''");
|
|
154
|
+
}
|
|
155
|
+
//# 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,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataEmitter — produces /metadata/ JSON files for mj-sync.
|
|
3
|
+
* Generates EntitySettings (e.g., IntegrationWriteAllowed) and mj-sync config.
|
|
4
|
+
*/
|
|
5
|
+
import type { EmittedFile } from './interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* Produces metadata JSON files for the mj-sync push pipeline.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MetadataEmitter {
|
|
10
|
+
/**
|
|
11
|
+
* Generate a single EntitySettings JSON object for an entity.
|
|
12
|
+
*/
|
|
13
|
+
GenerateEntitySettingsRecord(entityName: string, settings: Record<string, string>): Record<string, unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* Emit the IntegrationWriteAllowed EntitySettings file for a set of entities.
|
|
16
|
+
*/
|
|
17
|
+
EmitEntitySettingsFile(entityNames: string[], metadataDir: string): EmittedFile;
|
|
18
|
+
/**
|
|
19
|
+
* Emit the .mj-sync.json config for the entity-settings directory.
|
|
20
|
+
*/
|
|
21
|
+
EmitMjSyncConfig(metadataDir: string): EmittedFile;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=MetadataEmitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetadataEmitter.d.ts","sourceRoot":"","sources":["../src/MetadataEmitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;GAEG;AACH,qBAAa,eAAe;IACxB;;OAEG;IACH,4BAA4B,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAoB3G;;OAEG;IACH,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,WAAW;IAY/E;;OAEG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW;CAYrD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Produces metadata JSON files for the mj-sync push pipeline.
|
|
3
|
+
*/
|
|
4
|
+
export class MetadataEmitter {
|
|
5
|
+
/**
|
|
6
|
+
* Generate a single EntitySettings JSON object for an entity.
|
|
7
|
+
*/
|
|
8
|
+
GenerateEntitySettingsRecord(entityName, settings) {
|
|
9
|
+
const settingsRecords = Object.entries(settings).map(([name, value]) => ({
|
|
10
|
+
fields: {
|
|
11
|
+
Name: name,
|
|
12
|
+
Value: value,
|
|
13
|
+
Comments: `Managed by Integration Schema Builder`,
|
|
14
|
+
},
|
|
15
|
+
}));
|
|
16
|
+
return {
|
|
17
|
+
fields: { Name: entityName },
|
|
18
|
+
relatedEntities: {
|
|
19
|
+
'MJ: Entity Settings': settingsRecords,
|
|
20
|
+
},
|
|
21
|
+
primaryKey: {
|
|
22
|
+
ID: `@lookup:MJ: Entities.Name=${entityName}`,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Emit the IntegrationWriteAllowed EntitySettings file for a set of entities.
|
|
28
|
+
*/
|
|
29
|
+
EmitEntitySettingsFile(entityNames, metadataDir) {
|
|
30
|
+
const records = entityNames.map(name => this.GenerateEntitySettingsRecord(name, { IntegrationWriteAllowed: 'true' }));
|
|
31
|
+
return {
|
|
32
|
+
FilePath: `${metadataDir}/entity-settings/.integration-write-allowed.json`,
|
|
33
|
+
Content: JSON.stringify(records, null, 2) + '\n',
|
|
34
|
+
Description: `EntitySettings: IntegrationWriteAllowed=true for ${entityNames.join(', ')}`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Emit the .mj-sync.json config for the entity-settings directory.
|
|
39
|
+
*/
|
|
40
|
+
EmitMjSyncConfig(metadataDir) {
|
|
41
|
+
const config = {
|
|
42
|
+
entity: 'MJ: Entities',
|
|
43
|
+
filePattern: '**/.*.json',
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
FilePath: `${metadataDir}/entity-settings/.mj-sync.json`,
|
|
47
|
+
Content: JSON.stringify(config, null, 2) + '\n',
|
|
48
|
+
Description: 'mj-sync configuration for entity-settings directory',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=MetadataEmitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetadataEmitter.js","sourceRoot":"","sources":["../src/MetadataEmitter.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,OAAO,eAAe;IACxB;;OAEG;IACH,4BAA4B,CAAC,UAAkB,EAAE,QAAgC;QAC7E,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YACrE,MAAM,EAAE;gBACJ,IAAI,EAAE,IAAI;gBACV,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,uCAAuC;aACpD;SACJ,CAAC,CAAC,CAAC;QAEJ,OAAO;YACH,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,eAAe,EAAE;gBACb,qBAAqB,EAAE,eAAe;aACzC;YACD,UAAU,EAAE;gBACR,EAAE,EAAE,6BAA6B,UAAU,EAAE;aAChD;SACJ,CAAC;IACN,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,WAAqB,EAAE,WAAmB;QAC7D,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACnC,IAAI,CAAC,4BAA4B,CAAC,IAAI,EAAE,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,CAC/E,CAAC;QAEF,OAAO;YACH,QAAQ,EAAE,GAAG,WAAW,kDAAkD;YAC1E,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI;YAChD,WAAW,EAAE,oDAAoD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC5F,CAAC;IACN,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,WAAmB;QAChC,MAAM,MAAM,GAAG;YACX,MAAM,EAAE,cAAc;YACtB,WAAW,EAAE,YAAY;SAC5B,CAAC;QAEF,OAAO;YACH,QAAQ,EAAE,GAAG,WAAW,gCAAgC;YACxD,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI;YAC/C,WAAW,EAAE,qDAAqD;SACrE,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MigrationFileWriter — wraps DDL in properly-named Flyway migration files.
|
|
3
|
+
* File-emission only — produces EmittedFile objects, never writes to disk.
|
|
4
|
+
*/
|
|
5
|
+
import type { EmittedFile, MigrationMetadata } from './interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* Produces Flyway-compatible migration file names and content.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MigrationFileWriter {
|
|
10
|
+
/**
|
|
11
|
+
* Generate a Flyway-compatible migration file name.
|
|
12
|
+
* Format: V{YYYYMMDDHHMM}__v{VERSION}.x_Integration_{Source}_{Action}.sql
|
|
13
|
+
*/
|
|
14
|
+
GenerateMigrationFileName(sourceType: string, action: string, mjVersion: string, migrationsDir: string, timestamp: Date): string;
|
|
15
|
+
/**
|
|
16
|
+
* Wrap DDL content in a migration file with a header comment.
|
|
17
|
+
*/
|
|
18
|
+
WrapInMigrationFile(ddl: string, metadata: MigrationMetadata, filePath: string): EmittedFile;
|
|
19
|
+
/**
|
|
20
|
+
* Generate a sequence of timestamps, each 1 minute apart,
|
|
21
|
+
* for ordering multiple migrations correctly.
|
|
22
|
+
*/
|
|
23
|
+
GenerateTimestampSequence(count: number, startTime?: Date): Date[];
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=MigrationFileWriter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationFileWriter.d.ts","sourceRoot":"","sources":["../src/MigrationFileWriter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtE;;GAEG;AACH,qBAAa,mBAAmB;IAC5B;;;OAGG;IACH,yBAAyB,CACrB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,IAAI,GAChB,MAAM;IAOT;;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;CAQjF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
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: V{YYYYMMDDHHMM}__v{VERSION}.x_Integration_{Source}_{Action}.sql
|
|
8
|
+
*/
|
|
9
|
+
GenerateMigrationFileName(sourceType, action, mjVersion, migrationsDir, timestamp) {
|
|
10
|
+
const ts = FormatTimestamp(timestamp);
|
|
11
|
+
const safeSrc = SanitizeForFileName(sourceType);
|
|
12
|
+
const safeAction = SanitizeForFileName(action);
|
|
13
|
+
return `${migrationsDir}/V${ts}__v${mjVersion}.x_Integration_${safeSrc}_${safeAction}.sql`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Wrap DDL content in a migration file with a header comment.
|
|
17
|
+
*/
|
|
18
|
+
WrapInMigrationFile(ddl, metadata, filePath) {
|
|
19
|
+
const header = [
|
|
20
|
+
`-- ============================================================`,
|
|
21
|
+
`-- Auto-generated by MJ Integration Schema Builder`,
|
|
22
|
+
`-- Source: ${metadata.SourceType} | Object: ${metadata.ObjectName}`,
|
|
23
|
+
`-- Action: ${metadata.Action}`,
|
|
24
|
+
`-- Generated: ${metadata.Timestamp}`,
|
|
25
|
+
`-- Generated By: ${metadata.GeneratedBy}`,
|
|
26
|
+
`-- ============================================================`,
|
|
27
|
+
`-- NOTE: __mj_CreatedAt, __mj_UpdatedAt, FK indexes, views, and SPs`,
|
|
28
|
+
`-- are created by CodeGen — do NOT add them here.`,
|
|
29
|
+
`-- NOTE: Foreign keys are soft FKs defined in additionalSchemaInfo,`,
|
|
30
|
+
`-- applied by CodeGen — no FK constraints in this migration.`,
|
|
31
|
+
`-- ============================================================`,
|
|
32
|
+
``,
|
|
33
|
+
].join('\n');
|
|
34
|
+
return {
|
|
35
|
+
FilePath: filePath,
|
|
36
|
+
Content: header + ddl + '\n',
|
|
37
|
+
Description: `Migration: ${metadata.Action} for ${metadata.SourceType}.${metadata.ObjectName}`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Generate a sequence of timestamps, each 1 minute apart,
|
|
42
|
+
* for ordering multiple migrations correctly.
|
|
43
|
+
*/
|
|
44
|
+
GenerateTimestampSequence(count, startTime = new Date()) {
|
|
45
|
+
const result = [];
|
|
46
|
+
for (let i = 0; i < count; i++) {
|
|
47
|
+
const ts = new Date(startTime.getTime() + i * 60_000);
|
|
48
|
+
result.push(ts);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ─── Helpers ────────────────────────────────────────────────────────
|
|
54
|
+
/** Format a Date as YYYYMMDDHHMM for Flyway versioning. */
|
|
55
|
+
function FormatTimestamp(date) {
|
|
56
|
+
const y = date.getUTCFullYear();
|
|
57
|
+
const mo = String(date.getUTCMonth() + 1).padStart(2, '0');
|
|
58
|
+
const d = String(date.getUTCDate()).padStart(2, '0');
|
|
59
|
+
const h = String(date.getUTCHours()).padStart(2, '0');
|
|
60
|
+
const mi = String(date.getUTCMinutes()).padStart(2, '0');
|
|
61
|
+
return `${y}${mo}${d}${h}${mi}`;
|
|
62
|
+
}
|
|
63
|
+
/** Remove characters unsafe for file names. */
|
|
64
|
+
function SanitizeForFileName(input) {
|
|
65
|
+
return input.replace(/[^A-Za-z0-9_]/g, '');
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=MigrationFileWriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationFileWriter.js","sourceRoot":"","sources":["../src/MigrationFileWriter.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAC5B;;;OAGG;IACH,yBAAyB,CACrB,UAAkB,EAClB,MAAc,EACd,SAAiB,EACjB,aAAqB,EACrB,SAAe;QAEf,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,OAAO,GAAG,aAAa,KAAK,EAAE,MAAM,SAAS,kBAAkB,OAAO,IAAI,UAAU,MAAM,CAAC;IAC/F,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,GAAW,EAAE,QAA2B,EAAE,QAAgB;QAC1E,MAAM,MAAM,GAAG;YACX,iEAAiE;YACjE,oDAAoD;YACpD,cAAc,QAAQ,CAAC,UAAU,cAAc,QAAQ,CAAC,UAAU,EAAE;YACpE,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,qEAAqE;YACrE,oEAAoE;YACpE,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,EAAE,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ;AAED,uEAAuE;AAEvE,2DAA2D;AAC3D,SAAS,eAAe,CAAC,IAAU;IAC/B,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,+CAA+C;AAC/C,SAAS,mBAAmB,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SchemaBuilder — orchestrates the full schema generation pipeline.
|
|
3
|
+
* Pure function: takes input → produces output files. Never touches the database.
|
|
4
|
+
*/
|
|
5
|
+
import type { SchemaBuilderInput, SchemaBuilderOutput } from './interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* Main entry point for the Integration Schema Builder.
|
|
8
|
+
* Coordinates DDL generation, soft FK emission, metadata emission, and evolution diffs.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SchemaBuilder {
|
|
11
|
+
private readonly DDL;
|
|
12
|
+
private readonly MigrationWriter;
|
|
13
|
+
private readonly SoftFKEmitter;
|
|
14
|
+
private readonly MetaEmitter;
|
|
15
|
+
private readonly Evolution;
|
|
16
|
+
/**
|
|
17
|
+
* Build all artifacts for a set of integration target tables.
|
|
18
|
+
*/
|
|
19
|
+
BuildSchema(input: SchemaBuilderInput): SchemaBuilderOutput;
|
|
20
|
+
private ValidateAccessControl;
|
|
21
|
+
private CheckCollisions;
|
|
22
|
+
private ClassifyConfigs;
|
|
23
|
+
private GetUniqueSchemas;
|
|
24
|
+
private CollectSoftFKs;
|
|
25
|
+
private MakeMigrationMeta;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=SchemaBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaBuilder.d.ts","sourceRoot":"","sources":["../src/SchemaBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAKR,kBAAkB,EAClB,mBAAmB,EAGtB,MAAM,iBAAiB,CAAC;AAQzB;;;GAGG;AACH,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAC1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB;IAqG3D,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,iBAAiB;CAS5B"}
|