import type { YamlStore } from '../store/store' import { mkdtemp, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' import { isBaseError } from '../errors/base' import { ErrorCode } from '../errors/codes' import { ENV_CONFIG_DIR } from '../store/dir' import { getConfigurationStore } from '../store/manager' import { loadConfig } from './config-loader' describe('loadConfig', () => { let dir: string let prevConfigDir: string | undefined beforeEach(async () => { dir = await mkdtemp(join(tmpdir(), 'difyctl-cfg-')) prevConfigDir = process.env[ENV_CONFIG_DIR] process.env[ENV_CONFIG_DIR] = dir }) afterEach(async () => { if (prevConfigDir === undefined) delete process.env[ENV_CONFIG_DIR] else process.env[ENV_CONFIG_DIR] = prevConfigDir await rm(dir, { recursive: true, force: true }) }) it('returns found:false when config is missing', () => { const r = loadConfig(getConfigurationStore()) expect(r.found).toBe(false) }) it('parses a minimal valid config', () => { getConfigurationStore().setTyped({ schema_version: 1 }) const r = loadConfig(getConfigurationStore()) expect(r.found).toBe(true) if (r.found) expect(r.config.schema_version).toBe(1) }) it('parses defaults + state', () => { getConfigurationStore().setTyped({ schema_version: 1, defaults: { format: 'json', limit: 100 }, state: { current_app: 'app-1' }, }) const r = loadConfig(getConfigurationStore()) expect(r.found).toBe(true) if (r.found) { expect(r.config.defaults.format).toBe('json') expect(r.config.defaults.limit).toBe(100) expect(r.config.state.current_app).toBe('app-1') } }) it('throws BaseError(config_schema_unsupported) when the store fails to parse the file', () => { // Simulate a corrupt on-disk file via a fake store; loadConfig must wrap // the underlying error as ConfigSchemaUnsupported. const throwingStore = { getTyped: () => { throw new Error('YAML parse failure') }, } as unknown as YamlStore let caught: unknown try { loadConfig(throwingStore) } catch (err) { caught = err } expect(isBaseError(caught)).toBe(true) if (isBaseError(caught)) { expect(caught.code).toBe(ErrorCode.ConfigSchemaUnsupported) expect(caught.hint).toMatch(/not valid YAML/) } }) it('throws BaseError(config_schema_unsupported) when zod validation fails', () => { getConfigurationStore().setTyped({ defaults: { limit: 9999 } }) let caught: unknown try { loadConfig(getConfigurationStore()) } catch (err) { caught = err } expect(isBaseError(caught)).toBe(true) if (isBaseError(caught)) expect(caught.code).toBe(ErrorCode.ConfigSchemaUnsupported) }) it('throws BaseError(config_schema_unsupported) when schema_version > 1 (forward-refuse)', () => { getConfigurationStore().setTyped({ schema_version: 2 }) let caught: unknown try { loadConfig(getConfigurationStore()) } catch (err) { caught = err } expect(isBaseError(caught)).toBe(true) if (isBaseError(caught)) { expect(caught.code).toBe(ErrorCode.ConfigSchemaUnsupported) expect(caught.message).toMatch(/schema_version=2/) expect(caught.hint).toMatch(/upgrade difyctl/) } }) })