UNPKG

@electric-sql/pglite-tools

Version:

Tools for working with PGlite databases

1 lines 74.1 kB
{"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/tsup@8.3.0_@microsoft+api-extractor@7.47.7_@types+node@20.16.11__postcss@8.4.47_tsx@4.19.1_typescript@5.6.3/node_modules/tsup/assets/cjs_shims.js","../src/wasi/easywasi.js","../src/pg_dump.ts"],"sourcesContent":["export * from './pg_dump'\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","/* eslint-disable */\n\n// 2024-11-21\n\nimport * as defs from './defs.js'\n\nexport { defs }\n\nexport class WASIProcExit extends Error {\n constructor(code) {\n super(`Exit with code ${code}`)\n this.code = code\n }\n}\n\n// FS interface that is used here. Implement your own, if you want, or use zenfs or node fs!\nexport class FSDummy {\n appendFileSync(path, data, options = {}) {\n throw new Error('appendFileSync not implemented')\n }\n\n fsyncSync(fd) {\n throw new Error('fsyncSync not implemented')\n }\n\n linkSync(existingPath, newPath) {\n throw new Error('linkSync not implemented')\n }\n\n mkdirSync(path, options = {}) {\n throw new Error('mkdirSync not implemented')\n }\n\n readdirSync(path, options = {}) {\n throw new Error('readdirSync not implemented')\n }\n\n readFileSync(path, options = {}) {\n throw new Error('readFileSync not implemented')\n }\n\n readlinkSync(path, options = {}) {\n throw new Error('readlinkSync not implemented')\n }\n\n renameSync(oldPath, newPath) {\n throw new Error('renameSync not implemented')\n }\n\n rmdirSync(path, options = {}) {\n throw new Error('rmdirSync not implemented')\n }\n\n setFlagsSync(path, flags) {\n throw new Error('setFlagsSync not implemented')\n }\n\n statSync(path, options = {}) {\n throw new Error('statSync not implemented')\n }\n\n symlinkSync(target, path, type = 'file') {\n throw new Error('symlinkSync not implemented')\n }\n\n truncateSync(path, len = 0) {\n throw new Error('truncateSync not implemented')\n }\n\n unlinkSync(path) {\n throw new Error('unlinkSync not implemented')\n }\n\n utimesSync(path, atime, mtime) {\n throw new Error('utimesSync not implemented')\n }\n\n writeFileSync(path, data, options = {}) {\n throw new Error('writeFileSync not implemented')\n }\n}\n\nexport class WasiPreview1 {\n constructor(options = {}) {\n this.args = options.args || []\n this.env = options.env || {}\n this.fs = options.fs || new FSDummy()\n\n if (!this.fs) {\n throw new Error('File system implementation required')\n }\n\n // Initialize file descriptors with stdin(0), stdout(1), stderr(2), /\n // fd is first number\n this.fds = new Map([\n [0, { type: 'stdio' }], // stdin\n [1, { type: 'stdio' }], // stdout\n [2, { type: 'stdio' }], // stderr\n [3, { type: 'directory', preopenPath: '/' }], // root directory\n ])\n\n this.nextFd = this.fds.size\n this.textDecoder = new TextDecoder()\n this.textEncoder = new TextEncoder()\n\n // Bind all WASI functions to maintain correct 'this' context\n this.args_get = this.args_get.bind(this)\n this.args_sizes_get = this.args_sizes_get.bind(this)\n this.environ_get = this.environ_get.bind(this)\n this.environ_sizes_get = this.environ_sizes_get.bind(this)\n this.clock_res_get = this.clock_res_get.bind(this)\n this.clock_time_get = this.clock_time_get.bind(this)\n this.fd_close = this.fd_close.bind(this)\n this.fd_seek = this.fd_seek.bind(this)\n this.fd_write = this.fd_write.bind(this)\n this.fd_read = this.fd_read.bind(this)\n this.fd_fdstat_get = this.fd_fdstat_get.bind(this)\n this.fd_fdstat_set_flags = this.fd_fdstat_set_flags.bind(this)\n this.fd_prestat_get = this.fd_prestat_get.bind(this)\n this.fd_prestat_dir_name = this.fd_prestat_dir_name.bind(this)\n this.path_open = this.path_open.bind(this)\n this.path_filestat_get = this.path_filestat_get.bind(this)\n this.proc_exit = this.proc_exit.bind(this)\n this.fd_advise = this.fd_advise.bind(this)\n this.fd_allocate = this.fd_allocate.bind(this)\n this.fd_datasync = this.fd_datasync.bind(this)\n this.fd_filestat_get = this.fd_filestat_get.bind(this)\n this.fd_filestat_set_size = this.fd_filestat_set_size.bind(this)\n this.fd_filestat_set_times = this.fd_filestat_set_times.bind(this)\n this.fd_pread = this.fd_pread.bind(this)\n this.fd_pwrite = this.fd_pwrite.bind(this)\n this.fd_readdir = this.fd_readdir.bind(this)\n this.fd_renumber = this.fd_renumber.bind(this)\n this.fd_sync = this.fd_sync.bind(this)\n this.fd_tell = this.fd_tell.bind(this)\n this.path_create_directory = this.path_create_directory.bind(this)\n this.path_filestat_set_times = this.path_filestat_set_times.bind(this)\n this.path_link = this.path_link.bind(this)\n this.path_readlink = this.path_readlink.bind(this)\n this.path_remove_directory = this.path_remove_directory.bind(this)\n this.path_rename = this.path_rename.bind(this)\n this.path_symlink = this.path_symlink.bind(this)\n this.path_unlink_file = this.path_unlink_file.bind(this)\n this.poll_oneoff = this.poll_oneoff.bind(this)\n this.sock_accept = this.sock_accept.bind(this)\n this.sock_recv = this.sock_recv.bind(this)\n this.sock_send = this.sock_send.bind(this)\n this.sock_shutdown = this.sock_shutdown.bind(this)\n this.random_get = this.random_get.bind(this)\n this.sched_yield = this.sched_yield.bind(this)\n }\n\n // Helper methods\n\n // this binds the wasm to this WASI implementation\n setup(wasm) {\n this.wasm = wasm\n }\n\n // this binds the wasm to this WASI implementation\n // and calls it's main()'\n start(wasm) {\n this.setup(wasm)\n try {\n if (wasm._start) {\n wasm._start()\n }\n return 0\n } catch (e) {\n if (e instanceof WASIProcExit) {\n return e.code\n }\n throw e\n }\n }\n\n // Standard input (for fd_read)\n stdin() {\n return new Uint8Array()\n }\n\n // Standard output handling (for fd_write)\n stdout(buffer) {\n const text = this.textDecoder.decode(buffer).replace(/\\n$/g, '')\n if (text) console.log(text)\n }\n\n // Standard error handling (for fd_write)\n stderr(buffer) {\n const text = this.textDecoder.decode(buffer).replace(/\\n$/g, '')\n if (text) console.error(text)\n }\n\n // Args functions\n args_get(argvP, argvBufP) {\n const view = new DataView(this.wasm.memory.buffer)\n const mem = new Uint8Array(this.wasm.memory.buffer)\n\n for (const arg of this.args) {\n view.setUint32(argvP, argvBufP, true)\n argvP += 4\n const encoded = this.textEncoder.encode(arg)\n mem.set(encoded, argvBufP)\n mem[argvBufP + encoded.length] = 0 // null terminator\n argvBufP += encoded.length + 1\n }\n return defs.ERRNO_SUCCESS\n }\n\n args_sizes_get(argcPtr, argvBufSizePtr) {\n const view = new DataView(this.wasm.memory.buffer)\n view.setUint32(argcPtr, this.args.length, true)\n const bufSize = this.args.reduce((acc, arg) => acc + arg.length + 1, 0)\n view.setUint32(argvBufSizePtr, bufSize, true)\n return defs.ERRNO_SUCCESS\n }\n\n // Environment functions\n environ_get(environP, environBufP) {\n const view = new DataView(this.wasm.memory.buffer)\n const mem = new Uint8Array(this.wasm.memory.buffer)\n\n for (const [key, value] of Object.entries(this.env)) {\n view.setUint32(environP, environBufP, true)\n environP += 4\n const entry = `${key}=${value}\\0`\n const encoded = this.textEncoder.encode(entry)\n mem.set(encoded, environBufP)\n environBufP += encoded.length\n }\n return defs.ERRNO_SUCCESS\n }\n\n environ_sizes_get(environCountPtr, environBufSizePtr) {\n const view = new DataView(this.wasm.memory.buffer)\n const count = Object.keys(this.env).length\n view.setUint32(environCountPtr, count, true)\n const bufSize = Object.entries(this.env).reduce(\n (acc, [k, v]) => acc + k.length + v.length + 2,\n 0,\n )\n view.setUint32(environBufSizePtr, bufSize, true)\n return defs.ERRNO_SUCCESS\n }\n\n // Clock functions\n clock_res_get(id, resPtr) {\n const view = new DataView(this.wasm.memory.buffer)\n let resolution\n switch (id) {\n case defs.CLOCKID_REALTIME:\n resolution = 1_000_000n // 1ms in nanoseconds\n break\n case defs.CLOCKID_MONOTONIC:\n resolution = 1_000n // 1μs in nanoseconds\n break\n default:\n return defs.ERRNO_INVAL\n }\n view.setBigUint64(resPtr, resolution, true)\n return defs.ERRNO_SUCCESS\n }\n\n clock_time_get(id, precision, timePtr) {\n const view = new DataView(this.wasm.memory.buffer)\n let time\n switch (id) {\n case defs.CLOCKID_REALTIME: {\n const ms = Date.now()\n time = BigInt(ms) * 1_000_000n\n break\n }\n case defs.CLOCKID_MONOTONIC: {\n const ns = BigInt(Math.round(performance.now() * 1_000_000))\n time = ns\n break\n }\n default:\n return defs.ERRNO_INVAL\n }\n view.setBigUint64(timePtr, time, true)\n return defs.ERRNO_SUCCESS\n }\n\n fd_close(fd) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n this.fds.delete(fd)\n return defs.ERRNO_SUCCESS\n }\n\n // TODO: BIGINT\n fd_seek(fd, offset, whence, newOffsetPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type === 'stdio') return defs.ERRNO_SPIPE\n\n var stats = null\n let newPosition = 0\n let noffset = Number(offset)\n\n try {\n stats = this.fs.statSync(fileDesc.handle.path)\n } catch (e) {\n return defs.ERRNO_IO\n }\n\n switch (whence) {\n case defs.WHENCE_SET:\n newPosition = noffset\n break\n case defs.WHENCE_CUR:\n newPosition = Number(fileDesc.handle.position) + noffset\n break\n case defs.WHENCE_END:\n newPosition = Number(stats.size) + noffset\n break\n default:\n console.error('fd_seek invalid mode', whence)\n return defs.ERRNO_INVAL\n }\n\n // Update position\n fileDesc.handle.position = newPosition\n\n const view = new DataView(this.wasm.memory.buffer)\n view.setBigUint64(newOffsetPtr, BigInt(newPosition), true)\n return defs.ERRNO_SUCCESS\n }\n\n fd_write(fd, iovs, iovsLen, nwrittenPtr) {\n let written = 0\n const chunks = []\n const view = new DataView(this.wasm.memory.buffer)\n const mem = new Uint8Array(this.wasm.memory.buffer)\n\n // Gather all the chunks from the vectors\n for (let i = 0; i < iovsLen; i++) {\n const ptr = iovs + i * 8\n const buf = view.getUint32(ptr, true)\n const bufLen = view.getUint32(ptr + 4, true)\n chunks.push(new Uint8Array(mem.buffer, buf, bufLen))\n written += bufLen\n }\n\n // Concatenate chunks if needed\n let buffer\n if (chunks.length === 1) {\n buffer = chunks[0]\n } else {\n buffer = new Uint8Array(written)\n let offset = 0\n for (const chunk of chunks) {\n buffer.set(chunk, offset)\n offset += chunk.length\n }\n }\n\n // Handle standard streams\n if (fd === 1) {\n this.stdout(buffer)\n } else if (fd === 2) {\n this.stderr(buffer)\n } else {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n fileDesc.handle.position += written\n\n try {\n // Write using ZenFS path-based API\n this.fs.writeFileSync(fileDesc.handle.path, buffer)\n } catch (e) {\n //console.error(\"fs.writeFileSync failed:\", fileDesc.handle.path)\n return defs.ERRNO_IO\n }\n }\n //console.log(\"fd_write end\", written)\n view.setUint32(nwrittenPtr, written, true)\n return defs.ERRNO_SUCCESS\n }\n\n fd_read(fd, iovs, iovsLen, nreadPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n let totalRead = 0\n const view = new DataView(this.wasm.memory.buffer)\n const mem = new Uint8Array(this.wasm.memory.buffer)\n\n try {\n let content\n if (fd === 0) {\n content = this.stdin()\n } else {\n content = this.fs.readFileSync(fileDesc.handle.path)\n }\n\n for (let i = 0; i < iovsLen; i++) {\n const ptr = iovs + i * 8\n const buf = view.getUint32(ptr, true)\n const bufLen = view.getUint32(ptr + 4, true)\n\n const start = fileDesc.handle.position\n const end = Math.min(start + bufLen, content.length)\n const bytesToRead = end - start\n\n if (bytesToRead <= 0) break\n\n mem.set(new Uint8Array(content.slice(start, end)), buf)\n totalRead += bytesToRead\n fileDesc.handle.position += bytesToRead\n\n if (bytesToRead < bufLen) break\n }\n\n view.setUint32(nreadPtr, totalRead, true)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_open(\n dirfd,\n dirflags,\n path,\n pathLen,\n oflags,\n fsRightsBase,\n fsRightsInheriting,\n fdflags,\n fdPtr,\n ) {\n var fileDesc = this.fds.get(dirfd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const mem = new Uint8Array(this.wasm.memory.buffer)\n const pathBuffer = mem.slice(path, path + pathLen)\n const pathString = this.textDecoder.decode(pathBuffer)\n let resolvedPath = pathString\n\n var fd = 0\n const view = new DataView(this.wasm.memory.buffer)\n\n // Resolve path relative to the directory fd\n if (fileDesc.preopenPath) {\n if (pathString.startsWith('/')) {\n resolvedPath = pathString.slice(1)\n }\n resolvedPath =\n fileDesc.preopenPath +\n (fileDesc.preopenPath.endsWith('/') ? '' : '/') +\n resolvedPath\n }\n\n var exists = false\n var stats = null\n const o_create = (oflags & defs.OFLAGS_CREAT) == defs.OFLAGS_CREAT\n const o_directory =\n (oflags & defs.OFLAGS_DIRECTORY) == defs.OFLAGS_DIRECTORY\n const o_exclusive = (oflags & defs.OFLAGS_EXCL) == defs.OFLAGS_EXCL\n const o_truncate = (oflags & defs.OFLAGS_TRUNC) == defs.OFLAGS_TRUNC\n try {\n // Verify file exists\n stats = this.fs.statSync(resolvedPath)\n exists = true\n } catch (e) {}\n\n if (o_exclusive || o_truncate) {\n if (o_exclusive && exists) {\n // null\n view.setUint32(fdPtr, fd, true)\n return defs.ERRNO_EXIST\n }\n }\n\n // Store path and initial position in handle TODO: could be BIGINT\n // fd = this.allocateFd({ path: resolvedPath, position: 0 }, 'file')\n const fileHandle = { path: resolvedPath, position: 0 }\n const type = 'file'\n fd = this.nextFd++\n const descriptor = { type, handle: fileHandle, fd }\n this.fds.set(fd, descriptor)\n\n fileDesc = this.fds.get(fd)\n\n // TODO: could be BIGINT\n fileDesc.handle.position = 0\n\n if (o_truncate) {\n // TODO: could be BIGINT\n fileDesc.handle.size = 0\n }\n\n // console.log(`path_open[${fd}] : ${resolvedPath} o_directory=${o_directory} exists=${exists} o_exclusive=${o_exclusive} o_create=${o_create} o_truncate=${o_truncate}`)\n // if (stats)\n // console.log(`path_open[${fd}] : ${fileDesc.handle.position} / ${stats.size}`)\n\n // o_directory - ERRNO_NOTDIR\n\n // ERRNO_NOENT\n\n view.setUint32(fdPtr, fd, true)\n return defs.ERRNO_SUCCESS\n }\n\n proc_exit(code) {\n throw new WASIProcExit(code)\n }\n\n fd_fdstat_get(fd, statPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const view = new DataView(this.wasm.memory.buffer)\n\n // filetype - u8\n let filetype\n switch (fileDesc.type) {\n case 'stdio':\n filetype = defs.FILETYPE_CHARACTER_DEVICE\n break\n case 'directory':\n filetype = defs.FILETYPE_DIRECTORY\n break\n case 'file':\n filetype = defs.FILETYPE_REGULAR_FILE\n break\n default:\n filetype = defs.FILETYPE_UNKNOWN\n }\n view.setUint8(statPtr, filetype)\n\n // fdflags - u16\n // For now, we'll assume basic flags\n let fdflags = 0\n if (fileDesc.append) fdflags |= defs.FDFLAGS_APPEND\n view.setUint16(statPtr + 2, fdflags, true)\n\n // fs_rights_base - u64\n // Set basic rights depending on file type\n let fsRightsBase = 0n\n if (fileDesc.type === 'file') {\n fsRightsBase =\n defs.RIGHTS_FD_READ |\n defs.RIGHTS_FD_WRITE |\n defs.RIGHTS_FD_SEEK |\n defs.RIGHTS_FD_TELL |\n defs.RIGHTS_FD_FILESTAT_GET\n } else if (fileDesc.type === 'directory') {\n fsRightsBase =\n defs.RIGHTS_PATH_OPEN |\n defs.RIGHTS_FD_READDIR |\n defs.RIGHTS_PATH_CREATE_DIRECTORY |\n defs.RIGHTS_PATH_UNLINK_FILE |\n defs.RIGHTS_PATH_REMOVE_DIRECTORY\n }\n const bf = BigInt(fsRightsBase)\n view.setBigUint64(statPtr + 8, bf, true)\n\n // fs_rights_inheriting - u64\n // Child files/directories inherit the same rights\n view.setBigUint64(statPtr + 16, bf, true)\n\n return defs.ERRNO_SUCCESS\n }\n\n fd_fdstat_set_flags(fd, flags) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n // Check if flags are valid\n const validFlags =\n defs.FDFLAGS_APPEND |\n defs.FDFLAGS_DSYNC |\n defs.FDFLAGS_NONBLOCK |\n defs.FDFLAGS_RSYNC |\n defs.FDFLAGS_SYNC\n\n if (flags & ~validFlags) {\n return defs.ERRNO_INVAL // Invalid flags specified\n }\n\n // For stdio handles, we can't set flags\n if (fileDesc.type === 'stdio') {\n return defs.ERRNO_NOTSUP\n }\n\n try {\n // Update internal file descriptor state\n fileDesc.append = Boolean(flags & defs.FDFLAGS_APPEND)\n\n // Try to apply flags to the underlying file system\n // Note: Many flags might not be supported by the underlying fs\n if (fileDesc.handle && typeof this.fs.setFlagsSync === 'function') {\n this.fs.setFlagsSync(fileDesc.handle, flags)\n }\n\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_prestat_get(fd, prestatPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n // Only directory file descriptors have prestats\n if (fileDesc.type !== 'directory') {\n return defs.ERRNO_BADF\n }\n\n // Ensure we have a preopened path for this fd\n if (!fileDesc.preopenPath) {\n return defs.ERRNO_BADF\n }\n\n const view = new DataView(this.wasm.memory.buffer)\n\n // Write prestat struct:\n // struct prestat {\n // u8 type; // offset 0\n // u64 length; // offset 8 (with padding)\n // }\n\n // Set type to PREOPENTYPE_DIR (0)\n view.setUint8(prestatPtr, defs.PREOPENTYPE_DIR)\n\n // Get the length of the preopened directory path\n const pathLength = fileDesc.preopenPath.length\n view.setUint32(prestatPtr + 4, pathLength, true)\n\n return defs.ERRNO_SUCCESS\n }\n\n fd_prestat_dir_name(fd, pathPtr, pathLen) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n // Only directory file descriptors have prestats\n if (fileDesc.type !== 'directory') {\n return defs.ERRNO_BADF\n }\n\n // Ensure we have a preopened path for this fd\n if (!fileDesc.preopenPath) {\n return defs.ERRNO_BADF\n }\n\n // Check if the provided buffer is large enough\n if (pathLen < fileDesc.preopenPath.length) {\n return defs.ERRNO_NAMETOOLONG\n }\n\n // Write the path to memory\n const mem = new Uint8Array(this.wasm.memory.buffer)\n const pathBytes = this.textEncoder.encode(fileDesc.preopenPath)\n mem.set(pathBytes, pathPtr)\n\n return defs.ERRNO_SUCCESS\n }\n\n path_filestat_get(fd, flags, pathPtr, pathLen, filestatPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n // Read the path from memory\n const mem = new Uint8Array(this.wasm.memory.buffer)\n const pathBytes = new Uint8Array(mem.buffer, pathPtr, pathLen)\n const pathString = this.textDecoder.decode(pathBytes)\n\n try {\n // Resolve path relative to the directory fd\n let resolvedPath = pathString\n if (fileDesc.preopenPath) {\n // If path starts with '/', make it relative to preopenPath\n if (pathString.startsWith('/')) {\n resolvedPath = pathString.slice(1) // Remove leading '/'\n }\n // Combine preopenPath with the relative path\n resolvedPath =\n fileDesc.preopenPath +\n (fileDesc.preopenPath.endsWith('/') ? '' : '/') +\n resolvedPath\n }\n\n // Get stats from filesystem\n const stats = this.fs.statSync(resolvedPath, {\n followSymlinks: (flags & defs.LOOKUPFLAGS_SYMLINK_FOLLOW) !== 0,\n })\n\n const view = new DataView(this.wasm.memory.buffer)\n\n // Write filestat struct:\n // struct filestat {\n // dev: u64, // Device ID\n // ino: u64, // Inode number\n // filetype: u8, // File type\n // nlink: u64, // Number of hard links\n // size: u64, // File size\n // atim: u64, // Access time\n // mtim: u64, // Modification time\n // ctim: u64 // Change time\n // }\n\n // Device ID\n view.setBigUint64(filestatPtr, BigInt(stats.dev || 0), true)\n\n // Inode\n view.setBigUint64(filestatPtr + 8, BigInt(stats.ino || 0), true)\n\n // Filetype\n let filetype = defs.FILETYPE_UNKNOWN\n if (stats.isFile()) filetype = defs.FILETYPE_REGULAR_FILE\n else if (stats.isDirectory()) filetype = defs.FILETYPE_DIRECTORY\n else if (stats.isSymbolicLink()) filetype = defs.FILETYPE_SYMBOLIC_LINK\n else if (stats.isCharacterDevice())\n filetype = defs.FILETYPE_CHARACTER_DEVICE\n else if (stats.isBlockDevice()) filetype = defs.FILETYPE_BLOCK_DEVICE\n else if (stats.isFIFO()) filetype = defs.FILETYPE_SOCKET_STREAM\n view.setUint8(filestatPtr + 16, filetype)\n\n // Number of hard links\n view.setBigUint64(filestatPtr + 24, BigInt(stats.nlink || 1), true)\n\n // File size\n view.setBigUint64(filestatPtr + 32, BigInt(stats.size || 0), true)\n\n // Access time (in nanoseconds)\n view.setBigUint64(\n filestatPtr + 40,\n BigInt(stats.atimeMs * 1_000_000),\n true,\n )\n\n // Modification time (in nanoseconds)\n view.setBigUint64(\n filestatPtr + 48,\n BigInt(stats.mtimeMs * 1_000_000),\n true,\n )\n\n // Change time (in nanoseconds)\n view.setBigUint64(\n filestatPtr + 56,\n BigInt(stats.ctimeMs * 1_000_000),\n true,\n )\n\n return defs.ERRNO_SUCCESS\n } catch (e) {\n if (e.code === 'ENOENT') return defs.ERRNO_NOENT\n if (e.code === 'EACCES') return defs.ERRNO_ACCES\n return defs.ERRNO_IO\n }\n }\n\n // File/Directory Operations\n fd_advise(fd, offset, len, advice) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n // Most filesystems don't actually implement advisory hints,\n // so we'll just return success\n return defs.ERRNO_SUCCESS\n }\n\n fd_allocate(fd, offset, len) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n try {\n // Attempt to extend the file to the specified size\n const stats = this.fs.statSync(fileDesc.handle.path)\n const newSize = Number(offset) + Number(len)\n if (newSize > stats.size) {\n // Create a buffer of zeros to extend the file\n const zeros = new Uint8Array(newSize - stats.size)\n this.fs.appendFileSync(fileDesc.handle.path, zeros)\n }\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_datasync(fd) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n try {\n // Most JavaScript filesystem implementations handle syncing automatically\n // If your fs implementation has a specific sync method, call it here\n if (typeof this.fs.fsyncSync === 'function') {\n this.fs.fsyncSync(fileDesc.handle.path)\n }\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_filestat_get(fd, ptr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (!fileDesc.handle) return defs.ERRNO_BADF\n const mem = new DataView(this.wasm.memory.buffer)\n const stats = this.fs.statSync(fileDesc.handle.path)\n mem.setBigUint64(ptr, BigInt(stats.dev), true)\n mem.setBigUint64(ptr + 8, BigInt(stats.ino), true)\n mem.setUint8(ptr + 16, stats.filetype)\n mem.setBigUint64(ptr + 24, BigInt(stats.nlink), true)\n mem.setBigUint64(ptr + 32, BigInt(stats.size), true)\n mem.setBigUint64(ptr + 38, BigInt(stats.atime), true)\n mem.setBigUint64(ptr + 46, BigInt(stats.mtime), true)\n mem.setBigUint64(ptr + 52, BigInt(stats.ctime), true)\n return defs.ERRNO_SUCCESS\n }\n\n fd_filestat_set_size(fd, size) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n try {\n this.fs.truncateSync(fileDesc.handle.path, Number(size))\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_filestat_set_times(fd, atim, mtim, fst_flags) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n try {\n const times = {\n atime: Number(atim) / 1_000_000_000,\n mtime: Number(mtim) / 1_000_000_000,\n }\n\n this.fs.utimesSync(fileDesc.handle.path, times.atime, times.mtime)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_pread(fd, iovs, iovsLen, offset, nreadPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n try {\n const content = this.fs.readFileSync(fileDesc.handle.path)\n let totalRead = 0\n const view = new DataView(this.wasm.memory.buffer)\n const mem = new Uint8Array(this.wasm.memory.buffer)\n\n const position = Number(offset)\n\n for (let i = 0; i < iovsLen; i++) {\n const ptr = iovs + i * 8\n const buf = view.getUint32(ptr, true)\n const bufLen = view.getUint32(ptr + 4, true)\n\n const start = position + totalRead\n const end = Math.min(start + bufLen, content.length)\n const bytesToRead = end - start\n\n if (bytesToRead <= 0) break\n\n mem.set(new Uint8Array(content.slice(start, end)), buf)\n totalRead += bytesToRead\n\n if (bytesToRead < bufLen) break\n }\n\n view.setUint32(nreadPtr, totalRead, true)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_pwrite(fd, iovs, iovsLen, offset, nwrittenPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n try {\n let written = 0\n const chunks = []\n const view = new DataView(this.wasm.memory.buffer)\n const mem = new Uint8Array(this.wasm.memory.buffer)\n\n for (let i = 0; i < iovsLen; i++) {\n const ptr = iovs + i * 8\n const buf = view.getUint32(ptr, true)\n const bufLen = view.getUint32(ptr + 4, true)\n chunks.push(new Uint8Array(mem.buffer, buf, bufLen))\n written += bufLen\n }\n\n let buffer\n if (chunks.length === 1) {\n buffer = chunks[0]\n } else {\n buffer = new Uint8Array(written)\n let offset = 0\n for (const chunk of chunks) {\n buffer.set(chunk, offset)\n offset += chunk.length\n }\n }\n\n // Read existing file content\n const content = this.fs.readFileSync(fileDesc.handle.path)\n const newContent = new Uint8Array(\n Math.max(Number(offset) + buffer.length, content.length),\n )\n\n // Copy existing content\n newContent.set(content)\n // Write new data at specified offset\n newContent.set(buffer, Number(offset))\n\n // Write back to file\n this.fs.writeFileSync(fileDesc.handle.path, newContent)\n\n view.setUint32(nwrittenPtr, written, true)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_readdir(fd, buf, bufLen, cookie, bufusedPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'directory') return defs.ERRNO_NOTDIR\n\n try {\n const entries = this.fs.readdirSync(fileDesc.handle.path, {\n withFileTypes: true,\n })\n const view = new DataView(this.wasm.memory.buffer)\n const mem = new Uint8Array(this.wasm.memory.buffer)\n\n let offset = 0\n let entriesWritten = 0\n\n // Skip entries according to cookie\n const startIndex = Number(cookie)\n\n for (let i = startIndex; i < entries.length; i++) {\n const entry = entries[i]\n const name = entry.name\n const nameBytes = this.textEncoder.encode(name)\n\n // dirent structure size: 24 bytes + name length\n const direntSize = 24 + nameBytes.length\n\n if (offset + direntSize > bufLen) {\n break\n }\n\n // Write dirent structure\n view.setBigUint64(buf + offset, BigInt(i + 1), true) // d_next\n view.setBigUint64(buf + offset + 8, 0n, true) // d_ino\n view.setUint32(buf + offset + 16, nameBytes.length, true) // d_namlen\n\n // d_type\n let filetype = defs.FILETYPE_UNKNOWN\n if (entry.isFile()) filetype = defs.FILETYPE_REGULAR_FILE\n else if (entry.isDirectory()) filetype = defs.FILETYPE_DIRECTORY\n view.setUint8(buf + offset + 20, filetype)\n\n // Write name\n mem.set(nameBytes, buf + offset + 24)\n\n offset += direntSize\n entriesWritten++\n }\n\n view.setUint32(bufusedPtr, offset, true)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_renumber(from, to) {\n const fromDesc = this.fds.get(from)\n if (!fromDesc) return defs.ERRNO_BADF\n\n // Close existing 'to' fd if it exists\n this.fds.delete(to)\n\n // Move the fd\n this.fds.set(to, fromDesc)\n this.fds.delete(from)\n\n return defs.ERRNO_SUCCESS\n }\n\n fd_sync(fd) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n try {\n // Similar to fd_datasync, but might include metadata\n if (typeof this.fs.fsyncSync === 'function') {\n this.fs.fsyncSync(fileDesc.handle.path)\n }\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n fd_tell(fd, offsetPtr) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n if (fileDesc.type !== 'file') return defs.ERRNO_BADF\n\n const view = new DataView(this.wasm.memory.buffer)\n view.setBigUint64(offsetPtr, BigInt(fileDesc.handle.position), true)\n return defs.ERRNO_SUCCESS\n }\n\n // Path Operations\n path_create_directory(fd, path, pathLen) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const pathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, path, pathLen),\n )\n\n try {\n let resolvedPath = pathString\n if (fileDesc.preopenPath) {\n if (pathString.startsWith('/')) {\n resolvedPath = pathString.slice(1)\n }\n resolvedPath = fileDesc.preopenPath + '/' + resolvedPath\n }\n\n this.fs.mkdirSync(resolvedPath)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_filestat_set_times(fd, flags, path, pathLen, atim, mtim, fst_flags) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const pathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, path, pathLen),\n )\n\n try {\n let resolvedPath = pathString\n if (fileDesc.preopenPath) {\n if (pathString.startsWith('/')) {\n resolvedPath = pathString.slice(1)\n }\n resolvedPath = fileDesc.preopenPath + '/' + resolvedPath\n }\n\n const times = {\n atime: Number(atim) / 1_000_000_000,\n mtime: Number(mtim) / 1_000_000_000,\n }\n\n this.fs.utimesSync(resolvedPath, times.atime, times.mtime)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_link(\n old_fd,\n old_flags,\n old_path,\n old_path_len,\n new_fd,\n new_path,\n new_path_len,\n ) {\n const oldFileDesc = this.fds.get(old_fd)\n const newFileDesc = this.fds.get(new_fd)\n if (!oldFileDesc || !newFileDesc) return defs.ERRNO_BADF\n\n const oldPathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, old_path, old_path_len),\n )\n const newPathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, new_path, new_path_len),\n )\n\n try {\n let resolvedOldPath = oldPathString\n let resolvedNewPath = newPathString\n\n if (oldFileDesc.preopenPath) {\n if (oldPathString.startsWith('/')) {\n resolvedOldPath = oldPathString.slice(1)\n }\n resolvedOldPath = oldFileDesc.preopenPath + '/' + resolvedOldPath\n }\n\n if (newFileDesc.preopenPath) {\n if (newPathString.startsWith('/')) {\n resolvedNewPath = newPathString.slice(1)\n }\n resolvedNewPath = newFileDesc.preopenPath + '/' + resolvedNewPath\n }\n\n this.fs.linkSync(resolvedOldPath, resolvedNewPath)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_readlink(fd, path, path_len, buf, buf_len, bufused) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const pathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, path, path_len),\n )\n\n try {\n let resolvedPath = pathString\n if (fileDesc.preopenPath) {\n if (pathString.startsWith('/')) {\n resolvedPath = pathString.slice(1)\n }\n resolvedPath = fileDesc.preopenPath + '/' + resolvedPath\n }\n\n const linkString = this.fs.readlinkSync(resolvedPath)\n const linkBytes = this.textEncoder.encode(linkString)\n\n if (linkBytes.length > buf_len) {\n return defs.ERRNO_OVERFLOW\n }\n\n const mem = new Uint8Array(this.wasm.memory.buffer)\n mem.set(linkBytes, buf)\n\n const view = new DataView(this.wasm.memory.buffer)\n view.setUint32(bufused, linkBytes.length, true)\n\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_remove_directory(fd, path, path_len) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const pathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, path, path_len),\n )\n\n try {\n let resolvedPath = pathString\n if (fileDesc.preopenPath) {\n if (pathString.startsWith('/')) {\n resolvedPath = pathString.slice(1)\n }\n resolvedPath = fileDesc.preopenPath + '/' + resolvedPath\n }\n\n this.fs.rmdirSync(resolvedPath)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_rename(old_fd, old_path, old_path_len, new_fd, new_path, new_path_len) {\n const oldFileDesc = this.fds.get(old_fd)\n const newFileDesc = this.fds.get(new_fd)\n if (!oldFileDesc || !newFileDesc) return defs.ERRNO_BADF\n\n const oldPathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, old_path, old_path_len),\n )\n const newPathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, new_path, new_path_len),\n )\n\n try {\n let resolvedOldPath = oldPathString\n let resolvedNewPath = newPathString\n\n if (oldFileDesc.preopenPath) {\n if (oldPathString.startsWith('/')) {\n resolvedOldPath = oldPathString.slice(1)\n }\n resolvedOldPath = oldFileDesc.preopenPath + '/' + resolvedOldPath\n }\n\n if (newFileDesc.preopenPath) {\n if (newPathString.startsWith('/')) {\n resolvedNewPath = newPathString.slice(1)\n }\n resolvedNewPath = newFileDesc.preopenPath + '/' + resolvedNewPath\n }\n\n this.fs.renameSync(resolvedOldPath, resolvedNewPath)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_symlink(old_path, old_path_len, fd, new_path, new_path_len) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const oldPathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, old_path, old_path_len),\n )\n const newPathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, new_path, new_path_len),\n )\n\n try {\n let resolvedNewPath = newPathString\n if (fileDesc.preopenPath) {\n if (newPathString.startsWith('/')) {\n resolvedNewPath = newPathString.slice(1)\n }\n resolvedNewPath = fileDesc.preopenPath + '/' + resolvedNewPath\n }\n\n this.fs.symlinkSync(oldPathString, resolvedNewPath)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n path_unlink_file(fd, path, path_len) {\n const fileDesc = this.fds.get(fd)\n if (!fileDesc) return defs.ERRNO_BADF\n\n const pathString = this.textDecoder.decode(\n new Uint8Array(this.wasm.memory.buffer, path, path_len),\n )\n\n try {\n let resolvedPath = pathString\n if (fileDesc.preopenPath) {\n if (pathString.startsWith('/')) {\n resolvedPath = pathString.slice(1)\n }\n resolvedPath = fileDesc.preopenPath + '/' + resolvedPath\n }\n\n this.fs.unlinkSync(resolvedPath)\n return defs.ERRNO_SUCCESS\n } catch (e) {\n return defs.ERRNO_IO\n }\n }\n\n // Poll Operations\n poll_oneoff(in_, out, nsubscriptions, nevents) {\n // Basic implementation that just processes all subscriptions immediately\n const view = new DataView(this.wasm.memory.buffer)\n let numEvents = 0\n\n for (let i = 0; i < nsubscriptions; i++) {\n const subPtr = in_ + i * 48 // size of subscription struct\n const userdata = view.getBigUint64(subPtr, true)\n const type = view.getUint8(subPtr + 8)\n\n // Write event\n const eventPtr = out + numEvents * 32 // size of event struct\n view.setBigUint64(eventPtr, userdata, true)\n view.setUint8(eventPtr + 8, type)\n view.setUint8(eventPtr + 9, defs.EVENTRWFLAGS_FD_READWRITE_HANGUP)\n view.setUint16(eventPtr + 10, 0, true) // error\n\n numEvents++\n }\n\n view.setUint32(nevents, numEvents, true)\n return defs.ERRNO_SUCCESS\n }\n\n // Random Number Generation\n random_get(buf, buf_len) {\n const bytes = new Uint8Array(this.wasm.memory.buffer, buf, buf_len)\n crypto.getRandomValues(bytes)\n return defs.ERRNO_SUCCESS\n }\n\n // Scheduling Operations\n sched_yield() {\n os.sched_yield()\n return defs.ERRNO_SUCCESS\n }\n\n // STUB\n sock_accept(fd, flags) {\n return defs.ERRNO_NOSYS\n }\n\n sock_recv(fd, riData, riFlags) {\n return defs.ERRNO_NOSYS\n }\n\n sock_send(fd, siData, riFlags) {\n return defs.ERRNO_NOSYS\n }\n\n sock_shutdown(fd, how) {\n return defs.ERRNO_NOSYS\n }\n}\n\nexport default WasiPreview1\n","import { WasiPreview1 } from './wasi/easywasi'\nimport { postgresMod } from '@electric-sql/pglite'\nimport { PGlite } from '@electric-sql/pglite'\n\ntype FS = postgresMod.FS\ntype FSInterface = any // WASI FS interface\n\nconst IN_NODE =\n typeof process === 'object' &&\n typeof process.versions === 'object' &&\n typeof process.versions.node === 'string'\n\n/**\n * Emscripten FS is not quite compatible with WASI\n * so we need to patch it\n */\nfunction emscriptenFsToWasiFS(fs: FS, acc: any[]): FSInterface & FS {\n const requiredMethods = [\n 'appendFileSync',\n 'fsyncSync',\n 'linkSync',\n 'setFlagsSync',\n 'mkdirSync',\n 'readdirSync',\n 'readFileSync',\n 'readlinkSync',\n 'renameSync',\n 'rmdirSync',\n 'statSync',\n 'symlinkSync',\n 'truncateSync',\n 'unlinkSync',\n 'utimesSync',\n 'writeFileSync',\n ]\n return {\n // Bind all methods to the FS instance\n ...fs,\n // Add missing methods\n ...Object.fromEntries(\n requiredMethods\n .map((method) => {\n const target = method.slice(0, method.length - 4)\n if (!(target in fs)) {\n return [\n method,\n () => {\n throw new Error(`${target} not implemented.`)\n },\n ]\n }\n return [\n method,\n (...args: any[]) => {\n if (method === 'writeFileSync' && args[0] === '/tmp/out.sql') {\n acc.push(args[1])\n }\n return (fs as any)[target](...args)\n },\n ]\n })\n .filter(\n (entry): entry is [string, (fs: FS) => any] => entry !== undefined,\n ),\n ),\n } as FSInterface & FS\n}\n\n/**\n * Inner function to execute pg_dump\n */\nasync function execPgDump({\n pg,\n args,\n}: {\n pg: PGlite\n args: string[]\n}): Promise<[number, Uint8Array[], string]> {\n const bin = new URL('./pg_dump.wasm', import.meta.url)\n const acc: Uint8Array[] = []\n const FS = emscriptenFsToWasiFS(pg.Module.FS, acc)\n\n const wasi = new WasiPreview1({\n fs: FS,\n args: ['pg_dump', ...args],\n env: {\n PWD: '/',\n },\n })\n\n wasi.stdout = (_buffer) => {\n // console.log('stdout', _buffer)\n }\n const textDecoder = new TextDecoder()\n let errorMessage = ''\n\n wasi.stderr = (_buffer) => {\n const text = textDecoder.decode(_buffer)\n if (text) errorMessage += text\n }\n wasi.sched_yield = () => {\n const pgIn = '/tmp/pglite/base/.s.PGSQL.5432.in'\n const pgOut = '/tmp/pglite/base/.s.PGSQL.5432.out'\n if (FS.analyzePath(pgIn).exists) {\n // call interactive one\n const msgIn = FS.readFileSync(pgIn)\n\n // BYPASS the file socket emulation in PGlite\n FS.unlinkSync(pgIn)\n\n // Handle auth request\n if (msgIn[0] === 0) {\n const reply = new Uint8Array([\n ...authOk,\n ...versionParam,\n ...readyForQuery,\n ])\n FS.writeFileSync(pgOut, reply)\n return 0\n }\n\n // Handle query\n const reply = pg.execProtocolRawSync(msgIn)\n FS.writeFileSync(pgOut, reply)\n }\n return 0\n }\n\n // Postgres can complain if the binary is not on the filesystem\n // so we create a dummy file\n await FS.writeFile('/pg_dump', '\\0', { mode: 18 })\n\n let app: WebAssembly.WebAssemblyInstantiatedSource\n\n if (IN_NODE) {\n const fs = await import('fs/promises')\n const blob = await fs.readFile(bin.toString().slice(7))\n app = await WebAssembly.instantiate(blob, {\n wasi_snapshot_preview1: wasi as any,\n })\n } else {\n app = await WebAssembly.instantiateStreaming(fetch(bin), {\n wasi_snapshot_preview1: wasi as any,\n })\n }\n\n let exitCode: number\n await pg.runExclusive(async () => {\n exitCode = wasi.start(app.instance.exports)\n })\n return [exitCode!, acc, errorMessage]\n}\n\ninterface PgDumpOptions {\n pg: PGlite\n args?: string[]\n fileName?: string\n}\n\n/**\n * Execute pg_dump\n */\nexport async function pgDump({\n pg,\n args,\n fileName = 'dump.sql',\n}: PgDumpOptions) {\n const getSearchPath = await pg.query<{ search_path: string }>(\n 'SHOW SEARCH_PATH;',\n )\n const search_path = getSearchPath.rows[0].search_path\n\n const outFile = `/tmp/out.sql`\n const baseArgs = [\n '-U',\n 'postgres',\n '--inserts',\n '-j',\n '1',\n '-f',\n outFile,\n 'postgres',\n ]\n\n const [exitCode, acc, errorMessage] = await execPgDump({\n pg,\n args: [...(args ?? []), ...baseArgs],\n })\n\n pg.exec(`DEALLOCATE ALL; SET SEARCH_PATH = ${search_path}`)\n\n if (exitCode !== 0) {\n throw new Error(\n `pg_dump failed with exit code ${exitCode}. \\nError message: ${errorMessage}`,\n )\n }\n\n const file = new File(acc, fileName, {\n type: 'text/plain',\n })\n pg.Module.FS.unlink(outFile)\n\n return file\n}\n\n// Wire protocol messages for simulating auth handshake:\n\nfunction charToByte(char: string) {\n return char.charCodeAt(0)\n}\n\n// Function to convert an integer to a 4-byte array (Int32)\nfunction int32ToBytes(value: number) {\n const buffer = new ArrayBuffer(4)\n const view = new DataView(buffer)\n view.setInt32(0, value, false) // false for big-endian\n return new Uint8Array(buffer)\n}\n\n// Convert a string to a Uint8Array with a null terminator (C string)\nfunction stringToBytes(str: string) {\n const utf8Encoder = new TextEncoder()\n const strBytes = utf8Encoder.encode(str) // UTF-8 encoding\n return new Uint8Array([...strBytes, 0]) // Append null terminator\n}\n\nconst authOk = new Uint8Array([\n charToByte('R'),\n ...int32ToBytes(8),\n ...int32ToBytes(0),\n])\nconst readyForQuery = new Uint8Array([\n charToByte('Z'),\n ...int32ToBytes(5),\n charToByte('I'),\n])\n\nconst svParamName = stringToBytes('server_version')\nconst svParamValue = stringToBytes('16.3 (PGlite 0.2.0)')\nconst svTotalLength = 4 + svParamName.length + svParamValue.length\nconst versionParam = new Uint8Array([\n charToByte('S'),\n ...int32ToBytes(svTotalLength),\n ...svParamName,\n ...svParamValue,\n])\n"],"mappings":"mkBAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,YAAAE,KAAA,eAAAC,GAAAH,ICKA,IAAMI,GAAmB,IACvB,OAAO,SAAa,IAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,KAC7B,SAAS,eAAiB,SAAS,cAAc,KAClD,IAAI,IAAI,UAAW,SAAS,OAAO,EAAE,KAE9BC,EAAgCD,GAAiB,ECHvD,IAAME,EAAN,cAA2B,KAAM,CACtC,YAAYC,EAAM,CAChB,MAAM,kBAAkBA,CAAI,EAAE,EAC9B,KAAK,KAAOA,CACd,CACF,EAGaC,EAAN,KAAc,CACnB,eAAeC,EAAMC,EAAMC,EAAU,CAAC,EAAG,CACvC,MAAM,IAAI,MAAM,gCAAgC,CAClD,CAEA,UAAUC,EAAI,CACZ,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,SAASC,EAAcC,EAAS,CAC9B,MAAM,IAAI,MAAM,0BAA0B,CAC5C,CAEA,UAAUL,EAAME,EAAU,CAAC,EAAG,CAC5B,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,YAAYF,EAAME,EAAU,CAAC,EAAG,CAC9B,MAAM,IAAI,MAAM,6BAA6B,CAC/C,CAEA,aAAaF,EAAME,EAAU,CAAC,EAAG,CAC/B,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,aAAaF,EAAME,EAAU,CAAC,EAAG,CAC/B,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,WAAWI,EAASD,EAAS,CAC3B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,UAAUL,EAAME,EAAU,CAAC,EAAG,CAC5B,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,aAAaF,EAAMO,EAAO,CACxB,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,SAASP,EAAME,EAAU,CAAC,EAAG,CAC3B,MAAM,IAAI,MAAM,0BAA0B,CAC5C,CAEA,YAAYM,EAAQR,EAAMS,EAAO,OAAQ,CACvC,MAAM,IAAI,MAAM,6BAA6B,CAC/C,CAEA,aAAaT,EAAMU,EAAM,EAAG,CAC1B,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,WAAWV,EAAM,CACf,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,WAAWA,EAAMW,EAAOC,EAAO,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,cAAcZ,EAAMC,EAAMC,EAAU,CAAC,EAAG,CACtC,MAAM,IAAI,MAAM,+BAA+B,CACjD,CACF,EAEaW,EAAN,KAAmB,CACxB,YAAYX,EAAU,CAAC,EAAG,CAKxB,GAJA,KAAK,KAAOA,EAAQ,MAAQ,CAAC,EAC7B,KAAK,IAAMA,EAAQ,KAAO,CAAC,EAC3B,KAAK,GAAKA,EAAQ,IAAM,IAAIH,EAExB,CAAC,KAAK,GACR,MAAM,IAAI,MAAM,qCAAqC,EAKvD,KAAK,IAAM,IAAI,IAAI,CACjB,CAAC,EAAG,CAAE,KAAM,OAAQ,CAAC,EACrB,CAAC,EAAG,CAAE,KAAM,OAAQ,CAAC,EACrB,CAAC,EAAG,CAAE,KAAM,OAAQ,CAAC,EACrB,CAAC,EAAG,CAAE,KAAM,YAAa,YAAa,GAAI,CAAC,CAC7C,CAAC,EAED,KAAK,OAAS,KAAK,IAAI,KACvB,KAAK,YAAc,IAAI,YACvB,KAAK,YAAc,IAAI,YAGvB,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,EACvC,KAAK,eAAiB,KAAK,eAAe,KAAK,IAAI,EACnD,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAC7C,KAAK,kBAAoB,KAAK,kBAAkB,KAAK,IAAI,EACzD,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EACjD,KAAK,eAAiB,KAAK,eAAe,KAAK,IAAI,EACnD,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,EACvC,KAAK,QAAU,KAAK,QAAQ,KAAK,IAAI,EACrC,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,EACvC,KAAK,QAAU,KAAK,QAAQ,KAAK,IAAI,EACrC,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EACjD,KAAK,oBAAsB,KAAK,oBAAoB,KAAK,IAAI,EAC7D,KAAK,eAAiB,KAAK,eAAe,KAAK,IAAI,EACnD,KAAK,oBAAsB,KAAK,oBAAoB,KAAK,IAAI,EAC7D,KAAK,UAAY,KAAK,UAAU,KAAK,IAAI,EACzC,KAAK,kBAAoB,KAAK,kBAAkB,KAAK,IAAI,EACzD,KAAK,UAAY,KAAK,UAAU,KAAK,IAAI,EACzC,KAAK,UAAY,KAAK,UAAU,KAAK,IAAI,EACzC,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAC7C,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAC7C,KAAK,gBAAkB,KAAK,gBAAgB,KAAK,IAAI,EACrD,KAAK,qBAAuB,KAAK,qBAAqB,KAAK,IAAI,EAC/D,KAAK,sBAAwB,KAAK,sBAAsB,KAAK,IAAI,EACjE,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,EACvC,KAAK,UAAY,KAAK,UAAU,KAAK,IAAI,EACzC,KAAK,WAAa,KAAK,WAAW,KAAK,IAAI,EAC3C,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAC7C,KAAK,QAAU,KAAK,QAAQ,KAAK,IAAI,EACrC,KAAK,QAAU,KAAK,QAAQ,KAAK,IAAI,EACrC,KAAK,sBAAwB,K