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; }