fix: fix minor gotchas

This commit is contained in:
2026-04-15 14:12:16 +08:00
parent ae2445b79c
commit 392d5f1431
6 changed files with 10 additions and 158 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ describe('parseCsv - basic parsing', () => {
it('should parse CSV with string literal columns (unquoted in CSV)', () => {
const csv = [
'name,status',
'string,on | off',
"string,'on' | 'off'",
'Alice,on',
'Bob,off',
].join('\n');
+3 -4
View File
@@ -20,10 +20,9 @@ describe('Primitive types', () => {
expect(schema.validator(42)).toBe(false);
});
it('should handle identifiers with hyphens', () => {
const schema = defineSchema('word-smith');
expect(schema.parse('word-smith')).toBe('word-smith');
expect(schema.validator('word-smith')).toBe(true);
it('should reject unknown identifiers', () => {
expect(() => defineSchema('word-smith')).toThrow(ParseError);
expect(() => defineSchema('strign')).toThrow(ParseError);
});
});
+1 -17
View File
@@ -237,23 +237,7 @@ class Parser {
return { type: 'tuple', elements };
}
let identifier = '';
while (this.pos < this.input.length && /[a-zA-Z0-9\-_]/.test(this.peek())) {
identifier += this.consume();
}
if (identifier.length > 0) {
if (this.consumeStr('[')) {
this.skipWhitespace();
if (!this.consumeStr(']')) {
throw new ParseError('Expected ]', this.pos);
}
return { type: 'array', element: { type: 'string' } };
}
return { type: 'string' };
}
throw new ParseError(`Unexpected character: ${this.peek()}`, this.pos);
throw new ParseError(`Unknown type: ${this.peek() || 'end of input'}`, this.pos);
}
private parseStringLiteralSchema(): Schema {
-131
View File
@@ -1,131 +0,0 @@
import { defineSchema, parseSchema, parseValue, createValidator } from './index';
console.log('=== Testing Schema Parser ===\n');
const testCases = [
{ schema: 'string', value: 'hello', description: 'Simple string' },
{ schema: 'number', value: '42', description: 'Simple number' },
{ schema: 'int', value: '42', description: 'Simple int' },
{ schema: 'float', value: '3.14', description: 'Simple float' },
{ schema: 'float', value: '42', description: 'Float with integer value' },
{ schema: 'boolean', value: 'true', description: 'Simple boolean' },
{ schema: '[string; number]', value: '[hello; 42]', description: 'Tuple' },
{ schema: '[string; number]', value: 'hello; 42', description: 'Tuple without brackets' },
{ schema: 'string[]', value: '[hello; world; test]', description: 'Array of strings' },
{ schema: 'string[]', value: 'hello; world; test', description: 'Array without brackets' },
{ schema: 'number[]', value: '[1; 2; 3; 4]', description: 'Array of numbers' },
{ schema: 'int[]', value: '[1; 2; 3; 4]', description: 'Array of ints' },
{ schema: 'float[]', value: '[1.5; 2.5; 3.5]', description: 'Array of floats' },
{ schema: '[string; number][]', value: '[[a; 1]; [b; 2]; [c; 3]]', description: 'Array of tuples' },
{ schema: '[string; number][]', value: '[a; 1]; [b; 2]; [c; 3]', description: 'Array of tuples without outer brackets' },
{ schema: 'word-smith', value: 'word-smith', description: 'String with hyphen' },
{ schema: 'string', value: 'hello\\;world', description: 'Escaped semicolon' },
{ schema: 'string', value: 'hello\\[world', description: 'Escaped bracket' },
{ schema: 'string', value: 'hello\\\\world', description: 'Escaped backslash' },
{ schema: '[string; string]', value: 'hello\\;world; test', description: 'Tuple with escaped semicolon' },
{ schema: '[x: number; y: number]', value: '[x: 10; y: 20]', description: 'Named tuple' },
{ schema: '[x: number; y: number]', value: 'x: 10; y: 20', description: 'Named tuple without brackets' },
{ schema: '[name: string; age: number; active: boolean]', value: '[name: Alice; age: 30; active: true]', description: 'Named tuple with mixed types' },
{ schema: '[name: string; age: number]', value: 'name: Bob; age: 25', description: 'Named tuple without brackets' },
{ schema: '[point: [x: number; y: number]]', value: '[point: [x: 5; y: 10]]', description: 'Nested named tuple' },
];
console.log('=== Testing String Literals ===\n');
const stringLiteralCases = [
{ schema: '"hello"', value: '"hello"', description: 'Simple string literal' },
{ schema: "'world'", value: "'world'", description: 'Single quoted string literal' },
{ schema: '"on"', value: '"on"', description: 'String literal "on"' },
{ schema: '"off"', value: '"off"', description: 'String literal "off"' },
{ schema: '"hello;world"', value: '"hello;world"', description: 'String literal with semicolon' },
{ schema: '"hello\\"world"', value: '"hello\\"world"', description: 'String literal with escaped quote' },
];
testCases.push(...stringLiteralCases);
console.log('=== Testing Union Types (Enums) ===\n');
const unionCases = [
{ schema: '"on" | "off"', value: '"on"', description: 'Union: on' },
{ schema: '"on" | "off"', value: '"off"', description: 'Union: off' },
{ schema: '"pending" | "approved" | "rejected"', value: '"approved"', description: 'Union: approved' },
{ schema: '( "active" | "inactive" )', value: '"active"', description: 'Union with parentheses' },
{ schema: '[name: string; status: "active" | "inactive"]', value: '[myName; "active"]', description: 'Tuple with union field' },
{ schema: '("pending" | "approved" | "rejected")[]', value: '["pending"; "approved"; "rejected"]', description: 'Array of unions' },
{ schema: 'string | number', value: 'hello', description: 'Union: string' },
{ schema: 'string | number', value: '42', description: 'Union: number' },
{ schema: 'string | "special"', value: 'normal', description: 'Union: string type' },
{ schema: 'string | "special"', value: '"special"', description: 'Union: string literal' },
];
testCases.push(...unionCases);
testCases.forEach(({ schema, value, description }) => {
try {
console.log(`Test: ${description}`);
console.log(` Schema: ${schema}`);
console.log(` Value: "${value}"`);
const parsed = defineSchema(schema);
const parsedValue = parsed.parse(value);
const isValid = parsed.validator(parsedValue);
console.log(` Parsed: ${JSON.stringify(parsedValue)}`);
console.log(` Valid: ${isValid}`);
console.log(' ✓ Passed\n');
} catch (error) {
console.log(` ✗ Failed: ${(error as Error).message}\n`);
}
});
console.log('=== Testing Validation ===\n');
const stringSchema = defineSchema('string');
console.log('String schema validation:');
console.log(` "hello" is valid: ${stringSchema.validator('hello')}`);
console.log(` 42 is valid: ${stringSchema.validator(42)}\n`);
const numberSchema = defineSchema('number');
console.log('Number schema validation:');
console.log(` 42 is valid: ${numberSchema.validator(42)}`);
console.log(` "42" is valid: ${numberSchema.validator('42')}\n`);
const tupleSchema = defineSchema('[string; number; boolean]');
console.log('Tuple [string; number; boolean] validation:');
console.log(` ["hello", 42, true] is valid: ${tupleSchema.validator(['hello', 42, true])}`);
console.log(` ["hello", "42", true] is valid: ${tupleSchema.validator(['hello', '42', true])}\n`);
const arraySchema = defineSchema('number[]');
console.log('Array number[] validation:');
console.log(` [1, 2, 3] is valid: ${arraySchema.validator([1, 2, 3])}`);
console.log(` [1, "2", 3] is valid: ${arraySchema.validator([1, '2', 3])}\n`);
const arrayOfTuplesSchema = defineSchema('[string; number][]');
console.log('Array of tuples [string; number][] validation:');
console.log(` [["a", 1], ["b", 2]] is valid: ${arrayOfTuplesSchema.validator([['a', 1], ['b', 2]])}`);
console.log(` [["a", "1"], ["b", 2]] is valid: ${arrayOfTuplesSchema.validator([['a', '1'], ['b', 2]])}\n`);
console.log('=== Testing Int and Float Types ===\n');
const intSchema = defineSchema('int');
console.log('Int schema validation:');
console.log(` 42 is valid: ${intSchema.validator(42)}`);
console.log(` 3.14 is valid: ${intSchema.validator(3.14)}\n`);
const floatSchema = defineSchema('float');
console.log('Float schema validation:');
console.log(` 3.14 is valid: ${floatSchema.validator(3.14)}`);
console.log(` 42 is valid: ${floatSchema.validator(42)}`);
console.log(` "3.14" is valid: ${floatSchema.validator('3.14')}\n`);
const intArraySchema = defineSchema('int[]');
console.log('Int array validation:');
console.log(` [1, 2, 3] is valid: ${intArraySchema.validator([1, 2, 3])}`);
console.log(` [1, 2.5, 3] is valid: ${intArraySchema.validator([1, 2.5, 3])}\n`);
const floatArraySchema = defineSchema('float[]');
console.log('Float array validation:');
console.log(` [1.5, 2.5, 3.5] is valid: ${floatArraySchema.validator([1.5, 2.5, 3.5])}`);
console.log(` [1, 2, 3] is valid: ${floatArraySchema.validator([1, 2, 3])}\n`);
console.log('=== All tests completed ===');