This commit is contained in:
Benjamin Toby
2025-07-05 14:59:30 +01:00
parent 6e334c2525
commit 7e8bb37c09
526 changed files with 17560 additions and 11386 deletions
+14 -21
View File
@@ -1,25 +1,18 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = dbSchemaToType;
const fs_1 = __importDefault(require("fs"));
const grab_dir_names_1 = __importDefault(require("../../utils/backend/names/grab-dir-names"));
const lodash_1 = __importDefault(require("lodash"));
const ejson_1 = __importDefault(require("../../utils/ejson"));
const generate_type_definitions_1 = __importDefault(require("./generate-type-definitions"));
const path_1 = __importDefault(require("path"));
function dbSchemaToType(params) {
import fs from "fs";
import grabDirNames from "../../utils/backend/names/grab-dir-names";
import _ from "lodash";
import EJSON from "../../utils/ejson";
import generateTypeDefinition from "./generate-type-definitions";
import { AppNames } from "../../dict/app-names";
export default function dbSchemaToType(params) {
var _a, _b;
let datasquirelSchema;
const defaultTableFieldsJSONFilePath = path_1.default.resolve(__dirname, "../../data/defaultFields.json");
const { mainShemaJSONFilePath, defaultTableFieldsJSONFilePath } = grabDirNames();
if (params === null || params === void 0 ? void 0 : params.dbSchema) {
datasquirelSchema = params.dbSchema;
}
else {
const { mainShemaJSONFilePath } = (0, grab_dir_names_1.default)();
const mainSchema = ejson_1.default.parse(fs_1.default.readFileSync(mainShemaJSONFilePath, "utf-8"));
const mainSchema = EJSON.parse(fs.readFileSync(mainShemaJSONFilePath, "utf-8"));
datasquirelSchema = mainSchema.find((sch) => sch.dbFullName == "datasquirel");
}
if (!datasquirelSchema)
@@ -27,10 +20,10 @@ function dbSchemaToType(params) {
let tableNames = `export const DsqlTables = [\n${datasquirelSchema.tables
.map((tbl) => ` "${tbl.tableName}",`)
.join("\n")}\n] as const`;
const defaultFields = ejson_1.default.parse(fs_1.default.readFileSync(defaultTableFieldsJSONFilePath, "utf-8"));
const defaultFields = EJSON.parse(fs.readFileSync(defaultTableFieldsJSONFilePath, "utf-8"));
const dbTablesSchemas = datasquirelSchema.tables.map((tblSchm) => {
let newDefaultFields = lodash_1.default.cloneDeep(defaultFields);
return Object.assign(Object.assign({}, tblSchm), { fields: (params === null || params === void 0 ? void 0 : params.dbSchema)
let newDefaultFields = _.cloneDeep(defaultFields);
return Object.assign(Object.assign({}, tblSchm), { fields: tblSchm.fields.find((fld) => fld.fieldName == "id")
? tblSchm.fields
: [
newDefaultFields.shift(),
@@ -40,9 +33,9 @@ function dbSchemaToType(params) {
] });
});
const defDbName = (_b = (datasquirelSchema.dbName ||
((_a = datasquirelSchema.dbFullName) === null || _a === void 0 ? void 0 : _a.replace(/datasquirel_user_\d+_/, "")))) === null || _b === void 0 ? void 0 : _b.toUpperCase().replace(/ /g, "_");
((_a = datasquirelSchema.dbFullName) === null || _a === void 0 ? void 0 : _a.replace(new RegExp(`${AppNames["DsqlDbPrefix"]}\\d+_`), "")))) === null || _b === void 0 ? void 0 : _b.toUpperCase().replace(/ /g, "_");
const schemas = dbTablesSchemas
.map((table) => (0, generate_type_definitions_1.default)({
.map((table) => generateTypeDefinition({
paradigm: "TypeScript",
table,
typeDefName: `DSQL_${defDbName}_${table.tableName.toUpperCase()}`,
+9 -14
View File
@@ -1,23 +1,17 @@
"use strict";
// @ts-check
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = decrypt;
const crypto_1 = require("crypto");
const buffer_1 = require("buffer");
const grab_keys_1 = __importDefault(require("../../utils/grab-keys"));
import { scryptSync, createDecipheriv } from "crypto";
import { Buffer } from "buffer";
import grabKeys from "../../utils/grab-keys";
/**
* # Decrypt Function
*/
function decrypt({ encryptedString, encryptionKey, encryptionSalt, }) {
export default function decrypt({ encryptedString, encryptionKey, encryptionSalt, }) {
var _a;
if (!(encryptedString === null || encryptedString === void 0 ? void 0 : encryptedString.match(/./))) {
console.log("Encrypted string is invalid");
return encryptedString;
}
const { key: encrptKey, salt, keyLen, algorithm, bufferAllocSize, } = (0, grab_keys_1.default)({ encryptionKey });
const { key: encrptKey, salt, keyLen, algorithm, bufferAllocSize, } = grabKeys({ encryptionKey });
if (!(encrptKey === null || encrptKey === void 0 ? void 0 : encrptKey.match(/.{8,}/))) {
console.log("Decrption key is invalid");
return encryptedString;
@@ -26,9 +20,9 @@ function decrypt({ encryptedString, encryptionKey, encryptionSalt, }) {
console.log("Decrption salt is invalid");
return encryptedString;
}
let key = (0, crypto_1.scryptSync)(encrptKey, salt, keyLen);
let iv = buffer_1.Buffer.alloc(bufferAllocSize, 0);
const decipher = (0, crypto_1.createDecipheriv)(algorithm, key, iv);
let key = scryptSync(encrptKey, salt, keyLen);
let iv = Buffer.alloc(bufferAllocSize, 0);
const decipher = createDecipheriv(algorithm, key, iv);
try {
let decrypted = decipher.update(encryptedString, "hex", "utf8");
decrypted += decipher.final("utf8");
@@ -36,6 +30,7 @@ function decrypt({ encryptedString, encryptionKey, encryptionSalt, }) {
}
catch (error) {
console.log("Error in decrypting =>", error.message);
console.log("encryptedString =>", encryptedString);
(_a = global.ERROR_CALLBACK) === null || _a === void 0 ? void 0 : _a.call(global, `Error Decrypting data`, error);
return encryptedString;
}
@@ -1,7 +1,7 @@
/**
* Check for user in local storage
* Regular expression to match default fields
*
* @description Preventdefault, declare variables
* @description Regular expression to match default fields
*/
declare const defaultFieldsRegexp: RegExp;
export default defaultFieldsRegexp;
+4 -10
View File
@@ -1,13 +1,7 @@
"use strict";
// @ts-check
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Check for user in local storage
* Regular expression to match default fields
*
* @description Preventdefault, declare variables
* @description Regular expression to match default fields
*/
const defaultFieldsRegexp = /^id$|^uuid$|^date_created$|^date_created_code$|^date_created_timestamp$|^date_updated$|^date_updated_code$|^date_updated_timestamp$/;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
exports.default = defaultFieldsRegexp;
const defaultFieldsRegexp = /^id$|^uuid$|^uid$|^date_created$|^date_created_code$|^date_created_timestamp$|^date_updated$|^date_updated_code$|^date_updated_timestamp$/;
export default defaultFieldsRegexp;
+8 -14
View File
@@ -1,23 +1,17 @@
"use strict";
// @ts-check
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = encrypt;
const crypto_1 = require("crypto");
const buffer_1 = require("buffer");
const grab_keys_1 = __importDefault(require("../../utils/grab-keys"));
import { scryptSync, createCipheriv } from "crypto";
import { Buffer } from "buffer";
import grabKeys from "../../utils/grab-keys";
/**
* # Encrypt String
*/
function encrypt({ data, encryptionKey, encryptionSalt, }) {
export default function encrypt({ data, encryptionKey, encryptionSalt, }) {
var _a;
if (!(data === null || data === void 0 ? void 0 : data.match(/./))) {
console.log("Encryption string is invalid");
return data;
}
const { key: encrptKey, salt, keyLen, algorithm, bufferAllocSize, } = (0, grab_keys_1.default)({ encryptionKey });
const { key: encrptKey, salt, keyLen, algorithm, bufferAllocSize, } = grabKeys({ encryptionKey });
if (!(encrptKey === null || encrptKey === void 0 ? void 0 : encrptKey.match(/.{8,}/))) {
console.log("Encryption key is invalid");
return data;
@@ -27,9 +21,9 @@ function encrypt({ data, encryptionKey, encryptionSalt, }) {
return data;
}
const password = encrptKey;
let key = (0, crypto_1.scryptSync)(password, salt, keyLen);
let iv = buffer_1.Buffer.alloc(bufferAllocSize, 0);
const cipher = (0, crypto_1.createCipheriv)(algorithm, key, iv);
let key = scryptSync(password, salt, keyLen);
let iv = Buffer.alloc(bufferAllocSize, 0);
const cipher = createCipheriv(algorithm, key, iv);
try {
let encrypted = cipher.update(data, "utf8", "hex");
encrypted += cipher.final("hex");
@@ -6,6 +6,7 @@ type Param = {
typeDefName?: string;
allValuesOptional?: boolean;
addExport?: boolean;
dbName?: string;
};
export default function generateTypeDefinition({ paradigm, table, query, typeDefName, allValuesOptional, addExport, }: Param): string | null;
export default function generateTypeDefinition({ paradigm, table, query, typeDefName, allValuesOptional, addExport, dbName, }: Param): string | null;
export {};
@@ -1,21 +1,30 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = generateTypeDefinition;
const default_fields_regexp_1 = __importDefault(require("./default-fields-regexp"));
function generateTypeDefinition({ paradigm, table, query, typeDefName, allValuesOptional, addExport, }) {
import defaultFieldsRegexp from "./default-fields-regexp";
export default function generateTypeDefinition({ paradigm, table, query, typeDefName, allValuesOptional, addExport, dbName, }) {
let typeDefinition = ``;
try {
const tdName = typeDefName ||
`DSQL_${query.single}_${query.single_table}`.toUpperCase();
const tdName = typeDefName
? typeDefName
: dbName
? `DSQL_${dbName}_${table.tableName}`.toUpperCase()
: `DSQL_${query.single}_${query.single_table}`.toUpperCase();
const fields = table.fields;
function typeMap(type) {
if (type === null || type === void 0 ? void 0 : type.match(/int/i)) {
function typeMap(schemaType) {
var _a, _b;
if (schemaType.options && schemaType.options.length > 0) {
return schemaType.options
.map((opt) => {
var _a;
return ((_a = schemaType.dataType) === null || _a === void 0 ? void 0 : _a.match(/int/i)) ||
typeof opt == "number"
? `${opt}`
: `"${opt}"`;
})
.join(" | ");
}
if ((_a = schemaType.dataType) === null || _a === void 0 ? void 0 : _a.match(/int/i)) {
return "number";
}
if (type === null || type === void 0 ? void 0 : type.match(/text|varchar|timestamp/i)) {
if ((_b = schemaType.dataType) === null || _b === void 0 ? void 0 : _b.match(/text|varchar|timestamp/i)) {
return "string";
}
return "string";
@@ -28,13 +37,13 @@ function generateTypeDefinition({ paradigm, table, query, typeDefName, allValues
var _a;
const nullValue = allValuesOptional
? "?"
: field.nullValue
: ((_a = field.fieldName) === null || _a === void 0 ? void 0 : _a.match(defaultFieldsRegexp))
? "?"
: ((_a = field.fieldName) === null || _a === void 0 ? void 0 : _a.match(default_fields_regexp_1.default))
? "?"
: "";
typesArrayTypeScript.push(` ${field.fieldName}${nullValue}: ${typeMap(field.dataType || "")};`);
typesArrayJavascript.push(` * @property {${typeMap(field.dataType || "")}${nullValue}} ${field.fieldName}`);
: field.notNullValue
? ""
: "?";
typesArrayTypeScript.push(` ${field.fieldName}${nullValue}: ${typeMap(field)};`);
typesArrayJavascript.push(` * @property {${typeMap(field)}${nullValue}} ${field.fieldName}`);
});
typesArrayTypeScript.push(`}`);
typesArrayJavascript.push(` */`);
+5 -11
View File
@@ -1,20 +1,14 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = hashPassword;
const crypto_1 = require("crypto");
const grab_keys_1 = __importDefault(require("../../utils/grab-keys"));
import { createHmac } from "crypto";
import grabKeys from "../../utils/grab-keys";
/**
* # Hash password Function
*/
function hashPassword({ password, encryptionKey, }) {
const { key } = (0, grab_keys_1.default)({ encryptionKey });
export default function hashPassword({ password, encryptionKey, }) {
const { key } = grabKeys({ encryptionKey });
if (!(key === null || key === void 0 ? void 0 : key.match(/.{8,}/))) {
throw new Error("Encryption key is invalid");
}
const hmac = (0, crypto_1.createHmac)("sha512", key);
const hmac = createHmac("sha512", key);
hmac.update(password);
let hashed = hmac.digest("base64");
return hashed;
@@ -1,3 +1,4 @@
import { SQLDeleteGeneratorParams } from "../../../types";
interface SQLDeleteGenReturn {
query: string;
values: string[];
@@ -5,9 +6,5 @@ interface SQLDeleteGenReturn {
/**
* # SQL Delete Generator
*/
export default function sqlDeleteGenerator({ tableName, data, dbFullName, }: {
data: any;
tableName: string;
dbFullName?: string;
}): SQLDeleteGenReturn | undefined;
export default function sqlDeleteGenerator({ tableName, deleteKeyValues, dbFullName, data, }: SQLDeleteGeneratorParams): SQLDeleteGenReturn | undefined;
export {};
@@ -1,26 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = sqlDeleteGenerator;
import sqlEqualityParser from "../../../utils/sql-equality-parser";
/**
* # SQL Delete Generator
*/
function sqlDeleteGenerator({ tableName, data, dbFullName, }) {
export default function sqlDeleteGenerator({ tableName, deleteKeyValues, dbFullName, data, }) {
const finalDbName = dbFullName ? `${dbFullName}.` : "";
try {
let queryStr = `DELETE FROM ${finalDbName}${tableName}`;
let deleteBatch = [];
let queryArr = [];
Object.keys(data).forEach((ky) => {
deleteBatch.push(`${ky}=?`);
queryArr.push(data[ky]);
});
if (data) {
Object.keys(data).forEach((ky) => {
let value = data[ky];
const parsedValue = typeof value == "number" ? String(value) : value;
if (!parsedValue)
return;
if (parsedValue.match(/%/)) {
deleteBatch.push(`${ky} LIKE ?`);
queryArr.push(parsedValue);
}
else {
deleteBatch.push(`${ky}=?`);
queryArr.push(parsedValue);
}
});
}
else if (deleteKeyValues) {
deleteKeyValues.forEach((ky) => {
let value = ky.value;
const parsedValue = typeof value == "number" ? String(value) : value;
if (!parsedValue)
return;
const operator = sqlEqualityParser(ky.operator || "EQUAL");
deleteBatch.push(`${ky.key} ${operator} ?`);
queryArr.push(parsedValue);
});
}
queryStr += ` WHERE ${deleteBatch.join(" AND ")}`;
return {
query: queryStr,
values: queryArr,
};
}
catch ( /** @type {any} */error) {
catch (error) {
console.log(`SQL delete gen ERROR: ${error.message}`);
return undefined;
}
@@ -0,0 +1,12 @@
import { ServerQueryEqualities } from "../../../types";
type Params = {
fieldName: string;
value?: string;
equality: (typeof ServerQueryEqualities)[number];
};
/**
* # SQL Gen Operator Gen
* @description Generates an SQL operator for node module `mysql` or `serverless-mysql`
*/
export default function sqlGenOperatorGen({ fieldName, value, equality, }: Params): string;
export {};
@@ -0,0 +1,50 @@
import sqlEqualityParser from "../../../utils/sql-equality-parser";
/**
* # SQL Gen Operator Gen
* @description Generates an SQL operator for node module `mysql` or `serverless-mysql`
*/
export default function sqlGenOperatorGen({ fieldName, value, equality, }) {
if (value) {
if (equality == "LIKE") {
return `LOWER(${fieldName}) LIKE LOWER('%${value}%')`;
}
else if (equality == "LIKE_RAW") {
return `LOWER(${fieldName}) LIKE LOWER('${value}')`;
}
else if (equality == "NOT LIKE") {
return `LOWER(${fieldName}) NOT LIKE LOWER('%${value}%')`;
}
else if (equality == "NOT LIKE_RAW") {
return `LOWER(${fieldName}) NOT LIKE LOWER('${value}')`;
}
else if (equality == "REGEXP") {
return `LOWER(${fieldName}) REGEXP LOWER('${value}')`;
}
else if (equality == "FULLTEXT") {
return `MATCH(${fieldName}) AGAINST('${value}' IN BOOLEAN MODE)`;
}
else if (equality == "NOT EQUAL") {
return `${fieldName} != ${value}`;
}
else if (equality) {
return `${fieldName} ${sqlEqualityParser(equality)} ${value}`;
}
else {
return `${fieldName} = ${value}`;
}
}
else {
if (equality == "IS NULL") {
return `${fieldName} IS NULL`;
}
else if (equality == "IS NOT NULL") {
return `${fieldName} IS NOT NULL`;
}
else if (equality) {
return `${fieldName} ${sqlEqualityParser(equality)} ?`;
}
else {
return `${fieldName} = ?`;
}
}
}
+31 -8
View File
@@ -1,11 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = sqlGenerator;
import sqlEqualityParser from "../../../utils/sql-equality-parser";
/**
* # SQL Query Generator
* @description Generates an SQL Query for node module `mysql` or `serverless-mysql`
*/
function sqlGenerator({ tableName, genObject, dbFullName, count }) {
export default function sqlGenerator({ tableName, genObject, dbFullName, count }) {
var _a;
const finalQuery = (genObject === null || genObject === void 0 ? void 0 : genObject.query) ? genObject.query : undefined;
const queryKeys = finalQuery ? Object.keys(finalQuery) : undefined;
const sqlSearhValues = [];
@@ -33,19 +32,37 @@ function sqlGenerator({ tableName, genObject, dbFullName, count }) {
else if (typeof queryObj.value == "string" ||
typeof queryObj.value == "number") {
const valueParsed = String(queryObj.value);
const operator = sqlEqualityParser(queryObj.equality || "EQUAL");
if (queryObj.equality == "LIKE") {
str = `LOWER(${finalFieldName}) LIKE LOWER('%${valueParsed}%')`;
}
else if (queryObj.equality == "LIKE_RAW") {
str = `LOWER(${finalFieldName}) LIKE LOWER(?)`;
sqlSearhValues.push(valueParsed);
}
else if (queryObj.equality == "NOT LIKE") {
str = `LOWER(${finalFieldName}) NOT LIKE LOWER('%${valueParsed}%')`;
}
else if (queryObj.equality == "NOT LIKE_RAW") {
str = `LOWER(${finalFieldName}) NOT LIKE LOWER(?)`;
sqlSearhValues.push(valueParsed);
}
else if (queryObj.equality == "REGEXP") {
str = `${finalFieldName} REGEXP '${valueParsed}'`;
str = `LOWER(${finalFieldName}) REGEXP LOWER(?)`;
sqlSearhValues.push(valueParsed);
}
else if (queryObj.equality == "FULLTEXT") {
str = `MATCH(${finalFieldName}) AGAINST('${valueParsed}' IN BOOLEAN MODE)`;
str = `MATCH(${finalFieldName}) AGAINST(? IN BOOLEAN MODE)`;
sqlSearhValues.push(valueParsed);
}
else if (queryObj.equality == "NOT EQUAL") {
str = `${finalFieldName} != ?`;
sqlSearhValues.push(valueParsed);
}
else if (queryObj.equality) {
str = `${finalFieldName} ${operator} ?`;
sqlSearhValues.push(valueParsed);
}
else {
sqlSearhValues.push(valueParsed);
}
@@ -120,7 +137,7 @@ function sqlGenerator({ tableName, genObject, dbFullName, count }) {
}
else if ((_a = genObject === null || genObject === void 0 ? void 0 : genObject.selectFields) === null || _a === void 0 ? void 0 : _a[0]) {
if (genObject.join) {
str += ` ${(_b = genObject.selectFields) === null || _b === void 0 ? void 0 : _b.map((fld) => `${finalDbName}${tableName}.${fld}`).join(",")}`;
str += ` ${(_b = genObject.selectFields) === null || _b === void 0 ? void 0 : _b.map((fld) => `${finalDbName}${tableName}.${String(fld)}`).join(",")}`;
}
else {
str += ` ${(_c = genObject.selectFields) === null || _c === void 0 ? void 0 : _c.join(",")}`;
@@ -207,10 +224,16 @@ function sqlGenerator({ tableName, genObject, dbFullName, count }) {
const stringOperator = (genObject === null || genObject === void 0 ? void 0 : genObject.searchOperator) || "AND";
queryString += ` WHERE ${sqlSearhString.join(` ${stringOperator} `)}`;
}
if ((genObject === null || genObject === void 0 ? void 0 : genObject.order) && !count)
if ((_a = genObject === null || genObject === void 0 ? void 0 : genObject.group) === null || _a === void 0 ? void 0 : _a[0]) {
queryString += ` GROUP BY ${genObject.group
.map((g) => `\`${g.toString()}\``)
.join(",")}`;
}
if ((genObject === null || genObject === void 0 ? void 0 : genObject.order) && !count) {
queryString += ` ORDER BY ${genObject.join
? `${finalDbName}${tableName}.${String(genObject.order.field)}`
: String(genObject.order.field)} ${genObject.order.strategy}`;
}
if ((genObject === null || genObject === void 0 ? void 0 : genObject.limit) && !count)
queryString += ` LIMIT ${genObject.limit}`;
if ((genObject === null || genObject === void 0 ? void 0 : genObject.offset) && !count)
@@ -1,11 +1,8 @@
"use strict";
// @ts-check
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = sqlInsertGenerator;
/**
* # SQL Insert Generator
*/
function sqlInsertGenerator({ tableName, data, dbFullName, }) {
export default function sqlInsertGenerator({ tableName, data, dbFullName, }) {
const finalDbName = dbFullName ? `${dbFullName}.` : "";
try {
if (Array.isArray(data) && (data === null || data === void 0 ? void 0 : data[0])) {
@@ -0,0 +1 @@
export {};
@@ -0,0 +1,82 @@
import mysql from "mysql";
import { exec } from "child_process";
import { promisify } from "util";
function getConnection(config) {
return mysql.createConnection(config);
}
function getMasterStatus(config) {
return new Promise((resolve, reject) => {
const connection = getConnection(config);
connection.query("SHOW MASTER STATUS", (error, results) => {
connection.end();
if (error)
reject(error);
else
resolve(results[0]);
});
});
}
async function syncDatabases() {
const config = {
host: "localhost",
user: "root",
password: "your_password",
};
let lastPosition = null; // Track last synced position
while (true) {
try {
// Get current master status
const { File, Position } = await getMasterStatus(config);
// Determine start position (use lastPosition or 4 if first run)
const startPosition = lastPosition !== null ? lastPosition + 1 : 4;
if (startPosition >= Position) {
await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait 5 seconds if no new changes
continue;
}
// Execute mysqlbinlog to get changes
const execPromise = promisify(exec);
const { stdout } = await execPromise(`mysqlbinlog --database=db_master ${File} --start-position=${startPosition} --stop-position=${Position}`);
if (stdout) {
const connection = getConnection(Object.assign(Object.assign({}, config), { database: "db_slave" }));
return new Promise((resolve, reject) => {
connection.query(stdout, (error) => {
connection.end();
if (error)
reject(error);
else {
lastPosition = Position;
console.log(`Synced up to position ${Position} at ${new Date().toISOString()}`);
resolve(null);
}
});
});
}
}
catch (error) {
console.error("Sync error:", error);
}
await new Promise((resolve) => setTimeout(resolve, 5000)); // Check every 5 seconds
}
}
// Initialize db_slave with db_master data
async function initializeSlave() {
const config = {
host: "localhost",
user: "root",
password: "your_password",
};
try {
await promisify(exec)(`mysqldump -u ${config.user} -p${config.password} db_master > db_master_backup.sql`);
await promisify(exec)(`mysql -u ${config.user} -p${config.password} db_slave < db_master_backup.sql`);
console.log("Slave initialized with master data");
}
catch (error) {
console.error("Initialization error:", error);
}
}
// Run the sync process
async function main() {
await initializeSlave();
await syncDatabases();
}
main().catch(console.error);
@@ -0,0 +1,2 @@
type Params = {};
declare function createDuplicateTablesTriggers({}: Params): void;
@@ -0,0 +1,2 @@
"use strict";
function createDuplicateTablesTriggers({}) { }
@@ -0,0 +1,9 @@
export declare const TriggerParadigms: readonly ["sync_tables", "sync_dbs"];
type Params = {
userId?: string | number;
paradigm: (typeof TriggerParadigms)[number];
dbId?: string | number;
tableName?: string;
};
export default function grabTriggerName({ userId, paradigm, dbId, tableName, }: Params): string;
export {};
@@ -0,0 +1,11 @@
export const TriggerParadigms = ["sync_tables", "sync_dbs"];
export default function grabTriggerName({ userId, paradigm, dbId, tableName, }) {
let triggerName = `dsql_trig_${paradigm}`;
if (userId)
triggerName += `_${userId}`;
if (dbId)
triggerName += `_${dbId}`;
if (tableName)
triggerName += `_${tableName}`;
return triggerName;
}
@@ -0,0 +1,20 @@
import { DSQL_DatabaseSchemaType, DSQL_TableSchemaType } from "../../../types";
declare const TriggerTypes: readonly [{
readonly name: "after_insert";
readonly value: "INSERT";
}, {
readonly name: "after_update";
readonly value: "UPDATE";
}, {
readonly name: "after_delete";
readonly value: "DELETE";
}];
export type TriggerSQLGenParams = {
type: (typeof TriggerTypes)[number];
srcDbSchema: DSQL_DatabaseSchemaType;
srcTableSchema: DSQL_TableSchemaType;
content: string;
proceedureName: string;
};
export default function triggerSQLGen({ type, srcDbSchema, srcTableSchema, content, proceedureName, }: TriggerSQLGenParams): string;
export {};
@@ -0,0 +1,23 @@
const TriggerTypes = [
{
name: "after_insert",
value: "INSERT",
},
{
name: "after_update",
value: "UPDATE",
},
{
name: "after_delete",
value: "DELETE",
},
];
export default function triggerSQLGen({ type, srcDbSchema, srcTableSchema, content, proceedureName, }) {
let sql = `DELIMITER //\n`;
sql += `CREATE PROCEDURE ${proceedureName}`;
sql += `\nBEGIN`;
sql += ` ${content}`;
sql += `\nEND //`;
sql += `\nDELIMITER\n`;
return sql;
}
@@ -0,0 +1,8 @@
import { DSQL_DatabaseSchemaType, DSQL_TableSchemaType } from "../../../types";
import { TriggerSQLGenParams } from "./trigger-sql-gen";
type Params = TriggerSQLGenParams & {
dstDbSchema: DSQL_DatabaseSchemaType;
dstTableSchema: DSQL_TableSchemaType;
};
export default function tableReplicationTriggerSQLGen({ type, dstDbSchema, dstTableSchema, srcDbSchema, srcTableSchema, userId, paradigm, }: Params): string;
export {};
@@ -0,0 +1,32 @@
import triggerSQLGen from "./trigger-sql-gen";
export default function tableReplicationTriggerSQLGen({ type, dstDbSchema, dstTableSchema, srcDbSchema, srcTableSchema, userId, paradigm, }) {
let sql = `CREATE TRIGGER`;
const srcColumns = srcTableSchema.fields
.map((fld) => fld.fieldName)
.filter((fld) => typeof fld == "string");
const dstColumns = dstTableSchema.fields
.map((fld) => fld.fieldName)
.filter((fld) => typeof fld == "string");
if (type.name == "after_insert") {
sql += ` INSERT INTO ${dstDbSchema.dbFullName}.${dstTableSchema.tableName}`;
sql += ` (${dstColumns.join(",")})`;
sql += ` VALUES (${dstColumns.map((c) => `NEW.${c}`).join(",")})`;
}
else if (type.name == "after_update") {
sql += ` UPDATE ${dstDbSchema.dbFullName}.${dstTableSchema.tableName}`;
sql += ` SET ${dstColumns.map((c) => `${c}=NEW.${c}`).join(",")}`;
sql += ` WHERE id = NEW.id`;
}
else if (type.name == "after_delete") {
sql += ` DELETE FROM ${dstDbSchema.dbFullName}.${dstTableSchema.tableName}`;
sql += ` WHERE id = OLD.id`;
}
return triggerSQLGen({
content: sql,
srcDbSchema,
srcTableSchema,
type,
paradigm,
userId,
});
}
@@ -0,0 +1,22 @@
import { DSQL_DatabaseSchemaType, DSQL_TableSchemaType } from "../../../types";
import { TriggerParadigms } from "./grab-trigger-name";
declare const TriggerTypes: readonly [{
readonly name: "after_insert";
readonly value: "INSERT";
}, {
readonly name: "after_update";
readonly value: "UPDATE";
}, {
readonly name: "after_delete";
readonly value: "DELETE";
}];
export type TriggerSQLGenParams = {
type: (typeof TriggerTypes)[number];
srcDbSchema: DSQL_DatabaseSchemaType;
srcTableSchema: DSQL_TableSchemaType;
content: string;
userId?: string | number;
paradigm: (typeof TriggerParadigms)[number];
};
export default function triggerSQLGen({ type, srcDbSchema, srcTableSchema, content, userId, paradigm, }: TriggerSQLGenParams): string;
export {};
@@ -0,0 +1,30 @@
import grabTriggerName from "./grab-trigger-name";
const TriggerTypes = [
{
name: "after_insert",
value: "INSERT",
},
{
name: "after_update",
value: "UPDATE",
},
{
name: "after_delete",
value: "DELETE",
},
];
export default function triggerSQLGen({ type, srcDbSchema, srcTableSchema, content, userId, paradigm, }) {
let sql = `CREATE TRIGGER`;
let triggerName = grabTriggerName({
paradigm,
dbId: srcDbSchema.id,
tableName: srcTableSchema.tableName,
userId,
});
sql += ` ${triggerName}`;
sql += ` AFTER ${type.value} ON ${srcTableSchema.tableName}`;
sql += ` FOR EACH ROW BEGIN`;
sql += ` ${content}`;
sql += ` END`;
return sql;
}