- init() loads config, schema and the SQLite client once into globals - all CRUD queries go through lib/db-handler.ts (optional per-call config) - split db-schema-manager.ts into lib/schema/* with FK-aware table ordering - add bun:test tests for schema ordering, FK constraints and schema sync - config/schema files can be .ts/.js/.json/.yaml/.yml; db_schema_file_name is now optional (defaults to schema.* in db_dir) - add export/import commands (database snapshot + schema archives) - package exports map, type re-exports, hardened publish.sh - validate table name in delete Co-Authored-By: Claude Opus 5.5 <[email protected]>
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import type { BUN_SQLITE_TableSchemaType } from "../../types";
|
|
import orderDBSchema from "./order-db-schema";
|
|
|
|
function table({
|
|
name,
|
|
refs = [],
|
|
}: {
|
|
name: string;
|
|
refs?: string[];
|
|
}): BUN_SQLITE_TableSchemaType {
|
|
return {
|
|
tableName: name,
|
|
fields: refs.map((ref) => ({
|
|
fieldName: `${ref}_id`,
|
|
dataType: "INTEGER",
|
|
foreignKey: {
|
|
destinationTableName: ref,
|
|
destinationTableColumnName: "id",
|
|
},
|
|
})),
|
|
};
|
|
}
|
|
|
|
function order(tables: BUN_SQLITE_TableSchemaType[]) {
|
|
const res = orderDBSchema({ db_schema: { tables } });
|
|
return res.tables.map((t) => t.tableName);
|
|
}
|
|
|
|
describe("orderDBSchema", () => {
|
|
test("places parents before children", () => {
|
|
expect(
|
|
order([
|
|
table({ name: "comments", refs: ["posts", "users"] }),
|
|
table({ name: "posts", refs: ["users"] }),
|
|
table({ name: "users" }),
|
|
]),
|
|
).toEqual(["users", "posts", "comments"]);
|
|
});
|
|
|
|
test("keeps declaration order when there are no dependencies", () => {
|
|
expect(
|
|
order([table({ name: "b" }), table({ name: "a" })]),
|
|
).toEqual(["b", "a"]);
|
|
});
|
|
|
|
test("handles self references without recursing forever", () => {
|
|
expect(
|
|
order([
|
|
table({ name: "categories", refs: ["categories"] }),
|
|
table({ name: "comments", refs: ["comments", "users"] }),
|
|
table({ name: "users" }),
|
|
]),
|
|
).toEqual(["categories", "users", "comments"]);
|
|
});
|
|
|
|
test("handles cycles and emits each table once", () => {
|
|
const res = order([
|
|
table({ name: "a", refs: ["b"] }),
|
|
table({ name: "b", refs: ["a"] }),
|
|
table({ name: "c", refs: ["a"] }),
|
|
]);
|
|
expect(res).toHaveLength(3);
|
|
expect(new Set(res).size).toBe(3);
|
|
expect(res.indexOf("c")).toBeGreaterThan(res.indexOf("a"));
|
|
});
|
|
|
|
test("ignores references to tables outside the schema", () => {
|
|
expect(
|
|
order([table({ name: "posts", refs: ["external_users"] })]),
|
|
).toEqual(["posts"]);
|
|
});
|
|
});
|