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
@@ -0,0 +1,29 @@
import dataTypeParser, { DataTypesWithNumbers } from "./data-type-parser";
export default function dataTypeConstructor(
dataType: string,
limit?: number,
decimal?: number
) {
let finalType = dataTypeParser(dataType).type;
if (!DataTypesWithNumbers.includes(finalType)) {
return finalType;
}
if (finalType == "VARCHAR") {
return (finalType += `(${limit || 250})`);
}
if (
finalType == "DECIMAL" ||
finalType == "FLOAT" ||
finalType == "DOUBLE"
) {
return (finalType += `(${limit || 10},${decimal || 2})`);
}
if (limit && !decimal) finalType += `(${limit})`;
if (limit && decimal) finalType += `(${limit},${decimal})`;
return finalType;
}
@@ -0,0 +1,54 @@
import DataTypes from "../../../data/data-types";
import numberfy from "../../numberfy";
export const DataTypesWithNumbers: (typeof DataTypes)[number]["name"][] = [
"DECIMAL",
"DOUBLE",
"FLOAT",
"VARCHAR",
];
export const DataTypesWithTwoNumbers: (typeof DataTypes)[number]["name"][] = [
"DECIMAL",
"DOUBLE",
"FLOAT",
];
type Return = {
type: (typeof DataTypes)[number]["name"];
limit?: number;
decimal?: number;
};
export default function dataTypeParser(dataType?: string): Return {
if (!dataType) {
return {
type: "VARCHAR",
limit: 250,
};
}
const dataTypeArray = dataType.split("(");
const type = dataTypeArray[0] as (typeof DataTypes)[number]["name"];
const number = dataTypeArray[1] as string | undefined;
if (!DataTypesWithNumbers.includes(type)) {
return {
type,
};
}
if (number?.match(/,/)) {
const numberArr = number.split(",");
return {
type,
limit: numberfy(numberArr[0]),
decimal: numberArr[1] ? numberfy(numberArr[1]) : undefined,
};
}
return {
type,
limit: number ? numberfy(number) : undefined,
};
}
@@ -0,0 +1,36 @@
import {
DSQL_ChildrenDatabaseObject,
DSQL_ChildrenTablesType,
DSQL_DatabaseSchemaType,
} from "../../../types";
type Params = {
dbs?: DSQL_DatabaseSchemaType[];
dbSchema?: DSQL_DatabaseSchemaType;
childDbSchema?: DSQL_ChildrenDatabaseObject;
childTableSchema?: DSQL_ChildrenTablesType;
dbSlug?: string;
dbFullName?: string;
};
export default function grabTargetDatabaseSchemaIndex({
dbs,
dbFullName,
dbSlug,
dbSchema,
childDbSchema,
childTableSchema,
}: Params): number | undefined {
if (!dbs) return undefined;
const targetDbIndex = dbs.findIndex(
(db) =>
(dbSlug && dbSlug == db.dbSlug) ||
(dbFullName && dbFullName == db.dbFullName) ||
(dbSchema && dbSchema.dbSlug && dbSchema.dbSlug == db.dbSlug)
);
if (targetDbIndex < 0) return undefined;
return targetDbIndex;
}
@@ -0,0 +1,29 @@
import { DSQL_ChildrenTablesType, DSQL_TableSchemaType } from "../../../types";
type Params = {
tables?: DSQL_TableSchemaType[];
tableSchema?: DSQL_TableSchemaType;
childTableSchema?: DSQL_ChildrenTablesType;
tableName?: string;
};
export default function grabTargetTableSchemaIndex({
tables,
tableName,
tableSchema,
childTableSchema,
}: Params): number | undefined {
if (!tables) return undefined;
const targetTableIndex = tables.findIndex(
(tbl) =>
(tableName && tableName == tbl.tableName) ||
(tableSchema &&
tableSchema.tableName &&
tableSchema.tableName == tbl.tableName)
);
if (targetTableIndex < 0) return undefined;
return targetTableIndex;
}
@@ -0,0 +1,16 @@
import { DSQL_TableSchemaType } from "../../../types";
type Params = {
tables: DSQL_TableSchemaType[];
tableName?: string;
};
export default function grabTargetTableSchema({
tables,
tableName,
}: Params): DSQL_TableSchemaType | undefined {
const targetTable = tables.find(
(tbl) => tableName && tableName == tbl.tableName
);
return targetTable;
}
@@ -0,0 +1,16 @@
import { DSQL_FieldSchemaType, TextFieldTypesArray } from "../../../types";
export default function grabTextFieldType(
field: DSQL_FieldSchemaType,
nullReturn?: boolean
): (typeof TextFieldTypesArray)[number]["value"] | undefined {
if (field.richText) return "richText";
if (field.json) return "json";
if (field.yaml) return "yaml";
if (field.html) return "html";
if (field.css) return "css";
if (field.javascript) return "javascript";
if (field.shell) return "shell";
if (nullReturn) return undefined;
return "plain";
}
@@ -0,0 +1,132 @@
import {
grabPrimaryRequiredDbSchema,
writeUpdatedDbSchema,
} from "../../../shell/createDbFromSchema/grab-required-database-schemas";
import {
DSQL_ChildrenDatabaseObject,
DSQL_DatabaseSchemaType,
} from "../../../types";
import _ from "lodash";
import uniqueByKey from "../../unique-by-key";
type Params = {
currentDbSchema: DSQL_DatabaseSchemaType;
userId: string | number;
};
export default function ({ currentDbSchema, userId }: Params) {
const newCurrentDbSchema = _.cloneDeep(currentDbSchema);
if (newCurrentDbSchema.childrenDatabases) {
for (
let ch = 0;
ch < newCurrentDbSchema.childrenDatabases.length;
ch++
) {
const dbChildDb = newCurrentDbSchema.childrenDatabases[ch];
if (!dbChildDb.dbId) {
newCurrentDbSchema.childrenDatabases.splice(ch, 1, {});
continue;
}
const targetChildDatabase = grabPrimaryRequiredDbSchema({
dbId: dbChildDb.dbId,
userId,
});
/**
* Delete child database from array if said database
* doesn't exist
*/
if (targetChildDatabase?.id && targetChildDatabase.childDatabase) {
targetChildDatabase.tables = [...newCurrentDbSchema.tables];
writeUpdatedDbSchema({
dbSchema: targetChildDatabase,
userId,
});
} else {
newCurrentDbSchema.childrenDatabases?.splice(ch, 1, {});
}
}
newCurrentDbSchema.childrenDatabases =
uniqueByKey<DSQL_ChildrenDatabaseObject>(
newCurrentDbSchema.childrenDatabases.filter((db) =>
Boolean(db.dbId)
),
"dbId"
);
}
/**
* Handle scenario where this database is a child of another
*/
if (currentDbSchema.childDatabase && currentDbSchema.childDatabaseDbId) {
const targetParentDatabase = grabPrimaryRequiredDbSchema({
dbId: currentDbSchema.childDatabaseDbId,
userId,
});
if (!targetParentDatabase) {
return newCurrentDbSchema;
}
/**
* Delete child Database key/values from current database if
* the parent database doesn't esit
*/
if (!targetParentDatabase?.id) {
delete newCurrentDbSchema.childDatabase;
delete newCurrentDbSchema.childDatabaseDbId;
return newCurrentDbSchema;
}
/**
* New Child Database Object to be appended
*/
const newChildDatabaseObject: DSQL_ChildrenDatabaseObject = {
dbId: currentDbSchema.id,
};
/**
* Add a new Children array in the target Database if this is the
* first child to be added to said database. Else append to array
* if it exists
*/
if (
targetParentDatabase?.id &&
!targetParentDatabase.childrenDatabases?.[0]
) {
targetParentDatabase.childrenDatabases = [newChildDatabaseObject];
} else if (
targetParentDatabase?.id &&
targetParentDatabase.childrenDatabases?.[0]
) {
const existingChildDb = targetParentDatabase.childrenDatabases.find(
(db) => db.dbId == currentDbSchema.id
);
if (!existingChildDb?.dbId) {
targetParentDatabase.childrenDatabases.push(
newChildDatabaseObject
);
}
targetParentDatabase.childrenDatabases = uniqueByKey(
targetParentDatabase.childrenDatabases,
"dbId"
);
}
/**
* Update tables for child database, which is the current database
*/
if (targetParentDatabase?.id) {
newCurrentDbSchema.tables = targetParentDatabase.tables;
writeUpdatedDbSchema({ dbSchema: targetParentDatabase, userId });
}
}
return newCurrentDbSchema;
}
@@ -0,0 +1,229 @@
import {
grabPrimaryRequiredDbSchema,
writeUpdatedDbSchema,
} from "../../../shell/createDbFromSchema/grab-required-database-schemas";
import {
DSQL_ChildrenTablesType,
DSQL_DatabaseSchemaType,
DSQL_TableSchemaType,
} from "../../../types";
import _ from "lodash";
import uniqueByKey from "../../unique-by-key";
type Params = {
currentDbSchema: DSQL_DatabaseSchemaType;
currentTableSchema: DSQL_TableSchemaType;
currentTableSchemaIndex: number;
userId: string | number;
};
export default function ({
currentDbSchema,
currentTableSchema,
currentTableSchemaIndex,
userId,
}: Params): DSQL_DatabaseSchemaType {
if (!currentDbSchema.dbFullName) {
throw new Error(
`Resolve Children tables ERROR => currentDbSchema.dbFullName not found!`
);
}
const newCurrentDbSchema = _.cloneDeep(currentDbSchema);
if (newCurrentDbSchema.tables[currentTableSchemaIndex].childrenTables) {
for (
let ch = 0;
ch <
newCurrentDbSchema.tables[currentTableSchemaIndex].childrenTables
.length;
ch++
) {
const childTable =
newCurrentDbSchema.tables[currentTableSchemaIndex]
.childrenTables[ch];
if (!childTable.dbId || !childTable.tableId) {
newCurrentDbSchema.tables[
currentTableSchemaIndex
].childrenTables?.splice(ch, 1, {});
continue;
}
const targetChildTableParentDatabase = grabPrimaryRequiredDbSchema({
dbId: childTable.dbId,
userId,
});
/**
* Delete child table from array if the parent database
* of said child table has been deleted or doesn't exist
*/
if (!targetChildTableParentDatabase?.dbFullName) {
newCurrentDbSchema.tables[
currentTableSchemaIndex
].childrenTables?.splice(ch, 1, {});
} else {
/**
* Delete child table from array if the parent database
* exists but the target tabled has been deleted or doesn't
* exist
*/
const targetChildTableParentDatabaseTableIndex =
targetChildTableParentDatabase.tables.findIndex(
(tbl) => tbl.id == childTable.tableId
);
const targetChildTableParentDatabaseTable =
targetChildTableParentDatabase.tables[
targetChildTableParentDatabaseTableIndex
];
if (targetChildTableParentDatabaseTable?.childTable) {
targetChildTableParentDatabase.tables[
targetChildTableParentDatabaseTableIndex
].fields = [...currentTableSchema.fields];
targetChildTableParentDatabase.tables[
targetChildTableParentDatabaseTableIndex
].indexes = [...(currentTableSchema.indexes || [])];
writeUpdatedDbSchema({
dbSchema: targetChildTableParentDatabase,
userId,
});
} else {
newCurrentDbSchema.tables[
currentTableSchemaIndex
].childrenTables?.splice(ch, 1, {});
}
}
}
if (
newCurrentDbSchema.tables[currentTableSchemaIndex]
.childrenTables?.[0]
) {
newCurrentDbSchema.tables[currentTableSchemaIndex].childrenTables =
uniqueByKey<DSQL_ChildrenTablesType>(
newCurrentDbSchema.tables[
currentTableSchemaIndex
].childrenTables.filter(
(tbl) => Boolean(tbl.dbId) && Boolean(tbl.tableId)
),
"dbId"
);
} else {
delete newCurrentDbSchema.tables[currentTableSchemaIndex]
.childrenTables;
}
}
/**
* Handle scenario where this table is a child of another
*/
if (
currentTableSchema.childTable &&
currentTableSchema.childTableDbId &&
currentTableSchema.childTableDbId
) {
const targetParentDatabase = grabPrimaryRequiredDbSchema({
dbId: currentTableSchema.childTableDbId,
userId,
});
const targetParentDatabaseTableIndex =
targetParentDatabase?.tables.findIndex(
(tbl) => tbl.id == currentTableSchema.childTableId
);
const targetParentDatabaseTable =
typeof targetParentDatabaseTableIndex == "number"
? targetParentDatabaseTableIndex < 0
? undefined
: targetParentDatabase?.tables[
targetParentDatabaseTableIndex
]
: undefined;
/**
* Delete child Table key/values from current database if
* the parent database doesn't esit
*/
if (
!targetParentDatabase?.dbFullName ||
!targetParentDatabaseTable?.tableName
) {
delete newCurrentDbSchema.tables[currentTableSchemaIndex]
.childTable;
delete newCurrentDbSchema.tables[currentTableSchemaIndex]
.childTableDbId;
delete newCurrentDbSchema.tables[currentTableSchemaIndex]
.childTableId;
delete newCurrentDbSchema.tables[currentTableSchemaIndex]
.childTableDbId;
return newCurrentDbSchema;
}
/**
* New Child Database Table Object to be appended
*/
const newChildDatabaseTableObject: DSQL_ChildrenTablesType = {
tableId: currentTableSchema.id,
dbId: newCurrentDbSchema.id,
};
/**
* Add a new Children array in the target table schema if this is the
* first child to be added to said table schema. Else append to array
* if it exists
*/
if (
typeof targetParentDatabaseTableIndex == "number" &&
!targetParentDatabaseTable.childrenTables?.[0]
) {
targetParentDatabase.tables[
targetParentDatabaseTableIndex
].childrenTables = [newChildDatabaseTableObject];
} else if (
typeof targetParentDatabaseTableIndex == "number" &&
targetParentDatabaseTable.childrenTables?.[0]
) {
const existingChildDbTable =
targetParentDatabaseTable.childrenTables.find(
(tbl) =>
tbl.dbId == newCurrentDbSchema.id &&
tbl.tableId == currentTableSchema.id
);
if (!existingChildDbTable?.tableId) {
targetParentDatabase.tables[
targetParentDatabaseTableIndex
].childrenTables?.push(newChildDatabaseTableObject);
}
targetParentDatabase.tables[
targetParentDatabaseTableIndex
].childrenTables = uniqueByKey(
targetParentDatabase.tables[targetParentDatabaseTableIndex]
.childrenTables || [],
["dbId", "tableId"]
);
}
/**
* Update fields and indexes for child table, which is the
* current table
*/
if (targetParentDatabaseTable?.tableName) {
newCurrentDbSchema.tables[currentTableSchemaIndex].fields =
targetParentDatabaseTable.fields;
newCurrentDbSchema.tables[currentTableSchemaIndex].indexes =
targetParentDatabaseTable.indexes;
writeUpdatedDbSchema({ dbSchema: targetParentDatabase, userId });
}
}
return newCurrentDbSchema;
}
@@ -0,0 +1,32 @@
import fs from "fs";
import { DSQL_DatabaseSchemaType } from "../../../types";
import _ from "lodash";
import resolveSchemaChildrenHandleChildrenDatabases from "./resolve-schema-children-handle-children-databases";
import resolveSchemaChildrenHandleChildrenTables from "./resolve-schema-children-handle-children-tables";
type Params = {
dbSchema: DSQL_DatabaseSchemaType;
userId: string | number;
};
export default function resolveSchemaChildren({ dbSchema, userId }: Params) {
let newDbSchema = _.cloneDeep(dbSchema);
newDbSchema = resolveSchemaChildrenHandleChildrenDatabases({
currentDbSchema: newDbSchema,
userId,
});
for (let t = 0; t < newDbSchema.tables.length; t++) {
const tableSchema = newDbSchema.tables[t];
newDbSchema = resolveSchemaChildrenHandleChildrenTables({
currentDbSchema: newDbSchema,
currentTableSchema: tableSchema,
currentTableSchemaIndex: t,
userId,
});
}
return newDbSchema;
}
@@ -0,0 +1,38 @@
import { DSQL_DatabaseSchemaType } from "../../../types";
import _ from "lodash";
type Params = {
dbSchema: DSQL_DatabaseSchemaType;
userId: string | number;
};
export default function resolveSchemaForeignKeys({ dbSchema, userId }: Params) {
let newDbSchema = _.cloneDeep(dbSchema);
for (let t = 0; t < newDbSchema.tables.length; t++) {
const tableSchema = newDbSchema.tables[t];
for (let f = 0; f < tableSchema.fields.length; f++) {
const fieldSchema = tableSchema.fields[f];
if (fieldSchema.foreignKey?.destinationTableColumnName) {
const fkDestinationTableIndex = newDbSchema.tables.findIndex(
(tbl) =>
tbl.tableName ==
fieldSchema.foreignKey?.destinationTableName
);
/**
* Delete current Foreign Key if related table doesn't exist
* or has been deleted
*/
if (fkDestinationTableIndex < 0) {
delete newDbSchema.tables[t].fields[f].foreignKey;
continue;
}
}
}
}
return newDbSchema;
}
@@ -0,0 +1,78 @@
import fs from "fs";
import grabDirNames from "../../backend/names/grab-dir-names";
import _n from "../../numberfy";
import path from "path";
import { DSQL_DatabaseSchemaType } from "../../../types";
import _ from "lodash";
import EJSON from "../../ejson";
import { writeUpdatedDbSchema } from "../../../shell/createDbFromSchema/grab-required-database-schemas";
type Params = {
userId: string | number;
dbId?: string | number;
};
export default function resolveUsersSchemaIDs({ userId, dbId }: Params) {
const { targetUserPrivateDir, tempDirName } = grabDirNames({ userId });
if (!targetUserPrivateDir) return false;
const schemaDirFilesFolders = fs.readdirSync(targetUserPrivateDir);
for (let i = 0; i < schemaDirFilesFolders.length; i++) {
const fileOrFolderName = schemaDirFilesFolders[i];
if (!fileOrFolderName.match(/^\d+.json/)) continue;
const fileDbId = _n(fileOrFolderName.split(".").shift());
if (!fileDbId) continue;
if (dbId && _n(dbId) !== fileDbId) {
continue;
}
const schemaFullPath = path.join(
targetUserPrivateDir,
fileOrFolderName
);
if (!fs.existsSync(schemaFullPath)) continue;
const dbSchema = EJSON.parse(
fs.readFileSync(schemaFullPath, "utf-8")
) as DSQL_DatabaseSchemaType | undefined;
if (!dbSchema) continue;
let newDbSchema = resolveUserDatabaseSchemaIDs({ dbSchema });
writeUpdatedDbSchema({ dbSchema: newDbSchema, userId });
}
}
export function resolveUserDatabaseSchemaIDs({
dbSchema,
}: {
dbSchema: DSQL_DatabaseSchemaType;
}) {
let newDbSchema = _.cloneDeep(dbSchema);
if (!newDbSchema.id) newDbSchema.id = dbSchema.id;
newDbSchema.tables.forEach((tbl, index) => {
if (!tbl.id) {
newDbSchema.tables[index].id = index + 1;
}
tbl.fields.forEach((fld, flIndx) => {
if (!fld.id) {
newDbSchema.tables[index].fields[flIndx].id = flIndx + 1;
}
});
tbl.indexes?.forEach((indx, indIndx) => {
if (!indx.id && newDbSchema.tables[index].indexes) {
newDbSchema.tables[index].indexes[indIndx].id = indIndx + 1;
}
});
});
return newDbSchema;
}
@@ -0,0 +1,31 @@
import { DSQL_FieldSchemaType, TextFieldTypesArray } from "../../../types";
import _ from "lodash";
export default function setTextFieldType(
field: DSQL_FieldSchemaType,
type?: (typeof TextFieldTypesArray)[number]["value"]
): DSQL_FieldSchemaType {
const newField = _.cloneDeep(field);
delete newField.css;
delete newField.richText;
delete newField.json;
delete newField.shell;
delete newField.html;
delete newField.javascript;
delete newField.yaml;
delete newField.code;
delete newField.defaultValueLiteral;
if (type == "css") return { ...newField, css: true };
if (type == "richText") return { ...newField, richText: true };
if (type == "json") return { ...newField, json: true };
if (type == "shell") return { ...newField, shell: true };
if (type == "html") return { ...newField, html: true };
if (type == "yaml") return { ...newField, yaml: true };
if (type == "javascript") return { ...newField, javascript: true };
if (type == "code") return { ...newField, code: true };
return { ...newField };
}