@@ -2,11 +2,10 @@ import { execFile } from 'node:child_process';
22import crypto from 'node:crypto' ;
33import fs from 'node:fs/promises' ;
44import path from 'node:path' ;
5- import prettier from 'prettier ' ;
5+ import ts from 'typescript ' ;
66import util from 'util' ;
77import { generate_types , render_template } from './render.ts' ;
8- import type { Config , SqlcResult } from './types.ts' ;
9- import ts from 'typescript' ;
8+ import type { Config , SqlcResult , SqlQuery , SqlQueryParseResult } from './types.ts' ;
109
1110const execFileAsync = util . promisify ( execFile ) ;
1211
@@ -18,14 +17,14 @@ export const generate = async (config: Config) => {
1817 const exec_result = await exec_sqlc ( config ) ;
1918
2019 if ( exec_result . success ) {
21- const { queries_content , schema_types_content } = generate_types ( {
20+ const { rendered_queries , schema_types_content } = generate_types ( {
2221 sqlc_result : exec_result . result ,
2322 queries,
2423 config,
2524 } ) ;
2625
2726 await render_write ( {
28- queries_content ,
27+ rendered_queries ,
2928 schema_types_content,
3029 result_path : config . output ,
3130 config,
@@ -34,7 +33,10 @@ export const generate = async (config: Config) => {
3433 return { queries : queries . size } ;
3534 } else {
3635 await render_write ( {
37- queries_content : '// Unable to generate queries: ' + exec_result . result ,
36+ rendered_queries : {
37+ flat : '// Unable to generate queries: ' + exec_result . result ,
38+ nested : '// Unable to generate queries: ' + exec_result . result ,
39+ } ,
3840 result_path : config . output ,
3941 config,
4042 } ) ;
@@ -49,38 +51,26 @@ export const generate = async (config: Config) => {
4951} ;
5052
5153export const render_write = async ( {
52- queries_content ,
54+ rendered_queries ,
5355 schema_types_content,
5456 result_path,
5557 config,
5658} : {
57- queries_content : string ;
59+ rendered_queries : {
60+ flat : string ;
61+ nested : string ;
62+ } ;
5863 schema_types_content ?: string ;
5964 result_path : string ;
6065 config : Pick < Config , 'imports' > ;
6166} ) => {
6267 const file = render_template ( {
63- queries_content ,
68+ rendered_queries ,
6469 schema_types_content,
6570 imports : config . imports ,
6671 } ) ;
6772
68- const formatted = await prettier . format ( file , {
69- parser : 'typescript' ,
70- printWidth : 128 ,
71- tabWidth : 4 ,
72- useTabs : false ,
73- semi : true ,
74- singleQuote : true ,
75- jsxSingleQuote : true ,
76- trailingComma : 'all' ,
77- bracketSpacing : true ,
78- bracketSameLine : true ,
79- arrowParens : 'always' ,
80- endOfLine : 'lf' ,
81- } ) ;
82-
83- await fs . writeFile ( result_path , formatted ) ;
73+ await fs . writeFile ( result_path , file ) ;
8474} ;
8575
8676export const exec_sqlc = async ( { tmp_dir } : Pick < Config , 'tmp_dir' | 'root' > ) => {
@@ -154,22 +144,22 @@ export const prepare_tmp_dir = async ({ schema, tmp_dir }: Pick<Config, 'root' |
154144} ;
155145
156146export async function scan_files ( { root, include, tmp_dir } : Pick < Config , 'root' | 'include' | 'tmp_dir' > ) {
157- const queries = new Map < string , string > ( ) ;
147+ const queries = new Map < string , SqlQuery > ( ) ;
158148 const queries_file = await fs . open ( path . join ( tmp_dir , 'queries.sql' ) , 'w+' ) ;
159149
160150 try {
161151 for await ( const file of fs . glob ( include , { cwd : root } ) ) {
162152 const content = await fs . readFile ( path . join ( root , file ) , 'utf8' ) ;
163153
164- for ( const query of extract_sql ( content ) ) {
165- if ( query . success ) {
166- const { name, content } = render_query ( query . sql ) ;
154+ for ( const result of extract_sql ( content ) ) {
155+ if ( result . success ) {
156+ const { name, content } = render_query ( result . query . sql ) ;
167157 if ( ! queries . has ( name ) ) {
168158 await queries_file . appendFile ( `${ content } \n\n` ) ;
169- queries . set ( name , query . sql ) ;
159+ queries . set ( name , result . query ) ;
170160 }
171161 } else {
172- console . error ( query . error ) ;
162+ console . error ( result . error ) ;
173163 }
174164 }
175165 }
@@ -180,10 +170,8 @@ export async function scan_files({ root, include, tmp_dir }: Pick<Config, 'root'
180170 return queries ;
181171}
182172
183- type SqlResult = { success : true ; sql : string } | { success : false ; error : string } ;
184-
185- export const extract_sql = ( content : string ) : SqlResult [ ] => {
186- const results : SqlResult [ ] = [ ] ;
173+ export const extract_sql = ( content : string ) : SqlQueryParseResult [ ] => {
174+ const results : SqlQueryParseResult [ ] = [ ] ;
187175
188176 try {
189177 const sourceFile = ts . createSourceFile ( 'temp.ts' , content , ts . ScriptTarget . Latest , true ) ;
@@ -193,13 +181,13 @@ export const extract_sql = (content: string): SqlResult[] => {
193181 const identifier = node . expression ;
194182
195183 // Check if it's a call to 'sqlc'
196- if ( ts . isIdentifier ( identifier ) && identifier . text === 'sqlc' ) {
184+ if ( ts . isIdentifier ( identifier ) && ( identifier . text === 'sqlc' || identifier . text === 'sqln' ) ) {
197185 const arg = node . arguments [ 0 ] ;
198186
199187 if ( ! arg ) {
200188 results . push ( {
201189 success : false ,
202- error : `Missing argument in sqlc call at position ${ node . pos } ` ,
190+ error : `Missing argument in sqln call at position ${ node . pos } ` ,
203191 } ) ;
204192 return ;
205193 }
@@ -227,12 +215,24 @@ export const extract_sql = (content: string): SqlResult[] => {
227215 // Handle template literal
228216 if ( ts . isNoSubstitutionTemplateLiteral ( arg ) ) {
229217 query = arg . getText ( ) . slice ( 1 , - 1 ) ; // Remove backticks
230- results . push ( { success : true , sql : query } ) ;
218+ results . push ( {
219+ success : true ,
220+ query : {
221+ type : identifier . text === 'sqln' ? 'nested' : 'flat' ,
222+ sql : query ,
223+ } ,
224+ } ) ;
231225 }
232226 // Handle string literal
233227 else if ( ts . isStringLiteral ( arg ) ) {
234228 query = arg . getText ( ) . slice ( 1 , - 1 ) ; // Remove quotes
235- results . push ( { success : true , sql : query } ) ;
229+ results . push ( {
230+ success : true ,
231+ query : {
232+ type : identifier . text === 'sqln' ? 'nested' : 'flat' ,
233+ sql : query ,
234+ } ,
235+ } ) ;
236236 } else {
237237 results . push ( {
238238 success : false ,
0 commit comments