diff --git a/src/expression-attributes.ts b/src/expression-attributes.ts index b35ae7c..a808128 100644 --- a/src/expression-attributes.ts +++ b/src/expression-attributes.ts @@ -3,6 +3,8 @@ import { AlphaNumeric } from "./letter"; export type ExpressionAttributeValues = undefined extends Expression + ? {} + : ParseConditionExpressionValues extends never ? {} : { ExpressionAttributeValues: { @@ -12,6 +14,8 @@ export type ExpressionAttributeValues = export type ExpressionAttributeNames = undefined extends Expression + ? {} + : ParseConditionExpressionNames extends never ? {} : { ExpressionAttributeNames: { diff --git a/src/expression.ts b/src/expression.ts new file mode 100644 index 0000000..4de05ec --- /dev/null +++ b/src/expression.ts @@ -0,0 +1,52 @@ +export type Expr = + | ArrayIndex + | Identifier + | NumberLiteral + | OperatorExpr + | NameRef + | PropRef + | ValueRef; +// + +export interface NameRef { + kind: "name-ref"; + name: Name; +} +export interface ValueRef { + kind: "value-ref"; + name: Name; +} +export interface Identifier { + kind: "identifier"; + name: I; +} + +export interface NumberLiteral { + kind: "index"; + number: N; +} +export interface PropRef { + kind: "prop-ref"; + expr: Ex; + name: Id; +} +export interface ArrayIndex< + List extends Expr = any, + Number extends NumberLiteral | ValueRef = NumberLiteral | ValueRef +> { + kind: "array-index"; + list: List; + number: Number; +} + +export type Operator = "and" | "or" | "=" | "<" | "<=" | ">=" | ">"; +export interface OperatorExpr< + Left extends Expr = any, + Op extends Operator = Operator, + Right extends Expr = any +> { + kind: "op"; + left: Left; + op: Op; + right: Right; +} diff --git a/src/get-item.ts b/src/get-item.ts index 419f0ee..c4e6957 100644 --- a/src/get-item.ts +++ b/src/get-item.ts @@ -1,7 +1,7 @@ import type { DynamoDB } from "aws-sdk"; import { ToAttributeMap } from "./attribute-value"; import { KeyAttribute, KeyAttributeToObject } from "./key"; -import { ApplyProjection } from "./projection-expression"; +import { ApplyProjection } from "./projection"; export interface GetItemInput< Item extends object, diff --git a/src/index.ts b/src/index.ts index f7b9733..a2ba095 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,6 @@ export * from "./client"; export * from "./expression-attributes"; export * from "./get-item"; export * from "./key"; -export * from "./projection-expression"; +export * from "./projection"; export * from "./put-item"; export * from "./query"; diff --git a/src/projection-expression.ts b/src/projection.ts similarity index 53% rename from src/projection-expression.ts rename to src/projection.ts index f18497e..ae08aa2 100644 --- a/src/projection-expression.ts +++ b/src/projection.ts @@ -1,111 +1,77 @@ +import { + ArrayIndex, + Identifier, + NameRef, + NumberLiteral, + Expr, + PropRef, + ValueRef, +} from "./expression"; import { AlphaNumeric } from "./letter"; -export type ProjectionExpr = - | ArrayIndex - | Identifier - | NumberLiteral - | NameRef - | PropRef - | ValueRef; -// - -export interface NameRef { - kind: "name-ref"; - name: Name; -} -export interface ValueRef { - kind: "value-ref"; - name: Name; -} -export interface Identifier { - kind: "identifier"; - name: I; -} - -export interface NumberLiteral { - kind: "index"; - number: N; -} -export interface PropRef< - Expr extends ProjectionExpr = any, - Id extends Identifier = any -> { - kind: "prop-ref"; - expr: Expr; - name: Id; -} -export interface ArrayIndex< - List extends ProjectionExpr = any, - Number extends NumberLiteral | ValueRef = NumberLiteral | ValueRef -> { - kind: "array-index"; - list: List; - number: Number; -} - export type ParseProjectionExpression = Parse< Text, [], undefined >; -type AsExpr = Extract; +type AsExpr = Extract; type Parse< Text extends string, - Expressions extends ProjectionExpr[], - Expr extends ProjectionExpr | undefined + Expressions extends Expr[], + Exp extends Expr | undefined > = Text extends `.${infer Rest}` - ? Expr extends ProjectionExpr - ? Parse>> + ? Exp extends Expr + ? Parse>> : never : Text extends `[:${infer Rest}` - ? Parse, ValueRef<"">>> + ? Parse, ValueRef<"">>> : Text extends `[${infer Rest}` - ? Parse, NumberLiteral<"">>> + ? Parse, NumberLiteral<"">>> : Text extends `]${infer Rest}` - ? Parse + ? Parse : Text extends `]` - ? Concat + ? Concat : Text extends `${"," | " "}${infer Rest}` - ? Parse, undefined> + ? Parse, undefined> : Text extends `#${infer Rest}` - ? Parse, NameRef> + ? Parse, NameRef> : Text extends `:${infer Rest}` - ? Parse, ValueRef> + ? Parse, ValueRef> : Text extends `${AlphaNumeric}${string}` ? Text extends `${infer char}${infer Rest}` - ? Parse> + ? Parse> : never : Text extends `${AlphaNumeric}${string}` ? Text extends `${infer char}${infer Rest}` - ? Parse> + ? Parse> : never - : Concat; + : Concat; type Concat< - Expressions extends ProjectionExpr[], - CurrentExpr extends ProjectionExpr | undefined + Expressions extends Expr[], + CurrentExpr extends Expr | undefined > = undefined extends CurrentExpr ? Expressions - : [...Expressions, Extract]; + : [...Expressions, Extract]; type Append< - Expr extends ProjectionExpr | undefined, + Exp extends Expr | undefined, char extends string -> = Expr extends undefined +> = Exp extends undefined ? Identifier - : Expr extends Identifier + : Exp extends Identifier ? Identifier<`${Name}${char}`> - : Expr extends NumberLiteral + : Exp extends NumberLiteral ? NumberLiteral<`${Name}${char}`> - : Expr extends NameRef + : Exp extends NameRef ? NameRef<`${Name}${char}`> - : Expr extends ValueRef + : Exp extends ValueRef ? ValueRef<`${Name}${char}`> - : Expr extends PropRef + : Exp extends PropRef ? PropRef, Identifier>> - : Expr extends ArrayIndex + : Exp extends ArrayIndex ? ArrayIndex, NumberLiteral>> : never; @@ -115,27 +81,27 @@ export type ApplyProjection = Flatten< > >; -type ApplyProjectionExpr = T extends undefined +type ApplyProjectionExpr = T extends undefined ? never - : Expr extends PropRef + : Exp extends PropRef ? { [p in keyof ApplyProjectionExpr]: ApplyProjectionExpr< ApplyProjectionExpr[p], i >; } - : Expr extends ArrayIndex + : Exp extends ArrayIndex ? { [p in keyof ApplyProjectionExpr]: ApplyProjectionExpr< ApplyProjectionExpr[keyof ApplyProjectionExpr], i >; } - : Expr extends Identifier + : Exp extends Identifier ? I extends keyof T ? Pick : never - : Expr extends NumberLiteral + : Exp extends NumberLiteral ? ParseInt extends keyof T ? Pick> : never