UNPKG

@kuindji/sql-type-parser

Version:
103 lines 5.61 kB
/** * Type-level string and number utilities for the SQL parser * * These utilities are shared across all query type parsers. */ /** * Remove surrounding quotes from an identifier (double quotes or backticks) */ export type RemoveQuotes<T extends string> = Trim<T> extends `"${infer Inner}"` ? Inner : Trim<T> extends `\`${infer Inner}\`` ? Inner : Trim<T> extends `'${infer Inner}'` ? Inner : Trim<T>; /** * Trim leading and trailing whitespace from a string */ export type Trim<T extends string> = T extends ` ${infer Rest}` ? Trim<Rest> : T extends `${infer Rest} ` ? Trim<Rest> : T extends `\n${infer Rest}` ? Trim<Rest> : T extends `${infer Rest}\n` ? Trim<Rest> : T extends `\r${infer Rest}` ? Trim<Rest> : T extends `${infer Rest}\r` ? Trim<Rest> : T extends `\t${infer Rest}` ? Trim<Rest> : T extends `${infer Rest}\t` ? Trim<Rest> : T; /** * Join array of strings with a separator */ export type Join<T extends string[], Sep extends string = " "> = T extends [ infer First extends string, ...infer Rest extends string[] ] ? Rest extends [] ? First : `${First}${Sep}${Join<Rest, Sep>}` : ""; /** * Uppercase a string (limited set of characters for SQL keywords) */ export type ToUpperCase<S extends string> = S extends `${infer C}${infer Rest}` ? `${UpperChar<C>}${ToUpperCase<Rest>}` : S; type UpperChar<C extends string> = C extends "a" ? "A" : C extends "b" ? "B" : C extends "c" ? "C" : C extends "d" ? "D" : C extends "e" ? "E" : C extends "f" ? "F" : C extends "g" ? "G" : C extends "h" ? "H" : C extends "i" ? "I" : C extends "j" ? "J" : C extends "k" ? "K" : C extends "l" ? "L" : C extends "m" ? "M" : C extends "n" ? "N" : C extends "o" ? "O" : C extends "p" ? "P" : C extends "q" ? "Q" : C extends "r" ? "R" : C extends "s" ? "S" : C extends "t" ? "T" : C extends "u" ? "U" : C extends "v" ? "V" : C extends "w" ? "W" : C extends "x" ? "X" : C extends "y" ? "Y" : C extends "z" ? "Z" : C; /** * Increment a number (limited range 0-20) */ export type Increment<N extends number> = N extends 0 ? 1 : N extends 1 ? 2 : N extends 2 ? 3 : N extends 3 ? 4 : N extends 4 ? 5 : N extends 5 ? 6 : N extends 6 ? 7 : N extends 7 ? 8 : N extends 8 ? 9 : N extends 9 ? 10 : N extends 10 ? 11 : N extends 11 ? 12 : N extends 12 ? 13 : N extends 13 ? 14 : N extends 14 ? 15 : N extends 15 ? 16 : N extends 16 ? 17 : N extends 17 ? 18 : N extends 18 ? 19 : N extends 19 ? 20 : never; /** * Decrement a number (limited range 0-20) */ export type Decrement<N extends number> = N extends 20 ? 19 : N extends 19 ? 18 : N extends 18 ? 17 : N extends 17 ? 16 : N extends 16 ? 15 : N extends 15 ? 14 : N extends 14 ? 13 : N extends 13 ? 12 : N extends 12 ? 11 : N extends 11 ? 10 : N extends 10 ? 9 : N extends 9 ? 8 : N extends 8 ? 7 : N extends 7 ? 6 : N extends 6 ? 5 : N extends 5 ? 4 : N extends 4 ? 3 : N extends 3 ? 2 : N extends 2 ? 1 : N extends 1 ? 0 : never; /** * Flatten/simplify a type for better readability */ export type Flatten<T> = { [K in keyof T]: T[K]; } & {}; /** * Error marker type for parse errors */ export type ParseError<Message extends string> = { error: true; message: Message; }; /** * Check if a type is a parse error */ export type IsParseError<T> = T extends ParseError<string> ? true : false; /** * Error marker type for match errors */ export type MatchError<Message extends string> = { readonly __error: true; readonly message: Message; }; /** * Check if a type is a match error */ export type IsMatchError<T> = T extends { readonly __error: true; } ? true : false; /** * Check if a string type is a literal string or the generic `string` type. * This is used to detect dynamic queries that can't be parsed at compile time. * * When T is a literal like "SELECT * FROM users", this returns true. * When T is `string` (the type), this returns false. */ export type IsStringLiteral<T extends string> = string extends T ? false : true; /** * Check if a string type contains template literal holes (like ${string}). * * Template literals like `hello ${string}` are NOT plain `string`, but they * contain dynamic parts that can't be validated at compile time. */ export type HasTemplateHoles<T extends string> = string extends T ? true : `${T}_` extends T ? true : `_${T}` extends T ? true : HasInternalHole<T>; /** * Check for internal ${string} holes by testing if different values can fill the same position. */ type HasInternalHole<T extends string> = T extends `${infer Before} ${infer After}` ? `${Before} __X__ ${After}` extends T ? `${Before} __Y__ ${After}` extends T ? true : HasInternalHole<After> : HasInternalHole<After> : HasHoleAtOtherBoundaries<T>; /** * Check for holes at non-space boundaries (commas, equals, parentheses) */ type HasHoleAtOtherBoundaries<T extends string> = T extends `${infer A},${infer B}` ? `${A},__X__,${B}` extends T ? `${A},__Y__,${B}` extends T ? true : HasHoleAtOtherBoundaries<B> : HasHoleAtOtherBoundaries<B> : T extends `${infer A}=${infer B}` ? `${A}=__X__=${B}` extends T ? `${A}=__Y__=${B}` extends T ? true : false : false : false; /** * Marker for dynamic/non-literal queries that can't be validated at compile time. * These queries are passed through without validation. */ export type DynamicQuery = { readonly __dynamic: true; }; /** * Check if a type represents a dynamic (non-literal) query */ export type IsDynamicQuery<T> = T extends DynamicQuery ? true : false; /** * The result type for dynamic queries - allows any column access */ export type DynamicQueryResult = Record<string, unknown>; export {}; //# sourceMappingURL=utils.d.ts.map