Document typedefs better. Fix tables deletion schema sync issue.

This commit is contained in:
Benjamin Toby 2026-04-05 09:03:47 +01:00
parent 01b96d788e
commit 259a684136
14 changed files with 869 additions and 104 deletions

View File

@ -7,6 +7,7 @@ import dbSchemaToTypeDef from "../lib/sqlite/schema-to-typedef";
import _ from "lodash"; import _ from "lodash";
import appendDefaultFieldsToDbSchema from "../utils/append-default-fields-to-db-schema"; import appendDefaultFieldsToDbSchema from "../utils/append-default-fields-to-db-schema";
import chalk from "chalk"; import chalk from "chalk";
import { writeLiveSchema } from "../functions/live-schema";
export default function () { export default function () {
return new Command("schema") return new Command("schema")
.description("Build DB From Schema") .description("Build DB From Schema")
@ -33,6 +34,7 @@ export default function () {
config, config,
}); });
} }
writeLiveSchema({ schema: finaldbSchema });
console.log(`${chalk.bold(chalk.green(`DB Schema setup success!`))}`); console.log(`${chalk.bold(chalk.green(`DB Schema setup success!`))}`);
process.exit(); process.exit();
}); });

View File

@ -1,3 +1,11 @@
export default function grabDirNames(): { import type { BunSQLiteConfig } from "../types";
ROOT_DIR: string; type Params = {
config?: BunSQLiteConfig;
}; };
export default function grabDirNames(params?: Params): {
ROOT_DIR: string;
BUN_SQLITE_DIR: string;
BUN_SQLITE_TEMP_DIR: string;
BUN_SQLITE_LIVE_SCHEMA: string;
};
export {};

View File

@ -1,7 +1,13 @@
import path from "path"; import path from "path";
export default function grabDirNames() { export default function grabDirNames(params) {
const ROOT_DIR = process.cwd(); const ROOT_DIR = process.cwd();
const BUN_SQLITE_DIR = path.join(ROOT_DIR, ".bun-sqlite");
const BUN_SQLITE_TEMP_DIR = path.join(BUN_SQLITE_DIR, ".tmp");
const BUN_SQLITE_LIVE_SCHEMA = path.join(BUN_SQLITE_DIR, "live-schema.json");
return { return {
ROOT_DIR, ROOT_DIR,
BUN_SQLITE_DIR,
BUN_SQLITE_TEMP_DIR,
BUN_SQLITE_LIVE_SCHEMA,
}; };
} }

7
dist/functions/live-schema.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
import type { BUN_SQLITE_DatabaseSchemaType } from "../types";
type Params = {
schema: BUN_SQLITE_DatabaseSchemaType;
};
export declare function writeLiveSchema({ schema }: Params): void;
export declare function readLiveSchema(): BUN_SQLITE_DatabaseSchemaType | undefined;
export {};

15
dist/functions/live-schema.js vendored Normal file
View File

@ -0,0 +1,15 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import grabDirNames from "../data/grab-dir-names";
import path from "path";
const { BUN_SQLITE_LIVE_SCHEMA } = grabDirNames();
export function writeLiveSchema({ schema }) {
mkdirSync(path.dirname(BUN_SQLITE_LIVE_SCHEMA), { recursive: true });
writeFileSync(BUN_SQLITE_LIVE_SCHEMA, JSON.stringify(schema));
}
export function readLiveSchema() {
if (!existsSync(BUN_SQLITE_LIVE_SCHEMA)) {
return undefined;
}
const live_schema = readFileSync(BUN_SQLITE_LIVE_SCHEMA, "utf-8");
return JSON.parse(live_schema);
}

View File

