From 459a179ef38ddd77655503e72f9efd579458c208 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Fri, 28 Nov 2025 16:48:27 +0000 Subject: [PATCH] TSQL initial commit --- internal-packages/tsql/.gitignore | 3 + internal-packages/tsql/README.md | 15 + internal-packages/tsql/package.json | 18 + .../tsql/src/grammar/TSQLLexer.common.g4 | 288 ++++++++++++++++ .../tsql/src/grammar/TSQLLexer.typescript.g4 | 81 +++++ .../tsql/src/grammar/TSQLParser.g4 | 317 ++++++++++++++++++ internal-packages/tsql/src/index.ts | 1 + internal-packages/tsql/tsconfig.json | 23 ++ pnpm-lock.yaml | 240 +++++++++++++ 9 files changed, 986 insertions(+) create mode 100644 internal-packages/tsql/.gitignore create mode 100644 internal-packages/tsql/README.md create mode 100644 internal-packages/tsql/package.json create mode 100644 internal-packages/tsql/src/grammar/TSQLLexer.common.g4 create mode 100644 internal-packages/tsql/src/grammar/TSQLLexer.typescript.g4 create mode 100644 internal-packages/tsql/src/grammar/TSQLParser.g4 create mode 100644 internal-packages/tsql/src/index.ts create mode 100644 internal-packages/tsql/tsconfig.json diff --git a/internal-packages/tsql/.gitignore b/internal-packages/tsql/.gitignore new file mode 100644 index 000000000..be2243751 --- /dev/null +++ b/internal-packages/tsql/.gitignore @@ -0,0 +1,3 @@ +# Generated ANTLR parser files +src/generated/ + diff --git a/internal-packages/tsql/README.md b/internal-packages/tsql/README.md new file mode 100644 index 000000000..e7a58c92e --- /dev/null +++ b/internal-packages/tsql/README.md @@ -0,0 +1,15 @@ +# TSQL (TriggerSQL) + +TriggerSQL is a DSL that is safely converted into ClickHouse SQL queries with protection against SQL injection and it's tenant-safe (users can only query their own data). + +## ANTLR Grammar + +The ANTLR grammer is heavily inspired by [PostHog's HogQL](https://github.com/PostHog/posthog/tree/master/posthog/hogql). + +These are found in [./grammar] and are the `.g4` files. + +## Generating the source code + +```sh +pnpm run grammar:build +``` diff --git a/internal-packages/tsql/package.json b/internal-packages/tsql/package.json new file mode 100644 index 000000000..e2c0a1bed --- /dev/null +++ b/internal-packages/tsql/package.json @@ -0,0 +1,18 @@ +{ + "name": "@internal/tsql", + "private": true, + "version": "0.0.1", + "main": "./src/index.ts", + "types": "./src/index.ts", + "type": "module", + "dependencies": { + "@trigger.dev/core": "workspace:*" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "grammar:build": "antlr4 -Dlanguage=TypeScript -visitor -o src/generated src/grammar/*.g4" + }, + "devDependencies": { + "antlr4ts": "0.5.0-alpha.4" + } +} diff --git a/internal-packages/tsql/src/grammar/TSQLLexer.common.g4 b/internal-packages/tsql/src/grammar/TSQLLexer.common.g4 new file mode 100644 index 000000000..7988b54eb --- /dev/null +++ b/internal-packages/tsql/src/grammar/TSQLLexer.common.g4 @@ -0,0 +1,288 @@ +lexer grammar TSQLLexer; + +// NB! We cat TSQLLexter.typescript.g4 when generating the grammar. + +// NOTE: don't forget to add new keywords to the parser rule "keyword"! + +// Keywords + +ALL: A L L; +AND: A N D; +ANTI: A N T I; +ANY: A N Y; +ARRAY: A R R A Y; +AS: A S; +ASCENDING: A S C | A S C E N D I N G; +ASOF: A S O F; +BETWEEN: B E T W E E N; +BOTH: B O T H; +BY: B Y; +CASE: C A S E; +CAST: C A S T; +CATCH: C A T C H; +COHORT: C O H O R T; +COLLATE: C O L L A T E; +CROSS: C R O S S; +CUBE: C U B E; +CURRENT: C U R R E N T; +DATE: D A T E; +DAY: D A Y; +DESC: D E S C; +DESCENDING: D E S C E N D I N G; +DISTINCT: D I S T I N C T; +ELSE: E L S E; +END: E N D; +EXCEPT: E X C E P T; +EXTRACT: E X T R A C T; +FINAL: F I N A L; +FINALLY: F I N A L L Y; +FIRST: F I R S T; +FN: F N; +FOLLOWING: F O L L O W I N G; +FOR: F O R; +FROM: F R O M; +FULL: F U L L; +FUN: F U N; +GROUP: G R O U P; +HAVING: H A V I N G; +HOUR: H O U R; +ID: I D; +IF: I F; +ILIKE: I L I K E; +IN: I N; +INF: I N F | I N F I N I T Y; +INNER: I N N E R; +INTERSECT: I N T E R S E C T; +INTERVAL: I N T E R V A L; +IS: I S; +JOIN: J O I N; +KEY: K E Y; +LAST: L A S T; +LEADING: L E A D I N G; +LEFT: L E F T; +LET: L E T; +LIKE: L I K E; +LIMIT: L I M I T; +MINUTE: M I N U T E; +MONTH: M O N T H; +NAN_SQL: N A N; // conflicts with macro NAN +NOT: N O T; +NULL_SQL: N U L L; // conflicts with macro NULL +NULLS: N U L L S; +OFFSET: O F F S E T; +ON: O N; +OR: O R; +ORDER: O R D E R; +OUTER: O U T E R; +OVER: O V E R; +PARTITION: P A R T I T I O N; +PRECEDING: P R E C E D I N G; +PREWHERE: P R E W H E R E; +QUARTER: Q U A R T E R; +RANGE: R A N G E; +RETURN: R E T U R N; +RIGHT: R I G H T; +ROLLUP: R O L L U P; +ROW: R O W; +ROWS: R O W S; +SAMPLE: S A M P L E; +SECOND: S E C O N D; +SELECT: S E L E C T; +SEMI: S E M I; +SETTINGS: S E T T I N G S; +SUBSTRING: S U B S T R I N G; +THEN: T H E N; +THROW: T H R O W; +TIES: T I E S; +TIMESTAMP: T I M E S T A M P; +TO: T O; +TOP: T O P; +TOTALS: T O T A L S; +TRAILING: T R A I L I N G; +TRIM: T R I M; +TRUNCATE: T R U N C A T E; +TRY: T R Y; +UNBOUNDED: U N B O U N D E D; +UNION: U N I O N; +USING: U S I N G; +WEEK: W E E K; +WHEN: W H E N; +WHERE: W H E R E; +WHILE: W H I L E; +WINDOW: W I N D O W; +WITH: W I T H; +YEAR: Y E A R | Y Y Y Y; + +// Tokens + +// copied from clickhouse_driver/util/escape.py +ESCAPE_CHAR_COMMON + : BACKSLASH B + | BACKSLASH F + | BACKSLASH R + | BACKSLASH N + | BACKSLASH T + | BACKSLASH '0' + | BACKSLASH A + | BACKSLASH V + | BACKSLASH BACKSLASH; + +IDENTIFIER + : (LETTER | UNDERSCORE | DOLLAR) (LETTER | UNDERSCORE | DEC_DIGIT | DOLLAR)* + | BACKQUOTE ( ~([\\`]) | ESCAPE_CHAR_COMMON | BACKSLASH QUOTE_SINGLE | (BACKQUOTE BACKQUOTE) )* BACKQUOTE + | QUOTE_DOUBLE ( ~([\\"]) | ESCAPE_CHAR_COMMON | BACKSLASH QUOTE_DOUBLE | (QUOTE_DOUBLE QUOTE_DOUBLE) )* QUOTE_DOUBLE + ; +FLOATING_LITERAL + : HEXADECIMAL_LITERAL DOT HEX_DIGIT* (P | E) (PLUS | DASH)? DEC_DIGIT+ + | HEXADECIMAL_LITERAL (P | E) (PLUS | DASH)? DEC_DIGIT+ + | DECIMAL_LITERAL DOT DEC_DIGIT* E (PLUS | DASH)? DEC_DIGIT+ + | DOT DECIMAL_LITERAL E (PLUS | DASH)? DEC_DIGIT+ + | DECIMAL_LITERAL E (PLUS | DASH)? DEC_DIGIT+ + ; +OCTAL_LITERAL: '0' OCT_DIGIT+; +DECIMAL_LITERAL: DEC_DIGIT+; +HEXADECIMAL_LITERAL: '0' X HEX_DIGIT+; + +// It's important that quote-symbol is a single character. +STRING_LITERAL: QUOTE_SINGLE ( ~([\\']) | ESCAPE_CHAR_COMMON | BACKSLASH QUOTE_SINGLE | (QUOTE_SINGLE QUOTE_SINGLE) )* QUOTE_SINGLE; + + +// Alphabet and allowed symbols + +fragment A: [aA]; +fragment B: [bB]; +fragment C: [cC]; +fragment D: [dD]; +fragment E: [eE]; +fragment F: [fF]; +fragment G: [gG]; +fragment H: [hH]; +fragment I: [iI]; +fragment J: [jJ]; +fragment K: [kK]; +fragment L: [lL]; +fragment M: [mM]; +fragment N: [nN]; +fragment O: [oO]; +fragment P: [pP]; +fragment Q: [qQ]; +fragment R: [rR]; +fragment S: [sS]; +fragment T: [tT]; +fragment U: [uU]; +fragment V: [vV]; +fragment W: [wW]; +fragment X: [xX]; +fragment Y: [yY]; +fragment Z: [zZ]; + +fragment LETTER: [a-zA-Z]; +fragment OCT_DIGIT: [0-7]; +fragment DEC_DIGIT: [0-9]; +fragment HEX_DIGIT: [0-9a-fA-F]; + +ARROW: '->'; +ASTERISK: '*'; +BACKQUOTE: '`'; +BACKSLASH: '\\'; +COLON: ':'; +COMMA: ','; +CONCAT: '||'; +DASH: '-'; +DOLLAR: '$'; +DOT: '.'; +EQ_DOUBLE: '=='; +EQ_SINGLE: '='; +GT_EQ: '>='; +GT: '>'; +HASH: '#'; +IREGEX_SINGLE: '~*'; +IREGEX_DOUBLE: '=~*'; +LBRACE: '{' -> pushMode(DEFAULT_MODE); +LBRACKET: '['; +LPAREN: '('; +LT_EQ: '<='; +TAG_LT_SLASH: ' type(LT_SLASH), pushMode(TSQLX_TAG_CLOSE); +TAG_LT_OPEN: '<' {isOpeningTag()}? -> type(LT), pushMode(TSQLX_TAG_OPEN); +LT: '<'; +LT_SLASH: ''; +NOT_IREGEX: '!~*'; +NOT_REGEX: '!~'; +NULL_PROPERTY: '?.'; +NULLISH: '??'; +PERCENT: '%'; +PLUS: '+'; +QUERY: '?'; +QUOTE_DOUBLE: '"'; +QUOTE_SINGLE_TEMPLATE: 'f\'' -> pushMode(IN_TEMPLATE_STRING); // start of regular f'' template strings +QUOTE_SINGLE_TEMPLATE_FULL: 'F\'' -> pushMode(IN_FULL_TEMPLATE_STRING); // magic F' symbol used to parse "full text" templates +QUOTE_SINGLE: '\''; +REGEX_SINGLE: '~'; +REGEX_DOUBLE: '=~'; +RBRACE: '}' -> popMode; +RBRACKET: ']'; +RPAREN: ')'; +SEMICOLON: ';'; +SLASH: '/'; +SLASH_GT: '/>'; +UNDERSCORE: '_'; + +// Comments and whitespace +MULTI_LINE_COMMENT: '/*' .*? '*/' -> skip; +SINGLE_LINE_COMMENT: ('--' | '//') ~('\n'|'\r')* ('\n' | '\r' | EOF) -> skip; +// whitespace is hidden and not skipped so that it's preserved in ANTLR errors like "no viable alternative" +WHITESPACE: [ \u000B\u000C\t\r\n] -> channel(HIDDEN); + +// ───────── f' TEMPLATE STRING MODE ───────── +mode IN_TEMPLATE_STRING; +STRING_TEXT: ((~([\\'{])) | ESCAPE_CHAR_COMMON | BACKSLASH QUOTE_SINGLE | (BACKSLASH LBRACE) | (QUOTE_SINGLE QUOTE_SINGLE))+; +STRING_ESCAPE_TRIGGER: LBRACE -> pushMode(DEFAULT_MODE); +STRING_QUOTE_SINGLE: QUOTE_SINGLE -> type(QUOTE_SINGLE), popMode; + +// ───────── F' FULL TEMPLATE STRING MODE ───────── +// a magic F' takes us to "full template strings" mode, where we don't need to escape single quotes and parse until EOF +// this can't be used within a normal columnExpr, but has to be parsed for separately +mode IN_FULL_TEMPLATE_STRING; +FULL_STRING_TEXT: ((~([{])) | ESCAPE_CHAR_COMMON | (BACKSLASH LBRACE))+; +FULL_STRING_ESCAPE_TRIGGER: LBRACE -> pushMode(DEFAULT_MODE); + +// ───────── TSQLX TAG MODE for opening/self-closing tags ───────── +mode TSQLX_TAG_OPEN; + +TAG_SELF_CLOSE_GT : '/>' -> type(SLASH_GT), popMode; // +TAG_OPEN_GT : '>' -> type(GT), popMode, pushMode(TSQLX_TEXT); // + +// minimal token set; map everything back to the default token types +TAG_IDENT : [a-zA-Z_][a-zA-Z0-9_-]* -> type(IDENTIFIER); +TAG_EQ : '=' -> type(EQ_SINGLE); +TAG_STRING : STRING_LITERAL -> type(STRING_LITERAL); +TAG_WS : [ \t\r\n]+ -> channel(HIDDEN); +TAG_LBRACE : '{' -> type(LBRACE), pushMode(DEFAULT_MODE); + + +// ───────── TSQLX TAG MODE for closing tags ───────── +mode TSQLX_TAG_CLOSE; + +TAGC_GT : '>' -> type(GT), popMode; // *** no TEXT push *** +TAGC_IDENT : [a-zA-Z_][a-zA-Z0-9_-]* -> type(IDENTIFIER); +TAGC_WS : [ \t\r\n]+ -> channel(HIDDEN); + + +// ───────── TSQLX TEXT MODE ───────── +mode TSQLX_TEXT; + +TSQLX_TEXT_TEXT + : ~[<{]+ ; // everything except “{” or “<” + +TSQLX_TEXT_LBRACE + : '{' -> type(LBRACE), pushMode(DEFAULT_MODE); + +TSQLX_TEXT_LT_SLASH + : ' type(LT_SLASH), popMode, pushMode(TSQLX_TAG_CLOSE); + +TSQLX_TEXT_LT + : '<' -> type(LT), pushMode(TSQLX_TAG_OPEN); + +TSQLX_TEXT_WS + : [ \t\r\n]+ -> channel(HIDDEN); diff --git a/internal-packages/tsql/src/grammar/TSQLLexer.typescript.g4 b/internal-packages/tsql/src/grammar/TSQLLexer.typescript.g4 new file mode 100644 index 000000000..f09eb2aaa --- /dev/null +++ b/internal-packages/tsql/src/grammar/TSQLLexer.typescript.g4 @@ -0,0 +1,81 @@ +lexer grammar TSQLLexer; + +@header { +// put any global imports you need here +} + +@members { + +private _peekChar(k: number): string { + // Return the k-th look-ahead as a *single-char string* or '\0' at EOF. + const c = this._input.LA(k); // int code point or IntStream.EOF (-1) + if (c < 0 || c > 0x10FFFF) { // EOF or out-of-range → sentinel + return '\0'; + } + return String.fromCharCode(c); +} + +private _skipWsAndComments(idx: number): number { + // Return the first index ≥ idx that is *not* whitespace / single-line comment. + while (true) { + const ch = this._peekChar(idx); + if (/\s/.test(ch)) { // spaces, newlines, tabs … + idx++; + continue; + } + + // single-line comments + if (ch === '/' && this._peekChar(idx + 1) === '/') { // // + idx += 2; + } else if (ch === '-' && this._peekChar(idx + 1) === '-') { // -- + idx += 2; + } else if (ch === '#') { // # + idx++; + } else { + break; // no ws / comment + } + // consume until EOL / EOF + while (!['\0', '\n', '\r'].includes(this._peekChar(idx))) { + idx++; + } + } + return idx; +} + +// ───── opening tag test ───── +isOpeningTag(): boolean { + const ch1 = this._peekChar(1); + if (!(/[a-zA-Z]/.test(ch1) || ch1 === '_')) { + return false; // not a tag name start + } + + // skip tag name + let i = 2; + while (true) { + const ch = this._peekChar(i); + if (/[a-zA-Z0-9]/.test(ch) || ch === '_' || ch === '-') { + i++; + } else { + break; + } + } + + let ch = this._peekChar(i); + + // immediate delimiter → tag + if (ch === '>' || ch === '/') { + return true; + } + + // need to look beyond whitespace + if (/\s/.test(ch)) { + i = this._skipWsAndComments(i + 1); + ch = this._peekChar(i); + return ch === '>' || ch === '/' || /[a-zA-Z0-9]/.test(ch) || ch === '_'; + } + + // anything else → not a tag + return false; +} + +} \ No newline at end of file diff --git a/internal-packages/tsql/src/grammar/TSQLParser.g4 b/internal-packages/tsql/src/grammar/TSQLParser.g4 new file mode 100644 index 000000000..6cade4e63 --- /dev/null +++ b/internal-packages/tsql/src/grammar/TSQLParser.g4 @@ -0,0 +1,317 @@ +parser grammar TSQLParser; + +options { + tokenVocab = TSQLLexer; +} + + +program: declaration* EOF; + +declaration: varDecl | statement ; + +expression: columnExpr; + +varDecl: LET identifier ( COLON EQ_SINGLE expression )? ; +identifierList: identifier (COMMA identifier)* COMMA?; + +statement : returnStmt + | throwStmt + | tryCatchStmt + | ifStmt + | whileStmt + | forInStmt + | forStmt + | funcStmt + | varAssignment + | block + | exprStmt + | emptyStmt + ; + +returnStmt : RETURN expression? SEMICOLON?; +throwStmt : THROW expression? SEMICOLON?; +catchBlock : CATCH (LPAREN catchVar=identifier (COLON catchType=identifier)? RPAREN)? catchStmt=block; +tryCatchStmt : TRY tryStmt=block catchBlock* (FINALLY finallyStmt=block)?; +ifStmt : IF LPAREN expression RPAREN statement ( ELSE statement )? ; +whileStmt : WHILE LPAREN expression RPAREN statement SEMICOLON?; +forStmt : FOR LPAREN + (initializerVarDeclr=varDecl | initializerVarAssignment=varAssignment | initializerExpression=expression)? SEMICOLON + condition=expression? SEMICOLON + (incrementVarDeclr=varDecl | incrementVarAssignment=varAssignment | incrementExpression=expression)? + RPAREN statement SEMICOLON?; +forInStmt : FOR LPAREN LET identifier (COMMA identifier)? IN expression RPAREN statement SEMICOLON?; +funcStmt : (FN | FUN) identifier LPAREN identifierList? RPAREN block; +varAssignment : expression COLON EQ_SINGLE expression ; +exprStmt : expression SEMICOLON?; +emptyStmt : SEMICOLON ; +block : LBRACE declaration* RBRACE ; + +kvPair: expression ':' expression ; +kvPairList: kvPair (COMMA kvPair)* COMMA?; + + +// SELECT statement +select: (selectSetStmt | selectStmt | TSQLxTagElement) SEMICOLON? EOF; + +selectStmtWithParens: selectStmt | LPAREN selectSetStmt RPAREN | placeholder; + +subsequentSelectSetClause: (EXCEPT | UNION ALL | UNION DISTINCT | INTERSECT | INTERSECT DISTINCT) selectStmtWithParens; +selectSetStmt: selectStmtWithParens (subsequentSelectSetClause)*; + +selectStmt: + with=withClause? + SELECT DISTINCT? topClause? + columns=columnExprList + from=fromClause? + arrayJoinClause? + prewhereClause? + where=whereClause? + groupByClause? (WITH (CUBE | ROLLUP))? (WITH TOTALS)? + havingClause? + windowClause? + orderByClause? + limitByClause? + (limitAndOffsetClause | offsetOnlyClause)? + settingsClause? + ; + +withClause: WITH withExprList; +topClause: TOP DECIMAL_LITERAL (WITH TIES)?; +fromClause: FROM joinExpr; +arrayJoinClause: (LEFT | INNER)? ARRAY JOIN columnExprList; +windowClause: WINDOW identifier AS LPAREN windowExpr RPAREN (COMMA identifier AS LPAREN windowExpr RPAREN)*; +prewhereClause: PREWHERE columnExpr; +whereClause: WHERE columnExpr; +groupByClause: GROUP BY ((CUBE | ROLLUP) LPAREN columnExprList RPAREN | columnExprList); +havingClause: HAVING columnExpr; +orderByClause: ORDER BY orderExprList; +projectionOrderByClause: ORDER BY columnExprList; +limitByClause: LIMIT limitExpr BY columnExprList; +limitAndOffsetClause + : LIMIT columnExpr (COMMA columnExpr)? (WITH TIES)? // compact OFFSET-optional form + | LIMIT columnExpr (WITH TIES)? OFFSET columnExpr // verbose OFFSET-included form with WITH TIES + ; +offsetOnlyClause: OFFSET columnExpr; +settingsClause: SETTINGS settingExprList; + +joinExpr + : joinExpr joinOp? JOIN joinExpr joinConstraintClause # JoinExprOp + | joinExpr joinOpCross joinExpr # JoinExprCrossOp + | tableExpr FINAL? sampleClause? # JoinExprTable + | LPAREN joinExpr RPAREN # JoinExprParens + ; +joinOp + : ((ALL | ANY | ASOF)? INNER | INNER (ALL | ANY | ASOF)? | (ALL | ANY | ASOF)) # JoinOpInner + | ( (SEMI | ALL | ANTI | ANY | ASOF)? (LEFT | RIGHT) OUTER? + | (LEFT | RIGHT) OUTER? (SEMI | ALL | ANTI | ANY | ASOF)? + ) # JoinOpLeftRight + | ((ALL | ANY)? FULL OUTER? | FULL OUTER? (ALL | ANY)?) # JoinOpFull + ; +joinOpCross + : CROSS JOIN + | COMMA + ; +joinConstraintClause + : ON columnExprList + | USING LPAREN columnExprList RPAREN + | USING columnExprList + ; + +sampleClause: SAMPLE ratioExpr (OFFSET ratioExpr)?; +limitExpr: columnExpr ((COMMA | OFFSET) columnExpr)?; +orderExprList: orderExpr (COMMA orderExpr)*; +orderExpr: columnExpr (ASCENDING | DESCENDING | DESC)? (NULLS (FIRST | LAST))? (COLLATE STRING_LITERAL)?; +ratioExpr: placeholder | numberLiteral (SLASH numberLiteral)?; +settingExprList: settingExpr (COMMA settingExpr)*; +settingExpr: identifier EQ_SINGLE literal; + +windowExpr: winPartitionByClause? winOrderByClause? winFrameClause?; +winPartitionByClause: PARTITION BY columnExprList; +winOrderByClause: ORDER BY orderExprList; +winFrameClause: (ROWS | RANGE) winFrameExtend; +winFrameExtend + : winFrameBound # frameStart + | BETWEEN winFrameBound AND winFrameBound # frameBetween + ; +winFrameBound: (CURRENT ROW | UNBOUNDED PRECEDING | UNBOUNDED FOLLOWING | numberLiteral PRECEDING | numberLiteral FOLLOWING); +//rangeClause: RANGE LPAREN (MIN identifier MAX identifier | MAX identifier MIN identifier) RPAREN; + +// Columns +expr: columnExpr EOF; +columnTypeExpr + : identifier # ColumnTypeExprSimple // UInt64 + | identifier LPAREN identifier columnTypeExpr (COMMA identifier columnTypeExpr)* COMMA? RPAREN # ColumnTypeExprNested // Nested + | identifier LPAREN enumValue (COMMA enumValue)* COMMA? RPAREN # ColumnTypeExprEnum // Enum + | identifier LPAREN columnTypeExpr (COMMA columnTypeExpr)* COMMA? RPAREN # ColumnTypeExprComplex // Array, Tuple + | identifier LPAREN columnExprList? RPAREN # ColumnTypeExprParam // FixedString(N) + ; +columnExprList: columnExpr (COMMA columnExpr)* COMMA?; +columnExpr + : CASE caseExpr=columnExpr? (WHEN whenExpr=columnExpr THEN thenExpr=columnExpr)+ (ELSE elseExpr=columnExpr)? END # ColumnExprCase + | CAST LPAREN columnExpr AS columnTypeExpr RPAREN # ColumnExprCast + | DATE STRING_LITERAL # ColumnExprDate +// | EXTRACT LPAREN interval FROM columnExpr RPAREN # ColumnExprExtract // Interferes with a function call + | INTERVAL STRING_LITERAL # ColumnExprIntervalString + | INTERVAL columnExpr interval # ColumnExprInterval + | SUBSTRING LPAREN columnExpr FROM columnExpr (FOR columnExpr)? RPAREN # ColumnExprSubstring + | TIMESTAMP STRING_LITERAL # ColumnExprTimestamp + | TRIM LPAREN (BOTH | LEADING | TRAILING) string FROM columnExpr RPAREN # ColumnExprTrim + | identifier (LPAREN columnExprs=columnExprList? RPAREN) (LPAREN DISTINCT? columnArgList=columnExprList? RPAREN)? OVER LPAREN windowExpr RPAREN # ColumnExprWinFunction + | identifier (LPAREN columnExprs=columnExprList? RPAREN) (LPAREN DISTINCT? columnArgList=columnExprList? RPAREN)? OVER identifier # ColumnExprWinFunctionTarget + | identifier (LPAREN columnExprs=columnExprList? RPAREN)? LPAREN DISTINCT? columnArgList=columnExprList? RPAREN # ColumnExprFunction + | columnExpr LPAREN selectSetStmt RPAREN # ColumnExprCallSelect + | columnExpr LPAREN columnExprList? RPAREN # ColumnExprCall + | TSQLxTagElement # ColumnExprTagElement + | templateString # ColumnExprTemplateString + | literal # ColumnExprLiteral + + // FIXME(ilezhankin): this part looks very ugly, maybe there is another way to express it + | columnExpr LBRACKET columnExpr RBRACKET # ColumnExprArrayAccess + | columnExpr DOT DECIMAL_LITERAL # ColumnExprTupleAccess + | columnExpr DOT identifier # ColumnExprPropertyAccess + | columnExpr NULL_PROPERTY LBRACKET columnExpr RBRACKET # ColumnExprNullArrayAccess + | columnExpr NULL_PROPERTY DECIMAL_LITERAL # ColumnExprNullTupleAccess + | columnExpr NULL_PROPERTY identifier # ColumnExprNullPropertyAccess + | DASH columnExpr # ColumnExprNegate + | left=columnExpr ( operator=ASTERISK // * + | operator=SLASH // / + | operator=PERCENT // % + ) right=columnExpr # ColumnExprPrecedence1 + | left=columnExpr ( operator=PLUS // + + | operator=DASH // - + | operator=CONCAT // || + ) right=columnExpr # ColumnExprPrecedence2 + | left=columnExpr ( operator=EQ_DOUBLE // = + | operator=EQ_SINGLE // == + | operator=NOT_EQ // != + | operator=LT_EQ // <= + | operator=LT // < + | operator=GT_EQ // >= + | operator=GT // > + | operator=NOT? IN COHORT? // in, not in; in cohort; not in cohort + | operator=NOT? (LIKE | ILIKE) // like, not like, ilike, not ilike + | operator=REGEX_SINGLE // ~ + | operator=REGEX_DOUBLE // =~ + | operator=NOT_REGEX // !~ + | operator=IREGEX_SINGLE // ~* + | operator=IREGEX_DOUBLE // =~* + | operator=NOT_IREGEX // !~* + ) right=columnExpr # ColumnExprPrecedence3 + | columnExpr IS NOT? NULL_SQL # ColumnExprIsNull + | columnExpr NULLISH columnExpr # ColumnExprNullish + | NOT columnExpr # ColumnExprNot + | columnExpr AND columnExpr # ColumnExprAnd + | columnExpr OR columnExpr # ColumnExprOr + // TODO(ilezhankin): `BETWEEN a AND b AND c` is parsed in a wrong way: `BETWEEN (a AND b) AND c` + | columnExpr NOT? BETWEEN columnExpr AND columnExpr # ColumnExprBetween + | columnExpr QUERY columnExpr COLON columnExpr # ColumnExprTernaryOp + | columnExpr (AS identifier | AS STRING_LITERAL) # ColumnExprAlias + | (tableIdentifier DOT)? ASTERISK # ColumnExprAsterisk // single-column only + | LPAREN selectSetStmt RPAREN # ColumnExprSubquery // single-column only + | LPAREN columnExpr RPAREN # ColumnExprParens // single-column only + | LPAREN columnExprList RPAREN # ColumnExprTuple + | LBRACKET columnExprList? RBRACKET # ColumnExprArray + | LBRACE (kvPairList)? RBRACE # ColumnExprDict + | columnLambdaExpr # ColumnExprLambda + | columnIdentifier # ColumnExprIdentifier + ; + +columnLambdaExpr: + ( LPAREN identifier (COMMA identifier)* COMMA? RPAREN + | identifier (COMMA identifier)* COMMA? + | LPAREN RPAREN + ) + ARROW (columnExpr | block) + ; + +TSQLxChildElement + : TSQLxTagElement + | TSQLxText + | LBRACE columnExpr RBRACE; + +TSQLxText : TSQLX_TEXT_TEXT ; + +TSQLxTagElement + : LT identifier TSQLxTagAttribute* SLASH_GT + | LT identifier TSQLxTagAttribute* GT TSQLxChildElement* LT_SLASH identifier GT + ; +TSQLxTagAttribute + : identifier EQ_SINGLE string + | identifier EQ_SINGLE LBRACE columnExpr RBRACE + | identifier + ; + +withExprList: withExpr (COMMA withExpr)* COMMA?; +withExpr + : identifier AS LPAREN selectSetStmt RPAREN # WithExprSubquery + // NOTE: asterisk and subquery goes before |columnExpr| so that we can mark them as multi-column expressions. + | columnExpr AS identifier # WithExprColumn + ; + + +// This is slightly different in TSQL compared to ClickHouse SQL +// TSQL allows unlimited ("*") nestedIdentifier-s "properties.b.a.a.w.a.s". +// We parse and convert "databaseIdentifier.tableIdentifier.columnIdentifier.nestedIdentifier.*" +// to just one ast.Field(chain=['a','b','columnIdentifier','on','and','on']). +columnIdentifier: placeholder | ((tableIdentifier DOT)? nestedIdentifier); +nestedIdentifier: identifier (DOT identifier)*; +tableExpr + : tableIdentifier # TableExprIdentifier + | tableFunctionExpr # TableExprFunction + | LPAREN selectSetStmt RPAREN # TableExprSubquery + | tableExpr (alias | AS identifier) # TableExprAlias + | TSQLxTagElement # TableExprTag + | placeholder # TableExprPlaceholder + ; +tableFunctionExpr: identifier LPAREN tableArgList? RPAREN; +tableIdentifier: (databaseIdentifier DOT)? nestedIdentifier; +tableArgList: columnExpr (COMMA columnExpr)* COMMA?; + +// Databases + +databaseIdentifier: identifier; + +// Basics + +floatingLiteral + : FLOATING_LITERAL + | DOT (DECIMAL_LITERAL | OCTAL_LITERAL) + | DECIMAL_LITERAL DOT (DECIMAL_LITERAL | OCTAL_LITERAL)? // can't move this to the lexer or it will break nested tuple access: t.1.2 + ; +numberLiteral: (PLUS | DASH)? (floatingLiteral | OCTAL_LITERAL | DECIMAL_LITERAL | HEXADECIMAL_LITERAL | INF | NAN_SQL); +literal + : numberLiteral + | STRING_LITERAL + | NULL_SQL + ; +interval: SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | QUARTER | YEAR; +keyword + // except NULL_SQL, INF, NAN_SQL + : ALL | AND | ANTI | ANY | ARRAY | AS | ASCENDING | ASOF | BETWEEN | BOTH | BY | CASE + | CAST | COHORT | COLLATE | CROSS | CUBE | CURRENT | DATE | DESC | DESCENDING + | DISTINCT | ELSE | END | EXTRACT | FINAL | FIRST + | FOR | FOLLOWING | FROM | FULL | GROUP | HAVING | ID | IS + | IF | ILIKE | IN | INNER | INTERVAL | JOIN | KEY + | LAST | LEADING | LEFT | LIKE | LIMIT + | NOT | NULLS | OFFSET | ON | OR | ORDER | OUTER | OVER | PARTITION + | PRECEDING | PREWHERE | RANGE | RETURN | RIGHT | ROLLUP | ROW + | ROWS | SAMPLE | SELECT | SEMI | SETTINGS | SUBSTRING + | THEN | TIES | TIMESTAMP | TOTALS | TRAILING | TRIM | TRUNCATE | TO | TOP + | UNBOUNDED | UNION | USING | WHEN | WHERE | WINDOW | WITH + ; +keywordForAlias + : DATE | FIRST | ID | KEY + ; +alias: IDENTIFIER | keywordForAlias; // |interval| can't be an alias, otherwise 'INTERVAL 1 SOMETHING' becomes ambiguous. +identifier: IDENTIFIER | interval | keyword; +enumValue: string EQ_SINGLE numberLiteral; +placeholder: LBRACE columnExpr RBRACE; + +string: STRING_LITERAL | templateString; +templateString : QUOTE_SINGLE_TEMPLATE stringContents* QUOTE_SINGLE ; +stringContents : STRING_ESCAPE_TRIGGER columnExpr RBRACE | STRING_TEXT; + +// These are magic "full template strings", which are used to parse "full text field" templates without the surrounding SQL. +// We will need to add F' to the start of the string to change the lexer's mode. +fullTemplateString: QUOTE_SINGLE_TEMPLATE_FULL stringContentsFull* EOF ; +stringContentsFull : FULL_STRING_ESCAPE_TRIGGER columnExpr RBRACE | FULL_STRING_TEXT; \ No newline at end of file diff --git a/internal-packages/tsql/src/index.ts b/internal-packages/tsql/src/index.ts new file mode 100644 index 000000000..6580918fb --- /dev/null +++ b/internal-packages/tsql/src/index.ts @@ -0,0 +1 @@ +import { Logger } from "@trigger.dev/core/logger"; diff --git a/internal-packages/tsql/tsconfig.json b/internal-packages/tsql/tsconfig.json new file mode 100644 index 000000000..010433962 --- /dev/null +++ b/internal-packages/tsql/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2019", + "lib": ["ES2019", "DOM", "DOM.Iterable", "DOM.AsyncIterable"], + "module": "Node16", + "moduleResolution": "Node16", + "moduleDetection": "force", + "verbatimModuleSyntax": false, + "types": ["vitest/globals"], + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "preserveWatchOutput": true, + "skipLibCheck": true, + "noEmit": true, + "strict": true, + "paths": { + "@trigger.dev/core": ["../../packages/core/src/index"], + "@trigger.dev/core/*": ["../../packages/core/src/*"] + } + }, + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6fa66945d..ce2bde953 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -695,10 +695,28 @@ importers: version: 2.0.2(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))) remix-auth-github: specifier: ^1.6.0 +<<<<<<< ours version: 1.6.0(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))) +||||||| ancestor + version: 1.6.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))) +======= +<<<<<<< ours + version: 1.6.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))) +>>>>>>> theirs remix-auth-google: specifier: ^2.0.0 +<<<<<<< ours version: 2.0.0(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))) +||||||| ancestor + version: 2.0.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))) +======= + version: 2.0.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))) +||||||| ancestor + version: 1.6.0(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))) +======= + version: 1.6.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))) +>>>>>>> theirs +>>>>>>> theirs remix-typedjson: specifier: 0.3.1 version: 0.3.1(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(react@18.2.0) @@ -1263,6 +1281,16 @@ importers: specifier: workspace:* version: link:../../packages/core + internal-packages/tsql: + dependencies: + '@trigger.dev/core': + specifier: workspace:* + version: link:../../packages/core + devDependencies: + antlr4ts: + specifier: 0.5.0-alpha.4 + version: 0.5.0-alpha.4 + internal-packages/zod-worker: dependencies: '@internal/tracing': @@ -5788,6 +5816,7 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] +<<<<<<< ours libc: [glibc] '@next/swc-linux-arm64-gnu@15.4.8': @@ -5796,6 +5825,10 @@ packages: cpu: [arm64] os: [linux] libc: [glibc] +||||||| ancestor +======= + libc: [glibc] +>>>>>>> theirs '@next/swc-linux-arm64-gnu@15.5.6': resolution: {integrity: sha512-qvz4SVKQ0P3/Im9zcS2RmfFL/UCQnsJKJwQSkissbngnB/12c6bZTCB0gHTexz1s6d/mD0+egPKXAIRFVS7hQg==} @@ -5823,6 +5856,7 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] +<<<<<<< ours libc: [musl] '@next/swc-linux-arm64-musl@15.4.8': @@ -5831,6 +5865,10 @@ packages: cpu: [arm64] os: [linux] libc: [musl] +||||||| ancestor +======= + libc: [musl] +>>>>>>> theirs '@next/swc-linux-arm64-musl@15.5.6': resolution: {integrity: sha512-FsbGVw3SJz1hZlvnWD+T6GFgV9/NYDeLTNQB2MXoPN5u9VA9OEDy6fJEfePfsUKAhJufFbZLgp0cPxMuV6SV0w==} @@ -5858,6 +5896,7 @@ packages: engines: {node: '>= 10'} cpu: [x64] os: [linux] +<<<<<<< ours libc: [glibc] '@next/swc-linux-x64-gnu@15.4.8': @@ -5866,6 +5905,10 @@ packages: cpu: [x64] os: [linux] libc: [glibc] +||||||| ancestor +======= + libc: [glibc] +>>>>>>> theirs '@next/swc-linux-x64-gnu@15.5.6': resolution: {integrity: sha512-3QnHGFWlnvAgyxFxt2Ny8PTpXtQD7kVEeaFat5oPAHHI192WKYB+VIKZijtHLGdBBvc16tiAkPTDmQNOQ0dyrA==} @@ -5893,6 +5936,7 @@ packages: engines: {node: '>= 10'} cpu: [x64] os: [linux] +<<<<<<< ours libc: [musl] '@next/swc-linux-x64-musl@15.4.8': @@ -5901,6 +5945,10 @@ packages: cpu: [x64] os: [linux] libc: [musl] +||||||| ancestor +======= + libc: [musl] +>>>>>>> theirs '@next/swc-linux-x64-musl@15.5.6': resolution: {integrity: sha512-OsGX148sL+TqMK9YFaPFPoIaJKbFJJxFzkXZljIgA9hjMjdruKht6xDCEv1HLtlLNfkx3c5w2GLKhj7veBQizQ==} @@ -9415,11 +9463,16 @@ packages: '@smithy/core@3.18.3': resolution: {integrity: sha512-qqpNskkbHOSfrbFbjhYj5o8VMXO26fvN1K/+HbCzUNlTuxgNcPRouUDNm+7D6CkN244WG7aK533Ne18UtJEgAA==} engines: {node: '>=18.0.0'} +<<<<<<< ours deprecated: Please upgrade your lockfile to use the latest 3.x version of @smithy/core for various fixes, see https://github.com/smithy-lang/smithy-typescript/blob/main/packages/core/CHANGELOG.md '@smithy/core@3.18.5': resolution: {integrity: sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw==} engines: {node: '>=18.0.0'} +||||||| ancestor +======= + deprecated: Please upgrade your lockfile to use the latest 3.x version of @smithy/core for various fixes, see https://github.com/smithy-lang/smithy-typescript/blob/main/packages/core/CHANGELOG.md +>>>>>>> theirs '@smithy/core@3.6.0': resolution: {integrity: sha512-Pgvfb+TQ4wUNLyHzvgCP4aYZMh16y7GcfF59oirRHcgGgkH1e/s9C0nv/v3WP+Quymyr5je71HeFQCwh+44XLg==} @@ -11366,6 +11419,9 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + antlr4ts@0.5.0-alpha.4: + resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -28968,14 +29024,32 @@ snapshots: '@rushstack/eslint-patch@1.2.0': {} +<<<<<<< ours '@s2-dev/streamstore@0.17.3(typescript@5.9.3)': +||||||| ancestor + '@s2-dev/streamstore@0.17.3(typescript@5.5.4)': +======= +<<<<<<< ours + '@s2-dev/streamstore@0.17.3(typescript@5.5.4)': +>>>>>>> theirs dependencies: '@protobuf-ts/runtime': 2.11.1 typescript: 5.9.3 '@s2-dev/streamstore@0.17.6': +||||||| ancestor + '@s2-dev/streamstore@0.17.3(typescript@5.9.3)': +======= + '@s2-dev/streamstore@0.17.3(typescript@5.5.4)': +>>>>>>> theirs dependencies: '@protobuf-ts/runtime': 2.11.1 +<<<<<<< ours +||||||| ancestor + typescript: 5.9.3 +======= + typescript: 5.5.4 +>>>>>>> theirs '@sec-ant/readable-stream@0.4.1': {} @@ -31798,6 +31872,8 @@ snapshots: ansi-styles@6.2.1: {} + antlr4ts@0.5.0-alpha.4: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -32753,6 +32829,41 @@ snapshots: dependencies: layout-base: 2.0.1 +<<<<<<< ours +||||||| ancestor + cosmiconfig@8.3.6(typescript@5.5.4): + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.1 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.5.4 + +======= +<<<<<<< ours + cosmiconfig@8.3.6(typescript@5.5.4): + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.1 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.5.4 + +||||||| ancestor +======= + cosmiconfig@8.3.6(typescript@5.5.4): + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.5.4 + +>>>>>>> theirs +>>>>>>> theirs cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.0 @@ -35039,6 +35150,58 @@ snapshots: transitivePeerDependencies: - supports-color +<<<<<<< ours +||||||| ancestor + graphile-worker@0.16.6(patch_hash=798129c99ed02177430fc90a1fdef800ec94e5fd1d491b931297dc52f4c98ab1)(typescript@5.5.4): + dependencies: + '@graphile/logger': 0.2.0 + '@types/debug': 4.1.12 + '@types/pg': 8.11.6 + cosmiconfig: 8.3.6(typescript@5.5.4) + graphile-config: 0.0.1-beta.8 + json5: 2.2.3 + pg: 8.11.5 + tslib: 2.6.2 + yargs: 17.7.2 + transitivePeerDependencies: + - pg-native + - supports-color + - typescript + +======= + graphile-worker@0.16.6(patch_hash=798129c99ed02177430fc90a1fdef800ec94e5fd1d491b931297dc52f4c98ab1)(typescript@5.5.4): + dependencies: + '@graphile/logger': 0.2.0 + '@types/debug': 4.1.12 + '@types/pg': 8.11.6 + cosmiconfig: 8.3.6(typescript@5.5.4) + graphile-config: 0.0.1-beta.8 + json5: 2.2.3 + pg: 8.11.5 + tslib: 2.6.2 + yargs: 17.7.2 + transitivePeerDependencies: + - pg-native + - supports-color + - typescript + + graphile-worker@0.16.6(patch_hash=798129c99ed02177430fc90a1fdef800ec94e5fd1d491b931297dc52f4c98ab1)(typescript@5.5.4): + dependencies: + '@graphile/logger': 0.2.0 + '@types/debug': 4.1.12 + '@types/pg': 8.11.6 + cosmiconfig: 8.3.6(typescript@5.5.4) + graphile-config: 0.0.1-beta.8 + json5: 2.2.3 + pg: 8.11.5 + tslib: 2.6.2 + yargs: 17.7.2 + transitivePeerDependencies: + - pg-native + - supports-color + - typescript + +>>>>>>> theirs graphile-worker@0.16.6(patch_hash=798129c99ed02177430fc90a1fdef800ec94e5fd1d491b931297dc52f4c98ab1)(typescript@5.9.3): dependencies: '@graphile/logger': 0.2.0 @@ -39431,11 +39594,34 @@ snapshots: transitivePeerDependencies: - supports-color +<<<<<<< ours remix-auth-google@2.0.0(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))): +||||||| ancestor + remix-auth-google@2.0.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))): +======= +<<<<<<< ours + remix-auth-google@2.0.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))): +||||||| ancestor + remix-auth-oauth2@1.11.0(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))): +======= + remix-auth-oauth2@1.11.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))): +>>>>>>> theirs +>>>>>>> theirs dependencies: +<<<<<<< ours '@remix-run/server-runtime': 2.1.0(typescript@5.9.3) remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3)) remix-auth-oauth2: 1.11.0(@remix-run/server-runtime@2.1.0(typescript@5.9.3))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3))) +||||||| ancestor + '@remix-run/server-runtime': 2.1.0(typescript@5.5.4) + remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4)) + remix-auth-oauth2: 1.11.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))) +======= +<<<<<<< ours + '@remix-run/server-runtime': 2.1.0(typescript@5.5.4) + remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4)) + remix-auth-oauth2: 1.11.0(@remix-run/server-runtime@2.1.0(typescript@5.5.4))(remix-auth@3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4))) +>>>>>>> theirs transitivePeerDependencies: - supports-color @@ -39443,7 +39629,22 @@ snapshots: dependencies: '@remix-run/server-runtime': 2.1.0(typescript@5.9.3) debug: 4.4.1(supports-color@10.0.0) +<<<<<<< ours remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3)) +||||||| ancestor + remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4)) +======= + remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4)) +||||||| ancestor + '@remix-run/server-runtime': 2.1.0(typescript@5.9.3) + debug: 4.4.0 + remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(@remix-run/server-runtime@2.1.0(typescript@5.9.3)) +======= + '@remix-run/server-runtime': 2.1.0(typescript@5.5.4) + debug: 4.4.0 + remix-auth: 3.6.0(@remix-run/react@2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4))(@remix-run/server-runtime@2.1.0(typescript@5.5.4)) +>>>>>>> theirs +>>>>>>> theirs transitivePeerDependencies: - supports-color @@ -41655,6 +41856,7 @@ snapshots: - supports-color - typescript +<<<<<<< ours vite-tsconfig-paths@4.0.5(typescript@5.9.3): dependencies: debug: 4.3.7(supports-color@10.0.0) @@ -41664,6 +41866,44 @@ snapshots: - supports-color - typescript +||||||| ancestor +======= +<<<<<<< ours +||||||| ancestor + vite-tsconfig-paths@4.0.5(typescript@5.9.3): + dependencies: + debug: 4.3.7(supports-color@10.0.0) + globrex: 0.1.2 + tsconfck: 2.1.2(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + - typescript + + vite@4.1.4(@types/node@20.14.14)(terser@5.44.1): + dependencies: + esbuild: 0.16.17 + postcss: 8.5.3 + resolve: 1.22.8 + rollup: 3.10.0 + optionalDependencies: + '@types/node': 20.14.14 + fsevents: 2.3.3 + terser: 5.44.1 + +======= + vite@4.1.4(@types/node@20.14.14)(terser@5.44.1): + dependencies: + esbuild: 0.16.17 + postcss: 8.5.3 + resolve: 1.22.8 + rollup: 3.10.0 + optionalDependencies: + '@types/node': 20.14.14 + fsevents: 2.3.3 + terser: 5.44.1 + +>>>>>>> theirs +>>>>>>> theirs vite@4.4.9(@types/node@22.13.9)(lightningcss@1.29.2)(terser@5.44.1): dependencies: esbuild: 0.18.11