stringent 0.0.1 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -0
- package/dist/context.d.ts +45 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +14 -0
- package/dist/context.js.map +1 -0
- package/dist/createParser.d.ts +159 -0
- package/dist/createParser.d.ts.map +1 -0
- package/dist/createParser.js +118 -0
- package/dist/createParser.js.map +1 -0
- package/dist/errors.d.ts +121 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +186 -0
- package/dist/errors.js.map +1 -0
- package/dist/grammar/index.d.ts +48 -0
- package/dist/grammar/index.d.ts.map +1 -0
- package/dist/grammar/index.js +13 -0
- package/dist/grammar/index.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/parse/index.d.ts +211 -0
- package/dist/parse/index.d.ts.map +1 -0
- package/dist/parse/index.js +16 -0
- package/dist/parse/index.js.map +1 -0
- package/dist/performance.bench.d.ts +10 -0
- package/dist/performance.bench.d.ts.map +1 -0
- package/dist/performance.bench.js +379 -0
- package/dist/performance.bench.js.map +1 -0
- package/dist/primitive/index.d.ts +96 -0
- package/dist/primitive/index.d.ts.map +1 -0
- package/dist/primitive/index.js +102 -0
- package/dist/primitive/index.js.map +1 -0
- package/dist/runtime/eval.d.ts +157 -0
- package/dist/runtime/eval.d.ts.map +1 -0
- package/dist/runtime/eval.js +206 -0
- package/dist/runtime/eval.js.map +1 -0
- package/dist/runtime/infer.d.ts +27 -0
- package/dist/runtime/infer.d.ts.map +1 -0
- package/dist/runtime/infer.js +35 -0
- package/dist/runtime/infer.js.map +1 -0
- package/dist/runtime/parser.d.ts +115 -0
- package/dist/runtime/parser.d.ts.map +1 -0
- package/dist/runtime/parser.js +746 -0
- package/dist/runtime/parser.js.map +1 -0
- package/dist/schema/index.d.ts +476 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +137 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/static/infer.d.ts +27 -0
- package/dist/static/infer.d.ts.map +1 -0
- package/dist/static/infer.js +10 -0
- package/dist/static/infer.js.map +1 -0
- package/package.json +62 -8
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Stringent
|
|
2
|
+
|
|
3
|
+
Type-safe expression parser for TypeScript with compile-time validation.
|
|
4
|
+
|
|
5
|
+
> **Warning:** Under active development. APIs may change.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install stringent
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createParser, defineNode, constVal, lhs, rhs } from 'stringent';
|
|
17
|
+
|
|
18
|
+
// Define operators
|
|
19
|
+
const add = defineNode({
|
|
20
|
+
name: 'add',
|
|
21
|
+
pattern: [lhs('number').as('left'), constVal('+'), rhs('number').as('right')],
|
|
22
|
+
precedence: 1,
|
|
23
|
+
resultType: 'number',
|
|
24
|
+
eval: ({ left, right }) => left + right,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const mul = defineNode({
|
|
28
|
+
name: 'mul',
|
|
29
|
+
pattern: [lhs('number').as('left'), constVal('*'), rhs('number').as('right')],
|
|
30
|
+
precedence: 2,
|
|
31
|
+
resultType: 'number',
|
|
32
|
+
eval: ({ left, right }) => left * right,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Create parser
|
|
36
|
+
const parser = createParser([add, mul]);
|
|
37
|
+
|
|
38
|
+
// Parse and evaluate
|
|
39
|
+
const [evaluator, err] = parser.parse('x + 2 * 3', { x: 'number' });
|
|
40
|
+
if (!err) {
|
|
41
|
+
const result = evaluator({ x: 1 }); // 7
|
|
42
|
+
// ^? number
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Key Features
|
|
47
|
+
|
|
48
|
+
- **Compile-time validation** - Invalid expressions fail TypeScript compilation
|
|
49
|
+
- **Type inference** - Return types flow through parsing to evaluation
|
|
50
|
+
- **ArkType integration** - Schema types validated at compile-time and runtime
|
|
51
|
+
- **Operator precedence** - Configurable precedence for correct parsing
|
|
52
|
+
|
|
53
|
+
## Pattern Elements
|
|
54
|
+
|
|
55
|
+
| Element | Description |
|
|
56
|
+
| --------------- | ----------------------------------- |
|
|
57
|
+
| `lhs(type?)` | Left operand (higher precedence) |
|
|
58
|
+
| `rhs(type?)` | Right operand (same precedence) |
|
|
59
|
+
| `expr(type?)` | Full expression (resets precedence) |
|
|
60
|
+
| `constVal(str)` | Exact string match |
|
|
61
|
+
|
|
62
|
+
## API
|
|
63
|
+
|
|
64
|
+
### `createParser(nodes)`
|
|
65
|
+
|
|
66
|
+
Creates a parser from node definitions.
|
|
67
|
+
|
|
68
|
+
### `defineNode(config)`
|
|
69
|
+
|
|
70
|
+
Defines a grammar node:
|
|
71
|
+
|
|
72
|
+
- `name` - Unique identifier
|
|
73
|
+
- `pattern` - Array of pattern elements
|
|
74
|
+
- `precedence` - Lower binds looser
|
|
75
|
+
- `resultType` - Output type (e.g., `'number'`, `'boolean'`)
|
|
76
|
+
- `eval` - Evaluation function
|
|
77
|
+
|
|
78
|
+
### `parser.parse(input, schema)`
|
|
79
|
+
|
|
80
|
+
Returns `[evaluator, null]` on success or `[null, error]` on failure.
|
|
81
|
+
|
|
82
|
+
The evaluator is callable with data matching the schema and has `ast` and `schema` properties.
|
|
83
|
+
|
|
84
|
+
## Examples
|
|
85
|
+
|
|
86
|
+
See [`examples/`](./examples) for more:
|
|
87
|
+
|
|
88
|
+
- Basic arithmetic with precedence
|
|
89
|
+
- Comparison operators
|
|
90
|
+
- Ternary expressions
|
|
91
|
+
- Custom domain operators
|
|
92
|
+
- Form validation
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
MIT
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context - carries schema data for identifier type resolution
|
|
3
|
+
*
|
|
4
|
+
* The context maps variable names to their types, enabling type-safe
|
|
5
|
+
* parsing of expressions like `x + y` where x and y come from a schema.
|
|
6
|
+
*
|
|
7
|
+
* Grammar is now computed from node schemas via ComputeGrammar<Nodes>.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Schema value type: either a valid arktype type string or a nested object schema.
|
|
11
|
+
* This recursive type allows for nested object schemas like `{ x: { y: 'boolean' } }`.
|
|
12
|
+
*/
|
|
13
|
+
export type SchemaValue = string | {
|
|
14
|
+
readonly [key: string]: SchemaValue;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A schema record maps variable names to their type specifications.
|
|
18
|
+
* Values can be arktype type strings or nested object schemas.
|
|
19
|
+
*/
|
|
20
|
+
export type SchemaRecord = {
|
|
21
|
+
readonly [key: string]: SchemaValue;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Parse context with schema data.
|
|
25
|
+
*
|
|
26
|
+
* @typeParam TData - Schema mapping variable names to their types (strings or nested objects)
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* type Ctx = Context<{ x: "number"; y: "string" }>;
|
|
31
|
+
* // x resolves to type "number", y resolves to type "string"
|
|
32
|
+
*
|
|
33
|
+
* type NestedCtx = Context<{ user: { name: "string"; age: "number" } }>;
|
|
34
|
+
* // user resolves to type { name: string; age: number }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export interface Context<TData extends SchemaRecord = SchemaRecord> {
|
|
38
|
+
/** Schema types for identifier resolution */
|
|
39
|
+
readonly data: TData;
|
|
40
|
+
}
|
|
41
|
+
/** Empty context (no schema variables) */
|
|
42
|
+
export declare const emptyContext: Context<{}>;
|
|
43
|
+
/** Type alias for empty context */
|
|
44
|
+
export type EmptyContext = Context<{}>;
|
|
45
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,CAAC;AAE3E;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,CAAC;AAMnE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,OAAO,CAAC,KAAK,SAAS,YAAY,GAAG,YAAY;IAChE,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;CACtB;AAMD,0CAA0C;AAC1C,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,EAAE,CAAgB,CAAC;AAEtD,mCAAmC;AACnC,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context - carries schema data for identifier type resolution
|
|
3
|
+
*
|
|
4
|
+
* The context maps variable names to their types, enabling type-safe
|
|
5
|
+
* parsing of expressions like `x + y` where x and y come from a schema.
|
|
6
|
+
*
|
|
7
|
+
* Grammar is now computed from node schemas via ComputeGrammar<Nodes>.
|
|
8
|
+
*/
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// Default Context
|
|
11
|
+
// =============================================================================
|
|
12
|
+
/** Empty context (no schema variables) */
|
|
13
|
+
export const emptyContext = { data: {} };
|
|
14
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAyCH,gFAAgF;AAChF,kBAAkB;AAClB,gFAAgF;AAEhF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAgB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createParser Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Creates a type-safe parser from node schemas.
|
|
5
|
+
* The returned parser has:
|
|
6
|
+
* - Type-level parsing via Parse<Grammar, Input, Context>
|
|
7
|
+
* - Runtime parsing that mirrors the type structure
|
|
8
|
+
* - Bound evaluator with type-safe data requirements
|
|
9
|
+
*/
|
|
10
|
+
import type { NodeSchema, SchemaToType } from './schema/index.js';
|
|
11
|
+
import type { ComputeGrammar, Grammar } from './grammar/index.js';
|
|
12
|
+
import type { Parse } from './parse/index.js';
|
|
13
|
+
import type { Context, SchemaRecord } from './context.js';
|
|
14
|
+
import { type } from 'arktype';
|
|
15
|
+
export type { SchemaValue, SchemaRecord } from './context.js';
|
|
16
|
+
/**
|
|
17
|
+
* Extract the outputSchema from an AST node type.
|
|
18
|
+
* Returns the literal schema string if present, otherwise 'unknown'.
|
|
19
|
+
*/
|
|
20
|
+
type ExtractOutputSchema<T> = T extends {
|
|
21
|
+
outputSchema: infer S;
|
|
22
|
+
} ? S : 'unknown';
|
|
23
|
+
/**
|
|
24
|
+
* Convert a SchemaRecord to its corresponding TypeScript data type.
|
|
25
|
+
* Maps each schema value to its runtime type using arktype.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* type Data = SchemaRecordToData<{ x: 'number'; y: 'string' }>;
|
|
29
|
+
* // { x: number; y: string }
|
|
30
|
+
*/
|
|
31
|
+
export type SchemaRecordToData<TSchema extends SchemaRecord> = {
|
|
32
|
+
[K in keyof TSchema]: TSchema[K] extends string ? SchemaToType<TSchema[K]> : TSchema[K] extends SchemaRecord ? SchemaRecordToData<TSchema[K]> : unknown;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* A bound evaluator function returned by parser.parse().
|
|
36
|
+
*
|
|
37
|
+
* The evaluator:
|
|
38
|
+
* - Has the nodes pre-bound from the parser
|
|
39
|
+
* - Has the schema captured from the parse call
|
|
40
|
+
* - Requires data that matches the schema types
|
|
41
|
+
* - Returns a value with the type inferred from the AST's outputSchema
|
|
42
|
+
*
|
|
43
|
+
* @typeParam TAST - The parsed AST type
|
|
44
|
+
* @typeParam TSchema - The schema record type
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const [evaluator, err] = parser.parse('x + 1', { x: 'number' });
|
|
49
|
+
* if (!err) {
|
|
50
|
+
* const value = evaluator({ x: 5 }); // value is number
|
|
51
|
+
* const ast = evaluator.ast; // Access the parsed AST
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export interface Evaluator<TAST, TSchema extends SchemaRecord> {
|
|
56
|
+
/**
|
|
57
|
+
* Evaluate the parsed expression with the given data.
|
|
58
|
+
*
|
|
59
|
+
* @param data - Variable values matching the schema types
|
|
60
|
+
* @returns The evaluated result with type inferred from outputSchema
|
|
61
|
+
*/
|
|
62
|
+
(data: SchemaRecordToData<TSchema>): SchemaToType<ExtractOutputSchema<TAST>>;
|
|
63
|
+
/** The parsed AST */
|
|
64
|
+
readonly ast: TAST;
|
|
65
|
+
/** The schema used during parsing */
|
|
66
|
+
readonly schema: TSchema;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Result of parsing an expression.
|
|
70
|
+
*
|
|
71
|
+
* Returns a tuple of [evaluator, null] on success, or [null, error] on failure.
|
|
72
|
+
*
|
|
73
|
+
* @typeParam TAST - The parsed AST type
|
|
74
|
+
* @typeParam TSchema - The schema record type
|
|
75
|
+
*/
|
|
76
|
+
export type ParseResult<TAST, TSchema extends SchemaRecord> = [Evaluator<TAST, TSchema>, null] | [null, Error];
|
|
77
|
+
/**
|
|
78
|
+
* Parser interface with type-safe parse method.
|
|
79
|
+
*
|
|
80
|
+
* TGrammar: The computed grammar type from node schemas
|
|
81
|
+
* TNodes: The tuple of node schemas
|
|
82
|
+
*/
|
|
83
|
+
export interface Parser<TGrammar extends Grammar, TNodes extends readonly NodeSchema[]> {
|
|
84
|
+
/**
|
|
85
|
+
* Parse an input string and return a bound evaluator.
|
|
86
|
+
*
|
|
87
|
+
* Schema values are validated at compile time using arktype.
|
|
88
|
+
* Invalid type strings like 'garbage' will cause TypeScript errors.
|
|
89
|
+
*
|
|
90
|
+
* @param input - The input string to parse
|
|
91
|
+
* @param schema - Schema mapping field names to valid arktype type strings or nested object schemas
|
|
92
|
+
* @returns A tuple of [evaluator, null] on success, or [null, error] on failure
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* const [evaluator, err] = parser.parse("x + 1", { x: 'number' });
|
|
97
|
+
* if (!err) {
|
|
98
|
+
* const value = evaluator({ x: 5 }); // value is number
|
|
99
|
+
* const ast = evaluator.ast;
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* // Valid schema types:
|
|
103
|
+
* parser.parse("x + 1", { x: 'number' }); // primitive
|
|
104
|
+
* parser.parse("x + 1", { x: 'string.email' }); // subtype
|
|
105
|
+
* parser.parse("x + 1", { x: 'number >= 0' }); // constraint
|
|
106
|
+
* parser.parse("x + 1", { x: 'string | number' }); // union
|
|
107
|
+
*
|
|
108
|
+
* // Nested object schemas:
|
|
109
|
+
* parser.parse("user", { user: { name: 'string', age: 'number' } });
|
|
110
|
+
*
|
|
111
|
+
* // Invalid - causes compile error:
|
|
112
|
+
* // parser.parse("x + 1", { x: 'garbage' });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
parse<TInput extends string, const TSchema extends SchemaRecord>(input: ValidatedInput<TGrammar, TInput, Context<TSchema>>, schema: type.validate<TSchema>): ParseResult<ExtractAST<Parse<TGrammar, TInput, Context<TSchema>>>, TSchema>;
|
|
116
|
+
/** The node schemas used to create this parser */
|
|
117
|
+
readonly nodes: TNodes;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Extract the AST from a Parse result type.
|
|
121
|
+
* Parse returns [AST, remaining] where remaining is '' on success.
|
|
122
|
+
*/
|
|
123
|
+
type ExtractAST<T> = T extends [infer AST, ''] ? AST : never;
|
|
124
|
+
type ValidatedInput<TGrammar extends Grammar, TInput extends string, $ extends Context> = Parse<TGrammar, TInput, $> extends [unknown, ''] ? TInput : never;
|
|
125
|
+
/**
|
|
126
|
+
* Create a type-safe parser from node schemas.
|
|
127
|
+
*
|
|
128
|
+
* The returned parser has both:
|
|
129
|
+
* - Compile-time type inference via Parse<Grammar, Input, Context>
|
|
130
|
+
* - Runtime parsing that matches the type structure
|
|
131
|
+
* - Bound evaluator with type-safe data requirements
|
|
132
|
+
*
|
|
133
|
+
* @param nodes - Tuple of node schemas defining the grammar
|
|
134
|
+
* @returns Parser instance with type-safe parse method
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* import { defineNode, number, expr, constVal, createParser } from "stringent";
|
|
139
|
+
*
|
|
140
|
+
* const add = defineNode({
|
|
141
|
+
* name: "add",
|
|
142
|
+
* pattern: [lhs("number").as("left"), constVal("+"), rhs("number").as("right")],
|
|
143
|
+
* precedence: 1,
|
|
144
|
+
* resultType: "number",
|
|
145
|
+
* eval: ({ left, right }) => left + right,
|
|
146
|
+
* });
|
|
147
|
+
*
|
|
148
|
+
* const parser = createParser([add] as const);
|
|
149
|
+
*
|
|
150
|
+
* // Type-safe parsing with bound evaluator!
|
|
151
|
+
* const [evaluator, err] = parser.parse("x + 1", { x: 'number' });
|
|
152
|
+
* if (!err) {
|
|
153
|
+
* const value = evaluator({ x: 5 }); // value is number, equals 6
|
|
154
|
+
* const ast = evaluator.ast;
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare function createParser<const TNodes extends readonly NodeSchema[]>(nodes: TNodes): Parser<ComputeGrammar<TNodes>, TNodes>;
|
|
159
|
+
//# sourceMappingURL=createParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createParser.d.ts","sourceRoot":"","sources":["../src/createParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createParser Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Creates a type-safe parser from node schemas.
|
|
5
|
+
* The returned parser has:
|
|
6
|
+
* - Type-level parsing via Parse<Grammar, Input, Context>
|
|
7
|
+
* - Runtime parsing that mirrors the type structure
|
|
8
|
+
* - Bound evaluator with type-safe data requirements
|
|
9
|
+
*/
|
|
10
|
+
import { parse as runtimeParse } from './runtime/parser.js';
|
|
11
|
+
import { type } from 'arktype';
|
|
12
|
+
import { evaluate } from './runtime/eval.js';
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Runtime Validation
|
|
15
|
+
// =============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Cache for arktype validators to avoid re-creating them for each validation.
|
|
18
|
+
*/
|
|
19
|
+
const validatorCache = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* Get or create an arktype validator for a schema.
|
|
22
|
+
*/
|
|
23
|
+
function getValidator(schema) {
|
|
24
|
+
// For nested objects, create a composite key
|
|
25
|
+
const key = typeof schema === 'string' ? schema : JSON.stringify(schema);
|
|
26
|
+
let validator = validatorCache.get(key);
|
|
27
|
+
if (!validator) {
|
|
28
|
+
validator = type(schema);
|
|
29
|
+
validatorCache.set(key, validator);
|
|
30
|
+
}
|
|
31
|
+
return validator;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate data against a schema at runtime.
|
|
35
|
+
* Throws an error if validation fails.
|
|
36
|
+
*/
|
|
37
|
+
function validateData(data, schema) {
|
|
38
|
+
const validator = getValidator(schema);
|
|
39
|
+
const result = validator(data);
|
|
40
|
+
if (result instanceof type.errors) {
|
|
41
|
+
throw new Error(`Data validation failed: ${result.summary}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// =============================================================================
|
|
45
|
+
// createParser Factory
|
|
46
|
+
// =============================================================================
|
|
47
|
+
/**
|
|
48
|
+
* Create a type-safe parser from node schemas.
|
|
49
|
+
*
|
|
50
|
+
* The returned parser has both:
|
|
51
|
+
* - Compile-time type inference via Parse<Grammar, Input, Context>
|
|
52
|
+
* - Runtime parsing that matches the type structure
|
|
53
|
+
* - Bound evaluator with type-safe data requirements
|
|
54
|
+
*
|
|
55
|
+
* @param nodes - Tuple of node schemas defining the grammar
|
|
56
|
+
* @returns Parser instance with type-safe parse method
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { defineNode, number, expr, constVal, createParser } from "stringent";
|
|
61
|
+
*
|
|
62
|
+
* const add = defineNode({
|
|
63
|
+
* name: "add",
|
|
64
|
+
* pattern: [lhs("number").as("left"), constVal("+"), rhs("number").as("right")],
|
|
65
|
+
* precedence: 1,
|
|
66
|
+
* resultType: "number",
|
|
67
|
+
* eval: ({ left, right }) => left + right,
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* const parser = createParser([add] as const);
|
|
71
|
+
*
|
|
72
|
+
* // Type-safe parsing with bound evaluator!
|
|
73
|
+
* const [evaluator, err] = parser.parse("x + 1", { x: 'number' });
|
|
74
|
+
* if (!err) {
|
|
75
|
+
* const value = evaluator({ x: 5 }); // value is number, equals 6
|
|
76
|
+
* const ast = evaluator.ast;
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function createParser(nodes) {
|
|
81
|
+
// Implementation function with explicit typing to avoid deep instantiation
|
|
82
|
+
const parse = (input, schema) => {
|
|
83
|
+
try {
|
|
84
|
+
// type.validate ensures all string values are valid arktype types
|
|
85
|
+
const context = { data: schema };
|
|
86
|
+
const result = runtimeParse(nodes, input, context);
|
|
87
|
+
// Check for parse failure (empty result or non-empty remaining)
|
|
88
|
+
if (!Array.isArray(result) || result.length !== 2) {
|
|
89
|
+
return [null, new Error(`Parse failed: unexpected result format`)];
|
|
90
|
+
}
|
|
91
|
+
const [ast, remaining] = result;
|
|
92
|
+
if (remaining !== '') {
|
|
93
|
+
return [null, new Error(`Parse failed: unexpected input at '${remaining}'`)];
|
|
94
|
+
}
|
|
95
|
+
// Create the bound evaluator
|
|
96
|
+
const evaluatorFn = (data) => {
|
|
97
|
+
// Validate data against schema at runtime
|
|
98
|
+
validateData(data, schema);
|
|
99
|
+
// Evaluate with the bound nodes - cast for internal use
|
|
100
|
+
// The type system ensures data matches the schema at compile time
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
|
+
return evaluate(ast, { data, nodes });
|
|
103
|
+
};
|
|
104
|
+
// Create the evaluator object with call signature and properties
|
|
105
|
+
const evaluator = Object.assign(evaluatorFn, {
|
|
106
|
+
ast: ast,
|
|
107
|
+
schema: schema,
|
|
108
|
+
});
|
|
109
|
+
return [evaluator, null];
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
return [null, error instanceof Error ? error : new Error(String(error))];
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
// Return the parser object - cast to avoid deep type checking
|
|
116
|
+
return { parse, nodes };
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=createParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createParser.js","sourceRoot":"","sources":["../src/createParser.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Types and Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides rich error information for parse failures including:
|
|
5
|
+
* - Position tracking (offset, line, column)
|
|
6
|
+
* - Source snippets showing where errors occurred
|
|
7
|
+
* - Descriptive messages for different error types
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Source position in the input string.
|
|
11
|
+
*/
|
|
12
|
+
export interface SourcePosition {
|
|
13
|
+
/** Zero-based character offset from start of input */
|
|
14
|
+
readonly offset: number;
|
|
15
|
+
/** One-based line number */
|
|
16
|
+
readonly line: number;
|
|
17
|
+
/** One-based column number (characters from start of line) */
|
|
18
|
+
readonly column: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Calculate position information from input and current offset.
|
|
22
|
+
*
|
|
23
|
+
* @param input - The original input string
|
|
24
|
+
* @param offset - Character offset into the input
|
|
25
|
+
* @returns Position with line and column numbers
|
|
26
|
+
*/
|
|
27
|
+
export declare function calculatePosition(input: string, offset: number): SourcePosition;
|
|
28
|
+
/** Error kinds for categorization */
|
|
29
|
+
export type ParseErrorKind = 'no_match' | 'type_mismatch' | 'unterminated_string' | 'unclosed_paren' | 'unexpected_token' | 'empty_input';
|
|
30
|
+
/**
|
|
31
|
+
* Rich parse error with position and context information.
|
|
32
|
+
*/
|
|
33
|
+
export interface RichParseError {
|
|
34
|
+
/** Error marker for type discrimination */
|
|
35
|
+
readonly __error: true;
|
|
36
|
+
/** Error kind for categorization */
|
|
37
|
+
readonly kind: ParseErrorKind;
|
|
38
|
+
/** Human-readable error message */
|
|
39
|
+
readonly message: string;
|
|
40
|
+
/** Position where the error occurred */
|
|
41
|
+
readonly position: SourcePosition;
|
|
42
|
+
/** The problematic input snippet */
|
|
43
|
+
readonly snippet: string;
|
|
44
|
+
/** The full original input */
|
|
45
|
+
readonly input: string;
|
|
46
|
+
/** Additional context (e.g., expected type, actual type) */
|
|
47
|
+
readonly context?: ErrorContext;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Additional error context for specific error types.
|
|
51
|
+
*/
|
|
52
|
+
export interface ErrorContext {
|
|
53
|
+
/** Expected type for type mismatch errors */
|
|
54
|
+
expected?: string;
|
|
55
|
+
/** Actual type for type mismatch errors */
|
|
56
|
+
actual?: string;
|
|
57
|
+
/** What was being parsed when error occurred */
|
|
58
|
+
parsing?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create a snippet of the input around the error position.
|
|
62
|
+
*
|
|
63
|
+
* @param input - The full input string
|
|
64
|
+
* @param offset - Character offset where error occurred
|
|
65
|
+
* @param contextChars - Number of characters to show around the error
|
|
66
|
+
* @returns A snippet with error position marker
|
|
67
|
+
*/
|
|
68
|
+
export declare function createSnippet(input: string, offset: number, contextChars?: number): string;
|
|
69
|
+
/**
|
|
70
|
+
* Create a RichParseError.
|
|
71
|
+
*/
|
|
72
|
+
export declare function createParseError(kind: ParseErrorKind, message: string, input: string, offset: number, context?: ErrorContext): RichParseError;
|
|
73
|
+
/**
|
|
74
|
+
* Create a "no match" error.
|
|
75
|
+
*/
|
|
76
|
+
export declare function noMatchError(input: string, offset: number): RichParseError;
|
|
77
|
+
/**
|
|
78
|
+
* Create a "type mismatch" error.
|
|
79
|
+
*/
|
|
80
|
+
export declare function typeMismatchError(input: string, offset: number, expected: string, actual: string, parsing?: string): RichParseError;
|
|
81
|
+
/**
|
|
82
|
+
* Create an "unterminated string" error.
|
|
83
|
+
*/
|
|
84
|
+
export declare function unterminatedStringError(input: string, offset: number, quote: string): RichParseError;
|
|
85
|
+
/**
|
|
86
|
+
* Create an "unclosed parenthesis" error.
|
|
87
|
+
*/
|
|
88
|
+
export declare function unclosedParenError(input: string, offset: number): RichParseError;
|
|
89
|
+
/**
|
|
90
|
+
* Create an "unexpected token" error.
|
|
91
|
+
*/
|
|
92
|
+
export declare function unexpectedTokenError(input: string, offset: number, found: string, expected?: string): RichParseError;
|
|
93
|
+
/**
|
|
94
|
+
* Create an "empty input" error.
|
|
95
|
+
*/
|
|
96
|
+
export declare function emptyInputError(input: string): RichParseError;
|
|
97
|
+
import type { ASTNode } from './primitive/index.js';
|
|
98
|
+
/**
|
|
99
|
+
* Extended parse result that can include error information.
|
|
100
|
+
* - Empty array: no match (backward compatible)
|
|
101
|
+
* - [node, remaining]: successful parse
|
|
102
|
+
* - [node, remaining, errors]: successful parse with collected errors
|
|
103
|
+
*/
|
|
104
|
+
export type ParseResultWithErrors<T extends ASTNode<string, unknown> = ASTNode<string, unknown>> = [] | [T & {}, string] | [T & {}, string, RichParseError[]];
|
|
105
|
+
/**
|
|
106
|
+
* Check if a result includes errors.
|
|
107
|
+
*/
|
|
108
|
+
export declare function hasErrors(result: ParseResultWithErrors): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Get errors from a result, or empty array if none.
|
|
111
|
+
*/
|
|
112
|
+
export declare function getErrors(result: ParseResultWithErrors): RichParseError[];
|
|
113
|
+
/**
|
|
114
|
+
* Format an error for display with source context.
|
|
115
|
+
*/
|
|
116
|
+
export declare function formatError(error: RichParseError): string;
|
|
117
|
+
/**
|
|
118
|
+
* Format multiple errors for display.
|
|
119
|
+
*/
|
|
120
|
+
export declare function formatErrors(errors: RichParseError[]): string;
|
|
121
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAO/E;AAMD,qCAAqC;AACrC,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,eAAe,GACf,qBAAqB,GACrB,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,CAAC;AAElB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAMD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAE,MAAW,GAAG,MAAM,CAuB9F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,cAAc,CAUhB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAe1E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,cAAc,CAYhB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,cAAc,CAOhB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAOhF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,GAChB,cAAc,CAWhB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAE7D;AAMD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAC3F,EAAE,GACF,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,GAChB,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;AAEvC;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAEhE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,qBAAqB,GAAG,cAAc,EAAE,CAKzE;AAMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAmBzD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,CAE7D"}
|