Major version update. Major bugfixes. Security vulnerabilites fixed
This commit is contained in:
+7
@@ -0,0 +1,7 @@
|
||||
import { Database } from "bun:sqlite";
|
||||
import type { BunSQLiteConfig } from "../types";
|
||||
type Params = {
|
||||
config: BunSQLiteConfig;
|
||||
};
|
||||
export default function grabSQLiteClient({ config }: Params): Database;
|
||||
export {};
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
import { Database } from "bun:sqlite";
|
||||
import * as sqliteVec from "sqlite-vec";
|
||||
import grabDBDir from "../utils/grab-db-dir";
|
||||
/** Reuse one connection per database file. */
|
||||
const clientCache = new Map();
|
||||
export default function grabSQLiteClient({ config }) {
|
||||
const { db_file_path } = grabDBDir({ config });
|
||||
const cached = clientCache.get(db_file_path);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const SQLiteClient = new Database(db_file_path, {
|
||||
create: true,
|
||||
});
|
||||
sqliteVec.load(SQLiteClient);
|
||||
if (config.wal_mode) {
|
||||
SQLiteClient.run("PRAGMA journal_mode = WAL;");
|
||||
}
|
||||
clientCache.set(db_file_path, SQLiteClient);
|
||||
return SQLiteClient;
|
||||
}
|
||||
Vendored
+18
-2
@@ -1,2 +1,18 @@
|
||||
import type { BunSQLiteConfigReturn } from "../types";
|
||||
export default function init(): Promise<BunSQLiteConfigReturn>;
|
||||
import type { Database } from "bun:sqlite";
|
||||
import type { BunSQLiteConfig, BunSQLiteConfigReturn, BUN_SQLITE_DatabaseSchemaType } from "../types";
|
||||
/**
|
||||
* # Declare Global Variables
|
||||
*/
|
||||
declare global {
|
||||
var CONFIG: BunSQLiteConfig;
|
||||
var DB_SCHEMA: BUN_SQLITE_DatabaseSchemaType;
|
||||
var SQLITE_CLIENT: Database;
|
||||
var CONFIG_FILE_PATH: string;
|
||||
var SCHEMA_FILE_PATH: string;
|
||||
}
|
||||
/**
|
||||
* # Load config, schema and the SQLite client into globals
|
||||
* @description Runs once per process. Later calls return the loaded
|
||||
* globals.
|
||||
*/
|
||||
export default function init(): BunSQLiteConfigReturn;
|
||||
|
||||
Vendored
+79
-39
@@ -2,45 +2,85 @@ import path from "path";
|
||||
import fs from "fs";
|
||||
import { AppData } from "../data/app-data";
|
||||
import grabDirNames from "../data/grab-dir-names";
|
||||
export default async function init() {
|
||||
try {
|
||||
const { ROOT_DIR } = grabDirNames();
|
||||
const { ConfigFileName } = AppData;
|
||||
const ConfigFilePath = path.join(ROOT_DIR, ConfigFileName);
|
||||
if (!fs.existsSync(ConfigFilePath)) {
|
||||
console.log("ConfigFilePath", ConfigFilePath);
|
||||
console.error(`Please create a \`${ConfigFileName}\` file at the root of your project.`);
|
||||
process.exit(1);
|
||||
}
|
||||
const ConfigImport = await import(ConfigFilePath);
|
||||
const Config = ConfigImport["default"];
|
||||
if (!Config.db_name) {
|
||||
console.error(`\`db_name\` is required in your config`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (!Config.db_schema_file_name) {
|
||||
console.error(`\`db_schema_file_name\` is required in your config`);
|
||||
process.exit(1);
|
||||
}
|
||||
let db_dir = ROOT_DIR;
|
||||
if (Config.db_dir) {
|
||||
db_dir = path.resolve(ROOT_DIR, Config.db_dir);
|
||||
if (!fs.existsSync(Config.db_dir)) {
|
||||
fs.mkdirSync(Config.db_dir, { recursive: true });
|
||||
}
|
||||
}
|
||||
const DBSchemaFilePath = path.join(db_dir, Config.db_schema_file_name);
|
||||
const DbSchemaImport = await import(DBSchemaFilePath);
|
||||
const DbSchema = DbSchemaImport["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 });
|
||||
}
|
||||
return { config: Config, dbSchema: DbSchema };
|
||||
import setSQLiteClient from "./set-sqlite-client";
|
||||
import grabDBDir from "../utils/grab-db-dir";
|
||||
import { loadDataFile, resolveAndLoadDataFile, supportedDataFileNames, } from "../utils/resolve-and-load-data-file";
|
||||
/**
|
||||
* # Load config, schema and the SQLite client into globals
|
||||
* @description Runs once per process. Later calls return the loaded
|
||||
* globals.
|
||||
*/
|
||||
export default function init() {
|
||||
if (global.CONFIG && global.DB_SCHEMA && global.SQLITE_CLIENT) {
|
||||
return { config: global.CONFIG, dbSchema: global.DB_SCHEMA };
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Initialization ERROR => ` + error.message);
|
||||
process.exit(1);
|
||||
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. (Looked in ${ROOT_DIR})`);
|
||||
}
|
||||
const Config = loadedConfig.data;
|
||||
if (!Config || typeof Config !== "object") {
|
||||
throw new Error(`Invalid config in \`${loadedConfig.path}\`. Expected a config object${isCodeFile(loadedConfig) ? " (export default)" : ""}.`);
|
||||
}
|
||||
if (!Config.db_name) {
|
||||
throw new Error(`\`db_name\` is required in your config`);
|
||||
}
|
||||
const { db_dir, backup_dir } = grabDBDir({ config: Config });
|
||||
if (!fs.existsSync(db_dir)) {
|
||||
fs.mkdirSync(db_dir, { recursive: true });
|
||||
}
|
||||
const loadedSchema = loadSchema({ config: Config, db_dir });
|
||||
const DbSchema = loadedSchema.data;
|
||||
if (!DbSchema || typeof DbSchema !== "object") {
|
||||
throw new Error(`Invalid schema in \`${loadedSchema.path}\`. Expected a schema object${isCodeFile(loadedSchema) ? " (export default)" : ""}.`);
|
||||
}
|
||||
if (!fs.existsSync(backup_dir)) {
|
||||
fs.mkdirSync(backup_dir, { recursive: true });
|
||||
}
|
||||
global.CONFIG = Config;
|
||||
global.DB_SCHEMA = DbSchema;
|
||||
global.CONFIG_FILE_PATH = loadedConfig.path;
|
||||
global.SCHEMA_FILE_PATH = loadedSchema.path;
|
||||
setSQLiteClient({ config: Config });
|
||||
return { config: Config, dbSchema: DbSchema };
|
||||
}
|
||||
/**
|
||||
* # Load the schema file
|
||||
* @description Uses `db_schema_file_name` when set, otherwise
|
||||
* `schema.ts|js|json|yaml|yml` in `db_dir`.
|
||||
*/
|
||||
function loadSchema({ config, db_dir, }) {
|
||||
if (config.db_schema_file_name) {
|
||||
const schema_file_path = path.join(db_dir, config.db_schema_file_name);
|
||||
const extension = path.extname(schema_file_path);
|
||||
const supported = AppData.SupportedDataFileExtensions.find((ext) => ext === extension);
|
||||
if (!supported) {
|
||||
throw new Error(`Unsupported schema file \`${config.db_schema_file_name}\`. Use one of: ${AppData.SupportedDataFileExtensions.join(", ")}`);
|
||||
}
|
||||
if (!fs.existsSync(schema_file_path)) {
|
||||
throw new Error(`Schema file not found: ${schema_file_path}`);
|
||||
}
|
||||
const resolved = {
|
||||
path: schema_file_path,
|
||||
basename: path.basename(schema_file_path),
|
||||
extension: supported,
|
||||
format: supported === ".yml"
|
||||
? "yaml"
|
||||
: supported.slice(1),
|
||||
};
|
||||
return {
|
||||
...resolved,
|
||||
data: loadDataFile(resolved),
|
||||
};
|
||||
}
|
||||
const loaded = resolveAndLoadDataFile(db_dir, AppData.DbSchemaFileName);
|
||||
if (!loaded) {
|
||||
throw new Error(`Please create a schema file (${supportedDataFileNames(AppData.DbSchemaFileName)}) in \`${db_dir}\`, or set \`db_schema_file_name\` in your config.`);
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
function isCodeFile(file) {
|
||||
return file.format === "ts" || file.format === "js";
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import type { BunSQLiteConfig } from "../types";
|
||||
type Params = {
|
||||
config: BunSQLiteConfig;
|
||||
};
|
||||
export default function setSQLiteClient({ config }: Params): void;
|
||||
export {};
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import grabSQLiteClient from "./grab-sqlite-client";
|
||||
export default function setSQLiteClient({ config }) {
|
||||
global.SQLITE_CLIENT = grabSQLiteClient({ config });
|
||||
}
|
||||
Reference in New Issue
Block a user