config.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import { z } from "zod";
  2. import { mkdir } from "node:fs/promises";
  3. import { join, dirname } from "node:path";
  4. export const OacPreferencesSchema = z.object({
  5. yoloMode: z.boolean(),
  6. autoBackup: z.boolean(),
  7. });
  8. export const OacConfigSchema = z.object({
  9. version: z.literal("1"),
  10. preferences: OacPreferencesSchema,
  11. });
  12. export type OacPreferences = z.infer<typeof OacPreferencesSchema>;
  13. export type OacConfig = z.infer<typeof OacConfigSchema>;
  14. export const getConfigPath = (projectRoot: string): string =>
  15. join(projectRoot, ".oac", "config.json");
  16. export const createDefaultConfig = (): OacConfig => ({
  17. version: "1",
  18. preferences: { yoloMode: false, autoBackup: true },
  19. });
  20. // Pure — returns new object, no mutation
  21. export const mergeConfig = (base: OacConfig, overrides: Partial<OacPreferences>): OacConfig =>
  22. ({ ...base, preferences: { ...base.preferences, ...overrides } });
  23. export const isYoloMode = (config: OacConfig): boolean =>
  24. config.preferences.yoloMode || process.env["CI"] === "true";
  25. export const isAutoBackup = (config: OacConfig): boolean =>
  26. config.preferences.autoBackup;
  27. export async function readConfig(projectRoot: string): Promise<OacConfig | null> {
  28. const configPath = getConfigPath(projectRoot);
  29. if (!(await Bun.file(configPath).exists())) return null;
  30. const raw = await Bun.file(configPath).json() as unknown;
  31. const result = OacConfigSchema.safeParse(raw);
  32. if (!result.success) {
  33. throw new Error(`Invalid config at "${configPath}": ${result.error.message}`);
  34. }
  35. return result.data;
  36. }
  37. export async function writeConfig(projectRoot: string, config: OacConfig): Promise<void> {
  38. const configPath = getConfigPath(projectRoot);
  39. await mkdir(dirname(configPath), { recursive: true });
  40. await Bun.write(configPath, JSON.stringify(config, null, 2));
  41. }