Major version update. Major bugfixes. Security vulnerabilites fixed
This commit is contained in:
Vendored
+78
-16
@@ -1,38 +1,96 @@
|
||||
import { Command } from "commander";
|
||||
import { SQLiteSchemaManager } from "../lib/sqlite/db-schema-manager";
|
||||
import init from "../functions/init";
|
||||
import createDBSchema from "../lib/schema/create-db-schema";
|
||||
import grabDirNames from "../data/grab-dir-names";
|
||||
import path from "path";
|
||||
import dbSchemaToTypeDef from "../lib/sqlite/schema-to-typedef";
|
||||
import _ from "lodash";
|
||||
import appendDefaultFieldsToDbSchema from "../utils/append-default-fields-to-db-schema";
|
||||
import chalk from "chalk";
|
||||
import { writeLiveSchema } from "../functions/live-schema";
|
||||
import grabDBDir from "../utils/grab-db-dir";
|
||||
import { cpSync } from "fs";
|
||||
import snapshotDb from "../utils/snapshot-db";
|
||||
import replaceDbFile from "../utils/replace-db-file";
|
||||
import { confirm } from "@inquirer/prompts";
|
||||
export default function () {
|
||||
return new Command("schema")
|
||||
.description("Build DB From Schema")
|
||||
.option("-v, --vector", "Recreate Vector Tables. This will drop and rebuild all vector tables")
|
||||
.option("-t, --typedef", "Generate typescript type definitions")
|
||||
.option("--dry-run", "Print the schema changes that would be applied, without applying them")
|
||||
.option("-y, --yes", "Apply destructive changes (dropped tables / columns) without confirmation")
|
||||
.action(async (opts) => {
|
||||
console.log(`Starting process ...`);
|
||||
const { config, dbSchema } = await init();
|
||||
const config = global.CONFIG;
|
||||
const dbSchema = global.DB_SCHEMA;
|
||||
const DbClient = global.SQLITE_CLIENT;
|
||||
const { ROOT_DIR, BUN_SQLITE_TEMP_DB_FILE_PATH } = grabDirNames();
|
||||
const { db_file_path } = grabDBDir({ config });
|
||||
cpSync(db_file_path, BUN_SQLITE_TEMP_DB_FILE_PATH);
|
||||
const isVector = Boolean(opts.vector || opts.v);
|
||||
const isTypeDef = Boolean(opts.typedef || opts.t);
|
||||
const finaldbSchema = appendDefaultFieldsToDbSchema({
|
||||
dbSchema,
|
||||
});
|
||||
const params = {
|
||||
db: DbClient,
|
||||
db_schema: finaldbSchema,
|
||||
recreate_vector_table: isVector,
|
||||
};
|
||||
/**
|
||||
* Plan: run the sync in a transaction that is rolled back
|
||||
*/
|
||||
const plan = [];
|
||||
try {
|
||||
const isVector = Boolean(opts.vector || opts.v);
|
||||
const isTypeDef = Boolean(opts.typedef || opts.t);
|
||||
const finaldbSchema = appendDefaultFieldsToDbSchema({
|
||||
dbSchema,
|
||||
createDBSchema({ ...params, dry_run: true, changes: plan });
|
||||
}
|
||||
catch (error) {
|
||||
console.error(chalk.red(`Schema sync ERROR => ${error.message}`));
|
||||
process.exit(1);
|
||||
}
|
||||
const destructive = plan.filter((change) => change.destructive);
|
||||
if (opts.dryRun) {
|
||||
if (!plan.length) {
|
||||
console.log(chalk.green(`Schema is up to date.`));
|
||||
}
|
||||
else {
|
||||
console.log(chalk.bold(`Planned schema changes:\n`));
|
||||
for (const change of plan) {
|
||||
console.log(change.destructive
|
||||
? chalk.red(` ${change.description}`)
|
||||
: ` ${change.description}`);
|
||||
}
|
||||
if (destructive.length) {
|
||||
console.log(chalk.red(`\n${destructive.length} destructive change(s) (in red) would discard data.`));
|
||||
}
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
if (destructive.length && !opts.yes) {
|
||||
console.log(chalk.yellow(`\nThese changes will permanently discard data:\n`));
|
||||
for (const change of destructive) {
|
||||
console.log(chalk.red(` ${change.description}`));
|
||||
}
|
||||
console.log();
|
||||
if (!process.stdin.isTTY) {
|
||||
console.error(chalk.red(`Refusing to apply destructive changes non-interactively. Re-run with --yes to apply them.`));
|
||||
process.exit(1);
|
||||
}
|
||||
const proceed = await confirm({
|
||||
message: `Apply ${destructive.length} destructive change(s)?`,
|
||||
default: false,
|
||||
});
|
||||
const manager = new SQLiteSchemaManager({
|
||||
schema: finaldbSchema,
|
||||
recreate_vector_table: isVector,
|
||||
if (!proceed) {
|
||||
console.log(chalk.dim(`Schema sync cancelled.`));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
snapshotDb({ db: DbClient, dst: BUN_SQLITE_TEMP_DB_FILE_PATH });
|
||||
try {
|
||||
createDBSchema({
|
||||
...params,
|
||||
allow_destructive: opts.yes
|
||||
? true
|
||||
: new Set(destructive.map((c) => c.description)),
|
||||
});
|
||||
await manager.syncSchema();
|
||||
manager.close();
|
||||
DbClient.close();
|
||||
if (isTypeDef && config.typedef_file_path) {
|
||||
const out_file = path.resolve(ROOT_DIR, config.typedef_file_path);
|
||||
dbSchemaToTypeDef({
|
||||
@@ -47,7 +105,11 @@ export default function () {
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
cpSync(BUN_SQLITE_TEMP_DB_FILE_PATH, db_file_path);
|
||||
DbClient.close();
|
||||
replaceDbFile({
|
||||
src: BUN_SQLITE_TEMP_DB_FILE_PATH,
|
||||
db_file_path,
|
||||
});
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user