diff --git a/packages/benchmark/benchmarks-rtt.js b/packages/benchmark/benchmarks-rtt.js
index 40d0eb0f..bf0bcfb2 100644
--- a/packages/benchmark/benchmarks-rtt.js
+++ b/packages/benchmark/benchmarks-rtt.js
@@ -15,6 +15,23 @@ const CONFIGURATIONS = new Map(
db: "pglite",
dataDir: "idb://benchmark-rtt",
},
+ {
+ label: "PGlite IDB
relaxed durability",
+ db: "pglite",
+ dataDir: "idb://benchmark-rtt-rd",
+ options: { relaxedDurability: true },
+ },
+ {
+ label: "PGlite OPFS AHP",
+ db: "pglite",
+ dataDir: "opfs-ahp://benchmark-rtt",
+ },
+ {
+ label: "PGlite OPFS AHP
relaxed durability",
+ db: "pglite",
+ dataDir: "opfs-ahp://benchmark-rtt-rd",
+ options: { relaxedDurability: true },
+ },
{
label: 'SQLite Memory',
db: 'wa-sqlite',
@@ -39,6 +56,14 @@ const CONFIGURATIONS = new Map(
vfsClass: 'OriginPrivateFileSystemVFS',
vfsArgs: []
},
+ {
+ label: 'SQLite OPFS AHP',
+ db: 'wa-sqlite',
+ isAsync: false,
+ vfsModule: './node_modules/wa-sqlite/src/examples/AccessHandlePoolVFS.js',
+ vfsClass: 'AccessHandlePoolVFS',
+ vfsArgs: ['/benchmark-rtt-sqlite-ahp']
+ },
].map((obj) => [obj.label, obj])
);
@@ -107,7 +132,11 @@ document.getElementById("start").addEventListener("click", async (event) => {
// Remove OPFS
const root = await navigator.storage.getDirectory();
for await (const handle of root.values()) {
- await root.removeEntry(handle.name, { recursive: true });
+ try {
+ await root.removeEntry(handle.name, { recursive: true });
+ } catch (e) {
+ // ignore
+ }
}
const Comlink = await ComlinkReady;
@@ -170,6 +199,6 @@ document.getElementById("start").addEventListener("click", async (event) => {
function addEntry(parent, text) {
const tag = parent.parentElement.tagName === "TBODY" ? "td" : "th";
const child = document.createElement(tag);
- child.textContent = text;
+ child.innerHTML = text;
parent.appendChild(child);
}
diff --git a/packages/benchmark/benchmarks.js b/packages/benchmark/benchmarks.js
index c4889111..96673f30 100644
--- a/packages/benchmark/benchmarks.js
+++ b/packages/benchmark/benchmarks.js
@@ -18,6 +18,24 @@ const CONFIGURATIONS = new Map(
label: "Emscripten IndexedDB FS",
dataDir: "idb://benchmark",
},
+ {
+ label: "Emscripten IndexedDB FS
relaxed durability",
+ dataDir: "idb://benchmark-rd",
+ options: { relaxedDurability: true },
+ },
+ {
+ label: "OPFS Access Handle Pool",
+ dataDir: "opfs-ahp://benchmark-ahp",
+ },
+ {
+ label: "OPFS Access Handle Pool
relaxed durability",
+ dataDir: "opfs-ahp://benchmark-ahp-rd",
+ options: { relaxedDurability: true },
+ },
+ // {
+ // label: "OPFS Worker",
+ // dataDir: "opfs-worker://benchmark-worker",
+ // },
].map((obj) => [obj.label, obj])
);
@@ -77,6 +95,16 @@ document.getElementById("start").addEventListener("click", async (event) => {
}
});
+ // Remove OPFS
+ const root = await navigator.storage.getDirectory();
+ for await (const handle of root.values()) {
+ try {
+ await root.removeEntry(handle.name, { recursive: true });
+ } catch (e) {
+ // ignore
+ }
+ }
+
const benchmarks = await benchmarksReady;
const Comlink = await ComlinkReady;
try {
@@ -101,6 +129,7 @@ document.getElementById("start").addEventListener("click", async (event) => {
const query = await workerProxy({
dataDir: config.dataDir,
label: config.label,
+ options: config.options,
});
await query(preamble);
@@ -123,6 +152,7 @@ document.getElementById("start").addEventListener("click", async (event) => {
document.getElementById("error").textContent = e.stack.includes(e.message)
? e.stack
: `${e.stack}\n${e.message}`;
+ throw e;
} finally {
// @ts-ignore
event.target.disabled = false;
@@ -132,6 +162,6 @@ document.getElementById("start").addEventListener("click", async (event) => {
function addEntry(parent, text) {
const tag = parent.parentElement.tagName === "TBODY" ? "td" : "th";
const child = document.createElement(tag);
- child.textContent = text;
+ child.innerHTML = text;
parent.appendChild(child);
}
diff --git a/packages/benchmark/demo-worker.js b/packages/benchmark/demo-worker.js
index 3ecac0e5..1df1e830 100644
--- a/packages/benchmark/demo-worker.js
+++ b/packages/benchmark/demo-worker.js
@@ -14,7 +14,20 @@ import { PGlite } from "../pglite/dist/index.js";
* @returns {Promise}
*/
async function open(config) {
- const pg = new PGlite(config.dataDir);
+ if (config.dataDir.startsWith("opfs-")) {
+ // delete the existing database
+ const root = await navigator.storage.getDirectory();
+ const dirName = config.dataDir.slice(config.dataDir.indexOf("://") + 3);
+ try {
+ const dir = await root.getDirectoryHandle(dirName, { create: false });
+ await dir.remove();
+ } catch (e) {
+ // ignore
+ }
+ }
+
+ console.log("Opening PGLite database:", JSON.stringify(config, null, 2));
+ const pg = new PGlite(config.dataDir, config.options);
await pg.waitReady;
// Create the query interface.
diff --git a/packages/benchmark/package.json b/packages/benchmark/package.json
index bcfbe9cc..99ab9c34 100644
--- a/packages/benchmark/package.json
+++ b/packages/benchmark/package.json
@@ -18,6 +18,6 @@
"tsx": "^4.7.1"
},
"dependencies": {
- "wa-sqlite": "github:rhashimoto/wa-sqlite"
+ "wa-sqlite": "github:rhashimoto/wa-sqlite#v0.9.14"
}
}
diff --git a/packages/benchmark/rtt-demo-worker.js b/packages/benchmark/rtt-demo-worker.js
index 4deb7875..c7d7af38 100644
--- a/packages/benchmark/rtt-demo-worker.js
+++ b/packages/benchmark/rtt-demo-worker.js
@@ -4,7 +4,7 @@
import * as SQLite from './node_modules/wa-sqlite/src/sqlite-api.js';
import { createTag } from "./node_modules/wa-sqlite/src/examples/tag.js";
-import { PGlite } from "../pglite/dist/index.js";
+import { PGlite } from "../pglite/dist/index.js?1";
const WA_SQLITE = './node_modules/wa-sqlite/dist/wa-sqlite.mjs';
const WA_SQLITE_ASYNC = './node_modules/wa-sqlite/dist/wa-sqlite-async.mjs';
@@ -15,18 +15,17 @@ const WA_SQLITE_ASYNC = './node_modules/wa-sqlite/dist/wa-sqlite-async.mjs';
);
async function open(config) {
- console.log('Opening database:', config)
if (config.db === 'wa-sqlite') {
- console.log('Opening SQLite database:', config)
+ console.log('Opening SQLite database:', JSON.stringify(config, null, 2))
return openSQLite(config);
} else if (config.db === 'pglite') {
- console.log('Opening PGLite database:', config)
+ console.log('Opening PGLite database:', JSON.stringify(config, null, 2))
return openPGlite(config);
}
}
async function openPGlite(config) {
- const pg = new PGlite(config.dataDir);
+ const pg = new PGlite(config.dataDir, config.options);
await pg.waitReady;
// Create the query interface.
diff --git a/packages/pglite/examples/opfs-worker.js b/packages/pglite/examples/opfs-worker.js
new file mode 100644
index 00000000..9d03d3d3
--- /dev/null
+++ b/packages/pglite/examples/opfs-worker.js
@@ -0,0 +1,12 @@
+import { PGlite } from "../dist/index.js";
+import { worker } from "../dist/worker/index.js";
+
+worker({
+ async init() {
+ const pg = new PGlite("opfs-ahp://my-test-db2");
+ // If you want run any specific setup code for the worker process, you can do it here.
+ return pg;
+ },
+});
+
+console.log("Worker process started");
diff --git a/packages/pglite/examples/opfs.html b/packages/pglite/examples/opfs.html
new file mode 100644
index 00000000..cf3cb6a1
--- /dev/null
+++ b/packages/pglite/examples/opfs.html
@@ -0,0 +1,49 @@
+
diff --git a/packages/pglite/package.json b/packages/pglite/package.json
index 990270c7..dc2aa804 100644
--- a/packages/pglite/package.json
+++ b/packages/pglite/package.json
@@ -21,15 +21,26 @@
".": "./dist/index.js",
"./live": "./dist/live/index.js",
"./worker": "./dist/worker/index.js",
- "./vector": "./dist/vector/index.js"
+ "./vector": "./dist/vector/index.js",
+ "./nodefs": "./dist/fs/nodefs.js",
+ "./opfs-ahp": "./dist/fs/opfs-ahp/index.js"
},
"typesVersions": {
"*": {
+ "live": [
+ "./dist/live/index.d.ts"
+ ],
"worker": [
"./dist/worker/index.d.ts"
],
"vector": [
"./dist/vector/index.d.ts"
+ ],
+ "nodefs": [
+ "./dist/fs/nodefs.d.ts"
+ ],
+ "opfs-ahp": [
+ "./dist/fs/opfs-ahp/index.d.ts"
]
}
},
@@ -49,6 +60,8 @@
"test:bun": "rm -rf ./pgdata-test && npx bun test tests/basic.test.js && npx bun test tests/pgvector.test.js && npx bun test tests/targets/node-fs.test.js",
"build:js": "tsup && tsx scripts/bundle-wasm.ts",
"build": "npm run build:js",
+ "dev": "concurrently \"tsup --watch\" \"sleep 1 && tsx scripts/bundle-wasm.ts\" \"pnpm dev-server\"",
+ "dev-server": "pnpm http-server ../",
"format": "prettier --write ./src"
},
"devDependencies": {
@@ -64,8 +77,9 @@
"pg-protocol": "^1.6.1",
"playwright": "^1.42.1",
"prettier": "3.2.5",
+ "serve": "^14.2.3",
"tinytar": "^0.1.0",
- "tsup": "^8.0.2",
+ "tsup": "^8.1.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3"
}
diff --git a/packages/pglite/src/fs/idbfs.ts b/packages/pglite/src/fs/idbfs.ts
index 4965c92e..6b62510d 100644
--- a/packages/pglite/src/fs/idbfs.ts
+++ b/packages/pglite/src/fs/idbfs.ts
@@ -38,7 +38,7 @@ export class IdbFs extends FilesystemBase {
});
}
- syncToFs(fs: FS) {
+ syncToFs(fs: FS, relaxedDurability?: boolean) {
return new Promise((resolve, reject) => {
fs.syncfs(false, (err: any) => {
if (err) {
diff --git a/packages/pglite/src/fs/index.ts b/packages/pglite/src/fs/index.ts
index 0dfd5423..ebe8844a 100644
--- a/packages/pglite/src/fs/index.ts
+++ b/packages/pglite/src/fs/index.ts
@@ -20,6 +20,10 @@ export function parseDataDir(dataDir?: string) {
// Remove the idb:// prefix, and use indexeddb filesystem
dataDir = dataDir.slice(6);
fsType = "idbfs";
+ } else if (dataDir?.startsWith("opfs-ahp://")) {
+ // Remove the opfsahp:// prefix, and use opfs access handle pool filesystem
+ dataDir = dataDir.slice(11);
+ fsType = "opfs-ahp";
} else if (!dataDir || dataDir?.startsWith("memory://")) {
// Use in-memory filesystem
fsType = "memoryfs";
@@ -38,6 +42,10 @@ export async function loadFs(dataDir?: string, fsType?: FsType) {
fs = new NodeFS(dataDir);
} else if (dataDir && fsType === "idbfs") {
fs = new IdbFs(dataDir);
+ } else if (dataDir && fsType === "opfs-ahp") {
+ // Lazy load the opfs-ahp to so that it's optional in the bundle
+ const { OpfsAhpFS } = await import("./opfs-ahp/index.js");
+ fs = new OpfsAhpFS(dataDir);
} else {
fs = new MemoryFS();
}
diff --git a/packages/pglite/src/fs/opfs-ahp/emscriptenFs.ts b/packages/pglite/src/fs/opfs-ahp/emscriptenFs.ts
new file mode 100644
index 00000000..ab168b3d
--- /dev/null
+++ b/packages/pglite/src/fs/opfs-ahp/emscriptenFs.ts
@@ -0,0 +1,371 @@
+import type { PostgresMod } from "../../postgresMod.js";
+import type { OpfsAhp } from "./opfsAhp.js";
+import { FsError, ERRNO_CODES } from "./types.js";
+
+export type FileSystemType = Emscripten.FileSystemType & {
+ createNode: (
+ parent: FSNode | null,
+ name: string,
+ mode: number,
+ dev?: any,
+ ) => FSNode;
+ node_ops: FS.NodeOps;
+ stream_ops: FS.StreamOps & {
+ dup: (stream: FSStream) => void;
+ mmap: (
+ stream: FSStream,
+ length: number,
+ position: number,
+ prot: any,
+ flags: any,
+ ) => { ptr: number; allocated: boolean };
+ msync: (
+ stream: FSStream,
+ buffer: Uint8Array,
+ offset: number,
+ length: number,
+ mmapFlags: any,
+ ) => number;
+ };
+} & { [key: string]: any };
+
+type FSNode = FS.FSNode & {
+ node_ops: FS.NodeOps;
+ stream_ops: FS.StreamOps;
+};
+
+type FSStream = FS.FSStream & {
+ node: FSNode;
+ shared: {
+ refcount: number;
+ };
+};
+
+export interface OpfsMount extends FS.Mount {
+ opts: {
+ root: string;
+ };
+}
+
+type OpfsNode = FSNode & {};
+
+type EmscriptenFS = PostgresMod["FS"] & {
+ createNode: (
+ parent: FSNode | null,
+ name: string,
+ mode: number,
+ dev?: any,
+ ) => FSNode;
+};
+
+/**
+ * Create an emscripten filesystem that uses the AHP filesystem.
+ * @param Module The emscripten module
+ * @param opfsAhp The AHP filesystem - see `OpfsAhp.ts`
+ * @returns The emscripten filesystem
+ */
+export const createOPFSAHP = (Module: PostgresMod, opfsAhp: OpfsAhp) => {
+ const FS = Module.FS as EmscriptenFS;
+ const OPFS = {
+ tryFSOperation(f: () => T): T {
+ try {
+ return f();
+ } catch (e: any) {
+ if (!e.code) throw e;
+ if (e.code === "UNKNOWN") throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ throw new FS.ErrnoError(e.code);
+ }
+ },
+ mount(mount: OpfsMount): FSNode {
+ return OPFS.createNode(null, "/", 16384 | 511, 0);
+ },
+ syncfs(
+ mount: FS.Mount,
+ populate: any, // This has the wrong type in @types/emscripten
+ done: (err?: number | null) => unknown,
+ ): void {
+ // noop
+ },
+ createNode(
+ parent: FSNode | null,
+ name: string,
+ mode: number,
+ dev?: any,
+ ): OpfsNode {
+ if (!FS.isDir(mode) && !FS.isFile(mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ const node = FS.createNode(parent, name, mode);
+ node.node_ops = OPFS.node_ops;
+ node.stream_ops = OPFS.stream_ops;
+ return node;
+ },
+ getMode: function (path: string): number {
+ log("getMode", path);
+ return OPFS.tryFSOperation(() => {
+ const stats = opfsAhp.lstat(path);
+ return stats.mode;
+ });
+ },
+ realPath: function (node: FSNode): string {
+ const parts = [];
+ while (node.parent !== node) {
+ parts.push(node.name);
+ node = node.parent as FSNode;
+ }
+ parts.push((node.mount as OpfsMount).opts.root);
+ parts.reverse();
+ return parts.join("/");
+ },
+ node_ops: {
+ getattr(node: OpfsNode): FS.Stats {
+ log("getattr", OPFS.realPath(node));
+ const path = OPFS.realPath(node);
+ return OPFS.tryFSOperation(() => {
+ const stats = opfsAhp.lstat(path);
+ return {
+ ...stats,
+ dev: 0,
+ ino: node.id,
+ nlink: 1,
+ rdev: node.rdev,
+ atime: new Date(stats.atime),
+ mtime: new Date(stats.mtime),
+ ctime: new Date(stats.ctime),
+ };
+ });
+ },
+ setattr(node: OpfsNode, attr: FS.Stats): void {
+ log("setattr", OPFS.realPath(node), attr);
+ var path = OPFS.realPath(node);
+ OPFS.tryFSOperation(() => {
+ if (attr.mode !== undefined) {
+ opfsAhp.chmod(path, attr.mode);
+ }
+ if (attr.size !== undefined) {
+ opfsAhp.truncate(path, attr.size);
+ }
+ if (attr.timestamp !== undefined) {
+ opfsAhp.utimes(path, attr.timestamp, attr.timestamp);
+ }
+ if (attr.size !== undefined) {
+ opfsAhp.truncate(path, attr.size);
+ }
+ });
+ },
+ lookup(parent: FSNode, name: string): OpfsNode {
+ log("lookup", OPFS.realPath(parent), name);
+ const path = [OPFS.realPath(parent), name].join("/");
+ const mode = OPFS.getMode(path);
+ return OPFS.createNode(parent, name, mode);
+ },
+ mknod(
+ parent: FSNode,
+ name: string,
+ mode: number,
+ dev: unknown,
+ ): OpfsNode {
+ log("mknod", OPFS.realPath(parent), name, mode, dev);
+ const node = OPFS.createNode(parent, name, mode, dev);
+ // create the backing node for this in the fs root as well
+ const path = OPFS.realPath(node);
+ return OPFS.tryFSOperation(() => {
+ if (FS.isDir(node.mode)) {
+ opfsAhp.mkdir(path, { mode });
+ } else {
+ opfsAhp.writeFile(path, "", { mode });
+ }
+ return node;
+ });
+ },
+ rename(oldNode: OpfsNode, newDir: OpfsNode, newName: string): void {
+ log("rename", OPFS.realPath(oldNode), OPFS.realPath(newDir), newName);
+ const oldPath = OPFS.realPath(oldNode);
+ const newPath = [OPFS.realPath(newDir), newName].join("/");
+ OPFS.tryFSOperation(() => {
+ opfsAhp.rename(oldPath, newPath);
+ });
+ oldNode.name = newName;
+ },
+ unlink(parent: OpfsNode, name: string): void {
+ log("unlink", OPFS.realPath(parent), name);
+ const path = [OPFS.realPath(parent), name].join("/");
+ try {
+ opfsAhp.unlink(path);
+ } catch (e: any) {}
+ },
+ rmdir(parent: OpfsNode, name: string): void {
+ log("rmdir", OPFS.realPath(parent), name);
+ const path = [OPFS.realPath(parent), name].join("/");
+ return OPFS.tryFSOperation(() => {
+ opfsAhp.rmdir(path);
+ });
+ },
+ readdir(node: OpfsNode): string[] {
+ log("readdir", OPFS.realPath(node));
+ const path = OPFS.realPath(node);
+ return OPFS.tryFSOperation(() => {
+ return opfsAhp.readdir(path);
+ });
+ },
+ symlink(parent: FSNode, newName: string, oldPath: string): void {
+ log("symlink", OPFS.realPath(parent), newName, oldPath);
+ // This is not supported by OPFS
+ throw new FS.ErrnoError(63);
+ },
+ readlink(node: FSNode): string {
+ log("readlink", OPFS.realPath(node));
+ // This is not supported by OPFS
+ throw new FS.ErrnoError(63);
+ },
+ },
+ stream_ops: {
+ open(stream: FSStream): void {
+ log("open stream", OPFS.realPath(stream.node));
+ const path = OPFS.realPath(stream.node);
+ return OPFS.tryFSOperation(() => {
+ if (FS.isFile(stream.node.mode)) {
+ stream.shared.refcount = 1;
+ stream.nfd = opfsAhp.open(path);
+ }
+ });
+ },
+ close(stream: FSStream): void {
+ log("close stream", OPFS.realPath(stream.node));
+ return OPFS.tryFSOperation(() => {
+ if (
+ FS.isFile(stream.node.mode) &&
+ stream.nfd &&
+ --stream.shared.refcount === 0
+ ) {
+ opfsAhp.close(stream.nfd);
+ }
+ });
+ },
+ dup(stream: FSStream) {
+ log("dup stream", OPFS.realPath(stream.node));
+ stream.shared.refcount++;
+ },
+ read(
+ stream: FSStream, // Stream to read from
+ buffer: Uint8Array, // Buffer to read into - Wrong type in @types/emscripten
+ offset: number, // Offset in buffer to start writing to
+ length: number, // Number of bytes to read
+ position: number, // Position in file to read from
+ ): number {
+ log(
+ "read stream",
+ OPFS.realPath(stream.node),
+ offset,
+ length,
+ position,
+ );
+ if (length === 0) return 0;
+ const ret = OPFS.tryFSOperation(() =>
+ opfsAhp.read(
+ stream.nfd!,
+ buffer as unknown as Int8Array,
+ offset,
+ length,
+ position,
+ ),
+ );
+ return ret;
+ },
+ write(
+ stream: FSStream, // Stream to write to
+ buffer: Uint8Array, // Buffer to read from - Wrong type in @types/emscripten
+ offset: number, // Offset in buffer to start writing from
+ length: number, // Number of bytes to write
+ position: number, // Position in file to write to
+ ): number {
+ log(
+ "write stream",
+ OPFS.realPath(stream.node),
+ offset,
+ length,
+ position,
+ );
+ return OPFS.tryFSOperation(() =>
+ opfsAhp.write(
+ stream.nfd!,
+ buffer.buffer as unknown as Int8Array,
+ offset,
+ length,
+ position,
+ ),
+ );
+ },
+ llseek(stream: FSStream, offset: number, whence: number): number {
+ log("llseek stream", OPFS.realPath(stream.node), offset, whence);
+ var position = offset;
+ if (whence === 1) {
+ position += stream.position;
+ } else if (whence === 2) {
+ if (FS.isFile(stream.node.mode)) {
+ OPFS.tryFSOperation(() => {
+ var stat = opfsAhp.fstat(stream.nfd!);
+ position += stat.size;
+ });
+ }
+ }
+ if (position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ return position;
+ },
+ mmap(
+ stream: FSStream,
+ length: number,
+ position: number,
+ prot: any,
+ flags: any,
+ ) {
+ log(
+ "mmap stream",
+ OPFS.realPath(stream.node),
+ length,
+ position,
+ prot,
+ flags,
+ );
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
+ }
+
+ var ptr = (Module as any).mmapAlloc(length); // TODO: Fix type and check this is exported
+
+ OPFS.stream_ops.read(
+ stream,
+ Module.HEAP8 as unknown as Uint8Array,
+ ptr,
+ length,
+ position,
+ );
+ return { ptr, allocated: true };
+ },
+ msync(
+ stream: FSStream,
+ buffer: Uint8Array,
+ offset: number,
+ length: number,
+ mmapFlags: any,
+ ) {
+ log(
+ "msync stream",
+ OPFS.realPath(stream.node),
+ offset,
+ length,
+ mmapFlags,
+ );
+ OPFS.stream_ops.write(stream, buffer, 0, length, offset);
+ return 0;
+ },
+ },
+ } satisfies FileSystemType;
+ return OPFS;
+};
+
+function log(...args: any[]) {
+ // console.log(...args);
+}
diff --git a/packages/pglite/src/fs/opfs-ahp/index.ts b/packages/pglite/src/fs/opfs-ahp/index.ts
new file mode 100644
index 00000000..a4dee6c3
--- /dev/null
+++ b/packages/pglite/src/fs/opfs-ahp/index.ts
@@ -0,0 +1,67 @@
+import { FilesystemBase } from "../types.js";
+import { PGDATA } from "../index.js";
+import type { PostgresMod, FS } from "../../postgresMod.js";
+import { createOPFSAHP } from "./emscriptenFs.js";
+import { OpfsAhp } from "./opfsAhp.js";
+import { dumpTar } from "../tarUtils.js";
+
+export interface OpfsAhpFSOptions {
+ initialPoolSize?: number;
+ maintainedPoolSize?: number;
+}
+
+/**
+ * PGlite OPFS access handle pool filesystem.
+ * Opens a pool of sync access handles and then allocates them as needed.
+ */
+export class OpfsAhpFS extends FilesystemBase {
+ #initialPoolSize: number;
+ #maintainedPoolSize: number;
+ opfsAhp?: OpfsAhp;
+
+ constructor(
+ dataDir: string,
+ { initialPoolSize, maintainedPoolSize }: OpfsAhpFSOptions = {},
+ ) {
+ super(dataDir);
+ this.#initialPoolSize = initialPoolSize ?? 1000;
+ this.#maintainedPoolSize = maintainedPoolSize ?? 100;
+ }
+
+ async emscriptenOpts(opts: Partial) {
+ this.opfsAhp = await OpfsAhp.create({
+ root: this.dataDir!,
+ initialPoolSize: this.#initialPoolSize,
+ maintainedPoolSize: this.#maintainedPoolSize,
+ });
+ const options: Partial = {
+ ...opts,
+ preRun: [
+ ...(opts.preRun || []),
+ (mod: PostgresMod) => {
+ const OPFS = createOPFSAHP(mod, this.opfsAhp!);
+ mod.FS.mkdir(PGDATA);
+ mod.FS.mount(OPFS, {}, PGDATA);
+ },
+ ],
+ };
+ return options;
+ }
+
+ async syncToFs(fs: FS, relaxedDurability = false) {
+ await this.opfsAhp?.maybeCheckpointState();
+ await this.opfsAhp?.maintainPool();
+ // console.log("syncToFs", relaxedDurability);
+ if (!relaxedDurability) {
+ this.opfsAhp?.flush();
+ }
+ }
+
+ async dumpTar(mod: FS, dbname: string) {
+ return dumpTar(mod, dbname);
+ }
+
+ async close(): Promise {
+ this.opfsAhp?.exit();
+ }
+}
diff --git a/packages/pglite/src/fs/opfs-ahp/opfsAhp.ts b/packages/pglite/src/fs/opfs-ahp/opfsAhp.ts
new file mode 100644
index 00000000..2af10555
--- /dev/null
+++ b/packages/pglite/src/fs/opfs-ahp/opfsAhp.ts
@@ -0,0 +1,670 @@
+import { FsError } from "./types.js";
+import type {
+ FsStats,
+ State,
+ FileSystemSyncAccessHandle,
+ Node,
+ FileNode,
+ DirectoryNode,
+ WALEntry,
+} from "./types.js";
+
+const STATE_FILE = "state.txt";
+const DATA_DIR = "data";
+const INITIAL_MODE = {
+ DIR: 16384,
+ FILE: 32768,
+};
+
+export interface OpfsAhpOptions {
+ root: string;
+ initialPoolSize?: number;
+ maintainedPoolSize?: number;
+}
+
+/**
+ * An OPFS Access Handle Pool VFS that exports a Node.js-like FS interface.
+ * This FS is then wrapped by an Emscripten FS interface in emscriptenFs.ts.
+ */
+export class OpfsAhp {
+ readyPromise: Promise;
+ #ready = false;
+
+ readonly root: string;
+ readonly initialPoolSize: number;
+ readonly maintainedPoolSize: number;
+
+ #opfsRootAh!: FileSystemDirectoryHandle;
+ #rootAh!: FileSystemDirectoryHandle;
+ #dataDirAh!: FileSystemDirectoryHandle;
+
+ #stateFH!: FileSystemFileHandle;
+ #stateSH!: FileSystemSyncAccessHandle;
+
+ #fh: Map = new Map();
+ #sh: Map = new Map();
+
+ #handleIdCounter = 0;
+ #openHandlePaths: Map = new Map();
+ #openHandleIds: Map = new Map();
+
+ state!: State;
+ lastCheckpoint = 0;
+ checkpointInterval = 1000 * 60; // 1 minute
+ poolCounter = 0;
+
+ #unsyncedSH = new Set();
+
+ constructor({ root, initialPoolSize, maintainedPoolSize }: OpfsAhpOptions) {
+ this.root = root;
+ this.initialPoolSize = initialPoolSize || 1000;
+ this.maintainedPoolSize = maintainedPoolSize || 100;
+ this.readyPromise = this.#init();
+ }
+
+ static async create(options: OpfsAhpOptions) {
+ const instance = new OpfsAhp(options);
+ await instance.readyPromise;
+ return instance;
+ }
+
+ async #init() {
+ this.#opfsRootAh = await navigator.storage.getDirectory();
+ this.#rootAh = await this.#resolveOpfsDirectory(this.root, {
+ create: true,
+ });
+ this.#dataDirAh = await this.#resolveOpfsDirectory(DATA_DIR, {
+ from: this.#rootAh,
+ create: true,
+ });
+
+ this.#stateFH = await this.#rootAh.getFileHandle(STATE_FILE, {
+ create: true,
+ });
+ this.#stateSH = await (this.#stateFH as any).createSyncAccessHandle();
+
+ const stateAB = new ArrayBuffer(this.#stateSH.getSize());
+ this.#stateSH.read(stateAB, { at: 0 });
+ let state: State;
+ const stateLines = new TextDecoder().decode(stateAB).split("\n");
+ // Line 1 is a base state object.
+ // Lines 1+n are WAL entries.
+
+ let isNewState = false;
+ try {
+ state = JSON.parse(stateLines[0]);
+ } catch (e) {
+ state = {
+ root: {
+ type: "directory",
+ lastModified: Date.now(),
+ mode: INITIAL_MODE.DIR,
+ children: {},
+ },
+ pool: [],
+ };
+ // write new state to file
+ this.#stateSH.truncate(0);
+ this.#stateSH.write(new TextEncoder().encode(JSON.stringify(state)), {
+ at: 0,
+ });
+ isNewState = true;
+ }
+ this.state = state;
+
+ // Apply WAL entries
+ const wal = stateLines
+ .slice(1)
+ .filter(Boolean)
+ .map((line) => JSON.parse(line));
+ for (const entry of wal) {
+ const methodName = `_${entry.opp}State`;
+ if (typeof this[methodName as keyof this] === "function") {
+ try {
+ (this[methodName as keyof this] as any)(...entry.args);
+ } catch (e) {
+ console.warn("Error applying OPFS AHP WAL entry", entry, e);
+ }
+ }
+ }
+
+ // Open all file handles for dir tree
+ const walkPromises: Promise[] = [];
+ const walk = async (node: Node) => {
+ if (node.type === "file") {
+ try {
+ const fh = await this.#dataDirAh.getFileHandle(node.backingFilename);
+ const sh: FileSystemSyncAccessHandle = await (
+ fh as any
+ ).createSyncAccessHandle();
+ this.#fh.set(node.backingFilename, fh);
+
+ this.#sh.set(node.backingFilename, sh);
+ } catch (e) {
+ console.error("Error opening file handle for node", node, e);
+ }
+ } else {
+ for (const child of Object.values(node.children)) {
+ walkPromises.push(walk(child));
+ }
+ }
+ };
+ await walk(this.state.root);
+
+ // Open all pool file handles
+ const poolPromises: Promise[] = [];
+ for (const filename of this.state.pool) {
+ poolPromises.push(
+ new Promise(async (resolve) => {
+ if (this.#fh.has(filename)) {
+ console.warn("File handle already exists for pool file", filename);
+ }
+ const fh = await this.#dataDirAh.getFileHandle(filename);
+ const sh: FileSystemSyncAccessHandle = await (
+ fh as any
+ ).createSyncAccessHandle();
+ this.#fh.set(filename, fh);
+ this.#sh.set(filename, sh);
+ resolve();
+ }),
+ );
+ }
+
+ await Promise.all([...walkPromises, ...poolPromises]);
+
+ await this.maintainPool(
+ isNewState ? this.initialPoolSize : this.maintainedPoolSize,
+ );
+
+ this.#ready = true;
+ }
+
+ get ready() {
+ return this.#ready;
+ }
+
+ async maintainPool(size?: number) {
+ size = size || this.maintainedPoolSize;
+ const change = size - this.state.pool.length;
+ const promises: Promise[] = [];
+ for (let i = 0; i < change; i++) {
+ promises.push(
+ new Promise(async (resolve) => {
+ ++this.poolCounter;
+ const filename = `${(Date.now() - 1704063600).toString(16).padStart(8, "0")}-${this.poolCounter.toString(16).padStart(8, "0")}`;
+ const fh = await this.#dataDirAh.getFileHandle(filename, {
+ create: true,
+ });
+ const sh: FileSystemSyncAccessHandle = await (
+ fh as any
+ ).createSyncAccessHandle();
+ this.#fh.set(filename, fh);
+ this.#sh.set(filename, sh);
+ this.#logWAL({
+ opp: "createPoolFile",
+ args: [filename],
+ });
+ this.state.pool.push(filename);
+ resolve();
+ }),
+ );
+ }
+ for (let i = 0; i > change; i--) {
+ promises.push(
+ new Promise(async (resolve) => {
+ const filename = this.state.pool.pop()!;
+ this.#logWAL({
+ opp: "deletePoolFile",
+ args: [filename],
+ });
+ const fh = this.#fh.get(filename)!;
+ const sh = this.#sh.get(filename);
+ sh?.close();
+ // @ts-ignore
+ await fh.remove();
+ this.#fh.delete(filename);
+ this.#sh.delete(filename);
+ resolve();
+ }),
+ );
+ }
+ await Promise.all(promises);
+ }
+
+ _createPoolFileState(filename: string) {
+ this.state.pool.push(filename);
+ }
+
+ _deletePoolFileState(filename: string) {
+ const index = this.state.pool.indexOf(filename);
+ if (index > -1) {
+ this.state.pool.splice(index, 1);
+ }
+ }
+
+ async maybeCheckpointState() {
+ if (Date.now() - this.lastCheckpoint > this.checkpointInterval) {
+ await this.checkpointState();
+ }
+ }
+
+ async checkpointState() {
+ const stateAB = new TextEncoder().encode(JSON.stringify(this.state));
+ this.#stateSH.truncate(0);
+ this.#stateSH.write(stateAB, { at: 0 });
+ this.#stateSH.flush();
+ this.lastCheckpoint = Date.now();
+ }
+
+ flush() {
+ for (const sh of this.#unsyncedSH) {
+ try {
+ sh.flush();
+ } catch (e) {} // The file may have been closed if it was deleted
+ }
+ this.#unsyncedSH.clear();
+ }
+
+ exit(): void {
+ for (const sh of this.#sh.values()) {
+ sh.close();
+ }
+ this.#stateSH.flush();
+ this.#stateSH.close();
+ }
+
+ // Filesystem API:
+
+ chmod(path: string, mode: number): void {
+ this.#tryWithWAL({ opp: "chmod", args: [path, mode] }, () => {
+ this._chmodState(path, mode);
+ });
+ }
+
+ _chmodState(path: string, mode: number): void {
+ const node = this.#resolvePath(path);
+ node.mode = mode;
+ }
+
+ close(fd: number): void {
+ const path = this.#getPathFromFd(fd);
+ this.#openHandlePaths.delete(fd);
+ this.#openHandleIds.delete(path);
+ }
+
+ fstat(fd: number): FsStats {
+ const path = this.#getPathFromFd(fd);
+ return this.lstat(path);
+ }
+
+ lstat(path: string): FsStats {
+ const node = this.#resolvePath(path);
+ const size =
+ node.type === "file" ? this.#sh.get(node.backingFilename)!.getSize() : 0;
+ const blksize = 4096;
+ return {
+ dev: 0,
+ ino: 0,
+ mode: node.mode,
+ nlink: 1,
+ uid: 0,
+ gid: 0,
+ rdev: 0,
+ size,
+ blksize,
+ blocks: Math.ceil(size / blksize),
+ atime: node.lastModified,
+ mtime: node.lastModified,
+ ctime: node.lastModified,
+ };
+ }
+
+ mkdir(path: string, options?: { recursive?: boolean; mode?: number }): void {
+ this.#tryWithWAL({ opp: "mkdir", args: [path, options] }, () => {
+ this._mkdirState(path, options);
+ });
+ }
+
+ _mkdirState(
+ path: string,
+ options?: { recursive?: boolean; mode?: number },
+ ): void {
+ const parts = this.#pathParts(path);
+ const newDirName = parts.pop()!;
+ let currentPath = [];
+ let node = this.state.root;
+ for (const part of parts) {
+ currentPath.push(path);
+ if (!node.children.hasOwnProperty(part)) {
+ if (options?.recursive) {
+ this.mkdir(currentPath.join("/"));
+ } else {
+ throw new FsError("ENOENT", "No such file or directory");
+ }
+ }
+ if (node.children[part].type !== "directory") {
+ throw new FsError("ENOTDIR", "Not a directory");
+ }
+ node = node.children[part] as DirectoryNode;
+ }
+ if (node.children.hasOwnProperty(newDirName)) {
+ throw new FsError("EEXIST", "File exists");
+ }
+ const newDir: DirectoryNode = {
+ type: "directory",
+ lastModified: Date.now(),
+ mode: options?.mode || INITIAL_MODE.DIR,
+ children: {},
+ };
+ node.children[newDirName] = newDir;
+ }
+
+ open(path: string, flags?: string, mode?: number): number {
+ const node = this.#resolvePath(path);
+ if (node.type !== "file") {
+ throw new FsError("EISDIR", "Is a directory");
+ }
+ const handleId = this.#nextHandleId();
+ this.#openHandlePaths.set(handleId, path);
+ this.#openHandleIds.set(path, handleId);
+ return handleId;
+ }
+
+ readdir(path: string): string[] {
+ const node = this.#resolvePath(path);
+ if (node.type !== "directory") {
+ throw new FsError("ENOTDIR", "Not a directory");
+ }
+ return Object.keys(node.children);
+ }
+
+ read(
+ fd: number,
+ buffer: Int8Array, // Buffer to read into
+ offset: number, // Offset in buffer to start writing to
+ length: number, // Number of bytes to read
+ position: number, // Position in file to read from
+ ): number {
+ const path = this.#getPathFromFd(fd);
+ const node = this.#resolvePath(path);
+ if (node.type !== "file") {
+ throw new FsError("EISDIR", "Is a directory");
+ }
+ const sh = this.#sh.get(node.backingFilename)!;
+ return sh.read(new Int8Array(buffer.buffer, offset, length), {
+ at: position,
+ });
+ }
+
+ rename(oldPath: string, newPath: string): void {
+ this.#tryWithWAL({ opp: "rename", args: [oldPath, newPath] }, () => {
+ this._renameState(oldPath, newPath, true);
+ });
+ }
+
+ _renameState(oldPath: string, newPath: string, doFileOps = false): void {
+ const oldPathParts = this.#pathParts(oldPath);
+ const oldFilename = oldPathParts.pop()!;
+ const oldParent = this.#resolvePath(
+ oldPathParts.join("/"),
+ ) as DirectoryNode;
+ if (!oldParent.children.hasOwnProperty(oldFilename)) {
+ throw new FsError("ENOENT", "No such file or directory");
+ }
+ const newPathParts = this.#pathParts(newPath);
+ const newFilename = newPathParts.pop()!;
+ const newParent = this.#resolvePath(
+ newPathParts.join("/"),
+ ) as DirectoryNode;
+ if (doFileOps && newParent.children.hasOwnProperty(newFilename)) {
+ // Overwrite, so return the underlying file to the pool
+ const node = newParent.children[newFilename]! as FileNode;
+ const sh = this.#sh.get(node.backingFilename)!;
+ sh.truncate(0);
+ this.state.pool.push(node.backingFilename);
+ }
+ newParent.children[newFilename] = oldParent.children[oldFilename]!;
+ delete oldParent.children[oldFilename];
+ }
+
+ rmdir(path: string): void {
+ this.#tryWithWAL({ opp: "rmdir", args: [path] }, () => {
+ this._rmdirState(path);
+ });
+ }
+
+ _rmdirState(path: string): void {
+ const pathParts = this.#pathParts(path);
+ const dirName = pathParts.pop()!;
+ const parent = this.#resolvePath(pathParts.join("/")) as DirectoryNode;
+ if (!parent.children.hasOwnProperty(dirName)) {
+ throw new FsError("ENOENT", "No such file or directory");
+ }
+ const node = parent.children[dirName]!;
+ if (node.type !== "directory") {
+ throw new FsError("ENOTDIR", "Not a directory");
+ }
+ if (Object.keys(node.children).length > 0) {
+ throw new FsError("ENOTEMPTY", "Directory not empty");
+ }
+ delete parent.children[dirName];
+ }
+
+ truncate(path: string, len = 0): void {
+ const node = this.#resolvePath(path);
+ if (node.type !== "file") {
+ throw new FsError("EISDIR", "Is a directory");
+ }
+ const sh = this.#sh.get(node.backingFilename);
+ if (!sh) {
+ throw new FsError("ENOENT", "No such file or directory");
+ }
+ sh.truncate(len);
+ this.#unsyncedSH.add(sh);
+ }
+
+ unlink(path: string): void {
+ this.#tryWithWAL({ opp: "unlink", args: [path] }, () => {
+ this._unlinkState(path, true);
+ });
+ }
+
+ _unlinkState(path: string, doFileOps = false): void {
+ const pathParts = this.#pathParts(path);
+ const filename = pathParts.pop()!;
+ const dir = this.#resolvePath(pathParts.join("/")) as DirectoryNode;
+ if (!dir.children.hasOwnProperty(filename)) {
+ throw new FsError("ENOENT", "No such file or directory");
+ }
+ const node = dir.children[filename]!;
+ if (node.type !== "file") {
+ throw new FsError("EISDIR", "Is a directory");
+ }
+ delete dir.children[filename];
+ if (doFileOps) {
+ const sh = this.#sh.get(node.backingFilename)!;
+ // We don't delete the file, it's truncated and returned to the pool
+ sh?.truncate(0);
+ this.#unsyncedSH.add(sh);
+ if (this.#openHandleIds.has(path)) {
+ this.#openHandlePaths.delete(this.#openHandleIds.get(path)!);
+ this.#openHandleIds.delete(path);
+ }
+ }
+ this.state.pool.push(node.backingFilename);
+ }
+
+ utimes(path: string, atime: number, mtime: number): void {
+ this.#tryWithWAL({ opp: "utimes", args: [path, atime, mtime] }, () => {
+ this._utimesState(path, atime, mtime);
+ });
+ }
+
+ _utimesState(path: string, atime: number, mtime: number): void {
+ const node = this.#resolvePath(path);
+ node.lastModified = mtime;
+ }
+
+ writeFile(
+ path: string,
+ data: string | Int8Array,
+ options?: { encoding?: string; mode?: number; flag?: string },
+ ): void {
+ const pathParts = this.#pathParts(path);
+ const filename = pathParts.pop()!;
+ const parent = this.#resolvePath(pathParts.join("/")) as DirectoryNode;
+
+ if (!parent.children.hasOwnProperty(filename)) {
+ if (this.state.pool.length === 0) {
+ throw new Error("No more file handles available in the pool");
+ }
+ const node: Node = {
+ type: "file",
+ lastModified: Date.now(),
+ mode: options?.mode || INITIAL_MODE.FILE,
+ backingFilename: this.state.pool.pop()!,
+ };
+ parent.children[filename] = node;
+ this.#logWAL({
+ opp: "createFileNode",
+ args: [path, node],
+ });
+ } else {
+ const node = parent.children[filename] as FileNode;
+ node.lastModified = Date.now();
+ this.#logWAL({
+ opp: "setLastModified",
+ args: [path, node.lastModified],
+ });
+ }
+ const node = parent.children[filename] as FileNode;
+ const sh = this.#sh.get(node.backingFilename)!;
+ // Files in pool are empty, only write if data is provided
+ if (data.length > 0) {
+ sh.write(
+ typeof data === "string"
+ ? new TextEncoder().encode(data)
+ : new Int8Array(data),
+ { at: 0 },
+ );
+ if (path.startsWith("/pg_wal")) {
+ this.#unsyncedSH.add(sh);
+ }
+ }
+ }
+
+ _createFileNodeState(path: string, node: FileNode): FileNode {
+ const pathParts = this.#pathParts(path);
+ const filename = pathParts.pop()!;
+ const parent = this.#resolvePath(pathParts.join("/")) as DirectoryNode;
+ parent.children[filename] = node;
+ // remove backingFilename from pool
+ const index = this.state.pool.indexOf(node.backingFilename);
+ if (index > -1) {
+ this.state.pool.splice(index, 1);
+ }
+ return node;
+ }
+
+ _setLastModifiedState(path: string, lastModified: number): void {
+ const node = this.#resolvePath(path);
+ node.lastModified = lastModified;
+ }
+
+ write(
+ fd: number,
+ buffer: Int8Array, // Buffer to read from
+ offset: number, // Offset in buffer to start reading from
+ length: number, // Number of bytes to write
+ position: number, // Position in file to write to
+ ): number {
+ const path = this.#getPathFromFd(fd);
+ const node = this.#resolvePath(path);
+ if (node.type !== "file") {
+ throw new FsError("EISDIR", "Is a directory");
+ }
+ const sh = this.#sh.get(node.backingFilename);
+ if (!sh) {
+ throw new FsError("EBADF", "Bad file descriptor");
+ }
+ const ret = sh.write(new Int8Array(buffer, offset, length), {
+ at: position,
+ });
+ if (path.startsWith("/pg_wal")) {
+ this.#unsyncedSH.add(sh);
+ }
+ return ret;
+ }
+
+ // Internal methods:
+
+ #tryWithWAL(entry: WALEntry, fn: () => void) {
+ const offset = this.#logWAL(entry);
+ try {
+ fn();
+ } catch (e) {
+ // Rollback WAL entry
+ this.#stateSH.truncate(offset);
+ throw e;
+ }
+ }
+
+ #logWAL(entry: WALEntry) {
+ const entryJSON = JSON.stringify(entry);
+ const stateAB = new TextEncoder().encode(`\n${entryJSON}`);
+ const offset = this.#stateSH.getSize();
+ this.#stateSH.write(stateAB, { at: offset });
+ this.#unsyncedSH.add(this.#stateSH);
+ return offset;
+ }
+
+ #pathParts(path: string): string[] {
+ return path.split("/").filter(Boolean);
+ }
+
+ #resolvePath(path: string, from?: DirectoryNode): Node {
+ const parts = this.#pathParts(path);
+ let node: Node = from || this.state.root;
+ for (const part of parts) {
+ if (node.type !== "directory") {
+ throw new FsError("ENOTDIR", "Not a directory");
+ }
+ if (!node.children.hasOwnProperty(part)) {
+ throw new FsError("ENOENT", "No such file or directory");
+ }
+ node = node.children[part]!;
+ }
+ return node;
+ }
+
+ #getPathFromFd(fd: number): string {
+ const path = this.#openHandlePaths.get(fd);
+ if (!path) {
+ throw new FsError("EBADF", "Bad file descriptor");
+ }
+ return path;
+ }
+
+ #nextHandleId(): number {
+ const id = ++this.#handleIdCounter;
+ while (this.#openHandlePaths.has(id)) {
+ this.#handleIdCounter++;
+ }
+ return id;
+ }
+
+ async #resolveOpfsDirectory(
+ path: string,
+ options?: {
+ from?: FileSystemDirectoryHandle;
+ create?: boolean;
+ },
+ ): Promise {
+ const parts = this.#pathParts(path);
+ let ah = options?.from || this.#opfsRootAh;
+ for (const part of parts) {
+ ah = await ah.getDirectoryHandle(part, { create: options?.create });
+ }
+ return ah;
+ }
+}
diff --git a/packages/pglite/src/fs/opfs-ahp/types.ts b/packages/pglite/src/fs/opfs-ahp/types.ts
new file mode 100644
index 00000000..acc8dd4e
--- /dev/null
+++ b/packages/pglite/src/fs/opfs-ahp/types.ts
@@ -0,0 +1,87 @@
+export type FsStats = {
+ dev: number;
+ ino: number;
+ mode: number;
+ nlink: number;
+ uid: number;
+ gid: number;
+ rdev: number;
+ size: number;
+ blksize: number;
+ blocks: number;
+ atime: number;
+ mtime: number;
+ ctime: number;
+};
+
+// TypeScript doesn't have a built-in type for FileSystemSyncAccessHandle
+export interface FileSystemSyncAccessHandle {
+ close(): void;
+ flush(): void;
+ getSize(): number;
+ read(buffer: ArrayBuffer, options: { at: number }): number;
+ truncate(newSize: number): void;
+ write(buffer: ArrayBuffer, options: { at: number }): number;
+}
+
+export const ERRNO_CODES = {
+ EBADF: 8,
+ EBADFD: 127,
+ EEXIST: 20,
+ EINVAL: 28,
+ EISDIR: 31,
+ ENODEV: 43,
+ ENOENT: 44,
+ ENOTDIR: 54,
+ ENOTEMPTY: 55,
+} as const;
+
+export class FsError extends Error {
+ code?: number;
+ constructor(code: number | keyof typeof ERRNO_CODES | null, message: string) {
+ super(message);
+ if (typeof code === "number") {
+ this.code = code;
+ } else if (typeof code === "string") {
+ this.code = ERRNO_CODES[code];
+ }
+ }
+}
+
+// State
+
+export interface State {
+ root: DirectoryNode;
+ pool: PoolFilenames;
+}
+
+export type PoolFilenames = Array;
+
+// WAL
+
+export interface WALEntry {
+ opp: string;
+ args: any[];
+}
+
+// Node tree
+
+export type NodeType = "file" | "directory";
+
+interface BaseNode {
+ type: NodeType;
+ lastModified: number;
+ mode: number;
+}
+
+export interface FileNode extends BaseNode {
+ type: "file";
+ backingFilename: string;
+}
+
+export interface DirectoryNode extends BaseNode {
+ type: "directory";
+ children: { [filename: string]: Node };
+}
+
+export type Node = FileNode | DirectoryNode;
diff --git a/packages/pglite/src/fs/types.ts b/packages/pglite/src/fs/types.ts
index bef970a6..46b7aa00 100644
--- a/packages/pglite/src/fs/types.ts
+++ b/packages/pglite/src/fs/types.ts
@@ -1,6 +1,11 @@
import type { PostgresMod, FS } from "../postgresMod.js";
-export type FsType = "nodefs" | "idbfs" | "memoryfs";
+export type FsType =
+ | "nodefs"
+ | "idbfs"
+ | "memoryfs"
+ | "opfs-worker"
+ | "opfs-ahp";
export interface FilesystemFactory {
new (dataDir: string): Filesystem;
@@ -15,7 +20,7 @@ export interface Filesystem {
/**
* Sync the filesystem to the emscripten filesystem.
*/
- syncToFs(FS: FS): Promise;
+ syncToFs(mod: FS, relaxedDurability?: boolean): Promise;
/**
* Sync the emscripten filesystem to the filesystem.
@@ -26,6 +31,11 @@ export interface Filesystem {
* Dump the PGDATA dir from the filesystem to a gziped tarball.
*/
dumpTar(FS: FS, dbname: string): Promise;
+
+ /**
+ * Close the filesystem.
+ */
+ close(): Promise;
}
export abstract class FilesystemBase implements Filesystem {
@@ -36,7 +46,8 @@ export abstract class FilesystemBase implements Filesystem {
abstract emscriptenOpts(
opts: Partial,
): Promise>;
- async syncToFs(FS: FS) {}
+ async syncToFs(mod: FS, relaxedDurability?: boolean) {}
async initialSyncFs(mod: FS) {}
abstract dumpTar(mod: FS, dbname: string): Promise;
+ async close() {}
}
diff --git a/packages/pglite/src/index.ts b/packages/pglite/src/index.ts
index 6be35516..85ca58a5 100644
--- a/packages/pglite/src/index.ts
+++ b/packages/pglite/src/index.ts
@@ -4,4 +4,6 @@ export * as types from "./types.js";
export * as parse from "./parse.js";
export * as messages from "pg-protocol/dist/messages.js";
export * as protocol from "pg-protocol/dist/index.js";
+export { MemoryFS } from "./fs/memoryfs.js";
+export { IdbFs } from "./fs/idbfs.js";
export { Mutex } from "async-mutex";
diff --git a/packages/pglite/src/pglite.ts b/packages/pglite/src/pglite.ts
index 371057ff..3ce381d2 100644
--- a/packages/pglite/src/pglite.ts
+++ b/packages/pglite/src/pglite.ts
@@ -686,7 +686,7 @@ export class PGlite implements PGliteInterface {
const doSync = async () => {
await this.#fsSyncMutex.runExclusive(async () => {
this.#fsSyncScheduled = false;
- await this.fs!.syncToFs(this.mod!.FS);
+ await this.fs!.syncToFs(this.mod!.FS, this.#relaxedDurability);
});
};
diff --git a/packages/pglite/tests/targets/base.js b/packages/pglite/tests/targets/base.js
index ca0c80b5..7239c005 100644
--- a/packages/pglite/tests/targets/base.js
+++ b/packages/pglite/tests/targets/base.js
@@ -3,6 +3,8 @@ import playwright from "playwright";
const wsPort = process.env.WS_PORT || 3334;
+const useWorkerForBbFilename = ["opfs-ahp://base"];
+
export function tests(env, dbFilename, target) {
let browser;
let evaluate;
@@ -30,6 +32,7 @@ export function tests(env, dbFilename, target) {
page = await context.newPage();
await page.goto(`http://localhost:${wsPort}/tests/blank.html`);
page.evaluate(`window.dbFilename = "${dbFilename}";`);
+ page.evaluate(`window.useWorkerForBbFilename = ${JSON.stringify(useWorkerForBbFilename)};`);
page.on("console", (msg) => {
console.log(msg);
});
@@ -46,8 +49,20 @@ export function tests(env, dbFilename, target) {
test.serial(`targets ${target} basic`, async (t) => {
const res = await evaluate(async () => {
- const { PGlite } = await import("../../dist/index.js");
- db = new PGlite(dbFilename);
+ if (useWorkerForBbFilename.includes(dbFilename)) {
+ const { PGliteWorker } = await import("../../dist/worker/index.js");
+ db = new PGliteWorker(
+ new Worker("/tests/targets/worker.js", {
+ type: "module",
+ }),
+ {
+ dataDir: dbFilename,
+ }
+ );
+ } else {
+ const { PGlite } = await import("../../dist/index.js");
+ db = new PGlite(dbFilename);
+ }
await db.waitReady;
await db.query(`
CREATE TABLE IF NOT EXISTS test (
@@ -125,10 +140,24 @@ export function tests(env, dbFilename, target) {
test.serial(`targets ${target} persisted`, async (t) => {
await page?.reload(); // Refresh the page
page?.evaluate(`window.dbFilename = "${dbFilename}";`);
+ page?.evaluate(`window.useWorkerForBbFilename = ${JSON.stringify(useWorkerForBbFilename)};`);
const res = await evaluate(async () => {
- const { PGlite } = await import("../../dist/index.js");
- const db = new PGlite(dbFilename);
+ let db;
+ if (useWorkerForBbFilename.includes(dbFilename)) {
+ const { PGliteWorker } = await import("../../dist/worker/index.js");
+ db = new PGliteWorker(
+ new Worker("/tests/targets/worker.js", {
+ type: "module",
+ }),
+ {
+ dataDir: dbFilename,
+ }
+ );
+ } else {
+ const { PGlite } = await import("../../dist/index.js");
+ db = new PGlite(dbFilename);
+ }
await db.waitReady;
const res = await db.query(`
SELECT * FROM test;
diff --git a/packages/pglite/tests/targets/chromium-opfs-ahp.test.js b/packages/pglite/tests/targets/chromium-opfs-ahp.test.js
new file mode 100644
index 00000000..901b2ef2
--- /dev/null
+++ b/packages/pglite/tests/targets/chromium-opfs-ahp.test.js
@@ -0,0 +1,3 @@
+import { tests } from "./base.js";
+
+tests("chromium", "opfs-ahp://base", "chromium.opfs-ahp");
diff --git a/packages/pglite/tests/targets/firefox-opfs-ahp.test.js b/packages/pglite/tests/targets/firefox-opfs-ahp.test.js
new file mode 100644
index 00000000..0bb9cddc
--- /dev/null
+++ b/packages/pglite/tests/targets/firefox-opfs-ahp.test.js
@@ -0,0 +1,3 @@
+import { tests } from "./base.js";
+
+tests("firefox", "opfs-ahp://base", "firefox.opfs-ahp");
diff --git a/packages/pglite/tests/targets/webkit-opfs-ahp.test.js b/packages/pglite/tests/targets/webkit-opfs-ahp.test.js
new file mode 100644
index 00000000..5f884dda
--- /dev/null
+++ b/packages/pglite/tests/targets/webkit-opfs-ahp.test.js
@@ -0,0 +1,5 @@
+import { tests } from "./base.js";
+
+// There is an issue with webkit opening more than 252 access handles, this
+// prevents the opfs-ahp VFS working on webkit. :-(
+// tests("webkit", "opfs-ahp://base", "webkit.opfs-ahp");
diff --git a/packages/pglite/tsup.config.ts b/packages/pglite/tsup.config.ts
index 87781168..c0a184ab 100644
--- a/packages/pglite/tsup.config.ts
+++ b/packages/pglite/tsup.config.ts
@@ -20,6 +20,8 @@ const entryPoints = [
'src/live/index.ts',
"src/worker/index.ts",
"src/vector/index.ts",
+ "src/fs/opfs-ahp/index.ts",
+ "src/fs/nodefs.ts",
];
export default defineConfig({
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 812cec5a..efb0269c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -16,8 +16,8 @@ importers:
packages/benchmark:
dependencies:
wa-sqlite:
- specifier: github:rhashimoto/wa-sqlite
- version: github.com/rhashimoto/wa-sqlite/f1ab3d5d795fb4156e0b8e20ce2f58c05dfee74a
+ specifier: github:rhashimoto/wa-sqlite#v0.9.14
+ version: github.com/rhashimoto/wa-sqlite/6dbe4f044502a7a285e815896f56304a808fe25b
devDependencies:
'@types/better-sqlite3':
specifier: ^7.6.9
@@ -73,12 +73,15 @@ importers:
prettier:
specifier: 3.2.5
version: 3.2.5
+ serve:
+ specifier: ^14.2.3
+ version: 14.2.3
tinytar:
specifier: ^0.1.0
version: 0.1.0
tsup:
- specifier: ^8.0.2
- version: 8.0.2(typescript@5.3.3)
+ specifier: ^8.1.0
+ version: 8.2.3(tsx@4.7.1)(typescript@5.3.3)
tsx:
specifier: ^4.7.1
version: 4.7.1
@@ -576,6 +579,15 @@ packages:
dev: true
optional: true
+ /@esbuild/aix-ppc64@0.23.0:
+ resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/android-arm64@0.19.12:
resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
engines: {node: '>=12'}
@@ -594,6 +606,15 @@ packages:
dev: true
optional: true
+ /@esbuild/android-arm64@0.23.0:
+ resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/android-arm@0.19.12:
resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
engines: {node: '>=12'}
@@ -612,6 +633,15 @@ packages:
dev: true
optional: true
+ /@esbuild/android-arm@0.23.0:
+ resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/android-x64@0.19.12:
resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
engines: {node: '>=12'}
@@ -630,6 +660,15 @@ packages:
dev: true
optional: true
+ /@esbuild/android-x64@0.23.0:
+ resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/darwin-arm64@0.19.12:
resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
engines: {node: '>=12'}
@@ -648,6 +687,15 @@ packages:
dev: true
optional: true
+ /@esbuild/darwin-arm64@0.23.0:
+ resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/darwin-x64@0.19.12:
resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
engines: {node: '>=12'}
@@ -666,6 +714,15 @@ packages:
dev: true
optional: true
+ /@esbuild/darwin-x64@0.23.0:
+ resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/freebsd-arm64@0.19.12:
resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
engines: {node: '>=12'}
@@ -684,6 +741,15 @@ packages:
dev: true
optional: true
+ /@esbuild/freebsd-arm64@0.23.0:
+ resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/freebsd-x64@0.19.12:
resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
engines: {node: '>=12'}
@@ -702,6 +768,15 @@ packages:
dev: true
optional: true
+ /@esbuild/freebsd-x64@0.23.0:
+ resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-arm64@0.19.12:
resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
engines: {node: '>=12'}
@@ -720,6 +795,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-arm64@0.23.0:
+ resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-arm@0.19.12:
resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
engines: {node: '>=12'}
@@ -738,6 +822,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-arm@0.23.0:
+ resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-ia32@0.19.12:
resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
engines: {node: '>=12'}
@@ -756,6 +849,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-ia32@0.23.0:
+ resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-loong64@0.19.12:
resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
engines: {node: '>=12'}
@@ -774,6 +876,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-loong64@0.23.0:
+ resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-mips64el@0.19.12:
resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
engines: {node: '>=12'}
@@ -792,6 +903,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-mips64el@0.23.0:
+ resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-ppc64@0.19.12:
resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
engines: {node: '>=12'}
@@ -810,6 +930,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-ppc64@0.23.0:
+ resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-riscv64@0.19.12:
resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
engines: {node: '>=12'}
@@ -828,6 +957,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-riscv64@0.23.0:
+ resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-s390x@0.19.12:
resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
engines: {node: '>=12'}
@@ -846,6 +984,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-s390x@0.23.0:
+ resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/linux-x64@0.19.12:
resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
engines: {node: '>=12'}
@@ -864,6 +1011,15 @@ packages:
dev: true
optional: true
+ /@esbuild/linux-x64@0.23.0:
+ resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/netbsd-x64@0.19.12:
resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
engines: {node: '>=12'}
@@ -882,6 +1038,24 @@ packages:
dev: true
optional: true
+ /@esbuild/netbsd-x64@0.23.0:
+ resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-arm64@0.23.0:
+ resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/openbsd-x64@0.19.12:
resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
engines: {node: '>=12'}
@@ -900,6 +1074,15 @@ packages:
dev: true
optional: true
+ /@esbuild/openbsd-x64@0.23.0:
+ resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/sunos-x64@0.19.12:
resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
engines: {node: '>=12'}
@@ -918,6 +1101,15 @@ packages:
dev: true
optional: true
+ /@esbuild/sunos-x64@0.23.0:
+ resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/win32-arm64@0.19.12:
resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
engines: {node: '>=12'}
@@ -936,6 +1128,15 @@ packages:
dev: true
optional: true
+ /@esbuild/win32-arm64@0.23.0:
+ resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/win32-ia32@0.19.12:
resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
engines: {node: '>=12'}
@@ -954,6 +1155,15 @@ packages:
dev: true
optional: true
+ /@esbuild/win32-ia32@0.23.0:
+ resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@esbuild/win32-x64@0.19.12:
resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
engines: {node: '>=12'}
@@ -972,6 +1182,15 @@ packages:
dev: true
optional: true
+ /@esbuild/win32-x64@0.23.0:
+ resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@eslint-community/eslint-utils@4.4.0(eslint@8.57.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1043,15 +1262,6 @@ packages:
wrap-ansi-cjs: /wrap-ansi@7.0.0
dev: true
- /@jridgewell/gen-mapping@0.3.3:
- resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
- engines: {node: '>=6.0.0'}
- dependencies:
- '@jridgewell/set-array': 1.1.2
- '@jridgewell/sourcemap-codec': 1.4.15
- '@jridgewell/trace-mapping': 0.3.22
- dev: true
-
/@jridgewell/gen-mapping@0.3.5:
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
engines: {node: '>=6.0.0'}
@@ -1066,11 +1276,6 @@ packages:
engines: {node: '>=6.0.0'}
dev: true
- /@jridgewell/set-array@1.1.2:
- resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
- engines: {node: '>=6.0.0'}
- dev: true
-
/@jridgewell/set-array@1.2.1:
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
engines: {node: '>=6.0.0'}
@@ -1087,13 +1292,6 @@ packages:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
- /@jridgewell/trace-mapping@0.3.22:
- resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==}
- dependencies:
- '@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.4.15
- dev: true
-
/@jridgewell/trace-mapping@0.3.25:
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
dependencies:
@@ -1293,80 +1491,80 @@ packages:
picomatch: 2.3.1
dev: true
- /@rollup/rollup-android-arm-eabi@4.12.0:
- resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==}
+ /@rollup/rollup-android-arm-eabi@4.18.0:
+ resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-android-arm-eabi@4.18.0:
- resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==}
+ /@rollup/rollup-android-arm-eabi@4.19.1:
+ resolution: {integrity: sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-android-arm64@4.12.0:
- resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==}
+ /@rollup/rollup-android-arm64@4.18.0:
+ resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-android-arm64@4.18.0:
- resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==}
+ /@rollup/rollup-android-arm64@4.19.1:
+ resolution: {integrity: sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-darwin-arm64@4.12.0:
- resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==}
+ /@rollup/rollup-darwin-arm64@4.18.0:
+ resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-darwin-arm64@4.18.0:
- resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==}
+ /@rollup/rollup-darwin-arm64@4.19.1:
+ resolution: {integrity: sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-darwin-x64@4.12.0:
- resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==}
+ /@rollup/rollup-darwin-x64@4.18.0:
+ resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-darwin-x64@4.18.0:
- resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==}
+ /@rollup/rollup-darwin-x64@4.19.1:
+ resolution: {integrity: sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-linux-arm-gnueabihf@4.12.0:
- resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==}
+ /@rollup/rollup-linux-arm-gnueabihf@4.18.0:
+ resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
- /@rollup/rollup-linux-arm-gnueabihf@4.18.0:
- resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
+ /@rollup/rollup-linux-arm-gnueabihf@4.19.1:
+ resolution: {integrity: sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==}
cpu: [arm]
os: [linux]
requiresBuild: true
@@ -1381,9 +1579,9 @@ packages:
dev: true
optional: true
- /@rollup/rollup-linux-arm64-gnu@4.12.0:
- resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==}
- cpu: [arm64]
+ /@rollup/rollup-linux-arm-musleabihf@4.19.1:
+ resolution: {integrity: sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==}
+ cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
@@ -1397,8 +1595,8 @@ packages:
dev: true
optional: true
- /@rollup/rollup-linux-arm64-musl@4.12.0:
- resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==}
+ /@rollup/rollup-linux-arm64-gnu@4.19.1:
+ resolution: {integrity: sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==}
cpu: [arm64]
os: [linux]
requiresBuild: true
@@ -1413,6 +1611,14 @@ packages:
dev: true
optional: true
+ /@rollup/rollup-linux-arm64-musl@4.19.1:
+ resolution: {integrity: sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@rollup/rollup-linux-powerpc64le-gnu@4.18.0:
resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==}
cpu: [ppc64]
@@ -1421,9 +1627,9 @@ packages:
dev: true
optional: true
- /@rollup/rollup-linux-riscv64-gnu@4.12.0:
- resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==}
- cpu: [riscv64]
+ /@rollup/rollup-linux-powerpc64le-gnu@4.19.1:
+ resolution: {integrity: sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==}
+ cpu: [ppc64]
os: [linux]
requiresBuild: true
dev: true
@@ -1437,6 +1643,14 @@ packages:
dev: true
optional: true
+ /@rollup/rollup-linux-riscv64-gnu@4.19.1:
+ resolution: {integrity: sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@rollup/rollup-linux-s390x-gnu@4.18.0:
resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==}
cpu: [s390x]
@@ -1445,9 +1659,9 @@ packages:
dev: true
optional: true
- /@rollup/rollup-linux-x64-gnu@4.12.0:
- resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==}
- cpu: [x64]
+ /@rollup/rollup-linux-s390x-gnu@4.19.1:
+ resolution: {integrity: sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==}
+ cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
@@ -1461,8 +1675,8 @@ packages:
dev: true
optional: true
- /@rollup/rollup-linux-x64-musl@4.12.0:
- resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==}
+ /@rollup/rollup-linux-x64-gnu@4.19.1:
+ resolution: {integrity: sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==}
cpu: [x64]
os: [linux]
requiresBuild: true
@@ -1477,10 +1691,10 @@ packages:
dev: true
optional: true
- /@rollup/rollup-win32-arm64-msvc@4.12.0:
- resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==}
- cpu: [arm64]
- os: [win32]
+ /@rollup/rollup-linux-x64-musl@4.19.1:
+ resolution: {integrity: sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==}
+ cpu: [x64]
+ os: [linux]
requiresBuild: true
dev: true
optional: true
@@ -1493,9 +1707,9 @@ packages:
dev: true
optional: true
- /@rollup/rollup-win32-ia32-msvc@4.12.0:
- resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==}
- cpu: [ia32]
+ /@rollup/rollup-win32-arm64-msvc@4.19.1:
+ resolution: {integrity: sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==}
+ cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
@@ -1509,9 +1723,9 @@ packages:
dev: true
optional: true
- /@rollup/rollup-win32-x64-msvc@4.12.0:
- resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==}
- cpu: [x64]
+ /@rollup/rollup-win32-ia32-msvc@4.19.1:
+ resolution: {integrity: sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==}
+ cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
@@ -1525,6 +1739,14 @@ packages:
dev: true
optional: true
+ /@rollup/rollup-win32-x64-msvc@4.19.1:
+ resolution: {integrity: sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@rushstack/node-core-library@4.0.2:
resolution: {integrity: sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==}
peerDependencies:
@@ -1951,10 +2173,22 @@ packages:
resolution: {integrity: sha512-hQ2gAQcBO/CDpC82DCrinJNgOHI2v+FA7BDW4lMSPeBpQ7sRe2OLHWe5cph1s7D8DUQAwRt18dBDfJJ220APEA==}
dev: true
+ /@zeit/schemas@2.36.0:
+ resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==}
+ dev: true
+
/abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
dev: true
+ /accepts@1.3.8:
+ resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-types: 2.1.35
+ negotiator: 0.6.3
+ dev: true
+
/acorn-import-attributes@1.9.2(acorn@8.11.3):
resolution: {integrity: sha512-O+nfJwNolEA771IYJaiLWK1UAwjNsQmZbTRqqwBYxCgVQTmpFEMvBw6LOIQV0Me339L5UMVYFyRohGnGlQDdIQ==}
peerDependencies:
@@ -2000,6 +2234,21 @@ packages:
uri-js: 4.4.1
dev: true
+ /ajv@8.12.0:
+ resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-align@3.0.1:
+ resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
+ dependencies:
+ string-width: 4.2.3
+ dev: true
+
/ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -2045,6 +2294,10 @@ packages:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
dev: true
+ /arch@2.2.0:
+ resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==}
+ dev: true
+
/are-we-there-yet@2.0.0:
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
engines: {node: '>=10'}
@@ -2053,6 +2306,10 @@ packages:
readable-stream: 3.6.2
dev: true
+ /arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ dev: true
+
/argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies:
@@ -2216,6 +2473,20 @@ packages:
resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==}
dev: true
+ /boxen@7.0.0:
+ resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==}
+ engines: {node: '>=14.16'}
+ dependencies:
+ ansi-align: 3.0.1
+ camelcase: 7.0.1
+ chalk: 5.3.0
+ cli-boxes: 3.0.0
+ string-width: 5.1.2
+ type-fest: 2.19.0
+ widest-line: 4.0.1
+ wrap-ansi: 8.1.0
+ dev: true
+
/brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
dependencies:
@@ -2287,16 +2558,21 @@ packages:
'@oven/bun-windows-x64-baseline': 1.1.18
dev: true
- /bundle-require@4.0.2(esbuild@0.19.12):
- resolution: {integrity: sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==}
+ /bundle-require@5.0.0(esbuild@0.23.0):
+ resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
peerDependencies:
- esbuild: '>=0.17'
+ esbuild: '>=0.18'
dependencies:
- esbuild: 0.19.12
+ esbuild: 0.23.0
load-tsconfig: 0.2.5
dev: true
+ /bytes@3.0.0:
+ resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==}
+ engines: {node: '>= 0.8'}
+ dev: true
+
/cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
@@ -2323,6 +2599,11 @@ packages:
engines: {node: '>=12.20'}
dev: true
+ /camelcase@7.0.1:
+ resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
+ engines: {node: '>=14.16'}
+ dev: true
+
/caniuse-lite@1.0.30001636:
resolution: {integrity: sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==}
dev: true
@@ -2334,6 +2615,13 @@ packages:
nofilter: 3.1.0
dev: true
+ /chalk-template@0.4.0:
+ resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==}
+ engines: {node: '>=12'}
+ dependencies:
+ chalk: 4.1.2
+ dev: true
+
/chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
@@ -2351,6 +2639,11 @@ packages:
supports-color: 7.2.0
dev: true
+ /chalk@5.0.1:
+ resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+ dev: true
+
/chalk@5.3.0:
resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
@@ -2393,6 +2686,11 @@ packages:
resolution: {integrity: sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==}
dev: true
+ /cli-boxes@3.0.0:
+ resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
+ engines: {node: '>=10'}
+ dev: true
+
/cli-truncate@4.0.0:
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
engines: {node: '>=18'}
@@ -2401,6 +2699,15 @@ packages:
string-width: 7.1.0
dev: true
+ /clipboardy@3.0.0:
+ resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ arch: 2.2.0
+ execa: 5.1.1
+ is-wsl: 2.2.0
+ dev: true
+
/cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
@@ -2484,6 +2791,28 @@ packages:
resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
dev: true
+ /compressible@2.0.18:
+ resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-db: 1.52.0
+ dev: true
+
+ /compression@1.7.4:
+ resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ accepts: 1.3.8
+ bytes: 3.0.0
+ compressible: 2.0.18
+ debug: 2.6.9
+ on-headers: 1.0.2
+ safe-buffer: 5.1.2
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/computeds@0.0.1:
resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
dev: true
@@ -2522,10 +2851,20 @@ packages:
yargs: 17.7.2
dev: true
+ /consola@3.2.3:
+ resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==}
+ engines: {node: ^14.18.0 || >=16.10.0}
+ dev: true
+
/console-control-strings@1.1.0:
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
dev: true
+ /content-disposition@0.5.2:
+ resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==}
+ engines: {node: '>= 0.6'}
+ dev: true
+
/convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
dev: true
@@ -2582,6 +2921,17 @@ packages:
resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
dev: true
+ /debug@2.6.9:
+ resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.0.0
+ dev: true
+
/debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
@@ -2605,6 +2955,18 @@ packages:
ms: 2.1.2
dev: true
+ /debug@4.3.6:
+ resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
/decompress-response@6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
@@ -2786,6 +3148,38 @@ packages:
'@esbuild/win32-x64': 0.21.5
dev: true
+ /esbuild@0.23.0:
+ resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==}
+ engines: {node: '>=18'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.23.0
+ '@esbuild/android-arm': 0.23.0
+ '@esbuild/android-arm64': 0.23.0
+ '@esbuild/android-x64': 0.23.0
+ '@esbuild/darwin-arm64': 0.23.0
+ '@esbuild/darwin-x64': 0.23.0
+ '@esbuild/freebsd-arm64': 0.23.0
+ '@esbuild/freebsd-x64': 0.23.0
+ '@esbuild/linux-arm': 0.23.0
+ '@esbuild/linux-arm64': 0.23.0
+ '@esbuild/linux-ia32': 0.23.0
+ '@esbuild/linux-loong64': 0.23.0
+ '@esbuild/linux-mips64el': 0.23.0
+ '@esbuild/linux-ppc64': 0.23.0
+ '@esbuild/linux-riscv64': 0.23.0
+ '@esbuild/linux-s390x': 0.23.0
+ '@esbuild/linux-x64': 0.23.0
+ '@esbuild/netbsd-x64': 0.23.0
+ '@esbuild/openbsd-arm64': 0.23.0
+ '@esbuild/openbsd-x64': 0.23.0
+ '@esbuild/sunos-x64': 0.23.0
+ '@esbuild/win32-arm64': 0.23.0
+ '@esbuild/win32-ia32': 0.23.0
+ '@esbuild/win32-x64': 0.23.0
+ dev: true
+
/escalade@3.1.2:
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
engines: {node: '>=6'}
@@ -2982,6 +3376,12 @@ packages:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
dev: true
+ /fast-url-parser@1.1.3:
+ resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==}
+ dependencies:
+ punycode: 1.4.1
+ dev: true
+
/fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
dependencies:
@@ -3187,7 +3587,7 @@ packages:
dependencies:
foreground-child: 3.1.1
jackspeak: 2.3.6
- minimatch: 9.0.3
+ minimatch: 9.0.4
minipass: 7.0.4
path-scurry: 1.10.1
dev: true
@@ -3428,6 +3828,12 @@ packages:
hasown: 2.0.1
dev: true
+ /is-docker@2.2.1:
+ resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dev: true
+
/is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
@@ -3465,6 +3871,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /is-port-reachable@4.0.0:
+ resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
/is-promise@4.0.0:
resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
dev: true
@@ -3479,6 +3890,13 @@ packages:
engines: {node: '>=18'}
dev: true
+ /is-wsl@2.2.0:
+ resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
+ engines: {node: '>=8'}
+ dependencies:
+ is-docker: 2.2.1
+ dev: true
+
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: true
@@ -3538,6 +3956,10 @@ packages:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
dev: true
+ /json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+ dev: true
+
/json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
dev: true
@@ -3694,11 +4116,23 @@ packages:
picomatch: 2.3.1
dev: true
+ /mime-db@1.33.0:
+ resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==}
+ engines: {node: '>= 0.6'}
+ dev: true
+
/mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
dev: true
+ /mime-types@2.1.18:
+ resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-db: 1.33.0
+ dev: true
+
/mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
@@ -3799,6 +4233,10 @@ packages:
hasBin: true
dev: true
+ /ms@2.0.0:
+ resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+ dev: true
+
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
@@ -3833,6 +4271,11 @@ packages:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
+ /negotiator@0.6.3:
+ resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
+ engines: {node: '>= 0.6'}
+ dev: true
+
/node-abi@3.56.0:
resolution: {integrity: sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==}
engines: {node: '>=10'}
@@ -3904,6 +4347,11 @@ packages:
resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
dev: true
+ /on-headers@1.0.2:
+ resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
+ engines: {node: '>= 0.8'}
+ dev: true
+
/once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies:
@@ -3991,6 +4439,10 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /path-is-inside@1.0.2:
+ resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==}
+ dev: true
+
/path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@@ -4008,6 +4460,10 @@ packages:
minipass: 7.0.4
dev: true
+ /path-to-regexp@2.2.1:
+ resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==}
+ dev: true
+
/path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
@@ -4140,20 +4596,26 @@ packages:
- supports-color
dev: true
- /postcss-load-config@4.0.2:
- resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
- engines: {node: '>= 14'}
+ /postcss-load-config@6.0.1(tsx@4.7.1):
+ resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
+ engines: {node: '>= 18'}
peerDependencies:
+ jiti: '>=1.21.0'
postcss: '>=8.0.9'
- ts-node: '>=9.0.0'
+ tsx: ^4.8.1
+ yaml: ^2.4.2
peerDependenciesMeta:
+ jiti:
+ optional: true
postcss:
optional: true
- ts-node:
+ tsx:
+ optional: true
+ yaml:
optional: true
dependencies:
lilconfig: 3.1.1
- yaml: 2.3.4
+ tsx: 4.7.1
dev: true
/postcss@8.4.38:
@@ -4239,6 +4701,10 @@ packages:
once: 1.4.0
dev: true
+ /punycode@1.4.1:
+ resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==}
+ dev: true
+
/punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -4255,6 +4721,11 @@ packages:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true
+ /range-parser@1.2.0:
+ resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==}
+ engines: {node: '>= 0.6'}
+ dev: true
+
/rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
@@ -4306,11 +4777,30 @@ packages:
/regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+ /registry-auth-token@3.3.2:
+ resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==}
+ dependencies:
+ rc: 1.2.8
+ safe-buffer: 5.2.1
+ dev: true
+
+ /registry-url@3.1.0:
+ resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ rc: 1.2.8
+ dev: true
+
/require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
dev: true
+ /require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
/requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
dev: true
@@ -4364,29 +4854,6 @@ packages:
glob: 7.2.3
dev: true
- /rollup@4.12.0:
- resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==}
- engines: {node: '>=18.0.0', npm: '>=8.0.0'}
- hasBin: true
- dependencies:
- '@types/estree': 1.0.5
- optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.12.0
- '@rollup/rollup-android-arm64': 4.12.0
- '@rollup/rollup-darwin-arm64': 4.12.0
- '@rollup/rollup-darwin-x64': 4.12.0
- '@rollup/rollup-linux-arm-gnueabihf': 4.12.0
- '@rollup/rollup-linux-arm64-gnu': 4.12.0
- '@rollup/rollup-linux-arm64-musl': 4.12.0
- '@rollup/rollup-linux-riscv64-gnu': 4.12.0
- '@rollup/rollup-linux-x64-gnu': 4.12.0
- '@rollup/rollup-linux-x64-musl': 4.12.0
- '@rollup/rollup-win32-arm64-msvc': 4.12.0
- '@rollup/rollup-win32-ia32-msvc': 4.12.0
- '@rollup/rollup-win32-x64-msvc': 4.12.0
- fsevents: 2.3.3
- dev: true
-
/rollup@4.18.0:
resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -4413,6 +4880,32 @@ packages:
fsevents: 2.3.3
dev: true
+ /rollup@4.19.1:
+ resolution: {integrity: sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+ dependencies:
+ '@types/estree': 1.0.5
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.19.1
+ '@rollup/rollup-android-arm64': 4.19.1
+ '@rollup/rollup-darwin-arm64': 4.19.1
+ '@rollup/rollup-darwin-x64': 4.19.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.19.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.19.1
+ '@rollup/rollup-linux-arm64-gnu': 4.19.1
+ '@rollup/rollup-linux-arm64-musl': 4.19.1
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.19.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.19.1
+ '@rollup/rollup-linux-s390x-gnu': 4.19.1
+ '@rollup/rollup-linux-x64-gnu': 4.19.1
+ '@rollup/rollup-linux-x64-musl': 4.19.1
+ '@rollup/rollup-win32-arm64-msvc': 4.19.1
+ '@rollup/rollup-win32-ia32-msvc': 4.19.1
+ '@rollup/rollup-win32-x64-msvc': 4.19.1
+ fsevents: 2.3.3
+ dev: true
+
/run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies:
@@ -4475,6 +4968,39 @@ packages:
type-fest: 0.13.1
dev: true
+ /serve-handler@6.1.5:
+ resolution: {integrity: sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==}
+ dependencies:
+ bytes: 3.0.0
+ content-disposition: 0.5.2
+ fast-url-parser: 1.1.3
+ mime-types: 2.1.18
+ minimatch: 3.1.2
+ path-is-inside: 1.0.2
+ path-to-regexp: 2.2.1
+ range-parser: 1.2.0
+ dev: true
+
+ /serve@14.2.3:
+ resolution: {integrity: sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==}
+ engines: {node: '>= 14'}
+ hasBin: true
+ dependencies:
+ '@zeit/schemas': 2.36.0
+ ajv: 8.12.0
+ arg: 5.0.2
+ boxen: 7.0.0
+ chalk: 5.0.1
+ chalk-template: 0.4.0
+ clipboardy: 3.0.0
+ compression: 1.7.4
+ is-port-reachable: 4.0.0
+ serve-handler: 6.1.5
+ update-check: 1.5.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: true
@@ -4676,7 +5202,7 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
dependencies:
- '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/gen-mapping': 0.3.5
commander: 4.1.1
glob: 10.3.10
lines-and-columns: 1.2.4
@@ -4840,8 +5366,8 @@ packages:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
dev: true
- /tsup@8.0.2(typescript@5.3.3):
- resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==}
+ /tsup@8.2.3(tsx@4.7.1)(typescript@5.3.3):
+ resolution: {integrity: sha512-6YNT44oUfXRbZuSMNmN36GzwPPIlD2wBccY7looM2fkTcxkf2NEmwr3OZuDZoySklnrIG4hoEtzy8yUXYOqNcg==}
engines: {node: '>=18'}
hasBin: true
peerDependencies:
@@ -4859,24 +5385,28 @@ packages:
typescript:
optional: true
dependencies:
- bundle-require: 4.0.2(esbuild@0.19.12)
+ bundle-require: 5.0.0(esbuild@0.23.0)
cac: 6.7.14
chokidar: 3.6.0
- debug: 4.3.4
- esbuild: 0.19.12
+ consola: 3.2.3
+ debug: 4.3.6
+ esbuild: 0.23.0
execa: 5.1.1
globby: 11.1.0
joycon: 3.1.1
- postcss-load-config: 4.0.2
+ picocolors: 1.0.1
+ postcss-load-config: 6.0.1(tsx@4.7.1)
resolve-from: 5.0.0
- rollup: 4.12.0
+ rollup: 4.19.1
source-map: 0.8.0-beta.0
sucrase: 3.35.0
tree-kill: 1.2.2
typescript: 5.3.3
transitivePeerDependencies:
+ - jiti
- supports-color
- - ts-node
+ - tsx
+ - yaml
dev: true
/tsx@4.7.1:
@@ -4913,6 +5443,11 @@ packages:
engines: {node: '>=10'}
dev: true
+ /type-fest@2.19.0:
+ resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
+ engines: {node: '>=12.20'}
+ dev: true
+
/typescript@5.3.3:
resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
engines: {node: '>=14.17'}
@@ -4957,6 +5492,13 @@ packages:
picocolors: 1.0.1
dev: true
+ /update-check@1.5.4:
+ resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==}
+ dependencies:
+ registry-auth-token: 3.3.2
+ registry-url: 3.1.0
+ dev: true
+
/uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
dependencies:
@@ -4976,6 +5518,11 @@ packages:
engines: {node: '>= 0.10'}
dev: true
+ /vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+ dev: true
+
/vite-plugin-dts@3.9.1(typescript@5.3.3)(vite@5.3.1):
resolution: {integrity: sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -5118,6 +5665,13 @@ packages:
string-width: 4.2.3
dev: true
+ /widest-line@4.0.1:
+ resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 5.1.2
+ dev: true
+
/word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
@@ -5171,11 +5725,6 @@ packages:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
dev: true
- /yaml@2.3.4:
- resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
- engines: {node: '>= 14'}
- dev: true
-
/yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
@@ -5211,8 +5760,8 @@ packages:
commander: 9.5.0
dev: true
- github.com/rhashimoto/wa-sqlite/f1ab3d5d795fb4156e0b8e20ce2f58c05dfee74a:
- resolution: {tarball: https://codeload.github.com/rhashimoto/wa-sqlite/tar.gz/f1ab3d5d795fb4156e0b8e20ce2f58c05dfee74a}
+ github.com/rhashimoto/wa-sqlite/6dbe4f044502a7a285e815896f56304a808fe25b:
+ resolution: {tarball: https://codeload.github.com/rhashimoto/wa-sqlite/tar.gz/6dbe4f044502a7a285e815896f56304a808fe25b}
name: wa-sqlite
- version: 1.0.0
+ version: 0.9.14
dev: false