49 lines
2.0 KiB
TypeScript
49 lines
2.0 KiB
TypeScript
|
|
import { pgTable, text, timestamp, uniqueIndex } from 'drizzle-orm/pg-core';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Idempotency ledger for one-shot data migrations from external sources
|
||
|
|
* (e.g. the legacy NocoDB Interests table).
|
||
|
|
*
|
||
|
|
* Every entity created during a migration script's `--apply` run gets a
|
||
|
|
* row here mapping the source-system row identifier to the new-system
|
||
|
|
* entity id. Re-running `--apply` against the same report skips rows
|
||
|
|
* already linked, so partial-failure resumption is just "run again."
|
||
|
|
*
|
||
|
|
* One source row can generate multiple new entities (e.g. one NocoDB
|
||
|
|
* Interests row → one client + one interest + one yacht), so the
|
||
|
|
* uniqueness constraint includes `target_entity_type`.
|
||
|
|
*/
|
||
|
|
export const migrationSourceLinks = pgTable(
|
||
|
|
'migration_source_links',
|
||
|
|
{
|
||
|
|
id: text('id')
|
||
|
|
.primaryKey()
|
||
|
|
.$defaultFn(() => crypto.randomUUID()),
|
||
|
|
/** e.g. 'nocodb_interests', 'nocodb_residences', 'nocodb_website_submissions'. */
|
||
|
|
sourceSystem: text('source_system').notNull(),
|
||
|
|
/** Source row identifier as a string (NocoDB IDs are integers; we keep
|
||
|
|
* text here for forward compat with other sources). */
|
||
|
|
sourceId: text('source_id').notNull(),
|
||
|
|
/** e.g. 'client', 'interest', 'yacht', 'document'. */
|
||
|
|
targetEntityType: text('target_entity_type').notNull(),
|
||
|
|
/** UUID of the new-system entity (clients.id, interests.id, etc.). */
|
||
|
|
targetEntityId: text('target_entity_id').notNull(),
|
||
|
|
/** Apply-id from the migration run that created this link — pairs with
|
||
|
|
* the on-disk apply manifest so `--rollback --apply-id <id>` knows
|
||
|
|
* exactly which links to remove. */
|
||
|
|
appliedId: text('applied_id').notNull(),
|
||
|
|
appliedBy: text('applied_by'),
|
||
|
|
appliedAt: timestamp('applied_at', { withTimezone: true }).notNull().defaultNow(),
|
||
|
|
},
|
||
|
|
(table) => [
|
||
|
|
uniqueIndex('idx_msl_source_target').on(
|
||
|
|
table.sourceSystem,
|
||
|
|
table.sourceId,
|
||
|
|
table.targetEntityType,
|
||
|
|
),
|
||
|
|
],
|
||
|
|
);
|
||
|
|
|
||
|
|
export type MigrationSourceLink = typeof migrationSourceLinks.$inferSelect;
|
||
|
|
export type NewMigrationSourceLink = typeof migrationSourceLinks.$inferInsert;
|