@happyvertical/smrt-core 0.43.6 → 0.43.8
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/agents/schema-paths.md +12 -4
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/migrations/differ.d.ts +2 -1
- package/dist/migrations/differ.d.ts.map +1 -1
- package/dist/migrations/differ.js +63 -11
- package/dist/migrations/differ.js.map +1 -1
- package/dist/schema/foreign-key-ddl.d.ts +10 -1
- package/dist/schema/foreign-key-ddl.d.ts.map +1 -1
- package/dist/schema/foreign-key-ddl.js +28 -10
- package/dist/schema/foreign-key-ddl.js.map +1 -1
- package/dist/schema/schema-manager.d.ts +8 -1
- package/dist/schema/schema-manager.d.ts.map +1 -1
- package/dist/schema/schema-manager.js +55 -4
- package/dist/schema/schema-manager.js.map +1 -1
- package/dist/smrt-knowledge.json +5 -5
- package/package.json +10 -10
|
@@ -318,7 +318,7 @@ var SchemaComparer = class {
|
|
|
318
318
|
diff.added_tables.push(schema);
|
|
319
319
|
diff.has_changes = true;
|
|
320
320
|
} else {
|
|
321
|
-
const tableChanges = await this.compareTable(tableName, schema);
|
|
321
|
+
const tableChanges = await this.compareTable(tableName, schema, manifestSchemas);
|
|
322
322
|
if (tableChanges.length > 0) {
|
|
323
323
|
diff.changes.push(...tableChanges);
|
|
324
324
|
if (tableChanges.some((change) => !isInfoOnlyChange(change))) diff.has_changes = true;
|
|
@@ -340,7 +340,7 @@ var SchemaComparer = class {
|
|
|
340
340
|
/**
|
|
341
341
|
* Compare a single table's schema to manifest
|
|
342
342
|
*/
|
|
343
|
-
async compareTable(tableName, manifest) {
|
|
343
|
+
async compareTable(tableName, manifest, manifestSchemas = {}) {
|
|
344
344
|
const changes = [];
|
|
345
345
|
const dbSchema = await this.db.getTableSchema?.(tableName);
|
|
346
346
|
if (!dbSchema) return changes;
|
|
@@ -354,10 +354,10 @@ var SchemaComparer = class {
|
|
|
354
354
|
const dbIndexPredicates = await this.getDbIndexPredicates(tableName);
|
|
355
355
|
const indexChanges = this.compareIndexes(tableName, manifest, dbSchema, dbIndexPredicates);
|
|
356
356
|
changes.push(...indexChanges);
|
|
357
|
-
changes.push(...await this.compareForeignKeys(tableName, manifest, dbSchema));
|
|
357
|
+
changes.push(...await this.compareForeignKeys(tableName, manifest, dbSchema, manifestSchemas));
|
|
358
358
|
return changes;
|
|
359
359
|
}
|
|
360
|
-
async compareForeignKeys(tableName, manifest, dbSchema) {
|
|
360
|
+
async compareForeignKeys(tableName, manifest, dbSchema, manifestSchemas) {
|
|
361
361
|
const changes = [];
|
|
362
362
|
const liveForeignKeys = dbSchema.foreignKeys || [];
|
|
363
363
|
const declaredForeignKeys = schemaForeignKeys(manifest);
|
|
@@ -392,8 +392,18 @@ var SchemaComparer = class {
|
|
|
392
392
|
const expectedDelete = foreignKey.onDelete === void 0 ? "NO ACTION" : requireForeignKeyAction(foreignKey.onDelete, `${tableName}.${foreignKey.column} ON DELETE`);
|
|
393
393
|
const expectedUpdate = foreignKey.onUpdate === void 0 ? "NO ACTION" : requireForeignKeyAction(foreignKey.onUpdate, `${tableName}.${foreignKey.column} ON UPDATE`);
|
|
394
394
|
if (liveForeignKeys.some((live) => live.column === foreignKey.column && live.referencesTable === foreignKey.referencesTable && live.referencesColumn === foreignKey.referencesColumn && (normalizeForeignKeyAction(live.onDelete) || "NO ACTION") === expectedDelete && (normalizeForeignKeyAction(live.onUpdate) || "NO ACTION") === expectedUpdate)) continue;
|
|
395
|
-
const
|
|
396
|
-
const
|
|
395
|
+
const orphanOptions = await this.getForeignKeyOrphanOptions(tableName, manifest, dbSchema, foreignKey, manifestSchemas);
|
|
396
|
+
const detectorSql = renderForeignKeyOrphanDetector(tableName, foreignKey, {
|
|
397
|
+
engine: this.engine,
|
|
398
|
+
uuidComparison: orphanOptions.uuidComparison,
|
|
399
|
+
uuidCastSide: orphanOptions.uuidCastSide
|
|
400
|
+
});
|
|
401
|
+
const repairSql = renderForeignKeyOrphanRepair(tableName, foreignKey, {
|
|
402
|
+
engine: this.engine,
|
|
403
|
+
uuidComparison: orphanOptions.uuidComparison,
|
|
404
|
+
uuidCastSide: orphanOptions.uuidCastSide,
|
|
405
|
+
nullable: orphanOptions.nullable
|
|
406
|
+
});
|
|
397
407
|
if (liveForeignKeys.some((live) => live.column === foreignKey.column)) {
|
|
398
408
|
changes.push({
|
|
399
409
|
type: "add_foreign_key",
|
|
@@ -423,7 +433,7 @@ var SchemaComparer = class {
|
|
|
423
433
|
});
|
|
424
434
|
continue;
|
|
425
435
|
}
|
|
426
|
-
if (Boolean(dbSchema.columns[foreignKey.column]) && await this.foreignKeyHasOrphans(tableName, foreignKey)) {
|
|
436
|
+
if (Boolean(dbSchema.columns[foreignKey.column]) && await this.foreignKeyHasOrphans(tableName, foreignKey, orphanOptions)) {
|
|
427
437
|
changes.push({
|
|
428
438
|
type: "add_foreign_key",
|
|
429
439
|
table: tableName,
|
|
@@ -448,15 +458,57 @@ var SchemaComparer = class {
|
|
|
448
458
|
}
|
|
449
459
|
return changes;
|
|
450
460
|
}
|
|
451
|
-
async foreignKeyHasOrphans(tableName, foreignKey) {
|
|
461
|
+
async foreignKeyHasOrphans(tableName, foreignKey, options) {
|
|
452
462
|
try {
|
|
453
|
-
const result = await this.db.query(renderForeignKeyOrphanDetector(tableName, foreignKey, {
|
|
463
|
+
const result = await this.db.query(renderForeignKeyOrphanDetector(tableName, foreignKey, {
|
|
464
|
+
engine: this.engine,
|
|
465
|
+
limitOne: true,
|
|
466
|
+
uuidComparison: options.uuidComparison,
|
|
467
|
+
uuidCastSide: options.uuidCastSide
|
|
468
|
+
}));
|
|
454
469
|
return (Array.isArray(result) ? result : result.rows || []).length > 0;
|
|
455
470
|
} catch (error) {
|
|
456
|
-
|
|
457
|
-
return true;
|
|
471
|
+
throw new Error(`[SchemaComparer] Cannot probe ${tableName}.${foreignKey.column} for orphan rows; refusing automatic constraint addition: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
458
472
|
}
|
|
459
473
|
}
|
|
474
|
+
async getForeignKeyOrphanOptions(tableName, manifest, dbSchema, foreignKey, manifestSchemas) {
|
|
475
|
+
const sourceColumn = manifest.columns[foreignKey.column];
|
|
476
|
+
const targetColumn = manifestSchemas[foreignKey.referencesTable]?.columns[foreignKey.referencesColumn];
|
|
477
|
+
const nullable = sourceColumn?.notNull !== true;
|
|
478
|
+
const uuidComparison = sourceColumn?.type === "UUID" && (targetColumn === void 0 || targetColumn.type === "UUID");
|
|
479
|
+
if (!uuidComparison) return {
|
|
480
|
+
nullable,
|
|
481
|
+
uuidComparison
|
|
482
|
+
};
|
|
483
|
+
const parentSchema = foreignKey.referencesTable === tableName ? dbSchema : await this.db.getTableSchema?.(foreignKey.referencesTable);
|
|
484
|
+
const childType = dbSchema.columns[foreignKey.column]?.type;
|
|
485
|
+
const parentType = parentSchema?.columns[foreignKey.referencesColumn]?.type;
|
|
486
|
+
if (!childType || !parentType) return {
|
|
487
|
+
nullable,
|
|
488
|
+
uuidComparison
|
|
489
|
+
};
|
|
490
|
+
const childTypeNormalized = this.normalizeType(childType);
|
|
491
|
+
const parentTypeNormalized = this.normalizeType(parentType);
|
|
492
|
+
if (childTypeNormalized === parentTypeNormalized) return {
|
|
493
|
+
nullable,
|
|
494
|
+
uuidComparison: false
|
|
495
|
+
};
|
|
496
|
+
if (childTypeNormalized === "UUID") return {
|
|
497
|
+
nullable,
|
|
498
|
+
uuidComparison,
|
|
499
|
+
uuidCastSide: "parent"
|
|
500
|
+
};
|
|
501
|
+
if (parentTypeNormalized === "UUID") return {
|
|
502
|
+
nullable,
|
|
503
|
+
uuidComparison,
|
|
504
|
+
uuidCastSide: "child"
|
|
505
|
+
};
|
|
506
|
+
return {
|
|
507
|
+
nullable,
|
|
508
|
+
uuidComparison,
|
|
509
|
+
uuidCastSide: "both"
|
|
510
|
+
};
|
|
511
|
+
}
|
|
460
512
|
/**
|
|
461
513
|
* Compare columns between manifest and database.
|
|
462
514
|
*
|