Files
kevisual-noco/auto/migration /index.ts
2025-12-13 23:20:26 +08:00

122 lines
3.9 KiB
TypeScript

import { NocoApi } from "../../src/index.ts";
type TableOptions = {
fromTableId: string;
fromNoco?: NocoApi;
toNoco?: NocoApi;
toBaseId?: string;
}
export class TableMigration {
fromTableId: string;
fromNoco: NocoApi;
toNoco: NocoApi;
toBaseId: string;
constructor(options: TableOptions) {
this.fromTableId = options.fromTableId;
this.fromNoco = options.fromNoco!;
this.toNoco = options.toNoco!;
this.toBaseId = options.toBaseId!;
}
async migrate() {
const res = await this.migrateTable();
console.log('migrate table result:', res);
this.toNoco.record.table = res.id;
this.fromNoco.record.table = this.fromTableId;
const fromTable = await this.fromNoco?.record.list({ limit: 2000 });
const list = fromTable?.data.list || [];
let _list = list.map(item => {
delete item['CreatedAt'];
delete item['UpdatedAt'];
return item;
});
console.log('_list', _list.length);
const newRecord = await this.toNoco.record.create(_list);
console.log('migrate success:', this.fromTableId);
}
async hasTable(title: string): Promise<{ id: string, exists?: boolean }> {
const res = await this.toNoco?.meta.tables.list(this.toBaseId);
const tables = res?.data?.list || [];
for (const table of tables) {
if (table.title === title) {
return { id: table.id, exists: true };
}
}
return { id: '' };
}
async migrateTable() {
const res = await this.fromNoco?.meta.tables.getTableMeta(this.fromTableId);
const columns = res?.data.columns;
const title = res?.data.title;
const hasTableRes = await this.hasTable(title || '');
if (hasTableRes.id) {
return hasTableRes;
}
const clearCoulmns = ['nc_order', 'nc_created_by', 'nc_created_at', 'nc_updated_by', 'nc_updated_at', 'nc_owner_role', 'nc_owner_user', 'nc_status', 'CreatedAt', 'UpdatedAt'];
const _newColumns = [];
for (const col of columns || []) {
const createColData = {
title: col.title,
uidt: col.uidt,
description: col.description,
pk: col.pk,
pv: col.pv,
rqd: col.rqd,
cdf: col.cdf,
colOptions: col.colOptions,
};
if (clearCoulmns.includes(col.title)) {
continue;
}
_newColumns.push(createColData);
}
const createRes = await this.toNoco.meta.tables.createTable(this.toBaseId, {
title: res?.data.title || 'Migrated Table',
description: res?.data.description || '',
columns: _newColumns,
});
return { id: createRes.data.id };
}
}
export class BaseMigration {
fromBaseId: string;
toNoco: NocoApi;
toBaseId: string;
fromNoco: NocoApi;
constructor(options: { toNoco: NocoApi; toBaseId: string, fromNoco: NocoApi; fromBaseId: string }) {
this.toNoco = options.toNoco;
this.toBaseId = options.toBaseId;
this.fromNoco = options.fromNoco;
this.fromBaseId = options.fromBaseId;
}
async getTableList() {
const res = await this.fromNoco?.meta.tables.list(this.fromBaseId);
return res?.data?.list || [];
}
async migrate(options?: MigrateOptions) {
const tableList = await this.getTableList();
const excludeTables = options?.excludeTables || [];
const includeTables = options?.includeTables || [];
for (const table of tableList) {
if (excludeTables.includes(table.title || '')) {
console.log('skip table:', table.title);
continue;
}
if (includeTables.length > 0 && !includeTables.includes(table.title || '')) {
console.log('skip table not in include list:', table.title);
continue;
}
const tableMigration = new TableMigration({
fromTableId: table.id,
fromNoco: this.fromNoco,
toNoco: this.toNoco,
toBaseId: this.toBaseId,
});
await tableMigration.migrate();
}
}
}
type MigrateOptions = {
excludeTables?: string[];
includeTables?: string[];
}