datasquirel/package-shared/shell/createDbFromSchema/grab-required-database-schemas.ts
Benjamin Toby 7e8bb37c09 Updates
2025-07-05 14:59:30 +01:00

318 lines
8.9 KiB
TypeScript

import fs from "fs";
import path from "path";
import grabDirNames from "../../utils/backend/names/grab-dir-names";
import EJSON from "../../utils/ejson";
import { DSQL_DatabaseSchemaType } from "../../types";
import numberfy from "../../utils/numberfy";
import _ from "lodash";
import uniqueByKey from "../../utils/unique-by-key";
type Params = {
userId?: string | number | null;
dbId?: string | number;
dbSlug?: string;
};
export default function grabRequiredDatabaseSchemas(
params: Params
): DSQL_DatabaseSchemaType[] | undefined {
const primaryDbSchema = grabPrimaryRequiredDbSchema(params);
if (!primaryDbSchema) return undefined;
let relatedDatabases: DSQL_DatabaseSchemaType[] = [];
const childrenDatabases = primaryDbSchema.childrenDatabases || [];
const childrenTables =
primaryDbSchema.tables
.map((tbl) => {
return tbl.childrenTables || [];
})
.flat() || [];
for (let i = 0; i < childrenDatabases.length; i++) {
const childDb = childrenDatabases[i];
const childDbSchema = grabPrimaryRequiredDbSchema({
userId: params.userId,
dbId: childDb.dbId,
});
if (!childDbSchema?.dbSlug) continue;
relatedDatabases.push(childDbSchema);
}
for (let i = 0; i < childrenTables.length; i++) {
const childTbl = childrenTables[i];
const childTableDbSchema = grabPrimaryRequiredDbSchema({
userId: params.userId,
dbId: childTbl.dbId,
});
if (!childTableDbSchema?.dbSlug) continue;
relatedDatabases.push(childTableDbSchema);
}
return uniqueByKey([primaryDbSchema, ...relatedDatabases], "dbFullName");
}
export function grabPrimaryRequiredDbSchema({ userId, dbId, dbSlug }: Params) {
let finalDbId = dbId;
if (!finalDbId && userId && dbSlug) {
const searchedDb = findDbNameInSchemaDir({ dbName: dbSlug, userId });
if (searchedDb?.id) {
finalDbId = searchedDb.id;
}
}
if (!finalDbId) {
return undefined;
}
const { targetUserPrivateDir, oldSchemasDir } = grabDirNames({
userId,
});
const finalSchemaDir = targetUserPrivateDir || oldSchemasDir;
if (!finalSchemaDir) {
console.log(`finalSchemaDir not found!`);
return undefined;
}
if (finalDbId) {
const dbIdSchema = path.resolve(finalSchemaDir, `${finalDbId}.json`);
if (fs.existsSync(dbIdSchema)) {
const dbIdSchemaObject = EJSON.parse(
fs.readFileSync(dbIdSchema, "utf-8")
) as DSQL_DatabaseSchemaType | undefined;
return dbIdSchemaObject;
}
}
const dbSchemasFiles = fs.readdirSync(finalSchemaDir);
let targetDbSchema: DSQL_DatabaseSchemaType | undefined;
try {
for (let i = 0; i < dbSchemasFiles.length; i++) {
const fileOrPath = dbSchemasFiles[i];
if (!fileOrPath.endsWith(`.json`)) continue;
if (!fileOrPath.match(/^\d+.json/)) continue;
const targetFileJSONPath = path.join(finalSchemaDir, fileOrPath);
const targetSchema = EJSON.parse(
fs.readFileSync(targetFileJSONPath, "utf-8")
) as DSQL_DatabaseSchemaType | undefined;
if (targetSchema && finalDbId && targetSchema?.id == finalDbId) {
targetDbSchema = targetSchema;
}
}
} catch (error) {}
if (targetDbSchema) {
return targetDbSchema;
}
// else if ( dbFullName) {
// let existingSchemaInMainJSON = findTargetDbSchemaFromMainSchema(
// dbFullName
// );
// const nextID = grabLatestDbSchemaID(finalSchemaDir);
// if (existingSchemaInMainJSON) {
// existingSchemaInMainJSON.id = nextID;
// fs.writeFileSync(
// path.join(finalSchemaDir, `${nextID}.json`),
// EJSON.stringify(existingSchemaInMainJSON) || "[]"
// );
// return existingSchemaInMainJSON;
// }
// }
console.log(`userSchemaDir not found!`);
console.log(`userId`, userId);
return undefined;
}
export function findDbNameInSchemaDir({
userId,
dbName,
}: {
userId?: string | number;
dbName?: string;
}) {
if (!userId) {
console.log(`userId not provided!`);
return undefined;
}
if (!dbName) {
console.log(`dbName not provided!`);
return undefined;
}
const { targetUserPrivateDir } = grabDirNames({
userId,
});
if (!targetUserPrivateDir) {
console.log(`targetUserPrivateDir not found!`);
return undefined;
}
const dbSchemasFiles = fs.readdirSync(targetUserPrivateDir);
let targetDbSchema: DSQL_DatabaseSchemaType | undefined;
try {
for (let i = 0; i < dbSchemasFiles.length; i++) {
const fileOrPath = dbSchemasFiles[i];
if (!fileOrPath.endsWith(`.json`)) continue;
if (!fileOrPath.match(/^\d+.json/)) continue;
const targetFileJSONPath = path.join(
targetUserPrivateDir,
fileOrPath
);
const targetSchema = EJSON.parse(
fs.readFileSync(targetFileJSONPath, "utf-8")
) as DSQL_DatabaseSchemaType | undefined;
if (!targetSchema) continue;
if (
targetSchema.dbFullName == dbName ||
targetSchema.dbSlug == dbName
) {
targetDbSchema = targetSchema;
return targetSchema;
}
}
} catch (error) {}
return targetDbSchema;
}
type UpdateDbSchemaParam = {
dbSchema: DSQL_DatabaseSchemaType;
userId?: string | number | null;
};
export function writeUpdatedDbSchema({
dbSchema,
userId,
}: UpdateDbSchemaParam): { success?: boolean; dbSchemaId?: string | number } {
const { targetUserPrivateDir } = grabDirNames({
userId,
});
if (!targetUserPrivateDir) {
console.log(`user ${userId} has no targetUserPrivateDir`);
return {};
}
if (dbSchema.id) {
const dbIdSchemaPath = path.join(
targetUserPrivateDir,
`${dbSchema.id}.json`
);
fs.writeFileSync(dbIdSchemaPath, EJSON.stringify(dbSchema) || "[]");
return { success: true };
} else {
const nextID = grabLatestDbSchemaID(targetUserPrivateDir);
dbSchema.id = nextID;
fs.writeFileSync(
path.join(targetUserPrivateDir, `${nextID}.json`),
EJSON.stringify(dbSchema) || "[]"
);
return { success: true, dbSchemaId: nextID };
}
}
export function deleteDbSchema({ dbSchema, userId }: UpdateDbSchemaParam) {
const { targetUserPrivateDir, userSchemaMainJSONFilePath } = grabDirNames({
userId,
});
if (!targetUserPrivateDir) return;
const targetDbSchema = grabPrimaryRequiredDbSchema({
dbId: dbSchema.id,
userId,
});
const schemaFile = path.join(
targetUserPrivateDir,
`${targetDbSchema?.id}.json`
);
try {
fs.unlinkSync(schemaFile);
} catch (error) {}
if (
userSchemaMainJSONFilePath &&
fs.existsSync(userSchemaMainJSONFilePath)
) {
try {
let allDbSchemas = EJSON.parse(
fs.readFileSync(userSchemaMainJSONFilePath, "utf-8")
) as DSQL_DatabaseSchemaType[] | undefined;
if (allDbSchemas?.[0]) {
for (let i = 0; i < allDbSchemas.length; i++) {
const dbSch = allDbSchemas[i];
if (
dbSch.dbFullName == dbSchema.dbFullName ||
dbSch.id == dbSchema.id
) {
allDbSchemas.splice(i, 1);
}
}
fs.writeFileSync(
userSchemaMainJSONFilePath,
EJSON.stringify(allDbSchemas) || "[]"
);
}
} catch (error) {}
}
}
export function findTargetDbSchemaFromMainSchema(
schemas: DSQL_DatabaseSchemaType[],
dbFullName?: string,
dbId?: string | number
): DSQL_DatabaseSchemaType | undefined {
const targetDbSchema = schemas.find(
(sch) => sch.dbFullName == dbFullName || (dbId && sch.id == dbId)
);
return targetDbSchema;
}
export function grabLatestDbSchemaID(userSchemaDir: string) {
const dbSchemasFiles = fs.readdirSync(userSchemaDir);
const dbNumbers = dbSchemasFiles
.filter((dbSch) => {
if (!dbSch.endsWith(`.json`)) return false;
if (dbSch.match(/^\d+\.json/)) return true;
return false;
})
.map((dbSch) => numberfy(dbSch.replace(/[^0-9]/g, "")));
if (dbNumbers[0])
return (
(dbNumbers
.sort((a, b) => {
return a - b;
})
.pop() || 0) + 1
);
return 1;
}