typebox 1.1.6 → 1.1.8
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/build/type/engine/call/distribute-arguments.d.mts +10 -0
- package/build/type/engine/call/distribute-arguments.mjs +27 -0
- package/build/type/engine/call/instantiate.d.mts +9 -6
- package/build/type/engine/call/instantiate.mjs +33 -23
- package/build/type/engine/evaluate/broaden.d.mts +1 -1
- package/build/type/engine/evaluate/broaden.mjs +7 -8
- package/build/type/script/token/bigint.d.mts +1 -1
- package/build/type/script/token/bigint.mjs +3 -9
- package/build/type/script/token/ident.mjs +4 -13
- package/build/type/script/token/index.d.mts +3 -0
- package/build/type/script/token/index.mjs +3 -0
- package/build/type/script/token/integer.d.mts +5 -13
- package/build/type/script/token/integer.mjs +7 -33
- package/build/type/script/token/internal/many.mjs +4 -7
- package/build/type/script/token/internal/match.d.mts +6 -0
- package/build/type/script/token/internal/match.mjs +11 -0
- package/build/type/script/token/internal/optional.mjs +2 -5
- package/build/type/script/token/internal/take.mjs +23 -8
- package/build/type/script/token/number.d.mts +5 -14
- package/build/type/script/token/number.mjs +7 -53
- package/build/type/script/token/rest.d.mts +4 -0
- package/build/type/script/token/rest.mjs +9 -0
- package/build/type/script/token/span.d.mts +3 -2
- package/build/type/script/token/span.mjs +8 -19
- package/build/type/script/token/string.mjs +2 -6
- package/build/type/script/token/unsigned_integer.d.mts +16 -0
- package/build/type/script/token/unsigned_integer.mjs +26 -0
- package/build/type/script/token/unsigned_number.d.mts +17 -0
- package/build/type/script/token/unsigned_number.mjs +38 -0
- package/build/type/script/token/until.d.mts +3 -2
- package/build/type/script/token/until.mjs +11 -8
- package/build/type/script/token/until_1.mjs +4 -8
- package/package.json +29 -29
- package/readme.md +18 -50
- package/build/type/script/token/internal/result.d.mts +0 -2
- package/build/type/script/token/internal/result.mjs +0 -7
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type TSchema } from '../../types/schema.mjs';
|
|
2
|
+
import { type TUnion } from '../../types/union.mjs';
|
|
3
|
+
import { type TDeferred } from '../../types/deferred.mjs';
|
|
4
|
+
type TExpand<Type extends TSchema> = (Type extends TUnion<infer Types extends TSchema[]> ? [...Types] : [Type]);
|
|
5
|
+
type TAppend<Current extends TSchema[][], Type extends TSchema, Result extends TSchema[][] = []> = (Current extends [infer Left extends TSchema[], ...infer Right extends TSchema[][]] ? TAppend<Right, Type, [...Result, [...Left, Type]]> : Result);
|
|
6
|
+
type TCross<Current extends TSchema[][], Variants extends TSchema[], Result extends TSchema[][] = []> = (Variants extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TCross<Current, Right, [...Result, ...TAppend<Current, Left>]> : Result);
|
|
7
|
+
type TDistribute<Types extends TSchema[], Result extends TSchema[][] = [[]]> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TDistribute<Right, TCross<Result, TExpand<Left>>> : Result);
|
|
8
|
+
export type TDistributeArguments<Arguments extends TSchema[], Expression extends TSchema, Result extends TSchema[][] = Expression extends TDeferred<'Conditional', TSchema[]> ? TDistribute<Arguments> : [Arguments]> = Result;
|
|
9
|
+
export declare function DistributedArguments<Arguments extends TSchema[], Expression extends TSchema>(arguments_: [...Arguments], expression: Expression): TDistributeArguments<Arguments, Expression>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// deno-fmt-ignore-file
|
|
2
|
+
import { Guard } from '../../../guard/index.mjs';
|
|
3
|
+
import { IsUnion } from '../../types/union.mjs';
|
|
4
|
+
import { IsDeferred } from '../../types/deferred.mjs';
|
|
5
|
+
function Expand(type) {
|
|
6
|
+
return (IsUnion(type)
|
|
7
|
+
? [...type.anyOf]
|
|
8
|
+
: [type]);
|
|
9
|
+
}
|
|
10
|
+
function Append(current, type) {
|
|
11
|
+
return current.reduce((result, left) => [...result, [...left, type]], []);
|
|
12
|
+
}
|
|
13
|
+
function Cross(current, variants) {
|
|
14
|
+
return variants.reduce((result, left) => {
|
|
15
|
+
return [...result, ...Append(current, left)];
|
|
16
|
+
}, []);
|
|
17
|
+
}
|
|
18
|
+
function Distribute(types) {
|
|
19
|
+
return types.reduce((result, type) => {
|
|
20
|
+
return Cross(result, Expand(type));
|
|
21
|
+
}, [[]]);
|
|
22
|
+
}
|
|
23
|
+
export function DistributedArguments(arguments_, expression) {
|
|
24
|
+
return (IsDeferred(expression) && Guard.IsEqual(expression.action, 'Conditional')
|
|
25
|
+
? Distribute(arguments_)
|
|
26
|
+
: [arguments_]);
|
|
27
|
+
}
|
|
@@ -4,17 +4,20 @@ import { type TCallConstruct } from '../../types/call.mjs';
|
|
|
4
4
|
import { type TRef } from '../../types/ref.mjs';
|
|
5
5
|
import { type TGeneric } from '../../types/generic.mjs';
|
|
6
6
|
import { type TProperties } from '../../types/properties.mjs';
|
|
7
|
+
import { type TEvaluateUnion } from '../evaluate/index.mjs';
|
|
7
8
|
import { type TState } from '../instantiate.mjs';
|
|
8
9
|
import { type TInstantiateType } from '../instantiate.mjs';
|
|
9
10
|
import { type TInstantiateTypes } from '../instantiate.mjs';
|
|
11
|
+
import { type TDistributeArguments } from './distribute-arguments.mjs';
|
|
10
12
|
import { type TResolveTarget } from './resolve-target.mjs';
|
|
11
13
|
import { type TResolveArgumentsContext } from './resolve-arguments.mjs';
|
|
12
|
-
type TPeek<
|
|
13
|
-
type
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
callstack: [...State['callstack'], Name];
|
|
14
|
+
type TPeek<State extends TState, Result extends string = State['callstack'] extends [...infer _ extends string[], infer Top extends string] ? Top : ''> = Result;
|
|
15
|
+
type TIsTailCall<State extends TState, Name extends string, Result extends boolean = TPeek<State> extends Name ? true : false> = Result;
|
|
16
|
+
type TCallDispatch<Context extends TProperties, State extends TState, Target extends TRef, Parameters extends TParameter[], Expression extends TSchema, Arguments extends TSchema[], ArgumentsContext extends TProperties = TResolveArgumentsContext<Context, State, Parameters, Arguments>, ReturnType extends TSchema = TInstantiateType<ArgumentsContext, {
|
|
17
|
+
callstack: [...State['callstack'], Target['$ref']];
|
|
17
18
|
}, Expression>> = TInstantiateType<Context, State, ReturnType>;
|
|
18
|
-
|
|
19
|
+
type TCallDistributed<Context extends TProperties, State extends TState, Target extends TRef, Parameters extends TParameter[], Expression extends TSchema, DistributedArguments extends TSchema[][], Result extends TSchema[] = []> = (DistributedArguments extends [infer Arguments extends TSchema[], ...infer DistributedArguments extends TSchema[][]] ? TCallDispatch<Context, State, Target, Parameters, Expression, Arguments> extends infer ReturnType extends TSchema ? TCallDistributed<Context, State, Target, Parameters, Expression, DistributedArguments, [...Result, ReturnType]> : never : Result);
|
|
20
|
+
type TCallImmediate<Context extends TProperties, State extends TState, Target extends TRef, Parameters extends TParameter[], Expression extends TSchema, InstantiatedArguments extends TSchema[], DistributedArguments extends TSchema[][] = TDistributeArguments<InstantiatedArguments, Expression>, ReturnTypes extends TSchema[] = TCallDistributed<Context, State, Target, Parameters, Expression, DistributedArguments>, Result extends TSchema = ReturnTypes['length'] extends 1 ? ReturnTypes[0] : TEvaluateUnion<ReturnTypes>> = Result;
|
|
21
|
+
export type TCallInstantiate<Context extends TProperties, State extends TState, Target extends TSchema, Arguments extends TSchema[], InstantiatedArguments extends TSchema[] = TInstantiateTypes<Context, State, Arguments>, Resolved extends [string, TSchema] = TResolveTarget<Context, Target, Arguments>, Name extends string = Resolved[0], Type extends TSchema = Resolved[1], Result extends TSchema = (Type extends TGeneric<infer Parameters extends TParameter[], infer Expression extends TSchema> ? TIsTailCall<State, Name> extends true ? TCallConstruct<TRef<Name>, InstantiatedArguments> : TCallImmediate<Context, State, TRef<Name>, Parameters, Expression, InstantiatedArguments> : TCallConstruct<Target, InstantiatedArguments>)> = Result;
|
|
19
22
|
export declare function CallInstantiate<Context extends TProperties, State extends TState, Target extends TSchema, Arguments extends TSchema[]>(context: Context, state: State, target: Target, arguments_: [...Arguments]): TCallInstantiate<Context, State, Target, Arguments>;
|
|
20
23
|
export {};
|
|
@@ -3,36 +3,46 @@ import { Guard } from '../../../guard/index.mjs';
|
|
|
3
3
|
import { CallConstruct } from '../../types/call.mjs';
|
|
4
4
|
import { Ref } from '../../types/ref.mjs';
|
|
5
5
|
import { IsGeneric } from '../../types/generic.mjs';
|
|
6
|
+
import { EvaluateUnion } from '../evaluate/index.mjs';
|
|
6
7
|
import { InstantiateType } from '../instantiate.mjs';
|
|
7
8
|
import { InstantiateTypes } from '../instantiate.mjs';
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
9
|
+
// ------------------------------------------------------------------
|
|
10
|
+
// Infrastructure
|
|
11
|
+
// ------------------------------------------------------------------
|
|
12
|
+
import { DistributedArguments } from './distribute-arguments.mjs';
|
|
11
13
|
import { ResolveTarget } from './resolve-target.mjs';
|
|
12
14
|
import { ResolveArgumentsContext } from './resolve-arguments.mjs';
|
|
13
|
-
function Peek(
|
|
14
|
-
|
|
15
|
+
function Peek(state) {
|
|
16
|
+
const result = Guard.IsGreaterThan(state.callstack.length, 0) ? state.callstack[state.callstack.length - 1] : '';
|
|
17
|
+
return result;
|
|
15
18
|
}
|
|
16
|
-
function
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
return deferredCall;
|
|
20
|
-
}
|
|
21
|
-
function TailCall(context, state, name, arguments_) {
|
|
22
|
-
const deferredCall = DeferredCall(context, state, Ref(name), arguments_);
|
|
23
|
-
return deferredCall;
|
|
19
|
+
function IsTailCall(state, name) {
|
|
20
|
+
const result = Guard.IsEqual(Peek(state), name);
|
|
21
|
+
return result;
|
|
24
22
|
}
|
|
25
|
-
function
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const returnType = InstantiateType(argumentsContext, { callstack: [...state.callstack, name] }, expression);
|
|
23
|
+
function CallDispatch(context, state, target, parameters, expression, arguments_) {
|
|
24
|
+
const argumentsContext = ResolveArgumentsContext(context, state, parameters, arguments_);
|
|
25
|
+
const returnType = InstantiateType(argumentsContext, { callstack: [...state.callstack, target.$ref] }, expression);
|
|
29
26
|
return InstantiateType(context, state, returnType);
|
|
30
27
|
}
|
|
28
|
+
function CallDistributed(context, state, target, parameters, expression, distributedArguments) {
|
|
29
|
+
return distributedArguments.reduce((result, arguments_) => [...result, CallDispatch(context, state, target, parameters, expression, arguments_)], []);
|
|
30
|
+
}
|
|
31
|
+
function CallImmediate(context, state, target, parameters, expression, arguments_) {
|
|
32
|
+
const distributedArguments = DistributedArguments(arguments_, expression);
|
|
33
|
+
const returnTypes = CallDistributed(context, state, target, parameters, expression, distributedArguments);
|
|
34
|
+
const result = returnTypes.length === 1 ? returnTypes[0] : EvaluateUnion(returnTypes);
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
31
37
|
export function CallInstantiate(context, state, target, arguments_) {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
const instantiatedArguments = InstantiateTypes(context, state, arguments_);
|
|
39
|
+
const resolved = ResolveTarget(context, target, arguments_);
|
|
40
|
+
const name = resolved[0];
|
|
41
|
+
const type = resolved[1];
|
|
42
|
+
const result = (IsGeneric(type)
|
|
43
|
+
? IsTailCall(state, name)
|
|
44
|
+
? CallConstruct(Ref(name), instantiatedArguments)
|
|
45
|
+
: CallImmediate(context, state, Ref(name), type.parameters, type.expression, instantiatedArguments)
|
|
46
|
+
: CallConstruct(target, instantiatedArguments));
|
|
47
|
+
return result;
|
|
38
48
|
}
|
|
@@ -9,7 +9,7 @@ import { type TEvaluateType } from './evaluate.mjs';
|
|
|
9
9
|
type TBroadFilter<Type extends TSchema, Types extends TSchema[], Result extends TSchema[] = []> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TCompare<Type, Left> extends typeof ResultRightInside ? TBroadFilter<Type, Right, [...Result]> : TBroadFilter<Type, Right, [...Result, Left]> : Result);
|
|
10
10
|
type TIsBroadestType<Type extends TSchema, Types extends TSchema[]> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TCompare<Type, Left> extends typeof ResultLeftInside | typeof ResultEqual ? false : TIsBroadestType<Type, Right> : true);
|
|
11
11
|
type TBroadenType<Type extends TSchema, Types extends TSchema[], Evaluated extends TSchema = TEvaluateType<Type>, Result extends TSchema[] = (Evaluated extends TAny ? [Evaluated] : TIsBroadestType<Evaluated, Types> extends true ? [...TBroadFilter<Evaluated, Types>, Evaluated] : Types)> = Result;
|
|
12
|
-
type TBroadenTypes<Types extends TSchema[], Result extends TSchema[] = []> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TObject ? TBroadenTypes<Right, [...Result, Left]> : TBroadenTypes<Right, TBroadenType<Left, Result>> : Result);
|
|
12
|
+
type TBroadenTypes<Types extends TSchema[], Result extends TSchema[] = []> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? (Left extends TObject ? TBroadenTypes<Right, [...Result, Left]> : Left extends TNever ? TBroadenTypes<Right, Result> : TBroadenTypes<Right, TBroadenType<Left, Result>>) : Result);
|
|
13
13
|
export type TBroaden<Types extends TSchema[], Broadened extends TSchema[] = TBroadenTypes<Types>, Flattened extends TSchema[] = TFlatten<Broadened>, Result extends TSchema = (Flattened extends [] ? TNever : Flattened extends [infer Type extends TSchema] ? Type : TUnion<Flattened>)> = Result;
|
|
14
14
|
/** Broadens a set of types and returns either the most broad type, or union or disjoint types. */
|
|
15
15
|
export declare function Broaden<Types extends TSchema[]>(types: [...Types]): TBroaden<Types>;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
2
|
import { Guard } from '../../../guard/index.mjs';
|
|
3
|
-
import { IsSchema } from '../../types/schema.mjs';
|
|
4
3
|
import { IsAny } from '../../types/any.mjs';
|
|
5
|
-
import { Never } from '../../types/never.mjs';
|
|
4
|
+
import { Never, IsNever } from '../../types/never.mjs';
|
|
6
5
|
import { IsObject } from '../../types/object.mjs';
|
|
7
6
|
import { Union } from '../../types/union.mjs';
|
|
8
7
|
import { Compare, ResultRightInside, ResultLeftInside, ResultEqual } from './compare.mjs';
|
|
@@ -30,12 +29,12 @@ function BroadenType(type, types) {
|
|
|
30
29
|
: types);
|
|
31
30
|
}
|
|
32
31
|
function BroadenTypes(types, result = []) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
return types.reduce((result, left) => {
|
|
33
|
+
return (IsObject(left) ? [...result, left] : // push
|
|
34
|
+
IsNever(left) ? result : // ignore
|
|
35
|
+
BroadenType(left, result) // broaden
|
|
36
|
+
);
|
|
37
|
+
}, []);
|
|
39
38
|
}
|
|
40
39
|
/** Broadens a set of types and returns either the most broad type, or union or disjoint types. */
|
|
41
40
|
export function Broaden(types) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type TTake } from './internal/take.mjs';
|
|
2
2
|
import { type TInteger } from './integer.mjs';
|
|
3
|
-
type TTakeBigInt<Input extends string> = (TInteger<Input> extends [infer Integer extends string, infer IntegerRest extends string] ? TTake<['n'], IntegerRest> extends [infer
|
|
3
|
+
type TTakeBigInt<Input extends string> = (TInteger<Input> extends [infer Integer extends string, infer IntegerRest extends string] ? TTake<['n'], IntegerRest> extends [infer _N extends string, infer NRest extends string] ? [`${Integer}`, NRest] : [] : []);
|
|
4
4
|
/** Matches if next is a Integer literal with trailing 'n'. Trailing 'n' is omitted in result. */
|
|
5
5
|
export type TBigInt<Input extends string> = (TTakeBigInt<Input>);
|
|
6
6
|
/** Matches if next is a Integer literal with trailing 'n'. Trailing 'n' is omitted in result. */
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
4
4
|
import { Take } from './internal/take.mjs';
|
|
5
5
|
import { Integer } from './integer.mjs';
|
|
6
6
|
function TakeBigInt(input) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const n = Take(['n'], integer[1]);
|
|
10
|
-
return IsResult(n)
|
|
11
|
-
? [`${integer[0]}`, n[1]]
|
|
12
|
-
: []; // fail: did not match 'n'
|
|
13
|
-
})() : [] // fail: did not match Integer
|
|
14
|
-
);
|
|
7
|
+
return Match(Integer(input), (Integer, IntegerRest) => Match(Take(['n'], IntegerRest), (_N, NRest) => [`${Integer}`, NRest], () => []), // fail: did not match 'n'
|
|
8
|
+
() => []); // fail: did not match Integer
|
|
15
9
|
}
|
|
16
10
|
/** Matches if next is a Integer literal with trailing 'n'. Trailing 'n' is omitted in result. */
|
|
17
11
|
export function BigInt(input) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
4
4
|
import { Trim } from './internal/trim.mjs';
|
|
5
5
|
import { Take } from './internal/take.mjs';
|
|
6
6
|
import { Alpha } from './internal/char.mjs';
|
|
@@ -13,20 +13,11 @@ function TakeInitial(input) {
|
|
|
13
13
|
}
|
|
14
14
|
const Remaining = [...Initial, ...Digit];
|
|
15
15
|
function TakeRemaining(input, result = '') {
|
|
16
|
-
|
|
17
|
-
return (IsResult(remaining)
|
|
18
|
-
? TakeRemaining(remaining[1], `${result}${remaining[0]}`)
|
|
19
|
-
: [result, input]);
|
|
16
|
+
return Match(Take(Remaining, input), (Remaining, RemainingRest) => TakeRemaining(RemainingRest, `${result}${Remaining}`), () => [result, input]);
|
|
20
17
|
}
|
|
21
18
|
function TakeIdent(input) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const remaining = TakeRemaining(initial[1]);
|
|
25
|
-
return IsResult(remaining)
|
|
26
|
-
? [`${initial[0]}${remaining[0]}`, remaining[1]]
|
|
27
|
-
: []; // fail: did not match Remaining
|
|
28
|
-
})() : [] // fail: did not match Initial
|
|
29
|
-
);
|
|
19
|
+
return Match(TakeInitial(input), (Initial, InitialRest) => Match(TakeRemaining(InitialRest), (Remaining, RemainingRest) => [`${Initial}${Remaining}`, RemainingRest], () => []), // fail: did not match Remaining
|
|
20
|
+
() => []); // fail: did not match Initial
|
|
30
21
|
}
|
|
31
22
|
/** Matches if next is an Ident */
|
|
32
23
|
export function Ident(input) {
|
|
@@ -3,7 +3,10 @@ export * from './const.mjs';
|
|
|
3
3
|
export * from './ident.mjs';
|
|
4
4
|
export * from './integer.mjs';
|
|
5
5
|
export * from './number.mjs';
|
|
6
|
+
export * from './rest.mjs';
|
|
6
7
|
export * from './span.mjs';
|
|
7
8
|
export * from './string.mjs';
|
|
9
|
+
export * from './unsigned_integer.mjs';
|
|
10
|
+
export * from './unsigned_number.mjs';
|
|
8
11
|
export * from './until_1.mjs';
|
|
9
12
|
export * from './until.mjs';
|
|
@@ -3,7 +3,10 @@ export * from './const.mjs';
|
|
|
3
3
|
export * from './ident.mjs';
|
|
4
4
|
export * from './integer.mjs';
|
|
5
5
|
export * from './number.mjs';
|
|
6
|
+
export * from './rest.mjs';
|
|
6
7
|
export * from './span.mjs';
|
|
7
8
|
export * from './string.mjs';
|
|
9
|
+
export * from './unsigned_integer.mjs';
|
|
10
|
+
export * from './unsigned_number.mjs';
|
|
8
11
|
export * from './until_1.mjs';
|
|
9
12
|
export * from './until.mjs';
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import { type TTrim } from './internal/trim.mjs';
|
|
2
|
-
import { type TTake } from './internal/take.mjs';
|
|
3
|
-
import { type TMany } from './internal/many.mjs';
|
|
4
2
|
import { type TOptional } from './internal/optional.mjs';
|
|
5
|
-
import { type TDigit } from './internal/char.mjs';
|
|
6
3
|
import { type THyphen } from './internal/char.mjs';
|
|
7
|
-
import { type
|
|
8
|
-
import { type TNonZero } from './internal/char.mjs';
|
|
9
|
-
import { type TUnderScore } from './internal/char.mjs';
|
|
4
|
+
import { type TUnsignedInteger } from './unsigned_integer.mjs';
|
|
10
5
|
type TTakeSign<Input extends string> = (TOptional<THyphen, Input>);
|
|
11
|
-
type
|
|
12
|
-
|
|
13
|
-
type
|
|
14
|
-
|
|
15
|
-
/** Matches if next is a Integer */
|
|
16
|
-
export type TInteger<Input extends string> = (TTakeInteger<TTrim<Input>>);
|
|
17
|
-
/** Matches if next is a Integer */
|
|
6
|
+
type TTakeSignedInteger<Input extends string> = (TTakeSign<Input> extends [infer Sign extends string, infer SignRest extends string] ? TUnsignedInteger<SignRest> extends [infer UnsignedInteger extends string, infer UnsignedIntegerRest extends string] ? [`${Sign}${UnsignedInteger}`, UnsignedIntegerRest] : [] : []);
|
|
7
|
+
/** Matches if next is a signed or unsigned Integer */
|
|
8
|
+
export type TInteger<Input extends string> = (TTakeSignedInteger<TTrim<Input>>);
|
|
9
|
+
/** Matches if next is a signed or unsigned Integer */
|
|
18
10
|
export declare function Integer<Input extends string>(input: Input): TInteger<Input>;
|
|
19
11
|
export {};
|
|
@@ -1,45 +1,19 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
4
4
|
import { Trim } from './internal/trim.mjs';
|
|
5
|
-
import { Take } from './internal/take.mjs';
|
|
6
|
-
import { Many } from './internal/many.mjs';
|
|
7
5
|
import { Optional } from './internal/optional.mjs';
|
|
8
|
-
import { Digit } from './internal/char.mjs';
|
|
9
6
|
import { Hyphen } from './internal/char.mjs';
|
|
10
|
-
import {
|
|
11
|
-
import { NonZero } from './internal/char.mjs';
|
|
12
|
-
import { UnderScore } from './internal/char.mjs';
|
|
7
|
+
import { UnsignedInteger } from './unsigned_integer.mjs';
|
|
13
8
|
function TakeSign(input) {
|
|
14
9
|
return Optional(Hyphen, input);
|
|
15
10
|
}
|
|
16
|
-
function
|
|
17
|
-
return
|
|
11
|
+
function TakeSignedInteger(input) {
|
|
12
|
+
return Match(TakeSign(input), (Sign, SignRest) => Match(UnsignedInteger(SignRest), (UnsignedInteger, UnsignedIntegerRest) => [`${Sign}${UnsignedInteger}`, UnsignedIntegerRest], () => []), // fail: did not match unsigned integer
|
|
13
|
+
() => []); // fail: did not match Sign
|
|
18
14
|
}
|
|
19
|
-
|
|
20
|
-
function TakeDigits(input) {
|
|
21
|
-
return Many(AllowedDigits, [UnderScore], input);
|
|
22
|
-
}
|
|
23
|
-
function TakeInteger(input) {
|
|
24
|
-
const sign = TakeSign(input);
|
|
25
|
-
return (IsResult(sign) ? (() => {
|
|
26
|
-
const zero = Take([Zero], sign[1]);
|
|
27
|
-
return IsResult(zero)
|
|
28
|
-
? [`${sign[0]}${zero[0]}`, zero[1]]
|
|
29
|
-
: (() => {
|
|
30
|
-
const nonZero = TakeNonZero(sign[1]);
|
|
31
|
-
return IsResult(nonZero) ? (() => {
|
|
32
|
-
const digits = TakeDigits(nonZero[1]);
|
|
33
|
-
return IsResult(digits)
|
|
34
|
-
? [`${sign[0]}${nonZero[0]}${digits[0]}`, digits[1]]
|
|
35
|
-
: []; // fail: did not match Digits
|
|
36
|
-
})() : []; // fail: did not match NonZero
|
|
37
|
-
})();
|
|
38
|
-
})() : [] // fail: did not match Sign
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
/** Matches if next is a Integer */
|
|
15
|
+
/** Matches if next is a signed or unsigned Integer */
|
|
42
16
|
export function Integer(input) {
|
|
43
|
-
return
|
|
17
|
+
return TakeSignedInteger(Trim(input));
|
|
44
18
|
}
|
|
45
19
|
// deno-coverage-ignore-stop
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { Match } from './match.mjs';
|
|
4
4
|
import { Take } from './take.mjs';
|
|
5
5
|
function IsDiscard(discard, input) {
|
|
6
6
|
return discard.includes(input);
|
|
7
7
|
}
|
|
8
8
|
/** Takes characters from the Input until no-match. The Discard set is used to omit characters from the match */
|
|
9
9
|
export function Many(allowed, discard, input, result = '') {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
? Many(allowed, discard, takeResult[1], result)
|
|
14
|
-
: Many(allowed, discard, takeResult[1], `${result}${takeResult[0]}`)
|
|
15
|
-
: [result, input]);
|
|
10
|
+
return Match(Take(allowed, input), (Char, Rest) => IsDiscard(discard, Char)
|
|
11
|
+
? Many(allowed, discard, Rest, result)
|
|
12
|
+
: Many(allowed, discard, Rest, `${result}${Char}`), () => [result, input]);
|
|
16
13
|
}
|
|
17
14
|
// deno-coverage-ignore-stop
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type TResult = [string, string] | [];
|
|
2
|
+
/** Checks the value is a Tuple-2 [string, string] result */
|
|
3
|
+
export declare function IsMatch(value: TResult): value is [string, string];
|
|
4
|
+
/** Matches on a result and dispatches either left or right arm */
|
|
5
|
+
export declare function Match(input: TResult, ok: (value: string, rest: string) => TResult, fail: () => TResult): TResult;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// deno-coverage-ignore-start - parsebox tested
|
|
2
|
+
import { IsEqual } from './guard.mjs';
|
|
3
|
+
/** Checks the value is a Tuple-2 [string, string] result */
|
|
4
|
+
export function IsMatch(value) {
|
|
5
|
+
return IsEqual(value.length, 2);
|
|
6
|
+
}
|
|
7
|
+
/** Matches on a result and dispatches either left or right arm */
|
|
8
|
+
export function Match(input, ok, fail) {
|
|
9
|
+
return IsMatch(input) ? ok(input[0], input[1]) : fail();
|
|
10
|
+
}
|
|
11
|
+
// deno-coverage-ignore-stop
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { Match } from './match.mjs';
|
|
4
4
|
import { Take } from './take.mjs';
|
|
5
5
|
/** Matches the given Value or empty string if no match. This function never fails */
|
|
6
6
|
export function Optional(value, input) {
|
|
7
|
-
|
|
8
|
-
return (IsResult(result)
|
|
9
|
-
? result
|
|
10
|
-
: ['', input]);
|
|
7
|
+
return Match(Take([value], input), (Optional, Rest) => [Optional, Rest], () => ['', input]);
|
|
11
8
|
}
|
|
12
9
|
// deno-coverage-ignore-stop
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { IsMatch } from './match.mjs';
|
|
4
|
+
import { IsEqual } from './guard.mjs';
|
|
4
5
|
function TakeVariant(variant, input) {
|
|
5
6
|
return (IsEqual(input.indexOf(variant), 0)
|
|
6
7
|
? [variant, input.slice(variant.length)]
|
|
@@ -8,12 +9,26 @@ function TakeVariant(variant, input) {
|
|
|
8
9
|
}
|
|
9
10
|
/** Takes one of the given variants or fail */
|
|
10
11
|
export function Take(variants, input) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
// ----------------------------------------------------------------
|
|
13
|
+
// Symmetric
|
|
14
|
+
// ----------------------------------------------------------------
|
|
15
|
+
// const [left, ...right] = variants
|
|
16
|
+
// return (
|
|
17
|
+
// IsString(left)
|
|
18
|
+
// ? (() => {
|
|
19
|
+
// const result = TakeVariant(left, input)
|
|
20
|
+
// return IsEqual(result.length, 2) ? result : Take(right, input)
|
|
21
|
+
// })()
|
|
22
|
+
// : []
|
|
23
|
+
// ) as never
|
|
24
|
+
// ----------------------------------------------------------------
|
|
25
|
+
// Inline
|
|
26
|
+
// ----------------------------------------------------------------
|
|
27
|
+
for (let i = 0; i < variants.length; i++) {
|
|
28
|
+
const result = TakeVariant(variants[i], input);
|
|
29
|
+
if (IsMatch(result))
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
return [];
|
|
18
33
|
}
|
|
19
34
|
// deno-coverage-ignore-stop
|
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
import { type TTrim } from './internal/trim.mjs';
|
|
2
|
-
import { type TTake } from './internal/take.mjs';
|
|
3
|
-
import { type TMany } from './internal/many.mjs';
|
|
4
2
|
import { type TOptional } from './internal/optional.mjs';
|
|
5
|
-
import { type TDigit, TUnderScore } from './internal/char.mjs';
|
|
6
|
-
import { type TDot } from './internal/char.mjs';
|
|
7
3
|
import { type THyphen } from './internal/char.mjs';
|
|
8
|
-
import { type
|
|
9
|
-
type TAllowedDigits = [...TDigit, TUnderScore];
|
|
4
|
+
import { type TUnsignedNumber } from './unsigned_number.mjs';
|
|
10
5
|
type TTakeSign<Input extends string> = (TOptional<THyphen, Input>);
|
|
11
|
-
type
|
|
12
|
-
|
|
13
|
-
type
|
|
14
|
-
|
|
15
|
-
type TTakeNumber<Input extends string> = (TTakeSign<Input> extends [infer Sign extends string, infer SignRest extends string] ? TIsLeadingDot<SignRest> extends true ? TLeadingDot<Sign, SignRest> : TLeadingInteger<Sign, SignRest> : []);
|
|
16
|
-
/** Matches if next is a literal Number */
|
|
17
|
-
export type TNumber<Input extends string> = (TTakeNumber<TTrim<Input>>);
|
|
18
|
-
/** Matches if next is a literal Number */
|
|
6
|
+
type TTakeSignedNumber<Input extends string> = (TTakeSign<Input> extends [infer Sign extends string, infer SignRest extends string] ? TUnsignedNumber<SignRest> extends [infer UnsignedInteger extends string, infer UnsignedIntegerRest extends string] ? [`${Sign}${UnsignedInteger}`, UnsignedIntegerRest] : [] : []);
|
|
7
|
+
/** Matches if next is a signed or unsigned Number */
|
|
8
|
+
export type TNumber<Input extends string> = (TTakeSignedNumber<TTrim<Input>>);
|
|
9
|
+
/** Matches if next is a signed or unsigned Number */
|
|
19
10
|
export declare function Number<Input extends string>(input: Input): TNumber<Input>;
|
|
20
11
|
export {};
|
|
@@ -1,65 +1,19 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
4
|
-
import { IsResult } from './internal/result.mjs';
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
5
4
|
import { Trim } from './internal/trim.mjs';
|
|
6
|
-
import { Take } from './internal/take.mjs';
|
|
7
|
-
import { Many } from './internal/many.mjs';
|
|
8
5
|
import { Optional } from './internal/optional.mjs';
|
|
9
|
-
import { Digit, UnderScore } from './internal/char.mjs';
|
|
10
|
-
import { Dot } from './internal/char.mjs';
|
|
11
6
|
import { Hyphen } from './internal/char.mjs';
|
|
12
|
-
import {
|
|
13
|
-
const AllowedDigits = [...Digit, UnderScore];
|
|
7
|
+
import { UnsignedNumber } from './unsigned_number.mjs';
|
|
14
8
|
function TakeSign(input) {
|
|
15
9
|
return Optional(Hyphen, input);
|
|
16
10
|
}
|
|
17
|
-
function
|
|
18
|
-
return
|
|
11
|
+
function TakeSignedNumber(input) {
|
|
12
|
+
return Match(TakeSign(input), (Sign, SignRest) => Match(UnsignedNumber(SignRest), (UnsignedInteger, UnsignedIntegerRest) => [`${Sign}${UnsignedInteger}`, UnsignedIntegerRest], () => []), // fail: did not match unsigned integer
|
|
13
|
+
() => []); // fail: did not match Sign
|
|
19
14
|
}
|
|
20
|
-
|
|
21
|
-
const digits = Many(AllowedDigits, [UnderScore], input);
|
|
22
|
-
return (IsResult(digits)
|
|
23
|
-
? IsEqual(digits[0], '')
|
|
24
|
-
? [] // fail: no Digits
|
|
25
|
-
: [digits[0], digits[1]]
|
|
26
|
-
: [] // fail: did not match Digits
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
function LeadingDot(sign, input) {
|
|
30
|
-
const dot = Take([Dot], input);
|
|
31
|
-
return (IsResult(dot) ? (() => {
|
|
32
|
-
const fractional = TakeFractional(dot[1]);
|
|
33
|
-
return IsResult(fractional)
|
|
34
|
-
? [`${sign}0${dot[0]}${fractional[0]}`, fractional[1]]
|
|
35
|
-
: []; // fail: did not match Fractional
|
|
36
|
-
})() : [] // fail: did not match Dot
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
function LeadingInteger(sign, input) {
|
|
40
|
-
const integer = Integer(input);
|
|
41
|
-
return (IsResult(integer) ? (() => {
|
|
42
|
-
const dot = Take([Dot], integer[1]);
|
|
43
|
-
return IsResult(dot) ? (() => {
|
|
44
|
-
const fractional = TakeFractional(dot[1]);
|
|
45
|
-
return IsResult(fractional)
|
|
46
|
-
? [`${sign}${integer[0]}${dot[0]}${fractional[0]}`, fractional[1]]
|
|
47
|
-
: [`${sign}${integer[0]}`, dot[1]]; // fail: did not match Fractional, use Integer
|
|
48
|
-
})() : [`${sign}${integer[0]}`, integer[1]]; // fail: did not match Dot, use Integer
|
|
49
|
-
})() : [] // fail: did not match Integer
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
function TakeNumber(input) {
|
|
53
|
-
const sign = TakeSign(input);
|
|
54
|
-
return (IsResult(sign)
|
|
55
|
-
? IsLeadingDot(sign[1])
|
|
56
|
-
? LeadingDot(sign[0], sign[1])
|
|
57
|
-
: LeadingInteger(sign[0], sign[1])
|
|
58
|
-
: [] // fail: did not match Sign
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
/** Matches if next is a literal Number */
|
|
15
|
+
/** Matches if next is a signed or unsigned Number */
|
|
62
16
|
export function Number(input) {
|
|
63
|
-
return
|
|
17
|
+
return TakeSignedNumber(Trim(input));
|
|
64
18
|
}
|
|
65
19
|
// deno-coverage-ignore-stop
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Match remaining characters in the buffer until end. If no characters are in buffer, no match */
|
|
2
|
+
export type TRest<Input extends string> = (Input extends '' ? [] : [Input, '']);
|
|
3
|
+
/** Match remaining characters in the buffer until end. If no characters are in buffer, no match */
|
|
4
|
+
export declare function Rest<Input extends string>(input: Input): TRest<Input>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// deno-coverage-ignore-start - parsebox tested
|
|
2
|
+
// deno-fmt-ignore-file
|
|
3
|
+
import { IsEqual } from './internal/guard.mjs';
|
|
4
|
+
/** Match remaining characters in the buffer until end. If no characters are in buffer, no match */
|
|
5
|
+
export function Rest(input) {
|
|
6
|
+
const result = IsEqual(input, '') ? [] : [input, ''];
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
// deno-coverage-ignore-stop
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type TTrim } from './internal/trim.mjs';
|
|
2
2
|
import { type TNewLine } from './internal/char.mjs';
|
|
3
|
+
import { type TTake } from './internal/take.mjs';
|
|
3
4
|
import { type TUntil } from './until.mjs';
|
|
4
|
-
type TMultiLine<Start extends string, End extends string, Input extends string> = (Input extends
|
|
5
|
-
type TSingleLine<Start extends string, End extends string, Input extends string> = (Input extends
|
|
5
|
+
type TMultiLine<Start extends string, End extends string, Input extends string> = (TTake<[Start], Input> extends [infer _, infer Rest extends string] ? TUntil<[End], Rest> extends [infer Until extends string, infer UntilRest extends string] ? TTake<[End], UntilRest> extends [infer _ extends string, infer Rest extends string] ? [`${Until}`, Rest] : [] : [] : []);
|
|
6
|
+
type TSingleLine<Start extends string, End extends string, Input extends string> = (TTake<[Start], Input> extends [infer _ extends string, infer Rest extends string] ? TUntil<[TNewLine, End], Rest> extends [infer Until extends string, infer UntilRest extends string] ? TTake<[End], UntilRest> extends [infer _ extends string, infer EndRest extends string] ? [`${Until}`, EndRest] : [] : [] : []);
|
|
6
7
|
/** Matches from Start and End capturing everything in-between. Start and End are consumed. */
|
|
7
8
|
export type TSpan<Start extends string, End extends string, MultiLine extends boolean, Input extends string> = (MultiLine extends true ? TMultiLine<Start, End, TTrim<Input>> : TSingleLine<Start, End, TTrim<Input>>);
|
|
8
9
|
/** Matches from Start and End capturing everything in-between. Start and End are consumed. */
|
|
@@ -1,30 +1,19 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
4
4
|
import { Trim } from './internal/trim.mjs';
|
|
5
5
|
import { NewLine } from './internal/char.mjs';
|
|
6
|
+
import { Take } from './internal/take.mjs';
|
|
6
7
|
import { Until } from './until.mjs';
|
|
7
8
|
function MultiLine(start, end, input) {
|
|
8
|
-
return (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return until[1].startsWith(end)
|
|
12
|
-
? [`${until[0]}`, until[1].slice(end.length)]
|
|
13
|
-
: []; // fail: did not match End
|
|
14
|
-
})() : []; // fail: did not match Until
|
|
15
|
-
})() : [] // fail: did not match Start
|
|
16
|
-
);
|
|
9
|
+
return Match(Take([start], input), (_, Rest) => Match(Until([end], Rest), (Until, UntilRest) => Match(Take([end], UntilRest), (_, Rest) => [`${Until}`, Rest], () => []), // fail: did not match End
|
|
10
|
+
() => []), // fail: did not match Until
|
|
11
|
+
() => []); // fail: did not match Start
|
|
17
12
|
}
|
|
18
13
|
function SingleLine(start, end, input) {
|
|
19
|
-
return (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return until[1].startsWith(end)
|
|
23
|
-
? [`${until[0]}`, until[1].slice(end.length)]
|
|
24
|
-
: []; // fail: did not match End
|
|
25
|
-
})() : []; // fail: did not match Until
|
|
26
|
-
})() : [] // fail: not match Start
|
|
27
|
-
);
|
|
14
|
+
return Match(Take([start], input), (_, Rest) => Match(Until([NewLine, end], Rest), (Until, UntilRest) => Match(Take([end], UntilRest), (_, EndRest) => [`${Until}`, EndRest], () => []), // fail: did not match End
|
|
15
|
+
() => []), // fail: did not match Until
|
|
16
|
+
() => []); // fail: not match Start
|
|
28
17
|
}
|
|
29
18
|
/** Matches from Start and End capturing everything in-between. Start and End are consumed. */
|
|
30
19
|
export function Span(start, end, multiLine, input) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
-
import {
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
4
4
|
import { Take } from './internal/take.mjs';
|
|
5
5
|
import { Trim } from './internal/trim.mjs';
|
|
6
6
|
import { Span } from './span.mjs';
|
|
@@ -11,11 +11,7 @@ function TakeSpan(quote, input) {
|
|
|
11
11
|
return Span(quote, quote, false, input);
|
|
12
12
|
}
|
|
13
13
|
function TakeString(quotes, input) {
|
|
14
|
-
|
|
15
|
-
return (IsResult(initial)
|
|
16
|
-
? TakeSpan(initial[0], `${initial[0]}${initial[1]}`)
|
|
17
|
-
: [] // fail: did not match Initial
|
|
18
|
-
);
|
|
14
|
+
return Match(TakeInitial(quotes, input), (Initial, InitialRest) => TakeSpan(Initial, `${Initial}${InitialRest}`), () => []); // fail: did not match Initial
|
|
19
15
|
}
|
|
20
16
|
/** Matches a literal String with the given quotes */
|
|
21
17
|
export function String(quotes, input) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type TTrim } from './internal/trim.mjs';
|
|
2
|
+
import { type TTake } from './internal/take.mjs';
|
|
3
|
+
import { type TMany } from './internal/many.mjs';
|
|
4
|
+
import { type TDigit } from './internal/char.mjs';
|
|
5
|
+
import { type TZero } from './internal/char.mjs';
|
|
6
|
+
import { type TNonZero } from './internal/char.mjs';
|
|
7
|
+
import { type TUnderScore } from './internal/char.mjs';
|
|
8
|
+
type TTakeNonZero<Input extends string> = (TTake<TNonZero, Input>);
|
|
9
|
+
type TAllowedDigits = [...TDigit, TUnderScore];
|
|
10
|
+
type TTakeDigits<Input extends string> = (TMany<TAllowedDigits, [TUnderScore], Input>);
|
|
11
|
+
type TTakeUnsignedInteger<Input extends string> = (TTake<[TZero], Input> extends [infer Zero extends string, infer ZeroRest extends string] ? [Zero, ZeroRest] : TTakeNonZero<Input> extends [infer NonZero extends string, infer NonZeroRest extends string] ? TTakeDigits<NonZeroRest> extends [infer Digits extends string, infer DigitsRest extends string] ? [`${NonZero}${Digits}`, DigitsRest] : [] : []);
|
|
12
|
+
/** Matches if next is a UnsignedInteger */
|
|
13
|
+
export type TUnsignedInteger<Input extends string> = (TTakeUnsignedInteger<TTrim<Input>>);
|
|
14
|
+
/** Matches if next is a UnsignedInteger */
|
|
15
|
+
export declare function UnsignedInteger<Input extends string>(input: Input): TUnsignedInteger<Input>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// deno-coverage-ignore-start - parsebox tested
|
|
2
|
+
// deno-fmt-ignore-file
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
4
|
+
import { Trim } from './internal/trim.mjs';
|
|
5
|
+
import { Take } from './internal/take.mjs';
|
|
6
|
+
import { Many } from './internal/many.mjs';
|
|
7
|
+
import { Digit } from './internal/char.mjs';
|
|
8
|
+
import { Zero } from './internal/char.mjs';
|
|
9
|
+
import { NonZero } from './internal/char.mjs';
|
|
10
|
+
import { UnderScore } from './internal/char.mjs';
|
|
11
|
+
function TakeNonZero(input) {
|
|
12
|
+
return Take(NonZero, input);
|
|
13
|
+
}
|
|
14
|
+
const AllowedDigits = [...Digit, UnderScore];
|
|
15
|
+
function TakeDigits(input) {
|
|
16
|
+
return Many(AllowedDigits, [UnderScore], input);
|
|
17
|
+
}
|
|
18
|
+
function TakeUnsignedInteger(input) {
|
|
19
|
+
return Match(Take([Zero], input), (Zero, ZeroRest) => [Zero, ZeroRest], () => Match(TakeNonZero(input), (NonZero, NonZeroRest) => Match(TakeDigits(NonZeroRest), (Digits, DigitsRest) => [`${NonZero}${Digits}`, DigitsRest], () => []), // fail: did not match Digits
|
|
20
|
+
() => [])); // fail: did not match NonZero
|
|
21
|
+
}
|
|
22
|
+
/** Matches if next is a UnsignedInteger */
|
|
23
|
+
export function UnsignedInteger(input) {
|
|
24
|
+
return TakeUnsignedInteger(Trim(input));
|
|
25
|
+
}
|
|
26
|
+
// deno-coverage-ignore-stop
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type TTrim } from './internal/trim.mjs';
|
|
2
|
+
import { type TTake } from './internal/take.mjs';
|
|
3
|
+
import { type TMany } from './internal/many.mjs';
|
|
4
|
+
import { type TDigit, type TUnderScore } from './internal/char.mjs';
|
|
5
|
+
import { type TDot } from './internal/char.mjs';
|
|
6
|
+
import { type TUnsignedInteger } from './unsigned_integer.mjs';
|
|
7
|
+
type TAllowedDigits = [...TDigit, TUnderScore];
|
|
8
|
+
type TIsLeadingDot<Input extends string> = (TTake<[TDot], Input> extends [string, string] ? true : false);
|
|
9
|
+
type TTakeFractional<Input extends string> = (TMany<TAllowedDigits, [TUnderScore], Input> extends [infer Digits extends string, infer DigitsRest extends string] ? Digits extends '' ? [] : [Digits, DigitsRest] : []);
|
|
10
|
+
type TLeadingDot<Input extends string> = (TTake<[TDot], Input> extends [infer Dot extends string, infer DotRest extends string] ? TTakeFractional<DotRest> extends [infer Fractional extends string, infer FractionalRest extends string] ? [`0${Dot}${Fractional}`, FractionalRest] : [] : []);
|
|
11
|
+
type TLeadingInteger<Input extends string> = (TUnsignedInteger<Input> extends [infer Integer extends string, infer IntegerRest extends string] ? TTake<[TDot], IntegerRest> extends [infer Dot extends string, infer DotRest extends string] ? TTakeFractional<DotRest> extends [infer Fractional extends string, infer FractionalRest extends string] ? [`${Integer}${Dot}${Fractional}`, FractionalRest] : [`${Integer}`, DotRest] : [`${Integer}`, IntegerRest] : []);
|
|
12
|
+
type TTakeUnsignedNumber<Input extends string> = (TIsLeadingDot<Input> extends true ? TLeadingDot<Input> : TLeadingInteger<Input>);
|
|
13
|
+
/** Matches if next is a UnsignedNumber */
|
|
14
|
+
export type TUnsignedNumber<Input extends string> = (TTakeUnsignedNumber<TTrim<Input>>);
|
|
15
|
+
/** Matches if next is a UnsignedNumber */
|
|
16
|
+
export declare function UnsignedNumber<Input extends string>(input: Input): TUnsignedNumber<Input>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// deno-coverage-ignore-start - parsebox tested
|
|
2
|
+
// deno-fmt-ignore-file
|
|
3
|
+
import { IsEqual } from './internal/guard.mjs';
|
|
4
|
+
import { IsMatch, Match } from './internal/match.mjs';
|
|
5
|
+
import { Trim } from './internal/trim.mjs';
|
|
6
|
+
import { Take } from './internal/take.mjs';
|
|
7
|
+
import { Many } from './internal/many.mjs';
|
|
8
|
+
import { Digit, UnderScore } from './internal/char.mjs';
|
|
9
|
+
import { Dot } from './internal/char.mjs';
|
|
10
|
+
import { UnsignedInteger } from './unsigned_integer.mjs';
|
|
11
|
+
const AllowedDigits = [...Digit, UnderScore];
|
|
12
|
+
function IsLeadingDot(input) {
|
|
13
|
+
return IsMatch(Take([Dot], input));
|
|
14
|
+
}
|
|
15
|
+
function TakeFractional(input) {
|
|
16
|
+
return Match(Many(AllowedDigits, [UnderScore], input), (Digits, DigitsRest) => IsEqual(Digits, '')
|
|
17
|
+
? [] // fail: no Digits
|
|
18
|
+
: [Digits, DigitsRest], () => []); // fail: did not match Digits
|
|
19
|
+
}
|
|
20
|
+
function LeadingDot(input) {
|
|
21
|
+
return Match(Take([Dot], input), (Dot, DotRest) => Match(TakeFractional(DotRest), (Fractional, FractionalRest) => [`0${Dot}${Fractional}`, FractionalRest], () => []), // fail: did not match Fractional
|
|
22
|
+
() => []); // fail: did not match Dot
|
|
23
|
+
}
|
|
24
|
+
function LeadingInteger(input) {
|
|
25
|
+
return Match(UnsignedInteger(input), (Integer, IntegerRest) => Match(Take([Dot], IntegerRest), (Dot, DotRest) => Match(TakeFractional(DotRest), (Fractional, FractionalRest) => [`${Integer}${Dot}${Fractional}`, FractionalRest], () => [`${Integer}`, DotRest]), // fail: did not match Fractional, use Integer
|
|
26
|
+
() => [`${Integer}`, IntegerRest]), // fail: did not match Dot, use Integer
|
|
27
|
+
() => []); // fail: did not match Integer
|
|
28
|
+
}
|
|
29
|
+
function TakeUnsignedNumber(input) {
|
|
30
|
+
return (IsLeadingDot(input)
|
|
31
|
+
? LeadingDot(input)
|
|
32
|
+
: LeadingInteger(input));
|
|
33
|
+
}
|
|
34
|
+
/** Matches if next is a UnsignedNumber */
|
|
35
|
+
export function UnsignedNumber(input) {
|
|
36
|
+
return TakeUnsignedNumber(Trim(input));
|
|
37
|
+
}
|
|
38
|
+
// deno-coverage-ignore-stop
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
type
|
|
1
|
+
type TTakeOne<Input extends string> = (Input extends `${infer Left extends string}${infer Right extends string}` ? [Left, Right] : []);
|
|
2
|
+
type TIsInputMatchSentinal<End extends string[], Input extends string> = (End extends [infer Left extends string, ...infer Right extends string[]] ? Input extends `${Left}${string}` ? true : TIsInputMatchSentinal<Right, Input> : false);
|
|
2
3
|
/** Match Input until but not including End. No match if End not found. */
|
|
3
|
-
export type TUntil<End extends string[], Input extends string, Result extends string = ''> = (Input extends
|
|
4
|
+
export type TUntil<End extends string[], Input extends string, Result extends string = ''> = (TTakeOne<Input> extends [infer One extends string, infer Rest extends string] ? TIsInputMatchSentinal<End, Input> extends true ? [Result, Input] : TUntil<End, Rest, `${Result}${One}`> : []);
|
|
4
5
|
/** Match Input until but not including End. No match if End not found. */
|
|
5
6
|
export declare function Until<End extends string[], Input extends string>(end: [...End], input: Input, result?: string): TUntil<End, Input>;
|
|
6
7
|
export {};
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
|
+
import { Match } from './internal/match.mjs';
|
|
3
4
|
import { IsEqual, IsString } from './internal/guard.mjs';
|
|
4
|
-
function
|
|
5
|
+
function TakeOne(input) {
|
|
6
|
+
const result = IsEqual(input, '') ? [] : [input.slice(0, 1), input.slice(1)];
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
function IsInputMatchSentinal(end, input) {
|
|
5
10
|
const [left, ...right] = end;
|
|
6
11
|
return (IsString(left)
|
|
7
12
|
? input.startsWith(left)
|
|
8
13
|
? true
|
|
9
|
-
:
|
|
14
|
+
: IsInputMatchSentinal(right, input)
|
|
10
15
|
: false);
|
|
11
16
|
}
|
|
12
17
|
/** Match Input until but not including End. No match if End not found. */
|
|
13
18
|
export function Until(end, input, result = '') {
|
|
14
|
-
return (
|
|
15
|
-
? [] //
|
|
16
|
-
:
|
|
17
|
-
|
|
18
|
-
return Until(end, right, `${result}${left}`);
|
|
19
|
-
})());
|
|
19
|
+
return Match(TakeOne(input), (One, Rest) => IsInputMatchSentinal(end, input)
|
|
20
|
+
? [result, input] // ok: at sentinal
|
|
21
|
+
: Until(end, Rest, `${result}${One}`) // fail: advance + 1
|
|
22
|
+
, () => []);
|
|
20
23
|
}
|
|
21
24
|
// deno-coverage-ignore-stop
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
// deno-coverage-ignore-start - parsebox tested
|
|
2
2
|
// deno-fmt-ignore-file
|
|
3
3
|
import { IsEqual } from './internal/guard.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { Match } from './internal/match.mjs';
|
|
5
5
|
import { Until } from './until.mjs';
|
|
6
6
|
/** Match Input until but not including End. No match if End not found or match is zero-length. */
|
|
7
7
|
export function Until_1(end, input) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
? [] // fail: match has no characters
|
|
12
|
-
: until
|
|
13
|
-
: [] // fail: did not match Until
|
|
14
|
-
);
|
|
8
|
+
return Match(Until(end, input), (Until, UntilRest) => IsEqual(Until, '')
|
|
9
|
+
? [] // fail: match has no characters
|
|
10
|
+
: [Until, UntilRest], () => []); // fail: did not match Until
|
|
15
11
|
}
|
|
16
12
|
// deno-coverage-ignore-stop
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typebox",
|
|
3
3
|
"description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.8",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
7
7
|
"jsonschema"
|
|
@@ -16,38 +16,38 @@
|
|
|
16
16
|
"types": "./build/index.d.mts",
|
|
17
17
|
"module": "./build/index.mjs",
|
|
18
18
|
"exports": {
|
|
19
|
-
"./type": {
|
|
20
|
-
"import": "./build/type/index.mjs",
|
|
21
|
-
"default": "./build/type/index.mjs"
|
|
22
|
-
},
|
|
23
|
-
"./value": {
|
|
24
|
-
"import": "./build/value/index.mjs",
|
|
25
|
-
"default": "./build/value/index.mjs"
|
|
26
|
-
},
|
|
27
|
-
"./guard": {
|
|
28
|
-
"import": "./build/guard/index.mjs",
|
|
29
|
-
"default": "./build/guard/index.mjs"
|
|
30
|
-
},
|
|
31
19
|
"./system": {
|
|
32
20
|
"import": "./build/system/index.mjs",
|
|
33
21
|
"default": "./build/system/index.mjs"
|
|
34
22
|
},
|
|
35
|
-
"./format": {
|
|
36
|
-
"import": "./build/format/index.mjs",
|
|
37
|
-
"default": "./build/format/index.mjs"
|
|
38
|
-
},
|
|
39
23
|
"./compile": {
|
|
40
24
|
"import": "./build/compile/index.mjs",
|
|
41
25
|
"default": "./build/compile/index.mjs"
|
|
42
26
|
},
|
|
27
|
+
"./value": {
|
|
28
|
+
"import": "./build/value/index.mjs",
|
|
29
|
+
"default": "./build/value/index.mjs"
|
|
30
|
+
},
|
|
43
31
|
"./error": {
|
|
44
32
|
"import": "./build/error/index.mjs",
|
|
45
33
|
"default": "./build/error/index.mjs"
|
|
46
34
|
},
|
|
35
|
+
"./guard": {
|
|
36
|
+
"import": "./build/guard/index.mjs",
|
|
37
|
+
"default": "./build/guard/index.mjs"
|
|
38
|
+
},
|
|
47
39
|
"./schema": {
|
|
48
40
|
"import": "./build/schema/index.mjs",
|
|
49
41
|
"default": "./build/schema/index.mjs"
|
|
50
42
|
},
|
|
43
|
+
"./format": {
|
|
44
|
+
"import": "./build/format/index.mjs",
|
|
45
|
+
"default": "./build/format/index.mjs"
|
|
46
|
+
},
|
|
47
|
+
"./type": {
|
|
48
|
+
"import": "./build/type/index.mjs",
|
|
49
|
+
"default": "./build/type/index.mjs"
|
|
50
|
+
},
|
|
51
51
|
".": {
|
|
52
52
|
"import": "./build/index.mjs",
|
|
53
53
|
"default": "./build/index.mjs"
|
|
@@ -55,30 +55,30 @@
|
|
|
55
55
|
},
|
|
56
56
|
"typesVersions": {
|
|
57
57
|
"*": {
|
|
58
|
-
"type": [
|
|
59
|
-
"./build/type/index.d.mts"
|
|
60
|
-
],
|
|
61
|
-
"value": [
|
|
62
|
-
"./build/value/index.d.mts"
|
|
63
|
-
],
|
|
64
|
-
"guard": [
|
|
65
|
-
"./build/guard/index.d.mts"
|
|
66
|
-
],
|
|
67
58
|
"system": [
|
|
68
59
|
"./build/system/index.d.mts"
|
|
69
60
|
],
|
|
70
|
-
"format": [
|
|
71
|
-
"./build/format/index.d.mts"
|
|
72
|
-
],
|
|
73
61
|
"compile": [
|
|
74
62
|
"./build/compile/index.d.mts"
|
|
75
63
|
],
|
|
64
|
+
"value": [
|
|
65
|
+
"./build/value/index.d.mts"
|
|
66
|
+
],
|
|
76
67
|
"error": [
|
|
77
68
|
"./build/error/index.d.mts"
|
|
78
69
|
],
|
|
70
|
+
"guard": [
|
|
71
|
+
"./build/guard/index.d.mts"
|
|
72
|
+
],
|
|
79
73
|
"schema": [
|
|
80
74
|
"./build/schema/index.d.mts"
|
|
81
75
|
],
|
|
76
|
+
"format": [
|
|
77
|
+
"./build/format/index.d.mts"
|
|
78
|
+
],
|
|
79
|
+
"type": [
|
|
80
|
+
"./build/type/index.d.mts"
|
|
81
|
+
],
|
|
82
82
|
".": [
|
|
83
83
|
"./build/index.d.mts"
|
|
84
84
|
]
|
package/readme.md
CHANGED
|
@@ -57,12 +57,11 @@ License: MIT
|
|
|
57
57
|
|
|
58
58
|
## Contents
|
|
59
59
|
|
|
60
|
-
|
|
61
60
|
- [Type](#Type)
|
|
62
61
|
- [Value](#Value)
|
|
63
62
|
- [Script](#Script)
|
|
64
63
|
- [Schema](#Schema)
|
|
65
|
-
- [
|
|
64
|
+
- [Versions](#Versions)
|
|
66
65
|
- [Contribute](#Contribute)
|
|
67
66
|
|
|
68
67
|
|
|
@@ -70,7 +69,7 @@ License: MIT
|
|
|
70
69
|
|
|
71
70
|
## Type
|
|
72
71
|
|
|
73
|
-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/type/overview)
|
|
72
|
+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/type/overview)
|
|
74
73
|
|
|
75
74
|
TypeBox provides many functions to create JSON Schema types. Each function returns a small JSON Schema fragment that can be composed into more complex types. TypeBox includes a set of functions that are used to construct JSON Schema compliant schematics as well as a set of extended functions that return schematics for constructs native to JavaScript.
|
|
76
75
|
|
|
@@ -117,7 +116,7 @@ const S = Type.Number({ // const S = {
|
|
|
117
116
|
|
|
118
117
|
## Value
|
|
119
118
|
|
|
120
|
-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/value/overview)
|
|
119
|
+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/value/overview)
|
|
121
120
|
|
|
122
121
|
The Value submodule provides functions for validation and other typed operations on JavaScript values. It includes functions such as Check, Parse, Clone, Encode, and Decode, as well as advanced functions for performing structural Diff and Patch operations on dynamic JavaScript values.
|
|
123
122
|
|
|
@@ -145,7 +144,7 @@ const A = Value.Parse(T, { // const A: {
|
|
|
145
144
|
|
|
146
145
|
## Script
|
|
147
146
|
|
|
148
|
-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview)
|
|
147
|
+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview)
|
|
149
148
|
|
|
150
149
|
TypeBox includes a runtime TypeScript DSL engine that can transform TypeScript syntax into JSON Schema. The engine is implemented at runtime and within the TypeScript type system.
|
|
151
150
|
|
|
@@ -223,62 +222,31 @@ const R = C.Parse({ x: 0, y: 0, z: 0 }) // const R: {
|
|
|
223
222
|
// } = ...
|
|
224
223
|
```
|
|
225
224
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
If upgrading from `@sinclair/typebox` 0.34.x refer to the 1.0 migration guide at the following URL.
|
|
229
|
-
|
|
230
|
-
[Migration Guide](https://github.com/sinclairzx81/typebox/blob/main/changelog/1.0.0-migration.md)
|
|
225
|
+
<a name="Versions"></a>
|
|
231
226
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
[Compatibility](https://tsplay.dev/Wzr2rW)
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
import { Type } from '@sinclair/typebox' // TB: 0.34.x
|
|
238
|
-
import { Static } from 'typebox' // TB: 1.0.0
|
|
227
|
+
## Versions
|
|
239
228
|
|
|
240
|
-
|
|
241
|
-
// Legacy Types
|
|
242
|
-
// ----------------------------------------------------------
|
|
243
|
-
const A = Type.Object({
|
|
244
|
-
x: Type.Number(),
|
|
245
|
-
y: Type.Number(),
|
|
246
|
-
z: Type.Number()
|
|
247
|
-
})
|
|
229
|
+
TypeBox provides two distinct versions that span two generations of the TypeScript compiler.
|
|
248
230
|
|
|
249
|
-
|
|
250
|
-
a: Type.Number(),
|
|
251
|
-
b: Type.Number(),
|
|
252
|
-
c: Type.Number()
|
|
253
|
-
})
|
|
231
|
+
### Version 0.x
|
|
254
232
|
|
|
255
|
-
|
|
233
|
+
```bash
|
|
234
|
+
$ npm install @sinclair/typebox # 0.x - LTS | TS 4-6
|
|
235
|
+
```
|
|
256
236
|
|
|
257
|
-
|
|
258
|
-
// Modern Inference
|
|
259
|
-
// ----------------------------------------------------------
|
|
260
|
-
type C = Static<typeof C> // type C = {
|
|
261
|
-
// x: number;
|
|
262
|
-
// y: number;
|
|
263
|
-
// z: number;
|
|
264
|
-
// a: number;
|
|
265
|
-
// b: number;
|
|
266
|
-
// c: number;
|
|
267
|
-
// }
|
|
237
|
+
Developed against TypeScript 4-6 and maintained under Long Term Support (LTS) for existing infrastructure on the 0.x revision line. ESM and CJS compatible.
|
|
268
238
|
|
|
269
|
-
|
|
270
|
-
// Modern Compile
|
|
271
|
-
// ----------------------------------------------------------
|
|
272
|
-
import Schema from 'typebox/schema'
|
|
239
|
+
### Version 1.x
|
|
273
240
|
|
|
274
|
-
|
|
241
|
+
```bash
|
|
242
|
+
$ npm install typebox # 1.x - Latest | TS 7 Native
|
|
275
243
|
```
|
|
276
244
|
|
|
277
|
-
|
|
245
|
+
Developed against the TypeScript 7 native compiler with advanced type inference and JSON Schema 2020-12 compliant validation, with backwards compatibility for `0.x` types. ESM only.
|
|
278
246
|
|
|
279
|
-
|
|
247
|
+
### Additional
|
|
280
248
|
|
|
281
|
-
|
|
249
|
+
The `1.x` version is recommended for most new projects and is the active development line that targets optimizations enabled by the TypeScript 7 native compiler. The `0.x` version is maintained under LTS for environments requiring CJS and ESM compatibility as well as support for older TypeScript compiler versions. For issues relating to `0.x` please submit them to the [TypeBox 0.x](https://github.com/sinclairzx81/sinclair-typebox) repository.
|
|
282
250
|
|
|
283
251
|
## Contribute
|
|
284
252
|
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// deno-coverage-ignore-start - parsebox tested
|
|
2
|
-
import { IsArray, IsEqual } from './guard.mjs';
|
|
3
|
-
/** Checks the value is a Tuple-2 [string, string] result */
|
|
4
|
-
export function IsResult(value) {
|
|
5
|
-
return IsArray(value) && IsEqual(value.length, 2);
|
|
6
|
-
}
|
|
7
|
-
// deno-coverage-ignore-stop
|