* feat(cli): dump native Cordis config schemas * test(cli): include schema dump in launcher help snapshot * feat(cli): export JSON Schema for Cordis configuration * fix(cli): preserve config schema discovery and annotations * fix(cli): conservatively project effectful config validation * refactor(boot): encapsulate profile config schema generation * fix(cli): follow Loader disabling and native writeback in config schema - Dormant group/include rows (disabled without group: true) may omit config and are recorded as childless trees; the entry schema skips their child declarations, matching the Loader, which never creates them. - Lazy builders run once per document, and a wrapped null-only projection keeps a deduplicated type list so the document stays compilable. - Union widening applies only when an earlier branch can write adapted values back through a container; +Infinity max and -Infinity min without a step are treated as the native no-ops they are. - Projection limitations repeat at every entry sharing a Config, and the entry schema documents the boolean/expression domain of disabled. - Record the schema-dump validation policy as an Agent Note.
53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
/** Regex projection preserves known portable patterns and rejects Unicode-dependent assertions. */
|
|
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
import { RegExpParser } from '@eslint-community/regexpp'
|
|
import { createPatternCheck } from '../src/config-schema/pattern.ts'
|
|
|
|
const portable = await createPatternCheck()
|
|
|
|
describe('JSON Schema pattern compatibility', () => {
|
|
it.each([
|
|
['^[A-Za-z0-9_-]{1,32}$', '', true],
|
|
['^https?:\\/\\/\\S+$', '', true],
|
|
['\\S', '', true],
|
|
['^.$', '', false],
|
|
['\\uD83D', '', false],
|
|
['\\a', '', false],
|
|
['\\p{Letter}', '', false],
|
|
['^.$', 'u', true],
|
|
['\\a', 'u', false],
|
|
['^[a-z]+$', 'i', false],
|
|
['\\S+\\S+', '', false],
|
|
['(?:abc)', '', false],
|
|
['[\\uD7ff-\\uE000]', '', false],
|
|
['[\\uE000-\\uF000]', '', true],
|
|
['.', '', true],
|
|
['[^x]', '', false],
|
|
['^\\d+\\s\\w+$', '', true],
|
|
['a?', '', true],
|
|
['(?=a)a', '', false],
|
|
['\\bfoo\\b', '', true],
|
|
['a.*\\B', '', false],
|
|
['a.+\\B', '', false],
|
|
['a\\D*\\B', '', false],
|
|
['a\\W+\\B', '', false],
|
|
['a.*\\b', '', false],
|
|
])('%s with flags %s has portability %s', (source, flags, expected) => {
|
|
expect(portable(source, flags)).toBe(expected)
|
|
})
|
|
|
|
it('uses native flagless semantics when flags are absent', () => {
|
|
expect(portable('plain')).toBe(true)
|
|
})
|
|
|
|
it('does not hide unexpected parser failures', () => {
|
|
const parse = vi.spyOn(RegExpParser.prototype, 'parsePattern').mockImplementation(() => { throw new Error('parser failed') })
|
|
try {
|
|
expect(() => portable('plain')).toThrow('parser failed')
|
|
} finally {
|
|
parse.mockRestore()
|
|
}
|
|
})
|
|
})
|