@@ -8,17 +8,24 @@ import type { RefLeaf } from './types.js'
88 * JavaScript tries to coerce a RefProxy to a primitive value.
99 * This catches misuse like string concatenation, arithmetic, etc.
1010 */
11+ function getOperatorTypeFromHint ( hint : string ) : string {
12+ switch ( hint ) {
13+ case `number` :
14+ return `arithmetic`
15+ case `string` :
16+ return `string concatenation`
17+ default :
18+ return `comparison`
19+ }
20+ }
21+
1122function createToPrimitiveHandler (
1223 path : Array < string > ,
1324) : ( hint : string ) => never {
1425 return ( hint : string ) => {
1526 const pathStr = path . length > 0 ? path . join ( `.` ) : `<root>`
1627 throw new JavaScriptOperatorInQueryError (
17- hint === `number`
18- ? `arithmetic`
19- : hint === `string`
20- ? `string concatenation`
21- : `comparison` ,
28+ getOperatorTypeFromHint ( hint ) ,
2229 `Attempted to use "${ pathStr } " in a JavaScript ${ hint } context.\n` +
2330 `Query references can only be used with query functions, not JavaScript operators.` ,
2431 )
@@ -377,22 +384,31 @@ const JS_OPERATOR_PATTERNS: Array<{
377384 } ,
378385]
379386
387+ function getHintForOperator ( operator : string ) : string {
388+ switch ( operator ) {
389+ case `||` :
390+ case `??` :
391+ return `Use coalesce() instead: coalesce(value, defaultValue)`
392+ case `&&` :
393+ return `Use and() for logical conditions`
394+ case `?:` :
395+ return `Use cond() for conditional expressions: cond(condition, trueValue, falseValue)`
396+ default :
397+ return `Use the appropriate query function instead`
398+ }
399+ }
400+
380401/**
381402 * Removes string literals and comments from source code to avoid false positives
382403 * when checking for JavaScript operators.
383404 */
384405function stripStringsAndComments ( source : string ) : string {
385- // Remove template literals (backtick strings)
386- let result = source . replace ( / ` (?: [ ^ ` \\ ] | \\ .) * ` / g, `""` )
387- // Remove double-quoted strings
388- result = result . replace ( / " (?: [ ^ " \\ ] | \\ .) * " / g, `""` )
389- // Remove single-quoted strings
390- result = result . replace ( / ' (?: [ ^ ' \\ ] | \\ .) * ' / g, `""` )
391- // Remove single-line comments
392- result = result . replace ( / \/ \/ [ ^ \n ] * / g, `` )
393- // Remove multi-line comments
394- result = result . replace ( / \/ \* [ \s \S ] * ?\* \/ / g, `` )
395- return result
406+ return source
407+ . replace ( / ` (?: [ ^ ` \\ ] | \\ .) * ` / g, `""` ) // template literals
408+ . replace ( / " (?: [ ^ " \\ ] | \\ .) * " / g, `""` ) // double-quoted strings
409+ . replace ( / ' (?: [ ^ ' \\ ] | \\ .) * ' / g, `""` ) // single-quoted strings
410+ . replace ( / \/ \/ [ ^ \n ] * / g, `` ) // single-line comments
411+ . replace ( / \/ \* [ \s \S ] * ?\* \/ / g, `` ) // multi-line comments
396412}
397413
398414/**
@@ -427,15 +443,7 @@ export function checkCallbackForJsOperators<
427443
428444 for ( const { pattern, operator, description } of JS_OPERATOR_PATTERNS ) {
429445 if ( pattern . test ( cleanedSource ) ) {
430- const hint =
431- operator === `||` || operator === `??`
432- ? `Use coalesce() instead: coalesce(value, defaultValue)`
433- : operator === `&&`
434- ? `Use and() for logical conditions`
435- : operator === `?:`
436- ? `Use cond() for conditional expressions: cond(condition, trueValue, falseValue)`
437- : `Use the appropriate query function instead`
438-
446+ const hint = getHintForOperator ( operator )
439447 console . warn (
440448 `[TanStack DB] JavaScript operator "${ operator } " detected in query callback.\n\n` +
441449 `Found JavaScript ${ description } operator (${ operator } ) in query callback.\n` +
0 commit comments