1+ import { ParseResult } from "@pgsql/types" ;
2+ export * from "@pgsql/types" ;
3+
4+ // @ts -ignore
5+ import PgQueryModule from './libpg-query.js' ;
6+ // @ts -ignore
7+ import { pg_query } from '../proto.js' ;
8+
9+ interface WasmModule {
10+ _malloc : ( size : number ) => number ;
11+ _free : ( ptr : number ) => void ;
12+ _wasm_free_string : ( ptr : number ) => void ;
13+ _wasm_parse_query : ( queryPtr : number ) => number ;
14+ _wasm_deparse_protobuf : ( dataPtr : number , length : number ) => number ;
15+ _wasm_parse_plpgsql : ( queryPtr : number ) => number ;
16+ _wasm_fingerprint : ( queryPtr : number ) => number ;
17+ _wasm_normalize_query : ( queryPtr : number ) => number ;
18+ lengthBytesUTF8 : ( str : string ) => number ;
19+ stringToUTF8 : ( str : string , ptr : number , len : number ) => void ;
20+ UTF8ToString : ( ptr : number ) => string ;
21+ HEAPU8 : Uint8Array ;
22+ }
23+
24+ let wasmModule : WasmModule ;
25+
26+ const initPromise = PgQueryModule ( ) . then ( ( module : WasmModule ) => {
27+ wasmModule = module ;
28+ } ) ;
29+
30+ export async function loadModule ( ) : Promise < void > {
31+ if ( ! wasmModule ) {
32+ await initPromise ;
33+ }
34+ }
35+
36+ function awaitInit < T extends ( ...args : any [ ] ) => Promise < any > > ( fn : T ) : T {
37+ return ( async ( ...args : Parameters < T > ) => {
38+ await initPromise ;
39+ return fn ( ...args ) ;
40+ } ) as T ;
41+ }
42+
43+ function stringToPtr ( str : string ) : number {
44+ const len = wasmModule . lengthBytesUTF8 ( str ) + 1 ;
45+ const ptr = wasmModule . _malloc ( len ) ;
46+ try {
47+ wasmModule . stringToUTF8 ( str , ptr , len ) ;
48+ return ptr ;
49+ } catch ( error ) {
50+ wasmModule . _free ( ptr ) ;
51+ throw error ;
52+ }
53+ }
54+
55+ function ptrToString ( ptr : number ) : string {
56+ return wasmModule . UTF8ToString ( ptr ) ;
57+ }
58+
59+ export const parseQuery = awaitInit ( async ( query : string ) : Promise < ParseResult > => {
60+ const queryPtr = stringToPtr ( query ) ;
61+ let resultPtr = 0 ;
62+
63+ try {
64+ resultPtr = wasmModule . _wasm_parse_query ( queryPtr ) ;
65+ const resultStr = ptrToString ( resultPtr ) ;
66+
67+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
68+ throw new Error ( resultStr ) ;
69+ }
70+
71+ return JSON . parse ( resultStr ) ;
72+ } finally {
73+ wasmModule . _free ( queryPtr ) ;
74+ if ( resultPtr ) {
75+ wasmModule . _wasm_free_string ( resultPtr ) ;
76+ }
77+ }
78+ } ) ;
79+
80+ export const deparse = awaitInit ( async ( parseTree : ParseResult ) : Promise < string > => {
81+ if ( ! parseTree || typeof parseTree !== 'object' || ! Array . isArray ( parseTree . stmts ) || parseTree . stmts . length === 0 ) {
82+ throw new Error ( 'No parseTree provided' ) ;
83+ }
84+
85+ const msg = pg_query . ParseResult . fromObject ( parseTree ) ;
86+ const data = pg_query . ParseResult . encode ( msg ) . finish ( ) ;
87+
88+ const dataPtr = wasmModule . _malloc ( data . length ) ;
89+ let resultPtr = 0 ;
90+
91+ try {
92+ wasmModule . HEAPU8 . set ( data , dataPtr ) ;
93+ resultPtr = wasmModule . _wasm_deparse_protobuf ( dataPtr , data . length ) ;
94+ const resultStr = ptrToString ( resultPtr ) ;
95+
96+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
97+ throw new Error ( resultStr ) ;
98+ }
99+
100+ return resultStr ;
101+ } finally {
102+ wasmModule . _free ( dataPtr ) ;
103+ if ( resultPtr ) {
104+ wasmModule . _wasm_free_string ( resultPtr ) ;
105+ }
106+ }
107+ } ) ;
108+
109+ export const parsePlPgSQL = awaitInit ( async ( query : string ) : Promise < ParseResult > => {
110+ const queryPtr = stringToPtr ( query ) ;
111+ let resultPtr = 0 ;
112+
113+ try {
114+ resultPtr = wasmModule . _wasm_parse_plpgsql ( queryPtr ) ;
115+ const resultStr = ptrToString ( resultPtr ) ;
116+
117+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
118+ throw new Error ( resultStr ) ;
119+ }
120+
121+ return JSON . parse ( resultStr ) ;
122+ } finally {
123+ wasmModule . _free ( queryPtr ) ;
124+ if ( resultPtr ) {
125+ wasmModule . _wasm_free_string ( resultPtr ) ;
126+ }
127+ }
128+ } ) ;
129+
130+ export const fingerprint = awaitInit ( async ( query : string ) : Promise < string > => {
131+ const queryPtr = stringToPtr ( query ) ;
132+ let resultPtr = 0 ;
133+
134+ try {
135+ resultPtr = wasmModule . _wasm_fingerprint ( queryPtr ) ;
136+ const resultStr = ptrToString ( resultPtr ) ;
137+
138+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
139+ throw new Error ( resultStr ) ;
140+ }
141+
142+ return resultStr ;
143+ } finally {
144+ wasmModule . _free ( queryPtr ) ;
145+ if ( resultPtr ) {
146+ wasmModule . _wasm_free_string ( resultPtr ) ;
147+ }
148+ }
149+ } ) ;
150+
151+ export const normalize = awaitInit ( async ( query : string ) : Promise < string > => {
152+ const queryPtr = stringToPtr ( query ) ;
153+ let resultPtr = 0 ;
154+
155+ try {
156+ resultPtr = wasmModule . _wasm_normalize_query ( queryPtr ) ;
157+ const resultStr = ptrToString ( resultPtr ) ;
158+
159+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
160+ throw new Error ( resultStr ) ;
161+ }
162+
163+ return resultStr ;
164+ } finally {
165+ wasmModule . _free ( queryPtr ) ;
166+ if ( resultPtr ) {
167+ wasmModule . _wasm_free_string ( resultPtr ) ;
168+ }
169+ }
170+ } ) ;
171+
172+ // Sync versions
173+ export function parseQuerySync ( query : string ) : ParseResult {
174+ if ( ! wasmModule ) {
175+ throw new Error ( 'WASM module not initialized. Call loadModule() first.' ) ;
176+ }
177+ const queryPtr = stringToPtr ( query ) ;
178+ let resultPtr = 0 ;
179+
180+ try {
181+ resultPtr = wasmModule . _wasm_parse_query ( queryPtr ) ;
182+ const resultStr = ptrToString ( resultPtr ) ;
183+
184+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
185+ throw new Error ( resultStr ) ;
186+ }
187+
188+ return JSON . parse ( resultStr ) ;
189+ } finally {
190+ wasmModule . _free ( queryPtr ) ;
191+ if ( resultPtr ) {
192+ wasmModule . _wasm_free_string ( resultPtr ) ;
193+ }
194+ }
195+ }
196+
197+ export function deparseSync ( parseTree : ParseResult ) : string {
198+ if ( ! wasmModule ) {
199+ throw new Error ( 'WASM module not initialized. Call loadModule() first.' ) ;
200+ }
201+ if ( ! parseTree || typeof parseTree !== 'object' || ! Array . isArray ( parseTree . stmts ) || parseTree . stmts . length === 0 ) {
202+ throw new Error ( 'No parseTree provided' ) ;
203+ }
204+
205+ const msg = pg_query . ParseResult . fromObject ( parseTree ) ;
206+ const data = pg_query . ParseResult . encode ( msg ) . finish ( ) ;
207+
208+ const dataPtr = wasmModule . _malloc ( data . length ) ;
209+ let resultPtr = 0 ;
210+
211+ try {
212+ wasmModule . HEAPU8 . set ( data , dataPtr ) ;
213+ resultPtr = wasmModule . _wasm_deparse_protobuf ( dataPtr , data . length ) ;
214+ const resultStr = ptrToString ( resultPtr ) ;
215+
216+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
217+ throw new Error ( resultStr ) ;
218+ }
219+
220+ return resultStr ;
221+ } finally {
222+ wasmModule . _free ( dataPtr ) ;
223+ if ( resultPtr ) {
224+ wasmModule . _wasm_free_string ( resultPtr ) ;
225+ }
226+ }
227+ }
228+
229+ export function parsePlPgSQLSync ( query : string ) : ParseResult {
230+ if ( ! wasmModule ) {
231+ throw new Error ( 'WASM module not initialized. Call loadModule() first.' ) ;
232+ }
233+ const queryPtr = stringToPtr ( query ) ;
234+ let resultPtr = 0 ;
235+
236+ try {
237+ resultPtr = wasmModule . _wasm_parse_plpgsql ( queryPtr ) ;
238+ const resultStr = ptrToString ( resultPtr ) ;
239+
240+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
241+ throw new Error ( resultStr ) ;
242+ }
243+
244+ return JSON . parse ( resultStr ) ;
245+ } finally {
246+ wasmModule . _free ( queryPtr ) ;
247+ if ( resultPtr ) {
248+ wasmModule . _wasm_free_string ( resultPtr ) ;
249+ }
250+ }
251+ }
252+
253+ export function fingerprintSync ( query : string ) : string {
254+ if ( ! wasmModule ) {
255+ throw new Error ( 'WASM module not initialized. Call loadModule() first.' ) ;
256+ }
257+ const queryPtr = stringToPtr ( query ) ;
258+ let resultPtr = 0 ;
259+
260+ try {
261+ resultPtr = wasmModule . _wasm_fingerprint ( queryPtr ) ;
262+ const resultStr = ptrToString ( resultPtr ) ;
263+
264+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
265+ throw new Error ( resultStr ) ;
266+ }
267+
268+ return resultStr ;
269+ } finally {
270+ wasmModule . _free ( queryPtr ) ;
271+ if ( resultPtr ) {
272+ wasmModule . _wasm_free_string ( resultPtr ) ;
273+ }
274+ }
275+ }
276+
277+ export function normalizeSync ( query : string ) : string {
278+ if ( ! wasmModule ) {
279+ throw new Error ( 'WASM module not initialized. Call loadModule() first.' ) ;
280+ }
281+ const queryPtr = stringToPtr ( query ) ;
282+ let resultPtr = 0 ;
283+
284+ try {
285+ resultPtr = wasmModule . _wasm_normalize_query ( queryPtr ) ;
286+ const resultStr = ptrToString ( resultPtr ) ;
287+
288+ if ( resultStr . startsWith ( 'syntax error' ) || resultStr . startsWith ( 'deparse error' ) || resultStr . includes ( 'ERROR' ) ) {
289+ throw new Error ( resultStr ) ;
290+ }
291+
292+ return resultStr ;
293+ } finally {
294+ wasmModule . _free ( queryPtr ) ;
295+ if ( resultPtr ) {
296+ wasmModule . _wasm_free_string ( resultPtr ) ;
297+ }
298+ }
299+ }
0 commit comments