import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync } from "fs"; import { findUpSync } from "find-up"; import { join } from "path"; import type { ResocketConfig, UserConfig } from "./types"; import { resocketConfigSchema, userConfigSchema } from "./schema"; import { getFormattedError } from "./utils/errror"; import { readEnv } from "./env"; import { homedir } from "os"; interface GetResocketConfig { config?: string; configOverrides?: { port?: number; }; } export const getResocketConfigPath = () => { const resocketConfigPath = findUpSync("resocket.json"); return resocketConfigPath; }; //todo a better parsing of the config. and more proper zod :) export const getResocketConfig = (overrides: GetResocketConfig = {}) => { let resocketConfigPath: string | undefined = overrides.config ? overrides.config : getResocketConfigPath(); if (!resocketConfigPath) throw new Error("Unable to find resocket.config"); const resocketConfigBuffer = readFileSync(resocketConfigPath); const rawConfig = JSON.parse( Buffer.from(resocketConfigBuffer).toString() ) as ResocketConfig; const rawConfigWithOverrides = { ...rawConfig, ...overrides.configOverrides, }; const resocketConfig = resocketConfigSchema.parse(rawConfigWithOverrides); const envs = readEnv(resocketConfig.envFiles); //validate the config to avoid _ room names if (resocketConfig.rooms) { const rooms = Array.isArray(resocketConfig.rooms) ? resocketConfig.rooms : [resocketConfig.rooms]; for (let room of rooms) if (room.startsWith("_")) throw new Error( getFormattedError({ coreMessage: "Rooms cannot have a '_' (underscore) as the first character.", humanMessage: "this is a known limitation & most likely will not change due to internal workings of the framework, sorry for the inconvinience :( ", }) ); } const configWithEnv = { ...resocketConfig, envs }; resocketConfigSchema.parse(configWithEnv); return configWithEnv; }; export const getUserConfigPath = () => { return join(homedir(), ".resocket", "user-config.json"); }; export const getUserConfig = () => { const configPath = getUserConfigPath(); if (!existsSync(configPath)) return; const config = JSON.parse(readFileSync(configPath, "utf8")); return userConfigSchema.parse(config); }; export const saveUserConfig = (config: UserConfig) => { //todo should we use something like keytar? https://www.npmjs.com/package/keytar it is unmaintained though :/ const configPath = getUserConfigPath(); //make the .resocket directory mkdirSync(join(configPath, ".."), { recursive: true }); writeFileSync(configPath, JSON.stringify(config)); }; export const removeUserConfig = () => { rmSync(join(getUserConfigPath(), ".."), { recursive: true, force: true }); };