import { resolve } from 'path' import { cwd } from 'process' import z from 'zod' import fse from 'fs-extra' import { DEFAULT_OP_CONFIG_FILE_NAME } from '@/constants' import { pathToFileURL } from 'url' export const scanConfigSchema = z.object({ roots: z.array(z.string()), exclude: z.array(z.string().or(z.instanceof(RegExp))), output: z.object({ level: z.enum(['all', 'matched']), }), patternFragment: z.object({ pre: z.string(), placeholder: z.string(), post: z.string(), }), checkIsPathLikeString: z.function().args(z.string()).returns(z.boolean()), apis: z.array(z.string()), }) export const opConfigSchema = z.object({ onesVersion: z.string().optional(), enableApiHijack: z.boolean().optional(), scan: scanConfigSchema.deepPartial().optional(), }) export type ScanConfigSchema = z.infer export type OpConfigSchema = z.infer let opConfigCache: OpConfigSchema | null = null let opConfigSetterQueues: Array<(config: OpConfigSchema) => void> = [] export const getOpConfig = async (configPath = resolve(cwd(), DEFAULT_OP_CONFIG_FILE_NAME)) => { if (!opConfigCache) { if (!(await fse.pathExists(configPath))) { opConfigCache = {} } else { const configFilePath = pathToFileURL(configPath).href const configModule = await import(configFilePath) opConfigCache = configModule.default || {} } } if (opConfigSetterQueues.length > 0) { opConfigSetterQueues.forEach((setter) => setter(opConfigCache as OpConfigSchema)) opConfigSetterQueues = [] } return opConfigCache as OpConfigSchema } export const setOpConfig = (setter: (config: OpConfigSchema) => void) => { if (opConfigCache) { setter(opConfigCache) } else { opConfigSetterQueues.push(setter) } }