refactor: generic store and sources in core
This commit is contained in:
1 parent
32b64460bf
commit
f4249b58cf
7 files changed
+451
-114
No files matched your search
@@ -0,0 +1,124 @@
|
||||
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import * as z from 'zod'
|
||||
import { readConfigFile, readEnvConnections } from '../../../src/config/sources.js'
|
||||
import type { StoreOptions } from '../../../src/config/store.js'
|
||||
|
||||
const schema = z.object({ name: z.string(), value: z.number() }).strict()
|
||||
const opts: StoreOptions = { logLabel: 'testlabel' }
|
||||
const conn = { name: 'a', value: 1 }
|
||||
|
||||
describe('readEnvConnections', () => {
|
||||
let errSpy: ReturnType<typeof vi.spyOn>
|
||||
|
||||
beforeEach(() => {
|
||||
errSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('returns empty when the env var is unset', () => {
|
||||
expect(readEnvConnections(schema, {}, 'X_CONNECTIONS', opts)).toEqual([])
|
||||
expect(errSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('parses a JSON array of connections', () => {
|
||||
const env = { X_CONNECTIONS: JSON.stringify([conn]) }
|
||||
expect(readEnvConnections(schema, env, 'X_CONNECTIONS', opts)).toEqual([conn])
|
||||
})
|
||||
|
||||
it('ignores invalid JSON and logs with the label and var name', () => {
|
||||
expect(
|
||||
readEnvConnections(schema, { X_CONNECTIONS: 'nope{' }, 'X_CONNECTIONS', opts)
|
||||
).toEqual([])
|
||||
expect(errSpy).toHaveBeenCalledWith('testlabel: X_CONNECTIONS is not valid JSON, ignoring')
|
||||
})
|
||||
|
||||
it('ignores non-array JSON and logs with the label and var name', () => {
|
||||
expect(readEnvConnections(schema, { X_CONNECTIONS: '{}' }, 'X_CONNECTIONS', opts)).toEqual(
|
||||
[]
|
||||
)
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'testlabel: X_CONNECTIONS must be a JSON array, ignoring'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('readConfigFile', () => {
|
||||
let dir: string
|
||||
let errSpy: ReturnType<typeof vi.spyOn>
|
||||
|
||||
beforeEach(() => {
|
||||
dir = mkdtempSync(join(tmpdir(), 'core-config-'))
|
||||
errSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('returns empty when path is undefined', () => {
|
||||
expect(readConfigFile(schema, undefined, opts)).toEqual([])
|
||||
expect(errSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('warns and returns empty for a missing file', () => {
|
||||
const path = join(dir, 'absent.json')
|
||||
expect(readConfigFile(schema, path, opts)).toEqual([])
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'testlabel: config file ' + path + ' not found, ignoring'
|
||||
)
|
||||
})
|
||||
|
||||
it('reads the { connections: [...] } shape', () => {
|
||||
const path = join(dir, 'config.json')
|
||||
writeFileSync(path, JSON.stringify({ connections: [conn] }))
|
||||
expect(readConfigFile(schema, path, opts)).toEqual([conn])
|
||||
})
|
||||
|
||||
it('warns on invalid JSON', () => {
|
||||
const path = join(dir, 'config.json')
|
||||
writeFileSync(path, '{ broken')
|
||||
expect(readConfigFile(schema, path, opts)).toEqual([])
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'testlabel: config file ' + path + ' is not valid JSON, ignoring'
|
||||
)
|
||||
})
|
||||
|
||||
it('warns when the top level is an array, not an object', () => {
|
||||
const path = join(dir, 'config.json')
|
||||
writeFileSync(path, JSON.stringify([conn]))
|
||||
expect(readConfigFile(schema, path, opts)).toEqual([])
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'testlabel: config file ' + path + ' must contain { "connections": [...] }, ignoring'
|
||||
)
|
||||
})
|
||||
|
||||
it('warns on null config', () => {
|
||||
const path = join(dir, 'config.json')
|
||||
writeFileSync(path, 'null')
|
||||
expect(readConfigFile(schema, path, opts)).toEqual([])
|
||||
expect(errSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('warns on primitive config', () => {
|
||||
const path = join(dir, 'config.json')
|
||||
writeFileSync(path, '"just a string"')
|
||||
expect(readConfigFile(schema, path, opts)).toEqual([])
|
||||
expect(errSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('warns when the connections key is missing or not an array', () => {
|
||||
const path = join(dir, 'config.json')
|
||||
writeFileSync(path, JSON.stringify({ connections: 'nope' }))
|
||||
expect(readConfigFile(schema, path, opts)).toEqual([])
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'testlabel: config file ' + path + ' must contain { "connections": [...] }, ignoring'
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user