Skip to content

Commit 4c75e83

Browse files
feat: add parameterized utility function
1 parent 5c847d9 commit 4c75e83

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

src/strings.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,4 +341,74 @@ export const emailDataToString = (
341341
searchParams.size > 0 && `?${ searchParams.toString().replace( /\+/g, ' ' ) }`,
342342
].filter( Boolean ).join( '' )
343343

344+
}
345+
346+
347+
/**
348+
* Represents a value that can be used as a parameter in string operations.
349+
*
350+
*/
351+
type ParameterizedValue = string | boolean | number | bigint
352+
353+
354+
/**
355+
* Represents a parameterized string with its corresponding values.
356+
*
357+
* @property {string} 0 - The template string
358+
* @property {ParameterizedValue[]} 1 - Array of values to be substituted into the template string
359+
*/
360+
type Parameterized = [ string, ParameterizedValue[] ]
361+
362+
363+
/**
364+
* Creates a parameterized query string with placeholder values.
365+
*
366+
* @param strings - The template string parts from a template literal.
367+
* @param values - One or more parameter values or arrays of values to be substituted into the template.
368+
* @returns A tuple containing the normalized query string with `?` placeholders and an array of parameter values.
369+
*
370+
* @example
371+
* ```ts
372+
* const [ query, params ] = parameterized`
373+
* SELECT * FROM users WHERE id = ${ 1 } AND status IN ( ${ [ 'active', 'pending' ] } )
374+
* ` )
375+
*
376+
* // query: "SELECT * FROM users WHERE id = ? AND status IN ( ?, ? )"
377+
* // params: [ 1, 'active', 'pending' ]
378+
* ```
379+
*
380+
* @remarks
381+
* - Whitespace is normalized (multiple spaces reduced to single space, trimmed).
382+
* - Undefined values are skipped.
383+
* - Array values are expanded into comma-separated placeholders.
384+
* - Single values are replaced with a single `?` placeholder.
385+
*/
386+
export const parameterized = ( strings: TemplateStringsArray, ...values: ( ParameterizedValue | ParameterizedValue[] )[] ): Parameterized => {
387+
388+
const params: ParameterizedValue[] = []
389+
let text = ''
390+
391+
strings.forEach( ( string, index ) => {
392+
text += string
393+
394+
if ( index >= values.length ) return
395+
396+
const value = values[ index ]
397+
398+
if ( typeof value === 'undefined' ) return
399+
400+
if ( Array.isArray( value ) ) {
401+
402+
const placeholders = value.map( () => '?' ).join( ', ' )
403+
text += placeholders
404+
params.push( ...value )
405+
return
406+
}
407+
408+
text += '?'
409+
params.push( value )
410+
411+
} )
412+
413+
return [ text.replace( /\s+/g, ' ' ).trim(), params ]
344414
}

0 commit comments

Comments
 (0)