@ -3,6 +3,7 @@ import { Database } from "bun:sqlite";
import _ from "lodash"; import _ from "lodash";
import DbClient from "."; import DbClient from ".";
import { AppData } from "../../data/app-data"; import { AppData } from "../../data/app-data";
import { readLiveSchema } from "../../functions/live-schema";
// Schema Manager Class // Schema Manager Class
class SQLiteSchemaManager { class SQLiteSchemaManager {
db; db;
@ -60,8 +61,21 @@ class SQLiteSchemaManager {
* Drop tables that are no longer in the schema * Drop tables that are no longer in the schema
*/ */
async dropRemovedTables(existingTables, schemaTables) { async dropRemovedTables(existingTables, schemaTables) {
console.log(`Cleaning up tables ...`);
const tablesToDrop = existingTables.filter((t) => !schemaTables.includes(t) && const tablesToDrop = existingTables.filter((t) => !schemaTables.includes(t) &&
!schemaTables.find((scT) => t.startsWith(scT + "_"))); !schemaTables.find((scT) => t.startsWith(scT + "_")));
const currentSchema = readLiveSchema();
if (currentSchema?.tables?.[0]) {
for (let i = 0; i < currentSchema.tables.length; i++) {
const table = currentSchema.tables[i];
if (!table?.tableName)
continue;
const does_table_exist = schemaTables.find((t) => t == table.tableName);
if (!does_table_exist) {
tablesToDrop.push(table.tableName);
}
}
}
for (const tableName of tablesToDrop) { for (const tableName of tablesToDrop) {
console.log(`Dropping table: ${tableName}`); console.log(`Dropping table: ${tableName}`);
this.db.run(`DROP TABLE IF EXISTS "${tableName}"`); this.db.run(`DROP TABLE IF EXISTS "${tableName}"`);

403
dist/types/index.d.ts vendored

File diff suppressed because it is too large Load Diff

42
dist/types/index.js vendored
View File

@ -1,3 +1,7 @@
/**
* User fields that should be omitted from general-purpose payloads and public
* responses.
*/
export const UsersOmitedFields = [ export const UsersOmitedFields = [
"password", "password",
"social_id", "social_id",
@ -9,10 +13,17 @@ export const UsersOmitedFields = [
"date_updated_code", "date_updated_code",
"date_updated_timestamp", "date_updated_timestamp",
]; ];
/**
* Supported MariaDB collations that can be applied at the database or table
* level.
*/
export const MariaDBCollations = [ export const MariaDBCollations = [
"utf8mb4_bin", "utf8mb4_bin",
"utf8mb4_unicode_520_ci", "utf8mb4_unicode_520_ci",
]; ];
/**
* Supported editor/content modes for text fields.
*/
export const TextFieldTypesArray = [ export const TextFieldTypesArray = [
{ title: "Plain Text", value: "plain" }, { title: "Plain Text", value: "plain" },
{ title: "Rich Text", value: "richText" }, { title: "Rich Text", value: "richText" },
@ -25,13 +36,22 @@ export const TextFieldTypesArray = [
{ title: "Shell", value: "shell" }, { title: "Shell", value: "shell" },
{ title: "Code", value: "code" }, { title: "Code", value: "code" },
]; ];
/**
* Core SQLite column types supported by the schema builder.
*/
export const BUN_SQLITE_DATATYPES = [ export const BUN_SQLITE_DATATYPES = [
{ value: "TEXT" }, { value: "TEXT" },
{ value: "INTEGER" }, { value: "INTEGER" },
{ value: "BLOB" }, { value: "BLOB" },
{ value: "REAL" }, { value: "REAL" },
]; ];
/**
* Supported logical operators for server-side query generation.
*/
export const ServerQueryOperators = ["AND", "OR"]; export const ServerQueryOperators = ["AND", "OR"];
/**
* Supported comparison operators for server-side query generation.
*/
export const ServerQueryEqualities = [ export const ServerQueryEqualities = [
"EQUAL", "EQUAL",
"LIKE", "LIKE",
@ -60,6 +80,9 @@ export const ServerQueryEqualities = [
"MATCH", "MATCH",
"MATCH_BOOLEAN", "MATCH_BOOLEAN",
]; ];
/**
* Uppercase HTTP methods supported by the CRUD helpers.
*/
export const DataCrudRequestMethods = [ export const DataCrudRequestMethods = [
"GET", "GET",
"POST", "POST",
@ -68,6 +91,10 @@ export const DataCrudRequestMethods = [
"DELETE", "DELETE",
"OPTIONS", "OPTIONS",
]; ];
/**
* Lowercase variant of the supported HTTP methods, used where string casing
* must match external APIs.
*/
export const DataCrudRequestMethodsLowerCase = [ export const DataCrudRequestMethodsLowerCase = [
"get", "get",
"post", "post",
@ -76,7 +103,13 @@ export const DataCrudRequestMethodsLowerCase = [
"delete", "delete",
"options", "options",
]; ];
/**
* High-level CRUD actions supported by the DSQL helpers.
*/
export const DsqlCrudActions = ["insert", "update", "delete", "get"]; export const DsqlCrudActions = ["insert", "update", "delete", "get"];
/**
* Reserved query parameter names used throughout the API layer.
*/
export const QueryFields = [ export const QueryFields = [
"duplicate", "duplicate",
"user_id", "user_id",
@ -85,6 +118,9 @@ export const QueryFields = [
"table_id", "table_id",
"db_slug", "db_slug",
]; ];
/**
* Supported Docker Compose service names used by the deployment helpers.
*/
export const DockerComposeServices = [ export const DockerComposeServices = [
"setup", "setup",
"cron", "cron",
@ -102,7 +138,13 @@ export const DockerComposeServices = [
"db-cron", "db-cron",
"web-app-post-db-setup", "web-app-post-db-setup",
]; ];
/**
* Supported index strategies for generated schemas.
*/
export const IndexTypes = ["regular", "full_text", "vector"]; export const IndexTypes = ["regular", "full_text", "vector"];
/**
* Default fields automatically suggested for new tables.
*/
export const DefaultFields = [ export const DefaultFields = [
{ {
fieldName: "id", fieldName: "id",

View File

@ -1,6 +1,6 @@
{ {
"name": "@moduletrace/bun-sqlite", "name": "@moduletrace/bun-sqlite",
"version": "1.0.23", "version": "1.0.24",
"description": "SQLite manager for Bun", "description": "SQLite manager for Bun",
"author": "Benjamin Toby", "author": "Benjamin Toby",
"main": "dist/index.js", "main": "dist/index.js",

View File

@ -7,6 +7,7 @@ import dbSchemaToTypeDef from "../lib/sqlite/schema-to-typedef";
import _ from "lodash"; import _ from "lodash";
import appendDefaultFieldsToDbSchema from "../utils/append-default-fields-to-db-schema"; import appendDefaultFieldsToDbSchema from "../utils/append-default-fields-to-db-schema";
import chalk from "chalk"; import chalk from "chalk";
import { writeLiveSchema } from "../functions/live-schema";
export default function () { export default function () {
return new Command("schema") return new Command("schema")
@ -48,6 +49,8 @@ export default function () {
}); });
} }
writeLiveSchema({ schema: finaldbSchema });
console.log( console.log(
`${chalk.bold(chalk.green(`DB Schema setup success!`))}`, `${chalk.bold(chalk.green(`DB Schema setup success!`))}`,
); );

View File

@ -1,9 +1,23 @@
import path from "path"; import path from "path";
import type { BunSQLiteConfig } from "../types";
export default function grabDirNames() { type Params = {
config?: BunSQLiteConfig;
};
export default function grabDirNames(params?: Params) {
const ROOT_DIR = process.cwd(); const ROOT_DIR = process.cwd();
const BUN_SQLITE_DIR = path.join(ROOT_DIR, ".bun-sqlite");
const BUN_SQLITE_TEMP_DIR = path.join(BUN_SQLITE_DIR, ".tmp");
const BUN_SQLITE_LIVE_SCHEMA = path.join(
BUN_SQLITE_DIR,
"live-schema.json",
);
return { return {
ROOT_DIR, ROOT_DIR,
BUN_SQLITE_DIR,
BUN_SQLITE_TEMP_DIR,
BUN_SQLITE_LIVE_SCHEMA,
}; };
} }

View File

@ -0,0 +1,24 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import grabDirNames from "../data/grab-dir-names";
import type { BUN_SQLITE_DatabaseSchemaType } from "../types";
import path from "path";
const { BUN_SQLITE_LIVE_SCHEMA } = grabDirNames();
type Params = {
schema: BUN_SQLITE_DatabaseSchemaType;
};
export function writeLiveSchema({ schema }: Params) {
mkdirSync(path.dirname(BUN_SQLITE_LIVE_SCHEMA), { recursive: true });
writeFileSync(BUN_SQLITE_LIVE_SCHEMA, JSON.stringify(schema));
}
export function readLiveSchema() {
if (!existsSync(BUN_SQLITE_LIVE_SCHEMA)) {
return undefined;
}
const live_schema = readFileSync(BUN_SQLITE_LIVE_SCHEMA, "utf-8");
return JSON.parse(live_schema) as BUN_SQLITE_DatabaseSchemaType;
}

View File

@ -9,6 +9,7 @@ import type {
BUN_SQLITE_TableSchemaType, BUN_SQLITE_TableSchemaType,
} from "../../types"; } from "../../types";
import { AppData } from "../../data/app-data"; import { AppData } from "../../data/app-data";
import { readLiveSchema } from "../../functions/live-schema";
// Schema Manager Class // Schema Manager Class
class SQLiteSchemaManager { class SQLiteSchemaManager {
@ -95,12 +96,32 @@ class SQLiteSchemaManager {
existingTables: string[], existingTables: string[],
schemaTables: string[], schemaTables: string[],
): Promise<void> { ): Promise<void> {
console.log(`Cleaning up tables ...`);
const tablesToDrop = existingTables.filter( const tablesToDrop = existingTables.filter(
(t) => (t) =>
!schemaTables.includes(t) && !schemaTables.includes(t) &&
!schemaTables.find((scT) => t.startsWith(scT + "_")), !schemaTables.find((scT) => t.startsWith(scT + "_")),
); );
const currentSchema = readLiveSchema();
if (currentSchema?.tables?.[0]) {
for (let i = 0; i < currentSchema.tables.length; i++) {
const table = currentSchema.tables[i];
if (!table?.tableName) continue;
const does_table_exist = schemaTables.find(
(t) => t == table.tableName,
);
if (!does_table_exist) {
tablesToDrop.push(table.tableName);
}
}
}
for (const tableName of tablesToDrop) { for (const tableName of tablesToDrop) {
console.log(`Dropping table: ${tableName}`); console.log(`Dropping table: ${tableName}`);
this.db.run(`DROP TABLE IF EXISTS "${tableName}"`); this.db.run(`DROP TABLE IF EXISTS "${tableName}"`);

File diff suppressed because it is too large Load Diff