Skip to content

Commit 8f57476

Browse files
committed
refactor: cleanup & preserve object when using $where
1 parent 3b452f7 commit 8f57476

File tree

4 files changed

+31
-24
lines changed

4 files changed

+31
-24
lines changed

Diff for: interpreter.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { Parser, ParserError } from "./parser";
22
import { Tokenize } from "./tokenizer";
3-
import { GetByField, TuplifyUnion, UnionToIntersection } from "./utils";
3+
import { GetByField, IsUnion, TuplifyUnion } from "./utils";
44

55
type PushError<Errors extends any[], AST> = AST extends ParserError<infer E>
66
? [...Errors, E]
77
: [];
88

99
export type Interpret<
10-
Obj,
10+
Obj extends Record<any, any>,
1111
AST,
1212
Errors extends string[] = []
1313
> = AST extends ParserError<infer Err>
@@ -41,7 +41,9 @@ export type Interpret<
4141
value: infer FilterBy;
4242
}
4343
? Interpret<
44-
TuplifyUnion<GetByField<Obj, FilterBy>>,
44+
IsUnion<GetByField<Obj, FilterBy>> extends true
45+
? TuplifyUnion<GetByField<Obj, FilterBy>>
46+
: GetByField<Obj, FilterBy>,
4547
{},
4648
PushError<Errors, FilterBy>
4749
>

Diff for: parser.ts

+22-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Interpret } from "./interpreter";
2-
import { Tokenize, TokenTypes } from "./tokenizer";
2+
import { Token, Tokenize, TokenTypes } from "./tokenizer";
33
import { Head, Head2, ParseObj, TailBy } from "./utils";
44

55
export type ParserError<T extends string> = T & { __brand: "ParserError" };
@@ -22,14 +22,13 @@ type Eat<T extends { type: keyof TokenTypes }, Type extends string> = Expect<
2222
: Expect<T, Type, true>;
2323

2424
type IsToken<
25-
Tok extends { type: string },
25+
Tok extends { type: keyof TokenTypes },
2626
TokenType extends keyof TokenTypes
2727
> = Tok["type"] extends TokenType ? true : false;
2828

29-
type HasErrors<
30-
E extends ParserError<string>,
31-
Else
32-
> = E extends ParserError<string> ? E : Else;
29+
type HasErrors<Value extends unknown, Else> = Value extends ParserError<string>
30+
? Value
31+
: Else;
3332

3433
type GetValueIfNoParserError<T, K> = [Exclude<T, K>] extends [never]
3534
? T
@@ -44,8 +43,8 @@ type ParseIndexAccess<T extends any[]> = [
4443
? GetValueIfNoParserError<
4544
HasErrors<
4645
P1 | P2 | Rest[0],
47-
P2 extends { type: "NUMBER" }
48-
? { type: "ArrayAccess"; index: P2["value"]; eat: 3 }
46+
P2 extends { type: "NUMBER"; value: infer Index }
47+
? { type: "ArrayAccess"; index: Index; eat: 3 }
4948
: { type: "ArrayAccess"; index: never; eat: 3 }
5049
>,
5150
{ type: "ArrayAccess" }
@@ -61,21 +60,21 @@ type ParseWhereClause<T extends any[]> = [
6160
? GetValueIfNoParserError<
6261
HasErrors<
6362
P1 | P2 | P3 | P4,
64-
{ type: "WhereClause"; value: ParseObj<P3["name"]>; eat: 4 }
63+
P3 extends { type: "IDENT"; name: infer Name }
64+
? { type: "WhereClause"; value: ParseObj<Name & string>; eat: 4 }
65+
: { type: "WhereClause"; value: {}; eat: 4 }
6566
>,
6667
{ type: "WhereClause" }
6768
>
6869
: never;
6970

70-
type DD = ParseWhereClause<Tokenize<"$where(a:1)">>;
71-
7271
export type Parser<
73-
T extends any[],
72+
T extends Token[],
7473
AST = {},
75-
Cursor = Head<T>,
76-
LookAhead = Head2<T>
74+
Cursor extends Token = Head<T>,
75+
LookAhead extends Token = Head2<T>
7776
> = IsToken<Cursor, "WHERE"> extends true
78-
? Parser<TailBy<T, 4>, AST & ParseWhereClause<T>>
77+
? Parser<TailBy<T, 4>, ParseWhereClause<T>>
7978
: IsToken<Cursor, "IDENT"> extends true
8079
? Parser<TailBy<T, 1>, AST & { type: "Identifier"; value: Cursor["name"] }>
8180
: IsToken<Cursor, "DOT"> extends true
@@ -112,10 +111,16 @@ export type Parser<
112111
// type D = ParseIndexAccess<Tokenize<"0]">>;
113112
// type K = Interpret<{ a: { b: [0] } }, L3>;
114113

115-
type Toks = Tokenize<"a[].$where(id:1,age:2)">;
114+
// TODO Throw error on where syntax
115+
type Toks = Tokenize<"b[].$where().i[].$where(id:i11)">;
116116
type AST = Parser<Toks>;
117117
type K = Interpret<
118-
{ a: [{ id: 1; age: 2; name: "one" }, { id: 2; age: 2; name: "two" }] },
118+
{
119+
b: [
120+
{ id: 1; i: [{ id: "i11" }, { id: "i12" }] },
121+
{ id: 2; i: [{ id: "i21" }, { id: "i22" }] }
122+
];
123+
},
119124
AST
120125
>;
121126

Diff for: tokenizer.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ export type TokenMap = {
2222
")": { type: TokenTypes["PAREN_END"] };
2323
"[": { type: TokenTypes["BRACKET_START"] };
2424
"]": { type: TokenTypes["BRACKET_END"] };
25-
"$where": { type: TokenTypes["WHERE"] };
25+
$where: { type: TokenTypes["WHERE"] };
2626
".": { type: TokenTypes["DOT"] };
2727
};
28+
export type Token = { type: keyof TokenTypes; [x: string]: any };
2829

2930
type ExtractIdentifier<
3031
Acc extends string[],
@@ -37,8 +38,6 @@ type ExtractIdentifier<
3738
? never
3839
: Identifier<Tok>;
3940

40-
type E = ExtractIdentifier<['where']>
41-
4241
type SwitchToken<T> = T extends keyof TokenMap ? TokenMap[T] : T;
4342

4443
type TokenizeInternal<
@@ -65,4 +64,4 @@ export type Tokenize<T extends string> = TokenizeInternal<Split<T, "">>;
6564

6665
type Demo1 = Tokenize<"invoices.$where(1)">;
6766
type Demo2 = Tokenize<"invoices.data[].$where(id:2)">;
68-
// type Demo3 = Tokenize<"comments[].$where(id:abcdefghijklm)">;
67+
// type Demo3 = Tokenize<"comments[].$where(id:abcdefghijklm)">;

Diff for: utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export type TuplifyUnion<
8282
N = [T] extends [never] ? true : false
8383
> = true extends N ? [] : Push<TuplifyUnion<Exclude<T, L>>, L>;
8484

85+
export type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
8586
export type GetByField<T, Query> = Extract<T, Query>;
8687
export type ParseObj<
8788
ObjStr extends string,

0 commit comments

Comments
 (0)