@fncts/schema 0.0.14 → 0.0.16
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/AST.d.ts +29 -12
- package/Guard.d.ts +9 -0
- package/ParseError.d.ts +40 -3
- package/Parser/api.d.ts +0 -6
- package/Parser/interpreter.d.ts +1 -2
- package/Schema/api.d.ts +1 -1
- package/Schema/derivations.d.ts +1 -1
- package/Show.d.ts +1 -1
- package/_cjs/AST.cjs +115 -65
- package/_cjs/AST.cjs.map +1 -1
- package/_cjs/Guard.cjs +278 -0
- package/_cjs/Guard.cjs.map +1 -0
- package/_cjs/ParseError.cjs +77 -3
- package/_cjs/ParseError.cjs.map +1 -1
- package/_cjs/Parser/api.cjs +11 -23
- package/_cjs/Parser/api.cjs.map +1 -1
- package/_cjs/Parser/interpreter.cjs +93 -141
- package/_cjs/Parser/interpreter.cjs.map +1 -1
- package/_cjs/Schema/api.cjs +28 -29
- package/_cjs/Schema/api.cjs.map +1 -1
- package/_cjs/Show.cjs +23 -12
- package/_cjs/Show.cjs.map +1 -1
- package/_mjs/AST.mjs +107 -61
- package/_mjs/AST.mjs.map +1 -1
- package/_mjs/Guard.mjs +269 -0
- package/_mjs/Guard.mjs.map +1 -0
- package/_mjs/ParseError.mjs +72 -2
- package/_mjs/ParseError.mjs.map +1 -1
- package/_mjs/Parser/api.mjs +10 -21
- package/_mjs/Parser/api.mjs.map +1 -1
- package/_mjs/Parser/interpreter.mjs +94 -142
- package/_mjs/Parser/interpreter.mjs.map +1 -1
- package/_mjs/Schema/api.mjs +28 -29
- package/_mjs/Schema/api.mjs.map +1 -1
- package/_mjs/Show.mjs +23 -12
- package/_mjs/Show.mjs.map +1 -1
- package/_src/AST.ts +96 -47
- package/_src/Guard.ts +268 -0
- package/_src/ParseError.ts +88 -4
- package/_src/Parser/api.ts +8 -21
- package/_src/Parser/interpreter.ts +87 -121
- package/_src/Schema/api.ts +4 -11
- package/_src/Schema/derivations.ts +1 -1
- package/_src/Show.ts +28 -15
- package/package.json +3 -3
package/_src/Guard.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { globalValue } from "@fncts/base/data/Global";
|
|
2
|
+
import { isRecord } from "@fncts/base/util/predicates";
|
|
3
|
+
import { getKeysForIndexSignature, memoize } from "@fncts/schema/utils";
|
|
4
|
+
|
|
5
|
+
import { ASTTag, getSearchTree } from "./AST.js";
|
|
6
|
+
import { parserFor } from "./Parser.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @tsplus getter fncts.schema.Schema is
|
|
10
|
+
*/
|
|
11
|
+
export function is<A>(schema: Schema<A>) {
|
|
12
|
+
return (input: unknown): input is A => {
|
|
13
|
+
return guardFor(schema).is(input);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function guardFor<A>(schema: Schema<A>): Guard<A> {
|
|
18
|
+
return goMemo(schema.ast);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const guardStrict = (value: unknown) => Guard((inp): inp is any => inp === value);
|
|
22
|
+
|
|
23
|
+
const guardMemoMap = globalValue(Symbol.for("fncts.schema.Guard.guardMemoMap"), () => new WeakMap<AST, Guard<any>>());
|
|
24
|
+
|
|
25
|
+
function goMemo(ast: AST): Guard<any> {
|
|
26
|
+
const memo = guardMemoMap.get(ast);
|
|
27
|
+
if (memo) {
|
|
28
|
+
return memo;
|
|
29
|
+
}
|
|
30
|
+
const guard = go(ast);
|
|
31
|
+
guardMemoMap.set(ast, guard);
|
|
32
|
+
return guard;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function go(ast: AST): Guard<any> {
|
|
36
|
+
AST.concrete(ast);
|
|
37
|
+
switch (ast._tag) {
|
|
38
|
+
case ASTTag.Declaration: {
|
|
39
|
+
const parser = parserFor(ast, true);
|
|
40
|
+
return Guard((inp): inp is any =>
|
|
41
|
+
parser(inp).match(
|
|
42
|
+
() => false,
|
|
43
|
+
() => true,
|
|
44
|
+
),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
case ASTTag.Literal: {
|
|
48
|
+
return Guard((inp): inp is any => inp === ast.literal);
|
|
49
|
+
}
|
|
50
|
+
case ASTTag.UniqueSymbol: {
|
|
51
|
+
return guardStrict(ast.symbol);
|
|
52
|
+
}
|
|
53
|
+
case ASTTag.VoidKeyword:
|
|
54
|
+
case ASTTag.UndefinedKeyword: {
|
|
55
|
+
return guardStrict(undefined);
|
|
56
|
+
}
|
|
57
|
+
case ASTTag.NeverKeyword: {
|
|
58
|
+
return Guard((inp): inp is never => false);
|
|
59
|
+
}
|
|
60
|
+
case ASTTag.UnknownKeyword:
|
|
61
|
+
case ASTTag.AnyKeyword: {
|
|
62
|
+
return Guard((inp): inp is any => true);
|
|
63
|
+
}
|
|
64
|
+
case ASTTag.NumberKeyword: {
|
|
65
|
+
return Guard.number;
|
|
66
|
+
}
|
|
67
|
+
case ASTTag.BooleanKeyword: {
|
|
68
|
+
return Guard.boolean;
|
|
69
|
+
}
|
|
70
|
+
case ASTTag.StringKeyword: {
|
|
71
|
+
return Guard.string;
|
|
72
|
+
}
|
|
73
|
+
case ASTTag.BigIntKeyword: {
|
|
74
|
+
return Guard.bigint;
|
|
75
|
+
}
|
|
76
|
+
case ASTTag.SymbolKeyword: {
|
|
77
|
+
return Guard((inp): inp is symbol => typeof inp === "symbol");
|
|
78
|
+
}
|
|
79
|
+
case ASTTag.ObjectKeyword: {
|
|
80
|
+
return Guard(isObject);
|
|
81
|
+
}
|
|
82
|
+
case ASTTag.TemplateLiteral: {
|
|
83
|
+
const parser = parserFor(ast, true);
|
|
84
|
+
return Guard((inp): inp is any =>
|
|
85
|
+
parser(inp).match(
|
|
86
|
+
() => false,
|
|
87
|
+
() => true,
|
|
88
|
+
),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
case ASTTag.Tuple: {
|
|
92
|
+
const elements = ast.elements.map((element) => goMemo(element.type));
|
|
93
|
+
const restElements = ast.rest.match(
|
|
94
|
+
() => Vector.empty<Guard<any>>(),
|
|
95
|
+
(rest) => rest.map(goMemo),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
return Guard((input): input is any => {
|
|
99
|
+
if (!Array.isArray(input)) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let i = 0;
|
|
104
|
+
for (; i < elements.length; i++) {
|
|
105
|
+
if (input.length < i + 1) {
|
|
106
|
+
if (!ast.elements[i]!.isOptional) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
const guard = elements[i]!;
|
|
111
|
+
if (!guard.is(input[i])) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (restElements.length > 0) {
|
|
118
|
+
const head = restElements.unsafeHead!;
|
|
119
|
+
const tail = restElements.tail;
|
|
120
|
+
for (; i < input.length - tail.length; i++) {
|
|
121
|
+
if (!head.is(input[i])) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
for (let j = 0; j < tail.length; j++) {
|
|
126
|
+
i += j;
|
|
127
|
+
if (input.length < i + 1) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
const guard = tail[j]!;
|
|
131
|
+
if (!guard.is(input[i])) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return true;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
case ASTTag.TypeLiteral: {
|
|
141
|
+
if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) {
|
|
142
|
+
return Guard((input): input is Exclude<typeof input, null> => input !== null);
|
|
143
|
+
}
|
|
144
|
+
const propertySignatureTypes = ast.propertySignatures.map((ps) => goMemo(ps.type));
|
|
145
|
+
const indexSignatures = ast.indexSignatures.map((is) => [goMemo(is.parameter), goMemo(is.type)] as const);
|
|
146
|
+
return Guard((input): input is any => {
|
|
147
|
+
if (!isRecord(input)) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const expectedKeys: any = {};
|
|
152
|
+
|
|
153
|
+
console.log(ast.propertySignatures);
|
|
154
|
+
for (let i = 0; i < propertySignatureTypes.length; i++) {
|
|
155
|
+
const ps = ast.propertySignatures[i]!;
|
|
156
|
+
const guard = propertySignatureTypes[i]!;
|
|
157
|
+
const name = ps.name;
|
|
158
|
+
expectedKeys[name] = null;
|
|
159
|
+
if (!Object.prototype.hasOwnProperty.call(input, name)) {
|
|
160
|
+
if (!ps.isOptional) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
if (!guard(input[name])) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (indexSignatures.length > 0) {
|
|
171
|
+
for (let i = 0; i < indexSignatures.length; i++) {
|
|
172
|
+
const [parameter, type] = indexSignatures[i]!;
|
|
173
|
+
const keys = getKeysForIndexSignature(input, ast.indexSignatures[i]!.parameter);
|
|
174
|
+
for (const key of keys) {
|
|
175
|
+
if (Object.prototype.hasOwnProperty.call(expectedKeys, key)) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!parameter(key)) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!type(input[key])) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return true;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
case ASTTag.Union: {
|
|
194
|
+
const searchTree = getSearchTree(ast.types, true);
|
|
195
|
+
const ownKeys = Reflect.ownKeys(searchTree.keys);
|
|
196
|
+
const len = ownKeys.length;
|
|
197
|
+
const otherwise = searchTree.otherwise;
|
|
198
|
+
const map = new Map<any, Guard<any>>();
|
|
199
|
+
ast.types.forEach((ast) => {
|
|
200
|
+
map.set(ast, goMemo(ast));
|
|
201
|
+
});
|
|
202
|
+
return Guard((input): input is any => {
|
|
203
|
+
if (len > 0) {
|
|
204
|
+
if (isRecord(input)) {
|
|
205
|
+
for (let i = 0; i < len; i++) {
|
|
206
|
+
const name = ownKeys[i]!;
|
|
207
|
+
const buckets = searchTree.keys[name]!.buckets;
|
|
208
|
+
if (Object.prototype.hasOwnProperty.call(input, name)) {
|
|
209
|
+
const literal = String(input[name]);
|
|
210
|
+
if (Object.prototype.hasOwnProperty.call(buckets, literal)) {
|
|
211
|
+
const bucket: ReadonlyArray<AST> = buckets[literal]!;
|
|
212
|
+
for (let i = 0; i < bucket.length; i++) {
|
|
213
|
+
if (map.get(bucket[i])!(input)) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (let i = 0; i < otherwise.length; i++) {
|
|
223
|
+
if (map.get(otherwise[i])!(input)) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return false;
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
case ASTTag.Lazy: {
|
|
231
|
+
const f = () => goMemo(ast.getAST());
|
|
232
|
+
const get = memoize<void, Guard<any>>(f);
|
|
233
|
+
return Guard((input): input is any => get()(input));
|
|
234
|
+
}
|
|
235
|
+
case ASTTag.Enum: {
|
|
236
|
+
return Guard((input): input is any => ast.enums.some(([_, value]) => value === input));
|
|
237
|
+
}
|
|
238
|
+
case ASTTag.Refinement: {
|
|
239
|
+
const from = goMemo(ast.from);
|
|
240
|
+
return Guard((input): input is any => {
|
|
241
|
+
if (!from(input)) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
if (!ast.predicate(input)) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
return true;
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
case ASTTag.Transform: {
|
|
251
|
+
return goMemo(ast.to);
|
|
252
|
+
}
|
|
253
|
+
case ASTTag.Validation: {
|
|
254
|
+
const from = goMemo(ast.from);
|
|
255
|
+
return Guard((input): input is any => {
|
|
256
|
+
if (!from(input)) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
for (const validation of ast.validation) {
|
|
260
|
+
if (!validation.validate(input)) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return true;
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
package/_src/ParseError.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TemplateLiteral, TemplateLiteralSpan, Validation } from "@fncts/schema/AST";
|
|
1
|
+
import type { Refinement, TemplateLiteral, TemplateLiteralSpan, Transform, Validation } from "@fncts/schema/AST";
|
|
2
2
|
|
|
3
3
|
import { showWithOptions } from "@fncts/base/data/Showable";
|
|
4
4
|
import { concrete } from "@fncts/schema/AST";
|
|
@@ -12,6 +12,8 @@ export const enum ParseErrorTag {
|
|
|
12
12
|
Missing,
|
|
13
13
|
Unexpected,
|
|
14
14
|
UnionMember,
|
|
15
|
+
Refinement,
|
|
16
|
+
Transformation,
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -24,8 +26,9 @@ export type ParseError =
|
|
|
24
26
|
| KeyError
|
|
25
27
|
| MissingError
|
|
26
28
|
| UnexpectedError
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
+
| UnionMemberError
|
|
30
|
+
| RefinementError
|
|
31
|
+
| TransformationError;
|
|
29
32
|
|
|
30
33
|
/**
|
|
31
34
|
* @tsplus companion fncts.schema.ParseError.TypeError
|
|
@@ -78,7 +81,7 @@ export class KeyError {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
/**
|
|
81
|
-
* @tsplus static fncts.schema.ParseError.
|
|
84
|
+
* @tsplus static fncts.schema.ParseError.KeyError __call
|
|
82
85
|
* @tsplus static fncts.schema.ParseErrorOps KeyError
|
|
83
86
|
*/
|
|
84
87
|
export function keyError(keyAST: AST, key: any, errors: Vector<ParseError>): ParseError {
|
|
@@ -129,6 +132,58 @@ export function unionMemberError(errors: Vector<ParseError>): ParseError {
|
|
|
129
132
|
return new UnionMemberError(errors);
|
|
130
133
|
}
|
|
131
134
|
|
|
135
|
+
/**
|
|
136
|
+
* @tsplus companion fncts.schema.ParseError.RefinementError
|
|
137
|
+
*/
|
|
138
|
+
export class RefinementError {
|
|
139
|
+
readonly _tag = ParseErrorTag.Refinement;
|
|
140
|
+
constructor(
|
|
141
|
+
readonly ast: Refinement,
|
|
142
|
+
readonly actual: unknown,
|
|
143
|
+
readonly kind: "From" | "Predicate",
|
|
144
|
+
readonly errors: Vector<ParseError>,
|
|
145
|
+
) {}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @tsplus static fncts.schema.ParseError.RefinementError __call
|
|
150
|
+
* @tsplus static fncts.schema.ParseErrorOps RefinementError
|
|
151
|
+
*/
|
|
152
|
+
export function refinementError(
|
|
153
|
+
ast: Refinement,
|
|
154
|
+
actual: unknown,
|
|
155
|
+
kind: "From" | "Predicate",
|
|
156
|
+
errors: Vector<ParseError>,
|
|
157
|
+
): ParseError {
|
|
158
|
+
return new RefinementError(ast, actual, kind, errors);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @tsplus companion fncts.schema.ParseError.TransformationError
|
|
163
|
+
*/
|
|
164
|
+
export class TransformationError {
|
|
165
|
+
readonly _tag = ParseErrorTag.Transformation;
|
|
166
|
+
constructor(
|
|
167
|
+
readonly ast: Transform,
|
|
168
|
+
readonly actual: unknown,
|
|
169
|
+
readonly kind: "Encoded" | "Transformation" | "Type",
|
|
170
|
+
readonly errors: Vector<ParseError>,
|
|
171
|
+
) {}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @tsplus static fncts.schema.ParseError.TransformationError __call
|
|
176
|
+
* @tsplus static fncts.schema.ParseErrorOps TransformationError
|
|
177
|
+
*/
|
|
178
|
+
export function transformationError(
|
|
179
|
+
ast: Transform,
|
|
180
|
+
actual: unknown,
|
|
181
|
+
kind: "Encoded" | "Transformation" | "Type",
|
|
182
|
+
errors: Vector<ParseError>,
|
|
183
|
+
): ParseError {
|
|
184
|
+
return new TransformationError(ast, actual, kind, errors);
|
|
185
|
+
}
|
|
186
|
+
|
|
132
187
|
/**
|
|
133
188
|
* @tsplus static fncts.schema.ParseErrorOps format
|
|
134
189
|
*/
|
|
@@ -153,6 +208,31 @@ function formatTemplateLiteral(ast: TemplateLiteral): string {
|
|
|
153
208
|
return ast.head + ast.spans.map((span) => formatTemplateLiteralSpan(span) + span.literal).join("");
|
|
154
209
|
}
|
|
155
210
|
|
|
211
|
+
function formatRefinementKind(error: RefinementError): string {
|
|
212
|
+
switch (error.kind) {
|
|
213
|
+
case "From": {
|
|
214
|
+
return "From side refinement failure";
|
|
215
|
+
}
|
|
216
|
+
case "Predicate": {
|
|
217
|
+
return "Predicate refinement failure";
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function formatTransformationKind(error: TransformationError): string {
|
|
223
|
+
switch (error.kind) {
|
|
224
|
+
case "Encoded": {
|
|
225
|
+
return "Encoded side transformation failure";
|
|
226
|
+
}
|
|
227
|
+
case "Transformation": {
|
|
228
|
+
return "Transformation process failure";
|
|
229
|
+
}
|
|
230
|
+
case "Type": {
|
|
231
|
+
return "Type side transformation failure";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
156
236
|
function getExpected(ast: AST): Maybe<string> {
|
|
157
237
|
return ast.annotations
|
|
158
238
|
.get(ASTAnnotation.Identifier)
|
|
@@ -243,5 +323,9 @@ function go(error: ParseError): RoseTree<string> {
|
|
|
243
323
|
return RoseTree("is missing");
|
|
244
324
|
case ParseErrorTag.UnionMember:
|
|
245
325
|
return RoseTree("union member", error.errors.map(go));
|
|
326
|
+
case ParseErrorTag.Refinement:
|
|
327
|
+
return RoseTree(formatRefinementKind(error), error.errors.map(go));
|
|
328
|
+
case ParseErrorTag.Transformation:
|
|
329
|
+
return RoseTree(formatTransformationKind(error), error.errors.map(go));
|
|
246
330
|
}
|
|
247
331
|
}
|
package/_src/Parser/api.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { parserFor } from "./interpreter.js";
|
|
|
7
7
|
* @tsplus getter fncts.schema.Parser decode
|
|
8
8
|
*/
|
|
9
9
|
export function decode<A>(schema: Schema<A>): Parser<A> {
|
|
10
|
-
return parserFor(schema.ast);
|
|
10
|
+
return parserFor(schema.ast, true);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -23,7 +23,7 @@ export function decodeMaybe<A>(schema: Schema<A>): <A>(input: A, options?: Parse
|
|
|
23
23
|
* @tsplus getter fncts.schema.Parser encode
|
|
24
24
|
*/
|
|
25
25
|
export function encode<A>(schema: Schema<A>): <A>(input: A, options?: ParseOptions) => ParseResult<unknown> {
|
|
26
|
-
return parserFor(schema.ast
|
|
26
|
+
return parserFor(schema.ast, false);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -31,35 +31,22 @@ export function encode<A>(schema: Schema<A>): <A>(input: A, options?: ParseOptio
|
|
|
31
31
|
* @tsplus getter fncts.schema.Parser encodeMaybe
|
|
32
32
|
*/
|
|
33
33
|
export function encodeMaybe<A>(schema: Schema<A>): <A>(input: A, options?: ParseOptions) => Maybe<unknown> {
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @tsplus getter fncts.schema.Schema is
|
|
39
|
-
* @tsplus getter fncts.schema.Parser is
|
|
40
|
-
*/
|
|
41
|
-
export function is<A>(schema: Schema<A>) {
|
|
42
|
-
return (input: unknown, options?: ParseOptions): input is A => {
|
|
43
|
-
return parserFor(schema.ast)(input, options).isRight();
|
|
44
|
-
};
|
|
34
|
+
return (input, options) => encode(schema)(input, options).toMaybe;
|
|
45
35
|
}
|
|
46
36
|
|
|
47
37
|
function parseMaybe(ast: AST) {
|
|
48
|
-
const parse = parserFor(ast);
|
|
38
|
+
const parse = parserFor(ast, true);
|
|
49
39
|
return (input: unknown, options?: ParseOptions): Maybe<any> => {
|
|
50
40
|
return parse(input, options).toMaybe;
|
|
51
41
|
};
|
|
52
42
|
}
|
|
53
43
|
|
|
54
44
|
function parseOrThrow(ast: AST) {
|
|
55
|
-
const parser = parserFor(ast);
|
|
45
|
+
const parser = parserFor(ast, true);
|
|
56
46
|
return (input: unknown, options?: ParseOptions) => {
|
|
57
|
-
return parser(input, options).match({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
},
|
|
61
|
-
Right: Function.identity,
|
|
62
|
-
});
|
|
47
|
+
return parser(input, options).match((failure) => {
|
|
48
|
+
throw new Error(ParseError.format(failure.errors));
|
|
49
|
+
}, Function.identity);
|
|
63
50
|
};
|
|
64
51
|
}
|
|
65
52
|
|