Updates
This commit is contained in:
parent
b5e4724e03
commit
3b5fba4063
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@moduletrace/bun-mariadb",
|
||||
"version": "1.1.11",
|
||||
"version": "1.0.0",
|
||||
"description": "Mariadb manager for Bun",
|
||||
"author": "Benjamin Toby",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@ -6,31 +6,9 @@ import typedef from "./typedef";
|
||||
import backup from "./backup";
|
||||
import restore from "./restore";
|
||||
import admin from "./admin";
|
||||
import type {
|
||||
BUN_MARIADB_DatabaseSchemaType,
|
||||
BunMariaDBConfig,
|
||||
} from "../types";
|
||||
import init from "../functions/init";
|
||||
|
||||
/**
|
||||
* # Declare Global Variables
|
||||
*/
|
||||
declare global {
|
||||
var CONFIG: BunMariaDBConfig;
|
||||
var DB_SCHEMA: BUN_MARIADB_DatabaseSchemaType;
|
||||
}
|
||||
|
||||
await init();
|
||||
|
||||
if (!global.CONFIG) {
|
||||
console.error(`Couldn't grab global Config.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!global.DB_SCHEMA) {
|
||||
console.error(`Couldn't grab Database Schema.`);
|
||||
process.exit(1);
|
||||
}
|
||||
init();
|
||||
|
||||
/**
|
||||
* # Describe Program
|
||||
|
||||
@ -7,6 +7,7 @@ import _ from "lodash";
|
||||
import appendDefaultFieldsToDbSchema from "../utils/append-default-fields-to-db-schema";
|
||||
import chalk from "chalk";
|
||||
import { writeLiveSchema } from "../functions/live-schema";
|
||||
import createDBSchema from "../lib/schema/create-db-schema";
|
||||
|
||||
export default function () {
|
||||
return new Command("schema")
|
||||
@ -31,12 +32,14 @@ export default function () {
|
||||
dbSchema,
|
||||
});
|
||||
|
||||
const manager = new MariaDBSchemaManager({
|
||||
schema: finaldbSchema,
|
||||
});
|
||||
// const manager = new MariaDBSchemaManager({
|
||||
// schema: finaldbSchema,
|
||||
// });
|
||||
|
||||
await manager.syncSchema();
|
||||
manager.close();
|
||||
// await manager.syncSchema();
|
||||
// manager.close();
|
||||
|
||||
await createDBSchema({ db_schema: finaldbSchema });
|
||||
|
||||
if (isTypeDef && config.typedef_file_path) {
|
||||
const out_file = path.resolve(
|
||||
|
||||
@ -4,4 +4,6 @@ export const AppData = {
|
||||
DefaultBackupDirName: ".backups",
|
||||
DbSchemaManagerTableName: "__db_schema_manager__",
|
||||
DbSchemaFileName: "schema.ts",
|
||||
MaxInitRetries: 50,
|
||||
InitRetryIntervalMilliseconds: 5000,
|
||||
} as const;
|
||||
|
||||
41
src/functions/grab-mariadb-client.ts
Normal file
41
src/functions/grab-mariadb-client.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import path from "path";
|
||||
import grabDirNames from "../data/grab-dir-names";
|
||||
import { type BunMariaDBConfig } from "../types";
|
||||
import { SQL } from "bun";
|
||||
|
||||
type Params = {
|
||||
config: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
export default function grabMariaDBClient({
|
||||
config,
|
||||
}: Params): Bun.SQL | undefined {
|
||||
const { ROOT_DIR } = grabDirNames();
|
||||
|
||||
try {
|
||||
const MariaDBClient = new SQL({
|
||||
hostname: process.env.BUN_MARIADB_SERVER_HOST,
|
||||
username: process.env.BUN_MARIADB_SERVER_USERNAME,
|
||||
password: process.env.BUN_MARIADB_SERVER_PASSWORD,
|
||||
database: config.db_name,
|
||||
port: process.env.BUN_MARIADB_SERVER_PORT
|
||||
? Number(process.env.BUN_MARIADB_SERVER_PORT)
|
||||
: undefined,
|
||||
...config.db_config,
|
||||
tls: config.ssl_ca
|
||||
? {
|
||||
ca: Bun.file(path.resolve(ROOT_DIR, config.ssl_ca)),
|
||||
rejectUnauthorized: false,
|
||||
}
|
||||
: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
adapter: "mariadb",
|
||||
});
|
||||
|
||||
return MariaDBClient;
|
||||
} catch (error: any) {
|
||||
console.error(`Couldn't grab MariaDB Client => ` + error.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -4,12 +4,22 @@ import { AppData } from "../data/app-data";
|
||||
import grabDirNames from "../data/grab-dir-names";
|
||||
import {
|
||||
type BunMariaDBConfig,
|
||||
type BunMariaDBConfigReturn,
|
||||
type BUN_MARIADB_DatabaseSchemaType,
|
||||
RequiredENVs,
|
||||
} from "../types";
|
||||
import { SQL } from "bun";
|
||||
import setMariaDBClient from "./set-mariadb-client";
|
||||
|
||||
export default async function init(): Promise<BunMariaDBConfigReturn> {
|
||||
/**
|
||||
* # Declare Global Variables
|
||||
*/
|
||||
declare global {
|
||||
var CONFIG: BunMariaDBConfig;
|
||||
var DB_SCHEMA: BUN_MARIADB_DatabaseSchemaType;
|
||||
var MARIADB_CLIENT: Bun.SQL;
|
||||
}
|
||||
|
||||
export default function init(): void {
|
||||
try {
|
||||
const { ROOT_DIR } = grabDirNames();
|
||||
const { ConfigFileName } = AppData;
|
||||
@ -23,7 +33,7 @@ export default async function init(): Promise<BunMariaDBConfigReturn> {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const ConfigImport = await import(ConfigFilePath);
|
||||
const ConfigImport = require(ConfigFilePath);
|
||||
const Config = ConfigImport["default"] as BunMariaDBConfig;
|
||||
|
||||
if (!Config) {
|
||||
@ -73,7 +83,7 @@ export default async function init(): Promise<BunMariaDBConfigReturn> {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const DbSchemaImport = await import(DBSchemaFilePath);
|
||||
const DbSchemaImport = require(DBSchemaFilePath);
|
||||
const DbSchema = DbSchemaImport[
|
||||
"default"
|
||||
] as BUN_MARIADB_DatabaseSchemaType;
|
||||
@ -89,10 +99,22 @@ export default async function init(): Promise<BunMariaDBConfigReturn> {
|
||||
global.CONFIG = Config;
|
||||
global.DB_SCHEMA = DbSchema;
|
||||
|
||||
return {
|
||||
config: Config,
|
||||
dbSchema: DbSchema,
|
||||
};
|
||||
if (!global.CONFIG) {
|
||||
console.error(`Couldn't grab global Config.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!global.DB_SCHEMA) {
|
||||
console.error(`Couldn't grab Database Schema.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
setMariaDBClient({ config: Config });
|
||||
|
||||
if (!global.MARIADB_CLIENT) {
|
||||
console.error(`Couldn't set MariaDB Client.`);
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`Initialization ERROR => ` + error.message);
|
||||
process.exit(1);
|
||||
|
||||
29
src/functions/set-mariadb-client.ts
Normal file
29
src/functions/set-mariadb-client.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { type BunMariaDBConfig } from "../types";
|
||||
import grabMariaDBClient from "./grab-mariadb-client";
|
||||
|
||||
type Params = {
|
||||
config: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
export default function setMariaDBClient({ config }: Params): void {
|
||||
try {
|
||||
const MariaDBClient = grabMariaDBClient({ config });
|
||||
|
||||
if (!MariaDBClient) {
|
||||
throw new Error(`Couldn't grab MariaDB Client`);
|
||||
}
|
||||
|
||||
global.MARIADB_CLIENT = MariaDBClient;
|
||||
|
||||
// const test = await MariaDBClient.unsafe(`SHOW DATABASES`);
|
||||
|
||||
// if (!test.count) {
|
||||
// console.error(`MariaDBClient Error: Database not ready.`);
|
||||
// console.log(test);
|
||||
// process.exit(1);
|
||||
// }
|
||||
} catch (error: any) {
|
||||
console.error(`ERROR setting MariaDB Client => ` + error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@ -4,14 +4,10 @@ import DbInsert from "./lib/mariadb/db-insert";
|
||||
import DbSelect from "./lib/mariadb/db-select";
|
||||
import DbSQL from "./lib/mariadb/db-sql";
|
||||
import DbUpdate from "./lib/mariadb/db-update";
|
||||
import type { BUN_MARIADB_DatabaseSchemaType, BunMariaDBConfig } from "./types";
|
||||
import grabDbSchema from "./utils/grab-db-schema";
|
||||
import grabJoinFieldsFromQueryObject from "./utils/grab-join-fields-from-query-object";
|
||||
|
||||
declare global {
|
||||
var CONFIG: BunMariaDBConfig;
|
||||
var DB_SCHEMA: BUN_MARIADB_DatabaseSchemaType;
|
||||
}
|
||||
init();
|
||||
|
||||
const BunMariaDB = {
|
||||
select: DbSelect,
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
import type { DBInsertReturn, DBResponseObject } from "../types";
|
||||
import MariaDBClient from "./mariadb";
|
||||
import grabMariaDBClient from "../functions/grab-mariadb-client";
|
||||
import type {
|
||||
BunMariaDBConfig,
|
||||
DBInsertReturn,
|
||||
DBResponseObject,
|
||||
} from "../types";
|
||||
|
||||
type Param = {
|
||||
query: string;
|
||||
values?: any[];
|
||||
config?: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -12,9 +17,17 @@ type Param = {
|
||||
*/
|
||||
export default async function dbHandler<
|
||||
T extends { [k: string]: any } = { [k: string]: any },
|
||||
>({ query, values }: Param): Promise<DBResponseObject> {
|
||||
>({ query, values, config }: Param): Promise<DBResponseObject<T>> {
|
||||
try {
|
||||
const res = await MariaDBClient.unsafe(query, values);
|
||||
const CLIENT = config
|
||||
? grabMariaDBClient({ config })
|
||||
: global.MARIADB_CLIENT;
|
||||
|
||||
if (!CLIENT) {
|
||||
throw new Error(`Couldn't grab MariaDB Client.`);
|
||||
}
|
||||
|
||||
const res = await CLIENT.unsafe(query, values);
|
||||
|
||||
const count = res.count;
|
||||
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
import * as mariadb from "mariadb";
|
||||
import type { Connection } from "mariadb";
|
||||
import type { DsqlConnectionParam } from "../types";
|
||||
import grabDbSSL from "./grab-db-ssl";
|
||||
|
||||
/**
|
||||
* # Grab General CONNECTION for DSQL
|
||||
*/
|
||||
export default async function grabDBConnection(
|
||||
param?: DsqlConnectionParam,
|
||||
): Promise<Connection> {
|
||||
const configData = global.CONFIG;
|
||||
const CONN_TIMEOUT = configData?.connection_timeout || 10000;
|
||||
|
||||
const config: mariadb.ConnectionConfig = {
|
||||
host: process.env.BUN_MARIADB_SERVER_HOST,
|
||||
user: process.env.BUN_MARIADB_SERVER_USERNAME,
|
||||
password: process.env.BUN_MARIADB_SERVER_PASSWORD,
|
||||
database: configData?.db_name,
|
||||
port: process.env.BUN_MARIADB_SERVER_PORT
|
||||
? Number(process.env.BUN_MARIADB_SERVER_PORT)
|
||||
: undefined,
|
||||
charset: configData?.charset || "utf8mb4",
|
||||
ssl: grabDbSSL(),
|
||||
bigIntAsNumber: true,
|
||||
supportBigNumbers: true,
|
||||
bigNumberStrings: false,
|
||||
dateStrings: true,
|
||||
metaAsArray: true,
|
||||
socketTimeout: CONN_TIMEOUT,
|
||||
connectTimeout: CONN_TIMEOUT,
|
||||
compress: true,
|
||||
...param?.config,
|
||||
};
|
||||
|
||||
try {
|
||||
return await mariadb.createConnection(config);
|
||||
} catch (error) {
|
||||
console.log(`Error Grabbing DSQL Connection =>`, config);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
import dbHandler from "../db-handler";
|
||||
import _ from "lodash";
|
||||
import type { DBResponseObject, ServerQueryParam } from "../../types";
|
||||
import type {
|
||||
BunMariaDBConfig,
|
||||
DBResponseObject,
|
||||
ServerQueryParam,
|
||||
} from "../../types";
|
||||
import sqlGenerator from "../../utils/sql-generator";
|
||||
|
||||
type Params<
|
||||
@ -10,6 +14,7 @@ type Params<
|
||||
table: Table;
|
||||
query?: ServerQueryParam<Schema>;
|
||||
targetId?: number | string;
|
||||
config?: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
function quoteIdentifier(identifier: string): string {
|
||||
@ -23,6 +28,7 @@ export default async function DbDelete<
|
||||
table,
|
||||
query,
|
||||
targetId,
|
||||
config,
|
||||
}: Params<Schema, Table>): Promise<DBResponseObject> {
|
||||
let sqlObj: ReturnType<typeof sqlGenerator> | null = null;
|
||||
|
||||
@ -66,6 +72,7 @@ export default async function DbDelete<
|
||||
const res = await dbHandler({
|
||||
query: sql,
|
||||
values: sqlObj.values as any,
|
||||
config,
|
||||
});
|
||||
|
||||
if (!res.success) {
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import dbHandler from "../db-handler";
|
||||
import type { DBResponseObject, SQLInsertGenReturn } from "../../types";
|
||||
import type {
|
||||
BunMariaDBConfig,
|
||||
DBResponseObject,
|
||||
SQLInsertGenReturn,
|
||||
} from "../../types";
|
||||
import sqlInsertGenerator from "../../utils/sql-insert-generator";
|
||||
import grabDuplicateSafeInsertSql from "../grab-duplicate-safe-insert-sql";
|
||||
|
||||
@ -10,6 +14,7 @@ type Params<
|
||||
table: Table;
|
||||
data: Schema[];
|
||||
update_on_duplicate?: boolean;
|
||||
config?: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
export default async function DbInsert<
|
||||
@ -19,6 +24,7 @@ export default async function DbInsert<
|
||||
table,
|
||||
data,
|
||||
update_on_duplicate,
|
||||
config,
|
||||
}: Params<Schema, Table>): Promise<DBResponseObject> {
|
||||
let sqlObj: SQLInsertGenReturn | null = null;
|
||||
|
||||
@ -53,6 +59,7 @@ export default async function DbInsert<
|
||||
const res = await dbHandler({
|
||||
query: sql,
|
||||
values: sqlObj.values,
|
||||
config,
|
||||
});
|
||||
|
||||
if (!res.success) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,10 @@
|
||||
import dbHandler from "../db-handler";
|
||||
import _ from "lodash";
|
||||
import type { DBResponseObject, ServerQueryParam } from "../../types";
|
||||
import type {
|
||||
BunMariaDBConfig,
|
||||
DBResponseObject,
|
||||
ServerQueryParam,
|
||||
} from "../../types";
|
||||
import sqlGenerator from "../../utils/sql-generator";
|
||||
|
||||
type Params<
|
||||
@ -11,6 +15,7 @@ type Params<
|
||||
table: Table;
|
||||
count?: boolean;
|
||||
targetId?: number | string;
|
||||
config?: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
function quoteIdentifier(identifier: string): string {
|
||||
@ -25,6 +30,7 @@ export default async function DbSelect<
|
||||
query,
|
||||
count,
|
||||
targetId,
|
||||
config,
|
||||
}: Params<Schema, Table>): Promise<DBResponseObject<Schema>> {
|
||||
let sqlObj: ReturnType<typeof sqlGenerator> | null = null;
|
||||
|
||||
@ -52,6 +58,7 @@ export default async function DbSelect<
|
||||
const res = await dbHandler<Schema>({
|
||||
query: sqlObj.string,
|
||||
values: sqlObj.values as any,
|
||||
config,
|
||||
});
|
||||
|
||||
if (!res.success) {
|
||||
@ -89,6 +96,7 @@ export default async function DbSelect<
|
||||
const countRes = await dbHandler<{ count: number }>({
|
||||
query: countSql,
|
||||
values: countSqlObject.values as any,
|
||||
config,
|
||||
});
|
||||
|
||||
if (!countRes.success) {
|
||||
@ -104,7 +112,7 @@ export default async function DbSelect<
|
||||
}
|
||||
|
||||
const countRows = countRes.payload || [];
|
||||
const countVal = countRows[0]?.count ?? countRows[0]?.["COUNT(*)"];
|
||||
const countVal = countRows[0]?.count ?? countRows[0]?.["count"];
|
||||
|
||||
resp = {
|
||||
...resp,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import dbHandler from "../db-handler";
|
||||
import _ from "lodash";
|
||||
import type {
|
||||
BunMariaDBConfig,
|
||||
DBResponseObject,
|
||||
SQLInsertGenValueType,
|
||||
ServerQueryParam,
|
||||
@ -15,6 +16,7 @@ type Params<
|
||||
data: Schema;
|
||||
query?: ServerQueryParam<Schema>;
|
||||
targetId?: number | string;
|
||||
config?: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
function quoteIdentifier(identifier: string): string {
|
||||
@ -29,6 +31,7 @@ export default async function DbUpdate<
|
||||
data,
|
||||
query,
|
||||
targetId,
|
||||
config,
|
||||
}: Params<Schema, Table>): Promise<DBResponseObject> {
|
||||
let sqlObj: ReturnType<typeof sqlGenerator> = { string: "", values: [] };
|
||||
|
||||
@ -93,6 +96,7 @@ export default async function DbUpdate<
|
||||
const res = await dbHandler({
|
||||
query: sql,
|
||||
values: values as any,
|
||||
config,
|
||||
});
|
||||
|
||||
sqlObj.string = sql;
|
||||
@ -122,6 +126,7 @@ export default async function DbUpdate<
|
||||
const updated_res = await dbHandler({
|
||||
query: updated_sql,
|
||||
values: updated_sql_values,
|
||||
config,
|
||||
});
|
||||
|
||||
const affected_rows = updated_res.payload?.length;
|
||||
|
||||
@ -1,50 +1,49 @@
|
||||
import { SQL } from "bun";
|
||||
import init from "../../functions/init";
|
||||
import grabDirNames from "../../data/grab-dir-names";
|
||||
import path from "path";
|
||||
// import { SQL } from "bun";
|
||||
// import grabDirNames from "../../data/grab-dir-names";
|
||||
// import path from "path";
|
||||
|
||||
await init();
|
||||
// if (!global.CONFIG) {
|
||||
// console.error(`Couldn't grab global Config.`);
|
||||
// process.exit(1);
|
||||
// }
|
||||
|
||||
if (!global.CONFIG) {
|
||||
console.error(`Couldn't grab global Config.`);
|
||||
process.exit(1);
|
||||
}
|
||||
// if (!global.DB_SCHEMA) {
|
||||
// console.error(`Couldn't grab Database Schema.`);
|
||||
// process.exit(1);
|
||||
// }
|
||||
|
||||
if (!global.DB_SCHEMA) {
|
||||
console.error(`Couldn't grab Database Schema.`);
|
||||
process.exit(1);
|
||||
}
|
||||
// const config = global.CONFIG;
|
||||
|
||||
const config = global.CONFIG;
|
||||
// const { ROOT_DIR } = grabDirNames();
|
||||
|
||||
const { ROOT_DIR } = grabDirNames();
|
||||
// const MariaDBClient = new SQL({
|
||||
// hostname: process.env.BUN_MARIADB_SERVER_HOST,
|
||||
// username: process.env.BUN_MARIADB_SERVER_USERNAME,
|
||||
// password: process.env.BUN_MARIADB_SERVER_PASSWORD,
|
||||
// database: config.db_name,
|
||||
// port: process.env.BUN_MARIADB_SERVER_PORT
|
||||
// ? Number(process.env.BUN_MARIADB_SERVER_PORT)
|
||||
// : undefined,
|
||||
// ...config.db_config,
|
||||
// tls: config.ssl_ca
|
||||
// ? {
|
||||
// ca: Bun.file(path.resolve(ROOT_DIR, config.ssl_ca)),
|
||||
// rejectUnauthorized: false,
|
||||
// }
|
||||
// : {
|
||||
// rejectUnauthorized: false,
|
||||
// },
|
||||
// adapter: "mariadb",
|
||||
// });
|
||||
|
||||
const MariaDBClient = new SQL({
|
||||
hostname: process.env.BUN_MARIADB_SERVER_HOST,
|
||||
username: process.env.BUN_MARIADB_SERVER_USERNAME,
|
||||
password: process.env.BUN_MARIADB_SERVER_PASSWORD,
|
||||
database: config.db_name,
|
||||
port: process.env.BUN_MARIADB_SERVER_PORT
|
||||
? Number(process.env.BUN_MARIADB_SERVER_PORT)
|
||||
: undefined,
|
||||
...config.db_config,
|
||||
tls: config.ssl_ca
|
||||
? {
|
||||
ca: Bun.file(path.resolve(ROOT_DIR, config.ssl_ca)),
|
||||
rejectUnauthorized: false,
|
||||
}
|
||||
: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
adapter: "mariadb",
|
||||
});
|
||||
// global.MARIADB_CLIENT = MariaDBClient;
|
||||
|
||||
const test = await MariaDBClient.unsafe(`SHOW DATABASES`);
|
||||
// const test = await MariaDBClient.unsafe(`SHOW DATABASES`);
|
||||
|
||||
if (!test.count) {
|
||||
console.error(`MariaDBClient Error: Database not ready.`);
|
||||
console.log(test);
|
||||
process.exit(1);
|
||||
}
|
||||
// if (!test.count) {
|
||||
// console.error(`MariaDBClient Error: Database not ready.`);
|
||||
// console.log(test);
|
||||
// process.exit(1);
|
||||
// }
|
||||
|
||||
export default MariaDBClient;
|
||||
// export default MariaDBClient;
|
||||
|
||||
46
src/lib/schema/build-column-definition.ts
Normal file
46
src/lib/schema/build-column-definition.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import type { BUN_MARIADB_FieldSchemaType } from "../../types";
|
||||
import mapDataType from "./map-data-types";
|
||||
import MariaDBQuoteGen from "./mariadb-quote-gen";
|
||||
|
||||
export default function buildColumnDefinition(
|
||||
field: BUN_MARIADB_FieldSchemaType,
|
||||
): string {
|
||||
if (!field.fieldName) {
|
||||
throw new Error("Field name is required");
|
||||
}
|
||||
|
||||
const parts: string[] = [MariaDBQuoteGen(field.fieldName)];
|
||||
parts.push(mapDataType(field));
|
||||
|
||||
if (field.autoIncrement) {
|
||||
parts.push("AUTO_INCREMENT");
|
||||
}
|
||||
|
||||
if (field.notNullValue || field.primaryKey || field.isVector) {
|
||||
if (!field.primaryKey) {
|
||||
parts.push("NOT NULL");
|
||||
}
|
||||
}
|
||||
|
||||
if (field.unique && !field.primaryKey) {
|
||||
parts.push("UNIQUE");
|
||||
}
|
||||
|
||||
if (field.defaultValue !== undefined) {
|
||||
if (typeof field.defaultValue === "string") {
|
||||
parts.push(`DEFAULT '${field.defaultValue.replace(/'/g, "''")}'`);
|
||||
} else {
|
||||
parts.push(`DEFAULT ${field.defaultValue}`);
|
||||
}
|
||||
} else if (field.defaultValueLiteral) {
|
||||
parts.push(`DEFAULT ${field.defaultValueLiteral}`);
|
||||
}
|
||||
|
||||
if (field.onUpdate) {
|
||||
parts.push(`ON UPDATE ${field.onUpdate}`);
|
||||
} else if (field.onUpdateLiteral) {
|
||||
parts.push(`ON UPDATE ${field.onUpdateLiteral}`);
|
||||
}
|
||||
|
||||
return parts.join(" ");
|
||||
}
|
||||
22
src/lib/schema/create-db-manager-table.ts
Normal file
22
src/lib/schema/create-db-manager-table.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { AppData } from "../../data/app-data";
|
||||
import type { CreateDBSchemaParams } from "../../types";
|
||||
import dbHandler from "../db-handler";
|
||||
import MariaDBQuoteGen from "./mariadb-quote-gen";
|
||||
|
||||
export default async function createDBManagerTable({
|
||||
db_schema,
|
||||
config,
|
||||
}: CreateDBSchemaParams) {
|
||||
let sql = ``;
|
||||
|
||||
sql += `CREATE TABLE IF NOT EXISTS ${MariaDBQuoteGen(AppData["DbSchemaManagerTableName"])} (\n`;
|
||||
sql += ` table_name VARCHAR(255) NOT NULL PRIMARY KEY,\n`;
|
||||
sql += ` created_at BIGINT NOT NULL,\n`;
|
||||
sql += ` updated_at BIGINT NOT NULL\n`;
|
||||
sql += `) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci\n`;
|
||||
|
||||
await dbHandler({
|
||||
query: sql,
|
||||
config,
|
||||
});
|
||||
}
|
||||
23
src/lib/schema/create-db-schema.ts
Normal file
23
src/lib/schema/create-db-schema.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { CreateDBSchemaParams } from "../../types";
|
||||
import createDBManagerTable from "./create-db-manager-table";
|
||||
import handleDBSchemaTables from "./handle-db-schema-tables";
|
||||
import orderDBSchema from "./order-db-schema";
|
||||
|
||||
export default async function createDBSchema(params: CreateDBSchemaParams) {
|
||||
/**
|
||||
* Create Schema Manager Table
|
||||
*/
|
||||
await createDBManagerTable(params);
|
||||
|
||||
/**
|
||||
* Reorder Tables
|
||||
*/
|
||||
const ordered_db_schema = await orderDBSchema(params);
|
||||
|
||||
/**
|
||||
* Handle Tables
|
||||
*/
|
||||
await handleDBSchemaTables({ ...params, db_schema: ordered_db_schema });
|
||||
|
||||
process.exit();
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import { AppData } from "../../data/app-data";
|
||||
import type {
|
||||
BUN_MARIADB_DB_TABLE_MANAGER_TABLE,
|
||||
CreateDBSchemaParams,
|
||||
} from "../../types";
|
||||
import dbHandler from "../db-handler";
|
||||
import MariaDBQuoteGen from "./mariadb-quote-gen";
|
||||
|
||||
export default async function getExistingTablesFromTablesManagerTable({
|
||||
config,
|
||||
}: CreateDBSchemaParams) {
|
||||
const rows = await dbHandler<BUN_MARIADB_DB_TABLE_MANAGER_TABLE>({
|
||||
query: `SELECT table_name FROM ${MariaDBQuoteGen(AppData["DbSchemaManagerTableName"])}`,
|
||||
config,
|
||||
});
|
||||
|
||||
return rows.payload?.map((row) => row.table_name) || [];
|
||||
}
|
||||
46
src/lib/schema/handle-db-schema-table.ts
Normal file
46
src/lib/schema/handle-db-schema-table.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { AppData } from "../../data/app-data";
|
||||
import type {
|
||||
BUN_MARIADB_DB_TABLE_MANAGER_TABLE,
|
||||
BUN_MARIADB_INFORMATION_SCHEMA_TABLES,
|
||||
CreateDBSchemaTableHandlerParams,
|
||||
} from "../../types";
|
||||
import dbHandler from "../db-handler";
|
||||
import DbInsert from "../mariadb/db-insert";
|
||||
import buildColumnDefinition from "./build-column-definition";
|
||||
import MariaDBQuoteGen from "./mariadb-quote-gen";
|
||||
|
||||
export default async function handleDBSchemaTable({
|
||||
db_schema,
|
||||
config,
|
||||
table,
|
||||
db_manager_table_name,
|
||||
existing_live_table,
|
||||
}: CreateDBSchemaTableHandlerParams) {
|
||||
if (!db_manager_table_name || !existing_live_table?.TABLE_NAME) {
|
||||
const insert_table = await DbInsert<BUN_MARIADB_DB_TABLE_MANAGER_TABLE>(
|
||||
{
|
||||
data: [
|
||||
{
|
||||
table_name: table.tableName,
|
||||
},
|
||||
],
|
||||
table: AppData["DbSchemaManagerTableName"],
|
||||
config,
|
||||
},
|
||||
);
|
||||
|
||||
let sql = ``;
|
||||
|
||||
sql += `CREATE TABLE IF NOT EXISTS ${MariaDBQuoteGen(table.tableName)}`;
|
||||
sql += ` (`;
|
||||
|
||||
for (let i = 0; i < table.fields.length; i++) {
|
||||
const field = table.fields[i];
|
||||
if (!field) continue;
|
||||
const col_def = buildColumnDefinition(field);
|
||||
sql += ` ${col_def}`;
|
||||
}
|
||||
|
||||
sql += ` )`;
|
||||
}
|
||||
}
|
||||
57
src/lib/schema/handle-db-schema-tables.ts
Normal file
57
src/lib/schema/handle-db-schema-tables.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { AppData } from "../../data/app-data";
|
||||
import type {
|
||||
BUN_MARIADB_INFORMATION_SCHEMA_TABLES,
|
||||
CreateDBSchemaParams,
|
||||
} from "../../types";
|
||||
import dbHandler from "../db-handler";
|
||||
import getExistingTablesFromTablesManagerTable from "./get-existing-tables-from-tables-manager-table";
|
||||
import handleDBSchemaTable from "./handle-db-schema-table";
|
||||
|
||||
export default async function handleDBSchemaTables(
|
||||
params: CreateDBSchemaParams,
|
||||
) {
|
||||
const { db_schema, config } = params;
|
||||
|
||||
/**
|
||||
* Grab Tables that have been recorded in the Schema
|
||||
* Manager Table
|
||||
*/
|
||||
const existing_schema_tables =
|
||||
await getExistingTablesFromTablesManagerTable(params);
|
||||
|
||||
const existing_live_tables =
|
||||
await dbHandler<BUN_MARIADB_INFORMATION_SCHEMA_TABLES>({
|
||||
query: `SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME != ?`,
|
||||
config: params.config,
|
||||
values: [AppData["DbSchemaManagerTableName"]],
|
||||
});
|
||||
|
||||
for (let i = 0; i < db_schema.tables.length; i++) {
|
||||
const table = db_schema.tables[i];
|
||||
|
||||
const existing_table = existing_schema_tables.find(
|
||||
(t) => t == table?.tableName,
|
||||
);
|
||||
|
||||
const existing_live_table = existing_live_tables.payload?.find(
|
||||
(t) => t.TABLE_NAME == table?.tableName,
|
||||
);
|
||||
|
||||
if (!table) {
|
||||
if (existing_live_table?.TABLE_NAME) {
|
||||
await dbHandler<BUN_MARIADB_INFORMATION_SCHEMA_TABLES>({
|
||||
query: `DROP TABLE ${existing_live_table.TABLE_NAME}`,
|
||||
config: params.config,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
await handleDBSchemaTable({
|
||||
...params,
|
||||
table,
|
||||
db_manager_table_name: existing_table,
|
||||
existing_live_table,
|
||||
});
|
||||
}
|
||||
}
|
||||
102
src/lib/schema/map-data-types.ts
Normal file
102
src/lib/schema/map-data-types.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import type { BUN_MARIADB_FieldSchemaType } from "../../types";
|
||||
|
||||
export default function mapDataType(
|
||||
field: BUN_MARIADB_FieldSchemaType,
|
||||
): string {
|
||||
const dataType = field.dataType?.toUpperCase() || "TEXT";
|
||||
const vectorSize = field.vectorSize || 1536;
|
||||
|
||||
if (field.isVector) {
|
||||
return `LONGTEXT COMMENT 'vector_size=${vectorSize}'`;
|
||||
}
|
||||
|
||||
switch (dataType) {
|
||||
case "CHAR":
|
||||
return `CHAR(${field.integerLength || 255})`;
|
||||
case "VARCHAR":
|
||||
return `VARCHAR(${field.integerLength || 255})`;
|
||||
case "TEXT":
|
||||
return "TEXT";
|
||||
case "TINYTEXT":
|
||||
return "TINYTEXT";
|
||||
case "MEDIUMTEXT":
|
||||
return "MEDIUMTEXT";
|
||||
case "LONGTEXT":
|
||||
return "LONGTEXT";
|
||||
case "TINYINT":
|
||||
return field.integerLength
|
||||
? `TINYINT(${field.integerLength})`
|
||||
: "TINYINT";
|
||||
case "SMALLINT":
|
||||
return field.integerLength
|
||||
? `SMALLINT(${field.integerLength})`
|
||||
: "SMALLINT";
|
||||
case "MEDIUMINT":
|
||||
return field.integerLength
|
||||
? `MEDIUMINT(${field.integerLength})`
|
||||
: "MEDIUMINT";
|
||||
case "INT":
|
||||
return field.integerLength ? `INT(${field.integerLength})` : "INT";
|
||||
case "BIGINT":
|
||||
return field.integerLength
|
||||
? `BIGINT(${field.integerLength})`
|
||||
: "BIGINT";
|
||||
case "FLOAT":
|
||||
return "FLOAT";
|
||||
case "DOUBLE":
|
||||
return "DOUBLE";
|
||||
case "DECIMAL":
|
||||
if (field.integerLength && field.decimals) {
|
||||
return `DECIMAL(${field.integerLength}, ${field.decimals})`;
|
||||
}
|
||||
return "DECIMAL(10,2)";
|
||||
case "BINARY":
|
||||
return `BINARY(${field.integerLength || 1})`;
|
||||
case "VARBINARY":
|
||||
return `VARBINARY(${field.integerLength || 255})`;
|
||||
case "BLOB":
|
||||
return "BLOB";
|
||||
case "TINYBLOB":
|
||||
return "TINYBLOB";
|
||||
case "MEDIUMBLOB":
|
||||
return "MEDIUMBLOB";
|
||||
case "LONGBLOB":
|
||||
return "LONGBLOB";
|
||||
case "DATE":
|
||||
return "DATE";
|
||||
case "TIME":
|
||||
return "TIME";
|
||||
case "DATETIME":
|
||||
return "DATETIME";
|
||||
case "TIMESTAMP":
|
||||
return "TIMESTAMP";
|
||||
case "YEAR":
|
||||
return "YEAR";
|
||||
case "UUID":
|
||||
return "CHAR(36)"; // MariaDB does not have a native UUID type
|
||||
case "JSON":
|
||||
return "JSON";
|
||||
case "INET6":
|
||||
return "INET6";
|
||||
case "VECTOR": {
|
||||
const dimensions = field.vectorSize || 1536;
|
||||
return `VECTOR(${dimensions})`;
|
||||
}
|
||||
case "BOOLEAN":
|
||||
return "TINYINT(1)";
|
||||
case "ENUM": {
|
||||
const enumVals = (field.options || [])
|
||||
.map((v) => `'${String(v).replace(/'/g, "''")}'`)
|
||||
.join(", ");
|
||||
return `ENUM(${enumVals || "''"})`;
|
||||
}
|
||||
case "SET": {
|
||||
const setVals = (field.options || [])
|
||||
.map((v) => `'${String(v).replace(/'/g, "''")}'`)
|
||||
.join(", ");
|
||||
return `SET(${setVals || "''"})`;
|
||||
}
|
||||
default:
|
||||
return "TEXT";
|
||||
}
|
||||
}
|
||||
3
src/lib/schema/mariadb-quote-gen.ts
Normal file
3
src/lib/schema/mariadb-quote-gen.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default function MariaDBQuoteGen(str: string) {
|
||||
return `\`${str.replace(/`/g, "``")}\``;
|
||||
}
|
||||
86
src/lib/schema/order-db-schema.ts
Normal file
86
src/lib/schema/order-db-schema.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import _ from "lodash";
|
||||
import type {
|
||||
BUN_MARIADB_DatabaseSchemaType,
|
||||
BUN_MARIADB_TableSchemaType,
|
||||
CreateDBSchemaParams,
|
||||
} from "../../types";
|
||||
|
||||
export default async function orderDBSchema({
|
||||
db_schema,
|
||||
}: CreateDBSchemaParams): Promise<BUN_MARIADB_DatabaseSchemaType> {
|
||||
let new_db_schema = _.cloneDeep(db_schema);
|
||||
|
||||
const tables = new_db_schema.tables;
|
||||
|
||||
let new_tables_set = new Set<BUN_MARIADB_TableSchemaType>();
|
||||
let new_tables_start_set = new Set<BUN_MARIADB_TableSchemaType>();
|
||||
let new_tables_end_set = new Set<BUN_MARIADB_TableSchemaType>();
|
||||
|
||||
function setParentTable(table: BUN_MARIADB_TableSchemaType) {
|
||||
const fields = table.fields;
|
||||
let does_table_have_foreign_keys = false;
|
||||
|
||||
for (let f = 0; f < fields.length; f++) {
|
||||
const field = fields[f];
|
||||
if (!field) continue;
|
||||
|
||||
const dst_table_name = field.foreignKey?.destinationTableName;
|
||||
|
||||
if (dst_table_name) {
|
||||
const fk_table = tables.find(
|
||||
(tb) => tb.tableName == dst_table_name,
|
||||
);
|
||||
|
||||
if (
|
||||
fk_table &&
|
||||
!new_tables_start_set.has(fk_table) &&
|
||||
!new_tables_end_set.has(fk_table)
|
||||
) {
|
||||
setParentTable(fk_table);
|
||||
}
|
||||
|
||||
new_tables_end_set.add(table);
|
||||
|
||||
if (fk_table) {
|
||||
new_tables_start_set.add(fk_table);
|
||||
}
|
||||
|
||||
does_table_have_foreign_keys = true;
|
||||
}
|
||||
}
|
||||
|
||||
return { does_table_have_foreign_keys };
|
||||
}
|
||||
|
||||
for (let i = 0; i < tables.length; i++) {
|
||||
const table = tables[i];
|
||||
|
||||
if (!table) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let { does_table_have_foreign_keys } = setParentTable(table);
|
||||
|
||||
if (does_table_have_foreign_keys) {
|
||||
new_tables_end_set.add(table);
|
||||
} else {
|
||||
new_tables_start_set.add(table);
|
||||
}
|
||||
}
|
||||
|
||||
const parsed_tables = [
|
||||
...Array.from(new_tables_start_set),
|
||||
...Array.from(new_tables_end_set),
|
||||
];
|
||||
|
||||
for (let nt = 0; nt < parsed_tables.length; nt++) {
|
||||
const new_table = parsed_tables[nt];
|
||||
if (new_table) {
|
||||
new_tables_set.add(new_table);
|
||||
}
|
||||
}
|
||||
|
||||
new_db_schema.tables = Array.from(new_tables_set);
|
||||
|
||||
return new_db_schema;
|
||||
}
|
||||
@ -135,20 +135,49 @@ export const TextFieldTypesArray = [
|
||||
* Native MariaDB column types supported by the schema builder.
|
||||
*/
|
||||
export const BUN_MARIADB_DATATYPES = [
|
||||
// Strings & Text
|
||||
{ value: "CHAR" },
|
||||
{ value: "VARCHAR" },
|
||||
{ value: "TEXT" },
|
||||
{ value: "TINYTEXT" },
|
||||
{ value: "MEDIUMTEXT" },
|
||||
{ value: "LONGTEXT" },
|
||||
|
||||
// Numeric Integers
|
||||
{ value: "TINYINT" },
|
||||
{ value: "SMALLINT" },
|
||||
{ value: "MEDIUMINT" },
|
||||
{ value: "INT" },
|
||||
{ value: "BIGINT" },
|
||||
{ value: "DECIMAL" },
|
||||
|
||||
// Numeric Floats & Exact
|
||||
{ value: "FLOAT" },
|
||||
{ value: "DOUBLE" },
|
||||
{ value: "DECIMAL" },
|
||||
|
||||
// Binary Layouts
|
||||
{ value: "BINARY" },
|
||||
{ value: "VARBINARY" },
|
||||
{ value: "BLOB" },
|
||||
{ value: "TINYBLOB" },
|
||||
{ value: "MEDIUMBLOB" },
|
||||
{ value: "LONGBLOB" },
|
||||
{ value: "BOOLEAN" },
|
||||
|
||||
// Temporal (Dates / Times)
|
||||
{ value: "DATE" },
|
||||
{ value: "TIME" },
|
||||
{ value: "DATETIME" },
|
||||
{ value: "TIMESTAMP" },
|
||||
{ value: "DATE" },
|
||||
{ value: "YEAR" },
|
||||
|
||||
// Core Schema Primitives
|
||||
{ value: "BOOLEAN" },
|
||||
{ value: "UUID" },
|
||||
{ value: "JSON" },
|
||||
{ value: "INET6" },
|
||||
{ value: "ENUM" },
|
||||
{ value: "SET" },
|
||||
{ value: "VECTOR" },
|
||||
] as const;
|
||||
|
||||
/**
|
||||
@ -1561,21 +1590,6 @@ export type BunMariaDBQueryFieldValues<
|
||||
|
||||
export type QueryRawValueType = string | number | null | undefined;
|
||||
|
||||
export type DsqlConnectionParam = {
|
||||
/**
|
||||
* No Database Connection
|
||||
*/
|
||||
noDb?: boolean;
|
||||
/**
|
||||
* Database Name
|
||||
*/
|
||||
database?: string;
|
||||
/**
|
||||
* Debug
|
||||
*/
|
||||
config?: ConnectionConfig;
|
||||
};
|
||||
|
||||
export type DBResponseObject<
|
||||
T extends { [k: string]: any } = { [k: string]: any },
|
||||
> = {
|
||||
@ -1602,3 +1616,27 @@ export const RequiredENVs = [
|
||||
"BUN_MARIADB_SERVER_PASSWORD",
|
||||
"BUN_MARIADB_SERVER_SSL_KEY_PATH",
|
||||
] as const;
|
||||
|
||||
export type CreateDBSchemaParams = {
|
||||
db_schema: BUN_MARIADB_DatabaseSchemaType;
|
||||
config?: BunMariaDBConfig;
|
||||
};
|
||||
|
||||
export type CreateDBSchemaTableHandlerParams = CreateDBSchemaParams & {
|
||||
table: BUN_MARIADB_TableSchemaType;
|
||||
db_manager_table_name?: string;
|
||||
existing_live_table?: BUN_MARIADB_INFORMATION_SCHEMA_TABLES;
|
||||
};
|
||||
|
||||
export type BUN_MARIADB_DB_TABLE_MANAGER_TABLE = {
|
||||
table_name?: string;
|
||||
created_at?: number;
|
||||
updated_at?: number;
|
||||
};
|
||||
|
||||
export type BUN_MARIADB_INFORMATION_SCHEMA_TABLES = {
|
||||
TABLE_NAME?: string;
|
||||
TABLE_TYPE?: "BASE TABLE";
|
||||
ENGINE?: "InnoDB";
|
||||
VERSION?: number;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user