- Add bun test suite: SQL generator and value unit tests, plus MariaDB integration tests gated on BUN_MARIADB_TEST_DB - schema: add --dry-run and require confirmation (or --yes) before dropping tables/columns; block unapproved destructive statements - Always AND targetId with the query, regardless of searchOperator - Initialize lazily on first call; init throws instead of exiting - Generate IN (?, ?, ...) lists for IN / NOT IN - Share value binding between insert and update (booleans, embeddings, function values, "" -> NULL for non-text columns) - Keep Buffers and convert BigInt/Date without a JSON round-trip - DbSQL: report success for empty SELECT results - Run update() in a transaction with row locking - Key the client cache on the full connection config - Consolidate identifier quoting, drop dead code, merge column lookup - Read CLI version from package.json, pin @types/bun, chmod CLI on compile - Rebuild dist Co-Authored-By: Claude Opus 5.5 <[email protected]>
74 lines
3.3 KiB
JavaScript
74 lines
3.3 KiB
JavaScript
import path from "path";
|
|
import fs from "fs";
|
|
import { AppData } from "../data/app-data";
|
|
import grabDirNames from "../data/grab-dir-names";
|
|
import { RequiredENVs, } from "../types";
|
|
import setMariaDBClient from "./set-mariadb-client";
|
|
import { resolveAndLoadDataFile, supportedDataFileNames, } from "../utils/resolve-and-load-data-file";
|
|
/**
|
|
* Load config + schema and set up the shared MariaDB client.
|
|
* Throws on any problem (never exits the process).
|
|
*/
|
|
export default function init() {
|
|
const { ROOT_DIR } = grabDirNames();
|
|
const { ConfigFileName } = AppData;
|
|
const loadedConfig = resolveAndLoadDataFile(ROOT_DIR, ConfigFileName);
|
|
if (!loadedConfig) {
|
|
throw new Error(`Please create a ${supportedDataFileNames(ConfigFileName)} file at the root of your project.`);
|
|
}
|
|
const Config = loadedConfig.data;
|
|
if (!Config || typeof Config !== "object") {
|
|
throw new Error(`Invalid config in \`${loadedConfig.path}\`. Expected a config object${loadedConfig.format === "ts" || loadedConfig.format === "js" ? " (export default)" : ""}.`);
|
|
}
|
|
if (!Config.db_name) {
|
|
throw new Error(`\`db_name\` is required in your config`);
|
|
}
|
|
RequiredENVs.forEach((env_key) => {
|
|
if (env_key == "BUN_MARIADB_SERVER_PORT" ||
|
|
env_key == "BUN_MARIADB_SERVER_SSL_KEY_PATH") {
|
|
return;
|
|
}
|
|
if (!process.env[env_key]) {
|
|
throw new Error(`\`${env_key}\` env variable is required.`);
|
|
}
|
|
});
|
|
if (!Config.db_dir) {
|
|
throw new Error(`\`db_dir\` is required in your config. This directory holds all database related configuration. Also note that a ${supportedDataFileNames(AppData.DbSchemaFileName)} file is also required in this directory to define your database schema`);
|
|
}
|
|
const db_dir = path.resolve(ROOT_DIR, Config.db_dir);
|
|
if (!fs.existsSync(db_dir)) {
|
|
fs.mkdirSync(db_dir, { recursive: true });
|
|
}
|
|
const loadedSchema = resolveAndLoadDataFile(db_dir, AppData.DbSchemaFileName);
|
|
if (!loadedSchema) {
|
|
throw new Error(`Please create a schema file (${supportedDataFileNames(AppData.DbSchemaFileName)}) in \`${db_dir}\`${loadedConfig.format === "ts" || loadedConfig.format === "js" ? ". Don't forget to export a default module from .ts/.js files." : "."}`);
|
|
}
|
|
const DbSchema = loadedSchema.data;
|
|
if (!DbSchema || typeof DbSchema !== "object") {
|
|
throw new Error(`Invalid schema in \`${loadedSchema.path}\`. Expected a schema object${loadedSchema.format === "ts" || loadedSchema.format === "js" ? " (export default)" : ""}.`);
|
|
}
|
|
const backup_dir = Config.db_backup_dir || AppData["DefaultBackupDirName"];
|
|
const BackupDir = path.resolve(db_dir, backup_dir);
|
|
if (!fs.existsSync(BackupDir)) {
|
|
fs.mkdirSync(BackupDir, { recursive: true });
|
|
}
|
|
const ExportDir = path.resolve(db_dir, AppData["DefaultExportDirName"]);
|
|
if (!fs.existsSync(ExportDir)) {
|
|
fs.mkdirSync(ExportDir, { recursive: true });
|
|
}
|
|
global.CONFIG = Config;
|
|
global.DB_SCHEMA = DbSchema;
|
|
global.CONFIG_FILE_PATH = loadedConfig.path;
|
|
global.SCHEMA_FILE_PATH = loadedSchema.path;
|
|
setMariaDBClient({ config: Config });
|
|
}
|
|
/**
|
|
* Initialize once, on first use.
|
|
*/
|
|
export function ensureInit() {
|
|
if (global.CONFIG && global.DB_SCHEMA && global.MARIADB_CLIENT !== undefined) {
|
|
return;
|
|
}
|
|
init();
|
|
}
|