diff --git a/.github/workflows/native-fuzz.yml b/.github/workflows/native-fuzz.yml new file mode 100644 index 00000000..5d716f12 --- /dev/null +++ b/.github/workflows/native-fuzz.yml @@ -0,0 +1,100 @@ +name: Native fuzz + +# Differential ATTACH/DETACH/VACUUM INTO fuzz (tests/fuzz/) against the +# bundled native worker on all five shipped txiki.js targets (CI's native lanes +# run on Linux x64 only). Opt-in: manual, or on dev pushes and pull requests to +# dev that change the harness, the runtimes, the worker client it drives, the +# toolchain or this workflow. +on: + workflow_dispatch: + push: + branches: [dev] + paths: + - 'tests/fuzz/**' + - 'tests/unit/vscode_mock_setup.ts' + - 'tests/unit/mocks/**' + - 'natives/**' + - 'src/nativeWorker.ts' + - 'package.json' + - 'package-lock.json' + - '.nvmrc' + - '.github/workflows/native-fuzz.yml' + pull_request: + branches: [dev] + paths: + - 'tests/fuzz/**' + - 'tests/unit/vscode_mock_setup.ts' + - 'tests/unit/mocks/**' + - 'natives/**' + - 'src/nativeWorker.ts' + - 'package.json' + - 'package-lock.json' + - '.nvmrc' + - '.github/workflows/native-fuzz.yml' + +concurrency: + group: native-fuzz-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + native-fuzz: + name: Native fuzz (${{ matrix.target }}) + runs-on: ${{ matrix.runner }} + # Above the harness's own 60-minute test timeout, so a slow runner fails + # with the test's report rather than a bare cancellation. + timeout-minutes: 75 + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-24.04 + target: x86_64-linux-gnu + - runner: ubuntu-24.04-arm + target: aarch64-linux-gnu + - runner: windows-latest + target: x86_64-windows + # macos-13 is retired; macos-15-intel matches the arm64 lane's OS. + - runner: macos-15-intel + target: x86_64-macos + - runner: macos-15 + target: aarch64-macos + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version-file: .nvmrc + cache: npm + + - name: Install dependencies + run: npm ci + + # FUZZ_EXPECT_TARGET makes the harness fail unless it resolved and ran + # natives/ (no fallback to another runtime or arch). The worker + # logs every refusal, so the summary lines are copied to the job summary. + - name: Native ATTACH fuzz + shell: bash + env: + FUZZ_EXPECT_TARGET: ${{ matrix.target }} + run: | + set -o pipefail + npm run test:native-fuzz 2>&1 | tee native-fuzz.log + + - name: Summary + if: always() + shell: bash + env: + RUNNER_LABEL: ${{ matrix.runner }} + FUZZ_EXPECT_TARGET: ${{ matrix.target }} + run: | + { + echo "### ${RUNNER_LABEL} (expected ${FUZZ_EXPECT_TARGET})" + echo '```' + grep -F '[native fuzz]' native-fuzz.log || echo 'no [native fuzz] lines: the harness did not reach the worker' + echo '```' + } >> "$GITHUB_STEP_SUMMARY" diff --git a/CHANGELOG.md b/CHANGELOG.md index cd2412fc..034758b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 1.8.3 + +### Security + +- Show text that comes from a database file without links in VS Code notifications. VS Code turns `[label](command:…)` in an extension's notification or progress title into a link that runs that command, with arguments taken from the link, when clicked. A crafted database could put such a link into what SQLite Explorer showed: an error message, for example from exporting a view whose column name is a link, or a table, view or file name. These texts are now shown without links. The same applies to errors that VS Code shows itself, such as a failed save, which VS Code before 1.141 also turns into links. +- Narrow the native runtime's exception for export snapshots to the one statement that writes the snapshot, on the thread running it. In 1.8.2 the exception covered the connection while an export ran; the worker's statement check and its one-request-at-a-time order kept other SQL from using it. + +### Fixes + +- Keep TEXT values that contain a NUL character intact. The WebAssembly engine cut such a value short at the first NUL when writing it, for example from an import, and when reading it in the query console; the native engine did the same on some reads. Both engines now read and write the whole value. The grid still shows these cells as bytes on both engines; in tables with more than 999 columns it checks only the key columns, so other columns show such a value as text. A row whose WITHOUT ROWID primary key contains NUL stays read-only, and the reason now says so. +- Store TEXT that contains an unpaired surrogate, such as half of an emoji left by a truncated string, whole in the WebAssembly engine. When a multibyte character followed it, the end of the value was cut off. The stored bytes now match the native engine's. +- When the native engine fails to write a copy of the database, for Save As or an export, the error now gives SQLite's message instead of the generic text for its error code, such as "SQL logic error". + +### Maintenance + +- Update the native runtime and the WebAssembly build to the fork commits with these fixes (txiki.js `b45ac83`, sql.js `35ac205`). The runtime also resets a statement whose rows fail to convert, instead of leaving it running, and checks every step of that conversion; SQLite Explorer's worker finalizes its statements, so it was not affected. +- Run the native ATTACH, DETACH and VACUUM INTO fuzz on all five native targets in CI (`native-fuzz.yml`). Its run against this release's runtime generated 40,000 statements, 39,990 of them distinct, and found no attached database or file write on any target. + ## 1.8.2 ### Security diff --git a/CLAUDE.md b/CLAUDE.md index e8422506..234d05b7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -395,7 +395,7 @@ Settings in `package.json` → `contributes.configuration`: ### Build - **WASM not found**: Run `node scripts/build.mjs` if `assets/sqlite3.wasm` is missing - **Browser vs Node**: Check `import.meta.env.VSCODE_BROWSER_EXT` for environment-specific code -- **Query-plan runtime**: `src/runtime/query-plan.c` bounds plan compilation and extraction on the primary connection. `node scripts/build-query-plan.mjs` builds the five native libraries and the WASM runtime from that file and pinned sql.js commit `3181cc5ee888d3251228d3995c32bf9ea03c3240` and SQLite amalgamation 3.54.1. It requires Emscripten 5.0.0 and the official Zig 0.16.0 release (`zig cc --version` must report `clang version 21.1.0`; distribution builds such as Homebrew's are refused); use `--emcc PATH` and optionally `--sqljs-source GIT_CHECKOUT`. The source checkout is read through `git archive` at the pin. `scripts/refresh-sqljs.mjs` delegates to this builder. Native Explain uses the primary connection's signalled `Database.allAsync` so cancel RPCs remain deliverable without losing TEMP or pending transaction state. `scripts/refresh-natives.mjs` pins the tested `master` commit, Actions run, and hashes for all five native targets. +- **Query-plan runtime**: `src/runtime/query-plan.c` bounds plan compilation and extraction on the primary connection. `node scripts/build-query-plan.mjs` builds the five native libraries and the WASM runtime from that file and pinned sql.js commit `35ac205b7f9470d9aa7696ceb9cdab5dec4b6ed3` and SQLite amalgamation 3.54.1. It requires Emscripten 5.0.0 and the official Zig 0.16.0 release (`zig cc --version` must report `clang version 21.1.0`; distribution builds such as Homebrew's are refused); use `--emcc PATH` and optionally `--sqljs-source GIT_CHECKOUT`. The source checkout is read through `git archive` at the pin. `scripts/refresh-sqljs.mjs` delegates to this builder. Native Explain uses the primary connection's signalled `Database.allAsync` so cancel RPCs remain deliverable without losing TEMP or pending transaction state. `scripts/refresh-natives.mjs` pins the tested `master` commit, Actions run, and hashes for all five native targets. - **Runtime artifact gate**: `vendor/query-plan-manifest.json` records source and output hashes. Normal builds verify it before bundling. Regenerate runtime changes with the builder; do not edit native libraries, WASM/glue, or the manifest by hand. `node scripts/build-query-plan.mjs --check` verifies all copies. ## Extension Identifiers diff --git a/natives/aarch64-linux-gnu/tjs b/natives/aarch64-linux-gnu/tjs index 182bbe39..ae78337d 100755 Binary files a/natives/aarch64-linux-gnu/tjs and b/natives/aarch64-linux-gnu/tjs differ diff --git a/natives/aarch64-macos/tjs b/natives/aarch64-macos/tjs index 871b7344..b89e20e3 100755 Binary files a/natives/aarch64-macos/tjs and b/natives/aarch64-macos/tjs differ diff --git a/natives/native-worker.js b/natives/native-worker.js index 329a5d22..02a08bd1 100644 --- a/natives/native-worker.js +++ b/natives/native-worker.js @@ -147,8 +147,8 @@ function leadingStatementVerb(sql) { * ToString: an array ['ATTACH ...'] would otherwise compile unchecked. * * The bundled runtime enforces the same rule in C: every connection installs - * an authorizer at open that refuses ATTACH and DETACH (see runVacuumInto for - * the one permitted path), so a future SQLite tokenizer change that this + * an authorizer at open that refuses ATTACH and DETACH (runVacuumInto uses + * the runtime's one exception), so a future SQLite tokenizer change that this * mirror misses still cannot attach a file. This check stays in front for its * specific error code. */ @@ -199,7 +199,7 @@ function isPathAuthorityRefusal(error) { /** * Error text for the IPC reply. The authorizer's refusal gets its code, and - * every other failure it was wrapped with (a failed permit withdrawal, a + * every other failure it was wrapped with (a failed savepoint cleanup, a * failed deadline cleanup, a cancellation) is kept rather than replaced. */ function describeWorkerError(error) { @@ -674,13 +674,13 @@ function executeInterruptibleAsyncOperation(requestId, timeoutMs, operation) { * VACUUM must run on the interruptible connection and outside transactions. * * VACUUM INTO attaches its destination, and the runtime's authorizer refuses - * every ATTACH except the one path a connection permits. The permit names - * exactly this host-chosen snapshot and is withdrawn when the VACUUM settles, - * so SQL-level VACUUM INTO any other path (which would create an arbitrary - * file holding a copy of the database) stays refused. + * every ATTACH, so SQL-level VACUUM INTO (which would create an arbitrary file + * holding a copy of the database) is refused. vacuumInto is the runtime's one + * exception: it runs a fixed `VACUUM main INTO ?` and accepts this host-chosen + * destination only for that statement, on the thread running it. */ function runVacuumInto(asyncDatabase, database, snapshotPath, signal) { - if (!asyncDatabase || typeof asyncDatabase.run !== 'function') { + if (!asyncDatabase || typeof asyncDatabase.vacuumInto !== 'function') { return Promise.reject( new Error('Interruptible native database snapshots are unavailable in this runtime') ); @@ -693,47 +693,8 @@ function runVacuumInto(asyncDatabase, database, snapshotPath, signal) { if (typeof snapshotPath !== 'string' || snapshotPath.length === 0) { return Promise.reject(new Error('A native export snapshot path is required')); } - try { - asyncDatabase.permitAttach(snapshotPath); - } catch (error) { - return Promise.reject(error); - } - const withdrawPermit = () => { - try { - asyncDatabase.permitAttach(null); - } catch (error) { - // A closing connection ('Invalid DB') takes its permit with it. Any - // other failure leaves the permit installed, so the connection is - // closed (no handle keeps authorizing the path, even if a cancellation - // wrapper later hides this error) and the failure is reported. A - // reworded closing message lands here too, which fails closed. - if (error?.message === 'Invalid DB') return; - releaseAsyncDatabase(asyncDatabase); - throw error; - } - }; - // Through a promise, so a synchronous throw from run also withdraws the permit. - return new Promise(resolve => resolve( - asyncDatabase.run('VACUUM main INTO ?', [snapshotPath], { signal }) - )).then( - result => { - withdrawPermit(); - return result; - }, - error => { - try { - withdrawPermit(); - } catch (withdrawError) { - throw new AggregateError( - [error, withdrawError], - `${describeNativeError(error, 'VACUUM INTO failed')}; ` + - `withdrawing the ATTACH permit also failed: ` + - `${describeNativeError(withdrawError, 'Unknown permit error')}` - ); - } - throw error; - } - ); + // Through a promise, so a synchronous throw is reported as a rejection. + return new Promise(resolve => resolve(asyncDatabase.vacuumInto(snapshotPath, { signal }))); } /** Abort one active async operation without affecting queued or future work. */ @@ -747,23 +708,6 @@ function cancelOperation(correlationId) { return true; } -/** - * Take an AsyncDatabase out of service now. For the shared connection this - * goes through closeAsyncDatabase, which clears `asyncDb` synchronously, so - * later reads fall back to the primary connection instead of a closed handle. - */ -function releaseAsyncDatabase(connection) { - // Any other connection's close may be synchronous or throw; it is reported - // here rather than replacing the failure the caller is about to throw. - const closing = connection === asyncDb - ? closeAsyncDatabase() - : new Promise(resolve => resolve(connection.close())); - closing.catch(closeError => { - console.error('[native-worker] closing the snapshot connection failed:', - describeNativeError(closeError, 'Unknown close error')); - }); -} - function closeAsyncDatabase() { return (async () => { const connection = asyncDb; diff --git a/natives/x86_64-linux-gnu/tjs b/natives/x86_64-linux-gnu/tjs index a5939e5d..cf1656cc 100755 Binary files a/natives/x86_64-linux-gnu/tjs and b/natives/x86_64-linux-gnu/tjs differ diff --git a/natives/x86_64-macos/tjs b/natives/x86_64-macos/tjs index d20bdd8b..340fd185 100755 Binary files a/natives/x86_64-macos/tjs and b/natives/x86_64-macos/tjs differ diff --git a/natives/x86_64-windows/tjs.exe b/natives/x86_64-windows/tjs.exe index 6bc49d98..53165427 100755 Binary files a/natives/x86_64-windows/tjs.exe and b/natives/x86_64-windows/tjs.exe differ diff --git a/package-lock.json b/package-lock.json index fe192ff7..13e9a1d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sqlite-explorer", - "version": "1.8.2", + "version": "1.8.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sqlite-explorer", - "version": "1.8.2", + "version": "1.8.3", "funding": [ { "type": "github", diff --git a/package.json b/package.json index f9a3bab4..a7e19abc 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "name": "sqlite-explorer", "displayName": "SQLite Explorer", "description": "A powerful SQLite database viewer and editor for VS Code", - "version": "1.8.2", + "version": "1.8.3", "publisher": "zknpr", "license": "MIT", "repository": { @@ -282,7 +282,8 @@ "test:gui:interactions": "node tests/gui/interaction-details.mjs", "test:gui:contention": "node tests/gui/native-contention.mjs", "test:gui:uploads": "node tests/gui/drop-upload.mjs", - "test:native-smoke": "node --import tsx --test tests/unit/native_real_smoke.test.ts" + "test:native-smoke": "node --import tsx --test tests/unit/native_real_smoke.test.ts", + "test:native-fuzz": "node --import tsx --test tests/fuzz/native_attach_fuzz.test.ts" }, "devDependencies": { "@types/node": "^26.6.5", diff --git a/scripts/build-query-plan.mjs b/scripts/build-query-plan.mjs index cd81a42c..d6e3ad9c 100644 --- a/scripts/build-query-plan.mjs +++ b/scripts/build-query-plan.mjs @@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url'; import { createPinnedArtifactPolicy } from './lib/pinned-artifacts.mjs'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); -const sourceCommit = '3181cc5ee888d3251228d3995c32bf9ea03c3240'; +const sourceCommit = '35ac205b7f9470d9aa7696ceb9cdab5dec4b6ed3'; const manifestPath = 'vendor/query-plan-manifest.json'; const sourceFiles = ['src/runtime/query-plan.c', 'scripts/build-query-plan.mjs']; const nativeTargets = [ diff --git a/scripts/refresh-natives.mjs b/scripts/refresh-natives.mjs index 5e21acd6..fff9e33d 100644 --- a/scripts/refresh-natives.mjs +++ b/scripts/refresh-natives.mjs @@ -7,8 +7,8 @@ * An already-downloaded artifact can be verified without network access only * when its complete pinned provenance is supplied explicitly: * node scripts/refresh-natives.mjs --from /path/to/run-artifacts \ - * --run 39983760340 --branch master \ - * --commit 0353db5719c80ee69e0f400f4dfcd2256a034ee0 + * --run 40086152581 --branch master \ + * --commit b45ac83ec0d7809c413afcf4091d7ecf12a46452 */ import { execFileSync } from 'node:child_process'; @@ -20,14 +20,14 @@ import { createPinnedArtifactPolicy } from './lib/pinned-artifacts.mjs'; const REPOSITORY = 'zknpr/txiki.js'; const SOURCE_BRANCH = 'master'; -const SOURCE_COMMIT = '0353db5719c80ee69e0f400f4dfcd2256a034ee0'; -const PINNED_RUN_ID = '39983760340'; +const SOURCE_COMMIT = 'b45ac83ec0d7809c413afcf4091d7ecf12a46452'; +const PINNED_RUN_ID = '40086152581'; const PINNED_SHA256 = Object.freeze({ - 'aarch64-linux-gnu/tjs': '6ec923d4ade3dc0d0e3d00224db52f4e39c9bfbce771a9b61b8843a90954ab96', - 'aarch64-macos/tjs': '155a7abdfbbbad0b2610b6ca6e6a6d10aa83bd610d4be0f6a15d352bf3f6969a', - 'x86_64-linux-gnu/tjs': 'ec13344d64c8506c1821d4006999e4d089b05fe2499cd13f103e700d9a06b395', - 'x86_64-macos/tjs': '6b9537e33cb5180501e5ef9e735b8126a72998e5fb4a17519722c2ec72457978', - 'x86_64-windows/tjs.exe': '83b757b6f9698c669b26aead2bf795d0e2800d1cb9da85513881dc21630d2a4b' + 'aarch64-linux-gnu/tjs': 'd316445ec08f39baf0bdcdf7624df73e17f9b166a1365283b396e6afd4ee778a', + 'aarch64-macos/tjs': 'eabb77e38e127d0cd6276f12195524981ac0a8362ce58b56757ce74d660175c8', + 'x86_64-linux-gnu/tjs': 'b437ea6321c5a1a281a9711990eb0c72cfba054cda9daff88145ee44d00a8d11', + 'x86_64-macos/tjs': 'f0daa1b39b6f081053f1a41cfb4c8ef28872d2c3512a837b5f1c0bbfced126a7', + 'x86_64-windows/tjs.exe': 'ae95f8c909a0b00fe5a35417ccae36541a5bea87b04f07dd203e59c77dd6150c' }); const scriptDirectory = path.dirname(fileURLToPath(import.meta.url)); diff --git a/src/bulkImport.ts b/src/bulkImport.ts index 2b71e862..5183e39f 100644 --- a/src/bulkImport.ts +++ b/src/bulkImport.ts @@ -5,6 +5,7 @@ import { ExtensionId } from './config'; import { IMPORT_MAX_BYTES, IMPORT_LIMIT_DESCRIPTION, parseImport, mapImportRows, importRowsAtomically } from './core/bulk-import'; import { runReadSnapshot } from './core/operation-serializer'; import type { DatabaseOperations } from './core/types'; +import { plainErrors, plainNotificationText } from './notificationText'; /** Read no more than the accepted source size, including when a file grows during preview. */ const readSource: (uri: vscode.Uri) => Promise = import.meta.env?.VSCODE_BROWSER_EXT @@ -56,10 +57,10 @@ function assertCurrent(database: DatabaseDocument, generation: number): void { } export function registerBulkImport(): vscode.Disposable { - return vscode.commands.registerCommand(`${ExtensionId}.importData`, async () => { + return vscode.commands.registerCommand(`${ExtensionId}.importData`, plainErrors(async () => { try { await importData(); } - catch (error) { await vscode.window.showErrorMessage(error instanceof Error ? error.message : String(error)); } - }); + catch (error) { await vscode.window.showErrorMessage(plainNotificationText(error instanceof Error ? error.message : String(error))); } + })); } async function importData(): Promise { @@ -129,7 +130,7 @@ async function importData(): Promise { await vscode.window.showTextDocument(preview, { preview: true }); const native = await database.databaseOperations.engineKind === 'native'; const rowLabel = rows.length === 1 ? 'row' : 'rows'; - const confirmed = await vscode.window.showWarningMessage(`Import ${rows.length} ${rowLabel} into ${table}?`, { + const confirmed = await vscode.window.showWarningMessage(plainNotificationText(`Import ${rows.length} ${rowLabel} into ${table}?`), { modal: true, detail: 'The preview shows the first five mapped rows, destination column types, and declared SQL default expressions. Defaults apply to omitted columns, not explicit JSON null or CSV empty strings. SQLite evaluates expressions when inserting each row. Preview edits do not change the import.\n\n' + (native ? 'This writes to the database file immediately. ' : '') + @@ -137,7 +138,7 @@ async function importData(): Promise { }, 'Import'); if (confirmed !== 'Import') return; assertCurrent(database, generation); - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: `Importing into ${table}`, cancellable: true }, async (progress, token) => { + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: plainNotificationText(`Importing into ${table}`), cancellable: true }, async (progress, token) => { const abort = new AbortController(); const cancellation = token.onCancellationRequested(() => abort.abort()); const closed = database.onDidDispose(() => abort.abort()); @@ -154,7 +155,7 @@ async function importData(): Promise { throw new Error('The destination database schema changed after the preview was prepared. Start the import again.'); } return importRowsAtomically(transaction, table, rows, database.undoMemoryLimitBytes, abort.signal, - completed => { if (completed % 50 === 0 || completed === rows.length) progress.report({ message: `${completed} / ${rows.length} ${rowLabel}` }); }); + completed => { if (completed % 50 === 0 || completed === rows.length) progress.report({ message: plainNotificationText(`${completed} / ${rows.length} ${rowLabel}`) }); }); }); // Recording belongs to the same document mutation gate as commit. // Do not throw on cancellation after the transaction has committed. @@ -162,5 +163,5 @@ async function importData(): Promise { }, true); } finally { cancellation.dispose(); closed.dispose(); } }); - await vscode.window.showInformationMessage(`Imported ${rows.length} ${rowLabel} into ${table}.`); + await vscode.window.showInformationMessage(plainNotificationText(`Imported ${rows.length} ${rowLabel} into ${table}.`)); } diff --git a/src/core/cell-containment.ts b/src/core/cell-containment.ts index b10643b3..587567a4 100644 --- a/src/core/cell-containment.ts +++ b/src/core/cell-containment.ts @@ -414,6 +414,30 @@ export function decodeRawTextColumns( }); } +/** + * Whether an engine's string, given the string decoded from SQLite's stored + * TEXT bytes, can stand for those bytes as text. TEXT containing NUL never + * counts: some engines and connections truncate it at NUL and others return it + * whole, and VS Code guesses UTF-16 from the NUL bytes of a file, so it stays + * bytes everywhere. + */ +export function decodedTextReproduces(decoded: string, value: string): boolean { + return decoded === value && !value.includes('\0'); +} + +/** decodedTextReproduces for raw bytes; bytes that do not decode never count. */ +function decodedTextReproducesBytes( + decoder: { decode(bytes: Uint8Array): string }, + rawBytes: Uint8Array, + value: string +): boolean { + try { + return decodedTextReproduces(decoder.decode(rawBytes), value); + } catch { + return false; + } +} + /** Identify rows whose decoded TEXT cells cannot reproduce SQLite's bytes. */ export function findUnrepresentableTextRows(input: { sourceRows: readonly (readonly unknown[])[]; @@ -453,14 +477,8 @@ export function findUnrepresentableTextRows(input: { const value = row[input.sourceColumnIndices[slot]]; if (typeof value !== 'string') continue; const rawBytes = rawRow[rawSlots[slot]]; - let representable = false; - if (rawBytes instanceof Uint8Array) { - try { - representable = decoder.decode(rawBytes) === value; - } catch { - representable = false; - } - } + const representable = rawBytes instanceof Uint8Array + && decodedTextReproducesBytes(decoder, rawBytes, value); if (!representable) { unrepresentableRows ??= new Set(); unrepresentableRows.add(rowIndex); @@ -527,13 +545,7 @@ export function containUnrepresentableTextCells(input: { `Raw TEXT containment bytes are missing at row ${rowIndex}, column ${columnIndex}` ); } - let representable = false; - try { - representable = decoder.decode(rawBytes) === sourceValue; - } catch { - representable = false; - } - if (representable) return; + if (decodedTextReproducesBytes(decoder, rawBytes, sourceValue)) return; const previousValue = rows[rowIndex][columnIndex]; const metadataInsertionBytes = oversizedMetadataInsertionWireBytes( oversizedCells, @@ -1076,20 +1088,14 @@ export function encodeByteFaithfulPrimaryKeyRecordId( const value = values[index]; if (typeof value !== 'string') continue; const rawBytes = projectedRow[keyCount + index]; - let representable = false; - if (rawBytes instanceof Uint8Array) { - try { - representable = decoder.decode(rawBytes) === value; - } catch { - representable = false; - } - } + const representable = rawBytes instanceof Uint8Array + && decodedTextReproducesBytes(decoder, rawBytes, value); if (!representable) { throw new Error( `${context}: WITHOUT ROWID primary-key column ` + `"${identity.columns[index].identifier}" contains text that is not valid ` + - `${textEncodingLabel(textEncoding)} without changing its stored bytes; ` + - `a byte-faithful editable identity cannot be minted` + `${textEncodingLabel(textEncoding)} without changing its stored bytes, ` + + `or that contains a NUL character; a byte-faithful editable identity cannot be minted` ); } } @@ -1104,8 +1110,8 @@ function readOnlyPrimaryKeyTextReason( return ( `Row is read-only because WITHOUT ROWID primary-key ` + `${columns.length === 1 ? 'column' : 'columns'} ${names} contain text that is not valid ` + - `${textEncodingLabel(encoding)} without changing its stored bytes; ` + - `a byte-faithful editable identity cannot be minted.` + `${textEncodingLabel(encoding)} without changing its stored bytes, or that contains a NUL ` + + `character; a byte-faithful editable identity cannot be minted.` ); } @@ -1161,10 +1167,11 @@ export function remapPrimaryKeyContainment( ) { throw new Error(`Primary-key raw TEXT row missing at index ${rowIndex}`); } - // A byte-invalid TEXT key also has a sparse containment entry so the grid - // routes it to the raw inspector. Validate its authoritative bytes before - // classifying that entry as merely size-contained; otherwise a one-byte - // malformed key is mislabeled as exceeding an 800+ KiB inline limit. + // A byte-invalid TEXT key, or one containing NUL, also has a sparse + // containment entry so the grid routes it to the raw inspector. Validate + // its authoritative bytes before classifying that entry as merely + // size-contained; otherwise a one-byte malformed key is mislabeled as + // exceeding an 800+ KiB inline limit. const unrepresentableTextMembers = input.rawTextValidationUnavailable ? input.identity.columns.map(column => column.identifier) : input.identity.columns.flatMap((column, keyIndex) => { @@ -1179,11 +1186,7 @@ export function remapPrimaryKeyContainment( } const rawBytes = rawTextRow[rawTextSlots[keyIndex]]; if (!(rawBytes instanceof Uint8Array)) return [column.identifier]; - try { - return textDecoder.decode(rawBytes) === value ? [] : [column.identifier]; - } catch { - return [column.identifier]; - } + return decodedTextReproducesBytes(textDecoder, rawBytes, value) ? [] : [column.identifier]; }); let recordId; if (input.rawTextValidationUnavailable) { diff --git a/src/databaseModel.ts b/src/databaseModel.ts index 44a13a06..692af246 100644 --- a/src/databaseModel.ts +++ b/src/databaseModel.ts @@ -31,6 +31,7 @@ import { isInvocationTimeoutError } from './core/rpc'; import { type DatabaseConnectionInvalidatedError, isDatabaseConnectionInvalidatedError } from './core/database-connection-invalidated'; import type { LabeledModification, DatabaseOperations } from './core/types'; import { LoggingDatabaseOperations } from './loggingDatabaseOperations'; +import { plainErrors, plainNotificationText } from './notificationText'; import { captureWorkspaceFileGeneration, writeWorkspaceFileAtomically @@ -305,10 +306,10 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { recoveryError = error; } await vsc.window.showErrorMessage( - vsc.l10n.t('[{0}] occurred while applying unsaved changes', errorMsg), + plainNotificationText(vsc.l10n.t('[{0}] occurred while applying unsaved changes', errorMsg)), { modal: true, - detail: !recoveryFailed + detail: plainNotificationText(!recoveryFailed ? vsc.l10n.t( 'The document was restored from backup, but changes could not be applied. ' + 'The saved database was reopened in read-only mode.' @@ -317,7 +318,7 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { 'The document was restored from backup, but changes could not be applied. ' + 'Reopening the saved database also failed: {0}', recoveryError instanceof Error ? recoveryError.message : String(recoveryError) - ) + )) } ); if (recoveryFailed) throw recoveryError; @@ -658,7 +659,7 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { 'Save the database before making more changes.' ); try { - void Promise.resolve(vsc.window.showWarningMessage(message)).catch(error => { + void Promise.resolve(vsc.window.showWarningMessage(plainNotificationText(message))).catch(error => { GlobalOutputChannel?.appendLine( `[Undo history warning failed] ${error instanceof Error ? error.message : String(error)}` ); @@ -685,8 +686,10 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { let editState: 'applied' | 'undoing' | 'undone' | 'redoing' = 'applied'; return { - label: modification.label, - undo: () => this.#runHistoryCallback(historyGeneration, async () => { + // VS Code shows the label in its "Could not undo" warning, and a + // rejected undo or redo in its own notification. + label: plainNotificationText(modification.label), + undo: plainErrors(() => this.#runHistoryCallback(historyGeneration, async () => { if (editState !== 'applied') return; editState = 'undoing'; @@ -736,13 +739,13 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { editState = 'applied'; const errorMessage = e instanceof Error ? e.message : String(e); GlobalOutputChannel?.appendLine(`[Undo] Failed: ${errorMessage}`); - vsc.window.showErrorMessage(vsc.l10n.t('Undo failed: {0}', errorMessage)); + vsc.window.showErrorMessage(plainNotificationText(vsc.l10n.t('Undo failed: {0}', errorMessage))); // A fulfilled callback tells VS Code that its edit was undone and // can clear the dirty marker, even though SQLite rolled it back. throw e; } - }), - redo: () => this.#runHistoryCallback(historyGeneration, async () => { + })), + redo: plainErrors(() => this.#runHistoryCallback(historyGeneration, async () => { if (editState !== 'undone') return; editState = 'redoing'; @@ -783,10 +786,10 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { editState = 'undone'; const errorMessage = e instanceof Error ? e.message : String(e); GlobalOutputChannel?.appendLine(`[Redo] Failed: ${errorMessage}`); - vsc.window.showErrorMessage(vsc.l10n.t('Redo failed: {0}', errorMessage)); + vsc.window.showErrorMessage(plainNotificationText(vsc.l10n.t('Redo failed: {0}', errorMessage))); throw e; } - }) + })) }; } @@ -1253,7 +1256,7 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { 'The prior value was not retained for an oversized-cell replacement. ' + 'File Revert cannot cross that edit; save the database first to establish a new baseline.' ); - await vsc.window.showWarningMessage(message); + await vsc.window.showWarningMessage(plainNotificationText(message)); throw new Error('File Revert cannot cross an unsaved oversized-cell history barrier'); } let invalidatedByRecoveryReload = false; @@ -1341,11 +1344,11 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { // and one visible warning until a current save request actually succeeds. this.#autoSaveFailureNotified = true; try { - void Promise.resolve(vsc.window.showErrorMessage(vsc.l10n.t( + void Promise.resolve(vsc.window.showErrorMessage(plainNotificationText(vsc.l10n.t( 'Auto-save failed for {0}: {1}. Changes remain unsaved. Keep the database editor open and retry Save.', this.fileParts.filename, errorMessage - ))).catch(error => { + )))).catch(error => { GlobalOutputChannel?.appendLine(`[Auto-save notification failed] ${error instanceof Error ? error.message : String(error)}`); }); } catch (error) { @@ -1621,10 +1624,10 @@ export class DatabaseDocument extends Disposable implements vsc.CustomDocument { (this.viewerProvider.outputChannel ?? GlobalOutputChannel)?.appendLine( `[Connection cleanup failed] ${message}` ); - void vsc.window.showErrorMessage(vsc.l10n.t( + void vsc.window.showErrorMessage(plainNotificationText(vsc.l10n.t( 'The database was reloaded, but its previous worker could not be closed: {0}', message - )); + ))); } return databaseOps; } diff --git a/src/editorController.ts b/src/editorController.ts index 6361b43e..c150e291 100644 --- a/src/editorController.ts +++ b/src/editorController.ts @@ -28,6 +28,7 @@ import { WebviewMessageHandler } from './webviewMessageHandler'; import { HostBridge } from './hostBridge'; import type { CellMaterializationService } from './cellMaterialization'; import { confirmFileReplacement } from './fileReplacementConfirmation'; +import { withPlainErrors } from './notificationText'; /** Coalesce provider opens that race before their shared document is registered. */ const PendingDocumentOpens = new Map }>(); @@ -593,6 +594,16 @@ export class DatabaseEditorProvider extends DatabaseViewerProvider implements vs } } +// VS Code shows the errors of these provider methods itself (see withPlainErrors). +const CUSTOM_EDITOR_METHODS = [ + 'openCustomDocument', + 'resolveCustomEditor', + 'saveCustomDocument', + 'saveCustomDocumentAs', + 'revertCustomDocument', + 'backupCustomDocument' +] satisfies (keyof vsc.CustomEditorProvider)[]; + /** * Register an editor provider for SQLite files. * @@ -620,7 +631,7 @@ export function registerEditorProvider( const Provider = enableReadWrite ? DatabaseEditorProvider : DatabaseViewerProvider; return vsc.window.registerCustomEditorProvider( viewType, - new Provider( + withPlainErrors(new Provider( viewType, context, reporter, @@ -629,7 +640,7 @@ export function registerEditorProvider( accessToken, readOnly, cellMaterializer - ), + ), CUSTOM_EDITOR_METHODS), { webviewOptions: { enableFindWidget: false, diff --git a/src/fileReplacementConfirmation.ts b/src/fileReplacementConfirmation.ts index c25e8bfa..99f5199e 100644 --- a/src/fileReplacementConfirmation.ts +++ b/src/fileReplacementConfirmation.ts @@ -1,4 +1,5 @@ import * as vsc from 'vscode'; +import { plainNotificationText } from './notificationText'; /** Native save dialogs do not consistently confirm replacement on every host. */ export async function confirmFileReplacement(uri: vsc.Uri, exists?: boolean): Promise { @@ -16,7 +17,7 @@ export async function confirmFileReplacement(uri: vsc.Uri, exists?: boolean): Pr const replace = vsc.l10n.t('Replace'); const selected = await vsc.window.showWarningMessage( vsc.l10n.t('Replace the existing file?'), - { modal: true, detail: uri.fsPath || uri.toString() }, + { modal: true, detail: plainNotificationText(uri.fsPath || uri.toString()) }, replace ); return selected === replace; diff --git a/src/hostBridge.ts b/src/hostBridge.ts index e05248eb..a6e2c0a8 100644 --- a/src/hostBridge.ts +++ b/src/hostBridge.ts @@ -50,6 +50,7 @@ import { estimateUndoMemoryBytes } from './core/undo-history'; import type { CellMaterializationService } from './cellMaterialization'; import { openCellContentViewer } from './cellContentViewer'; import { writeCellFile } from './tableExporter'; +import { plainNotificationText } from './notificationText'; import { assertCellValueWithinEditLimit, assertCellValuesWithinEditLimit, @@ -597,7 +598,7 @@ export class HostBridge implements ToastService { byteLength: Number(byteLength) } as const; const answer = await vsc.window.showWarningMessage( - formatOversizedCellReplacementWarning(table, column, expected), + plainNotificationText(formatOversizedCellReplacementWarning(table, column, expected)), { modal: true }, { title: vsc.l10n.t('Replace Without Undo'), value: true }, { title: vsc.l10n.t('Cancel'), value: false, isCloseAffordance: true } @@ -896,7 +897,7 @@ export class HostBridge implements ToastService { ); const result = await vsc.window.showWarningMessage( - message, + plainNotificationText(message), { modal: true }, { title: vsc.l10n.t('Drop Indexes & Continue'), value: true }, { title: vsc.l10n.t('Cancel'), value: false, isCloseAffordance: true } @@ -1194,11 +1195,11 @@ export class HostBridge implements ToastService { if (current.triggers.length > 0) { const triggerNames = current.triggers.map(trigger => trigger.identifier).join(', '); const answer = await vsc.window.showWarningMessage( - vsc.l10n.t( + plainNotificationText(vsc.l10n.t( 'Editing view "{0}" without preserving triggers will permanently drop: {1}', view, triggerNames - ), + )), { modal: true }, { title: vsc.l10n.t('Edit and Drop Triggers'), value: true }, { title: vsc.l10n.t('Cancel'), value: false, isCloseAffordance: true } @@ -1248,7 +1249,7 @@ export class HostBridge implements ToastService { ) : vsc.l10n.t('Drop view "{0}"?', view); const answer = await vsc.window.showWarningMessage( - confirmationMessage, + plainNotificationText(confirmationMessage), { modal: true }, { title: vsc.l10n.t('Drop View'), value: true }, { title: vsc.l10n.t('Cancel'), value: false, isCloseAffordance: true } @@ -1641,21 +1642,21 @@ export class HostBridge implements ToastService { * Show an information toast message. */ async showInformationToast(message: string, options?: DialogConfig, ...items: T[]): Promise { - return showToast(vsc.window.showInformationMessage, message, options, items); + return showToast('information', message, options, items); } /** * Show a warning toast message. */ async showWarningToast(message: string, options?: DialogConfig, ...items: T[]): Promise { - return showToast(vsc.window.showWarningMessage, message, options, items); + return showToast('warning', message, options, items); } /** * Show an error toast message. */ async showErrorToast(message: string, options?: DialogConfig, ...items: T[]): Promise { - return showToast(vsc.window.showErrorMessage, message, options, items); + return showToast('error', message, options, items); } /** @@ -2088,7 +2089,7 @@ export class HostBridge implements ToastService { if (!Number.isSafeInteger(itemCount) || itemCount <= 0) throw new Error('Large change count must be a positive safe integer'); if (unit !== 'rows' && unit !== 'cells') throw new Error('Large change unit must be rows or cells'); const answer = await vsc.window.showWarningMessage(vsc.l10n.t('Large Change Warning'), { - detail: `This operation changes ${itemCount.toLocaleString()} ${unit}. Do you want to continue?`, + detail: plainNotificationText(`This operation changes ${itemCount.toLocaleString()} ${unit}. Do you want to continue?`), modal: true, }, { title: vsc.l10n.t('Continue'), value: true }, { title: vsc.l10n.t('Cancel'), value: false, isCloseAffordance: true }); return answer?.value ?? false; @@ -2115,11 +2116,11 @@ export class HostBridge implements ToastService { } const answer = await vsc.window.showWarningMessage(vsc.l10n.t('Large Selection Warning'), { - detail: vsc.l10n.t( + detail: plainNotificationText(vsc.l10n.t( 'Selecting {0} {1} may slow or freeze the editor. Cancel and use Export for large data operations. Continue?', itemCount.toLocaleString(), unit - ), + )), modal: true, }, { title: vsc.l10n.t('Continue'), value: true }, { title: vsc.l10n.t('Cancel'), @@ -2326,31 +2327,51 @@ export class HostBridge implements ToastService { } /** - * Map DialogConfig/DialogButton to VS Code MessageOptions/MessageItem and invoke the show function. + * Map DialogConfig/DialogButton to VS Code MessageOptions/MessageItem and show the message. * * DialogConfig.detailText → MessageOptions.detail * DialogButton.caption → MessageItem.title * DialogButton.isCloseAction → MessageItem.isCloseAffordance + * + * The message and detail are shown without links like every other notification + * text. */ async function showToast( - showFn: typeof vsc.window.showInformationMessage, + severity: 'information' | 'warning' | 'error', message: string, options: DialogConfig | undefined, items: T[] ): Promise { - // Map DialogConfig → MessageOptions - const msgOptions: vsc.MessageOptions = options - ? { modal: options.modal, detail: options.detailText } - : {}; - - // Map DialogButton items → MessageItem, pass strings through - const msgItems: (string | vsc.MessageItem)[] = items.map(item => + // Map DialogButton items → MessageItem, pass strings through. The show + // functions' overloads take either strings or MessageItems; VS Code accepts + // a mix of both. + const msgItems = items.map(item => typeof item === 'string' ? item : { title: (item as DialogButton).caption, isCloseAffordance: (item as DialogButton).isCloseAction } - ); - - const result = await (showFn as Function)(message, msgOptions, ...msgItems); + ) as vsc.MessageItem[]; + + let result: string | vsc.MessageItem | undefined; + switch (severity) { + case 'information': + result = await vsc.window.showInformationMessage(plainNotificationText(message), { + modal: options?.modal, + detail: options?.detailText == null ? undefined : plainNotificationText(options.detailText) + }, ...msgItems); + break; + case 'warning': + result = await vsc.window.showWarningMessage(plainNotificationText(message), { + modal: options?.modal, + detail: options?.detailText == null ? undefined : plainNotificationText(options.detailText) + }, ...msgItems); + break; + case 'error': + result = await vsc.window.showErrorMessage(plainNotificationText(message), { + modal: options?.modal, + detail: options?.detailText == null ? undefined : plainNotificationText(options.detailText) + }, ...msgItems); + break; + } // Map MessageItem result back to the original DialogButton if (result && typeof result === 'object' && 'title' in result) { diff --git a/src/main.ts b/src/main.ts index e6cb8576..16ab28e8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,6 +12,7 @@ import { CellMaterializationService } from './cellMaterialization'; import { createDesktopTestApi, type DesktopTestApi } from './desktopTestApi'; import { DocumentRegistry } from './documentRegistry'; import { generateDatabaseDocumentKey } from './helpers'; +import { plainErrors, withPlainErrors } from './notificationText'; export let GlobalOutputChannel: vsc.OutputChannel|null = null; @@ -40,13 +41,13 @@ export async function activate( // Register refresh command context.subscriptions.push( - vsc.commands.registerCommand(`${ExtensionId}.refresh`, refreshActiveDatabase), + vsc.commands.registerCommand(`${ExtensionId}.refresh`, plainErrors(refreshActiveDatabase)), ); // Register export table command context.subscriptions.push( - vsc.commands.registerCommand(`${ExtensionId}.exportTable`, (dbParams: DbParams, columns: string[], dbOptions?: unknown, tableStore?: unknown, exportOptions?: ExportOptions, extras?: unknown) => - exportTableCommand(context, reporter, dbParams, columns, dbOptions, tableStore, exportOptions, extras)), + vsc.commands.registerCommand(`${ExtensionId}.exportTable`, plainErrors((dbParams: DbParams, columns: string[], dbOptions?: unknown, tableStore?: unknown, exportOptions?: ExportOptions, extras?: unknown) => + exportTableCommand(context, reporter, dbParams, columns, dbOptions, tableStore, exportOptions, extras))), ); context.globalState.setKeysForSync(SyncedKeys); @@ -129,7 +130,12 @@ export async function activateProviders(context: vsc.ExtensionContext, reporter? if (cellMaterializer) subs.push(cellMaterializer); // Register file system provider - subs.push(vsc.workspace.registerFileSystemProvider(UriScheme, new SQLiteFileSystemProvider(), { isCaseSensitive: true })); + subs.push(vsc.workspace.registerFileSystemProvider( + UriScheme, + withPlainErrors(new SQLiteFileSystemProvider(), + ['stat', 'readDirectory', 'createDirectory', 'readFile', 'writeFile', 'delete', 'rename'] satisfies (keyof vsc.FileSystemProvider)[]), + { isCaseSensitive: true } + )); // Register the main editor provider (default for .sqlite, .db, etc.) subs.push(registerEditorProvider( diff --git a/src/nativeWorker.ts b/src/nativeWorker.ts index 67d19132..e9fc70ca 100644 --- a/src/nativeWorker.ts +++ b/src/nativeWorker.ts @@ -337,7 +337,7 @@ const BOUNDED_QUERY_TRANSPORT_MARGIN_MS = 2000; * @param extensionPath - Extension installation directory * @returns Path to native binary or null if unsupported */ -async function getNativeBinaryPath(extensionPath: string): Promise { +export async function getNativeBinaryPath(extensionPath: string): Promise { const platform = process.platform; const arch = process.arch; diff --git a/src/notificationText.ts b/src/notificationText.ts new file mode 100644 index 00000000..5d945761 --- /dev/null +++ b/src/notificationText.ts @@ -0,0 +1,87 @@ +/** + * VS Code still parses `[label](command:id?args)`, `https:` and `file:` links + * in the text extensions pass to notifications and progress titles, and a click + * runs the command with the JSON arguments from the link (microsoft/vscode + * notificationLegacy.ts, notificationsViewer.ts and openerService.ts). SQLite + * error messages, table, column and index names and file names can all come + * from a crafted database, so every such text goes through this function before + * it is shown, including modal messages, which are cheap to cover. + * + * The link syntax needs `]` immediately followed by `(`. A zero-width space + * after every `]` leaves the text reading the same and leaves VS Code nothing + * to parse. It goes after every `]`, not only before `(`, because VS Code + * removes `$(icon)` syntax from a progress title before parsing it, so + * `]$(x)(` would become `](`; U+200B is not whitespace to that removal. A `]` + * already followed by one is left alone, so disarming twice changes nothing: + * errors are disarmed in place and can pass through a wrapper again. + */ +export function plainNotificationText(text: string): string { + return text.replace(/\](?!\u200B)/g, ']\u200B'); +} + +/** + * VS Code shows the errors that providers and commands throw back to it in its + * own notifications, for example "Failed to save '…': ". VS Code 1.141 + * stopped parsing links in its own messages, but the 1.110 to 1.140 releases + * this extension supports parse them like extension messages. The message is + * disarmed in place so the error keeps its class and code + * (vscode.CancellationError, vscode.FileSystemError). + * + * A DOMException, such as an aborted save's AbortError, defines message as a + * getter without a setter: assigning it throws in strict mode and would replace + * the error. An own property shadows the getter instead; an own data property, + * which a sealed error keeps, only gets a new value. An error whose message + * cannot be changed, such as a frozen one, is replaced by a plain Error with it + * as cause. A message that is not text is left to VS Code. + */ +export function plainNotificationError(error: unknown): unknown { + if (error instanceof Error) { + if (typeof error.message !== 'string') return error; + const message = plainNotificationText(error.message); + if (message === error.message) return error; + const own = Object.getOwnPropertyDescriptor(error, 'message'); + try { + Object.defineProperty(error, 'message', own && 'value' in own + ? { value: message } + : { value: message, writable: true, configurable: true }); + } catch { + return new Error(message, { cause: error }); + } + return error; + } + return typeof error === 'string' ? plainNotificationText(error) : error; +} + +/** A command handler whose errors reach VS Code through plainNotificationError. */ +export function plainErrors(action: (...args: A) => R | PromiseLike): (...args: A) => Promise { + return async (...args: A) => { + try { + return await action(...args); + } catch (error) { + throw plainNotificationError(error); + } + }; +} + +/** + * The provider object to register with VS Code: the listed methods' errors pass + * through plainNotificationError. Every function runs on the provider itself, + * so its private fields keep working; a listed method the provider lacks stays + * absent. + */ +export function withPlainErrors(provider: T, methods: readonly string[]): T { + const wrapped = new Map(); + for (const name of methods) { + const method: unknown = Reflect.get(provider, name); + if (typeof method === 'function') { + wrapped.set(name, plainErrors((...args: unknown[]) => method.apply(provider, args))); + } + } + return new Proxy(provider, { + get: (target, property) => { + if (wrapped.has(property)) return wrapped.get(property); + const value: unknown = Reflect.get(target, property, target); + return typeof value === 'function' ? value.bind(target) : value; + } + }); +} diff --git a/src/sqlWorkspace.ts b/src/sqlWorkspace.ts index 30d61a53..349eff02 100644 --- a/src/sqlWorkspace.ts +++ b/src/sqlWorkspace.ts @@ -6,6 +6,7 @@ import { escapeIdentifier } from './core/sql-utils'; import { parseQueryParameters, prepareReadQuery, resultCsv, SQL_RESULT_ROWS } from './core/sql-workspace'; import type { QueryResultSet } from './core/types'; import { writeQueryResultFile } from './tableExporter'; +import { plainErrors, plainNotificationText } from './notificationText'; interface QueryBinding { database: DatabaseDocument } interface QueryOutput { text: string; csv: string } @@ -132,8 +133,10 @@ export function registerSqlWorkspace(_context: vscode.ExtensionContext): vscode. validateInput: value => { try { const values = parseQueryParameters(value); - return values.length === prepared.parameterCount ? undefined : `Expected ${prepared.parameterCount} values.`; - } catch (error) { return error instanceof Error ? error.message : String(error); } + return values.length === prepared.parameterCount + ? undefined + : plainNotificationText(`Expected ${prepared.parameterCount} values.`); + } catch (error) { return plainNotificationText(error instanceof Error ? error.message : String(error)); } } }); if (answer === undefined) return; @@ -160,12 +163,12 @@ export function registerSqlWorkspace(_context: vscode.ExtensionContext): vscode. } finally { cancel.dispose(); close.dispose(); } }); }; - const command = (suffix: string, action: (...args: unknown[]) => Promise | unknown) => subscriptions.push(vscode.commands.registerCommand(`${ExtensionId}.${suffix}`, async (...args: unknown[]) => { + const command = (suffix: string, action: (...args: unknown[]) => Promise | unknown) => subscriptions.push(vscode.commands.registerCommand(`${ExtensionId}.${suffix}`, plainErrors(async (...args: unknown[]) => { try { await action(...args); } catch (error) { - if (!(error instanceof vscode.CancellationError)) await vscode.window.showErrorMessage(error instanceof Error ? error.message : String(error)); + if (!(error instanceof vscode.CancellationError)) await vscode.window.showErrorMessage(plainNotificationText(error instanceof Error ? error.message : String(error))); } - })); + }))); command('newQuery', async (target?: unknown) => { const database = await selectDatabase(target); if (!database) return; const document = await vscode.workspace.openTextDocument({ language: 'sql', content: 'SELECT 1 AS value;\n' }); diff --git a/src/tableExporter.ts b/src/tableExporter.ts index e9f5f5b4..28a42758 100644 --- a/src/tableExporter.ts +++ b/src/tableExporter.ts @@ -21,6 +21,7 @@ import { type ExportCancellation } from './tableExportStreaming'; import { crypto as webCrypto } from './platform/cryptoShim'; +import { plainNotificationText } from './notificationText'; import { replacementFileMetadataFromStats, restoreTemporaryMetadata, @@ -953,7 +954,7 @@ export async function exportTableCommand( const tableName = dbParams.table; if (!tableName) { const message = 'No table specified for export'; - showExportNotification(vsc.window.showErrorMessage(message)); + showExportNotification(vsc.window.showErrorMessage(plainNotificationText(message))); return { success: false, message }; } @@ -985,7 +986,7 @@ export async function exportTableCommand( } if (!document) { const message = 'The requested database is no longer open'; - showExportNotification(vsc.window.showErrorMessage(message)); + showExportNotification(vsc.window.showErrorMessage(plainNotificationText(message))); return { success: false, message }; } } else { @@ -997,7 +998,7 @@ export async function exportTableCommand( if (!document || !document.databaseOperations) { const message = 'No active database connection'; - showExportNotification(vsc.window.showErrorMessage(message)); + showExportNotification(vsc.window.showErrorMessage(plainNotificationText(message))); return { success: false, message }; } @@ -1013,7 +1014,7 @@ export async function exportTableCommand( ); } catch (e) { const message = (e as Error).message; - showExportNotification(vsc.window.showErrorMessage(message)); + showExportNotification(vsc.window.showErrorMessage(plainNotificationText(message))); return { success: false, message }; } @@ -1042,7 +1043,7 @@ export async function exportTableCommand( const rowCount = await vsc.window.withProgress( { location: vsc.ProgressLocation.Notification, - title: `Exporting "${tableName}"`, + title: plainNotificationText(`Exporting "${tableName}"`), cancellable: true }, async (_progress, cancellation) => { @@ -1069,10 +1070,10 @@ export async function exportTableCommand( ); } ); - showExportNotification(vsc.window.showInformationMessage( + showExportNotification(vsc.window.showInformationMessage(plainNotificationText( `Exported ${rowCount} row${rowCount === 1 ? '' : 's'} to ` + `${uri.fsPath || uri.toString()}` - )); + ))); return { success: true, rowCount, @@ -1085,7 +1086,7 @@ export async function exportTableCommand( return { success: false, cancelled: true }; } const message = err instanceof Error ? err.message : String(err); - showExportNotification(vsc.window.showErrorMessage(`Export failed: ${message}`)); + showExportNotification(vsc.window.showErrorMessage(plainNotificationText(`Export failed: ${message}`))); console.error('Export error:', err); return { success: false, message }; } diff --git a/src/virtualFileSystem.ts b/src/virtualFileSystem.ts index 894041b2..9324cdb8 100644 --- a/src/virtualFileSystem.ts +++ b/src/virtualFileSystem.ts @@ -1,5 +1,6 @@ import * as vsc from 'vscode'; import { DocumentRegistry } from './documentRegistry'; +import { plainNotificationText } from './notificationText'; import { escapeIdentifier, escapeMainIdentifier, validateRowId } from './core/sql-utils'; import { buildRecordIdentityPredicate, @@ -14,6 +15,7 @@ import { } from './core/view-utils'; import { GlobalOutputChannel } from './main'; import { getMaxInlineCellBytes } from './config'; +import { decodedTextReproduces } from './core/cell-containment'; import { sqliteIdentifiersEqual } from './core/integer-utils'; import { assertCellValueWithinEditLimit, @@ -330,7 +332,7 @@ export class SQLiteFileSystemProvider implements vsc.FileSystemProvider { 'Open its raw Hex inspector or export it instead.' ); } - if (decoded !== value) { + if (!decodedTextReproduces(decoded, value)) { throw vsc.FileSystemError.NoPermissions( 'This TEXT cell cannot be represented by the external text editor without ' + 'changing its stored bytes. Open its raw Hex inspector or export it instead.' @@ -428,7 +430,7 @@ export class SQLiteFileSystemProvider implements vsc.FileSystemProvider { GlobalOutputChannel?.appendLine(`[VirtualFileSystem] Error writing view definition: ${rawMessage}`); const detail = getViewDefinitionErrorDetail(err); void vsc.window.showErrorMessage( - `Invalid view definition: ${detail}. The view was not modified.` + plainNotificationText(`Invalid view definition: ${detail}. The view was not modified.`) ).then(undefined, notificationError => { GlobalOutputChannel?.appendLine( `[VirtualFileSystem] Failed to show view error notification: ${notificationError instanceof Error ? notificationError.message : String(notificationError)}` @@ -526,7 +528,7 @@ export class SQLiteFileSystemProvider implements vsc.FileSystemProvider { byteLength: metadata.byteLength }; const answer = await vsc.window.showWarningMessage( - formatOversizedCellReplacementWarning(table, column, expected), + plainNotificationText(formatOversizedCellReplacementWarning(table, column, expected)), { modal: true }, { title: vsc.l10n.t('Replace Without Undo'), value: true }, { title: vsc.l10n.t('Cancel'), value: false, isCloseAffordance: true } @@ -625,7 +627,7 @@ export class SQLiteFileSystemProvider implements vsc.FileSystemProvider { } catch { decoded = ''; } - if (decoded !== boundedValue) { + if (typeof boundedValue !== 'string' || !decodedTextReproduces(decoded, boundedValue)) { throw vsc.FileSystemError.NoPermissions( 'This TEXT cell cannot be edited as text without changing its stored bytes. ' + 'Open its raw Hex inspector or export it instead.' diff --git a/src/workerFactory.ts b/src/workerFactory.ts index 274efeb2..3cc206b4 100644 --- a/src/workerFactory.ts +++ b/src/workerFactory.ts @@ -67,6 +67,7 @@ import { createSharedCancellationFlag } from './core/cancellation-utils'; import { writePagedWritableOverlayToFile } from './pagedWritableSave'; import { canPersistLocalDatabase } from './fileWritability'; import { DatabaseFileSizeLimitError } from './databaseFileSizeLimit'; +import { plainNotificationText } from './notificationText'; // Native worker support (only in Node.js environment) let nativeSupport: { @@ -1399,10 +1400,10 @@ function warnWalReadOnlyDowngrade(displayName: string): void { ); // Fire-and-forget: the toast resolves when dismissed and must not block // connection establishment. - void vsc.window.showWarningMessage(vsc.l10n.t( + void vsc.window.showWarningMessage(plainNotificationText(vsc.l10n.t( '{0} has WAL changes the WebAssembly SQLite backend cannot read, so it is opened read-only and the data shown may be incomplete. Run "PRAGMA wal_checkpoint(TRUNCATE)" on the database (or close the program writing to it), then reopen it.', displayName - )); + ))); } /** @@ -1420,8 +1421,8 @@ function warnPagedReadOnlyDowngrade(displayName: string): void { 'or use the native desktop backend to edit and save it.' ); // Fire-and-forget, matching warnWalReadOnlyDowngrade. - void vsc.window.showWarningMessage(vsc.l10n.t( + void vsc.window.showWarningMessage(plainNotificationText(vsc.l10n.t( '{0} is open page-on-demand as read-only. Reopen with writable page-on-demand support or use the native desktop backend to edit and save it.', displayName - )); + ))); } diff --git a/tests/fuzz/native_attach_fuzz.test.ts b/tests/fuzz/native_attach_fuzz.test.ts new file mode 100644 index 00000000..940c0c55 --- /dev/null +++ b/tests/fuzz/native_attach_fuzz.test.ts @@ -0,0 +1,268 @@ +import '../unit/vscode_mock_setup'; // Must be first + +import assert from 'node:assert/strict'; +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { DatabaseSync } from 'node:sqlite'; +import { it } from 'node:test'; + +import { getNativeBinaryPath, NativeWorkerProcess } from '../../src/nativeWorker'; + +// Differential fuzz of the native ATTACH/DETACH/VACUUM INTO refusal (the +// worker's tokenizer guard and the runtime's authorizer): node:sqlite decides +// whether SQLite itself would attach or write a file for a generated +// statement; the native worker must then leave no trace of it. Seeded so a +// failure reproduces. Opt-in (`npm run test:native-fuzz`, outside the unit +// glob); .github/workflows/native-fuzz.yml runs it on every bundled target. +// +// FUZZ_SINGLE / FUZZ_SCRIPTS: statement counts. FUZZ_SEED: generator seed. +// FUZZ_NO_CONTROL=1: skip the node:sqlite oracle. FUZZ_DEBUG=1: log the first +// oracle errors. FUZZ_EXPECT_TARGET: fail unless natives/ is the +// runtime exercised (CI sets it per runner). +const ROOT = process.cwd(); +const SINGLE = Number(process.env.FUZZ_SINGLE ?? 30000); +const SCRIPTS = Number(process.env.FUZZ_SCRIPTS ?? 10000); +const CONTROL = process.env.FUZZ_NO_CONTROL !== '1'; +// Two sanity floors on the generator; neither judges the worker. +// Control share: statements node:sqlite would execute (attach, or create or +// write a file), i.e. work the guard must refuse rather than syntax errors it +// never judges. Default counts measure 50.7% at the default seed and +// 50.3-51.3% over seeds 1-7; the default seed measures 45.2% singles-only and +// 68.7% scripts-only. 25% is about half the lowest of those, so seed, count +// and mix variance cannot trip it while a generator degrading into mostly +// rejected SQL does. Below CONTROL_MIN_SAMPLE statements the share is too +// noisy to judge. +// Distinct share: statements unique once counter digits are normalized. The +// generator measures 99.97% at default counts and a cycling PRNG collapses it +// (see rand), so 90% catches a repeat loop with room for incidental collisions. +const CONTROL_SHARE_FLOOR = 0.25; +const CONTROL_MIN_SAMPLE = 1000; +const DISTINCT_SHARE_FLOOR = 0.9; +let debugLeft = 15; +let seed = Number(process.env.FUZZ_SEED ?? 0x5eed1821); +// Math.imul, not `*`: the double product exceeds 2^53 and drops low bits, and +// that lossy map falls into a 419-step cycle within ~20k draws for most seeds +// (95 distinct statements out of 40,000 at the default seed). The exact +// 32-bit LCG has full period. +const rand = () => ((seed = (Math.imul(seed, 1103515245) + 12345) >>> 0) / 0x100000000); +const pick = (items: readonly T[]) => items[Math.floor(rand() * items.length)]; +const many = (make: () => string, max: number) => Array.from({ length: Math.floor(rand() * (max + 1)) }, make).join(''); + +// No \v: SQLite's tokenizer classes 0x0B as illegal, not whitespace. +const TRIVIA = [' ', '\t', '\n', '\r', '\f', '\uFEFF', '-- c\n', '-- c\r\n', '/* c */', '/**/', '/*\n*/']; +const caseVariant = (word: string) => [...word].map(ch => (rand() < 0.5 ? ch.toLowerCase() : ch.toUpperCase())).join(''); +const trivia = () => many(() => pick(TRIVIA), 3); +const lead = () => many(() => pick([...TRIVIA, ';', ';\n']), 4); +const sqlEscape = (value: string) => value.replaceAll('\'', '\'\''); +const sqlString = (value: string) => `'${sqlEscape(value)}'`; + +function filenameExpression(target: string): { sql: string; params: unknown[] } { + // Split only at the directory boundary so the control arm can relocate + // every form by rewriting the outside directory prefix. basename, not a + // '/' search, so Windows paths split there too. + const cut = target.length - path.basename(target).length; + return pick([ + () => ({ sql: sqlString(target), params: [] }), + () => ({ sql: '?', params: [target] }), + () => ({ sql: `${sqlString(target.slice(0, cut))}||${sqlString(target.slice(cut))}`, params: [] }), + () => ({ sql: `printf('%s',${sqlString(target)})`, params: [] }), + () => ({ sql: `(${sqlString(target)})`, params: [] }), + ])(); +} + +function explainPrefix(): string { + return pick(['', '', '', `${caseVariant('explain')}${trivia() || ' '}`, + `${caseVariant('explain')} ${trivia()}${caseVariant('query')} ${trivia()}${caseVariant('plan')} ${trivia()}`]); +} + +function attachStatement(target: string, alias: string) { + const file = filenameExpression(target); + const verb = caseVariant('attach') + (rand() < 0.5 ? ` ${trivia()}${caseVariant('database')}` : ''); + return { sql: `${explainPrefix()}${verb} ${trivia()}${file.sql}${trivia()} ${caseVariant('as')} ${trivia()}${alias}`, params: file.params }; +} + +function vacuumStatement(target: string) { + const file = filenameExpression(target); + const schema = pick(['', ' main', ' "main"', ' [main]', ' `main`', " 'main'"]); + return { sql: `${explainPrefix()}${caseVariant('vacuum')}${schema} ${trivia()}${caseVariant('into')} ${trivia()}${file.sql}`, params: file.params }; +} + +function controlEffect(sql: string, params: unknown[], outside: string, dir: string): boolean { + // Would SQLite itself attach or write a file? Relocate the whole outside + // directory into a scratch mirror (with the same seeded files) so the + // control never touches the fixture the worker is judged on. + const scratch = fs.mkdtempSync(path.join(dir, 'control-')); + const mirror = path.join(scratch, 'outside'); + fs.cpSync(outside, mirror, { recursive: true }); + const before = new Set(fs.readdirSync(mirror)); + // In SQL text a path only appears inside string literals, i.e. with its + // quotes doubled; matching the raw spelling there would miss a tmpdir + // containing a quote and run the control against the real fixture. + const relocateSql = (text: string) => text.split(sqlEscape(outside)).join(sqlEscape(mirror)); + const relocateValue = (text: string) => text.split(outside).join(mirror); + const db = new DatabaseSync(path.join(scratch, 'c.sqlite')); + try { + db.exec('CREATE TABLE t(v)'); + try { + if (params.length > 0) db.prepare(relocateSql(sql)).all(...params.map(value => relocateValue(String(value)))); + else db.exec(relocateSql(sql)); + } catch (error) { + // A script SQLite rejects part-way can still have attached first. + if (process.env.FUZZ_DEBUG && debugLeft-- > 0) console.log('CONTROL-ERR', (error as Error).message, JSON.stringify(sql.slice(0, 160))); + } + const attached = db.prepare('PRAGMA database_list').all().some(row => row.name !== 'main' && row.name !== 'temp'); + const created = fs.readdirSync(mirror).some(entry => !before.has(entry)); + return attached || created; + } finally { + db.close(); + // Retries: Windows briefly refuses to delete just-closed files + // (EBUSY/EPERM while a scanner holds them). + fs.rmSync(scratch, { recursive: true, force: true, maxRetries: 10 }); + } +} + +it('native worker leaves no trace of any ATTACH/DETACH/VACUUM INTO SQLite would execute', { timeout: 3_600_000 }, async () => { + // The extension's own platform/arch -> natives/ resolution, so the + // lane exercises the runtime a user on this host gets. No skip: the lane + // is opt-in, and a missing runtime must fail rather than pass vacuously. + const binary = await getNativeBinaryPath(ROOT); + assert.ok(binary, `no bundled native runtime for ${process.platform}-${process.arch} under ${ROOT}`); + const target = path.basename(path.dirname(binary)); + const expectedTarget = process.env.FUZZ_EXPECT_TARGET; + if (expectedTarget) assert.equal(target, expectedTarget, `exercised natives/${target}, expected natives/${expectedTarget}`); + + const worker = new NativeWorkerProcess(binary, path.join(ROOT, 'natives', 'native-worker.js')); + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sqlite-explorer-attach-fuzz-')); + try { + const bound = path.join(dir, 'bound', 'bound.sqlite'); + const outside = path.join(dir, 'outside'); + fs.mkdirSync(path.dirname(bound)); + fs.mkdirSync(outside); + const secret = path.join(outside, 'secret.sqlite'); + for (const [file, sql] of [[bound, 'CREATE TABLE entries(v); INSERT INTO entries VALUES (1);'], [secret, 'CREATE TABLE secret(v); INSERT INTO secret VALUES (1);']]) { + const seedDb = new DatabaseSync(file); + seedDb.exec(sql); + seedDb.close(); + } + const empty = path.join(outside, 'empty.bin'); + fs.writeFileSync(empty, new Uint8Array(0)); + const secretBytes = fs.readFileSync(secret); + + await worker.start(); + await worker.call('open', [bound, false]); + const version = (await worker.call<{ values: unknown[][] }>('query', ['SELECT sqlite_version()'])).values[0]?.[0]; + console.log(`[native fuzz] target=${target} binary=${path.relative(ROOT, binary)} host=${process.platform}-${process.arch} sqlite=${version}`); + + const seen = new Set(fs.readdirSync(outside)); + let counter = 0; + const stats = { generated: 0, distinct: 0, sqliteWouldExecute: 0, workerTraces: 0, workerRefused: 0, workerOther: 0 }; + const shapes = new Set(); + const failures: string[] = []; + + const traces = async (): Promise => { + const found: string[] = []; + const list = await worker.call<{ values: unknown[][] }>('query', ['PRAGMA database_list']); + for (const row of list.values) if (row[1] !== 'main' && row[1] !== 'temp') found.push(`schema ${row[1]}`); + for (const entry of fs.readdirSync(outside)) if (!seen.has(entry)) { seen.add(entry); found.push(`file ${entry}`); } + if (fs.statSync(empty).size !== 0) found.push('empty.bin written'); + if (!fs.readFileSync(secret).equals(secretBytes)) found.push('secret.sqlite modified'); + return found; + }; + + // Positive control for the detector: the worker's own export snapshot + // (vacuumInto, the runtime's one exception to the ATTACH refusal) + // creates a file in outside and fills the empty file. A detector blind + // to either would make every clean run below vacuous. The schema check + // reads PRAGMA database_list's name column, so pin that column first. + const schemas = (await worker.call<{ values: unknown[][] }>('query', ['PRAGMA database_list'])).values.map(row => row[1]); + assert.ok(schemas.includes('main'), `unexpected PRAGMA database_list shape: ${JSON.stringify(schemas)}`); + assert.deepEqual(await traces(), [], 'fixture must start without traces'); + const probe = path.join(outside, 'detector-probe.sqlite'); + await worker.call('vacuumInto', [probe]); + await worker.call('vacuumInto', [empty]); + assert.deepEqual((await traces()).sort(), ['empty.bin written', 'file detector-probe.sqlite'], 'detector must see the permitted export writes'); + fs.rmSync(probe, { recursive: true, maxRetries: 10 }); + seen.delete(path.basename(probe)); + fs.writeFileSync(empty, new Uint8Array(0)); + assert.deepEqual(await traces(), [], 'detector probe must reset cleanly'); + console.log('[native fuzz] detector probe: export file and empty-file write both detected'); + + const attempt = async (sql: string, params: unknown[], entry: string) => { + stats.generated++; + // Counter digits (new-N, aN, SELECT N) make every statement unique + // on their own; normalize them so only the generated shape counts. + shapes.add(`${entry}\0${sql}\0${params.join('\0')}`.replace(/\d+/g, 'N')); + if (CONTROL && controlEffect(sql, params, outside, dir)) stats.sqliteWouldExecute++; + try { + if (entry === 'query') await worker.call('query', [sql, params]); + else if (entry === 'run') await worker.call('run', [sql, params]); + else await worker.call('exec', [sql]); + } catch (error) { + if (/ERR_NATIVE_SQL_ATTACH_BLOCKED|authorization denied/.test((error as Error).message)) stats.workerRefused++; + else stats.workerOther++; + } + const found = await traces(); + if (found.length > 0) { + stats.workerTraces++; + if (failures.length < 20) failures.push(`${entry}: ${JSON.stringify(sql)} params=${JSON.stringify(params)} -> ${found.join(', ')}`); + } + }; + + for (let i = 0; i < SINGLE; i++) { + const kind = pick(['attach', 'attach', 'vacuum', 'detach']); + const destination = kind === 'vacuum' + ? path.join(outside, `vac-${++counter}.sqlite`) + : pick([secret, empty, path.join(outside, `new-${++counter}.sqlite`)]); + const statement = kind === 'vacuum' + ? vacuumStatement(destination) + : kind === 'detach' + ? { sql: `${explainPrefix()}${caseVariant('detach')} ${trivia()}${pick(['x', 'main', 'temp', '"x"'])}`, params: [] } + : attachStatement(destination, `a${counter}`); + const parameterized = statement.params.length > 0; + // A bound statement must be the first one: prepare compiles only that. + const prefix = parameterized ? '' : pick(['', '', 'SELECT 1;', 'SELECT 1;\n']); + const entry = parameterized ? pick(['query', 'run']) : pick(['query', 'run', 'exec']); + await attempt(`${parameterized ? trivia() : lead()}${prefix}${trivia()}${statement.sql}`, statement.params, entry); + } + for (let i = 0; i < SCRIPTS; i++) { + const parts: string[] = []; + const count = 2 + Math.floor(rand() * 4); + for (let j = 0; j < count; j++) { + const kind = pick(['select', 'attach', 'vacuum', 'select']); + // Scripts run unbound, so a '?' filename becomes a literal. + // Replacer functions: a '$' in a path is not a pattern. + if (kind === 'select') parts.push(`${trivia()}SELECT ${j}`); + else if (kind === 'vacuum') { + const file = path.join(outside, `svac-${++counter}.sqlite`); + parts.push(vacuumStatement(file).sql.replace(/\?$/, () => sqlString(file))); + } else { + // The '?' can be followed by a comment, and nothing else in + // the statement contains one. + const target = pick([secret, empty]); + const sql = attachStatement(target, `s${++counter}`).sql.replace('?', () => sqlString(target)); + // An unbound '?' would attach a temporary database instead. + assert.ok(!sql.includes('?'), `script ATTACH left a placeholder unbound: ${JSON.stringify(sql)}`); + parts.push(sql); + } + } + await attempt(`${lead()}${parts.join(pick([';', ';\n', ';/* c */', ';\uFEFF']))}`, [], 'exec'); + } + + stats.distinct = shapes.size; + console.log(`[native fuzz] target=${target} ${JSON.stringify(stats)}`); + if (failures.length > 0) console.log(failures.join('\n')); + // The security result first, so a sanity floor never masks a trace. + assert.deepEqual(failures, [], `worker left traces (${JSON.stringify(stats)})`); + assert.ok(stats.distinct >= stats.generated * DISTINCT_SHARE_FLOOR, `generator coverage: at least ${DISTINCT_SHARE_FLOOR * 100}% of generated statements must be distinct (${JSON.stringify(stats)})`); + if (CONTROL && stats.generated >= CONTROL_MIN_SAMPLE) { + assert.ok(stats.sqliteWouldExecute >= stats.generated * CONTROL_SHARE_FLOOR, `control arm: SQLite must execute at least ${CONTROL_SHARE_FLOOR * 100}% of generated statements (${JSON.stringify(stats)})`); + } + } finally { + // Release the worker's file handles before removing the fixture: + // Windows refuses to delete files a live process holds open. + await worker.call('close').catch((error: Error) => console.warn(`[native fuzz] worker close failed: ${error.message}`)); + worker.stop(); + fs.rmSync(dir, { recursive: true, force: true, maxRetries: 10 }); + } +}); diff --git a/tests/unit/artifact_refresh_policy.test.ts b/tests/unit/artifact_refresh_policy.test.ts index 87d27a07..a1d03771 100644 --- a/tests/unit/artifact_refresh_policy.test.ts +++ b/tests/unit/artifact_refresh_policy.test.ts @@ -28,8 +28,8 @@ const sourceRepositoryRoot = path.resolve( ); const TXIKI_BRANCH = 'master'; -const TXIKI_COMMIT = '0353db5719c80ee69e0f400f4dfcd2256a034ee0'; -const TXIKI_RUN = '39983760340'; +const TXIKI_COMMIT = 'b45ac83ec0d7809c413afcf4091d7ecf12a46452'; +const TXIKI_RUN = '40086152581'; interface ScriptSpec { name: string; diff --git a/tests/unit/databaseModel.test.ts b/tests/unit/databaseModel.test.ts index bd2d23b6..8a9bd7f4 100644 --- a/tests/unit/databaseModel.test.ts +++ b/tests/unit/databaseModel.test.ts @@ -2750,6 +2750,48 @@ describe('DatabaseDocument save/saveAs fallback', () => { assert.strictEqual(writes, 1, 'the no-write lease must end before a later ordinary Save'); }); + it('rejects a failed Undo or Redo without links in the error VS Code shows', async t => { + // VS Code shows a rejected custom-document Undo or Redo in its own + // notification. SQLite's error quotes the name of the CHECK constraint + // a crafted file's rows already violate. + const VSCODE_LINK = /\[([^\]]+)\]\(((?:https?:\/\/|command:|file:)[^\)\s]+)(?: (["'])(.+?)(\3))?\)/gi; + const linked = '[Open details](command:workbench.action.showCommands)'; + const { operations } = await createDatabaseEngine({ content: null, maxSize: 0, readOnlyMode: false }); + const engine = operations as DatabaseOperations & { shutdown(): void }; + t.after(() => engine.shutdown()); + await engine.executeQuery( + `CREATE TABLE t(v TEXT CONSTRAINT "${linked}" CHECK (v NOT IN ('before', 'after')));` + + " PRAGMA ignore_check_constraints = ON; INSERT INTO t VALUES ('after'); PRAGMA ignore_check_constraints = OFF" + ); + t.mock.method(mockVscode.window, 'showErrorMessage', async () => undefined); + const doc = createDocBypassingFactory(engine, createFileUri('/test/linked-history-error.db')); + let edit: { undo(): Promise; redo(): Promise } | undefined; + doc.onDidChange((event: { undo(): Promise; redo(): Promise }) => { edit = event; }); + doc.recordModification({ + label: 'Update t.v', + description: 'Update t.v', + modificationType: 'cell_update', + targetTable: 't', + targetRowId: 1, + targetColumn: 'v', + priorValue: 'before', + newValue: 'after', + priorState: { storageClass: 'text', value: 'before' }, + postState: { storageClass: 'text', value: 'after' } + }); + const withoutLinks = (error: unknown) => { + assert.match((error as Error).message, /Open details/, 'control arm: the constraint name supplied the error'); + assert.deepStrictEqual([...(error as Error).message.matchAll(VSCODE_LINK)], []); + return true; + }; + + await assert.rejects(edit!.undo(), withoutLinks); + await engine.executeQuery('PRAGMA ignore_check_constraints = ON'); + await edit!.undo(); + await engine.executeQuery('PRAGMA ignore_check_constraints = OFF'); + await assert.rejects(edit!.redo(), withoutLinks); + }); + it('keeps obsolete host Undo and Redo clean without replaying discarded history', async t => { const replayed: string[] = []; const replacementOps = { diff --git a/tests/unit/nativeWorker.test.ts b/tests/unit/nativeWorker.test.ts index b519ca64..1f577f28 100644 --- a/tests/unit/nativeWorker.test.ts +++ b/tests/unit/nativeWorker.test.ts @@ -4170,7 +4170,7 @@ describe('native synchronous query deadlines', () => { }); describe('native async VACUUM routing', () => { - it('uses a bound VACUUM main INTO path only outside the main transaction', async () => { + it('snapshots through the runtime vacuumInto only outside the main transaction', async () => { const isExplicitlyOutsideTransaction = loadNativeWorkerFunction( 'isExplicitlyOutsideTransaction', ['database'] @@ -4178,81 +4178,45 @@ describe('native async VACUUM routing', () => { const runVacuumInto = loadNativeWorkerFunction( 'runVacuumInto', ['asyncDatabase', 'database', 'snapshotPath', 'signal'], - { isExplicitlyOutsideTransaction, releaseAsyncDatabase: () => {} } + { isExplicitlyOutsideTransaction } ); const calls: unknown[][] = []; - let failNextRun = false; + let failNext = false; const asyncDatabase = { - // The runtime refuses VACUUM INTO's internal ATTACH unless the - // destination is the connection's one permitted path. - permitAttach(path: string | null) { calls.push(['permitAttach', path]); }, - async run(...args: unknown[]) { - calls.push(['run', ...args]); - if (failNextRun) throw new Error('disk full'); + // The runtime refuses SQL-level VACUUM INTO; vacuumInto is its one + // way to write a copy, scoped to that statement. + async vacuumInto(...args: unknown[]) { + calls.push(args); + if (failNext) throw new Error('disk full'); } }; const signal = new AbortController().signal; - await runVacuumInto( - asyncDatabase, - { inTransaction: false }, - "/private/quote'snapshot.sqlite", - signal - ); - assert.deepStrictEqual(calls, [ - ['permitAttach', "/private/quote'snapshot.sqlite"], - ['run', 'VACUUM main INTO ?', ["/private/quote'snapshot.sqlite"], { signal }], - ['permitAttach', null] - ]); + await runVacuumInto(asyncDatabase, { inTransaction: false }, "/private/quote'snapshot.sqlite", signal); + assert.deepStrictEqual(calls, [["/private/quote'snapshot.sqlite", { signal }]]); - // A failed VACUUM still withdraws the permit. calls.length = 0; - failNextRun = true; + failNext = true; await assert.rejects( runVacuumInto(asyncDatabase, { inTransaction: false }, '/private/failed.sqlite', signal), /disk full/ ); - assert.deepStrictEqual(calls.map(call => call[0] === 'run' ? 'run' : call), [ - ['permitAttach', '/private/failed.sqlite'], - 'run', - ['permitAttach', null] - ]); calls.length = 0; await assert.rejects( runVacuumInto(asyncDatabase, { inTransaction: true }, '/private/blocked.sqlite', signal), /active transaction/i ); - assert.deepStrictEqual(calls, [], 'a refused snapshot never grants a permit'); - }); + assert.deepStrictEqual(calls, [], 'a refused snapshot never reaches the runtime'); - it('takes the snapshot connection out of service when the ATTACH permit cannot be withdrawn', async () => { - const isExplicitlyOutsideTransaction = loadNativeWorkerFunction( - 'isExplicitlyOutsideTransaction', - ['database'] - ); - const released: unknown[] = []; - const runVacuumInto = loadNativeWorkerFunction( - 'runVacuumInto', - ['asyncDatabase', 'database', 'snapshotPath', 'signal'], - { isExplicitlyOutsideTransaction, releaseAsyncDatabase: (connection: unknown) => { released.push(connection); } } - ); - const asyncDatabase = { - permitAttach(path: string | null) { - if (path === null) throw new Error('permit store failed'); - }, - async run() {} - }; + // A runtime without the scoped call cannot snapshot at all. await assert.rejects( - runVacuumInto(asyncDatabase, { inTransaction: false }, '/private/a.sqlite', new AbortController().signal), - /permit store failed/ + runVacuumInto({ async run() {} }, { inTransaction: false }, '/private/old.sqlite', signal), + /unavailable in this runtime/ ); - // No reachable handle may keep authorizing ATTACH of the snapshot path, - // and later reads must not be routed to a closed one. - assert.deepStrictEqual(released, [asyncDatabase]); }); - it('withdraws the ATTACH permit when run throws synchronously', async () => { + it('reports a synchronous throw from vacuumInto as a rejection', async () => { const isExplicitlyOutsideTransaction = loadNativeWorkerFunction( 'isExplicitlyOutsideTransaction', ['database'] @@ -4260,88 +4224,12 @@ describe('native async VACUUM routing', () => { const runVacuumInto = loadNativeWorkerFunction( 'runVacuumInto', ['asyncDatabase', 'database', 'snapshotPath', 'signal'], - { isExplicitlyOutsideTransaction, releaseAsyncDatabase: () => {} } - ); - const permits: Array = []; - const asyncDatabase = { - permitAttach(path: string | null) { permits.push(path); }, - run() { throw new TypeError('bad arguments'); } - }; - await assert.rejects( - () => runVacuumInto(asyncDatabase, { inTransaction: false }, '/private/a.sqlite', new AbortController().signal), - /bad arguments/ - ); - assert.deepStrictEqual(permits, ['/private/a.sqlite', null]); - }); - - it('releases the shared async connection so later work falls back to the primary', async () => { - const isExplicitlyOutsideTransaction = loadNativeWorkerFunction( - 'isExplicitlyOutsideTransaction', - ['database'] - ); - const shouldUseAsyncDatabase = loadNativeWorkerFunction( - 'shouldUseAsyncDatabase', - ['database', 'asyncDatabase'], { isExplicitlyOutsideTransaction } ); - const describeNativeError = loadNativeWorkerFunction( - 'describeNativeError', - ['error', 'fallback'], - { MAX_NATIVE_ERROR_MESSAGE_LENGTH: 8192 } - ); - // The real releaseAsyncDatabase and closeAsyncDatabase over one shared - // `asyncDb` binding and spool set, as in the worker. - const source = ['function releaseAsyncDatabase(connection)', 'function closeAsyncDatabase()'] - .map(signature => { - const escaped = signature.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - const match = nativeWorkerSource.match(new RegExp(`${escaped} \\{[\\s\\S]*?^\\}`, 'm'))?.[0]; - assert.ok(match, `native worker signature changed; expected ${signature}`); - return match; - }) - .join('\n'); - const errors: string[] = []; - const workerState = (initial: unknown) => Function( - 'initial', 'describeNativeError', 'console', - `"use strict"; - let asyncDb = initial; - const exportSpools = new Set(['spool_1']); - ${source} - return { releaseAsyncDatabase, state: () => ({ asyncDb, spools: exportSpools.size }) };` - )(initial, describeNativeError, { error: (...args: unknown[]) => errors.push(args.join(' ')) }); - - let closed = 0; - const shared = { async close() { closed++; } }; - const worker = workerState(shared); - worker.releaseAsyncDatabase(shared); - // Synchronously, before the close settles: no later request can pick the - // stuck handle, and its TEMP spools are forgotten with it. - assert.deepStrictEqual(worker.state(), { asyncDb: null, spools: 0 }); - assert.strictEqual(shouldUseAsyncDatabase({ inTransaction: false }, worker.state().asyncDb), false); - await new Promise(resolve => setImmediate(resolve)); - assert.strictEqual(closed, 1); - - // A connection other than the shared one is closed without touching it. - const other = workerState(shared); - const stray = { async close() { closed++; } }; - other.releaseAsyncDatabase(stray); - await new Promise(resolve => setImmediate(resolve)); - assert.strictEqual(closed, 2); - assert.deepStrictEqual(other.state(), { asyncDb: shared, spools: 1 }); - - // A synchronous close, returning nothing or throwing, is handled the same way. - other.releaseAsyncDatabase({ close() { closed++; } }); - other.releaseAsyncDatabase({ close() { throw new Error('sync close failed'); } }); - await new Promise(resolve => setImmediate(resolve)); - assert.strictEqual(closed, 3); - - // A failed close is reported, not swallowed or left unhandled. - const failing = { async close() { throw new Error('close failed'); } }; - workerState(failing).releaseAsyncDatabase(failing); - await new Promise(resolve => setImmediate(resolve)); - assert.deepStrictEqual(errors, [ - '[native-worker] closing the snapshot connection failed: sync close failed', - '[native-worker] closing the snapshot connection failed: close failed' - ]); + const asyncDatabase = { vacuumInto() { throw new TypeError('bad arguments'); } }; + const result = runVacuumInto(asyncDatabase, { inTransaction: false }, '/private/a.sqlite', new AbortController().signal); + assert.ok(result instanceof Promise); + await assert.rejects(result, /bad arguments/); }); it('keeps every failure when reporting a runtime ATTACH refusal', () => { @@ -4360,10 +4248,10 @@ describe('native async VACUUM routing', () => { const refusal = () => Object.assign(new Error('authorization denied'), { errno: 23 }); const withdrawal = describeWorkerError( - new AggregateError([refusal(), new Error('permit store failed')], 'combined') + new AggregateError([refusal(), new Error('disk I/O error')], 'combined') ); assert.match(withdrawal, /ERR_NATIVE_SQL_ATTACH_BLOCKED/); - assert.match(withdrawal, /permit store failed/, 'a second failure must not be dropped'); + assert.match(withdrawal, /disk I\/O error/, 'a second failure must not be dropped'); // runWithQueryDeadline wraps executeStatement's failure in another AggregateError. const nested = describeWorkerError(new AggregateError([ @@ -4438,41 +4326,6 @@ describe('native async VACUUM routing', () => { ); }); - it('surfaces a failed ATTACH permit withdrawal unless the connection is closing', async () => { - const isExplicitlyOutsideTransaction = loadNativeWorkerFunction( - 'isExplicitlyOutsideTransaction', - ['database'] - ); - const runVacuumInto = loadNativeWorkerFunction( - 'runVacuumInto', - ['asyncDatabase', 'database', 'snapshotPath', 'signal'], - { isExplicitlyOutsideTransaction, releaseAsyncDatabase: () => {} } - ); - const signal = new AbortController().signal; - const connection = (withdrawError: Error | undefined, runError?: Error) => ({ - permitAttach(path: string | null) { - if (path === null && withdrawError) throw withdrawError; - }, - async run() { - if (runError) throw runError; - }, - async close() {} - }); - - // A permit left open with nothing reported is the silent failure. - await assert.rejects( - runVacuumInto(connection(new Error('permit store failed')), { inTransaction: false }, '/private/a.sqlite', signal), - /permit store failed/ - ); - // Both failures are reported when the VACUUM itself also failed. - await assert.rejects( - runVacuumInto(connection(new Error('permit store failed'), new Error('disk full')), { inTransaction: false }, '/private/b.sqlite', signal), - (error: Error) => /disk full/.test(error.message) && /permit store failed/.test(error.message) - ); - // A closing connection takes its permit with it. - await runVacuumInto(connection(new Error('Invalid DB')), { inTransaction: false }, '/private/c.sqlite', signal); - }); - it('reports a deadline that lands before an async completion is observed', async () => { const activeOperations = new Map await f.reopen(false); // Control arm: the host's own snapshot RPC still writes its destination, - // and the permit it needed is gone once it settles, even for that path. + // and that destination is not accepted once it settles, even for that path. const snapshot = path.join(f.directory, 'snapshot.sqlite'); await worker.call('vacuumInto', [snapshot, 5000]); assert.equal(fs.existsSync(snapshot), true, 'vacuumInto writes the host-chosen snapshot'); @@ -394,7 +394,7 @@ it('refuses SQL-level VACUUM INTO a path the worker did not choose', async t => const reuse = await refusalProblem(f, 'query: VACUUM INTO the snapshot path after vacuumInto settled', () => f.query(`VACUUM INTO ${sqlLiteral(snapshot)}`)); if (reuse !== undefined) problems.push(reuse); - if (fs.existsSync(snapshot)) problems.push('the vacuumInto permit outlived the RPC'); + if (fs.existsSync(snapshot)) problems.push('the vacuumInto destination stayed writable after the RPC'); // The refusal reads as one policy error, not a step failure followed by // the same code again from finalize. @@ -426,26 +426,39 @@ it('enforces the ATTACH refusal in the runtime itself, beneath the worker guard' } catch (error) { outcome.unpermitted = { errno: error.errno, message: error.message }; } - db.permitAttach(secret); + // Control arms: the file is readable, ATTACH syntax works for the + // private temporary database, and the runtime's one exception writes + // a copy without leaving its destination attachable. + const direct = new Database(secret, { readOnly: true }); + outcome.readable = direct.prepare('SELECT v FROM secret').all(); + direct.close(); + db.exec("ATTACH '' AS scratch"); + outcome.scratch = true; + const copy = secret + '.copy'; + db.vacuumInto(copy); try { - db.exec('ATTACH ' + quote(secret) + ' AS permitted'); - outcome.permitted = db.prepare('SELECT v FROM permitted.secret').all(); + db.exec('ATTACH ' + quote(copy) + ' AS copied'); + outcome.copyAttach = 'attached'; } catch (error) { - outcome.permitted = { errno: error.errno, message: error.message }; + outcome.copyAttach = { errno: error.errno }; } db.close(); console.log(JSON.stringify(outcome)); `); const outcome = JSON.parse(execFileSync(f.runtime.binary, ['run', script], { encoding: 'utf8' }).trim()) as { unpermitted: unknown; - permitted: unknown; + readable: unknown; + scratch: unknown; + copyAttach: unknown; }; assert.deepEqual(outcome.unpermitted, { errno: 23, message: 'authorization denied' }, 'the runtime refuses ATTACH with SQLITE_AUTH even without the worker guard'); - // Control arm: the same statement attaches once permitted, so the refusal - // above is the authorizer and not the path or the syntax. - assert.deepEqual(outcome.permitted, [{ v: SECRET }]); + // SQLITE_AUTH comes only from an authorizer, and the control arms rule out + // the path and the syntax. + assert.deepEqual(outcome.readable, [{ v: SECRET }]); + assert.equal(outcome.scratch, true); + assert.deepEqual(outcome.copyAttach, { errno: 23 }, 'a vacuumInto destination does not stay attachable'); }); it('explains a DETACH refusal without the ATTACH justification', async t => { diff --git a/tests/unit/native_real_smoke.test.ts b/tests/unit/native_real_smoke.test.ts index 18537d6c..8ab06130 100644 --- a/tests/unit/native_real_smoke.test.ts +++ b/tests/unit/native_real_smoke.test.ts @@ -2147,6 +2147,60 @@ it('passes the native view smoke lane through the bundled txiki worker', async ( ); }); + await testContext.test('keeps native NUL TEXT whole, shows it as bytes, and keeps NUL keys read-only', async () => { + await engine.executeQuery( + 'CREATE TABLE native_nul_text (id INTEGER PRIMARY KEY, value TEXT); ' + + "INSERT INTO native_nul_text VALUES (1, CAST(X'610062' AS TEXT)), (2, 'plain')" + ); + // Bound writes keep NUL and lone surrogates byte for byte; the + // WASM engine stores the same bytes (raw_text_transport.test.ts). + await engine.executeQuery( + 'INSERT INTO native_nul_text VALUES (?, ?), (?, ?)', + [3, 'c\0d', 4, 'x\uD800'] + ); + assert.deepStrictEqual( + (await engine.executeQuery( + 'SELECT hex(CAST(value AS BLOB)) FROM native_nul_text ORDER BY id' + ))[0].rows, + [['610062'], ['706C61696E'], ['630064'], ['78EDA080']] + ); + // The sync read now returns NUL TEXT whole, so only the + // containment rule keeps it out of the grid as a string. + const page = await engine.fetchTableData('native_nul_text', { + columns: ['rowid', 'id', 'value'], + limit: 10, + offset: 0 + }); + assert.deepStrictEqual(page.rows[0][2], new Uint8Array([0x61, 0x00, 0x62])); + assert.strictEqual(page.rows[1][2], 'plain'); + assert.deepStrictEqual(page.rows[2][2], new Uint8Array([0x63, 0x00, 0x64])); + + await engine.executeQuery( + 'CREATE TABLE native_nul_text_identity (key TEXT PRIMARY KEY, value TEXT) WITHOUT ROWID; ' + + "INSERT INTO native_nul_text_identity VALUES (CAST(X'610062' AS TEXT), 'nul'), ('plain', 'plain')" + ); + const keyed = await engine.fetchTableData('native_nul_text_identity', { + columns: ['rowid', 'key', 'value'], + limit: 10, + offset: 0 + }); + const nulIndex = keyed.rows.findIndex(row => row[2] === 'nul'); + assert.notStrictEqual(nulIndex, -1); + assert.match(String(keyed.rows[nulIndex][0]), /^readonly-pk:/); + assert.match(keyed.readOnlyRowReasons?.[nulIndex] ?? '', /NUL character/); + assert.doesNotMatch(keyed.readOnlyRowReasons?.[nulIndex] ?? '', /inline limit/); + await assert.rejects( + engine.insertRow('native_nul_text_identity', { key: 'b\0c', value: 'must-rollback' }), + /NUL character/ + ); + assert.deepStrictEqual( + (await engine.executeQuery( + 'SELECT hex(CAST(key AS BLOB)) FROM native_nul_text_identity ORDER BY 1' + ))[0].rows, + [['610062'], ['706C61696E']] + ); + }); + await testContext.test('retains raw prefixes for malformed native table and view TEXT', async () => { await engine.executeQuery( 'CREATE TABLE native_malformed_text_value (value TEXT); ' + diff --git a/tests/unit/notification_links.test.ts b/tests/unit/notification_links.test.ts new file mode 100644 index 00000000..80b70924 --- /dev/null +++ b/tests/unit/notification_links.test.ts @@ -0,0 +1,575 @@ +import './vscode_mock_setup'; +import assert from 'node:assert/strict'; +import { promises as fsPromises, readdirSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import { describe, it } from 'node:test'; +import ts from 'typescript'; +import * as vscode from 'vscode'; +import { mockVscode } from './mocks/vscode'; +import { DocumentRegistry } from '../../src/documentRegistry'; +import type { DatabaseDocument } from '../../src/databaseModel'; +import { createDatabaseEngine, WasmDatabaseEngine } from '../../src/core/sqlite-db'; +import { exportTableCommand } from '../../src/tableExporter'; +import { plainErrors, plainNotificationError, plainNotificationText, withPlainErrors } from '../../src/notificationText'; + +// The pattern VS Code parses extension notifications, modal messages and +// progress titles with (microsoft/vscode src/vs/base/common/linkedText.ts). +// A match is a clickable link; a command: link runs with the link's arguments. +const VSCODE_LINK = /\[([^\]]+)\]\(((?:https?:\/\/|command:|file:)[^\)\s]+)(?: (["'])(.+?)(\3))?\)/gi; +// VS Code removes $(icon) syntax from a progress title before parsing its links +// (stripIcons, src/vs/base/common/iconLabels.ts), so the text is checked both +// as given and with icons removed. +const ICON = /(\s)?(\\)?\$\([A-Za-z0-9-]+(?:~[A-Za-z]+)?\)(\s)?/g; +const stripIcons = (text: string): string => + text.replace(ICON, (match, before?: string, escaped?: string, after?: string) => escaped ? match : before || after || ''); +const linksIn = (text: string): string[] => + [...new Set([text, stripIcons(text)].flatMap(form => [...form.matchAll(VSCODE_LINK)].map(match => match[2])))]; + +// A crafted database: a view named as a command link, selecting a missing +// column that is also named as one, so reading the view fails with an error +// quoting the name. +const COMMAND = 'command:workbench.action.showCommands'; +const VIEW = `[Show export](${COMMAND})`; +const COLUMN = `[Open details](${COMMAND})`; +// No "](" until VS Code removes the icon. +const ICON_TABLE = `[Show export]$(x)(${COMMAND})`; + +async function openCraftedDatabase(): Promise { + const opened = await createDatabaseEngine({ content: null, maxSize: 0, readOnlyMode: false }); + const engine = opened.operations as WasmDatabaseEngine; + await engine.executeQuery('CREATE TABLE t(a)'); + await engine.executeQuery(`CREATE VIEW "${VIEW}" AS SELECT t.\`${COLUMN}\` FROM t`); + return engine; +} + +function replaceProperty(restorations: Array<() => void>, object: object, key: string, value: unknown): void { + const original = Object.getOwnPropertyDescriptor(object, key); + restorations.push(() => { + if (original) Object.defineProperty(object, key, original); + else Reflect.deleteProperty(object, key); + }); + Object.defineProperty(object, key, { configurable: true, writable: true, value }); +} + +describe('notification text from a crafted database', () => { + it('plainNotificationText leaves VS Code no link and keeps the text', () => { + const message = `Export failed: no such column: t.${COLUMN}`; + + assert.deepEqual(linksIn(message), [COMMAND], 'control arm: VS Code finds the link in the raw text'); + assert.deepEqual(linksIn(plainNotificationText(message)), []); + assert.equal(plainNotificationText(message).replaceAll('\u200B', ''), message); + assert.equal(plainNotificationText('Export failed: disk full'), 'Export failed: disk full'); + // Errors are disarmed in place and can be rethrown through a wrapper again. + assert.equal(plainNotificationText(plainNotificationText(message)), plainNotificationText(message)); + + const iconForm = `Exporting "${ICON_TABLE}"`; + assert.deepEqual(linksIn(iconForm), [COMMAND], 'control arm: VS Code finds the link once icons are removed'); + assert.deepEqual(linksIn(plainNotificationText(iconForm)), []); + }); + + it('shows the export progress title of a table named with icon syntax without a link', async () => { + const restorations: Array<() => void> = []; + const opened = await createDatabaseEngine({ content: null, maxSize: 0, readOnlyMode: false }); + const engine = opened.operations as WasmDatabaseEngine; + const scratch = await fsPromises.mkdtemp(path.join(process.cwd(), '.notification-links-')); + const docUri = mockVscode.Uri.parse('vscode-sqlite://notification-icon-title.db'); + const titles: string[] = []; + + try { + await engine.executeQuery(`CREATE TABLE "${ICON_TABLE}"(a); INSERT INTO "${ICON_TABLE}" VALUES (1)`); + replaceProperty(restorations, mockVscode.window, 'showSaveDialog', async () => mockVscode.Uri.file(path.join(scratch, 'export.csv'))); + const withProgress = mockVscode.window.withProgress; + replaceProperty(restorations, mockVscode.window, 'withProgress', (options: { title?: string }, task: Function) => { + titles.push(options.title ?? ''); + return withProgress(options, task); + }); + DocumentRegistry.set('notification-icon-title', { uri: docUri, databaseOperations: engine } as unknown as DatabaseDocument); + + const result = await exportTableCommand( + {} as vscode.ExtensionContext, + undefined, + { table: ICON_TABLE, uri: docUri.toString() }, + ['a'], + undefined, + undefined, + { format: 'csv' } + ); + + assert.equal(result.success, true); + assert.ok(titles.some(title => title.includes('[Show export]')), 'control arm: the progress title names the table'); + assert.deepEqual(titles.flatMap(linksIn), []); + } finally { + DocumentRegistry.delete('notification-icon-title'); + restorations.reverse().forEach(restore => restore()); + engine.shutdown(); + await fsPromises.rm(scratch, { recursive: true, force: true }); + } + }); + + it('shows a failed export of a crafted view without a link', async () => { + const restorations: Array<() => void> = []; + const engine = await openCraftedDatabase(); + const scratch = await fsPromises.mkdtemp(path.join(process.cwd(), '.notification-links-')); + const docUri = mockVscode.Uri.parse('vscode-sqlite://notification-links.db'); + const errors: string[] = []; + const titles: string[] = []; + + try { + replaceProperty(restorations, mockVscode.window, 'showErrorMessage', async (message: string) => { errors.push(message); }); + replaceProperty(restorations, mockVscode.window, 'showSaveDialog', async () => mockVscode.Uri.file(path.join(scratch, 'export.csv'))); + const withProgress = mockVscode.window.withProgress; + replaceProperty(restorations, mockVscode.window, 'withProgress', (options: { title?: string }, task: Function) => { + titles.push(options.title ?? ''); + return withProgress(options, task); + }); + replaceProperty(restorations, console, 'error', () => {}); + DocumentRegistry.set('notification-links', { uri: docUri, databaseOperations: engine } as unknown as DatabaseDocument); + + const result = await exportTableCommand( + {} as vscode.ExtensionContext, + undefined, + { table: VIEW, uri: docUri.toString() }, + [COLUMN], + undefined, + undefined, + { format: 'csv' } + ); + + assert.equal(result.success, false); + assert.equal(errors.length, 1); + assert.match(errors[0], /no such column/, 'control arm: the error quotes the crafted column'); + assert.deepEqual(linksIn(errors[0]), []); + assert.ok(titles.length > 0, 'control arm: the export showed a progress title'); + assert.deepEqual(titles.flatMap(linksIn), []); + } finally { + DocumentRegistry.delete('notification-links'); + restorations.reverse().forEach(restore => restore()); + engine.shutdown(); + await fsPromises.rm(scratch, { recursive: true, force: true }); + } + }); + + it('shows a failed query console read of a crafted view without a link', async () => { + const restorations: Array<() => void> = []; + const engine = await openCraftedDatabase(); + const database = { + uri: vscode.Uri.file('/workspace/crafted.db'), + databaseOperations: engine, + onDidDispose: () => ({ dispose() {} }) + } as unknown as DatabaseDocument; + const commands = new Map Promise>(); + const errors: string[] = []; + const document = { languageId: 'sql', isClosed: false, getText: () => `SELECT * FROM "${VIEW}"` }; + let registration: vscode.Disposable | undefined; + + try { + DocumentRegistry.set('notification-links-console', database); + replaceProperty(restorations, mockVscode, 'Disposable', class { constructor(private callback: () => void) {} dispose() { this.callback(); } }); + replaceProperty(restorations, mockVscode, 'CompletionItem', class { constructor(public label: string, public kind: number) {} }); + replaceProperty(restorations, mockVscode, 'CompletionItemKind', { Module: 8, Class: 6, Field: 4 }); + replaceProperty(restorations, mockVscode.commands, 'registerCommand', (id: string, action: (...args: unknown[]) => Promise) => { + commands.set(id, action); + return { dispose() {} }; + }); + replaceProperty(restorations, mockVscode.window, 'showQuickPick', async (items: unknown[]) => items[0]); + replaceProperty(restorations, mockVscode.window, 'showErrorMessage', async (message: string) => { errors.push(message); }); + replaceProperty(restorations, mockVscode.window, 'activeTextEditor', { document, selection: { isEmpty: true } }); + replaceProperty(restorations, mockVscode.window, 'showTextDocument', async () => ({ viewColumn: 2 })); + replaceProperty(restorations, mockVscode.workspace, 'openTextDocument', async () => document); + replaceProperty(restorations, mockVscode.workspace, 'registerTextDocumentContentProvider', () => ({ dispose() {} })); + replaceProperty(restorations, mockVscode, 'languages', { registerCompletionItemProvider: () => ({ dispose() {} }) }); + const { registerSqlWorkspace } = await import('../../src/sqlWorkspace'); + registration = registerSqlWorkspace({} as vscode.ExtensionContext); + + await commands.get('sqlite-explorer.newQuery')!(database.uri); + await commands.get('sqlite-explorer.runQuery')!(); + + assert.ok(errors.length > 0, 'control arm: the failed read was reported'); + for (const error of errors) { + assert.match(error, /no such column/, 'control arm: the error quotes the crafted column'); + assert.deepEqual(linksIn(error), []); + } + } finally { + registration?.dispose(); + DocumentRegistry.delete('notification-links-console'); + restorations.reverse().forEach(restore => restore()); + engine.shutdown(); + } + }); +}); + +// Errors thrown back to VS Code are shown by VS Code itself ("Failed to save +// '…': "). VS Code 1.110 to 1.140 parse links in those messages too. +describe('errors handed back to VS Code', () => { + const CRAFTED_ERROR = `no such collation sequence: ${COLUMN}`; + + it('disarms a failed save through the registered editor provider', async () => { + const restorations: Array<() => void> = []; + let registered: vscode.CustomEditorProvider | undefined; + try { + replaceProperty(restorations, mockVscode.window, 'registerCustomEditorProvider', (_viewType: string, provider: vscode.CustomEditorProvider) => { + registered = provider; + return { dispose() {} }; + }); + const context = { extensionUri: mockVscode.Uri.file('/ext'), globalState: { get: () => undefined } } as unknown as vscode.ExtensionContext; + // Imported here: a static import would load sqlWorkspace before the + // query console test installs the vscode.languages mock it reads. + const { registerEditorProvider } = await import('../../src/editorController'); + registerEditorProvider('sqlite-explorer.view', context, undefined, null, { verified: true, readOnly: false }); + assert.ok(registered, 'control arm: the provider was registered'); + + const failure = new Error(CRAFTED_ERROR); + const document = { save: async () => { throw failure; } } as unknown as vscode.CustomDocument; + await assert.rejects( + async () => registered!.saveCustomDocument(document, {} as vscode.CancellationToken), + (error: unknown) => { + assert.equal(error, failure, 'the same error object reaches VS Code'); + assert.match((error as Error).message, /no such collation sequence/); + assert.deepEqual(linksIn((error as Error).message), []); + return true; + } + ); + } finally { + restorations.reverse().forEach(restore => restore()); + } + }); + + it('keeps a DOMException, whose message has only a getter, as the error VS Code receives', async () => { + // An aborted save rethrows its AbortSignal's DOMException. + const aborted = new DOMException('This operation was aborted', 'AbortError'); + await assert.rejects(plainErrors(async () => { throw aborted; })(), (error: unknown) => { + assert.equal(error, aborted); + return true; + }); + const crafted = new DOMException(CRAFTED_ERROR, 'DataCloneError'); + await assert.rejects(plainErrors(async () => { throw crafted; })(), (error: unknown) => { + assert.equal(error, crafted); + assert.equal((error as DOMException).name, 'DataCloneError'); + assert.match((error as Error).message, /no such collation sequence/); + assert.deepEqual(linksIn((error as Error).message), []); + return true; + }); + }); + + it('plainNotificationError keeps sealed errors and non-text messages, and replaces only frozen ones', () => { + class CodedError extends Error { readonly code = 'Unavailable'; } + const sealed = Object.seal(new CodedError(CRAFTED_ERROR)); + assert.equal(plainNotificationError(sealed), sealed); + assert.deepEqual(linksIn(sealed.message), []); + + const numeric = new Error('placeholder'); + Object.defineProperty(numeric, 'message', { value: 42, writable: true, configurable: true }); + assert.equal(plainNotificationError(numeric), numeric); + + const frozen = Object.freeze(new Error(CRAFTED_ERROR)); + const replaced = plainNotificationError(frozen) as Error; + assert.notEqual(replaced, frozen); + assert.equal(replaced.cause, frozen); + assert.match(replaced.message, /no such collation sequence/); + assert.deepEqual(linksIn(replaced.message), []); + }); + + it('withPlainErrors keeps private fields, events, error classes and absent methods', async () => { + class FileSystemFailure extends Error { readonly code = 'Unavailable'; } + class Provider { + readonly #message = CRAFTED_ERROR; + readonly onDidChange = (listener: () => void) => { listener(); return { dispose() {} }; }; + async readFile(): Promise { throw new FileSystemFailure(this.#message); } + watch(): string { return this.#message; } + } + const provider = withPlainErrors(new Provider(), ['readFile', 'writeFile']); + let fired = false; + + provider.onDidChange(() => { fired = true; }); + assert.equal(fired, true); + assert.equal(provider.watch(), CRAFTED_ERROR, 'an unlisted method still reaches private fields'); + assert.equal('writeFile' in provider, false, 'a listed method the provider lacks stays absent'); + await assert.rejects(provider.readFile(), (error: unknown) => { + assert.ok(error instanceof FileSystemFailure); + assert.equal(error.code, 'Unavailable'); + assert.deepEqual(linksIn(error.message), []); + return true; + }); + }); +}); + +// Every notification, modal message and detail, progress title and message, +// input box and quick pick prompt, input validation message and undo label +// must be literal text or pass through plainNotificationText, so a new call +// site that shows database text cannot reintroduce links. +describe('notification call sites', () => { + const NOTIFY = new Set(['showErrorMessage', 'showWarningMessage', 'showInformationMessage']); + const WINDOW_METHODS = new Set([...NOTIFY, 'withProgress', 'showInputBox', 'showQuickPick', 'createInputBox', 'createQuickPick']); + // Commands and providers whose errors VS Code shows itself. + const REGISTRATIONS = new Map([ + ['registerCommand', 'plainErrors'], + ['registerTextEditorCommand', 'plainErrors'], + ['registerCustomEditorProvider', 'withPlainErrors'], + ['registerFileSystemProvider', 'withPlainErrors'] + ]); + const sourceRoot = path.resolve(__dirname, '..', '..', 'src'); + + function sourceFiles(directory: string): string[] { + return readdirSync(directory, { withFileTypes: true }).flatMap(entry => { + const full = path.join(directory, entry.name); + if (entry.isDirectory()) return sourceFiles(full); + return entry.name.endsWith('.ts') ? [full] : []; + }); + } + + // Literal text, a call to plainNotificationText, or a conditional of those. + function isPlainText(node: ts.Expression): boolean { + if (ts.isParenthesizedExpression(node)) return isPlainText(node.expression); + if (ts.isConditionalExpression(node)) return isPlainText(node.whenTrue) && isPlainText(node.whenFalse); + if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'plainNotificationText') { + return true; + } + return isLiteralText(node); + } + + // A string literal, a template without substitutions, undefined, l10n.t of + // a literal without placeholders, or a conditional or concatenation of + // those. A disarmed part may not be concatenated: a literal ending in "]" + // followed by database text starting with "(" would form a link. + function isLiteralText(node: ts.Expression): boolean { + if (ts.isParenthesizedExpression(node)) return isLiteralText(node.expression); + if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return true; + if (ts.isIdentifier(node) && node.text === 'undefined') return true; + if (ts.isConditionalExpression(node)) return isLiteralText(node.whenTrue) && isLiteralText(node.whenFalse); + if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) { + return isLiteralText(node.left) && isLiteralText(node.right); + } + return ts.isCallExpression(node) + && ts.isPropertyAccessExpression(node.expression) + && node.expression.name.text === 't' + && node.expression.expression.getText().endsWith('l10n') + && node.arguments.length === 1 + && isLiteralText(node.arguments[0]); + } + + // A property's name when it is written literally; undefined for a computed + // name that could be anything. + function propertyName(name: ts.PropertyName): string | undefined { + if (ts.isComputedPropertyName(name)) return ts.isStringLiteralLike(name.expression) ? name.expression.text : undefined; + return (name as ts.Identifier).text; + } + + // Every value the named property can take. A spread, a shorthand or an + // accessor yields an expression the check refuses; a computed name counts + // as every name. + function textProperty(options: ts.ObjectLiteralExpression, name: string): ts.Expression[] { + const values: ts.Expression[] = []; + for (const property of options.properties) { + if (ts.isSpreadAssignment(property)) { + values.push(property.expression); + continue; + } + const key = propertyName(property.name); + if (key !== undefined && key !== name) continue; + values.push(ts.isPropertyAssignment(property) ? property.initializer : ts.factory.createIdentifier(name)); + } + return values; + } + + // The values a validateInput function can return, without the returns of + // functions nested in it. + function returnedValues(fn: ts.ArrowFunction | ts.FunctionExpression): ts.Expression[] { + if (!ts.isBlock(fn.body)) return [fn.body]; + const values: ts.Expression[] = []; + const visit = (node: ts.Node) => { + if (ts.isReturnStatement(node) && node.expression) values.push(node.expression); + if (!ts.isFunctionLike(node)) ts.forEachChild(node, visit); + }; + ts.forEachChild(fn.body, visit); + return values; + } + + function scan(file: string, text: string) { + const source = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true); + const offenders: string[] = []; + const counts = { notificationCalls: 0, registrations: 0, historyEdits: 0, progressReports: 0, inputBoxes: 0 }; + const offend = (at: ts.Node, what: string) => { + const { line } = source.getLineAndCharacterOfPosition(at.getStart()); + offenders.push(`${file}:${line + 1} ${what}`); + }; + const check = (node: ts.Expression | undefined, what: string, at: ts.Node) => { + if (node && !isPlainText(node)) offend(at, what); + }; + // Options written in place, so their text can be checked. + const checkOptions = (options: ts.Expression | undefined, name: string, what: string, at: ts.Node) => { + if (!options) return; + if (!ts.isObjectLiteralExpression(options)) offend(at, `${what} in options not written in place`); + else for (const value of textProperty(options, name)) check(value, what, at); + }; + const checkValidation = (options: ts.Expression | undefined, at: ts.Node) => { + if (!options || !ts.isObjectLiteralExpression(options)) return; + for (const value of textProperty(options, 'validateInput')) { + if (!ts.isArrowFunction(value) && !ts.isFunctionExpression(value)) offend(at, 'validateInput not written in place'); + else for (const returned of returnedValues(value)) check(returned, 'validateInput message', returned); + } + }; + const directlyCalled = (node: ts.Node) => ts.isCallExpression(node.parent) && node.parent.expression === node; + + // Names this file binds to the vscode module and to its window. + const namespaces = new Set(); + const windows = new Set(); + for (const statement of source.statements) { + if (ts.isImportEqualsDeclaration(statement) && statement.moduleReference.getText() === "require('vscode')") { + namespaces.add(statement.name.text); + } + if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) + || statement.moduleSpecifier.text !== 'vscode' || !statement.importClause) continue; + const { name, namedBindings } = statement.importClause; + if (name) namespaces.add(name.text); + if (namedBindings && ts.isNamespaceImport(namedBindings)) namespaces.add(namedBindings.name.text); + if (namedBindings && ts.isNamedImports(namedBindings)) { + for (const element of namedBindings.elements) { + if ((element.propertyName ?? element.name).text === 'window') windows.add(element.name.text); + } + } + } + const isWindow = (node: ts.Node): boolean => { + if (ts.isPropertyAccessExpression(node)) { + return node.name.text === 'window' && ts.isIdentifier(node.expression) && namespaces.has(node.expression.text); + } + return ts.isIdentifier(node) && windows.has(node.text) && !ts.isImportSpecifier(node.parent) + && !((ts.isPropertyAccessExpression(node.parent) || ts.isPropertyAssignment(node.parent)) && node.parent.name === node); + }; + + const visit = (node: ts.Node) => { + // window and the functions checked here only through direct use, + // so an alias cannot skip the checks. + if (isWindow(node) && !(ts.isPropertyAccessExpression(node.parent) && node.parent.expression === node)) { + offend(node, 'window used other than through one of its properties'); + } + if (ts.isPropertyAccessExpression(node)) { + const method = node.name.text; + if (isWindow(node.expression) && WINDOW_METHODS.has(method) && !directlyCalled(node)) { + offend(node, `${method} used other than in a direct call`); + } + if ((method === 'report' || REGISTRATIONS.has(method)) && !directlyCalled(node)) { + offend(node, `${method} used other than in a direct call`); + } + } + if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) { + const method = node.expression.name.text; + const [first, second] = node.arguments; + if (isWindow(node.expression.expression)) { + if (NOTIFY.has(method)) { + counts.notificationCalls++; + check(first, `${method} message`, node); + // The second argument is the options or the first item. + if (second && !ts.isObjectLiteralExpression(second)) check(second, `${method} options or item`, node); + else checkOptions(second, 'detail', `${method} detail`, node); + } else if (method === 'withProgress') { + checkOptions(first, 'title', 'withProgress title', node); + } else if (method === 'showInputBox') { + counts.inputBoxes++; + checkOptions(first, 'prompt', 'showInputBox prompt', node); + checkValidation(first, node); + } else if (method === 'showQuickPick') { + checkOptions(second, 'prompt', 'showQuickPick prompt', node); + } else if (method === 'createInputBox' || method === 'createQuickPick') { + offend(node, `${method}: its prompt and validationMessage cannot be checked here`); + } + } + if (method === 'report') { + counts.progressReports++; + checkOptions(first, 'message', 'progress message', node); + } + const wrapper = REGISTRATIONS.get(method); + if (wrapper) { + counts.registrations++; + if (!second || !ts.isCallExpression(second) || second.expression.getText() !== wrapper) { + offend(node, `${method} without ${wrapper}`); + } + } + } + // A custom-document edit: VS Code shows a rejected undo or redo, + // and the label in its "Could not undo" warning. + if (ts.isObjectLiteralExpression(node)) { + const names = node.properties.map(property => ts.isSpreadAssignment(property) ? undefined : propertyName(property.name)); + if (names.includes('undo') && names.includes('redo')) { + counts.historyEdits++; + for (const name of ['undo', 'redo']) { + for (const value of textProperty(node, name)) { + if (!ts.isCallExpression(value) || value.expression.getText() !== 'plainErrors') offend(node, `${name} without plainErrors`); + } + } + for (const value of textProperty(node, 'label')) check(value, 'undo label', node); + } + } + ts.forEachChild(node, visit); + }; + visit(source); + return { offenders, counts }; + } + + it('pass non-literal text through plainNotificationText and register through the error wrappers', () => { + const offenders: string[] = []; + const totals = { notificationCalls: 0, registrations: 0, historyEdits: 0, progressReports: 0, inputBoxes: 0 }; + for (const file of sourceFiles(sourceRoot)) { + const result = scan(path.relative(sourceRoot, file), readFileSync(file, 'utf8')); + offenders.push(...result.offenders); + for (const key of Object.keys(totals) as Array) totals[key] += result.counts[key]; + } + + assert.ok(totals.notificationCalls > 20, `control arm: the scan found ${totals.notificationCalls} notification calls`); + assert.ok(totals.registrations >= 6, `control arm: the scan found ${totals.registrations} command and provider registrations`); + assert.ok(totals.historyEdits >= 1, `control arm: the scan found ${totals.historyEdits} undo/redo edits`); + assert.ok(totals.progressReports >= 1, `control arm: the scan found ${totals.progressReports} progress reports`); + assert.ok(totals.inputBoxes >= 1, `control arm: the scan found ${totals.inputBoxes} input boxes`); + assert.deepEqual(offenders, []); + }); + + it('reports each code shape that could show database text unchecked', () => { + // Each line marked "flagged" must be reported, and no other line. + const shapes = [ + "import * as vs from 'vscode';", + "import { window } from 'vscode';", + "import { window as win } from 'vscode';", + 'declare const dbText: string;', + 'declare const opts: { title: string };', + 'declare const f: () => void;', + 'declare const progress: { report(value: { message?: string }): void };', + "vs.window.showErrorMessage(dbText); // flagged", + "vs.window.showWarningMessage('Failed', { modal: true, 'detail': dbText }); // flagged", + "vs.window.showWarningMessage('Failed', { ['detail']: dbText }); // flagged", + "vs.window.showWarningMessage('Failed', { detail: 'x', detail: dbText }); // flagged", + "vs.window.withProgress({ title: 'Exporting', ...opts }, async () => {}); // flagged", + "progress.report({ 'message': dbText }); // flagged", + "vs.window.showInputBox({ 'prompt': dbText }); // flagged", + 'vs.window.showInputBox({ validateInput: value => value }); // flagged', + "vs.window.showQuickPick(['a'], { prompt: dbText }); // flagged", + 'const box = vs.window.createInputBox(); // flagged', + 'const w = vs.window; // flagged', + 'window.showErrorMessage(dbText); // flagged', + 'const w2 = window; // flagged', + 'win.showInformationMessage(dbText); // flagged', + 'const show = vs.window.showErrorMessage; // flagged', + 'const report = progress.report; // flagged', + 'const register = vs.commands.registerCommand; // flagged', + "vs.commands.registerCommand('x', f); // flagged", + 'const edit = { label: dbText, undo: plainErrors(f), redo: plainErrors(f) }; // flagged', + 'const edit2 = { label: "x", undo: f, redo: plainErrors(f) }; // flagged' + ]; + const flagged = shapes.flatMap((line, index) => line.endsWith('// flagged') ? [index + 1] : []); + const reported = new Set(scan('shapes.ts', shapes.join('\n')).offenders.map(entry => Number(/^shapes\.ts:(\d+) /.exec(entry)![1]))); + assert.deepEqual([...reported].sort((a, b) => a - b), flagged); + + const compliant = [ + "import * as vs from 'vscode';", + 'declare const dbText: string;', + 'declare const f: () => void;', + "vs.window.showErrorMessage(plainNotificationText(dbText), { modal: true, detail: plainNotificationText(dbText) }, 'Retry');", + 'vs.window.withProgress({ location: 15, title: plainNotificationText(dbText) }, async progress => {', + ' progress.report({ message: plainNotificationText(dbText) });', + '});', + "vs.window.showInputBox({ prompt: 'Value', validateInput: value => value ? undefined : 'Required.' });", + "vs.window.showQuickPick(['a'], { prompt: plainNotificationText(dbText) });", + "vs.commands.registerCommand('x', plainErrors(f));", + 'const edit = { label: plainNotificationText(dbText), undo: plainErrors(f), redo: plainErrors(f) };' + ]; + assert.deepEqual(scan('compliant.ts', compliant.join('\n')).offenders, []); + }); +}); diff --git a/tests/unit/raw_text_transport.test.ts b/tests/unit/raw_text_transport.test.ts index e6c12993..53002f12 100644 --- a/tests/unit/raw_text_transport.test.ts +++ b/tests/unit/raw_text_transport.test.ts @@ -3,7 +3,12 @@ import './vscode_mock_setup'; import assert from 'node:assert/strict'; import { it, type TestContext } from 'node:test'; import { createDatabaseEngine, WasmDatabaseEngine } from '../../src/core/sqlite-db'; -import { buildCellContainmentQuery, containUnrepresentableTextCells, decodeRawTextColumns } from '../../src/core/cell-containment'; +import { + buildCellContainmentQuery, + containUnrepresentableTextCells, + decodeRawTextColumns, + findUnrepresentableTextRows +} from '../../src/core/cell-containment'; async function database(t: TestContext, encoding = 'UTF-8') { const { operations } = await createDatabaseEngine({ content: null, maxSize: 0 }); @@ -99,6 +104,45 @@ for (const [encoding, malformed, nul] of [ }); } +it('keeps TEXT containing NUL as bytes even when the engine returns it exactly', () => { + const encode = (text: string) => new TextEncoder().encode(text); + const rows = findUnrepresentableTextRows({ + sourceRows: [['a\0b'], ['ordinary']], + sourceColumnIndices: [0], + rawTextRows: [[encode('a\0b')], [encode('ordinary')]], + rawTextColumnIndices: [0], + textEncoding: 'utf-8' + }); + assert.deepEqual([...(rows ?? [])], [0]); +}); + +it('stores bound TEXT containing NUL exactly', async t => { + const engine = await database(t); + await engine.executeQuery('CREATE TABLE cells(value TEXT)'); + await engine.executeQuery('INSERT INTO cells VALUES (?)', ['c\0d']); + const rows = (await engine.executeQuery('SELECT hex(CAST(value AS BLOB)) FROM cells'))[0].rows; + assert.deepEqual(rows, [['630064']], 'the WASM engine must not truncate a bound value at NUL'); +}); + +it('stores bound TEXT with lone surrogates byte for byte as the native engine does', async t => { + // Expected bytes are what the native runtime stores: each lone surrogate + // as its 3-byte encoding, and nothing appended or cut off around it. + const values: Array<[string, string]> = [ + ['x\uD800', '78EDA080'], + ['tweet \uD83D', '747765657420EDA0BD'], + ['\uD83D中文', 'EDA0BDE4B8ADE69687'], + ['\uDE00a', 'EDB88061'], + ['ok 😀', '6F6B20F09F9880'] + ]; + const engine = await database(t); + await engine.executeQuery('CREATE TABLE cells(id INTEGER PRIMARY KEY, value TEXT)'); + for (const [index, [value]] of values.entries()) { + await engine.executeQuery('INSERT INTO cells VALUES (?, ?)', [index, value]); + } + const rows = (await engine.executeQuery('SELECT hex(CAST(value AS BLOB)) FROM cells ORDER BY id'))[0].rows; + assert.deepEqual(rows.map(row => row[0]), values.map(([, hex]) => hex)); +}); + it('keeps the default native raw TEXT transport as BLOBs', async t => { const engine = await database(t); const query = buildCellContainmentQuery("SELECT 'native'", 1, { limit: 1 }, [0]); diff --git a/tests/unit/virtualFileSystem.test.ts b/tests/unit/virtualFileSystem.test.ts index fc2d42ed..047ee600 100644 --- a/tests/unit/virtualFileSystem.test.ts +++ b/tests/unit/virtualFileSystem.test.ts @@ -391,6 +391,53 @@ describe('SQLiteFileSystemProvider', () => { } }); + it('refuses a writable text document for SQLite TEXT containing NUL', async () => { + // Both engines return such TEXT whole, but VS Code guesses UTF-16 + // from the NUL bytes, so it stays bytes as in the grid. + const result = await createDatabaseEngine({ content: null, maxSize: 0 }); + const engine = result.operations!; + const document = setupMockDocument(docKey, engine); + const uri = vscode.Uri.parse( + `vscode-sqlite://${docKey}/nul_vfs/group/1/value.txt` + ); + try { + await engine.executeQuery( + 'CREATE TABLE nul_vfs (value TEXT); ' + + "INSERT INTO nul_vfs VALUES (CAST(X'610062' AS TEXT))" + ); + assert.deepStrictEqual( + (await engine.executeQuery('SELECT value FROM nul_vfs'))[0].rows, + [['a\0b']], + 'control arm: the engine returns the TEXT whole' + ); + + await assert.rejects( + provider.readFile(uri), + /cannot be represented by the external text editor.*raw Hex/i + ); + await assert.rejects( + provider.writeFile( + uri, + new TextEncoder().encode('a\0c'), + { create: false, overwrite: true } + ), + /cannot be edited as text.*raw Hex/i + ); + assert.deepStrictEqual( + (await engine.executeQuery( + 'SELECT hex(CAST(value AS BLOB)) FROM nul_vfs' + ))[0].rows, + [['610062']] + ); + assert.strictEqual( + (document.recordExternalModification as any).mock.callCount(), + 0 + ); + } finally { + (engine as WasmDatabaseEngine).shutdown(); + } + }); + it('refuses a direct oversized VFS read before fetching the raw value', async () => { const dbOps = { getCellMetadata: mock.fn(async () => ({ diff --git a/tests/unit/without_rowid_identity.test.ts b/tests/unit/without_rowid_identity.test.ts index 1ed28ae5..6b4f15dd 100644 --- a/tests/unit/without_rowid_identity.test.ts +++ b/tests/unit/without_rowid_identity.test.ts @@ -208,6 +208,35 @@ describe('WITHOUT ROWID primary-key identity', () => { ); }); + it('keeps TEXT identities containing NUL read-only with a reason that names the NUL', async () => { + await engine.executeQuery( + 'CREATE TABLE nul_text_identity (key TEXT PRIMARY KEY, value TEXT) WITHOUT ROWID; ' + + "INSERT INTO nul_text_identity VALUES (CAST(X'610062' AS TEXT), 'nul'), ('plain', 'plain')" + ); + const page = await engine.fetchTableData('nul_text_identity', { + columns: ['rowid', 'key', 'value'], + limit: 10, + offset: 0 + }); + const nulIndex = page.rows.findIndex(row => row[2] === 'nul'); + assert.notStrictEqual(nulIndex, -1); + assert.match(String(page.rows[nulIndex][0]), /^readonly-pk:/); + const reason = page.readOnlyRowReasons?.[nulIndex] ?? ''; + assert.match(reason, /NUL character/); + assert.doesNotMatch(reason, /inline limit/); + + await assert.rejects( + engine.insertRow('nul_text_identity', { key: 'b\0c', value: 'must-rollback' }), + /NUL character/ + ); + assert.deepStrictEqual( + (await engine.executeQuery( + 'SELECT hex(CAST(key AS BLOB)) FROM nul_text_identity ORDER BY 1' + ))[0].rows, + [['610062'], ['706C61696E']] + ); + }); + it('suppresses keyset anchors for malformed ordinary TEXT sort keys', async () => { await engine.executeQuery( 'CREATE TABLE malformed_text_sort (' + diff --git a/vendor/query-plan-manifest.json b/vendor/query-plan-manifest.json index 08269351..7f7db73c 100644 --- a/vendor/query-plan-manifest.json +++ b/vendor/query-plan-manifest.json @@ -1,12 +1,12 @@ { "schema": 1, - "sqlJsCommit": "3181cc5ee888d3251228d3995c32bf9ea03c3240", + "sqlJsCommit": "35ac205b7f9470d9aa7696ceb9cdab5dec4b6ed3", "emcc": "emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 5.0.0 (a7c5deabd7c88ba1c38ebe988112256775f944c6)", "zig": "0.16.0", "zigClang": "clang version 21.1.0", "inputs": { "src/runtime/query-plan.c": "a2e6d39c36152bf36bb3729aff12567ed4fa2d9c7ef3751e60db580f5276cc8f", - "scripts/build-query-plan.mjs": "0e4d926fd88b8bbe057e661adbcf0b04cafffdeda633e88f5e2fa61565031eb4" + "scripts/build-query-plan.mjs": "38f7f4b77fcef551788d7e807fec17ca1ea2770c41e74e76a3c8c05ef7c3c50d" }, "outputs": { "natives/aarch64-macos/query-plan.dylib": "3a51dcd0ebc627e63d664e9b9c317667cb356f197e0d5645262bc3b5ef7b8c3c", @@ -14,8 +14,8 @@ "natives/x86_64-linux-gnu/query-plan.so": "340669408947665a9468d1c579c2b5c5cf33d95f3600521fbd9c6abb3a487b75", "natives/aarch64-linux-gnu/query-plan.so": "c98df0252291daeac6e97ad38e706b4a3f016c3b983fc1ee936639c301a90dce", "natives/x86_64-windows/query-plan.dll": "8ac0a58303c8ae9eb27534878b7775d2476157db8e01ee8d275325848778a177", - "vendor/sql.js/sql-wasm.js": "9ec25067a7a2adf6faa080f922ac06fd10b4def3f4c9ea8428863e86093f6763", - "website/public/sqlite-viewer/sql-wasm.js": "9ec25067a7a2adf6faa080f922ac06fd10b4def3f4c9ea8428863e86093f6763", + "vendor/sql.js/sql-wasm.js": "5e68997539968392caf70207e26b78486ef2e9b1a50c04cdefa966030b782106", + "website/public/sqlite-viewer/sql-wasm.js": "5e68997539968392caf70207e26b78486ef2e9b1a50c04cdefa966030b782106", "vendor/sql.js/sql-wasm.wasm": "ea94cafe49733bd55b8b2481d5cf0f07c5e006728c94b04999be04582b19a1e7", "assets/sqlite3.wasm": "ea94cafe49733bd55b8b2481d5cf0f07c5e006728c94b04999be04582b19a1e7", "website/public/sqlite-viewer/sql-wasm.wasm": "ea94cafe49733bd55b8b2481d5cf0f07c5e006728c94b04999be04582b19a1e7" diff --git a/vendor/sql.js/sql-wasm.js b/vendor/sql.js/sql-wasm.js index be68699c..7b99b37d 100644 --- a/vendor/sql.js/sql-wasm.js +++ b/vendor/sql.js/sql-wasm.js @@ -69,111 +69,112 @@ var initSqlJs = function (moduleConfig) { // The emcc-generated code and shell-post.js code goes below, // meaning that all of it runs inside of this promise. If anything throws an exception, our promise will abort -var m;m||=typeof Module != 'undefined' ? Module : {};var ca=!!globalThis.window,da=!!globalThis.WorkerGlobalScope,ea=globalThis.process?.versions?.node&&"renderer"!=globalThis.process?.type; -m.onRuntimeInitialized=function(){function a(e,g){Fb(e,g instanceof Error?g.message:String(g),-1)}function b(e,g){switch(typeof g){case "boolean":Dc(e,g?1:0);break;case "number":Ec(e,g);break;case "string":Fc(e,g,-1,-1);break;case "object":if(null===g)Gb(e);else if(null!=g.length){var k=fa(g.length);p.set(g,k);Gc(e,k,g.length,-1);ia(k)}else Fb(e,"Wrong API use : tried to return a value of an unknown type ("+g+").",-1);break;default:Gb(e)}}function c(e,g){for(var k=[],n=0;n>>0);if(null!=e){var g=this.filename,k="/",n=g;k&&(k="string"==typeof k?k:ka(k),n=g?la(k+"/"+g):k);g=ma(!0,!0);n=na(n,g);if(e){if("string"==typeof e){k=Array(e.length);for(var q=0,r=e.length;qn||!Number.isSafeInteger(n))return-1;try{if(e){a:{var r=e.chunkSize,y=e.cb-n;var t=0;var E=n;var D,I;for(y>k&&(y=k);ty-t&&(M=y-t);if(D=e.mb.get(Q))C.set(D.subarray(O,O+M),g+t);else{var J=e.nb-E;J>M&&(J=M);if(0J&&(I=I.subarray(0,J),ha=J);0J&&C.fill(0, -g+t+J,g+t+M)}t+=M;E+=M}qa=t}return qa}t=q.read(n,k);if(null==t)return 0;E=t.length;E>k&&(t=t.subarray(0,k),E=k);C.set(t,g);return E}catch(La){return-1}}function A(e){var g=Z[e];e=aa[e];if(!g)return-1;if(e)return e.cb;try{var k=g.size()}catch(n){return-1}return"number"!==typeof k||0>k||!Number.isSafeInteger(k)?-1:k}function N(e,g){var k=e.chunkSize,n=[];g=g?n.push(r):y+k>g&&q.fill(0,g-y)}),n.forEach(function(q){e.mb.delete(q)}),gn||!Number.isSafeInteger(n)||0>k)return-1;try{for(var r=e.chunkSize,y=n,t=0,E,D,I,Q,O;tk-t&&(Q=k-t);O=e.mb.get(E);if(!O){O=new Uint8Array(r);if(Q=ba)){ba>qa.length&&(ba=qa.length);M=(J=ha.read(La,ba))?J.length:0;M>ba&&(J=J.subarray(0,ba),M=ba);if(Me.cb&&(e.cb=n+k);return 0}catch(Gd){return-1}}function Pc(e,g){e=aa[e];if(!e)return-1;g=Number(g);if(0>g||!Number.isSafeInteger(g))return-1;try{return N(e,g),0}catch(k){return-1}}function Lb(){throw Error("paged databases are read-only snapshots; export() is only available on openPagedWritable instances");}function Mb(){var e,g,k;if(null===this.db)throw Error("Database closed");if(0===Nb(this.db))throw Error("cannot export a paged database while a transaction is open; COMMIT or ROLLBACK first"); -var n=aa[this.tb];var q=Z[this.tb];var r=n.chunkSize;var y=new Uint8Array(n.cb);for(e=0;en.cb-e&&(t=n.cb-e);if(g=n.mb.get(e/r))y.set(g.subarray(0,t),e);else if(g=n.nb-e,g>t&&(g=t),0g&&(k=k.subarray(0,g));if(!k||k.lengthNumber.MAX_SAFE_INTEGER)throw"rowId too big to fit inside a Number";e(g,n,q,Number(r))},"viiiij");Tb(this.db,this.ib,0);return this};var Z={},aa={},Na=1,ra=null,Oa=null,ib=null,Wb=null;l.openPaged=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPaged requires a hostIo object with read(offset, length) and size() functions");null===ra&&(ra=G(x,"iiiij"),Oa=G(A,"di"));var g=Ub(ra, -Oa);if(0!==g)throw Error("could not register the sqljs_host VFS (error code "+g+")");var k=Na;Na+=1;Z[k]=e;try{g=hd(k,L);var n=w(L,"i32");if(0!==g){var q=0!==n?hb(n):"SQLite error "+g;0!==n&&xa(n);throw Error(q);}}catch(r){throw delete Z[k],r;}e=Object.create(l.prototype);e.db=n;e.filename=null;e.tb=k;e.lb={};e.$a=new Map;Ka(e.db);e.Eb=Lb;e["export"]=Lb;e.close=Ma;e.close=Ma;return e};l.openPagedWritable=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPagedWritable requires a hostIo object with read(offset, length) and size() functions"); -var g=e.size();if("number"!==typeof g||0>g||!Number.isSafeInteger(g))throw Error("hostIo.size() must return a non-negative byte count");null===ra&&(ra=G(x,"iiiij"),Oa=G(A,"di"));null===ib&&(ib=G(Kb,"iiiij"),Wb=G(Pc,"iij"));var k=Ub(ra,Oa);0===k&&(k=jd(ib,Wb));if(0!==k)throw Error("could not register the sqljs_host VFS (error code "+k+")");var n=Na;Na+=1;Z[n]=e;a:{try{var q=e.read(16,2)}catch(t){e=4096;break a}!q||2>q.length?e=4096:(e=256*q[0]+q[1],e=1===e?65536:512<=e&&32768>=e&&0===(e&e-1)?e:4096)}aa[n]= -{chunkSize:e,mb:new Map,cb:g,nb:g};try{k=kd(n,L);var r=w(L,"i32");if(0!==k){var y=0!==r?hb(r):"SQLite error "+k;0!==r&&xa(r);throw Error(y);}}catch(t){throw delete Z[n],delete aa[n],t;}k=Object.create(l.prototype);k.db=r;k.filename=null;k.tb=n;k.lb={};k.$a=new Map;Ka(k.db);k.Eb=Mb;k["export"]=Mb;k.xc=Ob;k.exportPagedWritableOverlay=Ob;k.close=Ma;k.close=Ma;return k};d.prototype.bind=d.prototype.bind;d.prototype.step=d.prototype.step;d.prototype.get=d.prototype.get;d.prototype.getColumnNames=d.prototype.Pb; -d.prototype.getAsObject=d.prototype.Ob;d.prototype.getSQL=d.prototype.hc;d.prototype.getNormalizedSQL=d.prototype.dc;d.prototype.run=d.prototype.run;d.prototype.reset=d.prototype.reset;d.prototype.freemem=d.prototype.freemem;d.prototype.free=d.prototype.fb;h.prototype.next=h.prototype.next;h.prototype.getRemainingSQL=h.prototype.ec;l.prototype.run=l.prototype.run;l.prototype.exec=l.prototype.exec;l.prototype.each=l.prototype.bc;l.prototype.prepare=l.prototype.Ib;l.prototype.iterateStatements=l.prototype.kc; -l.prototype["export"]=l.prototype.Eb;l.prototype.close=l.prototype.close;l.prototype.handleError=l.prototype.handleError;l.prototype.getRowsModified=l.prototype.fc;l.prototype.progress_handler=l.prototype.nc;l.prototype.interrupt=l.prototype.jc;l.prototype.create_function=l.prototype.$b;l.prototype.create_aggregate=l.prototype.Zb;l.prototype.updateHook=l.prototype.qc;m.Database=l};var Ca="./this.program",Da=(a,b)=>{throw b;},Ea=globalThis.document?.currentScript?.src; -"undefined"!=typeof __filename?Ea=__filename:da&&(Ea=self.location.href);var Fa="",Ga,Ha; -if(ea){var fs=require("node:fs");Fa=__dirname+"/";Ha=a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a)};Ga=async a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a,void 0)};1{process.exitCode=a;throw b;}}else if(ca||da){try{Fa=(new URL(".",Ea)).href}catch{}da&&(Ha=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}); -Ga=async a=>{if(Ia(a))return new Promise((c,d)=>{var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?c(f.response):d(f.status)};f.onerror=d;f.send(null)});var b=await fetch(a,{credentials:"same-origin"});if(b.ok)return b.arrayBuffer();throw Error(b.status+" : "+b.url);}}var Ja=console.log.bind(console),Pa=console.error.bind(console),Qa,Ra=!1,Sa,Ia=a=>a.startsWith("file://"),p,C,Ta,H,K,Ua,Va,P; -function Wa(){var a=Xa.buffer;p=new Int8Array(a);Ta=new Int16Array(a);C=new Uint8Array(a);new Uint16Array(a);H=new Int32Array(a);K=new Uint32Array(a);Ua=new Float32Array(a);Va=new Float64Array(a);P=new BigInt64Array(a);new BigUint64Array(a)}function Ya(a){m.onAbort?.(a);a="Aborted("+a+")";Pa(a);Ra=!0;throw new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");}var Za; +var l;l||=typeof Module != 'undefined' ? Module : {};var da=!!globalThis.window,ea=!!globalThis.WorkerGlobalScope,fa=globalThis.process?.versions?.node&&"renderer"!=globalThis.process?.type; +l.onRuntimeInitialized=function(){function a(e,g){Fb(e,g instanceof Error?g.message:String(g),-1)}function b(e,g){switch(typeof g){case "boolean":Ec(e,g?1:0);break;case "number":Fc(e,g);break;case "string":g=d(g);Gc(e,g.ub,g.size,-1);q(g.ub);break;case "object":if(null===g)Gb(e);else if(null!=g.length){var h=ia(g.length);x.set(g,h);Hc(e,h,g.length,-1);q(h)}else Fb(e,"Wrong API use : tried to return a value of an unknown type ("+g+").",-1);break;default:Gb(e)}}function c(e,g){for(var h=[],m=0;m=m?g+=1:2047>=m?g+=2:65535>=m?g+=3:(g+=4,h+=1)}h=ia(g+1);if(!h)throw Error("Out of memory while copying a string");e=E(e,F,h,g+1);if(e!==g)throw q(h),Error("UTF-8 length mismatch: counted "+g+" bytes, wrote "+ +e);return{ub:h,size:g}}function f(e,g){this.Ya=e;this.db=g;this.Wa=1;this.Db=[];this.ob=null;this.vb=!1}function k(e){if(null===e.ob){e.ob=[];for(var g=Mc(e.Ya),h=0;h>>0);if(null!=e){var g=this.filename,h="/",m=g;h&&(h="string"==typeof h?h: +ka(h),m=g?la(h+"/"+g):h);g=ma(!0,!0);m=na(m,g);if(e){if("string"==typeof e){h=Array(e.length);for(var r=0,t=e.length;rm||!Number.isSafeInteger(m))return-1; +try{if(e){a:{var t=e.chunkSize,y=e.cb-m;var u=0;var G=m;var D,I;for(y>h&&(y=h);uy-u&&(M=y-u);if(D=e.mb.get(Q))F.set(D.subarray(O,O+M),g+u);else{var J=e.nb-G;J>M&&(J=M);if(0J&&(I=I.subarray(0,J),ha=J);0J&&F.fill(0,g+u+J,g+u+M)}u+=M;G+=M}pa=u}return pa}u=r.read(m,h);if(null==u)return 0;G=u.length;G>h&&(u=u.subarray(0,h),G=h);F.set(u,g);return G}catch(La){return-1}} +function N(e){var g=aa[e];e=ba[e];if(!g)return-1;if(e)return e.cb;try{var h=g.size()}catch(m){return-1}return"number"!==typeof h||0>h||!Number.isSafeInteger(h)?-1:h}function Lb(e,g){var h=e.chunkSize,m=[];g=g?m.push(t):y+h>g&&r.fill(0,g-y)}),m.forEach(function(r){e.mb.delete(r)}),gm||!Number.isSafeInteger(m)||0>h)return-1;try{for(var t=e.chunkSize,y=m, +u=0,G,D,I,Q,O;uh-u&&(Q=h-u);O=e.mb.get(G);if(!O){O=new Uint8Array(t);if(Q=ca)){ca>pa.length&&(ca=pa.length);M=(J=ha.read(La,ca))?J.length:0;M>ca&&(J=J.subarray(0,ca),M=ca);if(Me.cb&&(e.cb=m+h);return 0}catch(Hd){return-1}}function Qc(e,g){e=ba[e];if(!e)return-1; +g=Number(g);if(0>g||!Number.isSafeInteger(g))return-1;try{return Lb(e,g),0}catch(h){return-1}}function Mb(){throw Error("paged databases are read-only snapshots; export() is only available on openPagedWritable instances");}function Nb(){var e,g,h;if(null===this.db)throw Error("Database closed");if(0===Ob(this.db))throw Error("cannot export a paged database while a transaction is open; COMMIT or ROLLBACK first");var m=ba[this.tb];var r=aa[this.tb];var t=m.chunkSize;var y=new Uint8Array(m.cb);for(e= +0;em.cb-e&&(u=m.cb-e);if(g=m.mb.get(e/t))y.set(g.subarray(0,u),e);else if(g=m.nb-e,g>u&&(g=u),0g&&(h=h.subarray(0,g));if(!h||h.lengthNumber.MAX_SAFE_INTEGER)throw"rowId too big to fit inside a Number";e(g,m,r,Number(t))},"viiiij");Ub(this.db,this.ib,0);return this};var aa={},ba={},Na=1,qa=null,Oa=null,ib=null,Xb=null;n.openPaged=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPaged requires a hostIo object with read(offset, length) and size() functions");null===qa&&(qa=K(A,"iiiij"),Oa=K(N,"di"));var g=Vb(qa,Oa);if(0!==g)throw Error("could not register the sqljs_host VFS (error code "+ +g+")");var h=Na;Na+=1;aa[h]=e;try{g=jd(h,L);var m=B(L,"i32");if(0!==g){var r=0!==m?hb(m):"SQLite error "+g;0!==m&&ya(m);throw Error(r);}}catch(t){throw delete aa[h],t;}e=Object.create(n.prototype);e.db=m;e.filename=null;e.tb=h;e.lb={};e.$a=new Map;Ka(e.db);e.Fb=Mb;e["export"]=Mb;e.close=Ma;e.close=Ma;return e};n.openPagedWritable=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPagedWritable requires a hostIo object with read(offset, length) and size() functions"); +var g=e.size();if("number"!==typeof g||0>g||!Number.isSafeInteger(g))throw Error("hostIo.size() must return a non-negative byte count");null===qa&&(qa=K(A,"iiiij"),Oa=K(N,"di"));null===ib&&(ib=K(Pc,"iiiij"),Xb=K(Qc,"iij"));var h=Vb(qa,Oa);0===h&&(h=kd(ib,Xb));if(0!==h)throw Error("could not register the sqljs_host VFS (error code "+h+")");var m=Na;Na+=1;aa[m]=e;a:{try{var r=e.read(16,2)}catch(u){e=4096;break a}!r||2>r.length?e=4096:(e=256*r[0]+r[1],e=1===e?65536:512<=e&&32768>=e&&0===(e&e-1)?e:4096)}ba[m]= +{chunkSize:e,mb:new Map,cb:g,nb:g};try{h=ld(m,L);var t=B(L,"i32");if(0!==h){var y=0!==t?hb(t):"SQLite error "+h;0!==t&&ya(t);throw Error(y);}}catch(u){throw delete aa[m],delete ba[m],u;}h=Object.create(n.prototype);h.db=t;h.filename=null;h.tb=m;h.lb={};h.$a=new Map;Ka(h.db);h.Fb=Nb;h["export"]=Nb;h.xc=Pb;h.exportPagedWritableOverlay=Pb;h.close=Ma;h.close=Ma;return h};f.prototype.bind=f.prototype.bind;f.prototype.step=f.prototype.step;f.prototype.get=f.prototype.get;f.prototype.getColumnNames=f.prototype.Qb; +f.prototype.getAsObject=f.prototype.Pb;f.prototype.getSQL=f.prototype.jc;f.prototype.getNormalizedSQL=f.prototype.fc;f.prototype.run=f.prototype.run;f.prototype.reset=f.prototype.reset;f.prototype.freemem=f.prototype.freemem;f.prototype.free=f.prototype.fb;p.prototype.next=p.prototype.next;p.prototype.getRemainingSQL=p.prototype.hc;n.prototype.run=n.prototype.run;n.prototype.exec=n.prototype.exec;n.prototype.each=n.prototype.dc;n.prototype.prepare=n.prototype.Jb;n.prototype.iterateStatements=n.prototype.lc; +n.prototype["export"]=n.prototype.Fb;n.prototype.close=n.prototype.close;n.prototype.handleError=n.prototype.handleError;n.prototype.getRowsModified=n.prototype.ic;n.prototype.progress_handler=n.prototype.oc;n.prototype.interrupt=n.prototype.kc;n.prototype.create_function=n.prototype.bc;n.prototype.create_aggregate=n.prototype.ac;n.prototype.updateHook=n.prototype.qc;l.Database=n};var Ca="./this.program",Da=(a,b)=>{throw b;},Ea=globalThis.document?.currentScript?.src; +"undefined"!=typeof __filename?Ea=__filename:ea&&(Ea=self.location.href);var Fa="",Ga,Ha; +if(fa){var fs=require("node:fs");Fa=__dirname+"/";Ha=a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a)};Ga=async a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a,void 0)};1{process.exitCode=a;throw b;}}else if(da||ea){try{Fa=(new URL(".",Ea)).href}catch{}ea&&(Ha=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}); +Ga=async a=>{if(Ia(a))return new Promise((c,d)=>{var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?c(f.response):d(f.status)};f.onerror=d;f.send(null)});var b=await fetch(a,{credentials:"same-origin"});if(b.ok)return b.arrayBuffer();throw Error(b.status+" : "+b.url);}}var Ja=console.log.bind(console),Pa=console.error.bind(console),Qa,Ra=!1,Sa,Ia=a=>a.startsWith("file://"),x,F,Ta,P,R,Ua,Va,S; +function Wa(){var a=Xa.buffer;x=new Int8Array(a);Ta=new Int16Array(a);F=new Uint8Array(a);new Uint16Array(a);P=new Int32Array(a);R=new Uint32Array(a);Ua=new Float32Array(a);Va=new Float64Array(a);S=new BigInt64Array(a);new BigUint64Array(a)}function Ya(a){l.onAbort?.(a);a="Aborted("+a+")";Pa(a);Ra=!0;throw new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");}var Za; async function $a(a){if(!Qa)try{var b=await Ga(a);return new Uint8Array(b)}catch{}if(a==Za&&Qa)a=new Uint8Array(Qa);else if(Ha)a=Ha(a);else throw"both async and sync fetching of the wasm failed";return a}async function ab(a,b){try{var c=await $a(a);return await WebAssembly.instantiate(c,b)}catch(d){Pa(`failed to asynchronously prepare wasm: ${d}`),Ya(d)}} -async function bb(a){var b=Za;if(!Qa&&!Ia(b)&&!ea)try{var c=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(c,a)}catch(d){Pa(`wasm streaming compile failed: ${d}`),Pa("falling back to ArrayBuffer instantiation")}return ab(b,a)}class cb{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}var db=a=>{for(;0{var a=m.preRun.shift();fb.push(a)},kb=0,lb=null; -function w(a,b="i8"){b.endsWith("*")&&(b="*");switch(b){case "i1":return p[a];case "i8":return p[a];case "i16":return Ta[a>>1];case "i32":return H[a>>2];case "i64":return P[a>>3];case "float":return Ua[a>>2];case "double":return Va[a>>3];case "*":return K[a>>2];default:Ya(`invalid type for getValue: ${b}`)}}var mb=!0; -function ya(a){var b="i32";b.endsWith("*")&&(b="*");switch(b){case "i1":p[a]=0;break;case "i8":p[a]=0;break;case "i16":Ta[a>>1]=0;break;case "i32":H[a>>2]=0;break;case "i64":P[a>>3]=BigInt(0);break;case "float":Ua[a>>2]=0;break;case "double":Va[a>>3]=0;break;case "*":K[a>>2]=0;break;default:Ya(`invalid type for setValue: ${b}`)}} -var nb=new TextDecoder,ob=(a,b,c,d)=>{c=b+c;if(d)return c;for(;a[b]&&!(b>=c);)++b;return b},F=(a,b,c)=>a?nb.decode(C.subarray(a,ob(C,a,b,c))):"",pb=(a,b)=>{for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a.splice(d,1):".."===f?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a},la=a=>{var b="/"===a.charAt(0),c="/"===a.slice(-1);(a=pb(a.split("/").filter(d=>!!d),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a},qb=a=>{var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1); -a=b[0];b=b[1];if(!a&&!b)return".";b&&=b.slice(0,-1);return a+b},rb=a=>a&&a.match(/([^\/]+|\/)\/*$/)[1],sb=()=>{if(ea){var a=require("node:crypto");return b=>a.randomFillSync(b)}return b=>crypto.getRandomValues(b)},tb=a=>{(tb=sb())(a)},ub=(...a)=>{for(var b="",c=!1,d=a.length-1;-1<=d&&!c;d--){c=0<=d?a[d]:"/";if("string"!=typeof c)throw new TypeError("Arguments to path.resolve must be strings");if(!c)return"";b=c+"/"+b;c="/"===c.charAt(0)}b=pb(b.split("/").filter(f=>!!f),!c).join("/");return(c?"/": -"")+b||"."},vb=a=>{var b=ob(a,0);return nb.decode(a.buffer?a.subarray(0,b):new Uint8Array(a.slice(0,b)))},wb=[],xb=a=>{for(var b=0,c=0;c=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}return b},R=(a,b,c,d)=>{if(!(0=l){if(c>=d)break;b[c++]=l}else if(2047>=l){if(c+1>=d)break;b[c++]=192|l>>6;b[c++]=128|l&63}else if(65535>=l){if(c+2>=d)break;b[c++]=224|l>>12;b[c++]=128| -l>>6&63;b[c++]=128|l&63}else{if(c+3>=d)break;b[c++]=240|l>>18;b[c++]=128|l>>12&63;b[c++]=128|l>>6&63;b[c++]=128|l&63;h++}}b[c]=0;return c-f},yb=[];function zb(a,b){yb[a]={input:[],output:[],sb:b};Ab(a,Bb)} -var Bb={open(a){var b=yb[a.node.rdev];if(!b)throw new S(43);a.tty=b;a.seekable=!1},close(a){a.tty.sb.fsync(a.tty)},fsync(a){a.tty.sb.fsync(a.tty)},read(a,b,c,d){if(!a.tty||!a.tty.sb.Rb)throw new S(60);for(var f=0,h=0;h=a.node.Za)return 0;a=Math.min(a.node.Za-f,d);if(8=h||(h=Math.max(h,l*(1048576>l?2:1.125)>>>0),0!=l&&(h=Math.max(h,256)),l=a.Va,a.Va=new Uint8Array(h),0b)throw new S(28); -return b},zb(a,b,c,d,f){if(32768!==(a.node.mode&61440))throw new S(43);a=a.node.Va;if(f&2||!a||a.buffer!==p.buffer){f=!0;d=65536*Math.ceil(b/65536);var h=Xb(65536,d);h&&C.fill(0,h,h+d);d=h;if(!d)throw new S(48);if(a){if(0{var c=0;a&&(c|=365);b&&(c|=146);return c},Yb=null,Zb={},$b=[],ac=1,bc=null,cc= -!1,dc=!0,ec={},S=class{name="ErrnoError";constructor(a){this.Xa=a}},fc=class{wb={};node=null;get flags(){return this.wb.flags}set flags(a){this.wb.flags=a}get position(){return this.wb.position}set position(a){this.wb.position=a}},gc=class{Ta={};Ua={};qb=null;constructor(a,b,c,d){a||=this;this.parent=a;this.kb=a.kb;this.id=ac++;this.name=b;this.mode=c;this.rdev=d;this.atime=this.mtime=this.ctime=Date.now()}get read(){return 365===(this.mode&365)}set read(a){a?this.mode|=365:this.mode&=-366}get write(){return 146=== +async function bb(a){var b=Za;if(!Qa&&!Ia(b)&&!fa)try{var c=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(c,a)}catch(d){Pa(`wasm streaming compile failed: ${d}`),Pa("falling back to ArrayBuffer instantiation")}return ab(b,a)}class cb{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}var db=a=>{for(;0{var a=l.preRun.shift();fb.push(a)},kb=0,lb=null; +function B(a,b="i8"){b.endsWith("*")&&(b="*");switch(b){case "i1":return x[a];case "i8":return x[a];case "i16":return Ta[a>>1];case "i32":return P[a>>2];case "i64":return S[a>>3];case "float":return Ua[a>>2];case "double":return Va[a>>3];case "*":return R[a>>2];default:Ya(`invalid type for getValue: ${b}`)}}var mb=!0; +function wa(a){var b="i32";b.endsWith("*")&&(b="*");switch(b){case "i1":x[a]=0;break;case "i8":x[a]=0;break;case "i16":Ta[a>>1]=0;break;case "i32":P[a>>2]=0;break;case "i64":S[a>>3]=BigInt(0);break;case "float":Ua[a>>2]=0;break;case "double":Va[a>>3]=0;break;case "*":R[a>>2]=0;break;default:Ya(`invalid type for setValue: ${b}`)}} +var nb=new TextDecoder,ob=(a,b,c,d)=>{c=b+c;if(d)return c;for(;a[b]&&!(b>=c);)++b;return b},C=(a,b,c)=>a?nb.decode(F.subarray(a,ob(F,a,b,c))):"",pb=(a,b)=>{for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a.splice(d,1):".."===f?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a},la=a=>{var b="/"===a.charAt(0),c="/"===a.slice(-1);(a=pb(a.split("/").filter(d=>!!d),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a},qb=a=>{var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1); +a=b[0];b=b[1];if(!a&&!b)return".";b&&=b.slice(0,-1);return a+b},rb=a=>a&&a.match(/([^\/]+|\/)\/*$/)[1],sb=()=>{if(fa){var a=require("node:crypto");return b=>a.randomFillSync(b)}return b=>crypto.getRandomValues(b)},tb=a=>{(tb=sb())(a)},ub=(...a)=>{for(var b="",c=!1,d=a.length-1;-1<=d&&!c;d--){c=0<=d?a[d]:"/";if("string"!=typeof c)throw new TypeError("Arguments to path.resolve must be strings");if(!c)return"";b=c+"/"+b;c="/"===c.charAt(0)}b=pb(b.split("/").filter(f=>!!f),!c).join("/");return(c?"/": +"")+b||"."},vb=a=>{var b=ob(a,0);return nb.decode(a.buffer?a.subarray(0,b):new Uint8Array(a.slice(0,b)))},wb=[],xb=a=>{for(var b=0,c=0;c=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}return b},E=(a,b,c,d)=>{if(!(0=p){if(c>=d)break;b[c++]=p}else if(2047>=p){if(c+1>=d)break;b[c++]=192|p>>6;b[c++]=128|p&63}else if(65535>=p){if(c+2>=d)break;b[c++]=224|p>>12;b[c++]=128| +p>>6&63;b[c++]=128|p&63}else{if(c+3>=d)break;b[c++]=240|p>>18;b[c++]=128|p>>12&63;b[c++]=128|p>>6&63;b[c++]=128|p&63;k++}}b[c]=0;return c-f},yb=[];function zb(a,b){yb[a]={input:[],output:[],sb:b};Ab(a,Bb)} +var Bb={open(a){var b=yb[a.node.rdev];if(!b)throw new T(43);a.tty=b;a.seekable=!1},close(a){a.tty.sb.fsync(a.tty)},fsync(a){a.tty.sb.fsync(a.tty)},read(a,b,c,d){if(!a.tty||!a.tty.sb.Tb)throw new T(60);for(var f=0,k=0;k=a.node.Za)return 0;a=Math.min(a.node.Za-f,d);if(8=k||(k=Math.max(k,p*(1048576>p?2:1.125)>>>0),0!=p&&(k=Math.max(k,256)),p=a.Va,a.Va=new Uint8Array(k),0b)throw new T(28); +return b},Ab(a,b,c,d,f){if(32768!==(a.node.mode&61440))throw new T(43);a=a.node.Va;if(f&2||!a||a.buffer!==x.buffer){f=!0;d=65536*Math.ceil(b/65536);var k=Yb(65536,d);k&&F.fill(0,k,k+d);d=k;if(!d)throw new T(48);if(a){if(0{var c=0;a&&(c|=365);b&&(c|=146);return c},Zb=null,$b={},ac=[],bc=1,cc=null,dc= +!1,ec=!0,fc={},T=class{name="ErrnoError";constructor(a){this.Xa=a}},gc=class{xb={};node=null;get flags(){return this.xb.flags}set flags(a){this.xb.flags=a}get position(){return this.xb.position}set position(a){this.xb.position=a}},hc=class{Ta={};Ua={};qb=null;constructor(a,b,c,d){a||=this;this.parent=a;this.kb=a.kb;this.id=bc++;this.name=b;this.mode=c;this.rdev=d;this.atime=this.mtime=this.ctime=Date.now()}get read(){return 365===(this.mode&365)}set read(a){a?this.mode|=365:this.mode&=-366}get write(){return 146=== (this.mode&146)}set write(a){a?this.mode|=146:this.mode&=-147}}; -function V(a,b={}){if(!a)throw new S(44);b.Fb??(b.Fb=!0);"/"===a.charAt(0)||(a="//"+a);var c=0;a:for(;40>c;c++){a=a.split("/").filter(v=>!!v);for(var d=Yb,f="/",h=0;h>>0)%bc.length} -function Vb(a){var b=hc(a.parent.id,a.name);if(bc[b]===a)bc[b]=a.rb;else for(b=bc[b];b;){if(b.rb===a){b.rb=a.rb;break}b=b.rb}}function Ib(a,b){var c=U(a.mode)?(c=ic(a,"x"))?c:a.Ta.lookup?0:2:54;if(c)throw new S(c);for(c=bc[hc(a.id,b)];c;c=c.rb){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.Ta.lookup(a,b)}function Hb(a,b,c,d){a=new gc(a,b,c,d);b=hc(a.parent.id,a.name);a.rb=bc[b];return bc[b]=a}function U(a){return 16384===(a&61440)} -function jc(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b}function ic(a,b){if(dc)return 0;if(!b.includes("r")||a.mode&292){if(b.includes("w")&&!(a.mode&146)||b.includes("x")&&!(a.mode&73))return 2}else return 2;return 0}function kc(a,b){if(!U(a.mode))return 54;try{return Ib(a,b),20}catch(c){}return ic(a,"wx")} -function lc(a,b,c){try{var d=Ib(a,b)}catch(f){return f.Xa}if(a=ic(a,"wx"))return a;if(c){if(!U(d.mode))return 54;if(d===d.parent||"/"===ka(d))return 10}else if(U(d.mode))return 31;return 0}function mc(a){if(!a)throw new S(63);return a}function W(a){a=$b[a];if(!a)throw new S(8);return a}function nc(a,b=-1){a=Object.assign(new fc,a);if(-1==b)a:{for(b=0;4096>=b;b++)if(!$b[b])break a;throw new S(33);}a.fd=b;return $b[b]=a}function oc(a,b=-1){a=nc(a,b);a.Ua?.wc?.(a);return a} -function pc(a,b,c){var d=a?.Ua.eb;a=d?a:b;d??=b.Ta.eb;mc(d);d(a,c)}var Eb={open(a){a.Ua=Zb[a.node.rdev].Ua;a.Ua.open?.(a)},gb(){throw new S(70);}};function Ab(a,b){Zb[a]={Ua:b}}function qc(a,b){var c="/"===b;if(c&&Yb)throw new S(10);if(!c&&b){var d=V(b,{Fb:!1});b=d.path;d=d.node;if(d.qb)throw new S(10);if(!U(d.mode))throw new S(54);}b={type:a,Cc:{},Tb:b,lc:[]};a=a.kb(b);a.kb=b;b.root=a;c?Yb=a:d&&(d.qb=b,d.kb&&d.kb.lc.push(b))} -function rc(a,b,c){var d=V(a,{parent:!0}).node;a=rb(a);if(!a)throw new S(28);if("."===a||".."===a)throw new S(20);var f=kc(d,a);if(f)throw new S(f);if(!d.Ta.yb)throw new S(63);return d.Ta.yb(d,a,b,c)}function na(a,b=438){return rc(a,b&4095|32768,0)}function X(a,b=511){return rc(a,b&1023|16384,0)}function sc(a,b,c){"undefined"==typeof c&&(c=b,b=438);rc(a,b|8192,c)} -function tc(a,b){if(!ub(a))throw new S(44);var c=V(b,{parent:!0}).node;if(!c)throw new S(44);b=rb(b);var d=kc(c,b);if(d)throw new S(d);if(!c.Ta.symlink)throw new S(63);c.Ta.symlink(c,b,a)}function uc(a){var b=V(a,{parent:!0}).node;a=rb(a);var c=Ib(b,a),d=lc(b,a,!0);if(d)throw new S(d);if(!b.Ta.rmdir)throw new S(63);if(c.qb)throw new S(10);b.Ta.rmdir(b,a);Vb(c)} -function Ba(a){var b=V(a,{parent:!0}).node;if(!b)throw new S(44);a=rb(a);var c=Ib(b,a),d=lc(b,a,!1);if(d)throw new S(d);if(!b.Ta.unlink)throw new S(63);if(c.qb)throw new S(10);b.Ta.unlink(b,a);Vb(c)}function vc(a,b){a=V(a,{pb:!b}).node;return mc(a.Ta.bb)(a)}function wc(a,b,c,d){pc(a,b,{mode:c&4095|b.mode&-4096,ctime:Date.now(),ac:d})}function oa(a,b){a="string"==typeof a?V(a,{pb:!0}).node:a;wc(null,a,b)} -function xc(a,b,c){if(U(b.mode))throw new S(31);if(32768!==(b.mode&61440))throw new S(28);var d=ic(b,"w");if(d)throw new S(d);pc(a,b,{size:c,timestamp:Date.now()})} -function pa(a,b,c=438){if(""===a)throw new S(44);if("string"==typeof b){var d={r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090}[b];if("undefined"==typeof d)throw Error(`Unknown file open mode: ${b}`);b=d}c=b&64?c&4095|32768:0;if("object"==typeof a)d=a;else{var f=a.endsWith("/");a=V(a,{pb:!(b&131072),mc:!0});d=a.node;a=a.path}var h=!1;if(b&64)if(d){if(b&128)throw new S(20);}else{if(f)throw new S(31);d=rc(a,c|511,0);h=!0}if(!d)throw new S(44);8192===(d.mode&61440)&&(b&=-513);if(b&65536&&!U(d.mode))throw new S(54); -if(!h&&(f=d?40960===(d.mode&61440)?32:U(d.mode)&&("r"!==jc(b)||b&576)?31:ic(d,jc(b)):44))throw new S(f);b&512&&!h&&(f=d,f="string"==typeof f?V(f,{pb:!0}).node:f,xc(null,f,0));b&=-131713;f=nc({node:d,path:ka(d),flags:b,seekable:!0,position:0,Ua:d.Ua,pc:[],error:!1});f.Ua.open&&f.Ua.open(f);h&&oa(d,c&511);!m.logReadFiles||b&1||a in ec||(ec[a]=1);return f}function ta(a){if(null===a.fd)throw new S(8);a.Gb&&(a.Gb=null);try{a.Ua.close&&a.Ua.close(a)}catch(b){throw b;}finally{$b[a.fd]=null}a.fd=null} -function yc(a,b,c){if(null===a.fd)throw new S(8);if(!a.seekable||!a.Ua.gb)throw new S(70);if(0!=c&&1!=c&&2!=c)throw new S(28);a.position=a.Ua.gb(a,b,c);a.pc=[]}function zc(a,b,c,d,f){if(0>d||0>f)throw new S(28);if(null===a.fd)throw new S(8);if(1===(a.flags&2097155))throw new S(8);if(U(a.node.mode))throw new S(31);if(!a.Ua.read)throw new S(28);var h="undefined"!=typeof f;if(!h)f=a.position;else if(!a.seekable)throw new S(70);b=a.Ua.read(a,b,c,d,f);h||(a.position+=b);return b} -function sa(a,b,c,d,f){if(0>d||0>f)throw new S(28);if(null===a.fd)throw new S(8);if(0===(a.flags&2097155))throw new S(8);if(U(a.node.mode))throw new S(31);if(!a.Ua.write)throw new S(28);a.seekable&&a.flags&1024&&yc(a,0,2);var h="undefined"!=typeof f;if(!h)f=a.position;else if(!a.seekable)throw new S(70);b=a.Ua.write(a,b,c,d,f,void 0);h||(a.position+=b);return b} -function Aa(a){var b=b||0;var c="binary";"utf8"!==c&&"binary"!==c&&Ya(`Invalid encoding type "${c}"`);b=pa(a,b);a=vc(a).size;var d=new Uint8Array(a);zc(b,d,0,a,0);"utf8"===c&&(d=vb(d));ta(b);return d} -function Ac(a,b,c){a=la("/dev/"+a);var d=ma(!!b,!!c);Ac.Sb??(Ac.Sb=64);var f=Ac.Sb++<<8|0;Ab(f,{open(h){h.seekable=!1},close(){c?.buffer?.length&&c(10)},read(h,l,v,z){for(var x=0,A=0;A>2]=b.dev;K[a+4>>2]=b.mode;K[a+8>>2]=b.nlink;K[a+12>>2]=b.uid;K[a+16>>2]=b.gid;K[a+20>>2]=b.rdev;P[a+24>>3]=BigInt(b.size);H[a+32>>2]=4096;H[a+36>>2]=b.blocks;var c=b.atime.getTime(),d=b.mtime.getTime(),f=b.ctime.getTime();P[a+40>>3]=BigInt(Math.floor(c/1E3));K[a+48>>2]=c%1E3*1E6;P[a+56>>3]=BigInt(Math.floor(d/1E3));K[a+64>>2]=d%1E3*1E6;P[a+72>>3]=BigInt(Math.floor(f/1E3));K[a+80>>2]=f%1E3*1E6;P[a+88>>3]=BigInt(b.ino);return 0} -var Oc=void 0,ld=()=>{var a=H[+Oc>>2];Oc+=4;return a},md=0,nd=[0,31,60,91,121,152,182,213,244,274,305,335],od=[0,31,59,90,120,151,181,212,243,273,304,334],pd={},qd=a=>{Sa=a;mb||0{if(!Ra)try{a()}catch(b){b instanceof cb||"unwind"==b||Da(1,b)}finally{if(!(mb||0{if(!td){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(globalThis.navigator?.language?? -"C").replace("-","_")+".UTF-8",_:Ca||"./this.program"},b;for(b in sd)void 0===sd[b]?delete a[b]:a[b]=sd[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);td=c}return td},td,vd=(a,b,c,d)=>{var f={string:x=>{var A=0;if(null!==x&&void 0!==x&&0!==x){A=xb(x)+1;var N=ua(A);R(x,C,N,A);A=N}return A},array:x=>{var A=ua(x.length);p.set(x,A);return A}};a=m["_"+a];var h=[],l=0;if(d)for(var v=0;v{var b=xb(a)+1,c=fa(b);c&&R(a,C,c,b);return c},wd,xd=[],B=a=>{wd.delete(yd.get(a));yd.set(a,null);xd.push(a)},zd=a=>{const b=a.length;return[b%128|128,b>>7,...a]},Ad={i:127,p:127,j:126,f:125,d:124,e:111},Bd=a=>zd(Array.from(a,b=>Ad[b])),G=(a,b)=>{if(!wd){wd=new WeakMap;var c=yd.length;if(wd)for(var d=0;d<0+c;d++){var f=yd.get(d);f&&wd.set(f,d)}}if(c=wd.get(a)||0)return c;c=xd.length?xd.pop():yd.grow(1);try{yd.set(c,a)}catch(h){if(!(h instanceof TypeError))throw h; -b=Uint8Array.of(0,97,115,109,1,0,0,0,1,...zd([1,96,...Bd(b.slice(1)),...Bd("v"===b[0]?"":b[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);b=new WebAssembly.Module(b);b=(new WebAssembly.Instance(b,{e:{f:a}})).exports.f;yd.set(c,b)}wd.set(a,c);return c};bc=Array(4096);qc(T,"/");X("/tmp");X("/home");X("/home/web_user"); -(function(){X("/dev");Ab(259,{read:()=>0,write:(d,f,h,l)=>l,gb:()=>0});sc("/dev/null",259);zb(1280,Cb);zb(1536,Db);sc("/dev/tty",1280);sc("/dev/tty1",1536);var a=new Uint8Array(1024),b=0,c=()=>{0===b&&(tb(a),b=a.byteLength);return a[--b]};Ac("random",c);Ac("urandom",c);X("/dev/shm");X("/dev/shm/tmp")})(); -(function(){X("/proc");var a=X("/proc/self");X("/proc/self/fd");qc({kb(){var b=Hb(a,"fd",16895,73);b.Ua={gb:T.Ua.gb};b.Ta={lookup(c,d){c=+d;var f=W(c);c={parent:null,kb:{Tb:"fake"},Ta:{readlink:()=>f.path},id:c+1};return c.parent=c},readdir(){return Array.from($b.entries()).filter(([,c])=>c).map(([c])=>c.toString())}};return b}},"/proc/self/fd")})();m.noExitRuntime&&(mb=m.noExitRuntime);m.print&&(Ja=m.print);m.printErr&&(Pa=m.printErr);m.wasmBinary&&(Qa=m.wasmBinary);m.thisProgram&&(Ca=m.thisProgram); -if(m.preInit)for("function"==typeof m.preInit&&(m.preInit=[m.preInit]);0va();m.stackRestore=a=>za(a);m.stackAlloc=a=>ua(a);m.cwrap=(a,b,c,d)=>{var f=!c||c.every(h=>"number"===h||"boolean"===h);return"string"!==b&&f&&!d?m["_"+a]:(...h)=>vd(a,b,c,h)};m.addFunction=G;m.removeFunction=B;m.UTF8ToString=F;m.stringToNewUTF8=ja;m.writeArrayToMemory=(a,b)=>{p.set(a,b)}; -var fa,ia,Xb,Cd,za,ua,va,Xa,yd,Dd={a:(a,b,c,d)=>Ya(`Assertion failed: ${F(a)}, at: `+[b?F(b):"unknown filename",c,d?F(d):"unknown function"]),i:function(a,b){try{return a=F(a),oa(a,b),0}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return-c.Xa}},L:function(a,b,c){try{b=F(b);b=Bc(a,b);if(c&-8)return-28;var d=V(b,{pb:!0}).node;if(!d)return-44;a="";c&4&&(a+="r");c&2&&(a+="w");c&1&&(a+="x");return a&&ic(d,a)?-2:0}catch(f){if("undefined"==typeof Y||"ErrnoError"!==f.name)throw f;return-f.Xa}}, -j:function(a,b){try{var c=W(a);wc(c,c.node,b,!1);return 0}catch(d){if("undefined"==typeof Y||"ErrnoError"!==d.name)throw d;return-d.Xa}},h:function(a){try{var b=W(a);pc(b,b.node,{timestamp:Date.now(),ac:!1});return 0}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return-c.Xa}},b:function(a,b,c){Oc=c;try{var d=W(a);switch(b){case 0:var f=ld();if(0>f)break;for(;$b[f];)f++;return oc(d,f).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return f=ld(),d.flags|=f,0;case 12:return f= -ld(),Ta[f+0>>1]=2,0;case 13:case 14:return 0}return-28}catch(h){if("undefined"==typeof Y||"ErrnoError"!==h.name)throw h;return-h.Xa}},g:function(a,b){try{var c=W(a),d=c.node,f=c.Ua.bb;a=f?c:d;f??=d.Ta.bb;mc(f);var h=f(a);return Cc(b,h)}catch(l){if("undefined"==typeof Y||"ErrnoError"!==l.name)throw l;return-l.Xa}},H:function(a,b){b=-9007199254740992>b||9007199254740992b||0===(c.flags&2097155))throw new S(28);xc(c,c.node,b);return 0}catch(d){if("undefined"== -typeof Y||"ErrnoError"!==d.name)throw d;return-d.Xa}},G:function(a,b){try{if(0===b)return-28;var c=xb("/")+1;if(b=d)return-28;var f=V(b).node;if(!f)throw new S(44);if(!f.Ta.readlink)throw new S(28);var h=f.Ta.readlink(f);var l=Math.min(d,xb(h)),v=p[c+l]; -R(h,C,c,d+1);p[c+l]=v;return l}catch(z){if("undefined"==typeof Y||"ErrnoError"!==z.name)throw z;return-z.Xa}},u:function(a){try{return a=F(a),uc(a),0}catch(b){if("undefined"==typeof Y||"ErrnoError"!==b.name)throw b;return-b.Xa}},f:function(a,b){try{return a=F(a),Cc(b,vc(a))}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return-c.Xa}},r:function(a,b,c){try{b=F(b);b=Bc(a,b);if(c)if(512===c)uc(b);else return-28;else Ba(b);return 0}catch(d){if("undefined"==typeof Y||"ErrnoError"!==d.name)throw d; -return-d.Xa}},q:function(a,b,c){try{b=F(b);b=Bc(a,b,!0);var d=Date.now(),f,h;if(c){var l=K[c>>2]+4294967296*H[c+4>>2],v=H[c+8>>2];1073741823==v?f=d:1073741822==v?f=null:f=1E3*l+v/1E6;c+=16;l=K[c>>2]+4294967296*H[c+4>>2];v=H[c+8>>2];1073741823==v?h=d:1073741822==v?h=null:h=1E3*l+v/1E6}else h=f=d;if(null!==(h??f)){a=f;var z=V(b,{pb:!0}).node;mc(z.Ta.eb)(z,{atime:a,mtime:h})}return 0}catch(x){if("undefined"==typeof Y||"ErrnoError"!==x.name)throw x;return-x.Xa}},m:()=>Ya(""),l:()=>{mb=!1;md=0},A:function(a, -b){a=-9007199254740992>a||9007199254740992>2]=a.getSeconds();H[b+4>>2]=a.getMinutes();H[b+8>>2]=a.getHours();H[b+12>>2]=a.getDate();H[b+16>>2]=a.getMonth();H[b+20>>2]=a.getFullYear()-1900;H[b+24>>2]=a.getDay();var c=a.getFullYear();H[b+28>>2]=(0!==c%4||0===c%100&&0!==c%400?od:nd)[a.getMonth()]+a.getDate()-1|0;H[b+36>>2]=-(60*a.getTimezoneOffset());c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();var d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset(); -H[b+32>>2]=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0},y:function(a,b,c,d,f,h,l){f=-9007199254740992>f||9007199254740992>2]=z.Ub;K[l>>2]=x;return 0}catch(A){if("undefined"==typeof Y||"ErrnoError"!==A.name)throw A;return-A.Xa}},z:function(a,b,c,d,f,h){h=-9007199254740992>h|| -9007199254740992{pd[a]&&(clearTimeout(pd[a].id),delete pd[a]);if(!b)return 0;var c=setTimeout(()=>{delete pd[a];rd(()=>Cd(a,performance.now()))},b);pd[a]={id:c,Dc:b};return 0},B:(a,b,c,d)=>{var f=(new Date).getFullYear(),h=(new Date(f,0,1)).getTimezoneOffset(); -f=(new Date(f,6,1)).getTimezoneOffset();K[a>>2]=60*Math.max(h,f);H[b>>2]=Number(h!=f);b=l=>{var v=Math.abs(l);return`UTC${0<=l?"-":"+"}${String(Math.floor(v/60)).padStart(2,"0")}${String(v%60).padStart(2,"0")}`};a=b(h);b=b(f);fDate.now(),s:()=>2147483648,c:()=>performance.now(),o:a=>{var b=C.length;a>>>=0;if(2147483648=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);a:{d=(Math.min(2147483648,65536*Math.ceil(Math.max(a, -d)/65536))-Xa.buffer.byteLength+65535)/65536|0;try{Xa.grow(d);Wa();var f=1;break a}catch(h){}f=void 0}if(f)return!0}return!1},E:(a,b)=>{var c=0,d=0,f;for(f of ud()){var h=b+c;K[a+d>>2]=h;c+=R(f,C,h,Infinity)+1;d+=4}return 0},F:(a,b)=>{var c=ud();K[a>>2]=c.length;a=0;for(var d of c)a+=xb(d)+1;K[b>>2]=a;return 0},e:function(a){try{var b=W(a);ta(b);return 0}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return c.Xa}},p:function(a,b){try{var c=W(a);p[b]=c.tty?2:U(c.mode)?3:40960===(c.mode& -61440)?7:4;Ta[b+2>>1]=0;P[b+8>>3]=BigInt(0);P[b+16>>3]=BigInt(0);return 0}catch(d){if("undefined"==typeof Y||"ErrnoError"!==d.name)throw d;return d.Xa}},w:function(a,b,c,d){try{a:{var f=W(a);a=b;for(var h,l=b=0;l>2],z=K[a+4>>2];a+=8;var x=zc(f,p,v,z,h);if(0>x){var A=-1;break a}b+=x;if(x>2]=A;return 0}catch(N){if("undefined"==typeof Y||"ErrnoError"!==N.name)throw N;return N.Xa}},D:function(a,b,c,d){b=-9007199254740992>b||9007199254740992< -b?NaN:Number(b);try{if(isNaN(b))return 61;var f=W(a);yc(f,b,c);P[d>>3]=BigInt(f.position);f.Gb&&0===b&&0===c&&(f.Gb=null);return 0}catch(h){if("undefined"==typeof Y||"ErrnoError"!==h.name)throw h;return h.Xa}},I:function(a){try{var b=W(a);return b.Ua?.fsync?.(b)}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return c.Xa}},t:function(a,b,c,d){try{a:{var f=W(a);a=b;for(var h,l=b=0;l>2],z=K[a+4>>2];a+=8;var x=sa(f,p,v,z,h);if(0>x){var A=-1;break a}b+=x;if(x>2]=A;return 0}catch(N){if("undefined"==typeof Y||"ErrnoError"!==N.name)throw N;return N.Xa}},k:qd}; -function Ed(){function a(){m.calledRun=!0;if(!Ra){if(!m.noFSInit&&!cc){var b,c;cc=!0;b??=m.stdin;c??=m.stdout;d??=m.stderr;b?Ac("stdin",b):tc("/dev/tty","/dev/stdin");c?Ac("stdout",null,c):tc("/dev/tty","/dev/stdout");d?Ac("stderr",null,d):tc("/dev/tty1","/dev/stderr");pa("/dev/stdin",0);pa("/dev/stdout",1);pa("/dev/stderr",1)}Fd.N();dc=!1;m.onRuntimeInitialized?.();if(m.postRun)for("function"==typeof m.postRun&&(m.postRun=[m.postRun]);m.postRun.length;){var d=m.postRun.shift();eb.push(d)}db(eb)}} -if(0{setTimeout(()=>m.setStatus(""),1);a()},1)):a()}}var Fd; -(async function(){function a(c){c=Fd=c.exports;m._sqlite3_free=c.P;m._sqlite3_value_text=c.Q;m._sqlite3_prepare_v2=c.R;m._sqlite3_step=c.S;m._sqlite3_reset=c.T;m._sqlite3_exec=c.U;m._sqlite3_finalize=c.V;m._sqlite3_column_name=c.W;m._sqlite3_column_text=c.X;m._sqlite3_column_type=c.Y;m._sqlite3_errmsg=c.Z;m._sqlite3_clear_bindings=c._;m._sqlite3_value_blob=c.$;m._sqlite3_value_bytes=c.aa;m._sqlite3_value_double=c.ba;m._sqlite3_value_int=c.ca;m._sqlite3_value_type=c.da;m._sqlite3_result_blob=c.ea; -m._sqlite3_result_double=c.fa;m._sqlite3_result_error=c.ga;m._sqlite3_result_int=c.ha;m._sqlite3_result_int64=c.ia;m._sqlite3_result_null=c.ja;m._sqlite3_result_text=c.ka;m._sqlite3_aggregate_context=c.la;m._sqlite3_column_count=c.ma;m._sqlite3_data_count=c.na;m._sqlite3_column_blob=c.oa;m._sqlite3_column_bytes=c.pa;m._sqlite3_column_double=c.qa;m._sqlite3_bind_blob=c.ra;m._sqlite3_bind_double=c.sa;m._sqlite3_bind_int=c.ta;m._sqlite3_bind_text=c.ua;m._sqlite3_bind_parameter_index=c.va;m._sqlite3_sql= -c.wa;m._sqlite3_normalized_sql=c.xa;m._sqlite3_changes=c.ya;m._sqlite3_close_v2=c.za;m._sqlite3_progress_handler=c.Aa;m._sqlite3_interrupt=c.Ba;m._sqlite3_create_function_v2=c.Ca;m._sqlite3_update_hook=c.Da;m._sqlite3_open=c.Ea;m._sqlite3_get_autocommit=c.Fa;fa=m._malloc=c.Ga;ia=m._free=c.Ha;m._RegisterExtensionFunctions=c.Ia;m._sqljs_vfs_register=c.Ja;m._sqljs_open_paged=c.Ka;m._sqljs_vfs_register_rw=c.La;m._sqljs_open_paged_rw=c.Ma;m._sqlite_explorer_register_query_plan=c.Na;Xb=c.Oa;Cd=c.Pa;za= -c.Qa;ua=c.Ra;va=c.Sa;Xa=c.M;yd=c.O;Wa();kb--;m.monitorRunDependencies?.(kb);0==kb&&lb&&(c=lb,lb=null,c());return Fd}kb++;m.monitorRunDependencies?.(kb);var b={a:Dd};if(m.instantiateWasm)return new Promise(c=>{m.instantiateWasm(b,(d,f)=>{c(a(d,f))})});Za??=m.locateFile?m.locateFile("sql-wasm.wasm",Fa):Fa+"sql-wasm.wasm";return a((await bb(b)).instance)})();Ed(); +function W(a,b={}){if(!a)throw new T(44);b.Gb??(b.Gb=!0);"/"===a.charAt(0)||(a="//"+a);var c=0;a:for(;40>c;c++){a=a.split("/").filter(n=>!!n);for(var d=Zb,f="/",k=0;k>>0)%cc.length} +function Wb(a){var b=ic(a.parent.id,a.name);if(cc[b]===a)cc[b]=a.rb;else for(b=cc[b];b;){if(b.rb===a){b.rb=a.rb;break}b=b.rb}}function Jb(a,b){var c=V(a.mode)?(c=jc(a,"x"))?c:a.Ta.lookup?0:2:54;if(c)throw new T(c);for(c=cc[ic(a.id,b)];c;c=c.rb){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.Ta.lookup(a,b)}function Ib(a,b,c,d){a=new hc(a,b,c,d);b=ic(a.parent.id,a.name);a.rb=cc[b];return cc[b]=a}function V(a){return 16384===(a&61440)} +function kc(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b}function jc(a,b){if(ec)return 0;if(!b.includes("r")||a.mode&292){if(b.includes("w")&&!(a.mode&146)||b.includes("x")&&!(a.mode&73))return 2}else return 2;return 0}function lc(a,b){if(!V(a.mode))return 54;try{return Jb(a,b),20}catch(c){}return jc(a,"wx")} +function mc(a,b,c){try{var d=Jb(a,b)}catch(f){return f.Xa}if(a=jc(a,"wx"))return a;if(c){if(!V(d.mode))return 54;if(d===d.parent||"/"===ka(d))return 10}else if(V(d.mode))return 31;return 0}function nc(a){if(!a)throw new T(63);return a}function X(a){a=ac[a];if(!a)throw new T(8);return a}function oc(a,b=-1){a=Object.assign(new gc,a);if(-1==b)a:{for(b=0;4096>=b;b++)if(!ac[b])break a;throw new T(33);}a.fd=b;return ac[b]=a}function pc(a,b=-1){a=oc(a,b);a.Ua?.wc?.(a);return a} +function qc(a,b,c){var d=a?.Ua.eb;a=d?a:b;d??=b.Ta.eb;nc(d);d(a,c)}var Eb={open(a){a.Ua=$b[a.node.rdev].Ua;a.Ua.open?.(a)},gb(){throw new T(70);}};function Ab(a,b){$b[a]={Ua:b}}function rc(a,b){var c="/"===b;if(c&&Zb)throw new T(10);if(!c&&b){var d=W(b,{Gb:!1});b=d.path;d=d.node;if(d.qb)throw new T(10);if(!V(d.mode))throw new T(54);}b={type:a,Cc:{},Vb:b,mc:[]};a=a.kb(b);a.kb=b;b.root=a;c?Zb=a:d&&(d.qb=b,d.kb&&d.kb.mc.push(b))} +function sc(a,b,c){var d=W(a,{parent:!0}).node;a=rb(a);if(!a)throw new T(28);if("."===a||".."===a)throw new T(20);var f=lc(d,a);if(f)throw new T(f);if(!d.Ta.zb)throw new T(63);return d.Ta.zb(d,a,b,c)}function na(a,b=438){return sc(a,b&4095|32768,0)}function Y(a,b=511){return sc(a,b&1023|16384,0)}function tc(a,b,c){"undefined"==typeof c&&(c=b,b=438);sc(a,b|8192,c)} +function uc(a,b){if(!ub(a))throw new T(44);var c=W(b,{parent:!0}).node;if(!c)throw new T(44);b=rb(b);var d=lc(c,b);if(d)throw new T(d);if(!c.Ta.symlink)throw new T(63);c.Ta.symlink(c,b,a)}function vc(a){var b=W(a,{parent:!0}).node;a=rb(a);var c=Jb(b,a),d=mc(b,a,!0);if(d)throw new T(d);if(!b.Ta.rmdir)throw new T(63);if(c.qb)throw new T(10);b.Ta.rmdir(b,a);Wb(c)} +function Ba(a){var b=W(a,{parent:!0}).node;if(!b)throw new T(44);a=rb(a);var c=Jb(b,a),d=mc(b,a,!1);if(d)throw new T(d);if(!b.Ta.unlink)throw new T(63);if(c.qb)throw new T(10);b.Ta.unlink(b,a);Wb(c)}function wc(a,b){a=W(a,{pb:!b}).node;return nc(a.Ta.bb)(a)}function xc(a,b,c,d){qc(a,b,{mode:c&4095|b.mode&-4096,ctime:Date.now(),cc:d})}function oa(a,b){a="string"==typeof a?W(a,{pb:!0}).node:a;xc(null,a,b)} +function yc(a,b,c){if(V(b.mode))throw new T(31);if(32768!==(b.mode&61440))throw new T(28);var d=jc(b,"w");if(d)throw new T(d);qc(a,b,{size:c,timestamp:Date.now()})} +function ra(a,b,c=438){if(""===a)throw new T(44);if("string"==typeof b){var d={r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090}[b];if("undefined"==typeof d)throw Error(`Unknown file open mode: ${b}`);b=d}c=b&64?c&4095|32768:0;if("object"==typeof a)d=a;else{var f=a.endsWith("/");a=W(a,{pb:!(b&131072),nc:!0});d=a.node;a=a.path}var k=!1;if(b&64)if(d){if(b&128)throw new T(20);}else{if(f)throw new T(31);d=sc(a,c|511,0);k=!0}if(!d)throw new T(44);8192===(d.mode&61440)&&(b&=-513);if(b&65536&&!V(d.mode))throw new T(54); +if(!k&&(f=d?40960===(d.mode&61440)?32:V(d.mode)&&("r"!==kc(b)||b&576)?31:jc(d,kc(b)):44))throw new T(f);b&512&&!k&&(f=d,f="string"==typeof f?W(f,{pb:!0}).node:f,yc(null,f,0));b&=-131713;f=oc({node:d,path:ka(d),flags:b,seekable:!0,position:0,Ua:d.Ua,pc:[],error:!1});f.Ua.open&&f.Ua.open(f);k&&oa(d,c&511);!l.logReadFiles||b&1||a in fc||(fc[a]=1);return f}function ta(a){if(null===a.fd)throw new T(8);a.Hb&&(a.Hb=null);try{a.Ua.close&&a.Ua.close(a)}catch(b){throw b;}finally{ac[a.fd]=null}a.fd=null} +function zc(a,b,c){if(null===a.fd)throw new T(8);if(!a.seekable||!a.Ua.gb)throw new T(70);if(0!=c&&1!=c&&2!=c)throw new T(28);a.position=a.Ua.gb(a,b,c);a.pc=[]}function Ac(a,b,c,d,f){if(0>d||0>f)throw new T(28);if(null===a.fd)throw new T(8);if(1===(a.flags&2097155))throw new T(8);if(V(a.node.mode))throw new T(31);if(!a.Ua.read)throw new T(28);var k="undefined"!=typeof f;if(!k)f=a.position;else if(!a.seekable)throw new T(70);b=a.Ua.read(a,b,c,d,f);k||(a.position+=b);return b} +function sa(a,b,c,d,f){if(0>d||0>f)throw new T(28);if(null===a.fd)throw new T(8);if(0===(a.flags&2097155))throw new T(8);if(V(a.node.mode))throw new T(31);if(!a.Ua.write)throw new T(28);a.seekable&&a.flags&1024&&zc(a,0,2);var k="undefined"!=typeof f;if(!k)f=a.position;else if(!a.seekable)throw new T(70);b=a.Ua.write(a,b,c,d,f,void 0);k||(a.position+=b);return b} +function Aa(a){var b=b||0;var c="binary";"utf8"!==c&&"binary"!==c&&Ya(`Invalid encoding type "${c}"`);b=ra(a,b);a=wc(a).size;var d=new Uint8Array(a);Ac(b,d,0,a,0);"utf8"===c&&(d=vb(d));ta(b);return d} +function Bc(a,b,c){a=la("/dev/"+a);var d=ma(!!b,!!c);Bc.Ub??(Bc.Ub=64);var f=Bc.Ub++<<8|0;Ab(f,{open(k){k.seekable=!1},close(){c?.buffer?.length&&c(10)},read(k,p,n,z){for(var w=0,A=0;A>2]=b.dev;R[a+4>>2]=b.mode;R[a+8>>2]=b.nlink;R[a+12>>2]=b.uid;R[a+16>>2]=b.gid;R[a+20>>2]=b.rdev;S[a+24>>3]=BigInt(b.size);P[a+32>>2]=4096;P[a+36>>2]=b.blocks;var c=b.atime.getTime(),d=b.mtime.getTime(),f=b.ctime.getTime();S[a+40>>3]=BigInt(Math.floor(c/1E3));R[a+48>>2]=c%1E3*1E6;S[a+56>>3]=BigInt(Math.floor(d/1E3));R[a+64>>2]=d%1E3*1E6;S[a+72>>3]=BigInt(Math.floor(f/1E3));R[a+80>>2]=f%1E3*1E6;S[a+88>>3]=BigInt(b.ino);return 0} +var Oc=void 0,md=()=>{var a=P[+Oc>>2];Oc+=4;return a},nd=0,od=[0,31,60,91,121,152,182,213,244,274,305,335],pd=[0,31,59,90,120,151,181,212,243,273,304,334],qd={},rd=a=>{Sa=a;mb||0{if(!Ra)try{a()}catch(b){b instanceof cb||"unwind"==b||Da(1,b)}finally{if(!(mb||0{if(!ud){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(globalThis.navigator?.language?? +"C").replace("-","_")+".UTF-8",_:Ca||"./this.program"},b;for(b in td)void 0===td[b]?delete a[b]:a[b]=td[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);ud=c}return ud},ud,wd=(a,b,c,d)=>{var f={string:w=>{var A=0;if(null!==w&&void 0!==w&&0!==w){A=xb(w)+1;var N=ua(A);E(w,F,N,A);A=N}return A},array:w=>{var A=ua(w.length);x.set(w,A);return A}};a=l["_"+a];var k=[],p=0;if(d)for(var n=0;n{var b=xb(a)+1,c=ia(b);c&&E(a,F,c,b);return c},xd,yd=[],H=a=>{xd.delete(zd.get(a));zd.set(a,null);yd.push(a)},Ad=a=>{const b=a.length;return[b%128|128,b>>7,...a]},Bd={i:127,p:127,j:126,f:125,d:124,e:111},Cd=a=>Ad(Array.from(a,b=>Bd[b])),K=(a,b)=>{if(!xd){xd=new WeakMap;var c=zd.length;if(xd)for(var d=0;d<0+c;d++){var f=zd.get(d);f&&xd.set(f,d)}}if(c=xd.get(a)||0)return c;c=yd.length?yd.pop():zd.grow(1);try{zd.set(c,a)}catch(k){if(!(k instanceof TypeError))throw k; +b=Uint8Array.of(0,97,115,109,1,0,0,0,1,...Ad([1,96,...Cd(b.slice(1)),...Cd("v"===b[0]?"":b[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);b=new WebAssembly.Module(b);b=(new WebAssembly.Instance(b,{e:{f:a}})).exports.f;zd.set(c,b)}xd.set(a,c);return c};cc=Array(4096);rc(U,"/");Y("/tmp");Y("/home");Y("/home/web_user"); +(function(){Y("/dev");Ab(259,{read:()=>0,write:(d,f,k,p)=>p,gb:()=>0});tc("/dev/null",259);zb(1280,Cb);zb(1536,Db);tc("/dev/tty",1280);tc("/dev/tty1",1536);var a=new Uint8Array(1024),b=0,c=()=>{0===b&&(tb(a),b=a.byteLength);return a[--b]};Bc("random",c);Bc("urandom",c);Y("/dev/shm");Y("/dev/shm/tmp")})(); +(function(){Y("/proc");var a=Y("/proc/self");Y("/proc/self/fd");rc({kb(){var b=Ib(a,"fd",16895,73);b.Ua={gb:U.Ua.gb};b.Ta={lookup(c,d){c=+d;var f=X(c);c={parent:null,kb:{Vb:"fake"},Ta:{readlink:()=>f.path},id:c+1};return c.parent=c},readdir(){return Array.from(ac.entries()).filter(([,c])=>c).map(([c])=>c.toString())}};return b}},"/proc/self/fd")})();l.noExitRuntime&&(mb=l.noExitRuntime);l.print&&(Ja=l.print);l.printErr&&(Pa=l.printErr);l.wasmBinary&&(Qa=l.wasmBinary);l.thisProgram&&(Ca=l.thisProgram); +if(l.preInit)for("function"==typeof l.preInit&&(l.preInit=[l.preInit]);0va();l.stackRestore=a=>za(a);l.stackAlloc=a=>ua(a);l.cwrap=(a,b,c,d)=>{var f=!c||c.every(k=>"number"===k||"boolean"===k);return"string"!==b&&f&&!d?l["_"+a]:(...k)=>wd(a,b,c,k)};l.addFunction=K;l.removeFunction=H;l.UTF8ToString=C;l.stringToUTF8=(a,b,c)=>E(a,F,b,c);l.stringToNewUTF8=ja;l.writeArrayToMemory=(a,b)=>{x.set(a,b)}; +var ia,q,Yb,Dd,za,ua,va,Xa,zd,Ed={a:(a,b,c,d)=>Ya(`Assertion failed: ${C(a)}, at: `+[b?C(b):"unknown filename",c,d?C(d):"unknown function"]),i:function(a,b){try{return a=C(a),oa(a,b),0}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return-c.Xa}},L:function(a,b,c){try{b=C(b);b=Cc(a,b);if(c&-8)return-28;var d=W(b,{pb:!0}).node;if(!d)return-44;a="";c&4&&(a+="r");c&2&&(a+="w");c&1&&(a+="x");return a&&jc(d,a)?-2:0}catch(f){if("undefined"==typeof Z||"ErrnoError"!==f.name)throw f;return-f.Xa}}, +j:function(a,b){try{var c=X(a);xc(c,c.node,b,!1);return 0}catch(d){if("undefined"==typeof Z||"ErrnoError"!==d.name)throw d;return-d.Xa}},h:function(a){try{var b=X(a);qc(b,b.node,{timestamp:Date.now(),cc:!1});return 0}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return-c.Xa}},b:function(a,b,c){Oc=c;try{var d=X(a);switch(b){case 0:var f=md();if(0>f)break;for(;ac[f];)f++;return pc(d,f).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return f=md(),d.flags|=f,0;case 12:return f= +md(),Ta[f+0>>1]=2,0;case 13:case 14:return 0}return-28}catch(k){if("undefined"==typeof Z||"ErrnoError"!==k.name)throw k;return-k.Xa}},g:function(a,b){try{var c=X(a),d=c.node,f=c.Ua.bb;a=f?c:d;f??=d.Ta.bb;nc(f);var k=f(a);return Dc(b,k)}catch(p){if("undefined"==typeof Z||"ErrnoError"!==p.name)throw p;return-p.Xa}},H:function(a,b){b=-9007199254740992>b||9007199254740992b||0===(c.flags&2097155))throw new T(28);yc(c,c.node,b);return 0}catch(d){if("undefined"== +typeof Z||"ErrnoError"!==d.name)throw d;return-d.Xa}},G:function(a,b){try{if(0===b)return-28;var c=xb("/")+1;if(b=d)return-28;var f=W(b).node;if(!f)throw new T(44);if(!f.Ta.readlink)throw new T(28);var k=f.Ta.readlink(f);var p=Math.min(d,xb(k)),n=x[c+p]; +E(k,F,c,d+1);x[c+p]=n;return p}catch(z){if("undefined"==typeof Z||"ErrnoError"!==z.name)throw z;return-z.Xa}},u:function(a){try{return a=C(a),vc(a),0}catch(b){if("undefined"==typeof Z||"ErrnoError"!==b.name)throw b;return-b.Xa}},f:function(a,b){try{return a=C(a),Dc(b,wc(a))}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return-c.Xa}},r:function(a,b,c){try{b=C(b);b=Cc(a,b);if(c)if(512===c)vc(b);else return-28;else Ba(b);return 0}catch(d){if("undefined"==typeof Z||"ErrnoError"!==d.name)throw d; +return-d.Xa}},q:function(a,b,c){try{b=C(b);b=Cc(a,b,!0);var d=Date.now(),f,k;if(c){var p=R[c>>2]+4294967296*P[c+4>>2],n=P[c+8>>2];1073741823==n?f=d:1073741822==n?f=null:f=1E3*p+n/1E6;c+=16;p=R[c>>2]+4294967296*P[c+4>>2];n=P[c+8>>2];1073741823==n?k=d:1073741822==n?k=null:k=1E3*p+n/1E6}else k=f=d;if(null!==(k??f)){a=f;var z=W(b,{pb:!0}).node;nc(z.Ta.eb)(z,{atime:a,mtime:k})}return 0}catch(w){if("undefined"==typeof Z||"ErrnoError"!==w.name)throw w;return-w.Xa}},m:()=>Ya(""),l:()=>{mb=!1;nd=0},A:function(a, +b){a=-9007199254740992>a||9007199254740992>2]=a.getSeconds();P[b+4>>2]=a.getMinutes();P[b+8>>2]=a.getHours();P[b+12>>2]=a.getDate();P[b+16>>2]=a.getMonth();P[b+20>>2]=a.getFullYear()-1900;P[b+24>>2]=a.getDay();var c=a.getFullYear();P[b+28>>2]=(0!==c%4||0===c%100&&0!==c%400?pd:od)[a.getMonth()]+a.getDate()-1|0;P[b+36>>2]=-(60*a.getTimezoneOffset());c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();var d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset(); +P[b+32>>2]=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0},y:function(a,b,c,d,f,k,p){f=-9007199254740992>f||9007199254740992>2]=z.Wb;R[p>>2]=w;return 0}catch(A){if("undefined"==typeof Z||"ErrnoError"!==A.name)throw A;return-A.Xa}},z:function(a,b,c,d,f,k){k=-9007199254740992>k|| +9007199254740992{qd[a]&&(clearTimeout(qd[a].id),delete qd[a]);if(!b)return 0;var c=setTimeout(()=>{delete qd[a];sd(()=>Dd(a,performance.now()))},b);qd[a]={id:c,Dc:b};return 0},B:(a,b,c,d)=>{var f=(new Date).getFullYear(),k=(new Date(f,0,1)).getTimezoneOffset(); +f=(new Date(f,6,1)).getTimezoneOffset();R[a>>2]=60*Math.max(k,f);P[b>>2]=Number(k!=f);b=p=>{var n=Math.abs(p);return`UTC${0<=p?"-":"+"}${String(Math.floor(n/60)).padStart(2,"0")}${String(n%60).padStart(2,"0")}`};a=b(k);b=b(f);fDate.now(),s:()=>2147483648,c:()=>performance.now(),o:a=>{var b=F.length;a>>>=0;if(2147483648=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);a:{d=(Math.min(2147483648,65536*Math.ceil(Math.max(a, +d)/65536))-Xa.buffer.byteLength+65535)/65536|0;try{Xa.grow(d);Wa();var f=1;break a}catch(k){}f=void 0}if(f)return!0}return!1},E:(a,b)=>{var c=0,d=0,f;for(f of vd()){var k=b+c;R[a+d>>2]=k;c+=E(f,F,k,Infinity)+1;d+=4}return 0},F:(a,b)=>{var c=vd();R[a>>2]=c.length;a=0;for(var d of c)a+=xb(d)+1;R[b>>2]=a;return 0},e:function(a){try{var b=X(a);ta(b);return 0}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return c.Xa}},p:function(a,b){try{var c=X(a);x[b]=c.tty?2:V(c.mode)?3:40960===(c.mode& +61440)?7:4;Ta[b+2>>1]=0;S[b+8>>3]=BigInt(0);S[b+16>>3]=BigInt(0);return 0}catch(d){if("undefined"==typeof Z||"ErrnoError"!==d.name)throw d;return d.Xa}},w:function(a,b,c,d){try{a:{var f=X(a);a=b;for(var k,p=b=0;p>2],z=R[a+4>>2];a+=8;var w=Ac(f,x,n,z,k);if(0>w){var A=-1;break a}b+=w;if(w>2]=A;return 0}catch(N){if("undefined"==typeof Z||"ErrnoError"!==N.name)throw N;return N.Xa}},D:function(a,b,c,d){b=-9007199254740992>b||9007199254740992< +b?NaN:Number(b);try{if(isNaN(b))return 61;var f=X(a);zc(f,b,c);S[d>>3]=BigInt(f.position);f.Hb&&0===b&&0===c&&(f.Hb=null);return 0}catch(k){if("undefined"==typeof Z||"ErrnoError"!==k.name)throw k;return k.Xa}},I:function(a){try{var b=X(a);return b.Ua?.fsync?.(b)}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return c.Xa}},t:function(a,b,c,d){try{a:{var f=X(a);a=b;for(var k,p=b=0;p>2],z=R[a+4>>2];a+=8;var w=sa(f,x,n,z,k);if(0>w){var A=-1;break a}b+=w;if(w>2]=A;return 0}catch(N){if("undefined"==typeof Z||"ErrnoError"!==N.name)throw N;return N.Xa}},k:rd}; +function Fd(){function a(){l.calledRun=!0;if(!Ra){if(!l.noFSInit&&!dc){var b,c;dc=!0;b??=l.stdin;c??=l.stdout;d??=l.stderr;b?Bc("stdin",b):uc("/dev/tty","/dev/stdin");c?Bc("stdout",null,c):uc("/dev/tty","/dev/stdout");d?Bc("stderr",null,d):uc("/dev/tty1","/dev/stderr");ra("/dev/stdin",0);ra("/dev/stdout",1);ra("/dev/stderr",1)}Gd.N();ec=!1;l.onRuntimeInitialized?.();if(l.postRun)for("function"==typeof l.postRun&&(l.postRun=[l.postRun]);l.postRun.length;){var d=l.postRun.shift();eb.push(d)}db(eb)}} +if(0{setTimeout(()=>l.setStatus(""),1);a()},1)):a()}}var Gd; +(async function(){function a(c){c=Gd=c.exports;l._sqlite3_free=c.P;l._sqlite3_value_text=c.Q;l._sqlite3_prepare_v2=c.R;l._sqlite3_step=c.S;l._sqlite3_reset=c.T;l._sqlite3_exec=c.U;l._sqlite3_finalize=c.V;l._sqlite3_column_name=c.W;l._sqlite3_column_text=c.X;l._sqlite3_column_type=c.Y;l._sqlite3_errmsg=c.Z;l._sqlite3_clear_bindings=c._;l._sqlite3_value_blob=c.$;l._sqlite3_value_bytes=c.aa;l._sqlite3_value_double=c.ba;l._sqlite3_value_int=c.ca;l._sqlite3_value_type=c.da;l._sqlite3_result_blob=c.ea; +l._sqlite3_result_double=c.fa;l._sqlite3_result_error=c.ga;l._sqlite3_result_int=c.ha;l._sqlite3_result_int64=c.ia;l._sqlite3_result_null=c.ja;l._sqlite3_result_text=c.ka;l._sqlite3_aggregate_context=c.la;l._sqlite3_column_count=c.ma;l._sqlite3_data_count=c.na;l._sqlite3_column_blob=c.oa;l._sqlite3_column_bytes=c.pa;l._sqlite3_column_double=c.qa;l._sqlite3_bind_blob=c.ra;l._sqlite3_bind_double=c.sa;l._sqlite3_bind_int=c.ta;l._sqlite3_bind_text=c.ua;l._sqlite3_bind_parameter_index=c.va;l._sqlite3_sql= +c.wa;l._sqlite3_normalized_sql=c.xa;l._sqlite3_changes=c.ya;l._sqlite3_close_v2=c.za;l._sqlite3_progress_handler=c.Aa;l._sqlite3_interrupt=c.Ba;l._sqlite3_create_function_v2=c.Ca;l._sqlite3_update_hook=c.Da;l._sqlite3_open=c.Ea;l._sqlite3_get_autocommit=c.Fa;ia=l._malloc=c.Ga;q=l._free=c.Ha;l._RegisterExtensionFunctions=c.Ia;l._sqljs_vfs_register=c.Ja;l._sqljs_open_paged=c.Ka;l._sqljs_vfs_register_rw=c.La;l._sqljs_open_paged_rw=c.Ma;l._sqlite_explorer_register_query_plan=c.Na;Yb=c.Oa;Dd=c.Pa;za=c.Qa; +ua=c.Ra;va=c.Sa;Xa=c.M;zd=c.O;Wa();kb--;l.monitorRunDependencies?.(kb);0==kb&&lb&&(c=lb,lb=null,c());return Gd}kb++;l.monitorRunDependencies?.(kb);var b={a:Ed};if(l.instantiateWasm)return new Promise(c=>{l.instantiateWasm(b,(d,f)=>{c(a(d,f))})});Za??=l.locateFile?l.locateFile("sql-wasm.wasm",Fa):Fa+"sql-wasm.wasm";return a((await bb(b)).instance)})();Fd(); // The shell-pre.js and emcc-generated code goes above diff --git a/website/public/sqlite-viewer/sql-wasm.js b/website/public/sqlite-viewer/sql-wasm.js index be68699c..7b99b37d 100644 --- a/website/public/sqlite-viewer/sql-wasm.js +++ b/website/public/sqlite-viewer/sql-wasm.js @@ -69,111 +69,112 @@ var initSqlJs = function (moduleConfig) { // The emcc-generated code and shell-post.js code goes below, // meaning that all of it runs inside of this promise. If anything throws an exception, our promise will abort -var m;m||=typeof Module != 'undefined' ? Module : {};var ca=!!globalThis.window,da=!!globalThis.WorkerGlobalScope,ea=globalThis.process?.versions?.node&&"renderer"!=globalThis.process?.type; -m.onRuntimeInitialized=function(){function a(e,g){Fb(e,g instanceof Error?g.message:String(g),-1)}function b(e,g){switch(typeof g){case "boolean":Dc(e,g?1:0);break;case "number":Ec(e,g);break;case "string":Fc(e,g,-1,-1);break;case "object":if(null===g)Gb(e);else if(null!=g.length){var k=fa(g.length);p.set(g,k);Gc(e,k,g.length,-1);ia(k)}else Fb(e,"Wrong API use : tried to return a value of an unknown type ("+g+").",-1);break;default:Gb(e)}}function c(e,g){for(var k=[],n=0;n>>0);if(null!=e){var g=this.filename,k="/",n=g;k&&(k="string"==typeof k?k:ka(k),n=g?la(k+"/"+g):k);g=ma(!0,!0);n=na(n,g);if(e){if("string"==typeof e){k=Array(e.length);for(var q=0,r=e.length;qn||!Number.isSafeInteger(n))return-1;try{if(e){a:{var r=e.chunkSize,y=e.cb-n;var t=0;var E=n;var D,I;for(y>k&&(y=k);ty-t&&(M=y-t);if(D=e.mb.get(Q))C.set(D.subarray(O,O+M),g+t);else{var J=e.nb-E;J>M&&(J=M);if(0J&&(I=I.subarray(0,J),ha=J);0J&&C.fill(0, -g+t+J,g+t+M)}t+=M;E+=M}qa=t}return qa}t=q.read(n,k);if(null==t)return 0;E=t.length;E>k&&(t=t.subarray(0,k),E=k);C.set(t,g);return E}catch(La){return-1}}function A(e){var g=Z[e];e=aa[e];if(!g)return-1;if(e)return e.cb;try{var k=g.size()}catch(n){return-1}return"number"!==typeof k||0>k||!Number.isSafeInteger(k)?-1:k}function N(e,g){var k=e.chunkSize,n=[];g=g?n.push(r):y+k>g&&q.fill(0,g-y)}),n.forEach(function(q){e.mb.delete(q)}),gn||!Number.isSafeInteger(n)||0>k)return-1;try{for(var r=e.chunkSize,y=n,t=0,E,D,I,Q,O;tk-t&&(Q=k-t);O=e.mb.get(E);if(!O){O=new Uint8Array(r);if(Q=ba)){ba>qa.length&&(ba=qa.length);M=(J=ha.read(La,ba))?J.length:0;M>ba&&(J=J.subarray(0,ba),M=ba);if(Me.cb&&(e.cb=n+k);return 0}catch(Gd){return-1}}function Pc(e,g){e=aa[e];if(!e)return-1;g=Number(g);if(0>g||!Number.isSafeInteger(g))return-1;try{return N(e,g),0}catch(k){return-1}}function Lb(){throw Error("paged databases are read-only snapshots; export() is only available on openPagedWritable instances");}function Mb(){var e,g,k;if(null===this.db)throw Error("Database closed");if(0===Nb(this.db))throw Error("cannot export a paged database while a transaction is open; COMMIT or ROLLBACK first"); -var n=aa[this.tb];var q=Z[this.tb];var r=n.chunkSize;var y=new Uint8Array(n.cb);for(e=0;en.cb-e&&(t=n.cb-e);if(g=n.mb.get(e/r))y.set(g.subarray(0,t),e);else if(g=n.nb-e,g>t&&(g=t),0g&&(k=k.subarray(0,g));if(!k||k.lengthNumber.MAX_SAFE_INTEGER)throw"rowId too big to fit inside a Number";e(g,n,q,Number(r))},"viiiij");Tb(this.db,this.ib,0);return this};var Z={},aa={},Na=1,ra=null,Oa=null,ib=null,Wb=null;l.openPaged=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPaged requires a hostIo object with read(offset, length) and size() functions");null===ra&&(ra=G(x,"iiiij"),Oa=G(A,"di"));var g=Ub(ra, -Oa);if(0!==g)throw Error("could not register the sqljs_host VFS (error code "+g+")");var k=Na;Na+=1;Z[k]=e;try{g=hd(k,L);var n=w(L,"i32");if(0!==g){var q=0!==n?hb(n):"SQLite error "+g;0!==n&&xa(n);throw Error(q);}}catch(r){throw delete Z[k],r;}e=Object.create(l.prototype);e.db=n;e.filename=null;e.tb=k;e.lb={};e.$a=new Map;Ka(e.db);e.Eb=Lb;e["export"]=Lb;e.close=Ma;e.close=Ma;return e};l.openPagedWritable=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPagedWritable requires a hostIo object with read(offset, length) and size() functions"); -var g=e.size();if("number"!==typeof g||0>g||!Number.isSafeInteger(g))throw Error("hostIo.size() must return a non-negative byte count");null===ra&&(ra=G(x,"iiiij"),Oa=G(A,"di"));null===ib&&(ib=G(Kb,"iiiij"),Wb=G(Pc,"iij"));var k=Ub(ra,Oa);0===k&&(k=jd(ib,Wb));if(0!==k)throw Error("could not register the sqljs_host VFS (error code "+k+")");var n=Na;Na+=1;Z[n]=e;a:{try{var q=e.read(16,2)}catch(t){e=4096;break a}!q||2>q.length?e=4096:(e=256*q[0]+q[1],e=1===e?65536:512<=e&&32768>=e&&0===(e&e-1)?e:4096)}aa[n]= -{chunkSize:e,mb:new Map,cb:g,nb:g};try{k=kd(n,L);var r=w(L,"i32");if(0!==k){var y=0!==r?hb(r):"SQLite error "+k;0!==r&&xa(r);throw Error(y);}}catch(t){throw delete Z[n],delete aa[n],t;}k=Object.create(l.prototype);k.db=r;k.filename=null;k.tb=n;k.lb={};k.$a=new Map;Ka(k.db);k.Eb=Mb;k["export"]=Mb;k.xc=Ob;k.exportPagedWritableOverlay=Ob;k.close=Ma;k.close=Ma;return k};d.prototype.bind=d.prototype.bind;d.prototype.step=d.prototype.step;d.prototype.get=d.prototype.get;d.prototype.getColumnNames=d.prototype.Pb; -d.prototype.getAsObject=d.prototype.Ob;d.prototype.getSQL=d.prototype.hc;d.prototype.getNormalizedSQL=d.prototype.dc;d.prototype.run=d.prototype.run;d.prototype.reset=d.prototype.reset;d.prototype.freemem=d.prototype.freemem;d.prototype.free=d.prototype.fb;h.prototype.next=h.prototype.next;h.prototype.getRemainingSQL=h.prototype.ec;l.prototype.run=l.prototype.run;l.prototype.exec=l.prototype.exec;l.prototype.each=l.prototype.bc;l.prototype.prepare=l.prototype.Ib;l.prototype.iterateStatements=l.prototype.kc; -l.prototype["export"]=l.prototype.Eb;l.prototype.close=l.prototype.close;l.prototype.handleError=l.prototype.handleError;l.prototype.getRowsModified=l.prototype.fc;l.prototype.progress_handler=l.prototype.nc;l.prototype.interrupt=l.prototype.jc;l.prototype.create_function=l.prototype.$b;l.prototype.create_aggregate=l.prototype.Zb;l.prototype.updateHook=l.prototype.qc;m.Database=l};var Ca="./this.program",Da=(a,b)=>{throw b;},Ea=globalThis.document?.currentScript?.src; -"undefined"!=typeof __filename?Ea=__filename:da&&(Ea=self.location.href);var Fa="",Ga,Ha; -if(ea){var fs=require("node:fs");Fa=__dirname+"/";Ha=a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a)};Ga=async a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a,void 0)};1{process.exitCode=a;throw b;}}else if(ca||da){try{Fa=(new URL(".",Ea)).href}catch{}da&&(Ha=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}); -Ga=async a=>{if(Ia(a))return new Promise((c,d)=>{var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?c(f.response):d(f.status)};f.onerror=d;f.send(null)});var b=await fetch(a,{credentials:"same-origin"});if(b.ok)return b.arrayBuffer();throw Error(b.status+" : "+b.url);}}var Ja=console.log.bind(console),Pa=console.error.bind(console),Qa,Ra=!1,Sa,Ia=a=>a.startsWith("file://"),p,C,Ta,H,K,Ua,Va,P; -function Wa(){var a=Xa.buffer;p=new Int8Array(a);Ta=new Int16Array(a);C=new Uint8Array(a);new Uint16Array(a);H=new Int32Array(a);K=new Uint32Array(a);Ua=new Float32Array(a);Va=new Float64Array(a);P=new BigInt64Array(a);new BigUint64Array(a)}function Ya(a){m.onAbort?.(a);a="Aborted("+a+")";Pa(a);Ra=!0;throw new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");}var Za; +var l;l||=typeof Module != 'undefined' ? Module : {};var da=!!globalThis.window,ea=!!globalThis.WorkerGlobalScope,fa=globalThis.process?.versions?.node&&"renderer"!=globalThis.process?.type; +l.onRuntimeInitialized=function(){function a(e,g){Fb(e,g instanceof Error?g.message:String(g),-1)}function b(e,g){switch(typeof g){case "boolean":Ec(e,g?1:0);break;case "number":Fc(e,g);break;case "string":g=d(g);Gc(e,g.ub,g.size,-1);q(g.ub);break;case "object":if(null===g)Gb(e);else if(null!=g.length){var h=ia(g.length);x.set(g,h);Hc(e,h,g.length,-1);q(h)}else Fb(e,"Wrong API use : tried to return a value of an unknown type ("+g+").",-1);break;default:Gb(e)}}function c(e,g){for(var h=[],m=0;m=m?g+=1:2047>=m?g+=2:65535>=m?g+=3:(g+=4,h+=1)}h=ia(g+1);if(!h)throw Error("Out of memory while copying a string");e=E(e,F,h,g+1);if(e!==g)throw q(h),Error("UTF-8 length mismatch: counted "+g+" bytes, wrote "+ +e);return{ub:h,size:g}}function f(e,g){this.Ya=e;this.db=g;this.Wa=1;this.Db=[];this.ob=null;this.vb=!1}function k(e){if(null===e.ob){e.ob=[];for(var g=Mc(e.Ya),h=0;h>>0);if(null!=e){var g=this.filename,h="/",m=g;h&&(h="string"==typeof h?h: +ka(h),m=g?la(h+"/"+g):h);g=ma(!0,!0);m=na(m,g);if(e){if("string"==typeof e){h=Array(e.length);for(var r=0,t=e.length;rm||!Number.isSafeInteger(m))return-1; +try{if(e){a:{var t=e.chunkSize,y=e.cb-m;var u=0;var G=m;var D,I;for(y>h&&(y=h);uy-u&&(M=y-u);if(D=e.mb.get(Q))F.set(D.subarray(O,O+M),g+u);else{var J=e.nb-G;J>M&&(J=M);if(0J&&(I=I.subarray(0,J),ha=J);0J&&F.fill(0,g+u+J,g+u+M)}u+=M;G+=M}pa=u}return pa}u=r.read(m,h);if(null==u)return 0;G=u.length;G>h&&(u=u.subarray(0,h),G=h);F.set(u,g);return G}catch(La){return-1}} +function N(e){var g=aa[e];e=ba[e];if(!g)return-1;if(e)return e.cb;try{var h=g.size()}catch(m){return-1}return"number"!==typeof h||0>h||!Number.isSafeInteger(h)?-1:h}function Lb(e,g){var h=e.chunkSize,m=[];g=g?m.push(t):y+h>g&&r.fill(0,g-y)}),m.forEach(function(r){e.mb.delete(r)}),gm||!Number.isSafeInteger(m)||0>h)return-1;try{for(var t=e.chunkSize,y=m, +u=0,G,D,I,Q,O;uh-u&&(Q=h-u);O=e.mb.get(G);if(!O){O=new Uint8Array(t);if(Q=ca)){ca>pa.length&&(ca=pa.length);M=(J=ha.read(La,ca))?J.length:0;M>ca&&(J=J.subarray(0,ca),M=ca);if(Me.cb&&(e.cb=m+h);return 0}catch(Hd){return-1}}function Qc(e,g){e=ba[e];if(!e)return-1; +g=Number(g);if(0>g||!Number.isSafeInteger(g))return-1;try{return Lb(e,g),0}catch(h){return-1}}function Mb(){throw Error("paged databases are read-only snapshots; export() is only available on openPagedWritable instances");}function Nb(){var e,g,h;if(null===this.db)throw Error("Database closed");if(0===Ob(this.db))throw Error("cannot export a paged database while a transaction is open; COMMIT or ROLLBACK first");var m=ba[this.tb];var r=aa[this.tb];var t=m.chunkSize;var y=new Uint8Array(m.cb);for(e= +0;em.cb-e&&(u=m.cb-e);if(g=m.mb.get(e/t))y.set(g.subarray(0,u),e);else if(g=m.nb-e,g>u&&(g=u),0g&&(h=h.subarray(0,g));if(!h||h.lengthNumber.MAX_SAFE_INTEGER)throw"rowId too big to fit inside a Number";e(g,m,r,Number(t))},"viiiij");Ub(this.db,this.ib,0);return this};var aa={},ba={},Na=1,qa=null,Oa=null,ib=null,Xb=null;n.openPaged=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPaged requires a hostIo object with read(offset, length) and size() functions");null===qa&&(qa=K(A,"iiiij"),Oa=K(N,"di"));var g=Vb(qa,Oa);if(0!==g)throw Error("could not register the sqljs_host VFS (error code "+ +g+")");var h=Na;Na+=1;aa[h]=e;try{g=jd(h,L);var m=B(L,"i32");if(0!==g){var r=0!==m?hb(m):"SQLite error "+g;0!==m&&ya(m);throw Error(r);}}catch(t){throw delete aa[h],t;}e=Object.create(n.prototype);e.db=m;e.filename=null;e.tb=h;e.lb={};e.$a=new Map;Ka(e.db);e.Fb=Mb;e["export"]=Mb;e.close=Ma;e.close=Ma;return e};n.openPagedWritable=function(e){if(!e||"function"!==typeof e.read||"function"!==typeof e.size)throw Error("openPagedWritable requires a hostIo object with read(offset, length) and size() functions"); +var g=e.size();if("number"!==typeof g||0>g||!Number.isSafeInteger(g))throw Error("hostIo.size() must return a non-negative byte count");null===qa&&(qa=K(A,"iiiij"),Oa=K(N,"di"));null===ib&&(ib=K(Pc,"iiiij"),Xb=K(Qc,"iij"));var h=Vb(qa,Oa);0===h&&(h=kd(ib,Xb));if(0!==h)throw Error("could not register the sqljs_host VFS (error code "+h+")");var m=Na;Na+=1;aa[m]=e;a:{try{var r=e.read(16,2)}catch(u){e=4096;break a}!r||2>r.length?e=4096:(e=256*r[0]+r[1],e=1===e?65536:512<=e&&32768>=e&&0===(e&e-1)?e:4096)}ba[m]= +{chunkSize:e,mb:new Map,cb:g,nb:g};try{h=ld(m,L);var t=B(L,"i32");if(0!==h){var y=0!==t?hb(t):"SQLite error "+h;0!==t&&ya(t);throw Error(y);}}catch(u){throw delete aa[m],delete ba[m],u;}h=Object.create(n.prototype);h.db=t;h.filename=null;h.tb=m;h.lb={};h.$a=new Map;Ka(h.db);h.Fb=Nb;h["export"]=Nb;h.xc=Pb;h.exportPagedWritableOverlay=Pb;h.close=Ma;h.close=Ma;return h};f.prototype.bind=f.prototype.bind;f.prototype.step=f.prototype.step;f.prototype.get=f.prototype.get;f.prototype.getColumnNames=f.prototype.Qb; +f.prototype.getAsObject=f.prototype.Pb;f.prototype.getSQL=f.prototype.jc;f.prototype.getNormalizedSQL=f.prototype.fc;f.prototype.run=f.prototype.run;f.prototype.reset=f.prototype.reset;f.prototype.freemem=f.prototype.freemem;f.prototype.free=f.prototype.fb;p.prototype.next=p.prototype.next;p.prototype.getRemainingSQL=p.prototype.hc;n.prototype.run=n.prototype.run;n.prototype.exec=n.prototype.exec;n.prototype.each=n.prototype.dc;n.prototype.prepare=n.prototype.Jb;n.prototype.iterateStatements=n.prototype.lc; +n.prototype["export"]=n.prototype.Fb;n.prototype.close=n.prototype.close;n.prototype.handleError=n.prototype.handleError;n.prototype.getRowsModified=n.prototype.ic;n.prototype.progress_handler=n.prototype.oc;n.prototype.interrupt=n.prototype.kc;n.prototype.create_function=n.prototype.bc;n.prototype.create_aggregate=n.prototype.ac;n.prototype.updateHook=n.prototype.qc;l.Database=n};var Ca="./this.program",Da=(a,b)=>{throw b;},Ea=globalThis.document?.currentScript?.src; +"undefined"!=typeof __filename?Ea=__filename:ea&&(Ea=self.location.href);var Fa="",Ga,Ha; +if(fa){var fs=require("node:fs");Fa=__dirname+"/";Ha=a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a)};Ga=async a=>{a=Ia(a)?new URL(a):a;return fs.readFileSync(a,void 0)};1{process.exitCode=a;throw b;}}else if(da||ea){try{Fa=(new URL(".",Ea)).href}catch{}ea&&(Ha=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}); +Ga=async a=>{if(Ia(a))return new Promise((c,d)=>{var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?c(f.response):d(f.status)};f.onerror=d;f.send(null)});var b=await fetch(a,{credentials:"same-origin"});if(b.ok)return b.arrayBuffer();throw Error(b.status+" : "+b.url);}}var Ja=console.log.bind(console),Pa=console.error.bind(console),Qa,Ra=!1,Sa,Ia=a=>a.startsWith("file://"),x,F,Ta,P,R,Ua,Va,S; +function Wa(){var a=Xa.buffer;x=new Int8Array(a);Ta=new Int16Array(a);F=new Uint8Array(a);new Uint16Array(a);P=new Int32Array(a);R=new Uint32Array(a);Ua=new Float32Array(a);Va=new Float64Array(a);S=new BigInt64Array(a);new BigUint64Array(a)}function Ya(a){l.onAbort?.(a);a="Aborted("+a+")";Pa(a);Ra=!0;throw new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");}var Za; async function $a(a){if(!Qa)try{var b=await Ga(a);return new Uint8Array(b)}catch{}if(a==Za&&Qa)a=new Uint8Array(Qa);else if(Ha)a=Ha(a);else throw"both async and sync fetching of the wasm failed";return a}async function ab(a,b){try{var c=await $a(a);return await WebAssembly.instantiate(c,b)}catch(d){Pa(`failed to asynchronously prepare wasm: ${d}`),Ya(d)}} -async function bb(a){var b=Za;if(!Qa&&!Ia(b)&&!ea)try{var c=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(c,a)}catch(d){Pa(`wasm streaming compile failed: ${d}`),Pa("falling back to ArrayBuffer instantiation")}return ab(b,a)}class cb{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}var db=a=>{for(;0{var a=m.preRun.shift();fb.push(a)},kb=0,lb=null; -function w(a,b="i8"){b.endsWith("*")&&(b="*");switch(b){case "i1":return p[a];case "i8":return p[a];case "i16":return Ta[a>>1];case "i32":return H[a>>2];case "i64":return P[a>>3];case "float":return Ua[a>>2];case "double":return Va[a>>3];case "*":return K[a>>2];default:Ya(`invalid type for getValue: ${b}`)}}var mb=!0; -function ya(a){var b="i32";b.endsWith("*")&&(b="*");switch(b){case "i1":p[a]=0;break;case "i8":p[a]=0;break;case "i16":Ta[a>>1]=0;break;case "i32":H[a>>2]=0;break;case "i64":P[a>>3]=BigInt(0);break;case "float":Ua[a>>2]=0;break;case "double":Va[a>>3]=0;break;case "*":K[a>>2]=0;break;default:Ya(`invalid type for setValue: ${b}`)}} -var nb=new TextDecoder,ob=(a,b,c,d)=>{c=b+c;if(d)return c;for(;a[b]&&!(b>=c);)++b;return b},F=(a,b,c)=>a?nb.decode(C.subarray(a,ob(C,a,b,c))):"",pb=(a,b)=>{for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a.splice(d,1):".."===f?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a},la=a=>{var b="/"===a.charAt(0),c="/"===a.slice(-1);(a=pb(a.split("/").filter(d=>!!d),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a},qb=a=>{var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1); -a=b[0];b=b[1];if(!a&&!b)return".";b&&=b.slice(0,-1);return a+b},rb=a=>a&&a.match(/([^\/]+|\/)\/*$/)[1],sb=()=>{if(ea){var a=require("node:crypto");return b=>a.randomFillSync(b)}return b=>crypto.getRandomValues(b)},tb=a=>{(tb=sb())(a)},ub=(...a)=>{for(var b="",c=!1,d=a.length-1;-1<=d&&!c;d--){c=0<=d?a[d]:"/";if("string"!=typeof c)throw new TypeError("Arguments to path.resolve must be strings");if(!c)return"";b=c+"/"+b;c="/"===c.charAt(0)}b=pb(b.split("/").filter(f=>!!f),!c).join("/");return(c?"/": -"")+b||"."},vb=a=>{var b=ob(a,0);return nb.decode(a.buffer?a.subarray(0,b):new Uint8Array(a.slice(0,b)))},wb=[],xb=a=>{for(var b=0,c=0;c=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}return b},R=(a,b,c,d)=>{if(!(0=l){if(c>=d)break;b[c++]=l}else if(2047>=l){if(c+1>=d)break;b[c++]=192|l>>6;b[c++]=128|l&63}else if(65535>=l){if(c+2>=d)break;b[c++]=224|l>>12;b[c++]=128| -l>>6&63;b[c++]=128|l&63}else{if(c+3>=d)break;b[c++]=240|l>>18;b[c++]=128|l>>12&63;b[c++]=128|l>>6&63;b[c++]=128|l&63;h++}}b[c]=0;return c-f},yb=[];function zb(a,b){yb[a]={input:[],output:[],sb:b};Ab(a,Bb)} -var Bb={open(a){var b=yb[a.node.rdev];if(!b)throw new S(43);a.tty=b;a.seekable=!1},close(a){a.tty.sb.fsync(a.tty)},fsync(a){a.tty.sb.fsync(a.tty)},read(a,b,c,d){if(!a.tty||!a.tty.sb.Rb)throw new S(60);for(var f=0,h=0;h=a.node.Za)return 0;a=Math.min(a.node.Za-f,d);if(8=h||(h=Math.max(h,l*(1048576>l?2:1.125)>>>0),0!=l&&(h=Math.max(h,256)),l=a.Va,a.Va=new Uint8Array(h),0b)throw new S(28); -return b},zb(a,b,c,d,f){if(32768!==(a.node.mode&61440))throw new S(43);a=a.node.Va;if(f&2||!a||a.buffer!==p.buffer){f=!0;d=65536*Math.ceil(b/65536);var h=Xb(65536,d);h&&C.fill(0,h,h+d);d=h;if(!d)throw new S(48);if(a){if(0{var c=0;a&&(c|=365);b&&(c|=146);return c},Yb=null,Zb={},$b=[],ac=1,bc=null,cc= -!1,dc=!0,ec={},S=class{name="ErrnoError";constructor(a){this.Xa=a}},fc=class{wb={};node=null;get flags(){return this.wb.flags}set flags(a){this.wb.flags=a}get position(){return this.wb.position}set position(a){this.wb.position=a}},gc=class{Ta={};Ua={};qb=null;constructor(a,b,c,d){a||=this;this.parent=a;this.kb=a.kb;this.id=ac++;this.name=b;this.mode=c;this.rdev=d;this.atime=this.mtime=this.ctime=Date.now()}get read(){return 365===(this.mode&365)}set read(a){a?this.mode|=365:this.mode&=-366}get write(){return 146=== +async function bb(a){var b=Za;if(!Qa&&!Ia(b)&&!fa)try{var c=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(c,a)}catch(d){Pa(`wasm streaming compile failed: ${d}`),Pa("falling back to ArrayBuffer instantiation")}return ab(b,a)}class cb{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}var db=a=>{for(;0{var a=l.preRun.shift();fb.push(a)},kb=0,lb=null; +function B(a,b="i8"){b.endsWith("*")&&(b="*");switch(b){case "i1":return x[a];case "i8":return x[a];case "i16":return Ta[a>>1];case "i32":return P[a>>2];case "i64":return S[a>>3];case "float":return Ua[a>>2];case "double":return Va[a>>3];case "*":return R[a>>2];default:Ya(`invalid type for getValue: ${b}`)}}var mb=!0; +function wa(a){var b="i32";b.endsWith("*")&&(b="*");switch(b){case "i1":x[a]=0;break;case "i8":x[a]=0;break;case "i16":Ta[a>>1]=0;break;case "i32":P[a>>2]=0;break;case "i64":S[a>>3]=BigInt(0);break;case "float":Ua[a>>2]=0;break;case "double":Va[a>>3]=0;break;case "*":R[a>>2]=0;break;default:Ya(`invalid type for setValue: ${b}`)}} +var nb=new TextDecoder,ob=(a,b,c,d)=>{c=b+c;if(d)return c;for(;a[b]&&!(b>=c);)++b;return b},C=(a,b,c)=>a?nb.decode(F.subarray(a,ob(F,a,b,c))):"",pb=(a,b)=>{for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a.splice(d,1):".."===f?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a},la=a=>{var b="/"===a.charAt(0),c="/"===a.slice(-1);(a=pb(a.split("/").filter(d=>!!d),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a},qb=a=>{var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1); +a=b[0];b=b[1];if(!a&&!b)return".";b&&=b.slice(0,-1);return a+b},rb=a=>a&&a.match(/([^\/]+|\/)\/*$/)[1],sb=()=>{if(fa){var a=require("node:crypto");return b=>a.randomFillSync(b)}return b=>crypto.getRandomValues(b)},tb=a=>{(tb=sb())(a)},ub=(...a)=>{for(var b="",c=!1,d=a.length-1;-1<=d&&!c;d--){c=0<=d?a[d]:"/";if("string"!=typeof c)throw new TypeError("Arguments to path.resolve must be strings");if(!c)return"";b=c+"/"+b;c="/"===c.charAt(0)}b=pb(b.split("/").filter(f=>!!f),!c).join("/");return(c?"/": +"")+b||"."},vb=a=>{var b=ob(a,0);return nb.decode(a.buffer?a.subarray(0,b):new Uint8Array(a.slice(0,b)))},wb=[],xb=a=>{for(var b=0,c=0;c=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}return b},E=(a,b,c,d)=>{if(!(0=p){if(c>=d)break;b[c++]=p}else if(2047>=p){if(c+1>=d)break;b[c++]=192|p>>6;b[c++]=128|p&63}else if(65535>=p){if(c+2>=d)break;b[c++]=224|p>>12;b[c++]=128| +p>>6&63;b[c++]=128|p&63}else{if(c+3>=d)break;b[c++]=240|p>>18;b[c++]=128|p>>12&63;b[c++]=128|p>>6&63;b[c++]=128|p&63;k++}}b[c]=0;return c-f},yb=[];function zb(a,b){yb[a]={input:[],output:[],sb:b};Ab(a,Bb)} +var Bb={open(a){var b=yb[a.node.rdev];if(!b)throw new T(43);a.tty=b;a.seekable=!1},close(a){a.tty.sb.fsync(a.tty)},fsync(a){a.tty.sb.fsync(a.tty)},read(a,b,c,d){if(!a.tty||!a.tty.sb.Tb)throw new T(60);for(var f=0,k=0;k=a.node.Za)return 0;a=Math.min(a.node.Za-f,d);if(8=k||(k=Math.max(k,p*(1048576>p?2:1.125)>>>0),0!=p&&(k=Math.max(k,256)),p=a.Va,a.Va=new Uint8Array(k),0b)throw new T(28); +return b},Ab(a,b,c,d,f){if(32768!==(a.node.mode&61440))throw new T(43);a=a.node.Va;if(f&2||!a||a.buffer!==x.buffer){f=!0;d=65536*Math.ceil(b/65536);var k=Yb(65536,d);k&&F.fill(0,k,k+d);d=k;if(!d)throw new T(48);if(a){if(0{var c=0;a&&(c|=365);b&&(c|=146);return c},Zb=null,$b={},ac=[],bc=1,cc=null,dc= +!1,ec=!0,fc={},T=class{name="ErrnoError";constructor(a){this.Xa=a}},gc=class{xb={};node=null;get flags(){return this.xb.flags}set flags(a){this.xb.flags=a}get position(){return this.xb.position}set position(a){this.xb.position=a}},hc=class{Ta={};Ua={};qb=null;constructor(a,b,c,d){a||=this;this.parent=a;this.kb=a.kb;this.id=bc++;this.name=b;this.mode=c;this.rdev=d;this.atime=this.mtime=this.ctime=Date.now()}get read(){return 365===(this.mode&365)}set read(a){a?this.mode|=365:this.mode&=-366}get write(){return 146=== (this.mode&146)}set write(a){a?this.mode|=146:this.mode&=-147}}; -function V(a,b={}){if(!a)throw new S(44);b.Fb??(b.Fb=!0);"/"===a.charAt(0)||(a="//"+a);var c=0;a:for(;40>c;c++){a=a.split("/").filter(v=>!!v);for(var d=Yb,f="/",h=0;h>>0)%bc.length} -function Vb(a){var b=hc(a.parent.id,a.name);if(bc[b]===a)bc[b]=a.rb;else for(b=bc[b];b;){if(b.rb===a){b.rb=a.rb;break}b=b.rb}}function Ib(a,b){var c=U(a.mode)?(c=ic(a,"x"))?c:a.Ta.lookup?0:2:54;if(c)throw new S(c);for(c=bc[hc(a.id,b)];c;c=c.rb){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.Ta.lookup(a,b)}function Hb(a,b,c,d){a=new gc(a,b,c,d);b=hc(a.parent.id,a.name);a.rb=bc[b];return bc[b]=a}function U(a){return 16384===(a&61440)} -function jc(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b}function ic(a,b){if(dc)return 0;if(!b.includes("r")||a.mode&292){if(b.includes("w")&&!(a.mode&146)||b.includes("x")&&!(a.mode&73))return 2}else return 2;return 0}function kc(a,b){if(!U(a.mode))return 54;try{return Ib(a,b),20}catch(c){}return ic(a,"wx")} -function lc(a,b,c){try{var d=Ib(a,b)}catch(f){return f.Xa}if(a=ic(a,"wx"))return a;if(c){if(!U(d.mode))return 54;if(d===d.parent||"/"===ka(d))return 10}else if(U(d.mode))return 31;return 0}function mc(a){if(!a)throw new S(63);return a}function W(a){a=$b[a];if(!a)throw new S(8);return a}function nc(a,b=-1){a=Object.assign(new fc,a);if(-1==b)a:{for(b=0;4096>=b;b++)if(!$b[b])break a;throw new S(33);}a.fd=b;return $b[b]=a}function oc(a,b=-1){a=nc(a,b);a.Ua?.wc?.(a);return a} -function pc(a,b,c){var d=a?.Ua.eb;a=d?a:b;d??=b.Ta.eb;mc(d);d(a,c)}var Eb={open(a){a.Ua=Zb[a.node.rdev].Ua;a.Ua.open?.(a)},gb(){throw new S(70);}};function Ab(a,b){Zb[a]={Ua:b}}function qc(a,b){var c="/"===b;if(c&&Yb)throw new S(10);if(!c&&b){var d=V(b,{Fb:!1});b=d.path;d=d.node;if(d.qb)throw new S(10);if(!U(d.mode))throw new S(54);}b={type:a,Cc:{},Tb:b,lc:[]};a=a.kb(b);a.kb=b;b.root=a;c?Yb=a:d&&(d.qb=b,d.kb&&d.kb.lc.push(b))} -function rc(a,b,c){var d=V(a,{parent:!0}).node;a=rb(a);if(!a)throw new S(28);if("."===a||".."===a)throw new S(20);var f=kc(d,a);if(f)throw new S(f);if(!d.Ta.yb)throw new S(63);return d.Ta.yb(d,a,b,c)}function na(a,b=438){return rc(a,b&4095|32768,0)}function X(a,b=511){return rc(a,b&1023|16384,0)}function sc(a,b,c){"undefined"==typeof c&&(c=b,b=438);rc(a,b|8192,c)} -function tc(a,b){if(!ub(a))throw new S(44);var c=V(b,{parent:!0}).node;if(!c)throw new S(44);b=rb(b);var d=kc(c,b);if(d)throw new S(d);if(!c.Ta.symlink)throw new S(63);c.Ta.symlink(c,b,a)}function uc(a){var b=V(a,{parent:!0}).node;a=rb(a);var c=Ib(b,a),d=lc(b,a,!0);if(d)throw new S(d);if(!b.Ta.rmdir)throw new S(63);if(c.qb)throw new S(10);b.Ta.rmdir(b,a);Vb(c)} -function Ba(a){var b=V(a,{parent:!0}).node;if(!b)throw new S(44);a=rb(a);var c=Ib(b,a),d=lc(b,a,!1);if(d)throw new S(d);if(!b.Ta.unlink)throw new S(63);if(c.qb)throw new S(10);b.Ta.unlink(b,a);Vb(c)}function vc(a,b){a=V(a,{pb:!b}).node;return mc(a.Ta.bb)(a)}function wc(a,b,c,d){pc(a,b,{mode:c&4095|b.mode&-4096,ctime:Date.now(),ac:d})}function oa(a,b){a="string"==typeof a?V(a,{pb:!0}).node:a;wc(null,a,b)} -function xc(a,b,c){if(U(b.mode))throw new S(31);if(32768!==(b.mode&61440))throw new S(28);var d=ic(b,"w");if(d)throw new S(d);pc(a,b,{size:c,timestamp:Date.now()})} -function pa(a,b,c=438){if(""===a)throw new S(44);if("string"==typeof b){var d={r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090}[b];if("undefined"==typeof d)throw Error(`Unknown file open mode: ${b}`);b=d}c=b&64?c&4095|32768:0;if("object"==typeof a)d=a;else{var f=a.endsWith("/");a=V(a,{pb:!(b&131072),mc:!0});d=a.node;a=a.path}var h=!1;if(b&64)if(d){if(b&128)throw new S(20);}else{if(f)throw new S(31);d=rc(a,c|511,0);h=!0}if(!d)throw new S(44);8192===(d.mode&61440)&&(b&=-513);if(b&65536&&!U(d.mode))throw new S(54); -if(!h&&(f=d?40960===(d.mode&61440)?32:U(d.mode)&&("r"!==jc(b)||b&576)?31:ic(d,jc(b)):44))throw new S(f);b&512&&!h&&(f=d,f="string"==typeof f?V(f,{pb:!0}).node:f,xc(null,f,0));b&=-131713;f=nc({node:d,path:ka(d),flags:b,seekable:!0,position:0,Ua:d.Ua,pc:[],error:!1});f.Ua.open&&f.Ua.open(f);h&&oa(d,c&511);!m.logReadFiles||b&1||a in ec||(ec[a]=1);return f}function ta(a){if(null===a.fd)throw new S(8);a.Gb&&(a.Gb=null);try{a.Ua.close&&a.Ua.close(a)}catch(b){throw b;}finally{$b[a.fd]=null}a.fd=null} -function yc(a,b,c){if(null===a.fd)throw new S(8);if(!a.seekable||!a.Ua.gb)throw new S(70);if(0!=c&&1!=c&&2!=c)throw new S(28);a.position=a.Ua.gb(a,b,c);a.pc=[]}function zc(a,b,c,d,f){if(0>d||0>f)throw new S(28);if(null===a.fd)throw new S(8);if(1===(a.flags&2097155))throw new S(8);if(U(a.node.mode))throw new S(31);if(!a.Ua.read)throw new S(28);var h="undefined"!=typeof f;if(!h)f=a.position;else if(!a.seekable)throw new S(70);b=a.Ua.read(a,b,c,d,f);h||(a.position+=b);return b} -function sa(a,b,c,d,f){if(0>d||0>f)throw new S(28);if(null===a.fd)throw new S(8);if(0===(a.flags&2097155))throw new S(8);if(U(a.node.mode))throw new S(31);if(!a.Ua.write)throw new S(28);a.seekable&&a.flags&1024&&yc(a,0,2);var h="undefined"!=typeof f;if(!h)f=a.position;else if(!a.seekable)throw new S(70);b=a.Ua.write(a,b,c,d,f,void 0);h||(a.position+=b);return b} -function Aa(a){var b=b||0;var c="binary";"utf8"!==c&&"binary"!==c&&Ya(`Invalid encoding type "${c}"`);b=pa(a,b);a=vc(a).size;var d=new Uint8Array(a);zc(b,d,0,a,0);"utf8"===c&&(d=vb(d));ta(b);return d} -function Ac(a,b,c){a=la("/dev/"+a);var d=ma(!!b,!!c);Ac.Sb??(Ac.Sb=64);var f=Ac.Sb++<<8|0;Ab(f,{open(h){h.seekable=!1},close(){c?.buffer?.length&&c(10)},read(h,l,v,z){for(var x=0,A=0;A>2]=b.dev;K[a+4>>2]=b.mode;K[a+8>>2]=b.nlink;K[a+12>>2]=b.uid;K[a+16>>2]=b.gid;K[a+20>>2]=b.rdev;P[a+24>>3]=BigInt(b.size);H[a+32>>2]=4096;H[a+36>>2]=b.blocks;var c=b.atime.getTime(),d=b.mtime.getTime(),f=b.ctime.getTime();P[a+40>>3]=BigInt(Math.floor(c/1E3));K[a+48>>2]=c%1E3*1E6;P[a+56>>3]=BigInt(Math.floor(d/1E3));K[a+64>>2]=d%1E3*1E6;P[a+72>>3]=BigInt(Math.floor(f/1E3));K[a+80>>2]=f%1E3*1E6;P[a+88>>3]=BigInt(b.ino);return 0} -var Oc=void 0,ld=()=>{var a=H[+Oc>>2];Oc+=4;return a},md=0,nd=[0,31,60,91,121,152,182,213,244,274,305,335],od=[0,31,59,90,120,151,181,212,243,273,304,334],pd={},qd=a=>{Sa=a;mb||0{if(!Ra)try{a()}catch(b){b instanceof cb||"unwind"==b||Da(1,b)}finally{if(!(mb||0{if(!td){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(globalThis.navigator?.language?? -"C").replace("-","_")+".UTF-8",_:Ca||"./this.program"},b;for(b in sd)void 0===sd[b]?delete a[b]:a[b]=sd[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);td=c}return td},td,vd=(a,b,c,d)=>{var f={string:x=>{var A=0;if(null!==x&&void 0!==x&&0!==x){A=xb(x)+1;var N=ua(A);R(x,C,N,A);A=N}return A},array:x=>{var A=ua(x.length);p.set(x,A);return A}};a=m["_"+a];var h=[],l=0;if(d)for(var v=0;v{var b=xb(a)+1,c=fa(b);c&&R(a,C,c,b);return c},wd,xd=[],B=a=>{wd.delete(yd.get(a));yd.set(a,null);xd.push(a)},zd=a=>{const b=a.length;return[b%128|128,b>>7,...a]},Ad={i:127,p:127,j:126,f:125,d:124,e:111},Bd=a=>zd(Array.from(a,b=>Ad[b])),G=(a,b)=>{if(!wd){wd=new WeakMap;var c=yd.length;if(wd)for(var d=0;d<0+c;d++){var f=yd.get(d);f&&wd.set(f,d)}}if(c=wd.get(a)||0)return c;c=xd.length?xd.pop():yd.grow(1);try{yd.set(c,a)}catch(h){if(!(h instanceof TypeError))throw h; -b=Uint8Array.of(0,97,115,109,1,0,0,0,1,...zd([1,96,...Bd(b.slice(1)),...Bd("v"===b[0]?"":b[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);b=new WebAssembly.Module(b);b=(new WebAssembly.Instance(b,{e:{f:a}})).exports.f;yd.set(c,b)}wd.set(a,c);return c};bc=Array(4096);qc(T,"/");X("/tmp");X("/home");X("/home/web_user"); -(function(){X("/dev");Ab(259,{read:()=>0,write:(d,f,h,l)=>l,gb:()=>0});sc("/dev/null",259);zb(1280,Cb);zb(1536,Db);sc("/dev/tty",1280);sc("/dev/tty1",1536);var a=new Uint8Array(1024),b=0,c=()=>{0===b&&(tb(a),b=a.byteLength);return a[--b]};Ac("random",c);Ac("urandom",c);X("/dev/shm");X("/dev/shm/tmp")})(); -(function(){X("/proc");var a=X("/proc/self");X("/proc/self/fd");qc({kb(){var b=Hb(a,"fd",16895,73);b.Ua={gb:T.Ua.gb};b.Ta={lookup(c,d){c=+d;var f=W(c);c={parent:null,kb:{Tb:"fake"},Ta:{readlink:()=>f.path},id:c+1};return c.parent=c},readdir(){return Array.from($b.entries()).filter(([,c])=>c).map(([c])=>c.toString())}};return b}},"/proc/self/fd")})();m.noExitRuntime&&(mb=m.noExitRuntime);m.print&&(Ja=m.print);m.printErr&&(Pa=m.printErr);m.wasmBinary&&(Qa=m.wasmBinary);m.thisProgram&&(Ca=m.thisProgram); -if(m.preInit)for("function"==typeof m.preInit&&(m.preInit=[m.preInit]);0va();m.stackRestore=a=>za(a);m.stackAlloc=a=>ua(a);m.cwrap=(a,b,c,d)=>{var f=!c||c.every(h=>"number"===h||"boolean"===h);return"string"!==b&&f&&!d?m["_"+a]:(...h)=>vd(a,b,c,h)};m.addFunction=G;m.removeFunction=B;m.UTF8ToString=F;m.stringToNewUTF8=ja;m.writeArrayToMemory=(a,b)=>{p.set(a,b)}; -var fa,ia,Xb,Cd,za,ua,va,Xa,yd,Dd={a:(a,b,c,d)=>Ya(`Assertion failed: ${F(a)}, at: `+[b?F(b):"unknown filename",c,d?F(d):"unknown function"]),i:function(a,b){try{return a=F(a),oa(a,b),0}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return-c.Xa}},L:function(a,b,c){try{b=F(b);b=Bc(a,b);if(c&-8)return-28;var d=V(b,{pb:!0}).node;if(!d)return-44;a="";c&4&&(a+="r");c&2&&(a+="w");c&1&&(a+="x");return a&&ic(d,a)?-2:0}catch(f){if("undefined"==typeof Y||"ErrnoError"!==f.name)throw f;return-f.Xa}}, -j:function(a,b){try{var c=W(a);wc(c,c.node,b,!1);return 0}catch(d){if("undefined"==typeof Y||"ErrnoError"!==d.name)throw d;return-d.Xa}},h:function(a){try{var b=W(a);pc(b,b.node,{timestamp:Date.now(),ac:!1});return 0}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return-c.Xa}},b:function(a,b,c){Oc=c;try{var d=W(a);switch(b){case 0:var f=ld();if(0>f)break;for(;$b[f];)f++;return oc(d,f).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return f=ld(),d.flags|=f,0;case 12:return f= -ld(),Ta[f+0>>1]=2,0;case 13:case 14:return 0}return-28}catch(h){if("undefined"==typeof Y||"ErrnoError"!==h.name)throw h;return-h.Xa}},g:function(a,b){try{var c=W(a),d=c.node,f=c.Ua.bb;a=f?c:d;f??=d.Ta.bb;mc(f);var h=f(a);return Cc(b,h)}catch(l){if("undefined"==typeof Y||"ErrnoError"!==l.name)throw l;return-l.Xa}},H:function(a,b){b=-9007199254740992>b||9007199254740992b||0===(c.flags&2097155))throw new S(28);xc(c,c.node,b);return 0}catch(d){if("undefined"== -typeof Y||"ErrnoError"!==d.name)throw d;return-d.Xa}},G:function(a,b){try{if(0===b)return-28;var c=xb("/")+1;if(b=d)return-28;var f=V(b).node;if(!f)throw new S(44);if(!f.Ta.readlink)throw new S(28);var h=f.Ta.readlink(f);var l=Math.min(d,xb(h)),v=p[c+l]; -R(h,C,c,d+1);p[c+l]=v;return l}catch(z){if("undefined"==typeof Y||"ErrnoError"!==z.name)throw z;return-z.Xa}},u:function(a){try{return a=F(a),uc(a),0}catch(b){if("undefined"==typeof Y||"ErrnoError"!==b.name)throw b;return-b.Xa}},f:function(a,b){try{return a=F(a),Cc(b,vc(a))}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return-c.Xa}},r:function(a,b,c){try{b=F(b);b=Bc(a,b);if(c)if(512===c)uc(b);else return-28;else Ba(b);return 0}catch(d){if("undefined"==typeof Y||"ErrnoError"!==d.name)throw d; -return-d.Xa}},q:function(a,b,c){try{b=F(b);b=Bc(a,b,!0);var d=Date.now(),f,h;if(c){var l=K[c>>2]+4294967296*H[c+4>>2],v=H[c+8>>2];1073741823==v?f=d:1073741822==v?f=null:f=1E3*l+v/1E6;c+=16;l=K[c>>2]+4294967296*H[c+4>>2];v=H[c+8>>2];1073741823==v?h=d:1073741822==v?h=null:h=1E3*l+v/1E6}else h=f=d;if(null!==(h??f)){a=f;var z=V(b,{pb:!0}).node;mc(z.Ta.eb)(z,{atime:a,mtime:h})}return 0}catch(x){if("undefined"==typeof Y||"ErrnoError"!==x.name)throw x;return-x.Xa}},m:()=>Ya(""),l:()=>{mb=!1;md=0},A:function(a, -b){a=-9007199254740992>a||9007199254740992>2]=a.getSeconds();H[b+4>>2]=a.getMinutes();H[b+8>>2]=a.getHours();H[b+12>>2]=a.getDate();H[b+16>>2]=a.getMonth();H[b+20>>2]=a.getFullYear()-1900;H[b+24>>2]=a.getDay();var c=a.getFullYear();H[b+28>>2]=(0!==c%4||0===c%100&&0!==c%400?od:nd)[a.getMonth()]+a.getDate()-1|0;H[b+36>>2]=-(60*a.getTimezoneOffset());c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();var d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset(); -H[b+32>>2]=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0},y:function(a,b,c,d,f,h,l){f=-9007199254740992>f||9007199254740992>2]=z.Ub;K[l>>2]=x;return 0}catch(A){if("undefined"==typeof Y||"ErrnoError"!==A.name)throw A;return-A.Xa}},z:function(a,b,c,d,f,h){h=-9007199254740992>h|| -9007199254740992{pd[a]&&(clearTimeout(pd[a].id),delete pd[a]);if(!b)return 0;var c=setTimeout(()=>{delete pd[a];rd(()=>Cd(a,performance.now()))},b);pd[a]={id:c,Dc:b};return 0},B:(a,b,c,d)=>{var f=(new Date).getFullYear(),h=(new Date(f,0,1)).getTimezoneOffset(); -f=(new Date(f,6,1)).getTimezoneOffset();K[a>>2]=60*Math.max(h,f);H[b>>2]=Number(h!=f);b=l=>{var v=Math.abs(l);return`UTC${0<=l?"-":"+"}${String(Math.floor(v/60)).padStart(2,"0")}${String(v%60).padStart(2,"0")}`};a=b(h);b=b(f);fDate.now(),s:()=>2147483648,c:()=>performance.now(),o:a=>{var b=C.length;a>>>=0;if(2147483648=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);a:{d=(Math.min(2147483648,65536*Math.ceil(Math.max(a, -d)/65536))-Xa.buffer.byteLength+65535)/65536|0;try{Xa.grow(d);Wa();var f=1;break a}catch(h){}f=void 0}if(f)return!0}return!1},E:(a,b)=>{var c=0,d=0,f;for(f of ud()){var h=b+c;K[a+d>>2]=h;c+=R(f,C,h,Infinity)+1;d+=4}return 0},F:(a,b)=>{var c=ud();K[a>>2]=c.length;a=0;for(var d of c)a+=xb(d)+1;K[b>>2]=a;return 0},e:function(a){try{var b=W(a);ta(b);return 0}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return c.Xa}},p:function(a,b){try{var c=W(a);p[b]=c.tty?2:U(c.mode)?3:40960===(c.mode& -61440)?7:4;Ta[b+2>>1]=0;P[b+8>>3]=BigInt(0);P[b+16>>3]=BigInt(0);return 0}catch(d){if("undefined"==typeof Y||"ErrnoError"!==d.name)throw d;return d.Xa}},w:function(a,b,c,d){try{a:{var f=W(a);a=b;for(var h,l=b=0;l>2],z=K[a+4>>2];a+=8;var x=zc(f,p,v,z,h);if(0>x){var A=-1;break a}b+=x;if(x>2]=A;return 0}catch(N){if("undefined"==typeof Y||"ErrnoError"!==N.name)throw N;return N.Xa}},D:function(a,b,c,d){b=-9007199254740992>b||9007199254740992< -b?NaN:Number(b);try{if(isNaN(b))return 61;var f=W(a);yc(f,b,c);P[d>>3]=BigInt(f.position);f.Gb&&0===b&&0===c&&(f.Gb=null);return 0}catch(h){if("undefined"==typeof Y||"ErrnoError"!==h.name)throw h;return h.Xa}},I:function(a){try{var b=W(a);return b.Ua?.fsync?.(b)}catch(c){if("undefined"==typeof Y||"ErrnoError"!==c.name)throw c;return c.Xa}},t:function(a,b,c,d){try{a:{var f=W(a);a=b;for(var h,l=b=0;l>2],z=K[a+4>>2];a+=8;var x=sa(f,p,v,z,h);if(0>x){var A=-1;break a}b+=x;if(x>2]=A;return 0}catch(N){if("undefined"==typeof Y||"ErrnoError"!==N.name)throw N;return N.Xa}},k:qd}; -function Ed(){function a(){m.calledRun=!0;if(!Ra){if(!m.noFSInit&&!cc){var b,c;cc=!0;b??=m.stdin;c??=m.stdout;d??=m.stderr;b?Ac("stdin",b):tc("/dev/tty","/dev/stdin");c?Ac("stdout",null,c):tc("/dev/tty","/dev/stdout");d?Ac("stderr",null,d):tc("/dev/tty1","/dev/stderr");pa("/dev/stdin",0);pa("/dev/stdout",1);pa("/dev/stderr",1)}Fd.N();dc=!1;m.onRuntimeInitialized?.();if(m.postRun)for("function"==typeof m.postRun&&(m.postRun=[m.postRun]);m.postRun.length;){var d=m.postRun.shift();eb.push(d)}db(eb)}} -if(0{setTimeout(()=>m.setStatus(""),1);a()},1)):a()}}var Fd; -(async function(){function a(c){c=Fd=c.exports;m._sqlite3_free=c.P;m._sqlite3_value_text=c.Q;m._sqlite3_prepare_v2=c.R;m._sqlite3_step=c.S;m._sqlite3_reset=c.T;m._sqlite3_exec=c.U;m._sqlite3_finalize=c.V;m._sqlite3_column_name=c.W;m._sqlite3_column_text=c.X;m._sqlite3_column_type=c.Y;m._sqlite3_errmsg=c.Z;m._sqlite3_clear_bindings=c._;m._sqlite3_value_blob=c.$;m._sqlite3_value_bytes=c.aa;m._sqlite3_value_double=c.ba;m._sqlite3_value_int=c.ca;m._sqlite3_value_type=c.da;m._sqlite3_result_blob=c.ea; -m._sqlite3_result_double=c.fa;m._sqlite3_result_error=c.ga;m._sqlite3_result_int=c.ha;m._sqlite3_result_int64=c.ia;m._sqlite3_result_null=c.ja;m._sqlite3_result_text=c.ka;m._sqlite3_aggregate_context=c.la;m._sqlite3_column_count=c.ma;m._sqlite3_data_count=c.na;m._sqlite3_column_blob=c.oa;m._sqlite3_column_bytes=c.pa;m._sqlite3_column_double=c.qa;m._sqlite3_bind_blob=c.ra;m._sqlite3_bind_double=c.sa;m._sqlite3_bind_int=c.ta;m._sqlite3_bind_text=c.ua;m._sqlite3_bind_parameter_index=c.va;m._sqlite3_sql= -c.wa;m._sqlite3_normalized_sql=c.xa;m._sqlite3_changes=c.ya;m._sqlite3_close_v2=c.za;m._sqlite3_progress_handler=c.Aa;m._sqlite3_interrupt=c.Ba;m._sqlite3_create_function_v2=c.Ca;m._sqlite3_update_hook=c.Da;m._sqlite3_open=c.Ea;m._sqlite3_get_autocommit=c.Fa;fa=m._malloc=c.Ga;ia=m._free=c.Ha;m._RegisterExtensionFunctions=c.Ia;m._sqljs_vfs_register=c.Ja;m._sqljs_open_paged=c.Ka;m._sqljs_vfs_register_rw=c.La;m._sqljs_open_paged_rw=c.Ma;m._sqlite_explorer_register_query_plan=c.Na;Xb=c.Oa;Cd=c.Pa;za= -c.Qa;ua=c.Ra;va=c.Sa;Xa=c.M;yd=c.O;Wa();kb--;m.monitorRunDependencies?.(kb);0==kb&&lb&&(c=lb,lb=null,c());return Fd}kb++;m.monitorRunDependencies?.(kb);var b={a:Dd};if(m.instantiateWasm)return new Promise(c=>{m.instantiateWasm(b,(d,f)=>{c(a(d,f))})});Za??=m.locateFile?m.locateFile("sql-wasm.wasm",Fa):Fa+"sql-wasm.wasm";return a((await bb(b)).instance)})();Ed(); +function W(a,b={}){if(!a)throw new T(44);b.Gb??(b.Gb=!0);"/"===a.charAt(0)||(a="//"+a);var c=0;a:for(;40>c;c++){a=a.split("/").filter(n=>!!n);for(var d=Zb,f="/",k=0;k>>0)%cc.length} +function Wb(a){var b=ic(a.parent.id,a.name);if(cc[b]===a)cc[b]=a.rb;else for(b=cc[b];b;){if(b.rb===a){b.rb=a.rb;break}b=b.rb}}function Jb(a,b){var c=V(a.mode)?(c=jc(a,"x"))?c:a.Ta.lookup?0:2:54;if(c)throw new T(c);for(c=cc[ic(a.id,b)];c;c=c.rb){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.Ta.lookup(a,b)}function Ib(a,b,c,d){a=new hc(a,b,c,d);b=ic(a.parent.id,a.name);a.rb=cc[b];return cc[b]=a}function V(a){return 16384===(a&61440)} +function kc(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b}function jc(a,b){if(ec)return 0;if(!b.includes("r")||a.mode&292){if(b.includes("w")&&!(a.mode&146)||b.includes("x")&&!(a.mode&73))return 2}else return 2;return 0}function lc(a,b){if(!V(a.mode))return 54;try{return Jb(a,b),20}catch(c){}return jc(a,"wx")} +function mc(a,b,c){try{var d=Jb(a,b)}catch(f){return f.Xa}if(a=jc(a,"wx"))return a;if(c){if(!V(d.mode))return 54;if(d===d.parent||"/"===ka(d))return 10}else if(V(d.mode))return 31;return 0}function nc(a){if(!a)throw new T(63);return a}function X(a){a=ac[a];if(!a)throw new T(8);return a}function oc(a,b=-1){a=Object.assign(new gc,a);if(-1==b)a:{for(b=0;4096>=b;b++)if(!ac[b])break a;throw new T(33);}a.fd=b;return ac[b]=a}function pc(a,b=-1){a=oc(a,b);a.Ua?.wc?.(a);return a} +function qc(a,b,c){var d=a?.Ua.eb;a=d?a:b;d??=b.Ta.eb;nc(d);d(a,c)}var Eb={open(a){a.Ua=$b[a.node.rdev].Ua;a.Ua.open?.(a)},gb(){throw new T(70);}};function Ab(a,b){$b[a]={Ua:b}}function rc(a,b){var c="/"===b;if(c&&Zb)throw new T(10);if(!c&&b){var d=W(b,{Gb:!1});b=d.path;d=d.node;if(d.qb)throw new T(10);if(!V(d.mode))throw new T(54);}b={type:a,Cc:{},Vb:b,mc:[]};a=a.kb(b);a.kb=b;b.root=a;c?Zb=a:d&&(d.qb=b,d.kb&&d.kb.mc.push(b))} +function sc(a,b,c){var d=W(a,{parent:!0}).node;a=rb(a);if(!a)throw new T(28);if("."===a||".."===a)throw new T(20);var f=lc(d,a);if(f)throw new T(f);if(!d.Ta.zb)throw new T(63);return d.Ta.zb(d,a,b,c)}function na(a,b=438){return sc(a,b&4095|32768,0)}function Y(a,b=511){return sc(a,b&1023|16384,0)}function tc(a,b,c){"undefined"==typeof c&&(c=b,b=438);sc(a,b|8192,c)} +function uc(a,b){if(!ub(a))throw new T(44);var c=W(b,{parent:!0}).node;if(!c)throw new T(44);b=rb(b);var d=lc(c,b);if(d)throw new T(d);if(!c.Ta.symlink)throw new T(63);c.Ta.symlink(c,b,a)}function vc(a){var b=W(a,{parent:!0}).node;a=rb(a);var c=Jb(b,a),d=mc(b,a,!0);if(d)throw new T(d);if(!b.Ta.rmdir)throw new T(63);if(c.qb)throw new T(10);b.Ta.rmdir(b,a);Wb(c)} +function Ba(a){var b=W(a,{parent:!0}).node;if(!b)throw new T(44);a=rb(a);var c=Jb(b,a),d=mc(b,a,!1);if(d)throw new T(d);if(!b.Ta.unlink)throw new T(63);if(c.qb)throw new T(10);b.Ta.unlink(b,a);Wb(c)}function wc(a,b){a=W(a,{pb:!b}).node;return nc(a.Ta.bb)(a)}function xc(a,b,c,d){qc(a,b,{mode:c&4095|b.mode&-4096,ctime:Date.now(),cc:d})}function oa(a,b){a="string"==typeof a?W(a,{pb:!0}).node:a;xc(null,a,b)} +function yc(a,b,c){if(V(b.mode))throw new T(31);if(32768!==(b.mode&61440))throw new T(28);var d=jc(b,"w");if(d)throw new T(d);qc(a,b,{size:c,timestamp:Date.now()})} +function ra(a,b,c=438){if(""===a)throw new T(44);if("string"==typeof b){var d={r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090}[b];if("undefined"==typeof d)throw Error(`Unknown file open mode: ${b}`);b=d}c=b&64?c&4095|32768:0;if("object"==typeof a)d=a;else{var f=a.endsWith("/");a=W(a,{pb:!(b&131072),nc:!0});d=a.node;a=a.path}var k=!1;if(b&64)if(d){if(b&128)throw new T(20);}else{if(f)throw new T(31);d=sc(a,c|511,0);k=!0}if(!d)throw new T(44);8192===(d.mode&61440)&&(b&=-513);if(b&65536&&!V(d.mode))throw new T(54); +if(!k&&(f=d?40960===(d.mode&61440)?32:V(d.mode)&&("r"!==kc(b)||b&576)?31:jc(d,kc(b)):44))throw new T(f);b&512&&!k&&(f=d,f="string"==typeof f?W(f,{pb:!0}).node:f,yc(null,f,0));b&=-131713;f=oc({node:d,path:ka(d),flags:b,seekable:!0,position:0,Ua:d.Ua,pc:[],error:!1});f.Ua.open&&f.Ua.open(f);k&&oa(d,c&511);!l.logReadFiles||b&1||a in fc||(fc[a]=1);return f}function ta(a){if(null===a.fd)throw new T(8);a.Hb&&(a.Hb=null);try{a.Ua.close&&a.Ua.close(a)}catch(b){throw b;}finally{ac[a.fd]=null}a.fd=null} +function zc(a,b,c){if(null===a.fd)throw new T(8);if(!a.seekable||!a.Ua.gb)throw new T(70);if(0!=c&&1!=c&&2!=c)throw new T(28);a.position=a.Ua.gb(a,b,c);a.pc=[]}function Ac(a,b,c,d,f){if(0>d||0>f)throw new T(28);if(null===a.fd)throw new T(8);if(1===(a.flags&2097155))throw new T(8);if(V(a.node.mode))throw new T(31);if(!a.Ua.read)throw new T(28);var k="undefined"!=typeof f;if(!k)f=a.position;else if(!a.seekable)throw new T(70);b=a.Ua.read(a,b,c,d,f);k||(a.position+=b);return b} +function sa(a,b,c,d,f){if(0>d||0>f)throw new T(28);if(null===a.fd)throw new T(8);if(0===(a.flags&2097155))throw new T(8);if(V(a.node.mode))throw new T(31);if(!a.Ua.write)throw new T(28);a.seekable&&a.flags&1024&&zc(a,0,2);var k="undefined"!=typeof f;if(!k)f=a.position;else if(!a.seekable)throw new T(70);b=a.Ua.write(a,b,c,d,f,void 0);k||(a.position+=b);return b} +function Aa(a){var b=b||0;var c="binary";"utf8"!==c&&"binary"!==c&&Ya(`Invalid encoding type "${c}"`);b=ra(a,b);a=wc(a).size;var d=new Uint8Array(a);Ac(b,d,0,a,0);"utf8"===c&&(d=vb(d));ta(b);return d} +function Bc(a,b,c){a=la("/dev/"+a);var d=ma(!!b,!!c);Bc.Ub??(Bc.Ub=64);var f=Bc.Ub++<<8|0;Ab(f,{open(k){k.seekable=!1},close(){c?.buffer?.length&&c(10)},read(k,p,n,z){for(var w=0,A=0;A>2]=b.dev;R[a+4>>2]=b.mode;R[a+8>>2]=b.nlink;R[a+12>>2]=b.uid;R[a+16>>2]=b.gid;R[a+20>>2]=b.rdev;S[a+24>>3]=BigInt(b.size);P[a+32>>2]=4096;P[a+36>>2]=b.blocks;var c=b.atime.getTime(),d=b.mtime.getTime(),f=b.ctime.getTime();S[a+40>>3]=BigInt(Math.floor(c/1E3));R[a+48>>2]=c%1E3*1E6;S[a+56>>3]=BigInt(Math.floor(d/1E3));R[a+64>>2]=d%1E3*1E6;S[a+72>>3]=BigInt(Math.floor(f/1E3));R[a+80>>2]=f%1E3*1E6;S[a+88>>3]=BigInt(b.ino);return 0} +var Oc=void 0,md=()=>{var a=P[+Oc>>2];Oc+=4;return a},nd=0,od=[0,31,60,91,121,152,182,213,244,274,305,335],pd=[0,31,59,90,120,151,181,212,243,273,304,334],qd={},rd=a=>{Sa=a;mb||0{if(!Ra)try{a()}catch(b){b instanceof cb||"unwind"==b||Da(1,b)}finally{if(!(mb||0{if(!ud){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(globalThis.navigator?.language?? +"C").replace("-","_")+".UTF-8",_:Ca||"./this.program"},b;for(b in td)void 0===td[b]?delete a[b]:a[b]=td[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);ud=c}return ud},ud,wd=(a,b,c,d)=>{var f={string:w=>{var A=0;if(null!==w&&void 0!==w&&0!==w){A=xb(w)+1;var N=ua(A);E(w,F,N,A);A=N}return A},array:w=>{var A=ua(w.length);x.set(w,A);return A}};a=l["_"+a];var k=[],p=0;if(d)for(var n=0;n{var b=xb(a)+1,c=ia(b);c&&E(a,F,c,b);return c},xd,yd=[],H=a=>{xd.delete(zd.get(a));zd.set(a,null);yd.push(a)},Ad=a=>{const b=a.length;return[b%128|128,b>>7,...a]},Bd={i:127,p:127,j:126,f:125,d:124,e:111},Cd=a=>Ad(Array.from(a,b=>Bd[b])),K=(a,b)=>{if(!xd){xd=new WeakMap;var c=zd.length;if(xd)for(var d=0;d<0+c;d++){var f=zd.get(d);f&&xd.set(f,d)}}if(c=xd.get(a)||0)return c;c=yd.length?yd.pop():zd.grow(1);try{zd.set(c,a)}catch(k){if(!(k instanceof TypeError))throw k; +b=Uint8Array.of(0,97,115,109,1,0,0,0,1,...Ad([1,96,...Cd(b.slice(1)),...Cd("v"===b[0]?"":b[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);b=new WebAssembly.Module(b);b=(new WebAssembly.Instance(b,{e:{f:a}})).exports.f;zd.set(c,b)}xd.set(a,c);return c};cc=Array(4096);rc(U,"/");Y("/tmp");Y("/home");Y("/home/web_user"); +(function(){Y("/dev");Ab(259,{read:()=>0,write:(d,f,k,p)=>p,gb:()=>0});tc("/dev/null",259);zb(1280,Cb);zb(1536,Db);tc("/dev/tty",1280);tc("/dev/tty1",1536);var a=new Uint8Array(1024),b=0,c=()=>{0===b&&(tb(a),b=a.byteLength);return a[--b]};Bc("random",c);Bc("urandom",c);Y("/dev/shm");Y("/dev/shm/tmp")})(); +(function(){Y("/proc");var a=Y("/proc/self");Y("/proc/self/fd");rc({kb(){var b=Ib(a,"fd",16895,73);b.Ua={gb:U.Ua.gb};b.Ta={lookup(c,d){c=+d;var f=X(c);c={parent:null,kb:{Vb:"fake"},Ta:{readlink:()=>f.path},id:c+1};return c.parent=c},readdir(){return Array.from(ac.entries()).filter(([,c])=>c).map(([c])=>c.toString())}};return b}},"/proc/self/fd")})();l.noExitRuntime&&(mb=l.noExitRuntime);l.print&&(Ja=l.print);l.printErr&&(Pa=l.printErr);l.wasmBinary&&(Qa=l.wasmBinary);l.thisProgram&&(Ca=l.thisProgram); +if(l.preInit)for("function"==typeof l.preInit&&(l.preInit=[l.preInit]);0va();l.stackRestore=a=>za(a);l.stackAlloc=a=>ua(a);l.cwrap=(a,b,c,d)=>{var f=!c||c.every(k=>"number"===k||"boolean"===k);return"string"!==b&&f&&!d?l["_"+a]:(...k)=>wd(a,b,c,k)};l.addFunction=K;l.removeFunction=H;l.UTF8ToString=C;l.stringToUTF8=(a,b,c)=>E(a,F,b,c);l.stringToNewUTF8=ja;l.writeArrayToMemory=(a,b)=>{x.set(a,b)}; +var ia,q,Yb,Dd,za,ua,va,Xa,zd,Ed={a:(a,b,c,d)=>Ya(`Assertion failed: ${C(a)}, at: `+[b?C(b):"unknown filename",c,d?C(d):"unknown function"]),i:function(a,b){try{return a=C(a),oa(a,b),0}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return-c.Xa}},L:function(a,b,c){try{b=C(b);b=Cc(a,b);if(c&-8)return-28;var d=W(b,{pb:!0}).node;if(!d)return-44;a="";c&4&&(a+="r");c&2&&(a+="w");c&1&&(a+="x");return a&&jc(d,a)?-2:0}catch(f){if("undefined"==typeof Z||"ErrnoError"!==f.name)throw f;return-f.Xa}}, +j:function(a,b){try{var c=X(a);xc(c,c.node,b,!1);return 0}catch(d){if("undefined"==typeof Z||"ErrnoError"!==d.name)throw d;return-d.Xa}},h:function(a){try{var b=X(a);qc(b,b.node,{timestamp:Date.now(),cc:!1});return 0}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return-c.Xa}},b:function(a,b,c){Oc=c;try{var d=X(a);switch(b){case 0:var f=md();if(0>f)break;for(;ac[f];)f++;return pc(d,f).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return f=md(),d.flags|=f,0;case 12:return f= +md(),Ta[f+0>>1]=2,0;case 13:case 14:return 0}return-28}catch(k){if("undefined"==typeof Z||"ErrnoError"!==k.name)throw k;return-k.Xa}},g:function(a,b){try{var c=X(a),d=c.node,f=c.Ua.bb;a=f?c:d;f??=d.Ta.bb;nc(f);var k=f(a);return Dc(b,k)}catch(p){if("undefined"==typeof Z||"ErrnoError"!==p.name)throw p;return-p.Xa}},H:function(a,b){b=-9007199254740992>b||9007199254740992b||0===(c.flags&2097155))throw new T(28);yc(c,c.node,b);return 0}catch(d){if("undefined"== +typeof Z||"ErrnoError"!==d.name)throw d;return-d.Xa}},G:function(a,b){try{if(0===b)return-28;var c=xb("/")+1;if(b=d)return-28;var f=W(b).node;if(!f)throw new T(44);if(!f.Ta.readlink)throw new T(28);var k=f.Ta.readlink(f);var p=Math.min(d,xb(k)),n=x[c+p]; +E(k,F,c,d+1);x[c+p]=n;return p}catch(z){if("undefined"==typeof Z||"ErrnoError"!==z.name)throw z;return-z.Xa}},u:function(a){try{return a=C(a),vc(a),0}catch(b){if("undefined"==typeof Z||"ErrnoError"!==b.name)throw b;return-b.Xa}},f:function(a,b){try{return a=C(a),Dc(b,wc(a))}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return-c.Xa}},r:function(a,b,c){try{b=C(b);b=Cc(a,b);if(c)if(512===c)vc(b);else return-28;else Ba(b);return 0}catch(d){if("undefined"==typeof Z||"ErrnoError"!==d.name)throw d; +return-d.Xa}},q:function(a,b,c){try{b=C(b);b=Cc(a,b,!0);var d=Date.now(),f,k;if(c){var p=R[c>>2]+4294967296*P[c+4>>2],n=P[c+8>>2];1073741823==n?f=d:1073741822==n?f=null:f=1E3*p+n/1E6;c+=16;p=R[c>>2]+4294967296*P[c+4>>2];n=P[c+8>>2];1073741823==n?k=d:1073741822==n?k=null:k=1E3*p+n/1E6}else k=f=d;if(null!==(k??f)){a=f;var z=W(b,{pb:!0}).node;nc(z.Ta.eb)(z,{atime:a,mtime:k})}return 0}catch(w){if("undefined"==typeof Z||"ErrnoError"!==w.name)throw w;return-w.Xa}},m:()=>Ya(""),l:()=>{mb=!1;nd=0},A:function(a, +b){a=-9007199254740992>a||9007199254740992>2]=a.getSeconds();P[b+4>>2]=a.getMinutes();P[b+8>>2]=a.getHours();P[b+12>>2]=a.getDate();P[b+16>>2]=a.getMonth();P[b+20>>2]=a.getFullYear()-1900;P[b+24>>2]=a.getDay();var c=a.getFullYear();P[b+28>>2]=(0!==c%4||0===c%100&&0!==c%400?pd:od)[a.getMonth()]+a.getDate()-1|0;P[b+36>>2]=-(60*a.getTimezoneOffset());c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();var d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset(); +P[b+32>>2]=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0},y:function(a,b,c,d,f,k,p){f=-9007199254740992>f||9007199254740992>2]=z.Wb;R[p>>2]=w;return 0}catch(A){if("undefined"==typeof Z||"ErrnoError"!==A.name)throw A;return-A.Xa}},z:function(a,b,c,d,f,k){k=-9007199254740992>k|| +9007199254740992{qd[a]&&(clearTimeout(qd[a].id),delete qd[a]);if(!b)return 0;var c=setTimeout(()=>{delete qd[a];sd(()=>Dd(a,performance.now()))},b);qd[a]={id:c,Dc:b};return 0},B:(a,b,c,d)=>{var f=(new Date).getFullYear(),k=(new Date(f,0,1)).getTimezoneOffset(); +f=(new Date(f,6,1)).getTimezoneOffset();R[a>>2]=60*Math.max(k,f);P[b>>2]=Number(k!=f);b=p=>{var n=Math.abs(p);return`UTC${0<=p?"-":"+"}${String(Math.floor(n/60)).padStart(2,"0")}${String(n%60).padStart(2,"0")}`};a=b(k);b=b(f);fDate.now(),s:()=>2147483648,c:()=>performance.now(),o:a=>{var b=F.length;a>>>=0;if(2147483648=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);a:{d=(Math.min(2147483648,65536*Math.ceil(Math.max(a, +d)/65536))-Xa.buffer.byteLength+65535)/65536|0;try{Xa.grow(d);Wa();var f=1;break a}catch(k){}f=void 0}if(f)return!0}return!1},E:(a,b)=>{var c=0,d=0,f;for(f of vd()){var k=b+c;R[a+d>>2]=k;c+=E(f,F,k,Infinity)+1;d+=4}return 0},F:(a,b)=>{var c=vd();R[a>>2]=c.length;a=0;for(var d of c)a+=xb(d)+1;R[b>>2]=a;return 0},e:function(a){try{var b=X(a);ta(b);return 0}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return c.Xa}},p:function(a,b){try{var c=X(a);x[b]=c.tty?2:V(c.mode)?3:40960===(c.mode& +61440)?7:4;Ta[b+2>>1]=0;S[b+8>>3]=BigInt(0);S[b+16>>3]=BigInt(0);return 0}catch(d){if("undefined"==typeof Z||"ErrnoError"!==d.name)throw d;return d.Xa}},w:function(a,b,c,d){try{a:{var f=X(a);a=b;for(var k,p=b=0;p>2],z=R[a+4>>2];a+=8;var w=Ac(f,x,n,z,k);if(0>w){var A=-1;break a}b+=w;if(w>2]=A;return 0}catch(N){if("undefined"==typeof Z||"ErrnoError"!==N.name)throw N;return N.Xa}},D:function(a,b,c,d){b=-9007199254740992>b||9007199254740992< +b?NaN:Number(b);try{if(isNaN(b))return 61;var f=X(a);zc(f,b,c);S[d>>3]=BigInt(f.position);f.Hb&&0===b&&0===c&&(f.Hb=null);return 0}catch(k){if("undefined"==typeof Z||"ErrnoError"!==k.name)throw k;return k.Xa}},I:function(a){try{var b=X(a);return b.Ua?.fsync?.(b)}catch(c){if("undefined"==typeof Z||"ErrnoError"!==c.name)throw c;return c.Xa}},t:function(a,b,c,d){try{a:{var f=X(a);a=b;for(var k,p=b=0;p>2],z=R[a+4>>2];a+=8;var w=sa(f,x,n,z,k);if(0>w){var A=-1;break a}b+=w;if(w>2]=A;return 0}catch(N){if("undefined"==typeof Z||"ErrnoError"!==N.name)throw N;return N.Xa}},k:rd}; +function Fd(){function a(){l.calledRun=!0;if(!Ra){if(!l.noFSInit&&!dc){var b,c;dc=!0;b??=l.stdin;c??=l.stdout;d??=l.stderr;b?Bc("stdin",b):uc("/dev/tty","/dev/stdin");c?Bc("stdout",null,c):uc("/dev/tty","/dev/stdout");d?Bc("stderr",null,d):uc("/dev/tty1","/dev/stderr");ra("/dev/stdin",0);ra("/dev/stdout",1);ra("/dev/stderr",1)}Gd.N();ec=!1;l.onRuntimeInitialized?.();if(l.postRun)for("function"==typeof l.postRun&&(l.postRun=[l.postRun]);l.postRun.length;){var d=l.postRun.shift();eb.push(d)}db(eb)}} +if(0{setTimeout(()=>l.setStatus(""),1);a()},1)):a()}}var Gd; +(async function(){function a(c){c=Gd=c.exports;l._sqlite3_free=c.P;l._sqlite3_value_text=c.Q;l._sqlite3_prepare_v2=c.R;l._sqlite3_step=c.S;l._sqlite3_reset=c.T;l._sqlite3_exec=c.U;l._sqlite3_finalize=c.V;l._sqlite3_column_name=c.W;l._sqlite3_column_text=c.X;l._sqlite3_column_type=c.Y;l._sqlite3_errmsg=c.Z;l._sqlite3_clear_bindings=c._;l._sqlite3_value_blob=c.$;l._sqlite3_value_bytes=c.aa;l._sqlite3_value_double=c.ba;l._sqlite3_value_int=c.ca;l._sqlite3_value_type=c.da;l._sqlite3_result_blob=c.ea; +l._sqlite3_result_double=c.fa;l._sqlite3_result_error=c.ga;l._sqlite3_result_int=c.ha;l._sqlite3_result_int64=c.ia;l._sqlite3_result_null=c.ja;l._sqlite3_result_text=c.ka;l._sqlite3_aggregate_context=c.la;l._sqlite3_column_count=c.ma;l._sqlite3_data_count=c.na;l._sqlite3_column_blob=c.oa;l._sqlite3_column_bytes=c.pa;l._sqlite3_column_double=c.qa;l._sqlite3_bind_blob=c.ra;l._sqlite3_bind_double=c.sa;l._sqlite3_bind_int=c.ta;l._sqlite3_bind_text=c.ua;l._sqlite3_bind_parameter_index=c.va;l._sqlite3_sql= +c.wa;l._sqlite3_normalized_sql=c.xa;l._sqlite3_changes=c.ya;l._sqlite3_close_v2=c.za;l._sqlite3_progress_handler=c.Aa;l._sqlite3_interrupt=c.Ba;l._sqlite3_create_function_v2=c.Ca;l._sqlite3_update_hook=c.Da;l._sqlite3_open=c.Ea;l._sqlite3_get_autocommit=c.Fa;ia=l._malloc=c.Ga;q=l._free=c.Ha;l._RegisterExtensionFunctions=c.Ia;l._sqljs_vfs_register=c.Ja;l._sqljs_open_paged=c.Ka;l._sqljs_vfs_register_rw=c.La;l._sqljs_open_paged_rw=c.Ma;l._sqlite_explorer_register_query_plan=c.Na;Yb=c.Oa;Dd=c.Pa;za=c.Qa; +ua=c.Ra;va=c.Sa;Xa=c.M;zd=c.O;Wa();kb--;l.monitorRunDependencies?.(kb);0==kb&&lb&&(c=lb,lb=null,c());return Gd}kb++;l.monitorRunDependencies?.(kb);var b={a:Ed};if(l.instantiateWasm)return new Promise(c=>{l.instantiateWasm(b,(d,f)=>{c(a(d,f))})});Za??=l.locateFile?l.locateFile("sql-wasm.wasm",Fa):Fa+"sql-wasm.wasm";return a((await bb(b)).instance)})();Fd(); // The shell-pre.js and emcc-generated code goes above diff --git a/website/public/sqlite-viewer/worker.js b/website/public/sqlite-viewer/worker.js index 8d6ddfa5..f526c113 100644 --- a/website/public/sqlite-viewer/worker.js +++ b/website/public/sqlite-viewer/worker.js @@ -1,14 +1,14 @@ -/*! sqlite-viewer-bundle-sha256:fc00d2fde89042a0124f0c3136e3b55c3b3a4ea1937c9671474dbcbb8e0311ec */ -"use strict";(()=>{var ns=Object.defineProperty;var rs=(e,t,n)=>t in e?ns(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var D=(e,t,n)=>rs(e,typeof t!="symbol"?t+"":t,n);function h(e){return`"${e.replace(/"/g,'""')}"`}function R(e){return`main.${h(e)}`}function K(e,t="Identifier"){if(typeof e!="string"||e.length===0)throw new Error(`${t} is required`);if(e.includes("\0"))throw new Error(`${t} cannot contain NUL characters`)}function sn(e){if(!e||typeof e!="string")throw new Error("Invalid SQL type: Type must be a non-empty string");if(/['";\-\/\*]/.test(e))throw new Error(`Invalid SQL type: "${e}" contains potentially unsafe characters`);if(!/^[a-zA-Z0-9_\s]+(?:\([0-9\s,]+\)[a-zA-Z0-9_\s]*)?$/.test(e.trim()))throw new Error(`Invalid SQL type: "${e}" does not match allowed format`)}function Er(e){if(e==null)return"NULL";if(typeof e=="number")return String(e);if(typeof e=="bigint")return e.toString();if(typeof e=="string"){if(e.includes("\0")){let n=new TextEncoder().encode(e);return`CAST(X'${Array.from(n).map(o=>o.toString(16).padStart(2,"0")).join("")}' AS TEXT)`}return`'${e.replace(/'/g,"''")}'`}return e instanceof Uint8Array?`X'${Array.from(e).map(n=>n.toString(16).padStart(2,"0")).join("")}'`:`'${String(e).replace(/'/g,"''")}'`}function ze(e,t="\\"){let n=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`[${n}%_]`,"g");return e.replace(r,o=>t+o)}var os=-9223372036854775808n,is=9223372036854775807n;function M(e){let t=typeof e;if(t!=="string"&&t!=="number"&&t!=="bigint")throw new Error(`Invalid rowid: ${e}`);if(typeof e=="number"){if(!Number.isSafeInteger(e))throw new Error(`Invalid rowid: ${e}`);return e}let n=typeof e=="string"?e.trim():e.toString();if(!/^[+-]?\d+$/.test(n))throw new Error(`Invalid rowid: ${e}`);let r=BigInt(n);if(ris)throw new Error(`Invalid rowid: ${e}`);let o=Number(r);return Number.isSafeInteger(o)?o:r.toString()}var pt=[{sql:"SELECT name, sql FROM main.sqlite_schema WHERE type = 'trigger' AND tbl_name = ? COLLATE NOCASE ORDER BY rowid",params:e=>[e],temporary:!1},{sql:"SELECT temp_trigger.name, temp_trigger.sql, EXISTS (SELECT 1 FROM sqlite_temp_schema AS temp_view WHERE temp_view.type = 'view' AND temp_view.name = ? COLLATE NOCASE) FROM sqlite_temp_schema AS temp_trigger WHERE temp_trigger.type = 'trigger' AND temp_trigger.tbl_name = ? COLLATE NOCASE ORDER BY temp_trigger.rowid",params:e=>[e,e],temporary:!0}];function hr(e){return/[A-Za-z0-9_$\u0080-\uFFFF]/.test(e)}function br(e){let t=[],n=0;for(;nt.toLowerCase())}function Le(e,t){if(!ce(e[t]))throw new Error("Expected an SQL identifier");return t+1}function ss(e,t){return t=Le(e,t),e[t]?.kind==="symbol"&&e[t].value==="."&&(t=Le(e,t+1)),t}function gt(e){let t=br(e),n=[],r,o=0,i=u=>{if(!V(t[o],u))throw new Error(`Expected ${u} in stored CREATE TRIGGER SQL`);o++};if(i("CREATE"),(V(t[o],"TEMP")||V(t[o],"TEMPORARY"))&&o++,i("TRIGGER"),V(t[o],"IF")&&(o++,i("NOT"),i("EXISTS")),o=ss(t,o),V(t[o],"BEFORE")||V(t[o],"AFTER")?o++:V(t[o],"INSTEAD")&&(o++,i("OF")),V(t[o],"INSERT"))r="insert",o++;else if(V(t[o],"DELETE"))r="delete",o++;else if(V(t[o],"UPDATE")){if(r="update",o++,V(t[o],"OF")){if(o++,!ce(t[o]))throw new Error("Expected an SQL identifier after UPDATE OF");for(n.push(t[o]),o=Le(t,o);t[o]?.kind==="symbol"&&t[o].value===",";){if(o++,!ce(t[o]))throw new Error("Expected an SQL identifier in UPDATE OF column list");n.push(t[o]),o=Le(t,o)}}}else throw new Error("Expected a trigger event in stored CREATE TRIGGER SQL");i("ON");let l=o,s=t[o];o=Le(t,o);let a;t[o]?.kind==="symbol"&&t[o].value==="."&&(a=s.value,o=Le(t,o+1));let d=o,c=t.findIndex((u,f)=>f>=o&&V(u,"BEGIN"));if(c<0)throw new Error("Expected BEGIN in stored CREATE TRIGGER SQL");return{tokens:t,event:r,targetSchema:a,targetStartIndex:l,updateOfColumns:n,referenceStartIndex:d,bodyStartIndex:c+1}}function ln(e){let t=gt(e);return{event:t.event,targetSchema:t.targetSchema,updateOfColumns:t.updateOfColumns.map(n=>n.value)}}function yt(e,t,n,r){let o=ln(e),i=`${h(t)}.${h(n)}`;if(o.event==="insert")return`EXPLAIN INSERT INTO ${i} DEFAULT VALUES`;if(o.event==="delete")return`EXPLAIN DELETE FROM ${i} WHERE 0`;let l=new Map(r.map(c=>[ue(c),c])),s=o.updateOfColumns.map(c=>l.get(ue(c))).find(c=>c!==void 0);if(o.updateOfColumns.length>0&&s===void 0)return;let a=s??r[0];if(a===void 0)throw new Error(`Trigger target ${t}.${n} has no writable column to probe`);let d=h(a);return`EXPLAIN UPDATE ${i} SET ${d} = ${d} WHERE 0`}function as(e){return gt(e).targetSchema}function Q(e){return`main.${h(e)}`}function Cr(e,t){let n=`-- TRIGGER ${t}`;return e.some(r=>r.some(o=>o===n))}function Tr(e,t){if(t.length!==pt.length)throw new Error(`View trigger definition fetch was incomplete for ${e}`);let n=[],r=[],o=[];return pt.forEach((i,l)=>{t[l].forEach(s=>{if(typeof s[0]!="string"||typeof s[1]!="string")throw new Error(`View trigger definition is unavailable for ${e}`);if(i.temporary){let a=s[2]===1||s[2]===1n;if(s[2]!==0&&s[2]!==0n&&!a)throw new Error(`Temporary view shadow state is unavailable for ${e}`);let d;try{d=as(s[1])}catch(c){let u=c instanceof Error?c.message:String(c);throw new Error(`Unable to determine the target of temporary trigger ${s[0]}: ${u}`)}if(d!==void 0&&ue(d)!=="main")return;if(d===void 0){o.push({identifier:s[0],sql:s[1],temporary:!0});return}}n.push(i.temporary?{identifier:s[0],sql:s[1],temporary:!0}:{identifier:s[0],sql:s[1]})})}),{triggers:n,ambiguousTemporaryTriggerNames:r,unqualifiedTemporaryTriggers:o}}function Et(e){let t=e.ambiguousTemporaryTriggerNames??[];if(t.length===0)return;let n=t.map(r=>`"${r}"`).join(", ");throw new Error(`Cannot modify main view "${e.identifier}" because temporary trigger target ownership is ambiguous for ${n}. Each named trigger uses an unqualified ON target whose historical schema cannot be proven. Drop the TEMP trigger, or recreate it with an explicitly schema-qualified target, before editing or dropping the main view.`)}function Ee(e){let t=e.trim();if(!t)throw new Error("View SELECT definition is required");let n=-1,r,o=!1,i=!1;for(let l=0;l=0&&t[n]===";"?(t.slice(0,n).trimEnd()+t.slice(n+1)).trim():t}function Rr(e){let t=0,n=-1,r=-1;for(let o of br(e)){if(o.kind==="symbol"&&o.value==="("){t===0&&n===-1&&(n=o.start),t++;continue}if(o.kind==="symbol"&&o.value===")"){t===1&&n!==-1&&r===-1&&(r=o.end),t=Math.max(0,t-1);continue}if(t===0&&V(o,"AS"))return{selectStart:o.end,columnListSql:n!==-1&&r!==-1?e.slice(n,r):void 0}}throw new Error("Unable to locate the SELECT body in the stored view definition")}function xr(e){let{selectStart:t}=Rr(e);return Ee(e.slice(t))}function cn(e){return Rr(e).columnListSql}function Qe(e,t,n,r){let o=n??(r?.length?`(${r.map(i=>h(i)).join(", ")})`:void 0);return`CREATE VIEW ${h(e)}${o?` ${o}`:""} AS ${t}`}function un(e,t){let n=gt(e);if(n.targetSchema===void 0){let r=n.tokens[n.targetStartIndex];return`${e.slice(0,r.start)}main.${e.slice(r.start)}`}if(ue(n.targetSchema)!=="main")throw new Error(`Unable to recreate temporary trigger ${t}: target is not in main`);return e}function dn(e){if(!e.temporary)return e.sql;let t=/^(\s*CREATE\s+)(?:(?:TEMP|TEMPORARY)\s+)?(TRIGGER\b)/i;if(!t.test(e.sql))throw new Error(`Unable to recreate temporary trigger ${e.identifier}: stored SQL is not a CREATE TRIGGER statement`);return un(e.sql,e.identifier).replace(t,"$1TEMP $2")}var ls=new Set(["AS","CROSS","END","EXCEPT","FULL","GROUP","HAVING","INDEXED","INNER","INTERSECT","JOIN","LEFT","LIMIT","NATURAL","NOT","OFFSET","ON","ORDER","OUTER","RETURNING","RIGHT","SET","UNION","USING","VALUES","WHERE","WINDOW"]),cs=new Set(["END","EXCEPT","GROUP","HAVING","INTERSECT","LIMIT","OFFSET","ON","ORDER","RETURNING","SET","UNION","USING","VALUES","WHERE","WINDOW"]);function an(e,t){return e.push({parent:t,aliases:new Set,hasAmbiguousSource:!1}),e.length-1}function us(e){let{tokens:t,referenceStartIndex:n,bodyStartIndex:r}=e,o=[],i=new Array(t.length),l=new Map,s=[],a=[an(o)],d=!1;for(let c=n;c1&&a.pop()}else u.kind==="symbol"&&u.value===";"&&a.length===1&&(d=!0)}return{scopes:o,tokenScopes:i,matchingParentheses:l}}function ds(e,t){t&&/^(?:NEW|OLD)$/i.test(t)&&e.aliases.add(ue(t))}function wr(e,t,n,r){let o=r.scopes[n],i=t,l;if(e[i]?.kind==="symbol"&&e[i].value==="("){let a=r.matchingParentheses.get(i);if(a===void 0)return o.hasAmbiguousSource=!0,i+1;i=a+1}else if(ce(e[i])){if(l=e[i].value,i++,e[i]?.kind==="symbol"&&e[i].value==="."){if(!ce(e[i+1]))return o.hasAmbiguousSource=!0,i+1;l=e[i+1].value,i+=2}if(e[i]?.kind==="symbol"&&e[i].value==="("){let a=r.matchingParentheses.get(i);if(a===void 0)return o.hasAmbiguousSource=!0,i+1;i=a+1}}else return o.hasAmbiguousSource=!0,i+1;let s;if(V(e[i],"AS")){if(!ce(e[i+1]))return o.hasAmbiguousSource=!0,i+1;s=e[i+1].value,i+=2}else if(ce(e[i])){let a=e[i];a.kind==="word"&&ls.has(a.value.toUpperCase())||(s=a.value,i++)}return ds(o,s??l),i}function fs(e,t){let n=new Map;for(let r=e.referenceStartIndex;r{let o=t[r];return n.identifier===o.identifier&&n.sql===o.sql&&n.temporary===!0==(o.temporary===!0)})}var Nr="The view changed outside this editor. Reload before saving; the view was not modified.";function ht(e,t,n,r){if(e!==void 0&&!ps(e,t)||!gs(n,r))throw new Error(Nr)}function _r(e,t){if(e===null||t===null){if(e!==t)throw new Error(Nr);return}ht(e.sql,t.sql,e.triggers,t.triggers)}var ys=32,wt=1024;function pn(e){return e.replace(/[A-Z]/g,t=>t.toLowerCase())}function mn(e){return JSON.stringify(e.map(pn))}function fn(e,t,n,r,o){let i=[e,t,n];return mn(r===void 0||o===void 0?i:[...i,r,o])}function $r(e){let t=e instanceof Error?e.message:String(e);return t.length>500?`${t.slice(0,500)}...`:t}function St(e,t,n){if(!(e<=t))throw new Error(`View dependency validation refused to inspect ${e} ${n}; the fail-closed limit is ${t}`)}async function Es(e){let t=await e.queryRows("PRAGMA database_list"),n=[],r=new Set;for(let o of t){if(typeof o[1]!="string")throw new Error("SQLite returned invalid database-list metadata during view validation");let i=pn(o[1]);r.has(i)||(r.add(i),n.push(o[1]))}return r.has("temp")||n.unshift("temp"),St(n.length,ys,"database schemas"),n}async function hs(e,t){let n=[];for(let r of t){let o=wt-n.length;o<0&&St(n.length,wt,"schema objects");let i=await e.queryRows(`SELECT type, name, tbl_name, sql FROM ${h(r)}.sqlite_schema WHERE type IN ('view', 'trigger') ORDER BY type, name LIMIT ${o+1}`);for(let l of i){let[s,a,d,c]=l;if(s!=="view"&&s!=="trigger"||typeof a!="string"||typeof c!="string"||s==="trigger"&&typeof d!="string")throw new Error(`SQLite returned invalid ${r} schema metadata during view validation`);n.push({schema:r,kind:s,identifier:a,targetIdentifier:s==="trigger"?d:void 0,sql:c})}St(n.length,wt,"schema objects")}return n}async function ws(e,t,n){return(await e.queryRows(`SELECT 1 FROM ${h(t)}.sqlite_schema WHERE type IN ('table', 'view') AND name = ? COLLATE NOCASE LIMIT 1`,[n])).length>0}async function Ss(e,t,n){let r=ln(n.sql);if(r.targetSchema!==void 0)return[r.targetSchema];if(pn(n.schema)!=="temp")return[n.schema];let o=[];for(let i of t)await ws(e,i,n.targetIdentifier)&&o.push(i);return o.length>0?o:["main"]}async function bs(e,t,n){let r=await e.queryRows(`PRAGMA ${h(t)}.table_xinfo(${h(n)})`),o=[];for(let i of r){if(typeof i[1]!="string")throw new Error(`SQLite returned invalid column metadata for ${t}.${n}`);let l=i[6];l!==2&&l!==2n&&l!==3&&l!==3n&&o.push(i[1])}return o}async function Or(e){let t=await Es(e),n=await hs(e,t),r=new Map,o=[],i=new Map;for(let s of n){if(s.kind==="view"){o.push({key:fn("view",s.schema,s.identifier),kind:"view",schema:s.schema,identifier:s.identifier,sql:`EXPLAIN SELECT * FROM ${h(s.schema)}.${h(s.identifier)}`});continue}let a;try{a=await Ss(e,t,s)}catch(d){let c=fn("trigger",s.schema,s.identifier);r.set(c,{key:c,kind:"trigger",schema:s.schema,identifier:s.identifier,valid:!1,error:$r(d)});continue}for(let d of a){let c=s.targetIdentifier,u=fn("trigger",s.schema,s.identifier,d,c);try{let f=mn([d,c]),m=i.get(f);m||(m=bs(e,d,c),i.set(f,m));let y=yt(s.sql,d,c,await m);if(y===void 0){r.set(u,{key:u,kind:"trigger",schema:s.schema,identifier:s.identifier,targetSchema:d,targetIdentifier:c,valid:!0});continue}o.push({key:u,kind:"trigger",schema:s.schema,identifier:s.identifier,targetSchema:d,targetIdentifier:c,sql:y})}catch(f){r.set(u,{key:u,kind:"trigger",schema:s.schema,identifier:s.identifier,targetSchema:d,targetIdentifier:c,valid:!1,error:$r(f)})}}}St(o.length+r.size,wt,"view and trigger probes");let l=await e.compileStatements(o.map(s=>s.sql));if(l.length!==o.length)throw new Error("View dependency validation returned an incomplete probe result set");return o.forEach((s,a)=>{let d=l[a];r.set(s.key,{key:s.key,kind:s.kind,schema:s.schema,identifier:s.identifier,targetSchema:s.targetSchema,targetIdentifier:s.targetIdentifier,valid:d===void 0,...d===void 0?{}:{error:d}})}),r}function de(e,t){for(let n of e.values()){if(!n.valid)continue;let r=t.get(n.key);if(!r||r.valid)continue;let o=r.targetSchema&&r.targetIdentifier?` on ${r.targetSchema}.${r.targetIdentifier}`:"";throw new Error(`Schema change would break existing ${r.kind} "${r.schema}.${r.identifier}"${o}: ${r.error??"SQLite rejected it"}`)}}var Lr=1024*1024,vr=2e5;function Xe(e){return e.replace(/[A-Z]/g,t=>t.toLowerCase())}function Cs(e){return/[A-Za-z_\u0080-\uFFFF]/.test(e)}function Ts(e){return/[A-Za-z0-9_$\u0080-\uFFFF]/.test(e)}function Rs(e,t,n){let r=t+1,o="";for(;rLr)throw new Error(`Cannot inspect index dependency: definition exceeds ${Lr} characters`);let t=[],n=o=>{if(t.push(o),t.length>vr)throw new Error(`Cannot inspect index dependency: definition exceeds ${vr} tokens`)},r=0;for(;rs.kind==="word"&&s.value.toUpperCase()==="INDEX"),r=t.findIndex((s,a)=>a>n&&s.kind==="word"&&s.value.toUpperCase()==="ON"),o=t.findIndex((s,a)=>a>r&&s.kind==="symbol"&&s.value==="(");if(n<0||r<0||o<0)throw new Error("Cannot inspect index dependency: unsupported CREATE INDEX definition");let i=t.filter((s,a)=>a>=o&&s.kind==="symbol"&&s.value===";");if(i.length>1||i.length===1&&t.at(-1)!==i[0])throw new Error("Cannot inspect index dependency: multiple statements are not allowed");let l=i[0]?.start??e.length;return e.slice(t[o].start,l).trim()}function kr(e,t){let n=[...t],r=`${e}_dummy`,o=new Set(t.map(Xe));for(;o.has(Xe(r));)r+="_";return n.push(r),`CREATE TEMP TABLE ${h(e)} (${n.map(h).join(", ")})`}function Pr(e,t){let n=new Set(t.map(Xe));return e.filter(r=>n.has(Xe(r)))}function Br(e,t,n){let r=Is(n);return`CREATE INDEX temp.${h(t)} ON ${h(e)} ${r}`}function Dr(e,t,n={}){if(K(e,"Table name"),t.length===0)throw new Error("At least one column is required");if(!n||typeof n!="object"||Array.isArray(n)||n.withoutRowid!==void 0&&typeof n.withoutRowid!="boolean")throw new Error("Invalid Create Table options");let r=t.filter(s=>s.primaryKey);if(n.withoutRowid&&r.length===0)throw new Error("WITHOUT ROWID requires a primary key");let o=r.length>1,i=new Set,l=t.map(s=>{if(typeof s=="string")throw new Error("Legacy string column definitions not supported for security");K(s.name,"Column name"),sn(s.type);let a=Xe(s.name);if(i.has(a))throw new Error(`Column ${JSON.stringify(s.name)} is defined more than once`);i.add(a);let d=`${h(s.name)} ${s.type}`;return s.primaryKey&&!o&&(d+=" PRIMARY KEY"),s.notNull&&(d+=" NOT NULL"),d+=As(s.defaultValue),d});return o&&l.push(`PRIMARY KEY (${r.map(s=>h(s.name)).join(", ")})`),`CREATE TABLE ${R(e)} (${l.join(", ")})${n.withoutRowid?" WITHOUT ROWID":""}`}function As(e){return e==null||e===""?"":e.toLowerCase()==="null"?" DEFAULT NULL":/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(e)?` DEFAULT ${e}`:` DEFAULT '${e.replace(/'/g,"''")}'`}var Ns=new Set(["=","+","-","@","\uFF1D","\uFF0B","\uFF0D","\uFF20"]),_s=/^(?:\p{White_Space}|\p{Cc}|\p{Cf})$/u;function Mr(){return{dangerousPrefix:!1,prefixOpen:!0,needsQuotes:!1}}function Ur(e,t){if((t.includes(",")||t.includes('"')||t.includes(` -`)||t.includes("\r"))&&(e.needsQuotes=!0),!!e.prefixOpen)for(let n of t){if(Ns.has(n)){e.dangerousPrefix=!0,e.needsQuotes=!0,e.prefixOpen=!1;return}if(!_s.test(n)){e.prefixOpen=!1;return}}}function $s(e){let t=Mr();Ur(t,e);let n=t.dangerousPrefix?`'${e}`:e;return t.needsQuotes?`"${n.replace(/"/g,'""')}"`:n}function Os(e,t){return e==="sql"?{prefix:"CAST(X'",suffix:"' AS TEXT)",byteEncoding:"hex"}:e==="json"?{prefix:`{"$sqliteExplorerTextBytes":{"encoding":${JSON.stringify(t)},"base64":"`,suffix:'"}}',byteEncoding:"base64"}:{prefix:`[SQLite TEXT bytes; encoding=${t}; base64=`,suffix:"]",byteEncoding:"base64"}}var fe="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function Vr(e){let t="",n=0;for(;n+2>>18&63]+fe[o>>>12&63]+fe[o>>>6&63]+fe[o&63]}let r=e.length-n;if(r===1){let o=e[n]<<16;t+=fe[o>>>18&63]+fe[o>>>12&63]+"=="}else if(r===2){let o=e[n]<<16|e[n+1]<<8;t+=fe[o>>>18&63]+fe[o>>>12&63]+fe[o>>>6&63]+"="}return t}function gn(e){let t=typeof e=="bigint"?e.toString():typeof e=="string"?e:void 0;if(t===void 0)throw new Error("SQLite returned invalid exact INTEGER text for export");try{if(BigInt(t).toString()!==t)throw new Error}catch{throw new Error("SQLite returned non-canonical INTEGER text for export")}return t}function Ls(e){if(!(e instanceof Uint8Array))throw new Error("SQLite returned invalid BLOB data for export");return e}function yn(e,t){let n=e.unrepresentableTextBytes;if(n===void 0)return;if(e.storageClass!=="text"||!(n instanceof Uint8Array)||!e.textEncoding)throw new Error("SQLite returned invalid unrepresentable TEXT export metadata");let r=Os(t,e.textEncoding),o=r.byteEncoding==="hex"?Array.from(n,i=>i.toString(16).padStart(2,"0")).join(""):Vr(n);return r.prefix+o+r.suffix}function En(e){let t=yn(e,"csv");return t!==void 0?t:e.storageClass==="null"?"":e.storageClass==="blob"?"[BLOB]":e.storageClass==="integer"?gn(e.value):e.storageClass==="text"?$s(String(e.value)):String(e.value)}function qr(e){let t=yn(e,"json");return t!==void 0?t:e.storageClass==="integer"?gn(e.value):e.storageClass==="blob"?JSON.stringify(Vr(Ls(e.value))):JSON.stringify(e.value)??"null"}function Wr(e){let t=yn(e,"sql");return t!==void 0?t:e.storageClass==="integer"?gn(e.value):Er(e.value)}var vs="__sqlite_explorer_numeric_source",ks="__sqlite_explorer_numeric_value_",Ps="__sqlite_explorer_numeric_text_",Fr="__sqlite_explorer_numeric_rowid",Bs="__sqlite_explorer_numeric_rowid_text_",Ds=2e3,Hr=999,bt=32766,Ge=`SELECT 1 FROM pragma.pragma_table_list AS target WHERE "schema" = 'main' AND "name" = ? AND (("type" IN ('table', 'shadow') AND "wr" = 0) OR "type" = 'virtual') AND (NOT EXISTS (SELECT 1 FROM pragma.pragma_table_info(?, 'main') WHERE lower("name") = 'rowid') OR ("type" = 'table' AND (SELECT count(*) FROM pragma.pragma_table_info(target."name", 'main') WHERE "pk" > 0) = 1 AND EXISTS (SELECT 1 FROM pragma.pragma_table_info(target."name", 'main') WHERE lower("name") = 'rowid' AND lower(trim("type")) = 'integer' AND "pk" = 1) AND NOT EXISTS (SELECT 1 FROM pragma.pragma_index_list(target."name", 'main') WHERE "origin" = 'pk'))) LIMIT 1`,Kr=`SELECT info."name" FROM pragma.pragma_table_list AS target JOIN pragma.pragma_table_info(target."name", 'main') AS info WHERE target."schema" = 'main' AND target."name" = ? AND target."type" = 'table' AND target."wr" = 0 AND info."pk" = 1 AND lower(trim(info."type")) = 'integer' AND (SELECT count(*) FROM pragma.pragma_table_info(target."name", 'main') WHERE "pk" > 0) = 1 AND NOT EXISTS (SELECT 1 FROM pragma.pragma_index_list(target."name", 'main') WHERE "origin" = 'pk') LIMIT 2`,jr=`SELECT info."cid", info."name", info."type", info."notnull", info."dflt_value", info."pk", info."hidden", CASE WHEN target."type" = 'table' AND target."wr" = 0 AND info."pk" = 1 AND lower(trim(info."type")) = 'integer' AND (SELECT count(*) FROM pragma.pragma_table_info(target."name", 'main') WHERE "pk" > 0) = 1 AND NOT EXISTS (SELECT 1 FROM pragma.pragma_index_list(target."name", 'main') WHERE "origin" = 'pk') THEN 1 ELSE 0 END AS is_rowid_alias FROM pragma.pragma_table_list AS target JOIN pragma.pragma_table_xinfo(target."name", 'main') AS info WHERE target."schema" = 'main' AND target."name" = ? ORDER BY info."cid"`;function zr(e,t){if(e.length!==0){if(e.length!==1||e[0].length<1||typeof e[0][0]!="string")throw new Error(`SQLite returned invalid rowid-alias metadata for ${t}`);return e[0][0]}}function Ct(e){return e.replace(/[A-Z]/g,t=>String.fromCharCode(t.charCodeAt(0)+32))}function ve(e,t){return Ct(e)===Ct(t)}function Qr(e,t){let n=BigInt(Number.MAX_SAFE_INTEGER),r=BigInt(Number.MIN_SAFE_INTEGER);return e.some(o=>{let i=o[t];return typeof i=="bigint"&&(i>n||i`${ks}${f}`),r=Array.from({length:t},(u,f)=>`${Ps}${f}`),o=h(vs),i=n.map(h),l=t*2<=Ds,s=i.map((u,f)=>`CASE WHEN typeof(${u}) = 'real' THEN CAST(${u} AS TEXT) END AS ${h(r[f])}`),a=l?[...i,...s]:i,d=l?[...n,...r]:n,c={sql:`WITH ${o} (${i.join(", ")}) AS ( +/*! sqlite-viewer-bundle-sha256:f4701a143ec7e3461d92f779f6aa5bdac17e1cbb15a84a2e2184168888784236 */ +"use strict";(()=>{var rs=Object.defineProperty;var os=(e,t,n)=>t in e?rs(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var D=(e,t,n)=>os(e,typeof t!="symbol"?t+"":t,n);function h(e){return`"${e.replace(/"/g,'""')}"`}function R(e){return`main.${h(e)}`}function K(e,t="Identifier"){if(typeof e!="string"||e.length===0)throw new Error(`${t} is required`);if(e.includes("\0"))throw new Error(`${t} cannot contain NUL characters`)}function an(e){if(!e||typeof e!="string")throw new Error("Invalid SQL type: Type must be a non-empty string");if(/['";\-\/\*]/.test(e))throw new Error(`Invalid SQL type: "${e}" contains potentially unsafe characters`);if(!/^[a-zA-Z0-9_\s]+(?:\([0-9\s,]+\)[a-zA-Z0-9_\s]*)?$/.test(e.trim()))throw new Error(`Invalid SQL type: "${e}" does not match allowed format`)}function hr(e){if(e==null)return"NULL";if(typeof e=="number")return String(e);if(typeof e=="bigint")return e.toString();if(typeof e=="string"){if(e.includes("\0")){let n=new TextEncoder().encode(e);return`CAST(X'${Array.from(n).map(o=>o.toString(16).padStart(2,"0")).join("")}' AS TEXT)`}return`'${e.replace(/'/g,"''")}'`}return e instanceof Uint8Array?`X'${Array.from(e).map(n=>n.toString(16).padStart(2,"0")).join("")}'`:`'${String(e).replace(/'/g,"''")}'`}function ze(e,t="\\"){let n=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`[${n}%_]`,"g");return e.replace(r,o=>t+o)}var is=-9223372036854775808n,ss=9223372036854775807n;function M(e){let t=typeof e;if(t!=="string"&&t!=="number"&&t!=="bigint")throw new Error(`Invalid rowid: ${e}`);if(typeof e=="number"){if(!Number.isSafeInteger(e))throw new Error(`Invalid rowid: ${e}`);return e}let n=typeof e=="string"?e.trim():e.toString();if(!/^[+-]?\d+$/.test(n))throw new Error(`Invalid rowid: ${e}`);let r=BigInt(n);if(rss)throw new Error(`Invalid rowid: ${e}`);let o=Number(r);return Number.isSafeInteger(o)?o:r.toString()}var pt=[{sql:"SELECT name, sql FROM main.sqlite_schema WHERE type = 'trigger' AND tbl_name = ? COLLATE NOCASE ORDER BY rowid",params:e=>[e],temporary:!1},{sql:"SELECT temp_trigger.name, temp_trigger.sql, EXISTS (SELECT 1 FROM sqlite_temp_schema AS temp_view WHERE temp_view.type = 'view' AND temp_view.name = ? COLLATE NOCASE) FROM sqlite_temp_schema AS temp_trigger WHERE temp_trigger.type = 'trigger' AND temp_trigger.tbl_name = ? COLLATE NOCASE ORDER BY temp_trigger.rowid",params:e=>[e,e],temporary:!0}];function wr(e){return/[A-Za-z0-9_$\u0080-\uFFFF]/.test(e)}function Cr(e){let t=[],n=0;for(;nt.toLowerCase())}function Le(e,t){if(!ce(e[t]))throw new Error("Expected an SQL identifier");return t+1}function as(e,t){return t=Le(e,t),e[t]?.kind==="symbol"&&e[t].value==="."&&(t=Le(e,t+1)),t}function gt(e){let t=Cr(e),n=[],r,o=0,i=u=>{if(!V(t[o],u))throw new Error(`Expected ${u} in stored CREATE TRIGGER SQL`);o++};if(i("CREATE"),(V(t[o],"TEMP")||V(t[o],"TEMPORARY"))&&o++,i("TRIGGER"),V(t[o],"IF")&&(o++,i("NOT"),i("EXISTS")),o=as(t,o),V(t[o],"BEFORE")||V(t[o],"AFTER")?o++:V(t[o],"INSTEAD")&&(o++,i("OF")),V(t[o],"INSERT"))r="insert",o++;else if(V(t[o],"DELETE"))r="delete",o++;else if(V(t[o],"UPDATE")){if(r="update",o++,V(t[o],"OF")){if(o++,!ce(t[o]))throw new Error("Expected an SQL identifier after UPDATE OF");for(n.push(t[o]),o=Le(t,o);t[o]?.kind==="symbol"&&t[o].value===",";){if(o++,!ce(t[o]))throw new Error("Expected an SQL identifier in UPDATE OF column list");n.push(t[o]),o=Le(t,o)}}}else throw new Error("Expected a trigger event in stored CREATE TRIGGER SQL");i("ON");let l=o,s=t[o];o=Le(t,o);let a;t[o]?.kind==="symbol"&&t[o].value==="."&&(a=s.value,o=Le(t,o+1));let d=o,c=t.findIndex((u,f)=>f>=o&&V(u,"BEGIN"));if(c<0)throw new Error("Expected BEGIN in stored CREATE TRIGGER SQL");return{tokens:t,event:r,targetSchema:a,targetStartIndex:l,updateOfColumns:n,referenceStartIndex:d,bodyStartIndex:c+1}}function cn(e){let t=gt(e);return{event:t.event,targetSchema:t.targetSchema,updateOfColumns:t.updateOfColumns.map(n=>n.value)}}function yt(e,t,n,r){let o=cn(e),i=`${h(t)}.${h(n)}`;if(o.event==="insert")return`EXPLAIN INSERT INTO ${i} DEFAULT VALUES`;if(o.event==="delete")return`EXPLAIN DELETE FROM ${i} WHERE 0`;let l=new Map(r.map(c=>[ue(c),c])),s=o.updateOfColumns.map(c=>l.get(ue(c))).find(c=>c!==void 0);if(o.updateOfColumns.length>0&&s===void 0)return;let a=s??r[0];if(a===void 0)throw new Error(`Trigger target ${t}.${n} has no writable column to probe`);let d=h(a);return`EXPLAIN UPDATE ${i} SET ${d} = ${d} WHERE 0`}function ls(e){return gt(e).targetSchema}function Q(e){return`main.${h(e)}`}function Tr(e,t){let n=`-- TRIGGER ${t}`;return e.some(r=>r.some(o=>o===n))}function Rr(e,t){if(t.length!==pt.length)throw new Error(`View trigger definition fetch was incomplete for ${e}`);let n=[],r=[],o=[];return pt.forEach((i,l)=>{t[l].forEach(s=>{if(typeof s[0]!="string"||typeof s[1]!="string")throw new Error(`View trigger definition is unavailable for ${e}`);if(i.temporary){let a=s[2]===1||s[2]===1n;if(s[2]!==0&&s[2]!==0n&&!a)throw new Error(`Temporary view shadow state is unavailable for ${e}`);let d;try{d=ls(s[1])}catch(c){let u=c instanceof Error?c.message:String(c);throw new Error(`Unable to determine the target of temporary trigger ${s[0]}: ${u}`)}if(d!==void 0&&ue(d)!=="main")return;if(d===void 0){o.push({identifier:s[0],sql:s[1],temporary:!0});return}}n.push(i.temporary?{identifier:s[0],sql:s[1],temporary:!0}:{identifier:s[0],sql:s[1]})})}),{triggers:n,ambiguousTemporaryTriggerNames:r,unqualifiedTemporaryTriggers:o}}function Et(e){let t=e.ambiguousTemporaryTriggerNames??[];if(t.length===0)return;let n=t.map(r=>`"${r}"`).join(", ");throw new Error(`Cannot modify main view "${e.identifier}" because temporary trigger target ownership is ambiguous for ${n}. Each named trigger uses an unqualified ON target whose historical schema cannot be proven. Drop the TEMP trigger, or recreate it with an explicitly schema-qualified target, before editing or dropping the main view.`)}function Ee(e){let t=e.trim();if(!t)throw new Error("View SELECT definition is required");let n=-1,r,o=!1,i=!1;for(let l=0;l=0&&t[n]===";"?(t.slice(0,n).trimEnd()+t.slice(n+1)).trim():t}function xr(e){let t=0,n=-1,r=-1;for(let o of Cr(e)){if(o.kind==="symbol"&&o.value==="("){t===0&&n===-1&&(n=o.start),t++;continue}if(o.kind==="symbol"&&o.value===")"){t===1&&n!==-1&&r===-1&&(r=o.end),t=Math.max(0,t-1);continue}if(t===0&&V(o,"AS"))return{selectStart:o.end,columnListSql:n!==-1&&r!==-1?e.slice(n,r):void 0}}throw new Error("Unable to locate the SELECT body in the stored view definition")}function Ir(e){let{selectStart:t}=xr(e);return Ee(e.slice(t))}function un(e){return xr(e).columnListSql}function Qe(e,t,n,r){let o=n??(r?.length?`(${r.map(i=>h(i)).join(", ")})`:void 0);return`CREATE VIEW ${h(e)}${o?` ${o}`:""} AS ${t}`}function dn(e,t){let n=gt(e);if(n.targetSchema===void 0){let r=n.tokens[n.targetStartIndex];return`${e.slice(0,r.start)}main.${e.slice(r.start)}`}if(ue(n.targetSchema)!=="main")throw new Error(`Unable to recreate temporary trigger ${t}: target is not in main`);return e}function fn(e){if(!e.temporary)return e.sql;let t=/^(\s*CREATE\s+)(?:(?:TEMP|TEMPORARY)\s+)?(TRIGGER\b)/i;if(!t.test(e.sql))throw new Error(`Unable to recreate temporary trigger ${e.identifier}: stored SQL is not a CREATE TRIGGER statement`);return dn(e.sql,e.identifier).replace(t,"$1TEMP $2")}var cs=new Set(["AS","CROSS","END","EXCEPT","FULL","GROUP","HAVING","INDEXED","INNER","INTERSECT","JOIN","LEFT","LIMIT","NATURAL","NOT","OFFSET","ON","ORDER","OUTER","RETURNING","RIGHT","SET","UNION","USING","VALUES","WHERE","WINDOW"]),us=new Set(["END","EXCEPT","GROUP","HAVING","INTERSECT","LIMIT","OFFSET","ON","ORDER","RETURNING","SET","UNION","USING","VALUES","WHERE","WINDOW"]);function ln(e,t){return e.push({parent:t,aliases:new Set,hasAmbiguousSource:!1}),e.length-1}function ds(e){let{tokens:t,referenceStartIndex:n,bodyStartIndex:r}=e,o=[],i=new Array(t.length),l=new Map,s=[],a=[ln(o)],d=!1;for(let c=n;c1&&a.pop()}else u.kind==="symbol"&&u.value===";"&&a.length===1&&(d=!0)}return{scopes:o,tokenScopes:i,matchingParentheses:l}}function fs(e,t){t&&/^(?:NEW|OLD)$/i.test(t)&&e.aliases.add(ue(t))}function Sr(e,t,n,r){let o=r.scopes[n],i=t,l;if(e[i]?.kind==="symbol"&&e[i].value==="("){let a=r.matchingParentheses.get(i);if(a===void 0)return o.hasAmbiguousSource=!0,i+1;i=a+1}else if(ce(e[i])){if(l=e[i].value,i++,e[i]?.kind==="symbol"&&e[i].value==="."){if(!ce(e[i+1]))return o.hasAmbiguousSource=!0,i+1;l=e[i+1].value,i+=2}if(e[i]?.kind==="symbol"&&e[i].value==="("){let a=r.matchingParentheses.get(i);if(a===void 0)return o.hasAmbiguousSource=!0,i+1;i=a+1}}else return o.hasAmbiguousSource=!0,i+1;let s;if(V(e[i],"AS")){if(!ce(e[i+1]))return o.hasAmbiguousSource=!0,i+1;s=e[i+1].value,i+=2}else if(ce(e[i])){let a=e[i];a.kind==="word"&&cs.has(a.value.toUpperCase())||(s=a.value,i++)}return fs(o,s??l),i}function ms(e,t){let n=new Map;for(let r=e.referenceStartIndex;r{let o=t[r];return n.identifier===o.identifier&&n.sql===o.sql&&n.temporary===!0==(o.temporary===!0)})}var _r="The view changed outside this editor. Reload before saving; the view was not modified.";function ht(e,t,n,r){if(e!==void 0&&!gs(e,t)||!ys(n,r))throw new Error(_r)}function $r(e,t){if(e===null||t===null){if(e!==t)throw new Error(_r);return}ht(e.sql,t.sql,e.triggers,t.triggers)}var Es=32,wt=1024;function gn(e){return e.replace(/[A-Z]/g,t=>t.toLowerCase())}function pn(e){return JSON.stringify(e.map(gn))}function mn(e,t,n,r,o){let i=[e,t,n];return pn(r===void 0||o===void 0?i:[...i,r,o])}function Or(e){let t=e instanceof Error?e.message:String(e);return t.length>500?`${t.slice(0,500)}...`:t}function St(e,t,n){if(!(e<=t))throw new Error(`View dependency validation refused to inspect ${e} ${n}; the fail-closed limit is ${t}`)}async function hs(e){let t=await e.queryRows("PRAGMA database_list"),n=[],r=new Set;for(let o of t){if(typeof o[1]!="string")throw new Error("SQLite returned invalid database-list metadata during view validation");let i=gn(o[1]);r.has(i)||(r.add(i),n.push(o[1]))}return r.has("temp")||n.unshift("temp"),St(n.length,Es,"database schemas"),n}async function ws(e,t){let n=[];for(let r of t){let o=wt-n.length;o<0&&St(n.length,wt,"schema objects");let i=await e.queryRows(`SELECT type, name, tbl_name, sql FROM ${h(r)}.sqlite_schema WHERE type IN ('view', 'trigger') ORDER BY type, name LIMIT ${o+1}`);for(let l of i){let[s,a,d,c]=l;if(s!=="view"&&s!=="trigger"||typeof a!="string"||typeof c!="string"||s==="trigger"&&typeof d!="string")throw new Error(`SQLite returned invalid ${r} schema metadata during view validation`);n.push({schema:r,kind:s,identifier:a,targetIdentifier:s==="trigger"?d:void 0,sql:c})}St(n.length,wt,"schema objects")}return n}async function Ss(e,t,n){return(await e.queryRows(`SELECT 1 FROM ${h(t)}.sqlite_schema WHERE type IN ('table', 'view') AND name = ? COLLATE NOCASE LIMIT 1`,[n])).length>0}async function bs(e,t,n){let r=cn(n.sql);if(r.targetSchema!==void 0)return[r.targetSchema];if(gn(n.schema)!=="temp")return[n.schema];let o=[];for(let i of t)await Ss(e,i,n.targetIdentifier)&&o.push(i);return o.length>0?o:["main"]}async function Cs(e,t,n){let r=await e.queryRows(`PRAGMA ${h(t)}.table_xinfo(${h(n)})`),o=[];for(let i of r){if(typeof i[1]!="string")throw new Error(`SQLite returned invalid column metadata for ${t}.${n}`);let l=i[6];l!==2&&l!==2n&&l!==3&&l!==3n&&o.push(i[1])}return o}async function Lr(e){let t=await hs(e),n=await ws(e,t),r=new Map,o=[],i=new Map;for(let s of n){if(s.kind==="view"){o.push({key:mn("view",s.schema,s.identifier),kind:"view",schema:s.schema,identifier:s.identifier,sql:`EXPLAIN SELECT * FROM ${h(s.schema)}.${h(s.identifier)}`});continue}let a;try{a=await bs(e,t,s)}catch(d){let c=mn("trigger",s.schema,s.identifier);r.set(c,{key:c,kind:"trigger",schema:s.schema,identifier:s.identifier,valid:!1,error:Or(d)});continue}for(let d of a){let c=s.targetIdentifier,u=mn("trigger",s.schema,s.identifier,d,c);try{let f=pn([d,c]),m=i.get(f);m||(m=Cs(e,d,c),i.set(f,m));let E=yt(s.sql,d,c,await m);if(E===void 0){r.set(u,{key:u,kind:"trigger",schema:s.schema,identifier:s.identifier,targetSchema:d,targetIdentifier:c,valid:!0});continue}o.push({key:u,kind:"trigger",schema:s.schema,identifier:s.identifier,targetSchema:d,targetIdentifier:c,sql:E})}catch(f){r.set(u,{key:u,kind:"trigger",schema:s.schema,identifier:s.identifier,targetSchema:d,targetIdentifier:c,valid:!1,error:Or(f)})}}}St(o.length+r.size,wt,"view and trigger probes");let l=await e.compileStatements(o.map(s=>s.sql));if(l.length!==o.length)throw new Error("View dependency validation returned an incomplete probe result set");return o.forEach((s,a)=>{let d=l[a];r.set(s.key,{key:s.key,kind:s.kind,schema:s.schema,identifier:s.identifier,targetSchema:s.targetSchema,targetIdentifier:s.targetIdentifier,valid:d===void 0,...d===void 0?{}:{error:d}})}),r}function de(e,t){for(let n of e.values()){if(!n.valid)continue;let r=t.get(n.key);if(!r||r.valid)continue;let o=r.targetSchema&&r.targetIdentifier?` on ${r.targetSchema}.${r.targetIdentifier}`:"";throw new Error(`Schema change would break existing ${r.kind} "${r.schema}.${r.identifier}"${o}: ${r.error??"SQLite rejected it"}`)}}var vr=1024*1024,kr=2e5;function Xe(e){return e.replace(/[A-Z]/g,t=>t.toLowerCase())}function Ts(e){return/[A-Za-z_\u0080-\uFFFF]/.test(e)}function Rs(e){return/[A-Za-z0-9_$\u0080-\uFFFF]/.test(e)}function xs(e,t,n){let r=t+1,o="";for(;rvr)throw new Error(`Cannot inspect index dependency: definition exceeds ${vr} characters`);let t=[],n=o=>{if(t.push(o),t.length>kr)throw new Error(`Cannot inspect index dependency: definition exceeds ${kr} tokens`)},r=0;for(;rs.kind==="word"&&s.value.toUpperCase()==="INDEX"),r=t.findIndex((s,a)=>a>n&&s.kind==="word"&&s.value.toUpperCase()==="ON"),o=t.findIndex((s,a)=>a>r&&s.kind==="symbol"&&s.value==="(");if(n<0||r<0||o<0)throw new Error("Cannot inspect index dependency: unsupported CREATE INDEX definition");let i=t.filter((s,a)=>a>=o&&s.kind==="symbol"&&s.value===";");if(i.length>1||i.length===1&&t.at(-1)!==i[0])throw new Error("Cannot inspect index dependency: multiple statements are not allowed");let l=i[0]?.start??e.length;return e.slice(t[o].start,l).trim()}function Pr(e,t){let n=[...t],r=`${e}_dummy`,o=new Set(t.map(Xe));for(;o.has(Xe(r));)r+="_";return n.push(r),`CREATE TEMP TABLE ${h(e)} (${n.map(h).join(", ")})`}function Br(e,t){let n=new Set(t.map(Xe));return e.filter(r=>n.has(Xe(r)))}function Dr(e,t,n){let r=As(n);return`CREATE INDEX temp.${h(t)} ON ${h(e)} ${r}`}function Mr(e,t,n={}){if(K(e,"Table name"),t.length===0)throw new Error("At least one column is required");if(!n||typeof n!="object"||Array.isArray(n)||n.withoutRowid!==void 0&&typeof n.withoutRowid!="boolean")throw new Error("Invalid Create Table options");let r=t.filter(s=>s.primaryKey);if(n.withoutRowid&&r.length===0)throw new Error("WITHOUT ROWID requires a primary key");let o=r.length>1,i=new Set,l=t.map(s=>{if(typeof s=="string")throw new Error("Legacy string column definitions not supported for security");K(s.name,"Column name"),an(s.type);let a=Xe(s.name);if(i.has(a))throw new Error(`Column ${JSON.stringify(s.name)} is defined more than once`);i.add(a);let d=`${h(s.name)} ${s.type}`;return s.primaryKey&&!o&&(d+=" PRIMARY KEY"),s.notNull&&(d+=" NOT NULL"),d+=Ns(s.defaultValue),d});return o&&l.push(`PRIMARY KEY (${r.map(s=>h(s.name)).join(", ")})`),`CREATE TABLE ${R(e)} (${l.join(", ")})${n.withoutRowid?" WITHOUT ROWID":""}`}function Ns(e){return e==null||e===""?"":e.toLowerCase()==="null"?" DEFAULT NULL":/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(e)?` DEFAULT ${e}`:` DEFAULT '${e.replace(/'/g,"''")}'`}var _s=new Set(["=","+","-","@","\uFF1D","\uFF0B","\uFF0D","\uFF20"]),$s=/^(?:\p{White_Space}|\p{Cc}|\p{Cf})$/u;function Ur(){return{dangerousPrefix:!1,prefixOpen:!0,needsQuotes:!1}}function Vr(e,t){if((t.includes(",")||t.includes('"')||t.includes(` +`)||t.includes("\r"))&&(e.needsQuotes=!0),!!e.prefixOpen)for(let n of t){if(_s.has(n)){e.dangerousPrefix=!0,e.needsQuotes=!0,e.prefixOpen=!1;return}if(!$s.test(n)){e.prefixOpen=!1;return}}}function Os(e){let t=Ur();Vr(t,e);let n=t.dangerousPrefix?`'${e}`:e;return t.needsQuotes?`"${n.replace(/"/g,'""')}"`:n}function Ls(e,t){return e==="sql"?{prefix:"CAST(X'",suffix:"' AS TEXT)",byteEncoding:"hex"}:e==="json"?{prefix:`{"$sqliteExplorerTextBytes":{"encoding":${JSON.stringify(t)},"base64":"`,suffix:'"}}',byteEncoding:"base64"}:{prefix:`[SQLite TEXT bytes; encoding=${t}; base64=`,suffix:"]",byteEncoding:"base64"}}var fe="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function qr(e){let t="",n=0;for(;n+2>>18&63]+fe[o>>>12&63]+fe[o>>>6&63]+fe[o&63]}let r=e.length-n;if(r===1){let o=e[n]<<16;t+=fe[o>>>18&63]+fe[o>>>12&63]+"=="}else if(r===2){let o=e[n]<<16|e[n+1]<<8;t+=fe[o>>>18&63]+fe[o>>>12&63]+fe[o>>>6&63]+"="}return t}function yn(e){let t=typeof e=="bigint"?e.toString():typeof e=="string"?e:void 0;if(t===void 0)throw new Error("SQLite returned invalid exact INTEGER text for export");try{if(BigInt(t).toString()!==t)throw new Error}catch{throw new Error("SQLite returned non-canonical INTEGER text for export")}return t}function vs(e){if(!(e instanceof Uint8Array))throw new Error("SQLite returned invalid BLOB data for export");return e}function En(e,t){let n=e.unrepresentableTextBytes;if(n===void 0)return;if(e.storageClass!=="text"||!(n instanceof Uint8Array)||!e.textEncoding)throw new Error("SQLite returned invalid unrepresentable TEXT export metadata");let r=Ls(t,e.textEncoding),o=r.byteEncoding==="hex"?Array.from(n,i=>i.toString(16).padStart(2,"0")).join(""):qr(n);return r.prefix+o+r.suffix}function hn(e){let t=En(e,"csv");return t!==void 0?t:e.storageClass==="null"?"":e.storageClass==="blob"?"[BLOB]":e.storageClass==="integer"?yn(e.value):e.storageClass==="text"?Os(String(e.value)):String(e.value)}function Wr(e){let t=En(e,"json");return t!==void 0?t:e.storageClass==="integer"?yn(e.value):e.storageClass==="blob"?JSON.stringify(qr(vs(e.value))):JSON.stringify(e.value)??"null"}function Fr(e){let t=En(e,"sql");return t!==void 0?t:e.storageClass==="integer"?yn(e.value):hr(e.value)}var ks="__sqlite_explorer_numeric_source",Ps="__sqlite_explorer_numeric_value_",Bs="__sqlite_explorer_numeric_text_",Hr="__sqlite_explorer_numeric_rowid",Ds="__sqlite_explorer_numeric_rowid_text_",Ms=2e3,Kr=999,bt=32766,Ge=`SELECT 1 FROM pragma.pragma_table_list AS target WHERE "schema" = 'main' AND "name" = ? AND (("type" IN ('table', 'shadow') AND "wr" = 0) OR "type" = 'virtual') AND (NOT EXISTS (SELECT 1 FROM pragma.pragma_table_info(?, 'main') WHERE lower("name") = 'rowid') OR ("type" = 'table' AND (SELECT count(*) FROM pragma.pragma_table_info(target."name", 'main') WHERE "pk" > 0) = 1 AND EXISTS (SELECT 1 FROM pragma.pragma_table_info(target."name", 'main') WHERE lower("name") = 'rowid' AND lower(trim("type")) = 'integer' AND "pk" = 1) AND NOT EXISTS (SELECT 1 FROM pragma.pragma_index_list(target."name", 'main') WHERE "origin" = 'pk'))) LIMIT 1`,jr=`SELECT info."name" FROM pragma.pragma_table_list AS target JOIN pragma.pragma_table_info(target."name", 'main') AS info WHERE target."schema" = 'main' AND target."name" = ? AND target."type" = 'table' AND target."wr" = 0 AND info."pk" = 1 AND lower(trim(info."type")) = 'integer' AND (SELECT count(*) FROM pragma.pragma_table_info(target."name", 'main') WHERE "pk" > 0) = 1 AND NOT EXISTS (SELECT 1 FROM pragma.pragma_index_list(target."name", 'main') WHERE "origin" = 'pk') LIMIT 2`,zr=`SELECT info."cid", info."name", info."type", info."notnull", info."dflt_value", info."pk", info."hidden", CASE WHEN target."type" = 'table' AND target."wr" = 0 AND info."pk" = 1 AND lower(trim(info."type")) = 'integer' AND (SELECT count(*) FROM pragma.pragma_table_info(target."name", 'main') WHERE "pk" > 0) = 1 AND NOT EXISTS (SELECT 1 FROM pragma.pragma_index_list(target."name", 'main') WHERE "origin" = 'pk') THEN 1 ELSE 0 END AS is_rowid_alias FROM pragma.pragma_table_list AS target JOIN pragma.pragma_table_xinfo(target."name", 'main') AS info WHERE target."schema" = 'main' AND target."name" = ? ORDER BY info."cid"`;function Qr(e,t){if(e.length!==0){if(e.length!==1||e[0].length<1||typeof e[0][0]!="string")throw new Error(`SQLite returned invalid rowid-alias metadata for ${t}`);return e[0][0]}}function Ct(e){return e.replace(/[A-Z]/g,t=>String.fromCharCode(t.charCodeAt(0)+32))}function ve(e,t){return Ct(e)===Ct(t)}function Xr(e,t){let n=BigInt(Number.MAX_SAFE_INTEGER),r=BigInt(Number.MIN_SAFE_INTEGER);return e.some(o=>{let i=o[t];return typeof i=="bigint"&&(i>n||i`${Ps}${f}`),r=Array.from({length:t},(u,f)=>`${Bs}${f}`),o=h(ks),i=n.map(h),l=t*2<=Ms,s=i.map((u,f)=>`CASE WHEN typeof(${u}) = 'real' THEN CAST(${u} AS TEXT) END AS ${h(r[f])}`),a=l?[...i,...s]:i,d=l?[...n,...r]:n,c={sql:`WITH ${o} (${i.join(", ")}) AS ( SELECT * FROM ( ${e} ) LIMIT -1 OFFSET 0 ) -SELECT ${a.join(", ")} FROM ${o}`,transportColumns:d};return l&&(c.valueColumnCount=t),c}function Xr(e,t,n){if(t.length<2||t[0].toLowerCase()!=="rowid"||n.length===0)return[];let r=t.slice(1),o=[];for(let i=0;ii+u+1),a=s.map(c=>`${Bs}${c}`),d=l.map((c,u)=>{let f=h(c);return`CASE WHEN typeof(${f}) = 'real' THEN CAST(${f} AS TEXT) END AS ${h(a[u])}`});for(let c=0;ctypeof m=="bigint"?m.toString():m);o.push({sql:`SELECT rowid AS ${h(Fr)}, ${d.join(", ")} FROM ${R(e)} WHERE rowid IN (${u.map(()=>"?").join(", ")})`,params:f,transportColumns:[Fr,...a],columnIndices:s})}}return o}function Gr(e,t){if(t.length===0)return;let n=new Map;e.forEach((o,i)=>{let l=o[0];if(!["bigint","number","string"].includes(typeof l))throw new Error(`Invalid rowid identity at source row ${i}`);let s=String(l);if(n.has(s))throw new Error(`Duplicate rowid identity at source row ${i}`);n.set(s,i)});let r;for(let{query:o,rows:i}of t)for(let l of i){if(l.length{let c=l[d+1];if(c==null)return;if(typeof c!="string")throw new Error(`Rowid exact REAL text at row ${s}, column ${a} is not text`);let u=e[s]?.[a];if(u===void 0)throw new Error(`Rowid exact REAL text is outside row ${s}, column ${a}`);c!==String(u)&&(r??(r={}),r[s]??(r[s]={}),r[s][a]=c)})}return r}function ke(e,t,n,r){let o,i=(s,a,d)=>{o??(o={}),o[s]??(o[s]={}),o[s][a]=d},l=e.map((s,a)=>{let d=t??s.length;if(t!==void 0&&s.length{let f=c;if(typeof c=="bigint"){let m=Number(c);if(Number.isSafeInteger(m))f=m;else{let y=c.toString();u===r?f=y:(i(a,u,y),f=m)}}if(t!==void 0){let m=s[t+u];if(m!=null){if(typeof m!="string")throw new Error(`Exact numeric text at row ${a}, column ${u} is not text`);m!==String(f)&&i(a,u,m)}}return f})});if(n)for(let[s,a]of Object.entries(n)){let d=Number(s);if(!Number.isInteger(d)||d<0||a===null||typeof a!="object")throw new Error(`Invalid exact numeric text row index: ${s}`);for(let[c,u]of Object.entries(a)){let f=Number(c);if(!Number.isInteger(f)||f<0||typeof u!="string")throw new Error(`Invalid exact numeric text entry at row ${s}, column ${c}`);let m=l[d]?.[f];if(m===void 0)throw new Error(`Exact numeric text entry is outside row ${s}, column ${c}`);u!==String(m)&&i(d,f,u)}}return o?{rows:l,exactIntegerTexts:o}:{rows:l}}var Je="pk:",wn=1,Tt="readonly-pk:",Yr=1,Jr=` +SELECT ${a.join(", ")} FROM ${o}`,transportColumns:d};return l&&(c.valueColumnCount=t),c}function Gr(e,t,n){if(t.length<2||t[0].toLowerCase()!=="rowid"||n.length===0)return[];let r=t.slice(1),o=[];for(let i=0;ii+u+1),a=s.map(c=>`${Ds}${c}`),d=l.map((c,u)=>{let f=h(c);return`CASE WHEN typeof(${f}) = 'real' THEN CAST(${f} AS TEXT) END AS ${h(a[u])}`});for(let c=0;ctypeof m=="bigint"?m.toString():m);o.push({sql:`SELECT rowid AS ${h(Hr)}, ${d.join(", ")} FROM ${R(e)} WHERE rowid IN (${u.map(()=>"?").join(", ")})`,params:f,transportColumns:[Hr,...a],columnIndices:s})}}return o}function Yr(e,t){if(t.length===0)return;let n=new Map;e.forEach((o,i)=>{let l=o[0];if(!["bigint","number","string"].includes(typeof l))throw new Error(`Invalid rowid identity at source row ${i}`);let s=String(l);if(n.has(s))throw new Error(`Duplicate rowid identity at source row ${i}`);n.set(s,i)});let r;for(let{query:o,rows:i}of t)for(let l of i){if(l.length{let c=l[d+1];if(c==null)return;if(typeof c!="string")throw new Error(`Rowid exact REAL text at row ${s}, column ${a} is not text`);let u=e[s]?.[a];if(u===void 0)throw new Error(`Rowid exact REAL text is outside row ${s}, column ${a}`);c!==String(u)&&(r??(r={}),r[s]??(r[s]={}),r[s][a]=c)})}return r}function ke(e,t,n,r){let o,i=(s,a,d)=>{o??(o={}),o[s]??(o[s]={}),o[s][a]=d},l=e.map((s,a)=>{let d=t??s.length;if(t!==void 0&&s.length{let f=c;if(typeof c=="bigint"){let m=Number(c);if(Number.isSafeInteger(m))f=m;else{let E=c.toString();u===r?f=E:(i(a,u,E),f=m)}}if(t!==void 0){let m=s[t+u];if(m!=null){if(typeof m!="string")throw new Error(`Exact numeric text at row ${a}, column ${u} is not text`);m!==String(f)&&i(a,u,m)}}return f})});if(n)for(let[s,a]of Object.entries(n)){let d=Number(s);if(!Number.isInteger(d)||d<0||a===null||typeof a!="object")throw new Error(`Invalid exact numeric text row index: ${s}`);for(let[c,u]of Object.entries(a)){let f=Number(c);if(!Number.isInteger(f)||f<0||typeof u!="string")throw new Error(`Invalid exact numeric text entry at row ${s}, column ${c}`);let m=l[d]?.[f];if(m===void 0)throw new Error(`Exact numeric text entry is outside row ${s}, column ${c}`);u!==String(m)&&i(d,f,u)}}return o?{rows:l,exactIntegerTexts:o}:{rows:l}}var Je="pk:",Sn=1,Tt="readonly-pk:",Jr=1,Zr=` SELECT tl."name" AS table_name, tl."type" AS object_type, @@ -21,36 +21,36 @@ FROM pragma.pragma_table_list AS tl LEFT JOIN pragma.pragma_table_info(tl."name", tl."schema") AS ti ON tl."type" IN ('table', 'shadow') AND tl."wr" = 1 WHERE tl."schema" = 'main' AND tl."name" NOT LIKE 'sqlite_%' -ORDER BY tl."name", ti."cid"`;function Ze(e){return new Error(`An UPDATE trigger changed or removed the rowid identity in ${e}; the edit was rolled back because SQLite Explorer cannot safely identify the resulting row.`)}var Zr=`SELECT "rootpage" FROM main.sqlite_schema WHERE "type" = 'table' AND "name" = ? LIMIT 2`;function eo(e,t){if(e.length!==1||e[0].length<1)throw new Error(`SQLite returned invalid table root-page metadata for ${t}`);let n=e[0][0],r=typeof n=="bigint"?Number(n):n;if(!Number.isSafeInteger(r)||Number(r)<0)throw new Error(`SQLite returned invalid table root-page metadata for ${t}`);return Number(r)}function Te(e){let t=typeof e=="bigint"?Number(e):e;return Number.isSafeInteger(t)?Number(t):void 0}function to(e,t,n,r="rowid"){if(!Number.isSafeInteger(t)||t<0)throw new Error(`SQLite returned invalid table root-page metadata for ${e}`);let o=!1,i=-1,l=0,s=!1,a,d=()=>{if(!a||a.isUserTrigger||!a.hasWrite)return;let c=a.prologueParameters,u=a.parametersAfterWrite,f=c.filter((y,g)=>g%2===1);c.length>0&&c.length%2===0&&f.every(y=>u.has(y))||(s=!0)};for(let c=0;c1?{isUserTrigger:m,hasWrite:!1,prologueParameters:[],parametersAfterWrite:new Set,prologueComplete:!1}:void 0;continue}if(a){if(u[1]==="Param"){let m=Te(u[2]);if(m===void 0)throw new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`);a.hasWrite?a.parametersAfterWrite.add(m):a.prologueComplete||a.prologueParameters.push(m);continue}u[1]==="OpenWrite"||u[1]==="Clear"?(a.prologueComplete=!0,a.hasWrite=!0):u[1].startsWith("Open")&&(a.prologueComplete=!0)}}if(d(),o)throw i<0?new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`):n.slice(i).some(u=>{if(u[1]==="OpenWrite"){let f=Te(u[3]),m=Te(u[4]);if(f===void 0||m===void 0)throw new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`);return f===t&&m===0}if(u[1]==="Clear"){let f=Te(u[2]),m=Te(u[3]);if(f===void 0||m===void 0)throw new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`);return f===t&&m===0}return!1})?new Error(`SQLite Explorer cannot prove whether an applicable UPDATE trigger changed or removed the ${r} identity in ${e}; the trigger can write the target table, so the edit was rolled back because SQLite cannot expose a trustworthy post-trigger ${r} identity.`):new Error(`Cannot update ${e} while an applicable UPDATE trigger can run; the operation was rolled back because trigger side effects cannot be represented safely in undo history.`);if(s)throw new Error(`Cannot update ${e} while a mutating foreign-key UPDATE action can run; the operation was rolled back because affected child rows are not represented in undo history.`)}function no(e,t,n){let r=0,o=!1;for(let i of n){if(i.length<6||typeof i[1]!="string")throw new Error(`SQLite returned invalid ${e} trigger metadata for ${t}`);let l=Te(i[0]);if(l===void 0)throw new Error(`SQLite returned invalid ${e} trigger metadata for ${t}`);if(i[1]==="Init"&&l===0){if(r+=1,typeof i[5]=="string"&&i[5].startsWith("-- TRIGGER "))throw new Error(`Cannot ${e.toLowerCase()} ${t} while an applicable ${e} trigger can run; the operation was rolled back because trigger side effects cannot be represented safely in undo history.`);continue}e==="DELETE"&&r>1&&(i[1]==="OpenWrite"||i[1]==="Clear")&&(o=!0)}if(o)throw new Error(`Cannot delete from ${t} while a mutating foreign-key DELETE action can run; the operation was rolled back because affected child rows are not represented in undo history.`)}function Ms(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function Us(e){let t=new Uint8Array(e.length/2);for(let n=0;n4096)throw new Error("Read-only primary-key reason must contain 1 through 4096 characters");if(!Number.isSafeInteger(t)||t<0)throw new Error(`Invalid read-only primary-key row ordinal: ${t}`);return Tt+encodeURIComponent(JSON.stringify({v:Yr,r:t,m:e}))}function qs(e){let t;try{t=JSON.parse(decodeURIComponent(e.slice(Tt.length)))}catch{throw new Error("Invalid read-only primary-key identity encoding")}if(!t||typeof t!="object"||Array.isArray(t)||Object.keys(t).length!==3||t.v!==Yr||!Number.isSafeInteger(t.r)||Number(t.r)<0||typeof t.m!="string"||String(t.m).length<1||String(t.m).length>4096)throw new Error("Invalid read-only primary-key identity payload");let n=t;if(Tt+encodeURIComponent(JSON.stringify(n))!==e)throw new Error("Read-only primary-key identity is not canonical");return n}function Re(e){if(Vs(e))throw new Error(qs(e).m)}function Pe(e,t){if(e.length===0||e.length!==t.length)throw new Error("Primary-key identity column/value count mismatch");let n={v:wn,c:e.map((r,o)=>[r.identifier,Rt(t[o])])};return Je+encodeURIComponent(JSON.stringify(n))}function io(e){if(!X(e))throw new Error(`Invalid primary-key identity: ${String(e)}`);let t,n;try{t=decodeURIComponent(e.slice(Je.length)),n=JSON.parse(t)}catch{throw new Error("Invalid primary-key identity encoding")}if(!n||typeof n!="object"||Array.isArray(n)||Object.keys(n).length!==2||n.v!==wn||!Array.isArray(n.c))throw new Error("Invalid primary-key identity payload");let r=n.c;if(r.length===0)throw new Error("Primary-key identity has no columns");let o=new Set,i=[],l=[],s=[],a=[];for(let c of r){if(!Array.isArray(c)||c.length!==2||typeof c[0]!="string")throw new Error("Invalid primary-key identity member");if(o.has(c[0]))throw new Error(`Duplicate primary-key identity column: ${c[0]}`);o.add(c[0]),i.push(c[0]);let u=ro(c[1]);l.push(u.value),s.push(u.storageClass),a.push(c[1])}if(Je+encodeURIComponent(JSON.stringify(n))!==e)throw new Error("Primary-key identity is not canonical");return{columns:i,values:l,storageClasses:s,encodedValues:a}}function so(e){let{columns:t,values:n}=io(e);return{columns:t,values:n}}function xt(e,t){Re(e);let n=io(e),r=t.columns.map(o=>o.identifier);if(n.columns.length!==r.length||n.columns.some((o,i)=>o!==r[i]))throw new Error(`Primary-key identity columns do not match the declared key (${r.join(", ")})`);return n}function Sn(e,t,n){let r=xt(e,t),o=new Map,i=new Set(t.columns.map(s=>s.identifier));for(let s of n){if(!i.has(s.column))throw new Error(`Primary-key replacement column is not declared: ${s.column}`);if(o.has(s.column))throw new Error(`Duplicate primary-key replacement column: ${s.column}`);o.set(s.column,s.value)}let l={v:wn,c:t.columns.map((s,a)=>[s.identifier,o.has(s.identifier)?Rt(o.get(s.identifier)):r.encodedValues[a]])};return Je+encodeURIComponent(JSON.stringify(l))}function hn(e){return e==="integer"?"CAST(? AS INTEGER)":"?"}function U(e,t){if(Re(e),t.kind==="rowid")return{sql:"rowid = ?",params:[M(e)]};let n=xt(e,t),r=t.columns.map(i=>i.identifier),o=r.map((i,l)=>hn(n.storageClasses[l]));return{sql:r.map((i,l)=>`${h(i)} = ${o[l]}`).join(" AND "),params:n.values,primaryKey:{columns:n.columns,values:n.values},primaryKeyIntegerCasts:o.map(i=>i!=="?")}}function Ws(e,t){if(e.length===0)throw new Error("At least one row identity is required");if(t.kind==="rowid"){let l=e.map(s=>U(s,t));return{sql:`rowid IN (${l.map(()=>"?").join(", ")})`,params:l.flatMap(s=>s.params)}}let n=e.map(l=>xt(l,t)),r=t.columns.map(l=>h(l.identifier)),o=n.flatMap(l=>l.values);if(r.length===1)return{sql:`${r[0]} IN (${n.map(l=>hn(l.storageClasses[0])).join(", ")})`,params:o};let i=n.map(l=>`(${l.storageClasses.map(s=>hn(s)).join(", ")})`);return{sql:`(${r.join(", ")}) IN (VALUES ${i.join(", ")})`,params:o}}function tt(e,t){if(e.length===0)throw new Error("At least one row identity is required");let n=new Set;for(let l of e){let s;if(t.kind==="rowid"?s=`rowid:${String(M(l))}`:(xt(l,t),s=`primaryKey:${String(l)}`),n.has(s))throw new Error("Duplicate row identities are not allowed");n.add(s)}let r=t.kind==="rowid"?1:t.columns.length,o=Math.max(1,Math.floor((bt-1)/r)),i=[];for(let l=0;lt.primaryKeyPosition>0).map(t=>({identifier:t.identifier,declaredType:t.declaredType,position:t.primaryKeyPosition})).sort((t,n)=>t.position-n.position)}var pc=2*1024*1024,gc=64*1024;async function lo(e,t,n,r){let o=`main.${h(e)}`;for(let i of n??[])await r(`DROP INDEX IF EXISTS main.${h(i)}`);for(let i of t)await r(`ALTER TABLE ${o} DROP COLUMN ${h(i)}`)}var Nt=1024*1024,me=16*1024*1024,Fs=256,Z=2*me,Hs=64*1024,nt=40,rt=512*1024,Rn=45,Ks=2,js="__sqlite_explorer_cell_source",zs="__sqlite_explorer_cell_value_",Qs="__sqlite_explorer_cell_metadata",go="__sqlite_explorer_cell_raw_text_",co=64*1024,uo=400,Xs=4,Tn=2e3;function It(e,t){return typeof e=="number"&&Number.isSafeInteger(e)&&e>0?e:t}function Gs(e,t){if(!Number.isSafeInteger(t)||t<1)throw new Error(`Cell containment requires a positive column count, got ${t}`);let n=It(e.maxInlineCellBytes,Nt),r=It(e.maxPageResponseBytes,me),i=It(e.limit,1)*t,l=Number.isSafeInteger(i)?Math.floor(r/i):0;if(!Number.isSafeInteger(i))return 0;let s=String(t-1).length+3,a=nt+Rn+s+Ks,d=Z-rt,c=Math.floor(d/i),u=Math.max(0,Math.floor((c-a)/4)*4),f=Math.floor(u/4)*3;return Math.min(n,l,Math.max(Fs,f))}function Ys(e,t){return`typeof(${e}) IN ('text', 'blob') AND octet_length(${e}) > ${t}`}function Js(e,t){return`CASE WHEN ${Ys(e,t)} THEN CASE typeof(${e}) WHEN 'text' THEN 't' ELSE 'b' END || CAST(octet_length(${e}) AS TEXT) ELSE '' END`}function Zs(e,t){let n=[];for(let r=0;rJs(l,t)).map((l,s)=>`${s===0?"SELECT":"UNION ALL SELECT"} ${l} AS "cell"`).join(` +ORDER BY tl."name", ti."cid"`;function Ze(e){return new Error(`An UPDATE trigger changed or removed the rowid identity in ${e}; the edit was rolled back because SQLite Explorer cannot safely identify the resulting row.`)}var eo=`SELECT "rootpage" FROM main.sqlite_schema WHERE "type" = 'table' AND "name" = ? LIMIT 2`;function to(e,t){if(e.length!==1||e[0].length<1)throw new Error(`SQLite returned invalid table root-page metadata for ${t}`);let n=e[0][0],r=typeof n=="bigint"?Number(n):n;if(!Number.isSafeInteger(r)||Number(r)<0)throw new Error(`SQLite returned invalid table root-page metadata for ${t}`);return Number(r)}function Te(e){let t=typeof e=="bigint"?Number(e):e;return Number.isSafeInteger(t)?Number(t):void 0}function no(e,t,n,r="rowid"){if(!Number.isSafeInteger(t)||t<0)throw new Error(`SQLite returned invalid table root-page metadata for ${e}`);let o=!1,i=-1,l=0,s=!1,a,d=()=>{if(!a||a.isUserTrigger||!a.hasWrite)return;let c=a.prologueParameters,u=a.parametersAfterWrite,f=c.filter((E,g)=>g%2===1);c.length>0&&c.length%2===0&&f.every(E=>u.has(E))||(s=!0)};for(let c=0;c1?{isUserTrigger:m,hasWrite:!1,prologueParameters:[],parametersAfterWrite:new Set,prologueComplete:!1}:void 0;continue}if(a){if(u[1]==="Param"){let m=Te(u[2]);if(m===void 0)throw new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`);a.hasWrite?a.parametersAfterWrite.add(m):a.prologueComplete||a.prologueParameters.push(m);continue}u[1]==="OpenWrite"||u[1]==="Clear"?(a.prologueComplete=!0,a.hasWrite=!0):u[1].startsWith("Open")&&(a.prologueComplete=!0)}}if(d(),o)throw i<0?new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`):n.slice(i).some(u=>{if(u[1]==="OpenWrite"){let f=Te(u[3]),m=Te(u[4]);if(f===void 0||m===void 0)throw new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`);return f===t&&m===0}if(u[1]==="Clear"){let f=Te(u[2]),m=Te(u[3]);if(f===void 0||m===void 0)throw new Error(`SQLite returned invalid UPDATE trigger metadata for ${e}`);return f===t&&m===0}return!1})?new Error(`SQLite Explorer cannot prove whether an applicable UPDATE trigger changed or removed the ${r} identity in ${e}; the trigger can write the target table, so the edit was rolled back because SQLite cannot expose a trustworthy post-trigger ${r} identity.`):new Error(`Cannot update ${e} while an applicable UPDATE trigger can run; the operation was rolled back because trigger side effects cannot be represented safely in undo history.`);if(s)throw new Error(`Cannot update ${e} while a mutating foreign-key UPDATE action can run; the operation was rolled back because affected child rows are not represented in undo history.`)}function ro(e,t,n){let r=0,o=!1;for(let i of n){if(i.length<6||typeof i[1]!="string")throw new Error(`SQLite returned invalid ${e} trigger metadata for ${t}`);let l=Te(i[0]);if(l===void 0)throw new Error(`SQLite returned invalid ${e} trigger metadata for ${t}`);if(i[1]==="Init"&&l===0){if(r+=1,typeof i[5]=="string"&&i[5].startsWith("-- TRIGGER "))throw new Error(`Cannot ${e.toLowerCase()} ${t} while an applicable ${e} trigger can run; the operation was rolled back because trigger side effects cannot be represented safely in undo history.`);continue}e==="DELETE"&&r>1&&(i[1]==="OpenWrite"||i[1]==="Clear")&&(o=!0)}if(o)throw new Error(`Cannot delete from ${t} while a mutating foreign-key DELETE action can run; the operation was rolled back because affected child rows are not represented in undo history.`)}function Us(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function Vs(e){let t=new Uint8Array(e.length/2);for(let n=0;n4096)throw new Error("Read-only primary-key reason must contain 1 through 4096 characters");if(!Number.isSafeInteger(t)||t<0)throw new Error(`Invalid read-only primary-key row ordinal: ${t}`);return Tt+encodeURIComponent(JSON.stringify({v:Jr,r:t,m:e}))}function Ws(e){let t;try{t=JSON.parse(decodeURIComponent(e.slice(Tt.length)))}catch{throw new Error("Invalid read-only primary-key identity encoding")}if(!t||typeof t!="object"||Array.isArray(t)||Object.keys(t).length!==3||t.v!==Jr||!Number.isSafeInteger(t.r)||Number(t.r)<0||typeof t.m!="string"||String(t.m).length<1||String(t.m).length>4096)throw new Error("Invalid read-only primary-key identity payload");let n=t;if(Tt+encodeURIComponent(JSON.stringify(n))!==e)throw new Error("Read-only primary-key identity is not canonical");return n}function Re(e){if(qs(e))throw new Error(Ws(e).m)}function Pe(e,t){if(e.length===0||e.length!==t.length)throw new Error("Primary-key identity column/value count mismatch");let n={v:Sn,c:e.map((r,o)=>[r.identifier,Rt(t[o])])};return Je+encodeURIComponent(JSON.stringify(n))}function so(e){if(!X(e))throw new Error(`Invalid primary-key identity: ${String(e)}`);let t,n;try{t=decodeURIComponent(e.slice(Je.length)),n=JSON.parse(t)}catch{throw new Error("Invalid primary-key identity encoding")}if(!n||typeof n!="object"||Array.isArray(n)||Object.keys(n).length!==2||n.v!==Sn||!Array.isArray(n.c))throw new Error("Invalid primary-key identity payload");let r=n.c;if(r.length===0)throw new Error("Primary-key identity has no columns");let o=new Set,i=[],l=[],s=[],a=[];for(let c of r){if(!Array.isArray(c)||c.length!==2||typeof c[0]!="string")throw new Error("Invalid primary-key identity member");if(o.has(c[0]))throw new Error(`Duplicate primary-key identity column: ${c[0]}`);o.add(c[0]),i.push(c[0]);let u=oo(c[1]);l.push(u.value),s.push(u.storageClass),a.push(c[1])}if(Je+encodeURIComponent(JSON.stringify(n))!==e)throw new Error("Primary-key identity is not canonical");return{columns:i,values:l,storageClasses:s,encodedValues:a}}function ao(e){let{columns:t,values:n}=so(e);return{columns:t,values:n}}function xt(e,t){Re(e);let n=so(e),r=t.columns.map(o=>o.identifier);if(n.columns.length!==r.length||n.columns.some((o,i)=>o!==r[i]))throw new Error(`Primary-key identity columns do not match the declared key (${r.join(", ")})`);return n}function bn(e,t,n){let r=xt(e,t),o=new Map,i=new Set(t.columns.map(s=>s.identifier));for(let s of n){if(!i.has(s.column))throw new Error(`Primary-key replacement column is not declared: ${s.column}`);if(o.has(s.column))throw new Error(`Duplicate primary-key replacement column: ${s.column}`);o.set(s.column,s.value)}let l={v:Sn,c:t.columns.map((s,a)=>[s.identifier,o.has(s.identifier)?Rt(o.get(s.identifier)):r.encodedValues[a]])};return Je+encodeURIComponent(JSON.stringify(l))}function wn(e){return e==="integer"?"CAST(? AS INTEGER)":"?"}function U(e,t){if(Re(e),t.kind==="rowid")return{sql:"rowid = ?",params:[M(e)]};let n=xt(e,t),r=t.columns.map(i=>i.identifier),o=r.map((i,l)=>wn(n.storageClasses[l]));return{sql:r.map((i,l)=>`${h(i)} = ${o[l]}`).join(" AND "),params:n.values,primaryKey:{columns:n.columns,values:n.values},primaryKeyIntegerCasts:o.map(i=>i!=="?")}}function Fs(e,t){if(e.length===0)throw new Error("At least one row identity is required");if(t.kind==="rowid"){let l=e.map(s=>U(s,t));return{sql:`rowid IN (${l.map(()=>"?").join(", ")})`,params:l.flatMap(s=>s.params)}}let n=e.map(l=>xt(l,t)),r=t.columns.map(l=>h(l.identifier)),o=n.flatMap(l=>l.values);if(r.length===1)return{sql:`${r[0]} IN (${n.map(l=>wn(l.storageClasses[0])).join(", ")})`,params:o};let i=n.map(l=>`(${l.storageClasses.map(s=>wn(s)).join(", ")})`);return{sql:`(${r.join(", ")}) IN (VALUES ${i.join(", ")})`,params:o}}function tt(e,t){if(e.length===0)throw new Error("At least one row identity is required");let n=new Set;for(let l of e){let s;if(t.kind==="rowid"?s=`rowid:${String(M(l))}`:(xt(l,t),s=`primaryKey:${String(l)}`),n.has(s))throw new Error("Duplicate row identities are not allowed");n.add(s)}let r=t.kind==="rowid"?1:t.columns.length,o=Math.max(1,Math.floor((bt-1)/r)),i=[];for(let l=0;lt.primaryKeyPosition>0).map(t=>({identifier:t.identifier,declaredType:t.declaredType,position:t.primaryKeyPosition})).sort((t,n)=>t.position-n.position)}var yc=2*1024*1024,Ec=64*1024;async function co(e,t,n,r){let o=`main.${h(e)}`;for(let i of n??[])await r(`DROP INDEX IF EXISTS main.${h(i)}`);for(let i of t)await r(`ALTER TABLE ${o} DROP COLUMN ${h(i)}`)}var Nt=1024*1024,me=16*1024*1024,Hs=256,Z=2*me,Ks=64*1024,nt=40,rt=512*1024,xn=45,js=2,zs="__sqlite_explorer_cell_source",Qs="__sqlite_explorer_cell_value_",Xs="__sqlite_explorer_cell_metadata",yo="__sqlite_explorer_cell_raw_text_",uo=64*1024,fo=400,Gs=4,Rn=2e3;function It(e,t){return typeof e=="number"&&Number.isSafeInteger(e)&&e>0?e:t}function Ys(e,t){if(!Number.isSafeInteger(t)||t<1)throw new Error(`Cell containment requires a positive column count, got ${t}`);let n=It(e.maxInlineCellBytes,Nt),r=It(e.maxPageResponseBytes,me),i=It(e.limit,1)*t,l=Number.isSafeInteger(i)?Math.floor(r/i):0;if(!Number.isSafeInteger(i))return 0;let s=String(t-1).length+3,a=nt+xn+s+js,d=Z-rt,c=Math.floor(d/i),u=Math.max(0,Math.floor((c-a)/4)*4),f=Math.floor(u/4)*3;return Math.min(n,l,Math.max(Hs,f))}function Js(e,t){return`typeof(${e}) IN ('text', 'blob') AND octet_length(${e}) > ${t}`}function Zs(e,t){return`CASE WHEN ${Js(e,t)} THEN CASE typeof(${e}) WHEN 'text' THEN 't' ELSE 'b' END || CAST(octet_length(${e}) AS TEXT) ELSE '' END`}function ea(e,t){let n=[];for(let r=0;rZs(l,t)).map((l,s)=>`${s===0?"SELECT":"UNION ALL SELECT"} ${l} AS "cell"`).join(` `);n.push(`(SELECT group_concat("cell", '|') FROM ( ${i} -))`)}return n.join(" || '|' || ")}function _t(e,t,n,r=[],o="blob"){let i=Gs(n,t),l=Math.floor(i/Xs),s=Array.from({length:t},(_,b)=>`${zs}${b}`),a=s.map(h);if(new Set(r).size!==r.length||r.some(_=>!Number.isInteger(_)||_<0||_>=t))throw new Error("Cell containment raw-TEXT columns must be unique in-range indices");let d=r.length>0&&t+1+r.length>Tn,c=d?[]:r,u=a.map((_,b)=>`CASE WHEN typeof(${_}) = 'text' AND octet_length(${_}) > ${i} THEN substr(${_}, 1, ${l}) WHEN typeof(${_}) = 'blob' AND octet_length(${_}) > ${i} THEN substr(${_}, 1, ${i}) ELSE ${_} END AS ${h(s[b])}`),f=h(js),m=Zs(a,i),y=c.map((_,b)=>{let C=a[_];return`CASE WHEN typeof(${C}) = 'text' AND octet_length(${C}) <= ${i} THEN ${o==="hex"?`hex(CAST(${C} AS BLOB))`:`CAST(${C} AS BLOB)`} END AS ${h(`${go}${b}`)}`}),g=y.length>0?`, ${y.join(", ")}`:"",E=t+1>Tn,T=`WITH ${f} (${a.join(", ")}) AS${E?" MATERIALIZED":""} ( +))`)}return n.join(" || '|' || ")}function _t(e,t,n,r=[],o="blob"){let i=Ys(n,t),l=Math.floor(i/Gs),s=Array.from({length:t},(_,b)=>`${Qs}${b}`),a=s.map(h);if(new Set(r).size!==r.length||r.some(_=>!Number.isInteger(_)||_<0||_>=t))throw new Error("Cell containment raw-TEXT columns must be unique in-range indices");let d=r.length>0&&t+1+r.length>Rn,c=d?[]:r,u=a.map((_,b)=>`CASE WHEN typeof(${_}) = 'text' AND octet_length(${_}) > ${i} THEN substr(${_}, 1, ${l}) WHEN typeof(${_}) = 'blob' AND octet_length(${_}) > ${i} THEN substr(${_}, 1, ${i}) ELSE ${_} END AS ${h(s[b])}`),f=h(zs),m=ea(a,i),E=c.map((_,b)=>{let C=a[_];return`CASE WHEN typeof(${C}) = 'text' AND octet_length(${C}) <= ${i} THEN ${o==="hex"?`hex(CAST(${C} AS BLOB))`:`CAST(${C} AS BLOB)`} END AS ${h(`${yo}${b}`)}`}),g=E.length>0?`, ${E.join(", ")}`:"",y=t+1>Rn,T=`WITH ${f} (${a.join(", ")}) AS${y?" MATERIALIZED":""} ( SELECT * FROM ( ${e} ) LIMIT -1 OFFSET 0 ) -`,x=E?"":`, ${m} AS ${h(Qs)}`,A=E?` +`,x=y?"":`, ${m} AS ${h(Xs)}`,A=y?` UNION ALL -SELECT (SELECT COALESCE(group_concat(${m}, char(10)), '') FROM ${f})${t>1?`, ${Array(t-1).fill("NULL").join(", ")}`:""}`:"";return{sql:T+`SELECT ${u.join(", ")}${x}${g} FROM ${f}`+A,metadataTrailer:E,primaryTransportColumnCount:t+(E?0:1)+c.length,valueColumnCount:t,metadataColumnIndex:t,transportColumnCount:t+1+c.length,rawTextColumnStart:t+1,rawTextColumnCount:c.length,rawTextTransport:o,rawTextColumnIndices:c,rawTextValidationUnavailable:d,effectiveInlineCellBytes:i}}function yo(e,t,n){if(!n.metadataTrailer){if(t!==void 0)throw new Error("Cell containment received unexpected separate metadata rows");return e}if(t!==void 0)throw new Error("Cell containment metadata must come from the value statement");let r=e.at(-1);if(!r||r.length!==n.primaryTransportColumnCount)throw new Error("Cell containment metadata trailer is missing or malformed");if(typeof r[0]!="string"||r.slice(1).some(l=>l!==null))throw new Error("Cell containment metadata trailer is not one packed text value");let o=e.slice(0,-1),i=r[0]===""?[]:r[0].split(` -`);if(i.length!==o.length)throw new Error("Cell containment metadata row count does not match the value page");return o.map((l,s)=>{if(l.length{if(!s)return;let a={};for(let[d,c]of Object.entries(s)){let u=Number(d);a[u]={};for(let[f,m]of Object.entries(c))a[u][Number(f)+1]=m}return a},o=r(t.exactIntegerTexts),i;for(let s of[n,o])if(s){i??(i={});for(let[a,d]of Object.entries(s)){let c=Number(a);i[c]??(i[c]={}),Object.assign(i[c],d)}}let l=r(t.oversizedCells);return{rows:t.rows.map((s,a)=>[e[a],...s]),...l?{oversizedCells:l}:{},...i?{exactIntegerTexts:i}:{}}}function ho(e,t){let n,r=0,o,i=s=>{if(s>=48&&s<=57)return s-48;let a=s|32;return a>=97&&a<=102?a-87:-1},l=(s,a,d)=>{let c=typeof s=="string"?s.length/2:NaN;if(typeof s!="string"||!Number.isSafeInteger(c)||!Number.isSafeInteger(t.effectiveInlineCellBytes)||t.effectiveInlineCellBytes<0||c>t.effectiveInlineCellBytes)throw new Error(`Raw TEXT value at row ${a}, key ${d} is not bounded hexadecimal text`);if(c===0)return o??(o=new Uint8Array(0));let u;c>co?u=new Uint8Array(c):((!n||n.byteLength-r{if(s.length{let u=s[t.rawTextColumnStart+c];if(u!==null&&t.rawTextTransport==="hex")return l(u,a,c);if(u!==null&&!(u instanceof Uint8Array))throw new Error(`Raw TEXT value at row ${a}, key ${c} is not a BLOB`);return u})})}function wo(e){if(e.sourceRows.length===0||e.sourceColumnIndices.length===0)return;if(e.rawTextValidationUnavailable)return new Set(e.sourceRows.map((o,i)=>i));if(e.rawTextRows.length!==e.sourceRows.length)throw new Error("Raw TEXT validation row count does not match the source page");let t=e.sourceColumnIndices.map(o=>{let i=e.rawTextColumnIndices.indexOf(o);if(i<0)throw new Error(`Raw TEXT validation column ${o} was not projected`);return i}),n=new TextDecoder(e.textEncoding,{fatal:!0,ignoreBOM:!0}),r;return e.sourceRows.forEach((o,i)=>{let l=e.rawTextRows[i];if(!l||l.length!==e.rawTextColumnIndices.length)throw new Error(`Raw TEXT validation row ${i} has the wrong width`);for(let s=0;sArray.from(s)),n;if(e.contained.oversizedCells){n={};for(let[s,a]of Object.entries(e.contained.oversizedCells))n[Number(s)]={...a}}let r;if(e.contained.exactIntegerTexts){r={};for(let[s,a]of Object.entries(e.contained.exactIntegerTexts))r[Number(s)]={...a}}let o=Z-rt,i=Ot(t)+Lt(n)+vt(r),l=new TextDecoder(e.textEncoding,{fatal:!0,ignoreBOM:!0});if(e.sourceRows.forEach((s,a)=>{let d=e.rawTextRows[a];if(!d||d.length!==e.rawTextColumnIndices.length)throw new Error(`Raw TEXT containment row ${a} has the wrong width`);e.rawTextColumnIndices.forEach((c,u)=>{let f=s[c];if(typeof f!="string"||n?.[a]?.[c])return;let m=d[u];if(!(m instanceof Uint8Array))throw new Error(`Raw TEXT containment bytes are missing at row ${a}, column ${c}`);let y=!1;try{y=l.decode(m)===f}catch{y=!1}if(y)return;let g=t[a][c],E=bo(n,a,c);n??(n={}),n[a]??(n[a]={}),n[a][c]={storageClass:"text",byteLength:m.byteLength};let T=Math.max(0,o-i-E+re(g)),x=T>nt?Math.floor((T-nt)/4)*3:0,A=Math.min(m.byteLength,Hs,x);if(A===0)throw new Error(`Raw TEXT containment cannot retain an authoritative byte prefix for row ${a}, column ${c} within the webview transport limit`);let _=m.slice(0,A);t[a][c]=_,i+=re(_)-re(g)+E,r?.[a]&&(delete r[a][c],Object.keys(r[a]).length===0&&delete r[a])})}),i>o)throw new Error(`Raw TEXT containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:t,...n?{oversizedCells:n}:{},...r&&Object.keys(r).length>0?{exactIntegerTexts:r}:{}}}function ea(e,t,n){if(e==="")return;let r=/^([tb])([1-9]\d*)$/.exec(e);if(!r)throw new Error(`Invalid oversized-cell metadata at row ${t}, column ${n}`);let o=Number(r[2]);if(!Number.isSafeInteger(o))throw new Error(`Oversized-cell byte length is unsafe at row ${t}, column ${n}`);return{storageClass:r[1]==="t"?"text":"blob",byteLength:o}}function $t(e){let t=0;for(let n=0;n=55296&&r<=56319&&n+1=56320&&o<=57343?(t+=4,n++):t+=3}else t+=3}return t}function ta(e){if(typeof e=="string")return $t(e);if(e instanceof Uint8Array)return e.byteLength}function fo(e){return e==="text"?"":new Uint8Array(0)}function na(e){return 4*Math.ceil(e/3)}function re(e){return e instanceof Uint8Array?na(e.byteLength)+nt:typeof e=="string"?$t(e)+2:8}function he(e){return $t(e)+3}function Ot(e){let t=2+Math.max(0,e.length-1);for(let n of e){t+=2+Math.max(0,n.length-1);for(let r of n)t+=re(r)}return t}function Lt(e){if(!e)return 0;let t=Object.entries(e),n=2+Math.max(0,t.length-1);for(let[r,o]of t){n+=he(r);let i=Object.entries(o);n+=2+Math.max(0,i.length-1);for(let[l]of i)n+=he(l)+Rn}return n}function bo(e,t,n){if(e?.[t]?.[n])return 0;let r=he(String(n))+Rn;if(e?.[t])return 1+r;let i=he(String(t))+2+r;return e?1+i:2+i}function vt(e){if(!e)return 0;let t=Object.entries(e),n=2+Math.max(0,t.length-1);for(let[r,o]of t){n+=he(r);let i=Object.entries(o);n+=2+Math.max(0,i.length-1);for(let[l,s]of i)n+=he(l)+$t(s)+2}return n}function Co(e){if(!e)return 0;let t=Object.entries(e),n=2+Math.max(0,t.length-1);for(let[r,o]of t)n+=he(r)+re(o);return n}function kt(e,t,n,r=me){var y;let o=It(r,me),i,l=0,s=!1,a=[],d=(g,E,T)=>{var x;i??(i={}),i[g]??(i[g]={}),(x=i[g])[E]??(x[E]=T)},c=e.map((g,E)=>{if(g.length{let C=ea(_,E,b);C&&d(E,b,C);let N=A[b],I=ta(N);if(I===void 0||I===0)return;let L=C??{storageClass:typeof N=="string"?"text":"blob",byteLength:I};if(s||I>o-l){s=!0,d(E,b,L),A[b]=fo(L.storageClass);return}l+=I,a.push({rowIndex:E,columnIndex:b,metadata:L})}),A}),u;if(n)for(let[g,E]of Object.entries(n))for(let[T,x]of Object.entries(E)){let A=Number(T);A>=t||(u??(u={}),u[y=Number(g)]??(u[y]={}),u[Number(g)][A]=x)}let f=Z-rt,m=Ot(c)+Lt(i)+vt(u);for(let g=a.length-1;g>=0&&m>f;g--){let E=a[g],T=c[E.rowIndex][E.columnIndex],x=fo(E.metadata.storageClass),A=re(x)-re(T)+bo(i,E.rowIndex,E.columnIndex);A>=0||(d(E.rowIndex,E.columnIndex,E.metadata),c[E.rowIndex][E.columnIndex]=x,m+=A)}if(m>f)throw new Error(`Cell containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:c,...i?{oversizedCells:i}:{},...u?{exactIntegerTexts:u}:{}}}function mo(e,t){var r;if(!e)return;let n;for(let[o,i]of Object.entries(e))for(let[l,s]of Object.entries(i)){let a=Number(l);a>=t||(n??(n={}),n[r=Number(o)]??(n[r]={}),n[Number(o)][a+1]=s)}return n}function po(e,t){var r;if(!e)return;let n;for(let[o,i]of Object.entries(e))for(let[l,s]of Object.entries(i)){let a=Number(l);a!==t&&(n??(n={}),n[r=Number(o)]??(n[r]={}),n[Number(o)][a]=s)}return n}function To(e){let t=`Row is read-only because a declared "rowid" column shadows SQLite's intrinsic row identity.`,n=Number.isSafeInteger(e.rowOffset)&&(e.rowOffset??0)>=0?e.rowOffset:0,r,o=e.rows.map((d,c)=>{if(d.length===0)throw new Error(`Shadowed rowid result row ${c} has no identity slot`);let u=n+c;if(!Number.isSafeInteger(u))throw new Error("Shadowed rowid result ordinal exceeds the safe integer range");return r??(r={}),r[c]=t,[et(t,u),...d.slice(1)]}),i=po(e.oversizedCells,0),l=po(e.exactIntegerTexts,0),s=Z-rt;if(Ot(o)+Lt(i)+vt(l)+Co(r)>s)throw new Error(`Cell containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:o,...i?{oversizedCells:i}:{},...l?{exactIntegerTexts:l}:{},...r?{readOnlyRowReasons:r}:{}}}function At(e){return`"${e.length<=128?e:`${e.slice(0,125)}...`}"`}function Ro(e){let t=e.slice(0,8).map(At);return e.length>t.length?`${t.join(", ")}, and ${e.length-t.length} more`:t.join(", ")}function ra(e,t){if(e.length===1){let r=e[0];return`Row is read-only because WITHOUT ROWID primary-key column ${At(r.identifier)} is ${r.byteLength} bytes and exceeds the ${t}-byte inline limit; its identity was not transported.`}let n=e.slice(0,8).map(r=>`${At(r.identifier)} (${r.byteLength} bytes)`);return e.length>n.length&&n.push(`and ${e.length-n.length} more`),`Row is read-only because WITHOUT ROWID primary-key columns ${n.join(", ")} exceed the ${t}-byte inline limit; their identity was not transported.`}function xo(e){return e==="utf-8"?"UTF-8":e==="utf-16le"?"UTF-16LE":"UTF-16BE"}function xn(e){if(e.columns.length*2>Tn)throw new Error(`Cannot mint a byte-faithful WITHOUT ROWID identity with ${e.columns.length} primary-key columns within SQLite's result-column limit`);let t=e.columns.map(r=>h(r.identifier)),n=t.map((r,o)=>`CASE WHEN typeof(${r}) = 'text' THEN CAST(${r} AS BLOB) END AS `+h(`${go}${o}`));return[...t,...n].join(", ")}function In(e,t,n,r){let o=e.columns.length;if(t.length!==o*2)throw new Error(`${r}: SQLite returned an invalid primary-key validation row`);let i=t.slice(0,o),l=new TextDecoder(n,{fatal:!0,ignoreBOM:!0});for(let s=0;s{let E=e.sourceColumns.indexOf(g.identifier);if(E<0)throw new Error(`Primary-key column missing from table fetch: ${g.identifier}`);return E}),n=Number.isSafeInteger(e.rowOffset)&&(e.rowOffset??0)>=0?e.rowOffset:0,r,o,i=[],l=new TextDecoder(e.textEncoding,{fatal:!0,ignoreBOM:!0}),s=e.rawTextValidationUnavailable?[]:t.map(g=>{let E=e.rawTextColumnIndices.indexOf(g);if(E<0)throw new Error(`Primary-key raw TEXT column ${g} was not projected`);return E}),a=e.rows.map((g,E)=>{let T=e.identity.columns.flatMap((C,N)=>{let I=e.oversizedCells?.[E]?.[t[N]];return I?[{identifier:C.identifier,byteLength:I.byteLength}]:[]}),x=e.identityRows[E];if(!x)throw new Error(`Primary-key identity row missing at index ${E}`);let A=e.rawTextBytes[E];if(!e.rawTextValidationUnavailable&&(!A||A.length!==e.rawTextColumnIndices.length))throw new Error(`Primary-key raw TEXT row missing at index ${E}`);let _=e.rawTextValidationUnavailable?e.identity.columns.map(C=>C.identifier):e.identity.columns.flatMap((C,N)=>{let I=x[t[N]];if(typeof I!="string")return[];let L=e.oversizedCells?.[E]?.[t[N]];if(L&&L.byteLength>e.effectiveInlineCellBytes)return[];let w=A[s[N]];if(!(w instanceof Uint8Array))return[C.identifier];try{return l.decode(w)===I?[]:[C.identifier]}catch{return[C.identifier]}}),b;if(e.rawTextValidationUnavailable&&(o??(o=new Set),o.add(E)),_.length>0){let C=e.rawTextValidationUnavailable?ia(_):oa(_,e.textEncoding);r??(r={}),r[E]=C,o??(o=new Set),o.add(E),b=et(C,n+E)}else if(T.length>0){let C=ra(T,e.effectiveInlineCellBytes);r??(r={}),r[E]=C,b=et(C,n+E)}else b=Pe(e.identity.columns,t.map(C=>x[C])),i.push(E);return[b,...g.slice(0,e.visibleColumnCount)]}),d=mo(e.oversizedCells,e.visibleColumnCount),c=mo(e.exactIntegerTexts,e.visibleColumnCount),u=Z-rt,f=Ot(a)+Lt(d)+vt(c)+Co(r),m="Row is read-only because its encoded WITHOUT ROWID primary-key identity exceeds the page transport budget.",y=g=>{if(r?.[g]!==void 0)return 0;let E=he(String(g))+re(m);return r?1+E:2+E};for(let g=i.length-1;g>=0&&f>u;g--){let E=i[g],T=a[E][0],x=et(m,n+E),A=re(x)-re(T)+y(E);A>=0||(a[E][0]=x,r??(r={}),r[E]=m,f+=A)}if(f>u)throw new Error(`Cell containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:a,...d?{oversizedCells:d}:{},...c?{exactIntegerTexts:c}:{},...r?{readOnlyRowReasons:r}:{},...o?{unrepresentableTextKeyRows:o}:{}}}var Pt=1e3,Ao=4*1024*1024,No=64*1024,Bt=128;function _o(e){if(e.length>No)throw new Error("Query text exceeds 65,536 characters.");let t=Ee(e),n="",r=0,o=0;for(let i=0;i1?`, ${Array(t-1).fill("NULL").join(", ")}`:""}`:"";return{sql:T+`SELECT ${u.join(", ")}${x}${g} FROM ${f}`+A,metadataTrailer:y,primaryTransportColumnCount:t+(y?0:1)+c.length,valueColumnCount:t,metadataColumnIndex:t,transportColumnCount:t+1+c.length,rawTextColumnStart:t+1,rawTextColumnCount:c.length,rawTextTransport:o,rawTextColumnIndices:c,rawTextValidationUnavailable:d,effectiveInlineCellBytes:i}}function Eo(e,t,n){if(!n.metadataTrailer){if(t!==void 0)throw new Error("Cell containment received unexpected separate metadata rows");return e}if(t!==void 0)throw new Error("Cell containment metadata must come from the value statement");let r=e.at(-1);if(!r||r.length!==n.primaryTransportColumnCount)throw new Error("Cell containment metadata trailer is missing or malformed");if(typeof r[0]!="string"||r.slice(1).some(l=>l!==null))throw new Error("Cell containment metadata trailer is not one packed text value");let o=e.slice(0,-1),i=r[0]===""?[]:r[0].split(` +`);if(i.length!==o.length)throw new Error("Cell containment metadata row count does not match the value page");return o.map((l,s)=>{if(l.length{if(!s)return;let a={};for(let[d,c]of Object.entries(s)){let u=Number(d);a[u]={};for(let[f,m]of Object.entries(c))a[u][Number(f)+1]=m}return a},o=r(t.exactIntegerTexts),i;for(let s of[n,o])if(s){i??(i={});for(let[a,d]of Object.entries(s)){let c=Number(a);i[c]??(i[c]={}),Object.assign(i[c],d)}}let l=r(t.oversizedCells);return{rows:t.rows.map((s,a)=>[e[a],...s]),...l?{oversizedCells:l}:{},...i?{exactIntegerTexts:i}:{}}}function wo(e,t){let n,r=0,o,i=s=>{if(s>=48&&s<=57)return s-48;let a=s|32;return a>=97&&a<=102?a-87:-1},l=(s,a,d)=>{let c=typeof s=="string"?s.length/2:NaN;if(typeof s!="string"||!Number.isSafeInteger(c)||!Number.isSafeInteger(t.effectiveInlineCellBytes)||t.effectiveInlineCellBytes<0||c>t.effectiveInlineCellBytes)throw new Error(`Raw TEXT value at row ${a}, key ${d} is not bounded hexadecimal text`);if(c===0)return o??(o=new Uint8Array(0));let u;c>uo?u=new Uint8Array(c):((!n||n.byteLength-r{if(s.length{let u=s[t.rawTextColumnStart+c];if(u!==null&&t.rawTextTransport==="hex")return l(u,a,c);if(u!==null&&!(u instanceof Uint8Array))throw new Error(`Raw TEXT value at row ${a}, key ${c} is not a BLOB`);return u})})}function ta(e,t){return e===t&&!t.includes("\0")}function $t(e,t,n){try{return ta(e.decode(t),n)}catch{return!1}}function So(e){if(e.sourceRows.length===0||e.sourceColumnIndices.length===0)return;if(e.rawTextValidationUnavailable)return new Set(e.sourceRows.map((o,i)=>i));if(e.rawTextRows.length!==e.sourceRows.length)throw new Error("Raw TEXT validation row count does not match the source page");let t=e.sourceColumnIndices.map(o=>{let i=e.rawTextColumnIndices.indexOf(o);if(i<0)throw new Error(`Raw TEXT validation column ${o} was not projected`);return i}),n=new TextDecoder(e.textEncoding,{fatal:!0,ignoreBOM:!0}),r;return e.sourceRows.forEach((o,i)=>{let l=e.rawTextRows[i];if(!l||l.length!==e.rawTextColumnIndices.length)throw new Error(`Raw TEXT validation row ${i} has the wrong width`);for(let s=0;sArray.from(s)),n;if(e.contained.oversizedCells){n={};for(let[s,a]of Object.entries(e.contained.oversizedCells))n[Number(s)]={...a}}let r;if(e.contained.exactIntegerTexts){r={};for(let[s,a]of Object.entries(e.contained.exactIntegerTexts))r[Number(s)]={...a}}let o=Z-rt,i=Lt(t)+vt(n)+kt(r),l=new TextDecoder(e.textEncoding,{fatal:!0,ignoreBOM:!0});if(e.sourceRows.forEach((s,a)=>{let d=e.rawTextRows[a];if(!d||d.length!==e.rawTextColumnIndices.length)throw new Error(`Raw TEXT containment row ${a} has the wrong width`);e.rawTextColumnIndices.forEach((c,u)=>{let f=s[c];if(typeof f!="string"||n?.[a]?.[c])return;let m=d[u];if(!(m instanceof Uint8Array))throw new Error(`Raw TEXT containment bytes are missing at row ${a}, column ${c}`);if($t(l,m,f))return;let E=t[a][c],g=Co(n,a,c);n??(n={}),n[a]??(n[a]={}),n[a][c]={storageClass:"text",byteLength:m.byteLength};let y=Math.max(0,o-i-g+re(E)),T=y>nt?Math.floor((y-nt)/4)*3:0,x=Math.min(m.byteLength,Ks,T);if(x===0)throw new Error(`Raw TEXT containment cannot retain an authoritative byte prefix for row ${a}, column ${c} within the webview transport limit`);let A=m.slice(0,x);t[a][c]=A,i+=re(A)-re(E)+g,r?.[a]&&(delete r[a][c],Object.keys(r[a]).length===0&&delete r[a])})}),i>o)throw new Error(`Raw TEXT containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:t,...n?{oversizedCells:n}:{},...r&&Object.keys(r).length>0?{exactIntegerTexts:r}:{}}}function na(e,t,n){if(e==="")return;let r=/^([tb])([1-9]\d*)$/.exec(e);if(!r)throw new Error(`Invalid oversized-cell metadata at row ${t}, column ${n}`);let o=Number(r[2]);if(!Number.isSafeInteger(o))throw new Error(`Oversized-cell byte length is unsafe at row ${t}, column ${n}`);return{storageClass:r[1]==="t"?"text":"blob",byteLength:o}}function Ot(e){let t=0;for(let n=0;n=55296&&r<=56319&&n+1=56320&&o<=57343?(t+=4,n++):t+=3}else t+=3}return t}function ra(e){if(typeof e=="string")return Ot(e);if(e instanceof Uint8Array)return e.byteLength}function mo(e){return e==="text"?"":new Uint8Array(0)}function oa(e){return 4*Math.ceil(e/3)}function re(e){return e instanceof Uint8Array?oa(e.byteLength)+nt:typeof e=="string"?Ot(e)+2:8}function he(e){return Ot(e)+3}function Lt(e){let t=2+Math.max(0,e.length-1);for(let n of e){t+=2+Math.max(0,n.length-1);for(let r of n)t+=re(r)}return t}function vt(e){if(!e)return 0;let t=Object.entries(e),n=2+Math.max(0,t.length-1);for(let[r,o]of t){n+=he(r);let i=Object.entries(o);n+=2+Math.max(0,i.length-1);for(let[l]of i)n+=he(l)+xn}return n}function Co(e,t,n){if(e?.[t]?.[n])return 0;let r=he(String(n))+xn;if(e?.[t])return 1+r;let i=he(String(t))+2+r;return e?1+i:2+i}function kt(e){if(!e)return 0;let t=Object.entries(e),n=2+Math.max(0,t.length-1);for(let[r,o]of t){n+=he(r);let i=Object.entries(o);n+=2+Math.max(0,i.length-1);for(let[l,s]of i)n+=he(l)+Ot(s)+2}return n}function To(e){if(!e)return 0;let t=Object.entries(e),n=2+Math.max(0,t.length-1);for(let[r,o]of t)n+=he(r)+re(o);return n}function Pt(e,t,n,r=me){var E;let o=It(r,me),i,l=0,s=!1,a=[],d=(g,y,T)=>{var x;i??(i={}),i[g]??(i[g]={}),(x=i[g])[y]??(x[y]=T)},c=e.map((g,y)=>{if(g.length{let C=na(_,y,b);C&&d(y,b,C);let N=A[b],I=ra(N);if(I===void 0||I===0)return;let L=C??{storageClass:typeof N=="string"?"text":"blob",byteLength:I};if(s||I>o-l){s=!0,d(y,b,L),A[b]=mo(L.storageClass);return}l+=I,a.push({rowIndex:y,columnIndex:b,metadata:L})}),A}),u;if(n)for(let[g,y]of Object.entries(n))for(let[T,x]of Object.entries(y)){let A=Number(T);A>=t||(u??(u={}),u[E=Number(g)]??(u[E]={}),u[Number(g)][A]=x)}let f=Z-rt,m=Lt(c)+vt(i)+kt(u);for(let g=a.length-1;g>=0&&m>f;g--){let y=a[g],T=c[y.rowIndex][y.columnIndex],x=mo(y.metadata.storageClass),A=re(x)-re(T)+Co(i,y.rowIndex,y.columnIndex);A>=0||(d(y.rowIndex,y.columnIndex,y.metadata),c[y.rowIndex][y.columnIndex]=x,m+=A)}if(m>f)throw new Error(`Cell containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:c,...i?{oversizedCells:i}:{},...u?{exactIntegerTexts:u}:{}}}function po(e,t){var r;if(!e)return;let n;for(let[o,i]of Object.entries(e))for(let[l,s]of Object.entries(i)){let a=Number(l);a>=t||(n??(n={}),n[r=Number(o)]??(n[r]={}),n[Number(o)][a+1]=s)}return n}function go(e,t){var r;if(!e)return;let n;for(let[o,i]of Object.entries(e))for(let[l,s]of Object.entries(i)){let a=Number(l);a!==t&&(n??(n={}),n[r=Number(o)]??(n[r]={}),n[Number(o)][a]=s)}return n}function Ro(e){let t=`Row is read-only because a declared "rowid" column shadows SQLite's intrinsic row identity.`,n=Number.isSafeInteger(e.rowOffset)&&(e.rowOffset??0)>=0?e.rowOffset:0,r,o=e.rows.map((d,c)=>{if(d.length===0)throw new Error(`Shadowed rowid result row ${c} has no identity slot`);let u=n+c;if(!Number.isSafeInteger(u))throw new Error("Shadowed rowid result ordinal exceeds the safe integer range");return r??(r={}),r[c]=t,[et(t,u),...d.slice(1)]}),i=go(e.oversizedCells,0),l=go(e.exactIntegerTexts,0),s=Z-rt;if(Lt(o)+vt(i)+kt(l)+To(r)>s)throw new Error(`Cell containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:o,...i?{oversizedCells:i}:{},...l?{exactIntegerTexts:l}:{},...r?{readOnlyRowReasons:r}:{}}}function At(e){return`"${e.length<=128?e:`${e.slice(0,125)}...`}"`}function xo(e){let t=e.slice(0,8).map(At);return e.length>t.length?`${t.join(", ")}, and ${e.length-t.length} more`:t.join(", ")}function ia(e,t){if(e.length===1){let r=e[0];return`Row is read-only because WITHOUT ROWID primary-key column ${At(r.identifier)} is ${r.byteLength} bytes and exceeds the ${t}-byte inline limit; its identity was not transported.`}let n=e.slice(0,8).map(r=>`${At(r.identifier)} (${r.byteLength} bytes)`);return e.length>n.length&&n.push(`and ${e.length-n.length} more`),`Row is read-only because WITHOUT ROWID primary-key columns ${n.join(", ")} exceed the ${t}-byte inline limit; their identity was not transported.`}function Io(e){return e==="utf-8"?"UTF-8":e==="utf-16le"?"UTF-16LE":"UTF-16BE"}function In(e){if(e.columns.length*2>Rn)throw new Error(`Cannot mint a byte-faithful WITHOUT ROWID identity with ${e.columns.length} primary-key columns within SQLite's result-column limit`);let t=e.columns.map(r=>h(r.identifier)),n=t.map((r,o)=>`CASE WHEN typeof(${r}) = 'text' THEN CAST(${r} AS BLOB) END AS `+h(`${yo}${o}`));return[...t,...n].join(", ")}function An(e,t,n,r){let o=e.columns.length;if(t.length!==o*2)throw new Error(`${r}: SQLite returned an invalid primary-key validation row`);let i=t.slice(0,o),l=new TextDecoder(n,{fatal:!0,ignoreBOM:!0});for(let s=0;s{let y=e.sourceColumns.indexOf(g.identifier);if(y<0)throw new Error(`Primary-key column missing from table fetch: ${g.identifier}`);return y}),n=Number.isSafeInteger(e.rowOffset)&&(e.rowOffset??0)>=0?e.rowOffset:0,r,o,i=[],l=new TextDecoder(e.textEncoding,{fatal:!0,ignoreBOM:!0}),s=e.rawTextValidationUnavailable?[]:t.map(g=>{let y=e.rawTextColumnIndices.indexOf(g);if(y<0)throw new Error(`Primary-key raw TEXT column ${g} was not projected`);return y}),a=e.rows.map((g,y)=>{let T=e.identity.columns.flatMap((C,N)=>{let I=e.oversizedCells?.[y]?.[t[N]];return I?[{identifier:C.identifier,byteLength:I.byteLength}]:[]}),x=e.identityRows[y];if(!x)throw new Error(`Primary-key identity row missing at index ${y}`);let A=e.rawTextBytes[y];if(!e.rawTextValidationUnavailable&&(!A||A.length!==e.rawTextColumnIndices.length))throw new Error(`Primary-key raw TEXT row missing at index ${y}`);let _=e.rawTextValidationUnavailable?e.identity.columns.map(C=>C.identifier):e.identity.columns.flatMap((C,N)=>{let I=x[t[N]];if(typeof I!="string")return[];let L=e.oversizedCells?.[y]?.[t[N]];if(L&&L.byteLength>e.effectiveInlineCellBytes)return[];let w=A[s[N]];return w instanceof Uint8Array?$t(l,w,I)?[]:[C.identifier]:[C.identifier]}),b;if(e.rawTextValidationUnavailable&&(o??(o=new Set),o.add(y)),_.length>0){let C=e.rawTextValidationUnavailable?aa(_):sa(_,e.textEncoding);r??(r={}),r[y]=C,o??(o=new Set),o.add(y),b=et(C,n+y)}else if(T.length>0){let C=ia(T,e.effectiveInlineCellBytes);r??(r={}),r[y]=C,b=et(C,n+y)}else b=Pe(e.identity.columns,t.map(C=>x[C])),i.push(y);return[b,...g.slice(0,e.visibleColumnCount)]}),d=po(e.oversizedCells,e.visibleColumnCount),c=po(e.exactIntegerTexts,e.visibleColumnCount),u=Z-rt,f=Lt(a)+vt(d)+kt(c)+To(r),m="Row is read-only because its encoded WITHOUT ROWID primary-key identity exceeds the page transport budget.",E=g=>{if(r?.[g]!==void 0)return 0;let y=he(String(g))+re(m);return r?1+y:2+y};for(let g=i.length-1;g>=0&&f>u;g--){let y=i[g],T=a[y][0],x=et(m,n+y),A=re(x)-re(T)+E(y);A>=0||(a[y][0]=x,r??(r={}),r[y]=m,f+=A)}if(f>u)throw new Error(`Cell containment cannot fit this page within the ${Z}-byte transport limit`);return{rows:a,...d?{oversizedCells:d}:{},...c?{exactIntegerTexts:c}:{},...r?{readOnlyRowReasons:r}:{},...o?{unrepresentableTextKeyRows:o}:{}}}var Bt=1e3,No=4*1024*1024,_o=64*1024,Dt=128;function $o(e){if(e.length>_o)throw new Error("Query text exceeds 65,536 characters.");let t=Ee(e),n="",r=0,o=0;for(let i=0;il+1?Number(t.slice(l+1,i)):r+1;if(!Number.isInteger(a)||a<1||a>100)throw new Error("Use at most 100 positional parameters.");r=Math.max(r,a),n+="NULL";continue}else{if(s==="("&&o++,s===")"&&--o<0)throw new Error("Unbalanced query parentheses.");if(s===";")throw new Error("Exactly one read query is required.");if(s===":"||s==="@"||s==="$")throw new Error("Use positional ? or ?NNN parameters. Named parameters are not supported.");i++}n+=t.slice(l,i)}if(o!==0)throw new Error("Unbalanced query parentheses.");return{sourceSql:t,sql:`SELECT * FROM ( ${t} -) LIMIT ${Pt+1}`,metadataSql:`SELECT * FROM ( +) LIMIT ${Bt+1}`,metadataSql:`SELECT * FROM ( ${n} -) LIMIT 0`,parameterCount:r}}function $o(e){if(e.length>No)throw new Error("Parameters exceed 65,536 characters.");let t=JSON.parse(e);if(!Array.isArray(t)||t.length>100)throw new Error("Enter a JSON array of at most 100 values.");for(let n of t){if(n!==null&&typeof n!="string"&&typeof n!="number")throw new Error("Parameters must be null, string, or number.");if(typeof n=="number"&&(!Number.isFinite(n)||Number.isInteger(n)&&!Number.isSafeInteger(n)))throw new Error("Numbers must be finite and integer values must be safe integers. Supply an exact integer as a quoted string and use CAST(? AS INTEGER).")}return t}function Oo(e,t){if(t<1||t>Bt)throw new Error("Queries support 1 to 128 result columns.");let n=_t(e,t,{limit:Pt+1,maxInlineCellBytes:64*1024,maxPageResponseBytes:Ao});return Ye(n.sql,n.primaryTransportColumnCount)}function Lo(e,t,n){let r=ke(t,n);return{headers:e,...kt(r.rows,e.length,r.exactIntegerTexts,Ao)}}function we(e){let t=e==null?"":String(e);return t.trim()?t:void 0}function Ut(e,t,n="set"){if(n==="json_patch")return{value:e,operation:"json_patch"};if(typeof e!="string"||typeof t!="string"||!(e.startsWith("{")||e.startsWith("["))||!(t.startsWith("{")||t.startsWith("[")))return{value:e,operation:"set"};try{let r=JSON.parse(t),o=JSON.parse(e);if(!r||typeof r!="object"||Array.isArray(r)||!o||typeof o!="object"||Array.isArray(o))return{value:e,operation:"set"};let i=Bo(r,o);return i===void 0||Po(i)?{value:e,operation:"set"}:{value:JSON.stringify(i),operation:"json_patch"}}catch{return{value:e,operation:"set"}}}function Po(e){return e===null?!0:F(e)?Object.values(e).some(Po):!1}function Bo(e,t,n=0){if(n>1e3)throw new Error("JSON merge patch depth limit exceeded");if(e===t)return;if(!F(e)||!F(t)||Array.isArray(e)||Array.isArray(t))return t;let r=Object.create(null),o=!1;for(let i of Object.keys(t)){let l=Object.prototype.hasOwnProperty.call(e,i)?e[i]:void 0,s=t[i];if(l===void 0)r[i]=s,o=!0;else if(l!==s){let a=Bo(l,s,n+1);a!==void 0&&(r[i]=a,o=!0)}}for(let i of Object.keys(e))Object.prototype.hasOwnProperty.call(t,i)||(r[i]=null,o=!0);return o?r:void 0}function Do(e,t,n=0){if(n>1e3)throw new Error("JSON apply merge patch depth limit exceeded");if(t===null)return null;if(typeof t!="object"||Array.isArray(t))return t;let r;typeof e!="object"||e===null||Array.isArray(e)?r=Object.create(null):r=Object.assign(Object.create(null),e);let o=t;for(let i in o)if(Object.prototype.hasOwnProperty.call(o,i)){let l=o[i];l===null?delete r[i]:r[i]=Do(r[i],l,n+1)}return r}function Dt(e){if(typeof e=="string")try{let t=JSON.parse(e);return F(t)?t:void 0}catch{return}}function Mo(e,t,n,r,o){let i=o==="undo"?r:n,l=o==="undo"?n:r,s=()=>ko(e,i)?{kind:"write",value:l}:{kind:"conflict"};if(Mt(e)||Mt(t)||Mt(n)||Mt(r))return s();let a=Dt(e),d=Dt(t),c=Dt(n),u=Dt(r);if(!a||!d||!c||!u)return s();if(!Uo(a,o==="undo"?u:c,d,c,0))return{kind:"conflict"};if(ko(e,i))return{kind:"write",value:l};let m=o==="undo"?Nn(a,d,c,0):Do(a,d,0);return{kind:"write",value:JSON.stringify(m)}}function Uo(e,t,n,r,o){if(o>1e3)throw new Error("JSON history replay depth limit exceeded");for(let i of Object.keys(n)){let l=n[i],s=Object.prototype.hasOwnProperty.call(e,i),a=Object.prototype.hasOwnProperty.call(t,i),d=Object.prototype.hasOwnProperty.call(r,i),c=s?e[i]:void 0,u=a?t[i]:void 0,f=d?r[i]:void 0;if(F(l)){if(!d||!F(f)){if(!vo(s,c,a,u,o+1))return!1;continue}if(!s||!F(c)||!a||!F(u)||!Uo(c,u,l,f,o+1))return!1;continue}if(!vo(s,c,a,u,o+1))return!1}return!0}function vo(e,t,n,r,o){return e===n&&(!e||An(t,r,o))}function An(e,t,n){if(n>1e3)throw new Error("JSON history replay depth limit exceeded");if(Object.is(e,t))return!0;if(Array.isArray(e)||Array.isArray(t))return!Array.isArray(e)||!Array.isArray(t)||e.length!==t.length?!1:e.every((i,l)=>An(i,t[l],n+1));if(!F(e)||!F(t))return!1;let r=Object.keys(e),o=Object.keys(t);return r.length!==o.length?!1:r.every(i=>Object.prototype.hasOwnProperty.call(t,i)&&An(e[i],t[i],n+1))}function ko(e,t){return e instanceof Uint8Array||t instanceof Uint8Array?!(e instanceof Uint8Array)||!(t instanceof Uint8Array)?!1:e.length===t.length&&e.every((n,r)=>n===t[r]):Object.is(e,t)}function Nn(e,t,n,r){if(r>1e3)throw new Error("JSON undo restore depth limit exceeded");let o=Object.assign(Object.create(null),e);for(let i of Object.keys(t)){let l=t[i],s=Object.prototype.hasOwnProperty.call(n,i),a=s?n[i]:void 0;if(F(l))if(s&&F(a))if(Object.prototype.hasOwnProperty.call(o,i)&&F(o[i])){let d=o[i];o[i]=Nn(d,l,a,r+1)}else o[i]=a;else if(s)o[i]=a;else{let d=Object.prototype.hasOwnProperty.call(o,i)&&F(o[i])?o[i]:Object.create(null),c=Nn(d,l,Object.create(null),r+1);Object.keys(c).length===0?delete o[i]:o[i]=c}else s?o[i]=a:delete o[i]}return o}function Mt(e){if(typeof e!="string")return!1;let n=e.replace(/"(?:\\.|[^"\\])*"/g,'""').match(/-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g);return n?n.some(r=>{let o=Number(r);return!Number.isFinite(o)||JSON.stringify(o)!==r}):!1}function F(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}var sa=new Set(["null","integer","real","text","blob"]),aa="Cell changed outside SQLite Explorer history; undo/redo was not applied.",la="This edit predates guarded cell history and cannot be replayed safely. Save or reload the database.",oe=class extends Error{constructor(n,r){let o=r.length===1?`${n}.${r[0]}`:`${r.length} cells in ${n}`;super(`${o}: ${aa}`);D(this,"code","SQLITE_EXPLORER_CELL_HISTORY_CONFLICT");this.name="CellHistoryConflictError"}},ot=class extends Error{constructor(){super(la);D(this,"code","SQLITE_EXPLORER_LEGACY_CELL_HISTORY");this.name="LegacyCellHistoryError"}};function ee(e){let t=h(e);return`typeof(${t}), CASE WHEN typeof(${t}) = 'text' THEN CAST(${t} AS BLOB) ELSE ${t} END`}function ca(e,t,n){if(!t)throw new Error(`SQLite text encoding is required for ${n}`);try{return{value:new TextDecoder(t,{fatal:!0,ignoreBOM:!0}).decode(e)}}catch{return{value:"",rawTextBytes:e}}}function q(e,t,n,r={}){if(typeof e!="string"||!sa.has(e))throw new Error(`SQLite returned an invalid storage class for ${n}`);let o=e;if(o!=="text"&&r.rawTextBytes!==void 0)throw new Error(`SQLite returned raw TEXT bytes for non-TEXT ${n}`);if(o==="text"){if(t instanceof Uint8Array)return{storageClass:o,...ca(t,r.textEncoding,n)};if(typeof t!="string")throw new Error(`SQLite returned an invalid text value for ${n}`);if(r.rawTextBytes!==void 0&&!(r.rawTextBytes instanceof Uint8Array))throw new Error(`SQLite returned invalid raw TEXT bytes for ${n}`);return{storageClass:o,value:t,...r.rawTextBytes instanceof Uint8Array?{rawTextBytes:r.rawTextBytes}:{}}}if(!(o==="null"?t===null:o==="integer"?typeof t=="bigint"||typeof t=="number"&&Number.isInteger(t):o==="real"?typeof t=="number":t instanceof Uint8Array))throw new Error(`SQLite returned an invalid ${o} value for ${n}`);return{storageClass:o,value:t}}function it(e){if(!e||typeof e!="object")throw new ot;q(e.storageClass,e.value,"cell history",{rawTextBytes:e.rawTextBytes})}function _n(e,t){if(e.storageClass!==t.storageClass)return!1;if(e.storageClass==="text"){let o=e.rawTextBytes,i=t.rawTextBytes;if(o||i)return!o||!i?!1:o.length===i.length&&o.every((l,s)=>l===i[s])}let n=e.value,r=t.value;return e.storageClass==="integer"&&typeof n!=typeof r?typeof n=="number"&&Number.isSafeInteger(n)&&typeof r=="bigint"?BigInt(n)===r:typeof r=="number"&&Number.isSafeInteger(r)&&typeof n=="bigint"?n===BigInt(r):!1:n instanceof Uint8Array||r instanceof Uint8Array?!(n instanceof Uint8Array)||!(r instanceof Uint8Array)?!1:n.length===r.length&&n.every((o,i)=>o===r[i]):Object.is(n,r)}function Vt(e,t=()=>"?"){switch(it(e),e.storageClass){case"null":return{sql:"NULL",params:[]};case"integer":return{sql:t(e.value),params:[e.value]};case"real":return{sql:"CAST(? AS REAL)",params:[e.value]};case"text":return{sql:e.rawTextBytes?"CAST(substr(?, 1) AS TEXT)":"CAST(? AS TEXT)",params:[e.rawTextBytes??e.value]};case"blob":return{sql:"?",params:[e.value]}}}function qt(e,t,n=()=>"?"){it(t);let r=h(e);switch(t.storageClass){case"null":return{sql:`typeof(${r}) = 'null'`,params:[]};case"integer":{let o=n(t.value);return{sql:`typeof(${r}) = 'integer' AND ${r} IS ${o}`,params:[t.value]}}case"real":return{sql:`typeof(${r}) = 'real' AND ${r} IS CAST(? AS REAL)`,params:[t.value]};case"text":return{sql:`typeof(${r}) = 'text' AND CAST(${r} AS BLOB) = CAST(? AS BLOB)`,params:[t.rawTextBytes??t.value]};case"blob":return{sql:`typeof(${r}) = 'blob' AND ${r} IS ?`,params:[t.value]}}}var ua="Row changed outside SQLite Explorer history; undo/redo was not applied.",da="This row edit predates guarded row history and cannot be replayed safely. Save or reload the database.",Se=class extends Error{constructor(n){super(`${n}: ${ua}`);D(this,"code","SQLITE_EXPLORER_ROW_HISTORY_CONFLICT");this.name="RowHistoryConflictError"}},G=class extends Error{constructor(){super(da);D(this,"code","SQLITE_EXPLORER_LEGACY_ROW_HISTORY");this.name="LegacyRowHistoryError"}};function st(e){if(!Array.isArray(e.storageClasses))throw new G;let t=new Set;return e.storageClasses.map(n=>{let r=typeof n?.column=="string"?Ct(n.column):void 0;if(!n||typeof n.column!="string"||r===void 0||t.has(r)||!Object.prototype.hasOwnProperty.call(e.row,n.column))throw new G;t.add(r);let o=e.row[n.column],i=n.storageClass==="text"&&o instanceof Uint8Array?o:void 0;return{column:n.column,state:q(n.storageClass,i?"":o,`row history column ${n.column}`,{rawTextBytes:i})}})}function $n(e,t=()=>"?"){let n=st(e).map(({column:r,state:o})=>qt(r,o,t));return{sql:n.length>0?n.map(r=>`(${r.sql})`).join(" AND "):"1",params:n.flatMap(r=>r.params)}}function Vo(e,t=()=>"?"){return st(e).map(({column:n,state:r})=>({column:n,write:Vt(r,t)}))}var On="~sqlite-explorer-non-finite:",kc=`${On}Infinity`,fa=`${On}-Infinity`,Pc=`${On}NaN`,ma=fa.length+2;function qo(e){let t=new Set,n=[e],r=0;for(;n.length>0;){let o=n.pop();if(o!=null){if(typeof o=="boolean")r+=4;else if(typeof o=="number"||typeof o=="bigint")r+=8;else if(typeof o=="string")r+=o.length*2;else if(o instanceof Uint8Array)r+=o.byteLength;else if(typeof o=="object"){if(t.has(o))continue;if(t.add(o),r+=8,Array.isArray(o))for(let i of o)n.push(i);else for(let i in o)Object.prototype.hasOwnProperty.call(o,i)&&(r+=i.length*2,n.push(o[i]))}}}return r}var pa=32,ga=48;function Wo(e,t){let n=typeof e=="bigint"?Number(e):e;if(!Number.isSafeInteger(n)||Number(n)<0)throw new Error(`SQLite returned an unsafe ${t} during delete undo preflight`);return Number(n)}function Fo(e,t){return[...e]}function Ho(e,t,n){return{sql:`SELECT COUNT(*), COALESCE(SUM(${t.map(o=>{let i=h(o);return`CASE typeof(${i}) WHEN 'text' THEN 2 * octet_length(${i}) WHEN 'blob' THEN octet_length(${i}) WHEN 'integer' THEN 8 WHEN 'real' THEN 8 ELSE 0 END`}).join(" + ")||"0"}), 0) FROM ${R(e)} WHERE ${n.sql}`,params:n.params}}function Ko(e){if(!e||e.length<2)throw new Error("SQLite omitted delete undo preflight metadata");return{rowCount:Wo(e[0],"row count"),valueBytes:Wo(e[1],"value byte count")}}function jo(e){if(!Number.isSafeInteger(e.maxSnapshotBytes)||e.maxSnapshotBytes<0)throw new Error("Delete undo snapshot budget must be a non-negative safe integer");if(e.rowCount!==e.rowIds.length)throw new Error(`Cannot delete from ${e.table}: one or more row identities no longer exist`);let n=[...new Set(e.insertableColumns)].reduce((l,s)=>l+s.length*2,0),r=e.rowIds.reduce((l,s)=>l+qo(s),0),o=e.rowCount*e.insertableColumns.reduce((l,s)=>l+s.length*2+ga,0),i=e.valueBytes+r+e.rowCount*(pa+n)+o;if(!Number.isSafeInteger(i)||i>e.maxSnapshotBytes){let l=e.operation??"Delete";throw new Error(`${l} undo snapshot exceeds the ${e.maxSnapshotBytes}-byte memory budget; ${l.toLowerCase()} fewer rows or increase sqliteExplorer.maxUndoMemory.`)}}var Wt="ksa:",Ft=1,vn=128*1024,ya=["first","after","atOrAfter","before","last"];function kn(e){return e.orderBy?.toLowerCase()==="rowid"&&e.columns?.[0]?.toLowerCase()==="rowid"&&!e.columns.slice(1).some(t=>t.toLowerCase()==="rowid")}function Pn(e,t){let n=(t.filters??[]).flatMap(a=>{let d=we(a.value);return d===void 0?[]:[[a.column,d]]}),r=we(t.globalFilter)??null,o=r===null?null:t.globalFilterColumns??t.columns??null,i=typeof t.orderBy=="string"&&t.orderBy!==""?t.orderBy:null,l=i!==null&&t.orderDir==="DESC"?"DESC":"ASC",s=typeof t.limit=="number"&&Number.isSafeInteger(t.limit)?t.limit:null;return JSON.stringify([Ft,e,i,l,s,n,r,o])}function Bn(e,t){if(!t||e.orderByColumns?.length)return;let n=t.kind==="rowid"?["rowid"]:t.columns.map(i=>i.identifier);if(n.length===0)return;let r=typeof e.orderBy=="string"&&e.orderBy!==""?e.orderBy:void 0;if(r===void 0)return{keyColumns:n,nullableSortKey:!1,direction:"ASC"};let o=e.orderDir==="DESC"?"DESC":"ASC";return kn(e)?{keyColumns:n,nullableSortKey:!1,direction:o}:n.includes(r)?{keyColumns:[r,...n.filter(i=>i!==r)],nullableSortKey:!1,direction:o}:{keyColumns:[r,...n],nullableSortKey:!0,direction:o}}function zo(e,t){if(!(!e||t))return{orderByColumns:e.keyColumns,orderDir:e.direction}}function Ea(e){return e===null?["null"]:Rt(e)}function ha(e){return Array.isArray(e)&&e.length===1&&e[0]==="null"?{value:null,storageClass:"null"}:{value:oo(e),storageClass:e[0]}}function wa(e,t){if(t.length===0)throw new Error("Keyset anchor requires at least one key value");let n={v:Ft,t:e,k:t.map(Ea)};return Wt+encodeURIComponent(JSON.stringify(n))}function Sa(e){if(e.length>vn)throw new Error(`Keyset anchor exceeds the ${vn}-byte limit`)}function ba(e){if(typeof e!="string"||!e.startsWith(Wt))throw new Error("Invalid keyset anchor");Sa(e);let t;try{t=JSON.parse(decodeURIComponent(e.slice(Wt.length)))}catch{throw new Error("Invalid keyset anchor encoding")}if(!t||typeof t!="object"||Array.isArray(t)||Object.keys(t).length!==3||t.v!==Ft||typeof t.t!="string"||!Array.isArray(t.k))throw new Error("Invalid keyset anchor payload");let n=t.k;if(n.length===0)throw new Error("Keyset anchor has no key values");let r,o;try{let l=n.map(ha);r=l.map(s=>s.value),o=l.map(s=>s.storageClass)}catch(l){throw new Error(`Invalid keyset anchor value: ${l instanceof Error?l.message:String(l)}`)}if(Wt+encodeURIComponent(JSON.stringify({v:Ft,t:t.t,k:n}))!==e)throw new Error("Keyset anchor is not canonical");return{tag:t.t,values:r,valueClasses:o}}function Qo(e,t,n){let r=t.keyset;if(!r||typeof r!="object"||Array.isArray(r)||!ya.includes(r.mode))return;let o=Bn(t,n);if(!o)return;let i=typeof t.limit=="number"&&Number.isSafeInteger(t.limit)&&t.limit>0?t.limit:void 0;if(i===void 0)return;if(r.mode==="first")return{...o,mode:"first",limit:i};if(r.mode==="last"){let a=r.lastPageRowCount??i;return typeof a!="number"||!Number.isSafeInteger(a)||a<1||a>i?void 0:{...o,mode:"last",limit:a}}if(r.anchor===void 0)return;let l=ba(r.anchor);if(l.tag!==Pn(e,t)||l.values.length!==o.keyColumns.length)return;let s=o.nullableSortKey?1:0;if(l.values.some((a,d)=>a===null&&d>=s))throw new Error("Keyset anchor has NULL in an identity slot");return{...o,mode:r.mode,values:l.values,valueClasses:l.valueClasses,limit:i}}function Ln(e,t,n){return e.length===1?`${e[0]} ${t} ${n[0]}`:`(${e.join(", ")}) ${t} (${n.join(", ")})`}function Ca(e){let t=e.values,r=e.mode==="before"?e.direction==="ASC"?"DESC":"ASC":e.direction,o=(r==="ASC"?">":"<")+(e.mode==="atOrAfter"?"=":""),i=e.keyColumns.map(h),l=e.keyColumns.map((f,m)=>e.valueClasses?.[m]==="integer"?"CAST(? AS INTEGER)":"?");if(!e.nullableSortKey)return{sql:Ln(i,o,l),params:t};let s=i[0],a=i.slice(1),d=t[0],c=t.slice(1);if(d===null){let f=Ln(a,o,l.slice(1));return r==="ASC"?{sql:`((${s} IS NULL AND ${f}) OR ${s} IS NOT NULL)`,params:c}:{sql:`(${s} IS NULL AND ${f})`,params:c}}let u=Ln(i,o,l);return r==="ASC"?{sql:u,params:t}:{sql:`(${u} OR ${s} IS NULL)`,params:t}}function Xo(e){let{plan:t}=e,n=t.mode==="before"||t.mode==="last",r=n?t.direction==="ASC"?"DESC":"ASC":t.direction,o=[...e.whereClauses],i=[...e.filterParams];if(t.mode!=="first"&&t.mode!=="last"){let d=Ca(t);o.push(d.sql),i.push(...d.params)}let l=t.keyColumns.map(h),s=d=>l.map(c=>`${c} ${d}`).join(", "),a=`SELECT ${e.selectListSql} FROM ${e.escapedTable}`;return o.length>0&&(a+=` WHERE ${o.join(" AND ")}`),a+=` ORDER BY ${s(r)} LIMIT ${t.limit}`,n&&(a=`SELECT * FROM (${a}) ORDER BY ${s(t.direction)}`),{sql:a,params:i}}function Go(e){if(e.rows.length===0)return;let t=e.key.keyColumns.map(i=>e.projectionColumns.indexOf(i));if(t.some(i=>i<0))return;let n=i=>{if(e.excludedRowIndices?.has(i))return;let l=e.rows[i],s=[];for(let d=0;dJo)throw new Error(`Cell read chunk size must be an integer from 1 through ${Jo}`)}function Be(e){let t=String(e).toLowerCase().replace(/[_\s-]/g,"");if(t==="utf8")return"utf-8";if(t==="utf16le")return"utf-16le";if(t==="utf16be")return"utf-16be";throw new Error(`Unsupported SQLite text encoding: ${String(e)}`)}function ti(e,t,n){if(e.length!==1)throw new Error(e.length===0?`Cell ${n.table}.${n.column} no longer exists`:`Cell ${n.table}.${n.column} matched more than one row`);let r=e[0][0];if(typeof r!="string"||!xa.has(r))throw new Error(`SQLite returned an invalid storage class for ${n.table}.${n.column}`);let o=e[0][1],i=typeof o=="bigint"?Number(o):o;if(!Number.isSafeInteger(i)||Number(i)<0)throw new Error(`SQLite returned an unsafe byte length for ${n.table}.${n.column}`);return{storageClass:r,byteLength:Number(i),...r==="text"?{textEncoding:t}:{}}}function Un(e,t){return Number.isFinite(e)&&Number(e)>=1?Math.floor(Number(e)):t}var De=me,Vn=Z;var qn="SQLITE_EXPLORER_CELL_EDIT_VALUE_TOO_LARGE",Wn="SQLITE_EXPLORER_OVERSIZED_CELL_REPLACEMENT_REQUIRED",ni="Oversized cell metadata changed before the confirmed replacement was applied";var Ia=De,Fn=class extends Error{constructor(n,r,o,i=`New ${n.toUpperCase()} cell value is ${r} bytes and exceeds the ${o}-byte edit limit.`){super(i);D(this,"storageClass",n);D(this,"actualBytes",r);D(this,"limitBytes",o);D(this,"name","CellEditPolicyError");D(this,"code",qn)}},Me=class extends Error{constructor(n,r,o,i,l,s=`Existing ${o.toUpperCase()} cell ${n}.${r} is ${i} bytes. Use the explicitly confirmed oversized-cell replacement path.`){super(s);D(this,"table",n);D(this,"column",r);D(this,"storageClass",o);D(this,"actualBytes",i);D(this,"limitBytes",l);D(this,"name","OversizedCellReplacementRequiredError");D(this,"code",Wn)}};function Aa(e){let t=0;for(let n=0;n=55296&&r<=56319){let o=e.charCodeAt(n+1);o>=56320&&o<=57343?(t+=4,n++):t+=3}else t+=3}return t}function at(e,t){if(!Number.isSafeInteger(t)||t<1)throw new Error(`Cell edit limit must be a positive safe integer, got ${t}`);let n=typeof e=="string"?"text":e instanceof Uint8Array?"blob":void 0;if(!n)return;let r=typeof e=="string"?Aa(e):e instanceof Uint8Array?e.byteLength:0;if(r>t)throw new Fn(n,r,t)}function ri(e){let t=e??Ia;if(!Number.isSafeInteger(t)||t<1)throw new Error(`Cell edit limit must be a positive safe integer, got ${t}`);return t}function lt(e,t){let n=ri(t);for(let r of e)at(r,n);return n}function oi(e,t){let n=ri(t);if(!e||e.storageClass!=="text"&&e.storageClass!=="blob"||!Number.isSafeInteger(e.byteLength)||e.byteLength<=n)throw new Error("Guarded oversized-cell replacement requires exact TEXT/BLOB metadata above the edit limit");return n}function Na(e){if(!e||typeof e!="object")return;let t=e;if(!(t.name!=="CellEditPolicyError"||t.code!==qn||t.storageClass!=="text"&&t.storageClass!=="blob"||!Number.isSafeInteger(t.actualBytes)||Number(t.actualBytes)<0||!Number.isSafeInteger(t.limitBytes)||Number(t.limitBytes)<1||typeof t.message!="string"))return{name:"CellEditPolicyError",code:qn,storageClass:t.storageClass,actualBytes:Number(t.actualBytes),limitBytes:Number(t.limitBytes),message:t.message}}function _a(e){if(!e||typeof e!="object")return;let t=e;if(!(t.name!=="OversizedCellReplacementRequiredError"||t.code!==Wn||typeof t.table!="string"||typeof t.column!="string"||t.storageClass!=="text"&&t.storageClass!=="blob"||!Number.isSafeInteger(t.actualBytes)||Number(t.actualBytes)<0||!Number.isSafeInteger(t.limitBytes)||Number(t.limitBytes)<1||typeof t.message!="string"))return{name:"OversizedCellReplacementRequiredError",code:Wn,table:t.table,column:t.column,storageClass:t.storageClass,actualBytes:Number(t.actualBytes),limitBytes:Number(t.limitBytes),message:t.message}}function ii(e){return Na(e)??_a(e)}var ui=100,$a=18,si=19,ai=2;var Oa=1024*1024*1024,xe=2145386496,La="WAL database too large for in-memory mode; checkpoint it first";function di(e){return e.length>si&&e[$a]===ai&&e[si]===ai}function li(e,t,n){if(e===void 0)return t;if(!Number.isSafeInteger(e)||e<1)throw new Error(`${n} must be a positive safe integer`);return e}function ci(e){return`${(e/(1024*1024*1024)).toFixed(1)} GiB`}function Hn(e,t={}){let n=li(t.pagedThresholdBytes,Oa,"Paged-open threshold"),r=li(t.bufferCeilingBytes,xe,"Buffer-open ceiling");if(n>r)throw new Error("Paged-open threshold must not exceed the buffer-open ceiling");if(!Number.isSafeInteger(e.sizeBytes)||e.sizeBytes<0)throw new Error("Database size must be a non-negative safe integer");return e.walMarked?e.sizeBytes>=r?{mode:"reject",message:La}:{mode:"buffer",readOnly:e.sizeBytes>n}:e.sizeBytes>n&&e.pagedAvailable?{mode:"paged"}:e.sizeBytes>=r?{mode:"reject",message:`Database is too large to load into memory in this browser (${ci(e.sizeBytes)}; limit ${ci(r)}) and page-on-demand mode is unavailable`}:{mode:"buffer",readOnly:!1}}var va=64*1024*1024,Ue=1e4,mi=`SELECT 1 FROM pragma.pragma_table_list WHERE "schema" = 'main' AND "name" = ? AND "type" IN ('table', 'shadow') AND "wr" = 1 LIMIT 1`;function Kn(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:va}function jn(e){return e.storage==="paged"&&!e.filtered&&e.authorityConfirmedRowIdTable&&e.pagedFileSizeBytes>e.exactCountMaxFileBytes}function pi(e){let t=R(e);return`SELECT (SELECT CAST(min(rowid) AS TEXT) FROM ${t}), (SELECT CAST(max(rowid) AS TEXT) FROM ${t})`}function gi(e){return`SELECT COUNT(*) FROM (SELECT 1 FROM ${R(e)} LIMIT ?)`}function yi(e,t){if(!(typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>Ue+1))return e<=Ue?{count:e,isExact:!0}:{count:zn(t,e),isExact:!1}}function zn(e,t=Ue+1){return(!Number.isSafeInteger(t)||t<0)&&(t=Ue+1),!Number.isSafeInteger(e)||eBigInt(Number.MAX_SAFE_INTEGER)))return Number(i)}function hi(e,t,n){if(e===void 0)return t;if(!Number.isSafeInteger(e)||e<1)throw new Error(`${n} must be a positive safe integer`);return e}function wi(e,t={}){let n=hi(t.chunkSizeBytes,65536,"Chunk size"),r=hi(t.maxCacheBytes,8388608,"Cache budget"),o=Math.max(1,Math.floor(r/n)),i=new Map;function l(s){let a=i.get(s);if(a!==void 0)return i.delete(s),i.set(s,a),a;let d=e(s*n,n),c=d.length>n?d.subarray(0,n):d;if(i.set(s,c),i.size>o){let u=i.keys().next().value;i.delete(u)}return c}return(s,a)=>{if(!Number.isSafeInteger(s)||s<0)throw new Error("Read offset must be a non-negative safe integer");if(!Number.isSafeInteger(a)||a<0)throw new Error("Read length must be a non-negative safe integer");if(a===0)return new Uint8Array(0);let d=Math.floor(s/n),c=Math.floor((s+a-1)/n);if(d===c){let m=l(d),y=s-d*n;return y>=m.length?new Uint8Array(0):m.subarray(y,Math.min(y+a,m.length))}let u=new Uint8Array(a),f=0;for(let m=d;m<=c;m++){let y=l(m),g=m*n,E=Math.max(s,g)-g,T=Math.min(s+a,g+n)-g,x=Math.min(T,y.length);if(E>=x||(u.set(y.subarray(E,x),g+E-s),f=g+x-s,y.length{if(typeof t!="bigint")return t;let n=Number(t);return Number.isSafeInteger(n)?n:t.toString()})}function Y(e){return typeof e=="bigint"&&!Number.isSafeInteger(Number(e))?"CAST(? AS INTEGER)":"?"}function He(e){ut(e).free()}function jt(e,t){if(t!==void 0&&!(typeof SharedArrayBuffer=="function"&&t instanceof Int32Array&&t.length>0&&t.buffer instanceof SharedArrayBuffer))throw new Error("Invalid query cancellation flag");let n=()=>t!==void 0&&Atomics.load(t,0)!==0,r=()=>{let l=new Error("Query execution cancelled");throw l.name="AbortError",l};n()&&r();let o=Date.now()+Gn,i;p.progress_handler(Ba,()=>n()?(i="cancelled",!0):Date.now(){let n=ut(e),r=n.getColumnNames();n.free();let o=Ye(e,r.length),i=ut(o.sql),l=[];try{for(;i.step();)l.push(i.get(null,{useBigInt:!0}));let{rows:s,exactIntegerTexts:a}=ke(l,o.valueColumnCount);return{headers:r,rows:s,exactIntegerTexts:a}}finally{i.free()}},t)}function Oi(e,t){if(t!=null)return t;let n=e??[];return n[0]==="rowid"?n.slice(1):n}function B(e,t){try{S(`ROLLBACK TO ${e}`),S(`RELEASE ${e}`)}catch(n){console.warn(`Failed to rollback savepoint (${t}):`,Ne(n))}}function Va(e){for(Ie.add(e);Ie.size>64;)Ie.delete(Ie.values().next().value)}function Li(e){S(`ROLLBACK TO ${e}`),S(`RELEASE ${e}`)}function Xt(e){let t=We;if(!t||e!==void 0&&t.sessionId!==e)return!1;We=null,Va(t.sessionId),t.expiryTimer!==void 0&&clearTimeout(t.expiryTimer);try{S(`RELEASE ${t.savepointName}`)}catch(n){try{Li(t.savepointName)}catch(r){let o=[n,r];try{p?.close()}catch(i){o.push(i)}finally{p=null}throw new AggregateError(o,"Cell read snapshot cleanup failed; the owning web database was closed")}}return!0}function vi(e){e.expiryTimer!==void 0&&clearTimeout(e.expiryTimer),e.expiresAt=Math.min(e.absoluteExpiresAt,e.lastAccessAt+rr),e.expiryTimer=setTimeout(()=>{try{Xt(e.sessionId)}catch(t){console.error("[Worker] Failed to expire cell read session:",Ne(t))}},Math.max(1,e.expiresAt-Date.now()))}async function ki(e){Zo(e);let t=await te(e.table),n=U(e.rowId,t);return{table:e.table,column:e.column,predicateSql:n.sql,predicateParams:n.params}}function qa(e){let t=h(e.column);return{sql:`SELECT typeof(${t}), CASE WHEN ${t} IS NULL THEN 0 ELSE length(CAST(${t} AS BLOB)) END FROM ${R(e.table)} WHERE ${e.predicateSql} LIMIT 2`,params:e.predicateParams}}function Wa(e){return{sql:`SELECT substr(CAST(${h(e.column)} AS BLOB), ? + 1, ?) FROM ${R(e.table)} WHERE ${e.predicateSql} LIMIT 2`,params:e.predicateParams}}function Ke(){return Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0])}function Pi(e,t){let n=qa(t),r=p.exec(n.sql,O(n.params),{useBigInt:!0});return ti(r[0]?.values??[],Ke(),e)}async function zt(e){if(!p)throw new Error("No database initialized");let t=await ki(e);return Pi(e,t)}async function Fa(e){if(!p)throw new Error("No database initialized");if(We)throw new Error("At most one web cell read session may be open");let t=await ki(e),n=P("sp_cell_read");S(`SAVEPOINT ${n}`);try{let r=Pi(e,t),o=Date.now(),i={sessionId:crypto.randomUUID(),target:e,sqlTarget:t,metadata:r,savepointName:n,lastAccessAt:o,absoluteExpiresAt:o+$i,expiresAt:o+rr,expiryTimer:void 0};return We=i,vi(i),{sessionId:i.sessionId,metadata:r,expiresAt:i.expiresAt}}catch(r){try{Li(n)}catch(o){let i=[r,o];try{p?.close()}catch(l){i.push(l)}finally{p=null}throw new AggregateError(i,"Cell read session open failed; the owning web database was closed")}throw r}}async function Ha(e,t,n){ei(t,n);let r=We;if(!r||r.sessionId!==e)throw new Error(Ie.has(e)?`Cell read session ${e} is closed or expired`:`Unknown cell read session: ${String(e)}`);if(Date.now()>=r.expiresAt)throw Xt(e),new Error(`Cell read session ${e} is closed or expired`);let o=Wa(r.sqlTarget),l=p.exec(o.sql,O([t,n,...o.params]))[0]?.values??[];if(l.length!==1)throw new Error(l.length===0?`Cell ${r.target.table}.${r.target.column} no longer exists in its snapshot`:`Cell ${r.target.table}.${r.target.column} matched more than one row`);let s=l[0][0],a=s===null?new Uint8Array(0):s;if(!(a instanceof Uint8Array))throw new Error(`SQLite returned a non-BLOB chunk for ${r.target.table}.${r.target.column}`);return r.lastAccessAt=Date.now(),vi(r),{byteOffset:t,bytes:a.slice(),done:t+a.byteLength>=r.metadata.byteLength}}async function Ka(e){if(typeof e!="string"||e.length===0)throw new Error("Cell read session id is required");if(!Xt(e)&&!Ie.has(e))throw new Error(`Unknown cell read session: ${e}`)}function ja(e){if(We&&!["readCellChunk","closeCellReadSession","initializeDatabase"].includes(e))throw new Error("A cell read snapshot is active; close it before another database operation")}function za(e){return!!e&&typeof e=="object"&&typeof e.slice=="function"&&typeof e.size=="number"}function Qa(e,t){let n=e.size,r=wi((o,i)=>new Uint8Array(t.readAsArrayBuffer(e.slice(o,o+i))));return{size:()=>n,read:r}}function Xa(e){let t={};return e.pagedOpenThresholdBytes!==void 0&&(t.pagedThresholdBytes=e.pagedOpenThresholdBytes),e.bufferOpenCeilingBytes!==void 0&&(t.bufferCeilingBytes=e.bufferOpenCeilingBytes),t}function Ga(e){if(e===void 0)return xe;if(!Number.isSafeInteger(e)||e<1)throw new Error("pagedExportMaxBytes must be a positive safe integer");if(e>xe)throw new Error(`pagedExportMaxBytes must not exceed ${xe} bytes`);return e}function Ne(e){let t="Unknown error";try{t=e&&typeof e=="object"&&typeof e.message=="string"&&e.message?e.message:String(e)}catch{}return t||(t="Unknown error"),t.length<=Si?t:t.slice(0,Si)+`... [truncated from ${t.length} characters]`}async function Ya(e,t){if(Xt(),p&&(p.close(),p=null),Gn=Number.isFinite(t.queryTimeout)&&t.queryTimeout>0?t.queryTimeout:Ai,j=t.readOnlyMode===!0,Ht=null,Ve="memory",Ae=0,ct=Ga(t.pagedExportMaxBytes),_i=Kn(t.pagedExactCountMaxFileBytes),rr=Un(t.cellReadSessionIdleTimeoutMs,Dn),$i=Un(t.cellReadSessionAbsoluteTimeoutMs,Mn),Ie.clear(),!pe){importScripts(ka);let n={};t.wasmBinary?n.wasmBinary=t.wasmBinary:n.locateFile=()=>Pa,pe=await self.initSqlJs(n)}return za(t.file)?Ve=Ja(t.file,Xa(t)):t.content&&t.content.length>0?p=new pe.Database(t.content):p=new pe.Database,j&&p.run("PRAGMA query_only = ON"),{operations:{},isReadOnly:j,storage:Ve,...Ht?{readOnlyReason:Ht}:{}}}function Ja(e,t){let n=new FileReaderSync,r=new Uint8Array(n.readAsArrayBuffer(e.slice(0,ui))),o=!j&&typeof pe.Database.openPagedWritable=="function",i=typeof pe.Database.openPaged=="function",l={sizeBytes:e.size,walMarked:di(r),pagedAvailable:o||i},s=Hn(l,t),a=null;if(s.mode==="paged"){let d=Math.min(ct,t.bufferCeilingBytes??xe),c=e.size>d,u=!j&&c?`This database exceeds the ${d}-byte browser save limit and is open read-only so edits cannot be stranded. Use the desktop extension to edit and save it.`:null,f=Qa(e,n),m=[];if(o&&!c)try{return p=pe.Database.openPagedWritable(f),Ae=e.size,"paged"}catch(y){let g=Ne(y);m.push(`writable paged open failed: ${g}`),p=null}if(i)try{return p=pe.Database.openPaged(f),j=!0,Ht=u,Ae=e.size,"paged"}catch(y){let g=Ne(y);m.push(`read-only paged open failed: ${g}`),p=null}a=m.length>0?new Error(m.join("; ")):null,s=Hn({...l,pagedAvailable:!1},t)}if(s.mode==="reject")throw new Error(a?`${s.message} (paged open failed: ${a.message})`:s.message);return p=new pe.Database(new Uint8Array(n.readAsArrayBuffer(e))),s.readOnly&&(j=!0),"memory"}async function Za(e,t=[],n){if(!p)throw new Error("No database initialized");if(j)throw new Error("Ad hoc SQL execution is unavailable because the database is read-only");try{return jt(()=>p.exec(e,t),n).map(o=>({headers:o.columns,rows:o.values}))}catch(r){throw r}}async function el(e,t="[]",n){if(!p)throw new Error("No database initialized");if(typeof e!="string"||typeof t!="string")throw new TypeError("SQL and parameter JSON must be strings");let r=_o(e),o=$o(t);if(o.length!==r.parameterCount)throw new Error(`Expected ${r.parameterCount} positional parameters.`);let i=`query_columns_${crypto.randomUUID().replace(/-/g,"")}`,l=Number(p.exec("PRAGMA query_only")[0]?.values[0]?.[0])===1,s=!1,a;try{l&&S("PRAGMA query_only = OFF"),a=jt(()=>{S(`CREATE TEMP VIEW "${i}" AS ${r.metadataSql}`),s=!0;let d=(p.exec("SELECT substr(name, 1, 4097) FROM pragma.pragma_table_info(?, 'temp') ORDER BY cid LIMIT ?",[i,Bt+1])[0]?.values??[]).map(c=>String(c[0]));if(!d.length||d.length>Bt)throw new Error("Queries support 1 to 128 result columns.");if(d.some(c=>c.length>4096))throw new Error("Result column labels must be at most 4096 characters.");return d},n)}finally{try{s&&S(`DROP VIEW temp."${i}"`)}finally{if(l)try{S("PRAGMA query_only = ON")}catch(d){let c=p;throw p=null,c.close(),d}}}return jt(()=>{let d=Oo(r.sql,a.length),c=ut(d.sql);try{c.bind(o);let u=[];for(;u.length<=Pt&&c.step();)u.push(c.get(null,{useBigInt:!0}));return Lo(a,u,d.valueColumnCount)}finally{c.free()}},n)}async function tl(e){if(!p)throw new Error("No database initialized");let t=Ve==="paged"&&!j;if(Ve==="paged"&&j)throw new Error("paged databases are read-only snapshots; export() is only available on openPagedWritable instances");let n=()=>new Error(`Cannot download this page-on-demand database: the merged image would exceed the ${ct}-byte browser memory limit. Saving materializes the complete database in memory; use the desktop extension or reduce the database size.`);if(t&&Ae>ct)throw n();let r;try{r=p.export()}catch(o){let i=Ne(o);throw t&&/transaction is open|while a transaction/i.test(i)?new Error("Cannot save while a database transaction is open; retry after the edit completes.",{cause:o}):o}if(t&&r.byteLength>ct)throw n();return r}async function nl(e,t,n,r,o={}){if(!p)throw new Error("No database initialized");let i=e?.table;if(!i)throw new Error("No table specified");let{format:l="csv",header:s=!0,includeTableName:a=!0,rowIds:d=null}=o;if(!["csv","json","sql","excel"].includes(l))throw new Error(`Unsupported export format: ${l}`);let c=[{sql:"",params:[]}];if(d&&d.length>0){let C=await te(i);if(d.some(X)&&!d.every(X))throw new Error("Cannot mix rowid and primary-key row identities");let N=new Set,I=[];for(let L of d){let w=C.kind==="rowid"?M(L):L,v=String(w);N.has(v)||(N.add(v),I.push(w))}c=tt(I,C)}let u=t&&t.length>0?t:rl(i);if(u.length>Kt)throw new Error(`Cannot export more than ${Kt} columns`);let f=l!=="csv"&&l!=="excel",m=u.map((C,N)=>{let I=h(C),L=`typeof(${I})`,w=`octet_length(${I})`;return`CASE ${L} WHEN 'null' THEN 'n:0:' WHEN 'integer' THEN 'i:0:' || CAST(${I} AS TEXT) WHEN 'real' THEN 'r:0:' || printf('%!.17g', ${I}) WHEN 'text' THEN 't:' || CAST(${w} AS TEXT) || ':' || hex(CAST(${I} AS BLOB)) WHEN 'blob' THEN 'b:' || CAST(${w} AS TEXT) || ':' || `+(f?`hex(${I}) `:"'' ")+`END AS ${h(`__export_cell_${N}`)}`}).join(", "),y=P("sp_export_rows");S(`SAVEPOINT ${y}`);let g=[];try{let C=1024;for(let N of c){let I=N.sql?` WHERE ${N.sql}`:"";if(C+=al(i,u,I,N.params,l),!Number.isSafeInteger(C)||C>Ni)throw or()}for(let N of c){let I=N.sql?` WHERE ${N.sql}`:"",L=p.exec(`SELECT ${m} FROM ${R(i)}${I}`,N.params);L.length>0&&g.push(...L[0].values)}S(`RELEASE ${y}`)}catch(C){throw B(y,"exportTable"),C}let E=u,T=Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]),x=g.map((C,N)=>{if(C.length!==u.length)throw new Error(`SQLite returned ${C.length} packed export cells for row ${N}; expected ${u.length}`);return u.map((I,L)=>il(i,I,C[L],f,T))}),A=new Yn,_="text/plain",b=`${i}.${l}`;switch(l){case"csv":Ti(E,x,s,A),_="text/csv";break;case"json":cl(E,x,A),_="application/json";break;case"sql":ul(i,E,x,a,A),_="text/sql";break;case"excel":Ti(E,x,s,A),_="text/csv",b=`${i}.csv`;break}return{contentChunks:A.finish(),filename:b,mimeType:_}}function or(){return new Error(`Web demo exports are limited to ${Da} because the worker RPC cannot stream downloads; use the desktop extension for larger exports.`)}function rl(e){let t=p.prepare(`SELECT * FROM ${R(e)} LIMIT 0`);try{return t.getColumnNames()}finally{t.free()}}function ol(e,t,n){if(e.length!==t*2||/[^0-9a-f]/i.test(e))throw new Error(`SQLite returned invalid packed bytes for ${n}`);let r=new Uint8Array(t);for(let o=0;o1;){let n=[];for(let r=0;r{let u=h(c),f=`length(${u})`,m=o==="csv"||o==="excel"?"64":o==="json"?`((${f} + 2) / 3) * 4 + 64`:`${f} * 2 + 64`;return`CASE typeof(${u}) WHEN 'text' THEN length(CAST(${u} AS BLOB)) * 6 + 64 WHEN 'blob' THEN ${m} ELSE 64 END`})),s=p.exec(`SELECT COUNT(*), COALESCE(SUM(${i}), 0) FROM ${R(e)}${n}`,r)[0]?.values?.[0]??[0,0],a=Number(s[0]),d=Number(s[1])+a*128;if(!Number.isSafeInteger(d)||d<0)throw or();return d}function ll(e){let t=0;for(let n=0;n=55296&&r<=56319&&n+1=56320&&o<=57343?(t+=4,n++):t+=3}else t+=3}return t}var Yn=class{constructor(){this.chunks=[],this.pending="",this.outputBytes=0}append(t){if(this.outputBytes+=ll(t),!Number.isSafeInteger(this.outputBytes)||this.outputBytes>Ni)throw or();let n=0;for(;n0&&t.charCodeAt(o-1)>=55296&&t.charCodeAt(o-1)<=56319&&t.charCodeAt(o)>=56320&&t.charCodeAt(o)<=57343&&r--,r===0){this.flush();continue}this.pending+=t.slice(n,n+r),n+=r,this.pending.length>=bi&&this.flush()}}flush(){this.pending.length>0&&(this.chunks.push(this.pending),this.pending="")}finish(){return this.flush(),this.chunks}};function Ti(e,t,n,r){let o=!1,i=l=>{o&&r.append(` -`),r.append(l.join(",")),o=!0};n&&i(e.map(l=>En({storageClass:"text",value:l})));for(let l of t)i(l.map(En))}function cl(e,t,n){n.append("[");for(let r=0;r_o)throw new Error("Parameters exceed 65,536 characters.");let t=JSON.parse(e);if(!Array.isArray(t)||t.length>100)throw new Error("Enter a JSON array of at most 100 values.");for(let n of t){if(n!==null&&typeof n!="string"&&typeof n!="number")throw new Error("Parameters must be null, string, or number.");if(typeof n=="number"&&(!Number.isFinite(n)||Number.isInteger(n)&&!Number.isSafeInteger(n)))throw new Error("Numbers must be finite and integer values must be safe integers. Supply an exact integer as a quoted string and use CAST(? AS INTEGER).")}return t}function Lo(e,t){if(t<1||t>Dt)throw new Error("Queries support 1 to 128 result columns.");let n=_t(e,t,{limit:Bt+1,maxInlineCellBytes:64*1024,maxPageResponseBytes:No});return Ye(n.sql,n.primaryTransportColumnCount)}function vo(e,t,n){let r=ke(t,n);return{headers:e,...Pt(r.rows,e.length,r.exactIntegerTexts,No)}}function we(e){let t=e==null?"":String(e);return t.trim()?t:void 0}function Vt(e,t,n="set"){if(n==="json_patch")return{value:e,operation:"json_patch"};if(typeof e!="string"||typeof t!="string"||!(e.startsWith("{")||e.startsWith("["))||!(t.startsWith("{")||t.startsWith("[")))return{value:e,operation:"set"};try{let r=JSON.parse(t),o=JSON.parse(e);if(!r||typeof r!="object"||Array.isArray(r)||!o||typeof o!="object"||Array.isArray(o))return{value:e,operation:"set"};let i=Do(r,o);return i===void 0||Bo(i)?{value:e,operation:"set"}:{value:JSON.stringify(i),operation:"json_patch"}}catch{return{value:e,operation:"set"}}}function Bo(e){return e===null?!0:F(e)?Object.values(e).some(Bo):!1}function Do(e,t,n=0){if(n>1e3)throw new Error("JSON merge patch depth limit exceeded");if(e===t)return;if(!F(e)||!F(t)||Array.isArray(e)||Array.isArray(t))return t;let r=Object.create(null),o=!1;for(let i of Object.keys(t)){let l=Object.prototype.hasOwnProperty.call(e,i)?e[i]:void 0,s=t[i];if(l===void 0)r[i]=s,o=!0;else if(l!==s){let a=Do(l,s,n+1);a!==void 0&&(r[i]=a,o=!0)}}for(let i of Object.keys(e))Object.prototype.hasOwnProperty.call(t,i)||(r[i]=null,o=!0);return o?r:void 0}function Mo(e,t,n=0){if(n>1e3)throw new Error("JSON apply merge patch depth limit exceeded");if(t===null)return null;if(typeof t!="object"||Array.isArray(t))return t;let r;typeof e!="object"||e===null||Array.isArray(e)?r=Object.create(null):r=Object.assign(Object.create(null),e);let o=t;for(let i in o)if(Object.prototype.hasOwnProperty.call(o,i)){let l=o[i];l===null?delete r[i]:r[i]=Mo(r[i],l,n+1)}return r}function Mt(e){if(typeof e=="string")try{let t=JSON.parse(e);return F(t)?t:void 0}catch{return}}function Uo(e,t,n,r,o){let i=o==="undo"?r:n,l=o==="undo"?n:r,s=()=>Po(e,i)?{kind:"write",value:l}:{kind:"conflict"};if(Ut(e)||Ut(t)||Ut(n)||Ut(r))return s();let a=Mt(e),d=Mt(t),c=Mt(n),u=Mt(r);if(!a||!d||!c||!u)return s();if(!Vo(a,o==="undo"?u:c,d,c,0))return{kind:"conflict"};if(Po(e,i))return{kind:"write",value:l};let m=o==="undo"?_n(a,d,c,0):Mo(a,d,0);return{kind:"write",value:JSON.stringify(m)}}function Vo(e,t,n,r,o){if(o>1e3)throw new Error("JSON history replay depth limit exceeded");for(let i of Object.keys(n)){let l=n[i],s=Object.prototype.hasOwnProperty.call(e,i),a=Object.prototype.hasOwnProperty.call(t,i),d=Object.prototype.hasOwnProperty.call(r,i),c=s?e[i]:void 0,u=a?t[i]:void 0,f=d?r[i]:void 0;if(F(l)){if(!d||!F(f)){if(!ko(s,c,a,u,o+1))return!1;continue}if(!s||!F(c)||!a||!F(u)||!Vo(c,u,l,f,o+1))return!1;continue}if(!ko(s,c,a,u,o+1))return!1}return!0}function ko(e,t,n,r,o){return e===n&&(!e||Nn(t,r,o))}function Nn(e,t,n){if(n>1e3)throw new Error("JSON history replay depth limit exceeded");if(Object.is(e,t))return!0;if(Array.isArray(e)||Array.isArray(t))return!Array.isArray(e)||!Array.isArray(t)||e.length!==t.length?!1:e.every((i,l)=>Nn(i,t[l],n+1));if(!F(e)||!F(t))return!1;let r=Object.keys(e),o=Object.keys(t);return r.length!==o.length?!1:r.every(i=>Object.prototype.hasOwnProperty.call(t,i)&&Nn(e[i],t[i],n+1))}function Po(e,t){return e instanceof Uint8Array||t instanceof Uint8Array?!(e instanceof Uint8Array)||!(t instanceof Uint8Array)?!1:e.length===t.length&&e.every((n,r)=>n===t[r]):Object.is(e,t)}function _n(e,t,n,r){if(r>1e3)throw new Error("JSON undo restore depth limit exceeded");let o=Object.assign(Object.create(null),e);for(let i of Object.keys(t)){let l=t[i],s=Object.prototype.hasOwnProperty.call(n,i),a=s?n[i]:void 0;if(F(l))if(s&&F(a))if(Object.prototype.hasOwnProperty.call(o,i)&&F(o[i])){let d=o[i];o[i]=_n(d,l,a,r+1)}else o[i]=a;else if(s)o[i]=a;else{let d=Object.prototype.hasOwnProperty.call(o,i)&&F(o[i])?o[i]:Object.create(null),c=_n(d,l,Object.create(null),r+1);Object.keys(c).length===0?delete o[i]:o[i]=c}else s?o[i]=a:delete o[i]}return o}function Ut(e){if(typeof e!="string")return!1;let n=e.replace(/"(?:\\.|[^"\\])*"/g,'""').match(/-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g);return n?n.some(r=>{let o=Number(r);return!Number.isFinite(o)||JSON.stringify(o)!==r}):!1}function F(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}var la=new Set(["null","integer","real","text","blob"]),ca="Cell changed outside SQLite Explorer history; undo/redo was not applied.",ua="This edit predates guarded cell history and cannot be replayed safely. Save or reload the database.",oe=class extends Error{constructor(n,r){let o=r.length===1?`${n}.${r[0]}`:`${r.length} cells in ${n}`;super(`${o}: ${ca}`);D(this,"code","SQLITE_EXPLORER_CELL_HISTORY_CONFLICT");this.name="CellHistoryConflictError"}},ot=class extends Error{constructor(){super(ua);D(this,"code","SQLITE_EXPLORER_LEGACY_CELL_HISTORY");this.name="LegacyCellHistoryError"}};function ee(e){let t=h(e);return`typeof(${t}), CASE WHEN typeof(${t}) = 'text' THEN CAST(${t} AS BLOB) ELSE ${t} END`}function da(e,t,n){if(!t)throw new Error(`SQLite text encoding is required for ${n}`);try{return{value:new TextDecoder(t,{fatal:!0,ignoreBOM:!0}).decode(e)}}catch{return{value:"",rawTextBytes:e}}}function q(e,t,n,r={}){if(typeof e!="string"||!la.has(e))throw new Error(`SQLite returned an invalid storage class for ${n}`);let o=e;if(o!=="text"&&r.rawTextBytes!==void 0)throw new Error(`SQLite returned raw TEXT bytes for non-TEXT ${n}`);if(o==="text"){if(t instanceof Uint8Array)return{storageClass:o,...da(t,r.textEncoding,n)};if(typeof t!="string")throw new Error(`SQLite returned an invalid text value for ${n}`);if(r.rawTextBytes!==void 0&&!(r.rawTextBytes instanceof Uint8Array))throw new Error(`SQLite returned invalid raw TEXT bytes for ${n}`);return{storageClass:o,value:t,...r.rawTextBytes instanceof Uint8Array?{rawTextBytes:r.rawTextBytes}:{}}}if(!(o==="null"?t===null:o==="integer"?typeof t=="bigint"||typeof t=="number"&&Number.isInteger(t):o==="real"?typeof t=="number":t instanceof Uint8Array))throw new Error(`SQLite returned an invalid ${o} value for ${n}`);return{storageClass:o,value:t}}function it(e){if(!e||typeof e!="object")throw new ot;q(e.storageClass,e.value,"cell history",{rawTextBytes:e.rawTextBytes})}function $n(e,t){if(e.storageClass!==t.storageClass)return!1;if(e.storageClass==="text"){let o=e.rawTextBytes,i=t.rawTextBytes;if(o||i)return!o||!i?!1:o.length===i.length&&o.every((l,s)=>l===i[s])}let n=e.value,r=t.value;return e.storageClass==="integer"&&typeof n!=typeof r?typeof n=="number"&&Number.isSafeInteger(n)&&typeof r=="bigint"?BigInt(n)===r:typeof r=="number"&&Number.isSafeInteger(r)&&typeof n=="bigint"?n===BigInt(r):!1:n instanceof Uint8Array||r instanceof Uint8Array?!(n instanceof Uint8Array)||!(r instanceof Uint8Array)?!1:n.length===r.length&&n.every((o,i)=>o===r[i]):Object.is(n,r)}function qt(e,t=()=>"?"){switch(it(e),e.storageClass){case"null":return{sql:"NULL",params:[]};case"integer":return{sql:t(e.value),params:[e.value]};case"real":return{sql:"CAST(? AS REAL)",params:[e.value]};case"text":return{sql:e.rawTextBytes?"CAST(substr(?, 1) AS TEXT)":"CAST(? AS TEXT)",params:[e.rawTextBytes??e.value]};case"blob":return{sql:"?",params:[e.value]}}}function Wt(e,t,n=()=>"?"){it(t);let r=h(e);switch(t.storageClass){case"null":return{sql:`typeof(${r}) = 'null'`,params:[]};case"integer":{let o=n(t.value);return{sql:`typeof(${r}) = 'integer' AND ${r} IS ${o}`,params:[t.value]}}case"real":return{sql:`typeof(${r}) = 'real' AND ${r} IS CAST(? AS REAL)`,params:[t.value]};case"text":return{sql:`typeof(${r}) = 'text' AND CAST(${r} AS BLOB) = CAST(? AS BLOB)`,params:[t.rawTextBytes??t.value]};case"blob":return{sql:`typeof(${r}) = 'blob' AND ${r} IS ?`,params:[t.value]}}}var fa="Row changed outside SQLite Explorer history; undo/redo was not applied.",ma="This row edit predates guarded row history and cannot be replayed safely. Save or reload the database.",Se=class extends Error{constructor(n){super(`${n}: ${fa}`);D(this,"code","SQLITE_EXPLORER_ROW_HISTORY_CONFLICT");this.name="RowHistoryConflictError"}},G=class extends Error{constructor(){super(ma);D(this,"code","SQLITE_EXPLORER_LEGACY_ROW_HISTORY");this.name="LegacyRowHistoryError"}};function st(e){if(!Array.isArray(e.storageClasses))throw new G;let t=new Set;return e.storageClasses.map(n=>{let r=typeof n?.column=="string"?Ct(n.column):void 0;if(!n||typeof n.column!="string"||r===void 0||t.has(r)||!Object.prototype.hasOwnProperty.call(e.row,n.column))throw new G;t.add(r);let o=e.row[n.column],i=n.storageClass==="text"&&o instanceof Uint8Array?o:void 0;return{column:n.column,state:q(n.storageClass,i?"":o,`row history column ${n.column}`,{rawTextBytes:i})}})}function On(e,t=()=>"?"){let n=st(e).map(({column:r,state:o})=>Wt(r,o,t));return{sql:n.length>0?n.map(r=>`(${r.sql})`).join(" AND "):"1",params:n.flatMap(r=>r.params)}}function qo(e,t=()=>"?"){return st(e).map(({column:n,state:r})=>({column:n,write:qt(r,t)}))}var Ln="~sqlite-explorer-non-finite:",Bc=`${Ln}Infinity`,pa=`${Ln}-Infinity`,Dc=`${Ln}NaN`,ga=pa.length+2;function Wo(e){let t=new Set,n=[e],r=0;for(;n.length>0;){let o=n.pop();if(o!=null){if(typeof o=="boolean")r+=4;else if(typeof o=="number"||typeof o=="bigint")r+=8;else if(typeof o=="string")r+=o.length*2;else if(o instanceof Uint8Array)r+=o.byteLength;else if(typeof o=="object"){if(t.has(o))continue;if(t.add(o),r+=8,Array.isArray(o))for(let i of o)n.push(i);else for(let i in o)Object.prototype.hasOwnProperty.call(o,i)&&(r+=i.length*2,n.push(o[i]))}}}return r}var ya=32,Ea=48;function Fo(e,t){let n=typeof e=="bigint"?Number(e):e;if(!Number.isSafeInteger(n)||Number(n)<0)throw new Error(`SQLite returned an unsafe ${t} during delete undo preflight`);return Number(n)}function Ho(e,t){return[...e]}function Ko(e,t,n){return{sql:`SELECT COUNT(*), COALESCE(SUM(${t.map(o=>{let i=h(o);return`CASE typeof(${i}) WHEN 'text' THEN 2 * octet_length(${i}) WHEN 'blob' THEN octet_length(${i}) WHEN 'integer' THEN 8 WHEN 'real' THEN 8 ELSE 0 END`}).join(" + ")||"0"}), 0) FROM ${R(e)} WHERE ${n.sql}`,params:n.params}}function jo(e){if(!e||e.length<2)throw new Error("SQLite omitted delete undo preflight metadata");return{rowCount:Fo(e[0],"row count"),valueBytes:Fo(e[1],"value byte count")}}function zo(e){if(!Number.isSafeInteger(e.maxSnapshotBytes)||e.maxSnapshotBytes<0)throw new Error("Delete undo snapshot budget must be a non-negative safe integer");if(e.rowCount!==e.rowIds.length)throw new Error(`Cannot delete from ${e.table}: one or more row identities no longer exist`);let n=[...new Set(e.insertableColumns)].reduce((l,s)=>l+s.length*2,0),r=e.rowIds.reduce((l,s)=>l+Wo(s),0),o=e.rowCount*e.insertableColumns.reduce((l,s)=>l+s.length*2+Ea,0),i=e.valueBytes+r+e.rowCount*(ya+n)+o;if(!Number.isSafeInteger(i)||i>e.maxSnapshotBytes){let l=e.operation??"Delete";throw new Error(`${l} undo snapshot exceeds the ${e.maxSnapshotBytes}-byte memory budget; ${l.toLowerCase()} fewer rows or increase sqliteExplorer.maxUndoMemory.`)}}var Ft="ksa:",Ht=1,kn=128*1024,ha=["first","after","atOrAfter","before","last"];function Pn(e){return e.orderBy?.toLowerCase()==="rowid"&&e.columns?.[0]?.toLowerCase()==="rowid"&&!e.columns.slice(1).some(t=>t.toLowerCase()==="rowid")}function Bn(e,t){let n=(t.filters??[]).flatMap(a=>{let d=we(a.value);return d===void 0?[]:[[a.column,d]]}),r=we(t.globalFilter)??null,o=r===null?null:t.globalFilterColumns??t.columns??null,i=typeof t.orderBy=="string"&&t.orderBy!==""?t.orderBy:null,l=i!==null&&t.orderDir==="DESC"?"DESC":"ASC",s=typeof t.limit=="number"&&Number.isSafeInteger(t.limit)?t.limit:null;return JSON.stringify([Ht,e,i,l,s,n,r,o])}function Dn(e,t){if(!t||e.orderByColumns?.length)return;let n=t.kind==="rowid"?["rowid"]:t.columns.map(i=>i.identifier);if(n.length===0)return;let r=typeof e.orderBy=="string"&&e.orderBy!==""?e.orderBy:void 0;if(r===void 0)return{keyColumns:n,nullableSortKey:!1,direction:"ASC"};let o=e.orderDir==="DESC"?"DESC":"ASC";return Pn(e)?{keyColumns:n,nullableSortKey:!1,direction:o}:n.includes(r)?{keyColumns:[r,...n.filter(i=>i!==r)],nullableSortKey:!1,direction:o}:{keyColumns:[r,...n],nullableSortKey:!0,direction:o}}function Qo(e,t){if(!(!e||t))return{orderByColumns:e.keyColumns,orderDir:e.direction}}function wa(e){return e===null?["null"]:Rt(e)}function Sa(e){return Array.isArray(e)&&e.length===1&&e[0]==="null"?{value:null,storageClass:"null"}:{value:io(e),storageClass:e[0]}}function ba(e,t){if(t.length===0)throw new Error("Keyset anchor requires at least one key value");let n={v:Ht,t:e,k:t.map(wa)};return Ft+encodeURIComponent(JSON.stringify(n))}function Ca(e){if(e.length>kn)throw new Error(`Keyset anchor exceeds the ${kn}-byte limit`)}function Ta(e){if(typeof e!="string"||!e.startsWith(Ft))throw new Error("Invalid keyset anchor");Ca(e);let t;try{t=JSON.parse(decodeURIComponent(e.slice(Ft.length)))}catch{throw new Error("Invalid keyset anchor encoding")}if(!t||typeof t!="object"||Array.isArray(t)||Object.keys(t).length!==3||t.v!==Ht||typeof t.t!="string"||!Array.isArray(t.k))throw new Error("Invalid keyset anchor payload");let n=t.k;if(n.length===0)throw new Error("Keyset anchor has no key values");let r,o;try{let l=n.map(Sa);r=l.map(s=>s.value),o=l.map(s=>s.storageClass)}catch(l){throw new Error(`Invalid keyset anchor value: ${l instanceof Error?l.message:String(l)}`)}if(Ft+encodeURIComponent(JSON.stringify({v:Ht,t:t.t,k:n}))!==e)throw new Error("Keyset anchor is not canonical");return{tag:t.t,values:r,valueClasses:o}}function Xo(e,t,n){let r=t.keyset;if(!r||typeof r!="object"||Array.isArray(r)||!ha.includes(r.mode))return;let o=Dn(t,n);if(!o)return;let i=typeof t.limit=="number"&&Number.isSafeInteger(t.limit)&&t.limit>0?t.limit:void 0;if(i===void 0)return;if(r.mode==="first")return{...o,mode:"first",limit:i};if(r.mode==="last"){let a=r.lastPageRowCount??i;return typeof a!="number"||!Number.isSafeInteger(a)||a<1||a>i?void 0:{...o,mode:"last",limit:a}}if(r.anchor===void 0)return;let l=Ta(r.anchor);if(l.tag!==Bn(e,t)||l.values.length!==o.keyColumns.length)return;let s=o.nullableSortKey?1:0;if(l.values.some((a,d)=>a===null&&d>=s))throw new Error("Keyset anchor has NULL in an identity slot");return{...o,mode:r.mode,values:l.values,valueClasses:l.valueClasses,limit:i}}function vn(e,t,n){return e.length===1?`${e[0]} ${t} ${n[0]}`:`(${e.join(", ")}) ${t} (${n.join(", ")})`}function Ra(e){let t=e.values,r=e.mode==="before"?e.direction==="ASC"?"DESC":"ASC":e.direction,o=(r==="ASC"?">":"<")+(e.mode==="atOrAfter"?"=":""),i=e.keyColumns.map(h),l=e.keyColumns.map((f,m)=>e.valueClasses?.[m]==="integer"?"CAST(? AS INTEGER)":"?");if(!e.nullableSortKey)return{sql:vn(i,o,l),params:t};let s=i[0],a=i.slice(1),d=t[0],c=t.slice(1);if(d===null){let f=vn(a,o,l.slice(1));return r==="ASC"?{sql:`((${s} IS NULL AND ${f}) OR ${s} IS NOT NULL)`,params:c}:{sql:`(${s} IS NULL AND ${f})`,params:c}}let u=vn(i,o,l);return r==="ASC"?{sql:u,params:t}:{sql:`(${u} OR ${s} IS NULL)`,params:t}}function Go(e){let{plan:t}=e,n=t.mode==="before"||t.mode==="last",r=n?t.direction==="ASC"?"DESC":"ASC":t.direction,o=[...e.whereClauses],i=[...e.filterParams];if(t.mode!=="first"&&t.mode!=="last"){let d=Ra(t);o.push(d.sql),i.push(...d.params)}let l=t.keyColumns.map(h),s=d=>l.map(c=>`${c} ${d}`).join(", "),a=`SELECT ${e.selectListSql} FROM ${e.escapedTable}`;return o.length>0&&(a+=` WHERE ${o.join(" AND ")}`),a+=` ORDER BY ${s(r)} LIMIT ${t.limit}`,n&&(a=`SELECT * FROM (${a}) ORDER BY ${s(t.direction)}`),{sql:a,params:i}}function Yo(e){if(e.rows.length===0)return;let t=e.key.keyColumns.map(i=>e.projectionColumns.indexOf(i));if(t.some(i=>i<0))return;let n=i=>{if(e.excludedRowIndices?.has(i))return;let l=e.rows[i],s=[];for(let d=0;dZo)throw new Error(`Cell read chunk size must be an integer from 1 through ${Zo}`)}function Be(e){let t=String(e).toLowerCase().replace(/[_\s-]/g,"");if(t==="utf8")return"utf-8";if(t==="utf16le")return"utf-16le";if(t==="utf16be")return"utf-16be";throw new Error(`Unsupported SQLite text encoding: ${String(e)}`)}function ni(e,t,n){if(e.length!==1)throw new Error(e.length===0?`Cell ${n.table}.${n.column} no longer exists`:`Cell ${n.table}.${n.column} matched more than one row`);let r=e[0][0];if(typeof r!="string"||!Aa.has(r))throw new Error(`SQLite returned an invalid storage class for ${n.table}.${n.column}`);let o=e[0][1],i=typeof o=="bigint"?Number(o):o;if(!Number.isSafeInteger(i)||Number(i)<0)throw new Error(`SQLite returned an unsafe byte length for ${n.table}.${n.column}`);return{storageClass:r,byteLength:Number(i),...r==="text"?{textEncoding:t}:{}}}function Vn(e,t){return Number.isFinite(e)&&Number(e)>=1?Math.floor(Number(e)):t}var De=me,qn=Z;var Wn="SQLITE_EXPLORER_CELL_EDIT_VALUE_TOO_LARGE",Fn="SQLITE_EXPLORER_OVERSIZED_CELL_REPLACEMENT_REQUIRED",ri="Oversized cell metadata changed before the confirmed replacement was applied";var Na=De,Hn=class extends Error{constructor(n,r,o,i=`New ${n.toUpperCase()} cell value is ${r} bytes and exceeds the ${o}-byte edit limit.`){super(i);D(this,"storageClass",n);D(this,"actualBytes",r);D(this,"limitBytes",o);D(this,"name","CellEditPolicyError");D(this,"code",Wn)}},Me=class extends Error{constructor(n,r,o,i,l,s=`Existing ${o.toUpperCase()} cell ${n}.${r} is ${i} bytes. Use the explicitly confirmed oversized-cell replacement path.`){super(s);D(this,"table",n);D(this,"column",r);D(this,"storageClass",o);D(this,"actualBytes",i);D(this,"limitBytes",l);D(this,"name","OversizedCellReplacementRequiredError");D(this,"code",Fn)}};function _a(e){let t=0;for(let n=0;n=55296&&r<=56319){let o=e.charCodeAt(n+1);o>=56320&&o<=57343?(t+=4,n++):t+=3}else t+=3}return t}function at(e,t){if(!Number.isSafeInteger(t)||t<1)throw new Error(`Cell edit limit must be a positive safe integer, got ${t}`);let n=typeof e=="string"?"text":e instanceof Uint8Array?"blob":void 0;if(!n)return;let r=typeof e=="string"?_a(e):e instanceof Uint8Array?e.byteLength:0;if(r>t)throw new Hn(n,r,t)}function oi(e){let t=e??Na;if(!Number.isSafeInteger(t)||t<1)throw new Error(`Cell edit limit must be a positive safe integer, got ${t}`);return t}function lt(e,t){let n=oi(t);for(let r of e)at(r,n);return n}function ii(e,t){let n=oi(t);if(!e||e.storageClass!=="text"&&e.storageClass!=="blob"||!Number.isSafeInteger(e.byteLength)||e.byteLength<=n)throw new Error("Guarded oversized-cell replacement requires exact TEXT/BLOB metadata above the edit limit");return n}function $a(e){if(!e||typeof e!="object")return;let t=e;if(!(t.name!=="CellEditPolicyError"||t.code!==Wn||t.storageClass!=="text"&&t.storageClass!=="blob"||!Number.isSafeInteger(t.actualBytes)||Number(t.actualBytes)<0||!Number.isSafeInteger(t.limitBytes)||Number(t.limitBytes)<1||typeof t.message!="string"))return{name:"CellEditPolicyError",code:Wn,storageClass:t.storageClass,actualBytes:Number(t.actualBytes),limitBytes:Number(t.limitBytes),message:t.message}}function Oa(e){if(!e||typeof e!="object")return;let t=e;if(!(t.name!=="OversizedCellReplacementRequiredError"||t.code!==Fn||typeof t.table!="string"||typeof t.column!="string"||t.storageClass!=="text"&&t.storageClass!=="blob"||!Number.isSafeInteger(t.actualBytes)||Number(t.actualBytes)<0||!Number.isSafeInteger(t.limitBytes)||Number(t.limitBytes)<1||typeof t.message!="string"))return{name:"OversizedCellReplacementRequiredError",code:Fn,table:t.table,column:t.column,storageClass:t.storageClass,actualBytes:Number(t.actualBytes),limitBytes:Number(t.limitBytes),message:t.message}}function si(e){return $a(e)??Oa(e)}var di=100,La=18,ai=19,li=2;var va=1024*1024*1024,xe=2145386496,ka="WAL database too large for in-memory mode; checkpoint it first";function fi(e){return e.length>ai&&e[La]===li&&e[ai]===li}function ci(e,t,n){if(e===void 0)return t;if(!Number.isSafeInteger(e)||e<1)throw new Error(`${n} must be a positive safe integer`);return e}function ui(e){return`${(e/(1024*1024*1024)).toFixed(1)} GiB`}function Kn(e,t={}){let n=ci(t.pagedThresholdBytes,va,"Paged-open threshold"),r=ci(t.bufferCeilingBytes,xe,"Buffer-open ceiling");if(n>r)throw new Error("Paged-open threshold must not exceed the buffer-open ceiling");if(!Number.isSafeInteger(e.sizeBytes)||e.sizeBytes<0)throw new Error("Database size must be a non-negative safe integer");return e.walMarked?e.sizeBytes>=r?{mode:"reject",message:ka}:{mode:"buffer",readOnly:e.sizeBytes>n}:e.sizeBytes>n&&e.pagedAvailable?{mode:"paged"}:e.sizeBytes>=r?{mode:"reject",message:`Database is too large to load into memory in this browser (${ui(e.sizeBytes)}; limit ${ui(r)}) and page-on-demand mode is unavailable`}:{mode:"buffer",readOnly:!1}}var Pa=64*1024*1024,Ue=1e4,pi=`SELECT 1 FROM pragma.pragma_table_list WHERE "schema" = 'main' AND "name" = ? AND "type" IN ('table', 'shadow') AND "wr" = 1 LIMIT 1`;function jn(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:Pa}function zn(e){return e.storage==="paged"&&!e.filtered&&e.authorityConfirmedRowIdTable&&e.pagedFileSizeBytes>e.exactCountMaxFileBytes}function gi(e){let t=R(e);return`SELECT (SELECT CAST(min(rowid) AS TEXT) FROM ${t}), (SELECT CAST(max(rowid) AS TEXT) FROM ${t})`}function yi(e){return`SELECT COUNT(*) FROM (SELECT 1 FROM ${R(e)} LIMIT ?)`}function Ei(e,t){if(!(typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>Ue+1))return e<=Ue?{count:e,isExact:!0}:{count:Qn(t,e),isExact:!1}}function Qn(e,t=Ue+1){return(!Number.isSafeInteger(t)||t<0)&&(t=Ue+1),!Number.isSafeInteger(e)||eBigInt(Number.MAX_SAFE_INTEGER)))return Number(i)}function wi(e,t,n){if(e===void 0)return t;if(!Number.isSafeInteger(e)||e<1)throw new Error(`${n} must be a positive safe integer`);return e}function Si(e,t={}){let n=wi(t.chunkSizeBytes,65536,"Chunk size"),r=wi(t.maxCacheBytes,8388608,"Cache budget"),o=Math.max(1,Math.floor(r/n)),i=new Map;function l(s){let a=i.get(s);if(a!==void 0)return i.delete(s),i.set(s,a),a;let d=e(s*n,n),c=d.length>n?d.subarray(0,n):d;if(i.set(s,c),i.size>o){let u=i.keys().next().value;i.delete(u)}return c}return(s,a)=>{if(!Number.isSafeInteger(s)||s<0)throw new Error("Read offset must be a non-negative safe integer");if(!Number.isSafeInteger(a)||a<0)throw new Error("Read length must be a non-negative safe integer");if(a===0)return new Uint8Array(0);let d=Math.floor(s/n),c=Math.floor((s+a-1)/n);if(d===c){let m=l(d),E=s-d*n;return E>=m.length?new Uint8Array(0):m.subarray(E,Math.min(E+a,m.length))}let u=new Uint8Array(a),f=0;for(let m=d;m<=c;m++){let E=l(m),g=m*n,y=Math.max(s,g)-g,T=Math.min(s+a,g+n)-g,x=Math.min(T,E.length);if(y>=x||(u.set(E.subarray(y,x),g+y-s),f=g+x-s,E.length{if(typeof t!="bigint")return t;let n=Number(t);return Number.isSafeInteger(n)?n:t.toString()})}function Y(e){return typeof e=="bigint"&&!Number.isSafeInteger(Number(e))?"CAST(? AS INTEGER)":"?"}function He(e){ut(e).free()}function zt(e,t){if(t!==void 0&&!(typeof SharedArrayBuffer=="function"&&t instanceof Int32Array&&t.length>0&&t.buffer instanceof SharedArrayBuffer))throw new Error("Invalid query cancellation flag");let n=()=>t!==void 0&&Atomics.load(t,0)!==0,r=()=>{let l=new Error("Query execution cancelled");throw l.name="AbortError",l};n()&&r();let o=Date.now()+Yn,i;p.progress_handler(Ma,()=>n()?(i="cancelled",!0):Date.now(){let n=ut(e),r=n.getColumnNames();n.free();let o=Ye(e,r.length),i=ut(o.sql),l=[];try{for(;i.step();)l.push(i.get(null,{useBigInt:!0}));let{rows:s,exactIntegerTexts:a}=ke(l,o.valueColumnCount);return{headers:r,rows:s,exactIntegerTexts:a}}finally{i.free()}},t)}function Li(e,t){if(t!=null)return t;let n=e??[];return n[0]==="rowid"?n.slice(1):n}function B(e,t){try{S(`ROLLBACK TO ${e}`),S(`RELEASE ${e}`)}catch(n){console.warn(`Failed to rollback savepoint (${t}):`,Ne(n))}}function Wa(e){for(Ie.add(e);Ie.size>64;)Ie.delete(Ie.values().next().value)}function vi(e){S(`ROLLBACK TO ${e}`),S(`RELEASE ${e}`)}function Gt(e){let t=We;if(!t||e!==void 0&&t.sessionId!==e)return!1;We=null,Wa(t.sessionId),t.expiryTimer!==void 0&&clearTimeout(t.expiryTimer);try{S(`RELEASE ${t.savepointName}`)}catch(n){try{vi(t.savepointName)}catch(r){let o=[n,r];try{p?.close()}catch(i){o.push(i)}finally{p=null}throw new AggregateError(o,"Cell read snapshot cleanup failed; the owning web database was closed")}}return!0}function ki(e){e.expiryTimer!==void 0&&clearTimeout(e.expiryTimer),e.expiresAt=Math.min(e.absoluteExpiresAt,e.lastAccessAt+or),e.expiryTimer=setTimeout(()=>{try{Gt(e.sessionId)}catch(t){console.error("[Worker] Failed to expire cell read session:",Ne(t))}},Math.max(1,e.expiresAt-Date.now()))}async function Pi(e){ei(e);let t=await te(e.table),n=U(e.rowId,t);return{table:e.table,column:e.column,predicateSql:n.sql,predicateParams:n.params}}function Fa(e){let t=h(e.column);return{sql:`SELECT typeof(${t}), CASE WHEN ${t} IS NULL THEN 0 ELSE length(CAST(${t} AS BLOB)) END FROM ${R(e.table)} WHERE ${e.predicateSql} LIMIT 2`,params:e.predicateParams}}function Ha(e){return{sql:`SELECT substr(CAST(${h(e.column)} AS BLOB), ? + 1, ?) FROM ${R(e.table)} WHERE ${e.predicateSql} LIMIT 2`,params:e.predicateParams}}function Ke(){return Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0])}function Bi(e,t){let n=Fa(t),r=p.exec(n.sql,O(n.params),{useBigInt:!0});return ni(r[0]?.values??[],Ke(),e)}async function Qt(e){if(!p)throw new Error("No database initialized");let t=await Pi(e);return Bi(e,t)}async function Ka(e){if(!p)throw new Error("No database initialized");if(We)throw new Error("At most one web cell read session may be open");let t=await Pi(e),n=P("sp_cell_read");S(`SAVEPOINT ${n}`);try{let r=Bi(e,t),o=Date.now(),i={sessionId:crypto.randomUUID(),target:e,sqlTarget:t,metadata:r,savepointName:n,lastAccessAt:o,absoluteExpiresAt:o+Oi,expiresAt:o+or,expiryTimer:void 0};return We=i,ki(i),{sessionId:i.sessionId,metadata:r,expiresAt:i.expiresAt}}catch(r){try{vi(n)}catch(o){let i=[r,o];try{p?.close()}catch(l){i.push(l)}finally{p=null}throw new AggregateError(i,"Cell read session open failed; the owning web database was closed")}throw r}}async function ja(e,t,n){ti(t,n);let r=We;if(!r||r.sessionId!==e)throw new Error(Ie.has(e)?`Cell read session ${e} is closed or expired`:`Unknown cell read session: ${String(e)}`);if(Date.now()>=r.expiresAt)throw Gt(e),new Error(`Cell read session ${e} is closed or expired`);let o=Ha(r.sqlTarget),l=p.exec(o.sql,O([t,n,...o.params]))[0]?.values??[];if(l.length!==1)throw new Error(l.length===0?`Cell ${r.target.table}.${r.target.column} no longer exists in its snapshot`:`Cell ${r.target.table}.${r.target.column} matched more than one row`);let s=l[0][0],a=s===null?new Uint8Array(0):s;if(!(a instanceof Uint8Array))throw new Error(`SQLite returned a non-BLOB chunk for ${r.target.table}.${r.target.column}`);return r.lastAccessAt=Date.now(),ki(r),{byteOffset:t,bytes:a.slice(),done:t+a.byteLength>=r.metadata.byteLength}}async function za(e){if(typeof e!="string"||e.length===0)throw new Error("Cell read session id is required");if(!Gt(e)&&!Ie.has(e))throw new Error(`Unknown cell read session: ${e}`)}function Qa(e){if(We&&!["readCellChunk","closeCellReadSession","initializeDatabase"].includes(e))throw new Error("A cell read snapshot is active; close it before another database operation")}function Xa(e){return!!e&&typeof e=="object"&&typeof e.slice=="function"&&typeof e.size=="number"}function Ga(e,t){let n=e.size,r=Si((o,i)=>new Uint8Array(t.readAsArrayBuffer(e.slice(o,o+i))));return{size:()=>n,read:r}}function Ya(e){let t={};return e.pagedOpenThresholdBytes!==void 0&&(t.pagedThresholdBytes=e.pagedOpenThresholdBytes),e.bufferOpenCeilingBytes!==void 0&&(t.bufferCeilingBytes=e.bufferOpenCeilingBytes),t}function Ja(e){if(e===void 0)return xe;if(!Number.isSafeInteger(e)||e<1)throw new Error("pagedExportMaxBytes must be a positive safe integer");if(e>xe)throw new Error(`pagedExportMaxBytes must not exceed ${xe} bytes`);return e}function Ne(e){let t="Unknown error";try{t=e&&typeof e=="object"&&typeof e.message=="string"&&e.message?e.message:String(e)}catch{}return t||(t="Unknown error"),t.length<=bi?t:t.slice(0,bi)+`... [truncated from ${t.length} characters]`}async function Za(e,t){if(Gt(),p&&(p.close(),p=null),Yn=Number.isFinite(t.queryTimeout)&&t.queryTimeout>0?t.queryTimeout:Ni,j=t.readOnlyMode===!0,Kt=null,Ve="memory",Ae=0,ct=Ja(t.pagedExportMaxBytes),$i=jn(t.pagedExactCountMaxFileBytes),or=Vn(t.cellReadSessionIdleTimeoutMs,Mn),Oi=Vn(t.cellReadSessionAbsoluteTimeoutMs,Un),Ie.clear(),!pe){importScripts(Ba);let n={};t.wasmBinary?n.wasmBinary=t.wasmBinary:n.locateFile=()=>Da,pe=await self.initSqlJs(n)}return Xa(t.file)?Ve=el(t.file,Ya(t)):t.content&&t.content.length>0?p=new pe.Database(t.content):p=new pe.Database,j&&p.run("PRAGMA query_only = ON"),{operations:{},isReadOnly:j,storage:Ve,...Kt?{readOnlyReason:Kt}:{}}}function el(e,t){let n=new FileReaderSync,r=new Uint8Array(n.readAsArrayBuffer(e.slice(0,di))),o=!j&&typeof pe.Database.openPagedWritable=="function",i=typeof pe.Database.openPaged=="function",l={sizeBytes:e.size,walMarked:fi(r),pagedAvailable:o||i},s=Kn(l,t),a=null;if(s.mode==="paged"){let d=Math.min(ct,t.bufferCeilingBytes??xe),c=e.size>d,u=!j&&c?`This database exceeds the ${d}-byte browser save limit and is open read-only so edits cannot be stranded. Use the desktop extension to edit and save it.`:null,f=Ga(e,n),m=[];if(o&&!c)try{return p=pe.Database.openPagedWritable(f),Ae=e.size,"paged"}catch(E){let g=Ne(E);m.push(`writable paged open failed: ${g}`),p=null}if(i)try{return p=pe.Database.openPaged(f),j=!0,Kt=u,Ae=e.size,"paged"}catch(E){let g=Ne(E);m.push(`read-only paged open failed: ${g}`),p=null}a=m.length>0?new Error(m.join("; ")):null,s=Kn({...l,pagedAvailable:!1},t)}if(s.mode==="reject")throw new Error(a?`${s.message} (paged open failed: ${a.message})`:s.message);return p=new pe.Database(new Uint8Array(n.readAsArrayBuffer(e))),s.readOnly&&(j=!0),"memory"}async function tl(e,t=[],n){if(!p)throw new Error("No database initialized");if(j)throw new Error("Ad hoc SQL execution is unavailable because the database is read-only");try{return zt(()=>p.exec(e,t),n).map(o=>({headers:o.columns,rows:o.values}))}catch(r){throw r}}async function nl(e,t="[]",n){if(!p)throw new Error("No database initialized");if(typeof e!="string"||typeof t!="string")throw new TypeError("SQL and parameter JSON must be strings");let r=$o(e),o=Oo(t);if(o.length!==r.parameterCount)throw new Error(`Expected ${r.parameterCount} positional parameters.`);let i=`query_columns_${crypto.randomUUID().replace(/-/g,"")}`,l=Number(p.exec("PRAGMA query_only")[0]?.values[0]?.[0])===1,s=!1,a;try{l&&S("PRAGMA query_only = OFF"),a=zt(()=>{S(`CREATE TEMP VIEW "${i}" AS ${r.metadataSql}`),s=!0;let d=(p.exec("SELECT substr(name, 1, 4097) FROM pragma.pragma_table_info(?, 'temp') ORDER BY cid LIMIT ?",[i,Dt+1])[0]?.values??[]).map(c=>String(c[0]));if(!d.length||d.length>Dt)throw new Error("Queries support 1 to 128 result columns.");if(d.some(c=>c.length>4096))throw new Error("Result column labels must be at most 4096 characters.");return d},n)}finally{try{s&&S(`DROP VIEW temp."${i}"`)}finally{if(l)try{S("PRAGMA query_only = ON")}catch(d){let c=p;throw p=null,c.close(),d}}}return zt(()=>{let d=Lo(r.sql,a.length),c=ut(d.sql);try{c.bind(o);let u=[];for(;u.length<=Bt&&c.step();)u.push(c.get(null,{useBigInt:!0}));return vo(a,u,d.valueColumnCount)}finally{c.free()}},n)}async function rl(e){if(!p)throw new Error("No database initialized");let t=Ve==="paged"&&!j;if(Ve==="paged"&&j)throw new Error("paged databases are read-only snapshots; export() is only available on openPagedWritable instances");let n=()=>new Error(`Cannot download this page-on-demand database: the merged image would exceed the ${ct}-byte browser memory limit. Saving materializes the complete database in memory; use the desktop extension or reduce the database size.`);if(t&&Ae>ct)throw n();let r;try{r=p.export()}catch(o){let i=Ne(o);throw t&&/transaction is open|while a transaction/i.test(i)?new Error("Cannot save while a database transaction is open; retry after the edit completes.",{cause:o}):o}if(t&&r.byteLength>ct)throw n();return r}async function ol(e,t,n,r,o={}){if(!p)throw new Error("No database initialized");let i=e?.table;if(!i)throw new Error("No table specified");let{format:l="csv",header:s=!0,includeTableName:a=!0,rowIds:d=null}=o;if(!["csv","json","sql","excel"].includes(l))throw new Error(`Unsupported export format: ${l}`);let c=[{sql:"",params:[]}];if(d&&d.length>0){let C=await te(i);if(d.some(X)&&!d.every(X))throw new Error("Cannot mix rowid and primary-key row identities");let N=new Set,I=[];for(let L of d){let w=C.kind==="rowid"?M(L):L,v=String(w);N.has(v)||(N.add(v),I.push(w))}c=tt(I,C)}let u=t&&t.length>0?t:il(i);if(u.length>jt)throw new Error(`Cannot export more than ${jt} columns`);let f=l!=="csv"&&l!=="excel",m=u.map((C,N)=>{let I=h(C),L=`typeof(${I})`,w=`octet_length(${I})`;return`CASE ${L} WHEN 'null' THEN 'n:0:' WHEN 'integer' THEN 'i:0:' || CAST(${I} AS TEXT) WHEN 'real' THEN 'r:0:' || printf('%!.17g', ${I}) WHEN 'text' THEN 't:' || CAST(${w} AS TEXT) || ':' || hex(CAST(${I} AS BLOB)) WHEN 'blob' THEN 'b:' || CAST(${w} AS TEXT) || ':' || `+(f?`hex(${I}) `:"'' ")+`END AS ${h(`__export_cell_${N}`)}`}).join(", "),E=P("sp_export_rows");S(`SAVEPOINT ${E}`);let g=[];try{let C=1024;for(let N of c){let I=N.sql?` WHERE ${N.sql}`:"";if(C+=cl(i,u,I,N.params,l),!Number.isSafeInteger(C)||C>_i)throw ir()}for(let N of c){let I=N.sql?` WHERE ${N.sql}`:"",L=p.exec(`SELECT ${m} FROM ${R(i)}${I}`,N.params);L.length>0&&g.push(...L[0].values)}S(`RELEASE ${E}`)}catch(C){throw B(E,"exportTable"),C}let y=u,T=Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]),x=g.map((C,N)=>{if(C.length!==u.length)throw new Error(`SQLite returned ${C.length} packed export cells for row ${N}; expected ${u.length}`);return u.map((I,L)=>al(i,I,C[L],f,T))}),A=new Jn,_="text/plain",b=`${i}.${l}`;switch(l){case"csv":Ri(y,x,s,A),_="text/csv";break;case"json":dl(y,x,A),_="application/json";break;case"sql":fl(i,y,x,a,A),_="text/sql";break;case"excel":Ri(y,x,s,A),_="text/csv",b=`${i}.csv`;break}return{contentChunks:A.finish(),filename:b,mimeType:_}}function ir(){return new Error(`Web demo exports are limited to ${Ua} because the worker RPC cannot stream downloads; use the desktop extension for larger exports.`)}function il(e){let t=p.prepare(`SELECT * FROM ${R(e)} LIMIT 0`);try{return t.getColumnNames()}finally{t.free()}}function sl(e,t,n){if(e.length!==t*2||/[^0-9a-f]/i.test(e))throw new Error(`SQLite returned invalid packed bytes for ${n}`);let r=new Uint8Array(t);for(let o=0;o1;){let n=[];for(let r=0;r{let u=h(c),f=`length(${u})`,m=o==="csv"||o==="excel"?"64":o==="json"?`((${f} + 2) / 3) * 4 + 64`:`${f} * 2 + 64`;return`CASE typeof(${u}) WHEN 'text' THEN length(CAST(${u} AS BLOB)) * 6 + 64 WHEN 'blob' THEN ${m} ELSE 64 END`})),s=p.exec(`SELECT COUNT(*), COALESCE(SUM(${i}), 0) FROM ${R(e)}${n}`,r)[0]?.values?.[0]??[0,0],a=Number(s[0]),d=Number(s[1])+a*128;if(!Number.isSafeInteger(d)||d<0)throw ir();return d}function ul(e){let t=0;for(let n=0;n=55296&&r<=56319&&n+1=56320&&o<=57343?(t+=4,n++):t+=3}else t+=3}return t}var Jn=class{constructor(){this.chunks=[],this.pending="",this.outputBytes=0}append(t){if(this.outputBytes+=ul(t),!Number.isSafeInteger(this.outputBytes)||this.outputBytes>_i)throw ir();let n=0;for(;n0&&t.charCodeAt(o-1)>=55296&&t.charCodeAt(o-1)<=56319&&t.charCodeAt(o)>=56320&&t.charCodeAt(o)<=57343&&r--,r===0){this.flush();continue}this.pending+=t.slice(n,n+r),n+=r,this.pending.length>=Ci&&this.flush()}}flush(){this.pending.length>0&&(this.chunks.push(this.pending),this.pending="")}finish(){return this.flush(),this.chunks}};function Ri(e,t,n,r){let o=!1,i=l=>{o&&r.append(` +`),r.append(l.join(",")),o=!0};n&&i(e.map(l=>hn({storageClass:"text",value:l})));for(let l of t)i(l.map(hn))}function dl(e,t,n){n.append("[");for(let r=0;r{a>0&&n.append(`, -`),n.append(` ${JSON.stringify(s)}: ${qr(i[s])}`)}),n.append(` +`),n.append(` ${JSON.stringify(s)}: ${Wr(i[s])}`)}),n.append(` }`)}n.append(t.length===0?"]":` -]`)}function ul(e,t,n,r,o){let i=r?h(e):'"table_name"',l=t.map(h).join(", ");n.forEach((s,a)=>{let d=s.map(Wr).join(", ");a>0&&o.append(` -`),o.append(`INSERT INTO ${i} (${l}) VALUES (${d});`)})}async function Bi(e){let t=p.exec(`SELECT "type", "wr" FROM pragma.pragma_table_list WHERE "schema" = 'main' AND "name" = ? LIMIT 1`,[e]);if((t[0]?.values.length??0)===0)return;let n=bn(t[0].values[0][0],t[0].values[0][1]);if(!n)return;if(n==="rowid")return{kind:"rowid"};let r=Cn(await Di(e));if(r.length===0)throw new Error(`WITHOUT ROWID table ${e} has no declared primary key`);return{kind:"primaryKey",columns:r}}async function te(e){let t=await Bi(e);if(!t)throw new Error(`Table not found: ${e}`);if(t.kind==="rowid"&&(p.exec(Ge,[e,e])[0]?.values.length??0)!==1)throw new Error(`Table ${e} is read-only because a declared "rowid" column shadows SQLite's intrinsic row identity`);return t}function Jn(e){return new Error(`An UPDATE trigger changed or removed the primary-key identity in ${e}; the edit was rolled back because SQLite Explorer cannot safely identify the resulting row.`)}function ir(e,t,n,r){let i=p.exec(`SELECT ${xn(t)} FROM ${R(e)} WHERE ${n.sql} LIMIT 2`,O(n.params),{useBigInt:!0})[0]?.values??[];if(i.length===0)throw r??new Error(`Updated row in ${e} no longer exists`);if(i.length!==1)throw new Error(`Primary-key identity for ${e} matched more than one row`);return In(t,i[0],Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]),`Cannot resolve updated identity in ${e}`)}function sr(e){let t=p.exec(Kr,[e]);return zr(t[0]?.values??[],e)}function dl(e,t,n=!0){let r=[...new Set(t)];if(r.length===0)throw new Error("UPDATE trigger probe requires at least one column");let o=r.map(l=>{let s=h(l);return`${s} = ${s}`}),i=n?"rowid = ?":"0";return`EXPLAIN UPDATE ${R(e)} SET ${o.join(", ")} WHERE ${i}`}function fl(e,t){return`EXPLAIN ${t.length===0?`INSERT INTO ${R(e)} DEFAULT VALUES`:`INSERT INTO ${R(e)} (${t.map(h).join(", ")}) VALUES (${t.map(()=>"NULL").join(", ")})`}`}function ml(e){return`EXPLAIN DELETE FROM ${R(e)} WHERE 0`}function dt(e,t,n=!0){let r=p.exec(Zr,O([e]),{useBigInt:!0}),o=eo(r[0]?.values??[],e),i=p.exec(dl(e,t,n),O(n?[0]:[]),{useBigInt:!0});to(e,o,i[0]?.values??[],n?"rowid":"primary-key")}function Fe(e,t,n=[]){let r=e==="INSERT"?fl(t,n):ml(t),o=p.exec(r,[],{useBigInt:!0});no(e,t,o[0]?.values??[])}function ar(e,t,n,r,o){let i=t!==void 0&&r!==void 0&&ve(t,r),l=i?h(t):"rowid",s=i?o:n,d=p.exec(`SELECT CAST(rowid AS TEXT) FROM ${R(e)} WHERE ${l} = ? LIMIT 2`,O([s??null]),{useBigInt:!0})[0]?.values??[];if(d.length===0)throw Ze(e);if(d.length!==1)throw new Error(`Rowid identity for ${e} matched more than one row`);return M(d[0][0])}function Zn(e,t){let n=typeof t=="string"?t:JSON.stringify(t),r=p.exec("SELECT json_patch(COALESCE(?, '{}'), ?)",O([e,n]))[0]?.values?.[0]?.[0];if(typeof r!="string")throw new Error("SQLite returned an invalid json_patch result");return r}function pl(e,t,n,r,o){let i=Ke(),l=new Map;for(let a of n){let d=M(a.rowId),c=l.get(d)??[];c.push({...a,rowId:d}),l.set(d,c)}let s=[];for(let[a,d]of l){let c=[...new Set(d.map(g=>g.column))];if(c.length!==d.length)throw new Error(`Batch update for ${e} contains the same column more than once`);let u=p.exec(`SELECT ${c.map(ee).join(", ")} FROM ${R(e)} WHERE rowid = ? LIMIT 2`,O([a]),{useBigInt:!0})[0];if((u?.values.length??0)!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);let f=d.map((g,E)=>{let T=q(u.values[0][E*2],u.values[0][E*2+1],`${e}.${g.column}`,{textEncoding:i}),x=T.value,A=Ut(g.value,x,g.operation??"set"),_=A.operation==="json_patch"?Zn(x,A.value):A.value;return!o&&A.operation==="json_patch"&&at(_,r),{update:g,priorValue:x,priorState:T,prepared:A,storedValue:_}}),m=a;for(let g of f){let E=h(g.update.column),T=g.prepared.operation==="json_patch",x=T?typeof g.prepared.value=="string"?g.prepared.value:JSON.stringify(g.prepared.value):g.storedValue,A=T?`json_patch(COALESCE(${E}, '{}'), ?)`:Y(g.storedValue);if(p.run(`UPDATE ${R(e)} SET ${E} = ${A} WHERE rowid = ?`,O([x,m])),p.exec("SELECT changes()")[0]?.values?.[0]?.[0]!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);m=ar(e,t,m,g.update.column,g.storedValue)}let y=p.exec(`SELECT ${c.map(ee).join(", ")} FROM ${R(e)} WHERE rowid = ? LIMIT 2`,O([m]),{useBigInt:!0})[0];if((y?.values.length??0)!==1)throw Ze(e);for(let[g,E]of f.entries())s.push({rowId:a,newRowId:m,columnName:E.update.column,priorValue:E.priorValue,newValue:E.prepared.value,priorState:E.priorState,postState:q(y.values[0][g*2],y.values[0][g*2+1],`${e}.${E.update.column}`,{textEncoding:i}),operation:E.prepared.operation})}return s}async function gl(e,t={}){if(!p)throw new Error("No database initialized");t=Yo(t,1e3);let{columns:n=null,offset:r,limit:o,orderBy:i=null,orderDir:l="ASC",filters:s=[],globalFilter:a="",globalFilterColumns:d=null}=t,c=n,u=i,f=null,m,y,g=!1;if(n?.[0]?.toLowerCase()==="rowid")if(y=await Bi(e),y?.kind==="primaryKey"){let $=y,k=n.slice(1),J=$.columns.map(ye=>ye.identifier).filter(ye=>!k.includes(ye));c=[...k,...J],m={identity:$,visibleColumns:k},kn({...t,columns:n})&&(u=null,f=$.columns.map(ye=>ye.identifier))}else y?.kind==="rowid"&&(g=(p.exec(Ge,[e,e])[0]?.values.length??0)>0);let E=y?.kind==="primaryKey"||g?y:void 0,T=Bn(t,E),x=T?Pn(e,t):void 0,A=T?Qo(e,t,E):void 0,_=g&&c?.[0]?.toLowerCase()==="rowid"&&c.length>Kt,b=_?c.slice(1):c,C;b&&b.length>0?C=b.map(h).join(", "):C="*";let N=[],I=[];if(s&&s.length>0)for(let $ of s){let k=we($.value);$.column&&k!==void 0&&(N.push(`${h($.column)} LIKE ? ESCAPE '\\'`),I.push(`%${ze(k)}%`))}let L=we(a);if(L!==void 0){let $=Oi(n,d);if($.length>0){let k=$.map(J=>`${h(J)} LIKE ? ESCAPE '\\'`);N.push(`(${k.join(" OR ")})`);for(let J=0;J<$.length;J++)I.push(`%${ze(L)}%`)}}let w=I,v=$=>{if(A)return Xo({selectListSql:$,escapedTable:R(e),whereClauses:N,filterParams:w,plan:A});let k=`SELECT ${$} FROM ${R(e)}`;N.length>0&&(k+=` WHERE ${N.join(" AND ")}`);let J=zo(T,A),ye=J?J.orderByColumns:f??(u?[u]:[]);if(ye.length>0){let es=J?J.orderDir:l==="DESC"?"DESC":"ASC";k+=` ORDER BY ${ye.map(ts=>`${h(ts)} ${es}`).join(", ")}`}return k+=` LIMIT ${parseInt(o,10)} OFFSET ${parseInt(r,10)}`,{sql:k,params:w}},{sql:ne,params:ie}=v(C);I=ie;let H=_?v(h("rowid")):void 0,se=p.prepare(ne,I),_e=se.getColumnNames(),be=_?["rowid",..._e]:_e;se.free();let zi=Number.isSafeInteger(t.maxInlineCellBytes)&&t.maxInlineCellBytes>0?t.maxInlineCellBytes:Nt,Qi=Number.isSafeInteger(t.maxPageResponseBytes)&&t.maxPageResponseBytes>0?t.maxPageResponseBytes:me,lr={limit:parseInt(o,10),maxInlineCellBytes:Math.min(Nt,zi),maxPageResponseBytes:Math.min(me,Qi)},Xi=m?m.identity.columns.map($=>{let k=be.indexOf($.identifier);if(k<0)throw new Error(`Primary-key column missing from table fetch: ${$.identifier}`);return k}):[],cr=T?T.keyColumns.map($=>be.indexOf($)).filter($=>$>=0):[],ur=[...new Set([...Xi,...cr])],Gi=_?ur.filter($=>$>0).map($=>$-1):ur,dr=_e.length*2+1<=Kt?_e.map(($,k)=>k):Gi,ae=_t(ne,_e.length,lr,dr),Yt=Ye(ae.sql,ae.primaryTransportColumnCount),Yi=p.exec(Yt.sql,I,{useBigInt:!0}),ft=yo(Yi[0]?.values??[],void 0,ae),$e=(H?p.exec(H.sql,H.params,{useBigInt:!0}):void 0)?.[0]?.values;if($e&&$e.length!==ft.length)throw new Error("Synthetic rowid companion row count does not match the value page");let ge=$e?$e.map(($,k)=>{if($.length!==1)throw new Error(`Synthetic rowid companion row ${k} is not one value`);return[$[0],...ft[k]]}):ft,fr=[],Jt=be[0]?.toLowerCase()==="rowid",Zt=Jt&&Qr(ge,0),mr=Yt.valueColumnCount===void 0&&Jt;if(!g&&(mr||Zt)&&ge.length>0&&(g=(p.exec(Ge,[e,e])[0]?.values.length??0)>0),g&&mr)for(let $ of Xr(e,be,ge.map(k=>k[0]))){let k=p.exec($.sql,$.params,{useBigInt:!0});fr.push({query:$,rows:k[0]?.values??[]})}let pr=Gr(ge,fr),en=ke(ft,Yt.valueColumnCount,_?void 0:pr,!_&&g&&Zt?0:void 0),gr=kt(en.rows,_e.length,en.exactIntegerTexts,lr.maxPageResponseBytes),yr=$e?Eo(ke($e,void 0,void 0,Zt?0:void 0).rows.map($=>$[0]),gr,pr):gr,tn=ho(en.rows,ae),Oe=dr.length>0?Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]):void 0,nn=_?ae.rawTextColumnIndices.map($=>$+1):ae.rawTextColumnIndices,Ji=Oe?So({sourceRows:ge,rawTextRows:tn,rawTextColumnIndices:nn,textEncoding:Oe,contained:yr}):yr,{rows:rn,oversizedCells:je,exactIntegerTexts:on}=Ji,le=y?.kind==="rowid"&&Jt&&!g?To({rows:rn,oversizedCells:je,exactIntegerTexts:on,rowOffset:parseInt(r,10)}):void 0,Ce=m&&Oe?Io({identity:m.identity,sourceColumns:be,visibleColumnCount:m.visibleColumns.length,identityRows:ge,rawTextBytes:tn,rawTextColumnIndices:nn,rawTextValidationUnavailable:ae.rawTextValidationUnavailable,textEncoding:Oe,rows:rn,oversizedCells:je,exactIntegerTexts:on,effectiveInlineCellBytes:ae.effectiveInlineCellBytes,rowOffset:parseInt(r,10)}):void 0,Zi=T&&Oe?wo({sourceRows:ge,sourceColumnIndices:cr,rawTextRows:tn,rawTextColumnIndices:nn,textEncoding:Oe,rawTextValidationUnavailable:ae.rawTextValidationUnavailable}):void 0,mt=T&&x!==void 0?Go({tag:x,key:T,projectionColumns:be,rows:ge,oversizedCells:je,excludedRowIndices:Zi}):void 0;return m&&Ce?{headers:["rowid",...m.visibleColumns],rows:Ce.rows,exactIntegerTexts:Ce.exactIntegerTexts,...Ce.oversizedCells?{oversizedCells:Ce.oversizedCells}:{},...Ce.readOnlyRowReasons?{readOnlyRowReasons:Ce.readOnlyRowReasons}:{},...mt?{keysetAnchors:mt}:{}}:{headers:be,rows:le?.rows??rn,exactIntegerTexts:le?le.exactIntegerTexts:on,...(le?le.oversizedCells:je)?{oversizedCells:le?le.oversizedCells:je}:{},...le?.readOnlyRowReasons?{readOnlyRowReasons:le.readOnlyRowReasons}:{},...mt?{keysetAnchors:mt}:{}}}async function yl(e,t={}){if(!p)throw new Error("No database initialized");let{columns:n=[],filters:r=[],globalFilter:o="",globalFilterColumns:i=null}=t,l=`SELECT COUNT(*) FROM ${R(e)}`,s=[],a=[];if(r&&r.length>0)for(let f of r){let m=we(f.value);f.column&&m!==void 0&&(s.push(`${h(f.column)} LIKE ? ESCAPE '\\'`),a.push(`%${ze(m)}%`))}let d=we(o);if(d!==void 0){let f=Oi(n,i);if(f.length>0){let m=f.map(y=>`${h(y)} LIKE ? ESCAPE '\\'`);s.push(`(${m.join(" OR ")})`);for(let y=0;y0&&(l+=` WHERE ${s.join(" AND ")}`);let c={storage:Ve,filtered:s.length>0,authorityConfirmedRowIdTable:!0,pagedFileSizeBytes:Ae,exactCountMaxFileBytes:_i};if(jn(c)){let f=!1;try{if(f=(p.exec(Ge,[e,e])[0]?.values.length??0)>0,jn({...c,authorityConfirmedRowIdTable:f})){let y=p.exec(pi(e)),g=Ei(y[0]?.values?.[0]);if(g!==void 0)return{count:g,isExact:!1}}}catch{}if(!f){let m=!1;try{m=(p.exec(mi,[e])[0]?.values.length??0)>0}catch{}if(m){try{let y=p.exec(gi(e),[Ue+1]),g=yi(y[0]?.values?.[0]?.[0],Ae);if(g)return g}catch{}return{count:zn(Ae),isExact:!1}}}}let u=p.exec(l,a);return u.length===0||u[0].values.length===0?{count:0,isExact:!0}:{count:u[0].values[0][0],isExact:!0}}async function El(){if(!p)throw new Error("No database initialized");let e=p.exec(` +]`)}function fl(e,t,n,r,o){let i=r?h(e):'"table_name"',l=t.map(h).join(", ");n.forEach((s,a)=>{let d=s.map(Fr).join(", ");a>0&&o.append(` +`),o.append(`INSERT INTO ${i} (${l}) VALUES (${d});`)})}async function Di(e){let t=p.exec(`SELECT "type", "wr" FROM pragma.pragma_table_list WHERE "schema" = 'main' AND "name" = ? LIMIT 1`,[e]);if((t[0]?.values.length??0)===0)return;let n=Cn(t[0].values[0][0],t[0].values[0][1]);if(!n)return;if(n==="rowid")return{kind:"rowid"};let r=Tn(await Mi(e));if(r.length===0)throw new Error(`WITHOUT ROWID table ${e} has no declared primary key`);return{kind:"primaryKey",columns:r}}async function te(e){let t=await Di(e);if(!t)throw new Error(`Table not found: ${e}`);if(t.kind==="rowid"&&(p.exec(Ge,[e,e])[0]?.values.length??0)!==1)throw new Error(`Table ${e} is read-only because a declared "rowid" column shadows SQLite's intrinsic row identity`);return t}function Zn(e){return new Error(`An UPDATE trigger changed or removed the primary-key identity in ${e}; the edit was rolled back because SQLite Explorer cannot safely identify the resulting row.`)}function sr(e,t,n,r){let i=p.exec(`SELECT ${In(t)} FROM ${R(e)} WHERE ${n.sql} LIMIT 2`,O(n.params),{useBigInt:!0})[0]?.values??[];if(i.length===0)throw r??new Error(`Updated row in ${e} no longer exists`);if(i.length!==1)throw new Error(`Primary-key identity for ${e} matched more than one row`);return An(t,i[0],Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]),`Cannot resolve updated identity in ${e}`)}function ar(e){let t=p.exec(jr,[e]);return Qr(t[0]?.values??[],e)}function ml(e,t,n=!0){let r=[...new Set(t)];if(r.length===0)throw new Error("UPDATE trigger probe requires at least one column");let o=r.map(l=>{let s=h(l);return`${s} = ${s}`}),i=n?"rowid = ?":"0";return`EXPLAIN UPDATE ${R(e)} SET ${o.join(", ")} WHERE ${i}`}function pl(e,t){return`EXPLAIN ${t.length===0?`INSERT INTO ${R(e)} DEFAULT VALUES`:`INSERT INTO ${R(e)} (${t.map(h).join(", ")}) VALUES (${t.map(()=>"NULL").join(", ")})`}`}function gl(e){return`EXPLAIN DELETE FROM ${R(e)} WHERE 0`}function dt(e,t,n=!0){let r=p.exec(eo,O([e]),{useBigInt:!0}),o=to(r[0]?.values??[],e),i=p.exec(ml(e,t,n),O(n?[0]:[]),{useBigInt:!0});no(e,o,i[0]?.values??[],n?"rowid":"primary-key")}function Fe(e,t,n=[]){let r=e==="INSERT"?pl(t,n):gl(t),o=p.exec(r,[],{useBigInt:!0});ro(e,t,o[0]?.values??[])}function lr(e,t,n,r,o){let i=t!==void 0&&r!==void 0&&ve(t,r),l=i?h(t):"rowid",s=i?o:n,d=p.exec(`SELECT CAST(rowid AS TEXT) FROM ${R(e)} WHERE ${l} = ? LIMIT 2`,O([s??null]),{useBigInt:!0})[0]?.values??[];if(d.length===0)throw Ze(e);if(d.length!==1)throw new Error(`Rowid identity for ${e} matched more than one row`);return M(d[0][0])}function er(e,t){let n=typeof t=="string"?t:JSON.stringify(t),r=p.exec("SELECT json_patch(COALESCE(?, '{}'), ?)",O([e,n]))[0]?.values?.[0]?.[0];if(typeof r!="string")throw new Error("SQLite returned an invalid json_patch result");return r}function yl(e,t,n,r,o){let i=Ke(),l=new Map;for(let a of n){let d=M(a.rowId),c=l.get(d)??[];c.push({...a,rowId:d}),l.set(d,c)}let s=[];for(let[a,d]of l){let c=[...new Set(d.map(g=>g.column))];if(c.length!==d.length)throw new Error(`Batch update for ${e} contains the same column more than once`);let u=p.exec(`SELECT ${c.map(ee).join(", ")} FROM ${R(e)} WHERE rowid = ? LIMIT 2`,O([a]),{useBigInt:!0})[0];if((u?.values.length??0)!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);let f=d.map((g,y)=>{let T=q(u.values[0][y*2],u.values[0][y*2+1],`${e}.${g.column}`,{textEncoding:i}),x=T.value,A=Vt(g.value,x,g.operation??"set"),_=A.operation==="json_patch"?er(x,A.value):A.value;return!o&&A.operation==="json_patch"&&at(_,r),{update:g,priorValue:x,priorState:T,prepared:A,storedValue:_}}),m=a;for(let g of f){let y=h(g.update.column),T=g.prepared.operation==="json_patch",x=T?typeof g.prepared.value=="string"?g.prepared.value:JSON.stringify(g.prepared.value):g.storedValue,A=T?`json_patch(COALESCE(${y}, '{}'), ?)`:Y(g.storedValue);if(p.run(`UPDATE ${R(e)} SET ${y} = ${A} WHERE rowid = ?`,O([x,m])),p.exec("SELECT changes()")[0]?.values?.[0]?.[0]!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);m=lr(e,t,m,g.update.column,g.storedValue)}let E=p.exec(`SELECT ${c.map(ee).join(", ")} FROM ${R(e)} WHERE rowid = ? LIMIT 2`,O([m]),{useBigInt:!0})[0];if((E?.values.length??0)!==1)throw Ze(e);for(let[g,y]of f.entries())s.push({rowId:a,newRowId:m,columnName:y.update.column,priorValue:y.priorValue,newValue:y.prepared.value,priorState:y.priorState,postState:q(E.values[0][g*2],E.values[0][g*2+1],`${e}.${y.update.column}`,{textEncoding:i}),operation:y.prepared.operation})}return s}async function El(e,t={}){if(!p)throw new Error("No database initialized");t=Jo(t,1e3);let{columns:n=null,offset:r,limit:o,orderBy:i=null,orderDir:l="ASC",filters:s=[],globalFilter:a="",globalFilterColumns:d=null}=t,c=n,u=i,f=null,m,E,g=!1;if(n?.[0]?.toLowerCase()==="rowid")if(E=await Di(e),E?.kind==="primaryKey"){let $=E,k=n.slice(1),J=$.columns.map(ye=>ye.identifier).filter(ye=>!k.includes(ye));c=[...k,...J],m={identity:$,visibleColumns:k},Pn({...t,columns:n})&&(u=null,f=$.columns.map(ye=>ye.identifier))}else E?.kind==="rowid"&&(g=(p.exec(Ge,[e,e])[0]?.values.length??0)>0);let y=E?.kind==="primaryKey"||g?E:void 0,T=Dn(t,y),x=T?Bn(e,t):void 0,A=T?Xo(e,t,y):void 0,_=g&&c?.[0]?.toLowerCase()==="rowid"&&c.length>jt,b=_?c.slice(1):c,C;b&&b.length>0?C=b.map(h).join(", "):C="*";let N=[],I=[];if(s&&s.length>0)for(let $ of s){let k=we($.value);$.column&&k!==void 0&&(N.push(`${h($.column)} LIKE ? ESCAPE '\\'`),I.push(`%${ze(k)}%`))}let L=we(a);if(L!==void 0){let $=Li(n,d);if($.length>0){let k=$.map(J=>`${h(J)} LIKE ? ESCAPE '\\'`);N.push(`(${k.join(" OR ")})`);for(let J=0;J<$.length;J++)I.push(`%${ze(L)}%`)}}let w=I,v=$=>{if(A)return Go({selectListSql:$,escapedTable:R(e),whereClauses:N,filterParams:w,plan:A});let k=`SELECT ${$} FROM ${R(e)}`;N.length>0&&(k+=` WHERE ${N.join(" AND ")}`);let J=Qo(T,A),ye=J?J.orderByColumns:f??(u?[u]:[]);if(ye.length>0){let ts=J?J.orderDir:l==="DESC"?"DESC":"ASC";k+=` ORDER BY ${ye.map(ns=>`${h(ns)} ${ts}`).join(", ")}`}return k+=` LIMIT ${parseInt(o,10)} OFFSET ${parseInt(r,10)}`,{sql:k,params:w}},{sql:ne,params:ie}=v(C);I=ie;let H=_?v(h("rowid")):void 0,se=p.prepare(ne,I),_e=se.getColumnNames(),be=_?["rowid",..._e]:_e;se.free();let Qi=Number.isSafeInteger(t.maxInlineCellBytes)&&t.maxInlineCellBytes>0?t.maxInlineCellBytes:Nt,Xi=Number.isSafeInteger(t.maxPageResponseBytes)&&t.maxPageResponseBytes>0?t.maxPageResponseBytes:me,cr={limit:parseInt(o,10),maxInlineCellBytes:Math.min(Nt,Qi),maxPageResponseBytes:Math.min(me,Xi)},Gi=m?m.identity.columns.map($=>{let k=be.indexOf($.identifier);if(k<0)throw new Error(`Primary-key column missing from table fetch: ${$.identifier}`);return k}):[],ur=T?T.keyColumns.map($=>be.indexOf($)).filter($=>$>=0):[],dr=[...new Set([...Gi,...ur])],Yi=_?dr.filter($=>$>0).map($=>$-1):dr,fr=_e.length*2+1<=jt?_e.map(($,k)=>k):Yi,ae=_t(ne,_e.length,cr,fr),Jt=Ye(ae.sql,ae.primaryTransportColumnCount),Ji=p.exec(Jt.sql,I,{useBigInt:!0}),ft=Eo(Ji[0]?.values??[],void 0,ae),$e=(H?p.exec(H.sql,H.params,{useBigInt:!0}):void 0)?.[0]?.values;if($e&&$e.length!==ft.length)throw new Error("Synthetic rowid companion row count does not match the value page");let ge=$e?$e.map(($,k)=>{if($.length!==1)throw new Error(`Synthetic rowid companion row ${k} is not one value`);return[$[0],...ft[k]]}):ft,mr=[],Zt=be[0]?.toLowerCase()==="rowid",en=Zt&&Xr(ge,0),pr=Jt.valueColumnCount===void 0&&Zt;if(!g&&(pr||en)&&ge.length>0&&(g=(p.exec(Ge,[e,e])[0]?.values.length??0)>0),g&&pr)for(let $ of Gr(e,be,ge.map(k=>k[0]))){let k=p.exec($.sql,$.params,{useBigInt:!0});mr.push({query:$,rows:k[0]?.values??[]})}let gr=Yr(ge,mr),tn=ke(ft,Jt.valueColumnCount,_?void 0:gr,!_&&g&&en?0:void 0),yr=Pt(tn.rows,_e.length,tn.exactIntegerTexts,cr.maxPageResponseBytes),Er=$e?ho(ke($e,void 0,void 0,en?0:void 0).rows.map($=>$[0]),yr,gr):yr,nn=wo(tn.rows,ae),Oe=fr.length>0?Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]):void 0,rn=_?ae.rawTextColumnIndices.map($=>$+1):ae.rawTextColumnIndices,Zi=Oe?bo({sourceRows:ge,rawTextRows:nn,rawTextColumnIndices:rn,textEncoding:Oe,contained:Er}):Er,{rows:on,oversizedCells:je,exactIntegerTexts:sn}=Zi,le=E?.kind==="rowid"&&Zt&&!g?Ro({rows:on,oversizedCells:je,exactIntegerTexts:sn,rowOffset:parseInt(r,10)}):void 0,Ce=m&&Oe?Ao({identity:m.identity,sourceColumns:be,visibleColumnCount:m.visibleColumns.length,identityRows:ge,rawTextBytes:nn,rawTextColumnIndices:rn,rawTextValidationUnavailable:ae.rawTextValidationUnavailable,textEncoding:Oe,rows:on,oversizedCells:je,exactIntegerTexts:sn,effectiveInlineCellBytes:ae.effectiveInlineCellBytes,rowOffset:parseInt(r,10)}):void 0,es=T&&Oe?So({sourceRows:ge,sourceColumnIndices:ur,rawTextRows:nn,rawTextColumnIndices:rn,textEncoding:Oe,rawTextValidationUnavailable:ae.rawTextValidationUnavailable}):void 0,mt=T&&x!==void 0?Yo({tag:x,key:T,projectionColumns:be,rows:ge,oversizedCells:je,excludedRowIndices:es}):void 0;return m&&Ce?{headers:["rowid",...m.visibleColumns],rows:Ce.rows,exactIntegerTexts:Ce.exactIntegerTexts,...Ce.oversizedCells?{oversizedCells:Ce.oversizedCells}:{},...Ce.readOnlyRowReasons?{readOnlyRowReasons:Ce.readOnlyRowReasons}:{},...mt?{keysetAnchors:mt}:{}}:{headers:be,rows:le?.rows??on,exactIntegerTexts:le?le.exactIntegerTexts:sn,...(le?le.oversizedCells:je)?{oversizedCells:le?le.oversizedCells:je}:{},...le?.readOnlyRowReasons?{readOnlyRowReasons:le.readOnlyRowReasons}:{},...mt?{keysetAnchors:mt}:{}}}async function hl(e,t={}){if(!p)throw new Error("No database initialized");let{columns:n=[],filters:r=[],globalFilter:o="",globalFilterColumns:i=null}=t,l=`SELECT COUNT(*) FROM ${R(e)}`,s=[],a=[];if(r&&r.length>0)for(let f of r){let m=we(f.value);f.column&&m!==void 0&&(s.push(`${h(f.column)} LIKE ? ESCAPE '\\'`),a.push(`%${ze(m)}%`))}let d=we(o);if(d!==void 0){let f=Li(n,i);if(f.length>0){let m=f.map(E=>`${h(E)} LIKE ? ESCAPE '\\'`);s.push(`(${m.join(" OR ")})`);for(let E=0;E0&&(l+=` WHERE ${s.join(" AND ")}`);let c={storage:Ve,filtered:s.length>0,authorityConfirmedRowIdTable:!0,pagedFileSizeBytes:Ae,exactCountMaxFileBytes:$i};if(zn(c)){let f=!1;try{if(f=(p.exec(Ge,[e,e])[0]?.values.length??0)>0,zn({...c,authorityConfirmedRowIdTable:f})){let E=p.exec(gi(e)),g=hi(E[0]?.values?.[0]);if(g!==void 0)return{count:g,isExact:!1}}}catch{}if(!f){let m=!1;try{m=(p.exec(pi,[e])[0]?.values.length??0)>0}catch{}if(m){try{let E=p.exec(yi(e),[Ue+1]),g=Ei(E[0]?.values?.[0]?.[0],Ae);if(g)return g}catch{}return{count:Qn(Ae),isExact:!1}}}}let u=p.exec(l,a);return u.length===0||u[0].values.length===0?{count:0,isExact:!0}:{count:u[0].values[0][0],isExact:!0}}async function wl(){if(!p)throw new Error("No database initialized");let e=p.exec(` SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name - `),t=p.exec(Jr),n=ao(t[0]?.values||[]),r=(e[0]?.values||[]).map(a=>{let d=a[0],c=n.get(d);if(!c)throw new Error(`Table not found: ${d}`);return{identifier:d,identity:c}}),i=(p.exec(` + `),t=p.exec(Zr),n=lo(t[0]?.values||[]),r=(e[0]?.values||[]).map(a=>{let d=a[0],c=n.get(d);if(!c)throw new Error(`Table not found: ${d}`);return{identifier:d,identity:c}}),i=(p.exec(` SELECT name FROM sqlite_master WHERE type = 'view' ORDER BY name @@ -58,6 +58,6 @@ ${t}`);if(!n.getSQL().trimEnd().endsWith(t))throw n.free(),new Error("Exactly on SELECT name, tbl_name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_%' ORDER BY name - `)[0]?.values||[]).map(a=>({identifier:a[0],parentTable:a[1]}));return{tables:r,views:i,indexes:s}}async function Di(e){if(!p)throw new Error("No database initialized");let t=p.exec(jr,[e]);return t.length===0?[]:t[0].values.filter(n=>Number(n[6]??0)!==1).map(n=>({ordinal:n[0],identifier:n[1],declaredType:n[2],isRequired:n[3],defaultExpression:n[4],primaryKeyPosition:n[5],isGenerated:Number(n[6]??0)===2||Number(n[6]??0)===3,isRowidAlias:Number(n[7]??0)===1}))}function er(e){return(p.exec("SELECT name FROM pragma.pragma_table_xinfo(?) WHERE hidden NOT IN (2, 3) ORDER BY cid",[e])[0]?.values??[]).map(n=>{if(typeof n[0]!="string")throw new Error(`SQLite returned invalid column metadata for ${e}`);return n[0]})}function hl(e,t,n,r){let o=Ke(),i=U(n,t),l=r.map(ee),a=p.exec(`SELECT ${l.join(", ")||"1"} FROM ${R(e)} WHERE ${i.sql} LIMIT 2`,O(i.params),{useBigInt:!0})[0]?.values??[];if(a.length!==1)throw new Se(e);let d=r.map((c,u)=>q(a[0][u*2],a[0][u*2+1],`${e}.${c}`,{textEncoding:o}));return{rowId:n,row:Object.fromEntries(r.map((c,u)=>[c,d[u].rawTextBytes??d[u].value])),storageClasses:r.map((c,u)=>({column:c,storageClass:d[u].storageClass}))}}function wl(e,t,n,r,o){if(o===void 0)return;let i=U(n,t),l=Fo(r,t.kind==="rowid"),s=Ho(e,l,i),a=p.exec(s.sql,O(s.params),{useBigInt:!0})[0]?.values?.[0],d=Ko(a);jo({table:e,insertableColumns:r,includeSyntheticRowId:t.kind==="rowid",rowIds:[n],rowCount:d.rowCount,valueBytes:d.valueBytes,maxSnapshotBytes:o,operation:"Insert"})}function Ri(e,t,n,r){let o=er(e),i=U(n,t);return tr(e,[n],o,[i]),wl(e,t,n,o,r),hl(e,t,n,o)}async function Sl(){if(!p)throw new Error("No database initialized");let e={},t=["foreign_keys","journal_mode","synchronous","cache_size","locking_mode","temp_store","encoding","auto_vacuum"];for(let n of t)try{let r=p.exec(`PRAGMA ${n}`);r.length>0&&r[0].values.length>0&&(e[n]=r[0].values[0][0])}catch{}return e}async function bl(e,t){if(!p)throw new Error("No database initialized");if(z("Pragma updates"),!["foreign_keys","journal_mode","synchronous","cache_size","locking_mode","temp_store","auto_vacuum"].includes(e))throw new Error(`Invalid or disallowed PRAGMA: ${e}`);let r;if(typeof t=="string"){if(!/^[a-zA-Z0-9_-]+$/.test(t))throw new Error("Invalid PRAGMA string value: contains disallowed characters");r=`PRAGMA ${e} = '${t}'`}else if(typeof t=="number"){if(!Number.isFinite(t))throw new Error("Invalid PRAGMA numeric value: must be finite");r=`PRAGMA ${e} = ${t}`}else if(typeof t=="boolean")r=`PRAGMA ${e} = ${t?"ON":"OFF"}`;else throw new Error(`Invalid PRAGMA value type: ${typeof t}`);S(r)}async function Cl(e,t,n,r,o,i,l){let s=l===nr,a=!s&&i!==void 0,d=s?0:lt([r],i);if(Re(t),!p)throw new Error("No database initialized");if(z("Cell updates"),X(t))return(await ji(e,[{rowId:t,column:n,value:r,operation:"set"}],void 0,i,l))[0]?.newRowId??t;let c=M(t);if((await te(e)).kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let f=P("sp_update_rowid_cell");S(`SAVEPOINT ${f}`);try{let m=sr(e);dt(e,[n]);let y=h(n);if(p.run(`UPDATE ${R(e)} SET ${y} = ${Y(r)} WHERE rowid = ?`+(a?` AND NOT (typeof(${y}) IN ('text', 'blob') AND length(CAST(${y} AS BLOB)) > ?)`:""),O(a?[r,c,d]:[r,c])),p.exec("SELECT changes()")[0]?.values?.[0]?.[0]!==1){if(a){let T=await zt({table:e,rowId:c,column:n});if((T.storageClass==="text"||T.storageClass==="blob")&&T.byteLength>d)throw new Me(e,n,T.storageClass,T.byteLength,d)}throw new Error(`Cannot update ${e}.${n}: row ${t} no longer exists`)}let E=ar(e,m,c,n,r);return S(`RELEASE ${f}`),E}catch(m){throw B(f,"updateCell"),m}}async function Tl(e,t,n,r,o,i){let l=lt([r],i);if(oi(o,l),Re(t),!p)throw new Error("No database initialized");z("Oversized cell replacement");let s=await te(e),a=U(t,s),d=h(n),c=()=>{if(p.run(`UPDATE ${R(e)} SET ${d} = ${Y(r)} WHERE ${a.sql} AND typeof(${d}) = ? AND length(CAST(${d} AS BLOB)) = ?`,O([r,...a.params,o.storageClass,o.byteLength])),p.exec("SELECT changes()")[0]?.values?.[0]?.[0]!==1)throw new Error(ni);if(s.kind==="rowid")return ar(e,sr(e),M(t),n,r);let m=s.columns.findIndex(g=>g.identifier===n),y=Sn(t,s,m>=0?[{column:n,value:r}]:[]);return ir(e,s,U(y,s),Jn(e))},u=P("sp_replace_oversized_cell");S(`SAVEPOINT ${u}`);try{dt(e,[n],s.kind==="rowid");let f=c();return S(`RELEASE ${u}`),f}catch(f){throw B(u,"replaceOversizedCell"),f}}async function Mi(e,t,n,r,o,i){if(!p)throw new Error("No database initialized");z("Row insertion"),r!==nr&<(Object.values(t),n);let l=Object.keys(t),s=Object.values(t),a=await te(e),d;if(l.length===0)d=`INSERT INTO ${R(e)} DEFAULT VALUES`;else{let u=l.map(h).join(", "),f=s.map(Y).join(", ");d=`INSERT INTO ${R(e)} (${u}) VALUES (${f})`}if(a.kind==="primaryKey"){let u=P("sp_insert_pk_row");S(`SAVEPOINT ${u}`);try{Fe("INSERT",e,l);let f=p.prepare(`${d} RETURNING `+xn(a),O(s)),m;try{if(!f.step())throw new Error(`Insert into ${e} did not return a primary-key identity`);if(m=f.get(null,{useBigInt:!0}),!m||f.step())throw new Error(`Insert into ${e} did not return exactly one primary-key identity`)}finally{f.free()}let y=In(a,m,Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]),`Cannot insert into ${e}`),g=ir(e,a,U(y,a)),E=o?Ri(e,a,g,i):g;return S(`RELEASE ${u}`),E}catch(f){throw B(u,"insertPrimaryKeyRow"),f}}let c=P("sp_insert_rowid_row");S(`SAVEPOINT ${c}`);try{Fe("INSERT",e,l),p.run(d,O(s));let u=p.exec("SELECT changes(), CAST(last_insert_rowid() AS TEXT)")[0]?.values?.[0];if(!u||Number(u[0])!==1)throw new Error(`Insert into ${e} did not create exactly one row`);let f=M(u[1]),m=U(f,a);if((p.exec(`SELECT 1 FROM ${R(e)} WHERE ${m.sql} LIMIT 2`,O(m.params))[0]?.values.length??0)!==1)throw new Error(`Insert into ${e} did not leave one addressable row; the insert was rolled back`);let g=o?Ri(e,a,f,i):f;return S(`RELEASE ${c}`),g}catch(u){throw B(c,"insertRowIdRow"),u}}async function Rl(e,t,n,r){return Mi(e,t,n,r,!1)}async function xl(e,t,n,r){return Mi(e,t,n,void 0,!0,r)}var xi=64;function Xn(e,t){let n=typeof e=="bigint"?Number(e):e;if(!Number.isSafeInteger(n)||n<0)throw new Error(`Demo delete snapshot ${t} exceeds the web transport safety bound`);return n}function Il(e){let t=h(e);return`CASE typeof(${t}) WHEN 'text' THEN 6 * octet_length(${t}) WHEN 'blob' THEN 4 * ((octet_length(${t}) + 2) / 3) + 40 WHEN 'integer' THEN 8 WHEN 'real' THEN 8 ELSE 4 END`}function Al(e){let t=h(e);return`COALESCE(MAX(CASE WHEN typeof(${t}) = 'blob' THEN octet_length(${t}) ELSE 0 END), 0)`}function tr(e,t,n,r){let o=1024;for(let s of t)o+=64+6*String(s).length;let i=128+n.reduce((s,a)=>s+48+6*a.length,0),l=0;for(let s of r)for(let a=0;a0?", ":""}`+d.map(Al).join(", ")+` FROM ${R(e)} WHERE ${s.sql}`,O(s.params),{useBigInt:!0})[0]?.values?.[0];if(!c)throw new Error("Demo delete snapshot preflight returned no metadata");let u=Xn(c[0],"row count");a===0&&(l+=u,o+=u*i),o+=Xn(c[1],"encoded size");for(let f of c.slice(2))if(Xn(f,"BLOB size")>De)throw new Error(`Demo delete snapshot exceeds the ${De}-byte web transport binary limit; the row was not deleted`);if(!Number.isSafeInteger(o))throw new Error("Demo delete snapshot exceeds the web transport safety bound")}if(l!==t.length)throw new Error(`Cannot delete from ${e}: one or more row identities no longer exist`);if(o>Vn)throw new Error(`Demo delete snapshot exceeds the ${Vn}-byte web transport response limit; no rows were deleted`)}async function Nl(e,t){if(t.forEach(Re),!p)throw new Error("No database initialized");if(z("Row deletion"),t.length===0)return[];let n=await te(e),r=Ke();if(t.some(X)){if(!t.every(X))throw new Error("Cannot mix rowid and primary-key row identities");if(n.kind!=="primaryKey")throw new Error(`Primary-key identity cannot target rowid table ${e}`);let l=tt(t,n),s=P("sp_delete_pk_rows");S(`SAVEPOINT ${s}`);try{Fe("DELETE",e);let a=er(e);tr(e,t,a,l);let d=[];for(let c of l){let f=p.exec(`SELECT ${a.map(ee).join(", ")||"1"} FROM ${R(e)} WHERE ${c.sql}`,O(c.params),{useBigInt:!0})[0]?.values??[],m=n.columns.map(y=>{let g=a.indexOf(y.identifier);if(g<0)throw new Error(`Primary-key column missing from ${e}: ${y.identifier}`);return g});d.push(...f.map(y=>{let g=a.map((E,T)=>q(y[T*2],y[T*2+1],`${e}.${E}`,{textEncoding:r}));return{rowId:Pe(n.columns,m.map(E=>g[E].value)),row:Object.fromEntries(a.map((E,T)=>[E,g[T].rawTextBytes??g[T].value])),storageClasses:a.map((E,T)=>({column:E,storageClass:g[T].storageClass}))}}))}if(d.length!==t.length)throw new Error(`Cannot delete from ${e}: one or more row identities no longer exist`);for(let c of l)p.run(`DELETE FROM ${R(e)} WHERE ${c.sql}`,O(c.params));return S(`RELEASE ${s}`),d}catch(a){throw B(s,"deletePrimaryKeyRows"),a}}if(n.kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let o=tt(t,n),i=P("sp_delete_rowid_rows");S(`SAVEPOINT ${i}`);try{Fe("DELETE",e);let l=er(e);tr(e,t,l,o);let s=[];for(let a of o){let d=p.exec(`SELECT CAST(rowid AS TEXT)${l.length>0?", ":""}${l.map(ee).join(", ")} FROM ${R(e)} WHERE ${a.sql}`,O(a.params),{useBigInt:!0})[0];s.push(...(d?.values??[]).map(c=>{let u=M(c[0]),f=l.map((m,y)=>q(c[y*2+1],c[y*2+2],`${e}.${m}`,{textEncoding:r}));return{rowId:u,row:Object.fromEntries(l.map((m,y)=>[m,f[y].rawTextBytes??f[y].value])),storageClasses:l.map((m,y)=>({column:m,storageClass:f[y].storageClass}))}}))}if(s.length!==t.length)throw new Error(`Cannot delete from ${e}: one or more row identities no longer exist`);for(let a of o)p.run(`DELETE FROM ${R(e)} WHERE ${a.sql}`,O(a.params));return S(`RELEASE ${i}`),s}catch(l){throw B(i,"deleteRowidRows"),l}}async function Ui(e,t){if(!p)throw new Error("No database initialized");if(!Array.isArray(t))throw new Error("Column names must be an array");K(e,"Table name"),t.forEach(u=>K(u,"Column name"));let r=(p.exec("SELECT name, sql FROM main.sqlite_schema WHERE type = 'index' AND tbl_name = ? AND sql IS NOT NULL ORDER BY name",[e])[0]?.values??[]).map(u=>({identifier:u[0],sql:u[1]}));if(r.length===0||t.length===0)return[];let i=(p.exec(`PRAGMA main.table_xinfo(${h(e)})`)[0]?.values??[]).map(u=>u[1]),l=Pr(i,t);if(l.length===0)return[];let s=crypto.randomUUID().replace(/-/g,""),a=`__sqlite_explorer_index_probe_${s}`,d=`__sqlite_explorer_index_candidate_${s}`,c=P("sp_index_dependencies");S(`SAVEPOINT ${c}`);try{S(kr(a,i));let u=P("sp_index_baseline");S(`SAVEPOINT ${u}`);try{for(let m of l)S(`ALTER TABLE temp.${h(a)} DROP COLUMN ${h(m)}`);S(`ROLLBACK TO ${u}`),S(`RELEASE ${u}`)}catch(m){throw B(u,"findDependentIndexBaseline"),new Error("Cannot establish the index dependency probe baseline",{cause:m})}let f=[];for(let m of r){let y=P("sp_index_candidate");S(`SAVEPOINT ${y}`);try{S(Br(a,d,m.sql));let g=!1;for(let E of l)try{S(`ALTER TABLE temp.${h(a)} DROP COLUMN ${h(E)}`)}catch{g=!0;break}S(`ROLLBACK TO ${y}`),S(`RELEASE ${y}`),g&&f.push(m)}catch(g){throw B(y,"findDependentIndex"),new Error(`Cannot inspect dependency for index ${h(m.identifier)}`,{cause:g})}}return S(`ROLLBACK TO ${c}`),S(`RELEASE ${c}`),f}catch(u){throw B(c,"findDependentIndexes"),u}}function _l(e){if(e!==void 0){if(!Array.isArray(e))throw new Error("Dependent-index confirmation must be an array");return e.map(t=>{if(!t||typeof t!="object"||Array.isArray(t)||typeof t.identifier!="string"||typeof t.sql!="string")throw new Error("Dependent-index confirmation contains an invalid definition");return K(t.identifier,"Index name"),{identifier:t.identifier,sql:t.sql}})}}function $l(e,t,n){if(t.length===0&&(n?.length??0)===0)return;if(!n)throw new Error("Column deletion requires confirmation for dependent indexes: "+t.map(i=>i.identifier).join(", "));let r=new Map(n.map(i=>[i.identifier,i.sql]));if(!(r.size===n.length&&n.length===t.length&&t.every(i=>r.get(i.identifier)===i.sql)))throw new Error(`Cannot delete columns from ${e}: dependent indexes changed while the confirmation was open`)}async function Ol(e,t,n){if(!p)throw new Error("No database initialized");if(z("Column deletion"),t.length===0)return;let r=P("sp_delete_columns");S(`SAVEPOINT ${r}`);try{let o=_l(n),i=await Ui(e,t);$l(e,i,o),await lo(e,t,i.map(l=>l.identifier),l=>S(l)),S(`RELEASE ${r}`)}catch(o){throw B(r,"deleteColumns"),o}}async function Ll(e,t,n){if(!p)throw new Error("No database initialized");z("Table creation");let r=Dr(e,t,n),o=P("sp_create_table");S(`SAVEPOINT ${o}`);try{let i=await W();S(r),de(i,await W()),S(`RELEASE ${o}`)}catch(i){throw B(o,"createTable"),i}}async function Vi(e,t=!1){if(!p)throw new Error("No database initialized");let r=p.exec("SELECT sql FROM sqlite_schema WHERE type = 'view' AND name = ?",[e])[0]?.values?.[0]?.[0];if(typeof r!="string")return null;let o=pt.map(c=>p.exec(c.sql,c.params(e))[0]?.values||[]),{triggers:i,ambiguousTemporaryTriggerNames:l,unqualifiedTemporaryTriggers:s}=Tr(e,o);if(s.length>0){let u=(p.exec("SELECT name FROM pragma.pragma_table_xinfo(?, 'main') ORDER BY cid",[e])[0]?.values??[]).map(f=>{if(typeof f[0]!="string")throw new Error(`SQLite returned invalid view column metadata for ${e}`);return f[0]});for(let f of s){if(i.some(m=>!m.temporary&&ve(m.identifier,f.identifier))){l.push(f.identifier);continue}try{let m=yt(f.sql,"main",e,u);if(m===void 0){l.push(f.identifier);continue}let y=p.exec(m);Cr(y[0]?.values??[],f.identifier)&&i.push({...f,sql:un(f.sql,f.identifier)})}catch{l.push(f.identifier)}}}let a,d;try{a=xr(r),d=cn(r)}catch(c){if(!t)throw c;a=""}return{identifier:e,sql:r,selectSql:a,columnListSql:d,triggers:i,...l.length>0?{ambiguousTemporaryTriggerNames:l}:{}}}async function qi(e,t=!1){let n=await Vi(e,t);if(!n)throw new Error(`View not found: ${e}`);return n}async function Qt(e){return qi(e,!1)}function W(){return Or({queryRows:async(e,t)=>p.exec(e,O(t))[0]?.values??[],compileStatements:async e=>e.map(t=>{try{He(t);return}catch(n){return Ne(n)}})})}function Wi(e,t){let r=p.exec("SELECT sql FROM sqlite_schema WHERE type = 'view' AND name = ?",[e])[0]?.values?.[0];Ar(e,r!==void 0,t);let o=r?.[0];return{storedSql:o,columnListSql:typeof o=="string"?cn(o):void 0}}function z(e){if(j)throw new Error(`${e} is unavailable because the database is read-only`)}async function vl(e,t,n="edit"){if(K(e,"View name"),!p)throw new Error("No database initialized");if(j)throw new Error("View validation is unavailable because the database is read-only");let r=Ee(t),{storedSql:o,columnListSql:i}=Wi(e,n),l=P("sp_validate_view");S(`SAVEPOINT ${l}`);try{let s=await W();typeof o=="string"&&S(`DROP VIEW ${Q(e)}`),S(Qe(e,r,i)),He(`EXPLAIN SELECT * FROM ${Q(e)}`),de(s,await W()),S(`ROLLBACK TO ${l}`),S(`RELEASE ${l}`)}catch(s){throw B(l,"validateViewDefinition"),s}}async function kl(e,t,n=50,r="edit",o){if(K(e,"View name"),!p)throw new Error("No database initialized");let i=Ee(t),l=Math.max(1,Math.min(100,Math.trunc(n)||50)),{storedSql:s,columnListSql:a}=Wi(e,r);if(j){let c=h(e);return Qn(a?`WITH ${c} ${a} AS (${i} + `)[0]?.values||[]).map(a=>({identifier:a[0],parentTable:a[1]}));return{tables:r,views:i,indexes:s}}async function Mi(e){if(!p)throw new Error("No database initialized");let t=p.exec(zr,[e]);return t.length===0?[]:t[0].values.filter(n=>Number(n[6]??0)!==1).map(n=>({ordinal:n[0],identifier:n[1],declaredType:n[2],isRequired:n[3],defaultExpression:n[4],primaryKeyPosition:n[5],isGenerated:Number(n[6]??0)===2||Number(n[6]??0)===3,isRowidAlias:Number(n[7]??0)===1}))}function tr(e){return(p.exec("SELECT name FROM pragma.pragma_table_xinfo(?) WHERE hidden NOT IN (2, 3) ORDER BY cid",[e])[0]?.values??[]).map(n=>{if(typeof n[0]!="string")throw new Error(`SQLite returned invalid column metadata for ${e}`);return n[0]})}function Sl(e,t,n,r){let o=Ke(),i=U(n,t),l=r.map(ee),a=p.exec(`SELECT ${l.join(", ")||"1"} FROM ${R(e)} WHERE ${i.sql} LIMIT 2`,O(i.params),{useBigInt:!0})[0]?.values??[];if(a.length!==1)throw new Se(e);let d=r.map((c,u)=>q(a[0][u*2],a[0][u*2+1],`${e}.${c}`,{textEncoding:o}));return{rowId:n,row:Object.fromEntries(r.map((c,u)=>[c,d[u].rawTextBytes??d[u].value])),storageClasses:r.map((c,u)=>({column:c,storageClass:d[u].storageClass}))}}function bl(e,t,n,r,o){if(o===void 0)return;let i=U(n,t),l=Ho(r,t.kind==="rowid"),s=Ko(e,l,i),a=p.exec(s.sql,O(s.params),{useBigInt:!0})[0]?.values?.[0],d=jo(a);zo({table:e,insertableColumns:r,includeSyntheticRowId:t.kind==="rowid",rowIds:[n],rowCount:d.rowCount,valueBytes:d.valueBytes,maxSnapshotBytes:o,operation:"Insert"})}function xi(e,t,n,r){let o=tr(e),i=U(n,t);return nr(e,[n],o,[i]),bl(e,t,n,o,r),Sl(e,t,n,o)}async function Cl(){if(!p)throw new Error("No database initialized");let e={},t=["foreign_keys","journal_mode","synchronous","cache_size","locking_mode","temp_store","encoding","auto_vacuum"];for(let n of t)try{let r=p.exec(`PRAGMA ${n}`);r.length>0&&r[0].values.length>0&&(e[n]=r[0].values[0][0])}catch{}return e}async function Tl(e,t){if(!p)throw new Error("No database initialized");if(z("Pragma updates"),!["foreign_keys","journal_mode","synchronous","cache_size","locking_mode","temp_store","auto_vacuum"].includes(e))throw new Error(`Invalid or disallowed PRAGMA: ${e}`);let r;if(typeof t=="string"){if(!/^[a-zA-Z0-9_-]+$/.test(t))throw new Error("Invalid PRAGMA string value: contains disallowed characters");r=`PRAGMA ${e} = '${t}'`}else if(typeof t=="number"){if(!Number.isFinite(t))throw new Error("Invalid PRAGMA numeric value: must be finite");r=`PRAGMA ${e} = ${t}`}else if(typeof t=="boolean")r=`PRAGMA ${e} = ${t?"ON":"OFF"}`;else throw new Error(`Invalid PRAGMA value type: ${typeof t}`);S(r)}async function Rl(e,t,n,r,o,i,l){let s=l===rr,a=!s&&i!==void 0,d=s?0:lt([r],i);if(Re(t),!p)throw new Error("No database initialized");if(z("Cell updates"),X(t))return(await zi(e,[{rowId:t,column:n,value:r,operation:"set"}],void 0,i,l))[0]?.newRowId??t;let c=M(t);if((await te(e)).kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let f=P("sp_update_rowid_cell");S(`SAVEPOINT ${f}`);try{let m=ar(e);dt(e,[n]);let E=h(n);if(p.run(`UPDATE ${R(e)} SET ${E} = ${Y(r)} WHERE rowid = ?`+(a?` AND NOT (typeof(${E}) IN ('text', 'blob') AND length(CAST(${E} AS BLOB)) > ?)`:""),O(a?[r,c,d]:[r,c])),p.exec("SELECT changes()")[0]?.values?.[0]?.[0]!==1){if(a){let T=await Qt({table:e,rowId:c,column:n});if((T.storageClass==="text"||T.storageClass==="blob")&&T.byteLength>d)throw new Me(e,n,T.storageClass,T.byteLength,d)}throw new Error(`Cannot update ${e}.${n}: row ${t} no longer exists`)}let y=lr(e,m,c,n,r);return S(`RELEASE ${f}`),y}catch(m){throw B(f,"updateCell"),m}}async function xl(e,t,n,r,o,i){let l=lt([r],i);if(ii(o,l),Re(t),!p)throw new Error("No database initialized");z("Oversized cell replacement");let s=await te(e),a=U(t,s),d=h(n),c=()=>{if(p.run(`UPDATE ${R(e)} SET ${d} = ${Y(r)} WHERE ${a.sql} AND typeof(${d}) = ? AND length(CAST(${d} AS BLOB)) = ?`,O([r,...a.params,o.storageClass,o.byteLength])),p.exec("SELECT changes()")[0]?.values?.[0]?.[0]!==1)throw new Error(ri);if(s.kind==="rowid")return lr(e,ar(e),M(t),n,r);let m=s.columns.findIndex(g=>g.identifier===n),E=bn(t,s,m>=0?[{column:n,value:r}]:[]);return sr(e,s,U(E,s),Zn(e))},u=P("sp_replace_oversized_cell");S(`SAVEPOINT ${u}`);try{dt(e,[n],s.kind==="rowid");let f=c();return S(`RELEASE ${u}`),f}catch(f){throw B(u,"replaceOversizedCell"),f}}async function Ui(e,t,n,r,o,i){if(!p)throw new Error("No database initialized");z("Row insertion"),r!==rr&<(Object.values(t),n);let l=Object.keys(t),s=Object.values(t),a=await te(e),d;if(l.length===0)d=`INSERT INTO ${R(e)} DEFAULT VALUES`;else{let u=l.map(h).join(", "),f=s.map(Y).join(", ");d=`INSERT INTO ${R(e)} (${u}) VALUES (${f})`}if(a.kind==="primaryKey"){let u=P("sp_insert_pk_row");S(`SAVEPOINT ${u}`);try{Fe("INSERT",e,l);let f=p.prepare(`${d} RETURNING `+In(a),O(s)),m;try{if(!f.step())throw new Error(`Insert into ${e} did not return a primary-key identity`);if(m=f.get(null,{useBigInt:!0}),!m||f.step())throw new Error(`Insert into ${e} did not return exactly one primary-key identity`)}finally{f.free()}let E=An(a,m,Be(p.exec("PRAGMA encoding")[0]?.values?.[0]?.[0]),`Cannot insert into ${e}`),g=sr(e,a,U(E,a)),y=o?xi(e,a,g,i):g;return S(`RELEASE ${u}`),y}catch(f){throw B(u,"insertPrimaryKeyRow"),f}}let c=P("sp_insert_rowid_row");S(`SAVEPOINT ${c}`);try{Fe("INSERT",e,l),p.run(d,O(s));let u=p.exec("SELECT changes(), CAST(last_insert_rowid() AS TEXT)")[0]?.values?.[0];if(!u||Number(u[0])!==1)throw new Error(`Insert into ${e} did not create exactly one row`);let f=M(u[1]),m=U(f,a);if((p.exec(`SELECT 1 FROM ${R(e)} WHERE ${m.sql} LIMIT 2`,O(m.params))[0]?.values.length??0)!==1)throw new Error(`Insert into ${e} did not leave one addressable row; the insert was rolled back`);let g=o?xi(e,a,f,i):f;return S(`RELEASE ${c}`),g}catch(u){throw B(c,"insertRowIdRow"),u}}async function Il(e,t,n,r){return Ui(e,t,n,r,!1)}async function Al(e,t,n,r){return Ui(e,t,n,void 0,!0,r)}var Ii=64;function Gn(e,t){let n=typeof e=="bigint"?Number(e):e;if(!Number.isSafeInteger(n)||n<0)throw new Error(`Demo delete snapshot ${t} exceeds the web transport safety bound`);return n}function Nl(e){let t=h(e);return`CASE typeof(${t}) WHEN 'text' THEN 6 * octet_length(${t}) WHEN 'blob' THEN 4 * ((octet_length(${t}) + 2) / 3) + 40 WHEN 'integer' THEN 8 WHEN 'real' THEN 8 ELSE 4 END`}function _l(e){let t=h(e);return`COALESCE(MAX(CASE WHEN typeof(${t}) = 'blob' THEN octet_length(${t}) ELSE 0 END), 0)`}function nr(e,t,n,r){let o=1024;for(let s of t)o+=64+6*String(s).length;let i=128+n.reduce((s,a)=>s+48+6*a.length,0),l=0;for(let s of r)for(let a=0;a0?", ":""}`+d.map(_l).join(", ")+` FROM ${R(e)} WHERE ${s.sql}`,O(s.params),{useBigInt:!0})[0]?.values?.[0];if(!c)throw new Error("Demo delete snapshot preflight returned no metadata");let u=Gn(c[0],"row count");a===0&&(l+=u,o+=u*i),o+=Gn(c[1],"encoded size");for(let f of c.slice(2))if(Gn(f,"BLOB size")>De)throw new Error(`Demo delete snapshot exceeds the ${De}-byte web transport binary limit; the row was not deleted`);if(!Number.isSafeInteger(o))throw new Error("Demo delete snapshot exceeds the web transport safety bound")}if(l!==t.length)throw new Error(`Cannot delete from ${e}: one or more row identities no longer exist`);if(o>qn)throw new Error(`Demo delete snapshot exceeds the ${qn}-byte web transport response limit; no rows were deleted`)}async function $l(e,t){if(t.forEach(Re),!p)throw new Error("No database initialized");if(z("Row deletion"),t.length===0)return[];let n=await te(e),r=Ke();if(t.some(X)){if(!t.every(X))throw new Error("Cannot mix rowid and primary-key row identities");if(n.kind!=="primaryKey")throw new Error(`Primary-key identity cannot target rowid table ${e}`);let l=tt(t,n),s=P("sp_delete_pk_rows");S(`SAVEPOINT ${s}`);try{Fe("DELETE",e);let a=tr(e);nr(e,t,a,l);let d=[];for(let c of l){let f=p.exec(`SELECT ${a.map(ee).join(", ")||"1"} FROM ${R(e)} WHERE ${c.sql}`,O(c.params),{useBigInt:!0})[0]?.values??[],m=n.columns.map(E=>{let g=a.indexOf(E.identifier);if(g<0)throw new Error(`Primary-key column missing from ${e}: ${E.identifier}`);return g});d.push(...f.map(E=>{let g=a.map((y,T)=>q(E[T*2],E[T*2+1],`${e}.${y}`,{textEncoding:r}));return{rowId:Pe(n.columns,m.map(y=>g[y].value)),row:Object.fromEntries(a.map((y,T)=>[y,g[T].rawTextBytes??g[T].value])),storageClasses:a.map((y,T)=>({column:y,storageClass:g[T].storageClass}))}}))}if(d.length!==t.length)throw new Error(`Cannot delete from ${e}: one or more row identities no longer exist`);for(let c of l)p.run(`DELETE FROM ${R(e)} WHERE ${c.sql}`,O(c.params));return S(`RELEASE ${s}`),d}catch(a){throw B(s,"deletePrimaryKeyRows"),a}}if(n.kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let o=tt(t,n),i=P("sp_delete_rowid_rows");S(`SAVEPOINT ${i}`);try{Fe("DELETE",e);let l=tr(e);nr(e,t,l,o);let s=[];for(let a of o){let d=p.exec(`SELECT CAST(rowid AS TEXT)${l.length>0?", ":""}${l.map(ee).join(", ")} FROM ${R(e)} WHERE ${a.sql}`,O(a.params),{useBigInt:!0})[0];s.push(...(d?.values??[]).map(c=>{let u=M(c[0]),f=l.map((m,E)=>q(c[E*2+1],c[E*2+2],`${e}.${m}`,{textEncoding:r}));return{rowId:u,row:Object.fromEntries(l.map((m,E)=>[m,f[E].rawTextBytes??f[E].value])),storageClasses:l.map((m,E)=>({column:m,storageClass:f[E].storageClass}))}}))}if(s.length!==t.length)throw new Error(`Cannot delete from ${e}: one or more row identities no longer exist`);for(let a of o)p.run(`DELETE FROM ${R(e)} WHERE ${a.sql}`,O(a.params));return S(`RELEASE ${i}`),s}catch(l){throw B(i,"deleteRowidRows"),l}}async function Vi(e,t){if(!p)throw new Error("No database initialized");if(!Array.isArray(t))throw new Error("Column names must be an array");K(e,"Table name"),t.forEach(u=>K(u,"Column name"));let r=(p.exec("SELECT name, sql FROM main.sqlite_schema WHERE type = 'index' AND tbl_name = ? AND sql IS NOT NULL ORDER BY name",[e])[0]?.values??[]).map(u=>({identifier:u[0],sql:u[1]}));if(r.length===0||t.length===0)return[];let i=(p.exec(`PRAGMA main.table_xinfo(${h(e)})`)[0]?.values??[]).map(u=>u[1]),l=Br(i,t);if(l.length===0)return[];let s=crypto.randomUUID().replace(/-/g,""),a=`__sqlite_explorer_index_probe_${s}`,d=`__sqlite_explorer_index_candidate_${s}`,c=P("sp_index_dependencies");S(`SAVEPOINT ${c}`);try{S(Pr(a,i));let u=P("sp_index_baseline");S(`SAVEPOINT ${u}`);try{for(let m of l)S(`ALTER TABLE temp.${h(a)} DROP COLUMN ${h(m)}`);S(`ROLLBACK TO ${u}`),S(`RELEASE ${u}`)}catch(m){throw B(u,"findDependentIndexBaseline"),new Error("Cannot establish the index dependency probe baseline",{cause:m})}let f=[];for(let m of r){let E=P("sp_index_candidate");S(`SAVEPOINT ${E}`);try{S(Dr(a,d,m.sql));let g=!1;for(let y of l)try{S(`ALTER TABLE temp.${h(a)} DROP COLUMN ${h(y)}`)}catch{g=!0;break}S(`ROLLBACK TO ${E}`),S(`RELEASE ${E}`),g&&f.push(m)}catch(g){throw B(E,"findDependentIndex"),new Error(`Cannot inspect dependency for index ${h(m.identifier)}`,{cause:g})}}return S(`ROLLBACK TO ${c}`),S(`RELEASE ${c}`),f}catch(u){throw B(c,"findDependentIndexes"),u}}function Ol(e){if(e!==void 0){if(!Array.isArray(e))throw new Error("Dependent-index confirmation must be an array");return e.map(t=>{if(!t||typeof t!="object"||Array.isArray(t)||typeof t.identifier!="string"||typeof t.sql!="string")throw new Error("Dependent-index confirmation contains an invalid definition");return K(t.identifier,"Index name"),{identifier:t.identifier,sql:t.sql}})}}function Ll(e,t,n){if(t.length===0&&(n?.length??0)===0)return;if(!n)throw new Error("Column deletion requires confirmation for dependent indexes: "+t.map(i=>i.identifier).join(", "));let r=new Map(n.map(i=>[i.identifier,i.sql]));if(!(r.size===n.length&&n.length===t.length&&t.every(i=>r.get(i.identifier)===i.sql)))throw new Error(`Cannot delete columns from ${e}: dependent indexes changed while the confirmation was open`)}async function vl(e,t,n){if(!p)throw new Error("No database initialized");if(z("Column deletion"),t.length===0)return;let r=P("sp_delete_columns");S(`SAVEPOINT ${r}`);try{let o=Ol(n),i=await Vi(e,t);Ll(e,i,o),await co(e,t,i.map(l=>l.identifier),l=>S(l)),S(`RELEASE ${r}`)}catch(o){throw B(r,"deleteColumns"),o}}async function kl(e,t,n){if(!p)throw new Error("No database initialized");z("Table creation");let r=Mr(e,t,n),o=P("sp_create_table");S(`SAVEPOINT ${o}`);try{let i=await W();S(r),de(i,await W()),S(`RELEASE ${o}`)}catch(i){throw B(o,"createTable"),i}}async function qi(e,t=!1){if(!p)throw new Error("No database initialized");let r=p.exec("SELECT sql FROM sqlite_schema WHERE type = 'view' AND name = ?",[e])[0]?.values?.[0]?.[0];if(typeof r!="string")return null;let o=pt.map(c=>p.exec(c.sql,c.params(e))[0]?.values||[]),{triggers:i,ambiguousTemporaryTriggerNames:l,unqualifiedTemporaryTriggers:s}=Rr(e,o);if(s.length>0){let u=(p.exec("SELECT name FROM pragma.pragma_table_xinfo(?, 'main') ORDER BY cid",[e])[0]?.values??[]).map(f=>{if(typeof f[0]!="string")throw new Error(`SQLite returned invalid view column metadata for ${e}`);return f[0]});for(let f of s){if(i.some(m=>!m.temporary&&ve(m.identifier,f.identifier))){l.push(f.identifier);continue}try{let m=yt(f.sql,"main",e,u);if(m===void 0){l.push(f.identifier);continue}let E=p.exec(m);Tr(E[0]?.values??[],f.identifier)&&i.push({...f,sql:dn(f.sql,f.identifier)})}catch{l.push(f.identifier)}}}let a,d;try{a=Ir(r),d=un(r)}catch(c){if(!t)throw c;a=""}return{identifier:e,sql:r,selectSql:a,columnListSql:d,triggers:i,...l.length>0?{ambiguousTemporaryTriggerNames:l}:{}}}async function Wi(e,t=!1){let n=await qi(e,t);if(!n)throw new Error(`View not found: ${e}`);return n}async function Xt(e){return Wi(e,!1)}function W(){return Lr({queryRows:async(e,t)=>p.exec(e,O(t))[0]?.values??[],compileStatements:async e=>e.map(t=>{try{He(t);return}catch(n){return Ne(n)}})})}function Fi(e,t){let r=p.exec("SELECT sql FROM sqlite_schema WHERE type = 'view' AND name = ?",[e])[0]?.values?.[0];Nr(e,r!==void 0,t);let o=r?.[0];return{storedSql:o,columnListSql:typeof o=="string"?un(o):void 0}}function z(e){if(j)throw new Error(`${e} is unavailable because the database is read-only`)}async function Pl(e,t,n="edit"){if(K(e,"View name"),!p)throw new Error("No database initialized");if(j)throw new Error("View validation is unavailable because the database is read-only");let r=Ee(t),{storedSql:o,columnListSql:i}=Fi(e,n),l=P("sp_validate_view");S(`SAVEPOINT ${l}`);try{let s=await W();typeof o=="string"&&S(`DROP VIEW ${Q(e)}`),S(Qe(e,r,i)),He(`EXPLAIN SELECT * FROM ${Q(e)}`),de(s,await W()),S(`ROLLBACK TO ${l}`),S(`RELEASE ${l}`)}catch(s){throw B(l,"validateViewDefinition"),s}}async function Bl(e,t,n=50,r="edit",o){if(K(e,"View name"),!p)throw new Error("No database initialized");let i=Ee(t),l=Math.max(1,Math.min(100,Math.trunc(n)||50)),{storedSql:s,columnListSql:a}=Fi(e,r);if(j){let c=h(e);return Xn(a?`WITH ${c} ${a} AS (${i} ) SELECT * FROM ${c} LIMIT ${l}`:`WITH ${c} AS (${i} -) SELECT * FROM ${c} LIMIT ${l}`,o)}let d=P("sp_preview_view");S(`SAVEPOINT ${d}`);try{let c=await W();typeof s=="string"&&S(`DROP VIEW ${Q(e)}`),S(Qe(e,i,a)),He(`EXPLAIN SELECT * FROM ${Q(e)}`),de(c,await W());let u=Qn(`SELECT * FROM ${Q(e)} LIMIT ${l}`,o);return S(`ROLLBACK TO ${d}`),S(`RELEASE ${d}`),u}catch(c){throw B(d,"previewViewDefinition"),c}}async function Pl(e,t){if(K(e,"View name"),!p)throw new Error("No database initialized");z("View creation");let n=Ee(t),r=P("sp_create_view");S(`SAVEPOINT ${r}`);try{let o=await W();S(Qe(e,n)),He(`EXPLAIN SELECT * FROM ${Q(e)}`);let i=await Qt(e);return de(o,await W()),S(`RELEASE ${r}`),i}catch(o){throw B(r,"createView"),o}}async function Bl(e,t,n=!0,r,o){if(!p)throw new Error("No database initialized");z("View editing");let i=Ee(t),l=P("sp_edit_view");S(`SAVEPOINT ${l}`);try{let s=await Qt(e);Et(s),ht(r,s.sql,o,s.triggers);let a=await W();if(S(`DROP VIEW ${Q(e)}`),S(Qe(e,i,s.columnListSql,s.columns)),He(`EXPLAIN SELECT * FROM ${Q(e)}`),n){let u=(p.exec(`PRAGMA main.table_info(${h(e)})`)[0]?.values??[]).map(f=>{if(typeof f[1]!="string")throw new Error(`SQLite returned invalid column metadata for view ${e}`);return f[1]});Ir(s.triggers,u);for(let f of s.triggers)S(dn(f))}let d=await Qt(e);return de(a,await W()),S(`RELEASE ${l}`),{before:s,after:d}}catch(s){throw B(l,"editView"),s}}async function Dl(e,t,n){if(!p)throw new Error("No database initialized");z("View deletion");let r=P("sp_drop_view");S(`SAVEPOINT ${r}`);try{let o=await qi(e,!0);Et(o),ht(t,o.sql,n,o.triggers);let i=await W();return S(`DROP VIEW ${Q(e)}`),de(i,await W()),S(`RELEASE ${r}`),o}catch(o){throw B(r,"dropView"),o}}async function qe(e,t,n){z("View history replay");let r=P("sp_restore_view");S(`SAVEPOINT ${r}`);try{let o=await Vi(e,!0);o&&Et(o),_r(t,o);let i=await W();if(o&&S(`DROP VIEW ${Q(e)}`),n){S(n.sql),He(`EXPLAIN SELECT * FROM ${Q(n.identifier)}`);for(let l of n.triggers)S(dn(l))}de(i,await W()),S(`RELEASE ${r}`)}catch(o){throw B(r,"restoreViewDefinition"),o}}function Gt(){let e=p.exec("SELECT changes()",void 0,{useBigInt:!0})[0]?.values?.[0]?.[0],t=typeof e=="bigint"?Number(e):e;if(!Number.isSafeInteger(t)||t<0)throw new Error("SQLite returned an invalid changes() count");return t}async function Fi(e,t){if(!Array.isArray(t)||t.length===0)throw new G;t.forEach(st);let n=await te(e),r=P("sp_history_delete_rows");S(`SAVEPOINT ${r}`);try{Fe("DELETE",e);for(let o of t){let i=U(o.rowId,n),l=$n(o,Y);if(p.run(`DELETE FROM ${R(e)} WHERE (${i.sql}) AND (${l.sql})`,O([...i.params,...l.params])),Gt()!==1)throw new Se(e)}S(`RELEASE ${r}`)}catch(o){throw B(r,"deleteRowHistorySnapshots"),o}}async function Hi(e,t){if(!Array.isArray(t)||t.length===0)throw new G;let n=await te(e),r=t.map(i=>({snapshot:i,states:st(i),writes:Vo(i,Y)})),o=P("sp_history_restore_rows");S(`SAVEPOINT ${o}`);try{for(let i of r){Fe("INSERT",e,i.states.map(a=>a.column));let l=U(i.snapshot.rowId,n);if((p.exec(`SELECT 1 FROM ${R(e)} WHERE ${l.sql} LIMIT 1`,O(l.params))[0]?.values.length??0)!==0)throw new Se(e)}for(let i of r){let l=i.writes.map(f=>f.column),s=i.writes.map(f=>f.write.sql),a=i.writes.flatMap(f=>f.write.params);if(n.kind==="rowid"&&!l.some(f=>f.toLowerCase()==="rowid")&&(l.unshift("rowid"),s.unshift(Y(i.snapshot.rowId)),a.unshift(i.snapshot.rowId)),p.run(`INSERT INTO ${R(e)} (${l.map(h).join(", ")}) VALUES (${s.join(", ")})`,O(a)),Gt()!==1)throw new Se(e);let d=U(i.snapshot.rowId,n),c=$n(i.snapshot,Y);if((p.exec(`SELECT 1 FROM ${R(e)} WHERE (${d.sql}) AND (${c.sql}) LIMIT 2`,O([...d.params,...c.params]))[0]?.values.length??0)!==1)throw new Se(e)}S(`RELEASE ${o}`)}catch(i){throw B(o,"restoreRowHistorySnapshots"),i}}function Ml(e){let t=e.affectedCells??(e.targetRowId!==void 0&&e.targetColumn?[{rowId:e.targetRowId,newRowId:e.newTargetRowId,columnName:e.targetColumn,newValue:e.newValue,operation:e.operation,priorState:e.priorState,postState:e.postState}]:[]);if(t.length===0)throw new ot;return t.map(n=>(it(n.priorState),it(n.postState),n))}async function Ki(e,t,n){if(t.undoPolicy==="barrier")throw new Error("Forward-only cell history barriers cannot be replayed");let r=Ml(t),o=r.some(c=>X(c.rowId));if(o&&!r.every(c=>X(c.rowId)))throw new Error("Cannot mix rowid and primary-key row identities");let i=await te(e);if(o&&i.kind!=="primaryKey")throw new Error(`Primary-key identity cannot target rowid table ${e}`);if(!o&&i.kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let l=Ke(),s=new Map;for(let c of r){let u=s.get(c.rowId)??[];if(u.some(f=>ve(f.columnName,c.columnName)))throw new Error(`Cell history for ${e} contains the same column more than once`);u.push(c),s.set(c.rowId,u)}let a=[...s.entries()];n==="undo"&&r.some(c=>c.newRowId!==void 0&&c.newRowId!==c.rowId)&&a.reverse();let d=P("sp_replay_cell_history");S(`SAVEPOINT ${d}`);try{dt(e,r.map(c=>c.columnName),i.kind==="rowid");for(let[c,u]of a){if(new Set(u.map(w=>w.newRowId??w.rowId)).size!==1)throw new Error(`Cell history for ${e} has inconsistent post-update identities`);let m=u[0].newRowId??c,y=n==="undo"?m:c,g=n==="undo"?c:m,E=U(y,i),T=u.map(w=>ee(w.columnName)),x=p.exec(`SELECT ${T.join(", ")} FROM ${R(e)} WHERE ${E.sql} LIMIT 2`,O(E.params),{useBigInt:!0})[0];if((x?.values.length??0)!==1)throw new oe(e,u.map(w=>w.columnName));let A=u.map((w,v)=>q(x.values[0][v*2],x.values[0][v*2+1],`${e}.${w.columnName}`,{textEncoding:l})),_=u.map((w,v)=>{let ne=n==="undo"?w.postState:w.priorState,ie=n==="undo"?w.priorState:w.postState,H=A[v];if(w.operation!=="json_patch"){if(!_n(H,ne))throw new oe(e,[w.columnName]);return ie}if(H.storageClass!==ne.storageClass||w.newValue===void 0)throw new oe(e,[w.columnName]);let se=Mo(H.value,w.newValue,w.priorState.value,w.postState.value,n);if(se.kind==="conflict")throw new oe(e,[w.columnName]);return Object.is(se.value,ie.value)?ie:q("text",se.value,`${e}.${w.columnName} JSON replay`)}),b=_.map(w=>Vt(w,Y)),C=A.map((w,v)=>qt(u[v].columnName,w,Y));if(p.run(`UPDATE ${R(e)} SET ${u.map((w,v)=>`${h(w.columnName)} = ${b[v].sql}`).join(", ")} WHERE ${E.sql} AND `+C.map(w=>`(${w.sql})`).join(" AND "),O([...b.flatMap(w=>w.params),...E.params,...C.flatMap(w=>w.params)])),Gt()!==1)throw new oe(e,u.map(w=>w.columnName));let N=U(g,i),I=p.exec(`SELECT ${T.join(", ")} FROM ${R(e)} WHERE ${N.sql} LIMIT 2`,O(N.params),{useBigInt:!0})[0];if((I?.values.length??0)!==1)throw new oe(e,u.map(w=>w.columnName));if(!_.every((w,v)=>_n(w,q(I.values[0][v*2],I.values[0][v*2+1],`${e}.${u[v].columnName}`,{textEncoding:l}))))throw new oe(e,u.map(w=>w.columnName))}S(`RELEASE ${d}`)}catch(c){throw B(d,"replayCellHistory"),c}}async function Ul(e){let{modificationType:t,targetTable:n,viewDefBefore:r,viewDefAfter:o,affectedCells:i,targetRowId:l,newTargetRowId:s,targetColumn:a,priorValue:d,newValue:c,operation:u,deletedRows:f,insertedRow:m}=e;if(n)switch(t){case"cell_update":await Ki(n,e,"undo");return;case"row_insert":if(!m||l===void 0)throw new G;if(typeof m.rowId!=typeof l||String(m.rowId)!==String(l))throw new G;await Fi(n,[m]);return;case"row_delete":{if(!f||f.length===0)throw new G;await Hi(n,f);return}case"view_create":if(o)await qe(n,o,null);else throw new Error("Cannot undo view_create: missing view definition");return;case"view_edit":if(r&&o)await qe(n,o,r);else throw new Error("Cannot undo view_edit: missing view definition");return;case"view_drop":if(r)await qe(n,null,r);else throw new Error("Cannot undo view_drop: missing view definition");return;default:throw new Error(`Demo history replay does not support undoing ${String(t)}`)}}async function Vl(e){let{modificationType:t,targetTable:n,viewDefBefore:r,viewDefAfter:o,affectedCells:i,targetRowId:l,targetColumn:s,newValue:a,operation:d,rowData:c,affectedRowIds:u,insertedRow:f,deletedRows:m}=e;if(n)switch(t){case"cell_update":await Ki(n,e,"redo");return;case"row_insert":{if(!f)throw new G;await Hi(n,[f]);return}case"row_delete":if(!m||m.length===0)throw new G;await Fi(n,m);return;case"view_create":if(o)await qe(n,null,o);else throw new Error("Cannot redo view_create: missing view definition");return;case"view_edit":if(r&&o)await qe(n,r,o);else throw new Error("Cannot redo view_edit: missing view definition");return;case"view_drop":if(r)await qe(n,r,null);else throw new Error("Cannot redo view_drop: missing view definition");return;default:throw new Error(`Demo history replay does not support redoing ${String(t)}`)}}function ql(e,t){let n=new Map;for(let r of t){K(r.column,"Column name");let o;X(r.rowId)?(so(r.rowId),o=`primary-key:${r.rowId}`):o=`rowid:${String(M(r.rowId))}`;let i=n.get(o)??[];if(i.some(l=>ve(l,r.column)))throw new Error(`Batch update for ${e} contains a duplicate row identity/column target: ${String(r.rowId)} / ${r.column}`);i.push(r.column),n.set(o,i)}}async function ji(e,t,n,r,o){if(t.forEach(c=>Re(c.rowId)),!p)throw new Error("No database initialized");if(z("Batch cell updates"),t.length===0)return[];ql(e,t);let i=o===nr,l=i?0:lt(t.map(c=>c.value),r),s=Ke();if(t.some(c=>X(c.rowId))){if(!t.every(f=>X(f.rowId)))throw new Error("Cannot mix rowid and primary-key row identities");let c=await te(e);if(c.kind!=="primaryKey")throw new Error(`Primary-key identity cannot target rowid table ${e}`);let u=P("sp_update_pk_batch");S(`SAVEPOINT ${u}`);try{if(dt(e,t.map(y=>y.column),!1),!i&&r!==void 0)for(let y of t){let g=await zt({table:e,rowId:y.rowId,column:y.column});if((g.storageClass==="text"||g.storageClass==="blob")&&g.byteLength>l)throw new Me(e,y.column,g.storageClass,g.byteLength,l)}let f=new Map;for(let y of t){let g=f.get(y.rowId)??[];g.push(y),f.set(y.rowId,g)}let m=[];for(let[y,g]of f){let E=U(y,c),T=[...new Set(g.map(w=>w.column))];if(T.length!==g.length)throw new Error(`Batch update for ${e} contains the same column more than once`);let x=p.exec(`SELECT ${T.map(ee).join(", ")} FROM ${R(e)} WHERE ${E.sql} LIMIT 2`,O(E.params),{useBigInt:!0})[0];if((x?.values.length??0)!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);let A=g.map((w,v)=>{let ne=q(x.values[0][v*2],x.values[0][v*2+1],`${e}.${w.column}`,{textEncoding:s}),ie=ne.value,H=Ut(w.value,ie,w.operation??"set"),se=H.operation==="json_patch"?Zn(ie,H.value):H.value;return!i&&H.operation==="json_patch"&&at(se,l),{update:w,priorValue:ie,priorState:ne,prepared:H,storedValue:se}}),_=A.map(({update:w,storedValue:v})=>`${h(w.column)} = ${Y(v)}`).join(", ");if(p.run(`UPDATE ${R(e)} SET ${_} WHERE ${E.sql}`,O([...A.map(w=>w.storedValue),...E.params])),Gt()!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);let b=[];for(let w of A)c.columns.findIndex(ne=>ne.identifier===w.update.column)>=0&&b.push({column:w.update.column,value:w.storedValue});let C=Sn(y,c,b),N=ir(e,c,U(C,c),Jn(e)),I=U(N,c),L=p.exec(`SELECT ${T.map(ee).join(", ")} FROM ${R(e)} WHERE ${I.sql} LIMIT 2`,O(I.params),{useBigInt:!0})[0];if((L?.values.length??0)!==1)throw Jn(e);for(let[w,v]of A.entries())m.push({rowId:y,newRowId:N,columnName:v.update.column,priorValue:v.priorValue,newValue:v.prepared.value,priorState:v.priorState,postState:q(L.values[0][w*2],L.values[0][w*2+1],`${e}.${v.update.column}`,{textEncoding:s}),operation:v.prepared.operation})}return S(`RELEASE ${u}`),m}catch(f){throw B(u,"updatePrimaryKeyCellBatch"),f}}if((await te(e)).kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let d=P("sp_update_cell_batch");S(`SAVEPOINT ${d}`);try{if(!i&&r!==void 0)for(let b of t){let C=await zt({table:e,rowId:b.rowId,column:b.column});if((C.storageClass==="text"||C.storageClass==="blob")&&C.byteLength>l)throw new Me(e,b.column,C.storageClass,C.byteLength,l)}let c=sr(e);if(dt(e,t.map(b=>b.column)),c!==void 0&&t.some(b=>ve(b.column,c))){let b=pl(e,c,t,l,i);return S(`RELEASE ${d}`),b}let u=[...new Set(t.map(b=>M(b.rowId)))],f=[...new Set(t.map(b=>b.column))],m=R(e),y=new Map,g=tt(u,{kind:"rowid"});for(let b of g){let C=p.exec(`SELECT CAST(rowid AS TEXT), ${f.map(ee).join(", ")} FROM ${m} WHERE ${b.sql}`,O(b.params),{useBigInt:!0})[0];for(let N of C?.values??[]){let I=new Map;f.forEach((L,w)=>I.set(L,q(N[w*2+1],N[w*2+2],`${e}.${L}`,{textEncoding:s}))),y.set(String(M(N[0])),I)}}let E=[],T=t.map(b=>{let C=M(b.rowId),N=y.get(String(C));if(!N)throw new Error(`Cannot update ${e}.${b.column}: row ${b.rowId} no longer exists`);let I=N.get(b.column);if(!I)throw new Error(`Cannot update ${e}.${b.column}: cell state is unavailable`);let L=I.value,w=Ut(b.value,L,b.operation??"set");if(!i&&w.operation==="json_patch"){let v=Zn(L,w.value);at(v,l)}return E.push({rowId:C,columnName:b.column,priorValue:L,newValue:w.value,priorState:I,operation:w.operation}),{...b,rowId:C,value:w.value,operation:w.operation}});for(let b of T){let C=h(b.column),N=b.operation==="json_patch"?`UPDATE ${m} SET ${C} = json_patch(COALESCE(${C}, '{}'), ?) WHERE rowid = ?`:`UPDATE ${m} SET ${C} = ${Y(b.value)} WHERE rowid = ?`;p.run(N,O([b.value,b.rowId]))}let x=new Set;for(let b of g){let C=p.exec(`SELECT CAST(rowid AS TEXT) FROM ${m} WHERE ${b.sql}`,O(b.params),{useBigInt:!0})[0];for(let N of C?.values??[])x.add(String(M(N[0])))}if(u.some(b=>!x.has(String(b))))throw Ze(e);let A=new Map;for(let b of g){let C=p.exec(`SELECT CAST(rowid AS TEXT), ${f.map(ee).join(", ")} FROM ${m} WHERE ${b.sql}`,O(b.params),{useBigInt:!0})[0];for(let N of C?.values??[]){let I=new Map;f.forEach((L,w)=>I.set(L,q(N[w*2+1],N[w*2+2],`${e}.${L}`,{textEncoding:s}))),A.set(String(M(N[0])),I)}}let _=E.map(b=>{let C=A.get(String(b.rowId))?.get(b.columnName);if(!C)throw Ze(e);return{...b,postState:C}});return S(`RELEASE ${d}`),_}catch(c){throw B(d,"updateCellBatch"),c}}async function Wl(e,t,n,r){if(K(e,"Table name"),K(t,"Column name"),!p)throw new Error("No database initialized");z("Column creation"),Ma(n);let o=`ALTER TABLE ${R(e)} ADD COLUMN ${h(t)} ${n}`;r!=null&&r!==""&&(o+=` DEFAULT ${Ua(r)}`);let i=P("sp_add_column");S(`SAVEPOINT ${i}`);try{let l=await W();S(o),de(l,await W()),S(`RELEASE ${i}`)}catch(l){throw B(i,"addColumn"),l}}async function Fl(){if(!p)return!1;try{return p.exec("SELECT 1"),!0}catch{return!1}}async function Hl(){throw new Error("Reload must be handled by the demo host so it can reinitialize from the original database source")}var Ii={initializeDatabase:Ya,runQuery:Za,executeReadQuery:el,getCellMetadata:zt,openCellReadSession:Fa,readCellChunk:Ha,closeCellReadSession:Ka,exportDatabase:tl,exportTable:nl,fetchTableData:gl,fetchTableCount:yl,fetchSchema:El,getTableInfo:Di,getPragmas:Sl,setPragma:bl,updateCell:Cl,replaceOversizedCell:Tl,insertRow:Rl,insertRowWithHistory:xl,deleteRows:Nl,findDependentIndexes:Ui,deleteColumns:Ol,createTable:Ll,getViewDefinition:Qt,validateViewDefinition:vl,previewViewDefinition:kl,createView:Pl,editView:Bl,dropView:Dl,undoModification:Ul,redoModification:Vl,updateCellBatch:ji,addColumn:Wl,ping:Fl,refreshFile:Hl};self.onmessage=async e=>{let t=e.data;if(!t||t.channel!=="rpc"||!t.content){console.warn("[Worker] Invalid message format",{valueType:t===null?"null":Array.isArray(t)?"array":typeof t,hasRpcChannel:t?.channel==="rpc",hasContent:!!t?.content});return}let{kind:n,messageId:r,targetMethod:o,payload:i}=t.content;if(n!=="invoke")return;if(typeof r!="string"||r.length===0||r.length>256){console.warn("[Worker] Invalid RPC correlation ID");return}let s=typeof o=="string"&&Object.prototype.hasOwnProperty.call(Ii,o)?Ii[o]:void 0;if(typeof s!="function"){self.postMessage({channel:"rpc",content:{kind:"response",messageId:r,success:!1,errorMessage:`Unknown method: ${typeof o=="string"?o.slice(0,256):""}`}});return}if(!Array.isArray(i)){self.postMessage({channel:"rpc",content:{kind:"response",messageId:r,success:!1,errorMessage:"Worker RPC payload must be an array"}});return}try{ja(o);let a=await s(...i),d={channel:"rpc",content:{kind:"response",messageId:r,success:!0,data:a}};if(o==="exportDatabase"&&a instanceof Uint8Array){let c=a.byteOffset===0&&a.byteLength===a.buffer.byteLength&&a.buffer instanceof ArrayBuffer?a:a.slice();d.content.data=c,self.postMessage(d,[c.buffer])}else self.postMessage(d)}catch(a){let d=Ne(a);console.error("[Worker] Method error:",o,d);let c;try{c=ii(a)}catch{}self.postMessage({channel:"rpc",content:{kind:"response",messageId:r,success:!1,errorMessage:d,...c?{error:c}:{}}})}};})(); +) SELECT * FROM ${c} LIMIT ${l}`,o)}let d=P("sp_preview_view");S(`SAVEPOINT ${d}`);try{let c=await W();typeof s=="string"&&S(`DROP VIEW ${Q(e)}`),S(Qe(e,i,a)),He(`EXPLAIN SELECT * FROM ${Q(e)}`),de(c,await W());let u=Xn(`SELECT * FROM ${Q(e)} LIMIT ${l}`,o);return S(`ROLLBACK TO ${d}`),S(`RELEASE ${d}`),u}catch(c){throw B(d,"previewViewDefinition"),c}}async function Dl(e,t){if(K(e,"View name"),!p)throw new Error("No database initialized");z("View creation");let n=Ee(t),r=P("sp_create_view");S(`SAVEPOINT ${r}`);try{let o=await W();S(Qe(e,n)),He(`EXPLAIN SELECT * FROM ${Q(e)}`);let i=await Xt(e);return de(o,await W()),S(`RELEASE ${r}`),i}catch(o){throw B(r,"createView"),o}}async function Ml(e,t,n=!0,r,o){if(!p)throw new Error("No database initialized");z("View editing");let i=Ee(t),l=P("sp_edit_view");S(`SAVEPOINT ${l}`);try{let s=await Xt(e);Et(s),ht(r,s.sql,o,s.triggers);let a=await W();if(S(`DROP VIEW ${Q(e)}`),S(Qe(e,i,s.columnListSql,s.columns)),He(`EXPLAIN SELECT * FROM ${Q(e)}`),n){let u=(p.exec(`PRAGMA main.table_info(${h(e)})`)[0]?.values??[]).map(f=>{if(typeof f[1]!="string")throw new Error(`SQLite returned invalid column metadata for view ${e}`);return f[1]});Ar(s.triggers,u);for(let f of s.triggers)S(fn(f))}let d=await Xt(e);return de(a,await W()),S(`RELEASE ${l}`),{before:s,after:d}}catch(s){throw B(l,"editView"),s}}async function Ul(e,t,n){if(!p)throw new Error("No database initialized");z("View deletion");let r=P("sp_drop_view");S(`SAVEPOINT ${r}`);try{let o=await Wi(e,!0);Et(o),ht(t,o.sql,n,o.triggers);let i=await W();return S(`DROP VIEW ${Q(e)}`),de(i,await W()),S(`RELEASE ${r}`),o}catch(o){throw B(r,"dropView"),o}}async function qe(e,t,n){z("View history replay");let r=P("sp_restore_view");S(`SAVEPOINT ${r}`);try{let o=await qi(e,!0);o&&Et(o),$r(t,o);let i=await W();if(o&&S(`DROP VIEW ${Q(e)}`),n){S(n.sql),He(`EXPLAIN SELECT * FROM ${Q(n.identifier)}`);for(let l of n.triggers)S(fn(l))}de(i,await W()),S(`RELEASE ${r}`)}catch(o){throw B(r,"restoreViewDefinition"),o}}function Yt(){let e=p.exec("SELECT changes()",void 0,{useBigInt:!0})[0]?.values?.[0]?.[0],t=typeof e=="bigint"?Number(e):e;if(!Number.isSafeInteger(t)||t<0)throw new Error("SQLite returned an invalid changes() count");return t}async function Hi(e,t){if(!Array.isArray(t)||t.length===0)throw new G;t.forEach(st);let n=await te(e),r=P("sp_history_delete_rows");S(`SAVEPOINT ${r}`);try{Fe("DELETE",e);for(let o of t){let i=U(o.rowId,n),l=On(o,Y);if(p.run(`DELETE FROM ${R(e)} WHERE (${i.sql}) AND (${l.sql})`,O([...i.params,...l.params])),Yt()!==1)throw new Se(e)}S(`RELEASE ${r}`)}catch(o){throw B(r,"deleteRowHistorySnapshots"),o}}async function Ki(e,t){if(!Array.isArray(t)||t.length===0)throw new G;let n=await te(e),r=t.map(i=>({snapshot:i,states:st(i),writes:qo(i,Y)})),o=P("sp_history_restore_rows");S(`SAVEPOINT ${o}`);try{for(let i of r){Fe("INSERT",e,i.states.map(a=>a.column));let l=U(i.snapshot.rowId,n);if((p.exec(`SELECT 1 FROM ${R(e)} WHERE ${l.sql} LIMIT 1`,O(l.params))[0]?.values.length??0)!==0)throw new Se(e)}for(let i of r){let l=i.writes.map(f=>f.column),s=i.writes.map(f=>f.write.sql),a=i.writes.flatMap(f=>f.write.params);if(n.kind==="rowid"&&!l.some(f=>f.toLowerCase()==="rowid")&&(l.unshift("rowid"),s.unshift(Y(i.snapshot.rowId)),a.unshift(i.snapshot.rowId)),p.run(`INSERT INTO ${R(e)} (${l.map(h).join(", ")}) VALUES (${s.join(", ")})`,O(a)),Yt()!==1)throw new Se(e);let d=U(i.snapshot.rowId,n),c=On(i.snapshot,Y);if((p.exec(`SELECT 1 FROM ${R(e)} WHERE (${d.sql}) AND (${c.sql}) LIMIT 2`,O([...d.params,...c.params]))[0]?.values.length??0)!==1)throw new Se(e)}S(`RELEASE ${o}`)}catch(i){throw B(o,"restoreRowHistorySnapshots"),i}}function Vl(e){let t=e.affectedCells??(e.targetRowId!==void 0&&e.targetColumn?[{rowId:e.targetRowId,newRowId:e.newTargetRowId,columnName:e.targetColumn,newValue:e.newValue,operation:e.operation,priorState:e.priorState,postState:e.postState}]:[]);if(t.length===0)throw new ot;return t.map(n=>(it(n.priorState),it(n.postState),n))}async function ji(e,t,n){if(t.undoPolicy==="barrier")throw new Error("Forward-only cell history barriers cannot be replayed");let r=Vl(t),o=r.some(c=>X(c.rowId));if(o&&!r.every(c=>X(c.rowId)))throw new Error("Cannot mix rowid and primary-key row identities");let i=await te(e);if(o&&i.kind!=="primaryKey")throw new Error(`Primary-key identity cannot target rowid table ${e}`);if(!o&&i.kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let l=Ke(),s=new Map;for(let c of r){let u=s.get(c.rowId)??[];if(u.some(f=>ve(f.columnName,c.columnName)))throw new Error(`Cell history for ${e} contains the same column more than once`);u.push(c),s.set(c.rowId,u)}let a=[...s.entries()];n==="undo"&&r.some(c=>c.newRowId!==void 0&&c.newRowId!==c.rowId)&&a.reverse();let d=P("sp_replay_cell_history");S(`SAVEPOINT ${d}`);try{dt(e,r.map(c=>c.columnName),i.kind==="rowid");for(let[c,u]of a){if(new Set(u.map(w=>w.newRowId??w.rowId)).size!==1)throw new Error(`Cell history for ${e} has inconsistent post-update identities`);let m=u[0].newRowId??c,E=n==="undo"?m:c,g=n==="undo"?c:m,y=U(E,i),T=u.map(w=>ee(w.columnName)),x=p.exec(`SELECT ${T.join(", ")} FROM ${R(e)} WHERE ${y.sql} LIMIT 2`,O(y.params),{useBigInt:!0})[0];if((x?.values.length??0)!==1)throw new oe(e,u.map(w=>w.columnName));let A=u.map((w,v)=>q(x.values[0][v*2],x.values[0][v*2+1],`${e}.${w.columnName}`,{textEncoding:l})),_=u.map((w,v)=>{let ne=n==="undo"?w.postState:w.priorState,ie=n==="undo"?w.priorState:w.postState,H=A[v];if(w.operation!=="json_patch"){if(!$n(H,ne))throw new oe(e,[w.columnName]);return ie}if(H.storageClass!==ne.storageClass||w.newValue===void 0)throw new oe(e,[w.columnName]);let se=Uo(H.value,w.newValue,w.priorState.value,w.postState.value,n);if(se.kind==="conflict")throw new oe(e,[w.columnName]);return Object.is(se.value,ie.value)?ie:q("text",se.value,`${e}.${w.columnName} JSON replay`)}),b=_.map(w=>qt(w,Y)),C=A.map((w,v)=>Wt(u[v].columnName,w,Y));if(p.run(`UPDATE ${R(e)} SET ${u.map((w,v)=>`${h(w.columnName)} = ${b[v].sql}`).join(", ")} WHERE ${y.sql} AND `+C.map(w=>`(${w.sql})`).join(" AND "),O([...b.flatMap(w=>w.params),...y.params,...C.flatMap(w=>w.params)])),Yt()!==1)throw new oe(e,u.map(w=>w.columnName));let N=U(g,i),I=p.exec(`SELECT ${T.join(", ")} FROM ${R(e)} WHERE ${N.sql} LIMIT 2`,O(N.params),{useBigInt:!0})[0];if((I?.values.length??0)!==1)throw new oe(e,u.map(w=>w.columnName));if(!_.every((w,v)=>$n(w,q(I.values[0][v*2],I.values[0][v*2+1],`${e}.${u[v].columnName}`,{textEncoding:l}))))throw new oe(e,u.map(w=>w.columnName))}S(`RELEASE ${d}`)}catch(c){throw B(d,"replayCellHistory"),c}}async function ql(e){let{modificationType:t,targetTable:n,viewDefBefore:r,viewDefAfter:o,affectedCells:i,targetRowId:l,newTargetRowId:s,targetColumn:a,priorValue:d,newValue:c,operation:u,deletedRows:f,insertedRow:m}=e;if(n)switch(t){case"cell_update":await ji(n,e,"undo");return;case"row_insert":if(!m||l===void 0)throw new G;if(typeof m.rowId!=typeof l||String(m.rowId)!==String(l))throw new G;await Hi(n,[m]);return;case"row_delete":{if(!f||f.length===0)throw new G;await Ki(n,f);return}case"view_create":if(o)await qe(n,o,null);else throw new Error("Cannot undo view_create: missing view definition");return;case"view_edit":if(r&&o)await qe(n,o,r);else throw new Error("Cannot undo view_edit: missing view definition");return;case"view_drop":if(r)await qe(n,null,r);else throw new Error("Cannot undo view_drop: missing view definition");return;default:throw new Error(`Demo history replay does not support undoing ${String(t)}`)}}async function Wl(e){let{modificationType:t,targetTable:n,viewDefBefore:r,viewDefAfter:o,affectedCells:i,targetRowId:l,targetColumn:s,newValue:a,operation:d,rowData:c,affectedRowIds:u,insertedRow:f,deletedRows:m}=e;if(n)switch(t){case"cell_update":await ji(n,e,"redo");return;case"row_insert":{if(!f)throw new G;await Ki(n,[f]);return}case"row_delete":if(!m||m.length===0)throw new G;await Hi(n,m);return;case"view_create":if(o)await qe(n,null,o);else throw new Error("Cannot redo view_create: missing view definition");return;case"view_edit":if(r&&o)await qe(n,r,o);else throw new Error("Cannot redo view_edit: missing view definition");return;case"view_drop":if(r)await qe(n,r,null);else throw new Error("Cannot redo view_drop: missing view definition");return;default:throw new Error(`Demo history replay does not support redoing ${String(t)}`)}}function Fl(e,t){let n=new Map;for(let r of t){K(r.column,"Column name");let o;X(r.rowId)?(ao(r.rowId),o=`primary-key:${r.rowId}`):o=`rowid:${String(M(r.rowId))}`;let i=n.get(o)??[];if(i.some(l=>ve(l,r.column)))throw new Error(`Batch update for ${e} contains a duplicate row identity/column target: ${String(r.rowId)} / ${r.column}`);i.push(r.column),n.set(o,i)}}async function zi(e,t,n,r,o){if(t.forEach(c=>Re(c.rowId)),!p)throw new Error("No database initialized");if(z("Batch cell updates"),t.length===0)return[];Fl(e,t);let i=o===rr,l=i?0:lt(t.map(c=>c.value),r),s=Ke();if(t.some(c=>X(c.rowId))){if(!t.every(f=>X(f.rowId)))throw new Error("Cannot mix rowid and primary-key row identities");let c=await te(e);if(c.kind!=="primaryKey")throw new Error(`Primary-key identity cannot target rowid table ${e}`);let u=P("sp_update_pk_batch");S(`SAVEPOINT ${u}`);try{if(dt(e,t.map(E=>E.column),!1),!i&&r!==void 0)for(let E of t){let g=await Qt({table:e,rowId:E.rowId,column:E.column});if((g.storageClass==="text"||g.storageClass==="blob")&&g.byteLength>l)throw new Me(e,E.column,g.storageClass,g.byteLength,l)}let f=new Map;for(let E of t){let g=f.get(E.rowId)??[];g.push(E),f.set(E.rowId,g)}let m=[];for(let[E,g]of f){let y=U(E,c),T=[...new Set(g.map(w=>w.column))];if(T.length!==g.length)throw new Error(`Batch update for ${e} contains the same column more than once`);let x=p.exec(`SELECT ${T.map(ee).join(", ")} FROM ${R(e)} WHERE ${y.sql} LIMIT 2`,O(y.params),{useBigInt:!0})[0];if((x?.values.length??0)!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);let A=g.map((w,v)=>{let ne=q(x.values[0][v*2],x.values[0][v*2+1],`${e}.${w.column}`,{textEncoding:s}),ie=ne.value,H=Vt(w.value,ie,w.operation??"set"),se=H.operation==="json_patch"?er(ie,H.value):H.value;return!i&&H.operation==="json_patch"&&at(se,l),{update:w,priorValue:ie,priorState:ne,prepared:H,storedValue:se}}),_=A.map(({update:w,storedValue:v})=>`${h(w.column)} = ${Y(v)}`).join(", ");if(p.run(`UPDATE ${R(e)} SET ${_} WHERE ${y.sql}`,O([...A.map(w=>w.storedValue),...y.params])),Yt()!==1)throw new Error(`Cannot update ${e}: row identity no longer exists`);let b=[];for(let w of A)c.columns.findIndex(ne=>ne.identifier===w.update.column)>=0&&b.push({column:w.update.column,value:w.storedValue});let C=bn(E,c,b),N=sr(e,c,U(C,c),Zn(e)),I=U(N,c),L=p.exec(`SELECT ${T.map(ee).join(", ")} FROM ${R(e)} WHERE ${I.sql} LIMIT 2`,O(I.params),{useBigInt:!0})[0];if((L?.values.length??0)!==1)throw Zn(e);for(let[w,v]of A.entries())m.push({rowId:E,newRowId:N,columnName:v.update.column,priorValue:v.priorValue,newValue:v.prepared.value,priorState:v.priorState,postState:q(L.values[0][w*2],L.values[0][w*2+1],`${e}.${v.update.column}`,{textEncoding:s}),operation:v.prepared.operation})}return S(`RELEASE ${u}`),m}catch(f){throw B(u,"updatePrimaryKeyCellBatch"),f}}if((await te(e)).kind!=="rowid")throw new Error(`Rowid identity cannot target WITHOUT ROWID table ${e}`);let d=P("sp_update_cell_batch");S(`SAVEPOINT ${d}`);try{if(!i&&r!==void 0)for(let b of t){let C=await Qt({table:e,rowId:b.rowId,column:b.column});if((C.storageClass==="text"||C.storageClass==="blob")&&C.byteLength>l)throw new Me(e,b.column,C.storageClass,C.byteLength,l)}let c=ar(e);if(dt(e,t.map(b=>b.column)),c!==void 0&&t.some(b=>ve(b.column,c))){let b=yl(e,c,t,l,i);return S(`RELEASE ${d}`),b}let u=[...new Set(t.map(b=>M(b.rowId)))],f=[...new Set(t.map(b=>b.column))],m=R(e),E=new Map,g=tt(u,{kind:"rowid"});for(let b of g){let C=p.exec(`SELECT CAST(rowid AS TEXT), ${f.map(ee).join(", ")} FROM ${m} WHERE ${b.sql}`,O(b.params),{useBigInt:!0})[0];for(let N of C?.values??[]){let I=new Map;f.forEach((L,w)=>I.set(L,q(N[w*2+1],N[w*2+2],`${e}.${L}`,{textEncoding:s}))),E.set(String(M(N[0])),I)}}let y=[],T=t.map(b=>{let C=M(b.rowId),N=E.get(String(C));if(!N)throw new Error(`Cannot update ${e}.${b.column}: row ${b.rowId} no longer exists`);let I=N.get(b.column);if(!I)throw new Error(`Cannot update ${e}.${b.column}: cell state is unavailable`);let L=I.value,w=Vt(b.value,L,b.operation??"set");if(!i&&w.operation==="json_patch"){let v=er(L,w.value);at(v,l)}return y.push({rowId:C,columnName:b.column,priorValue:L,newValue:w.value,priorState:I,operation:w.operation}),{...b,rowId:C,value:w.value,operation:w.operation}});for(let b of T){let C=h(b.column),N=b.operation==="json_patch"?`UPDATE ${m} SET ${C} = json_patch(COALESCE(${C}, '{}'), ?) WHERE rowid = ?`:`UPDATE ${m} SET ${C} = ${Y(b.value)} WHERE rowid = ?`;p.run(N,O([b.value,b.rowId]))}let x=new Set;for(let b of g){let C=p.exec(`SELECT CAST(rowid AS TEXT) FROM ${m} WHERE ${b.sql}`,O(b.params),{useBigInt:!0})[0];for(let N of C?.values??[])x.add(String(M(N[0])))}if(u.some(b=>!x.has(String(b))))throw Ze(e);let A=new Map;for(let b of g){let C=p.exec(`SELECT CAST(rowid AS TEXT), ${f.map(ee).join(", ")} FROM ${m} WHERE ${b.sql}`,O(b.params),{useBigInt:!0})[0];for(let N of C?.values??[]){let I=new Map;f.forEach((L,w)=>I.set(L,q(N[w*2+1],N[w*2+2],`${e}.${L}`,{textEncoding:s}))),A.set(String(M(N[0])),I)}}let _=y.map(b=>{let C=A.get(String(b.rowId))?.get(b.columnName);if(!C)throw Ze(e);return{...b,postState:C}});return S(`RELEASE ${d}`),_}catch(c){throw B(d,"updateCellBatch"),c}}async function Hl(e,t,n,r){if(K(e,"Table name"),K(t,"Column name"),!p)throw new Error("No database initialized");z("Column creation"),Va(n);let o=`ALTER TABLE ${R(e)} ADD COLUMN ${h(t)} ${n}`;r!=null&&r!==""&&(o+=` DEFAULT ${qa(r)}`);let i=P("sp_add_column");S(`SAVEPOINT ${i}`);try{let l=await W();S(o),de(l,await W()),S(`RELEASE ${i}`)}catch(l){throw B(i,"addColumn"),l}}async function Kl(){if(!p)return!1;try{return p.exec("SELECT 1"),!0}catch{return!1}}async function jl(){throw new Error("Reload must be handled by the demo host so it can reinitialize from the original database source")}var Ai={initializeDatabase:Za,runQuery:tl,executeReadQuery:nl,getCellMetadata:Qt,openCellReadSession:Ka,readCellChunk:ja,closeCellReadSession:za,exportDatabase:rl,exportTable:ol,fetchTableData:El,fetchTableCount:hl,fetchSchema:wl,getTableInfo:Mi,getPragmas:Cl,setPragma:Tl,updateCell:Rl,replaceOversizedCell:xl,insertRow:Il,insertRowWithHistory:Al,deleteRows:$l,findDependentIndexes:Vi,deleteColumns:vl,createTable:kl,getViewDefinition:Xt,validateViewDefinition:Pl,previewViewDefinition:Bl,createView:Dl,editView:Ml,dropView:Ul,undoModification:ql,redoModification:Wl,updateCellBatch:zi,addColumn:Hl,ping:Kl,refreshFile:jl};self.onmessage=async e=>{let t=e.data;if(!t||t.channel!=="rpc"||!t.content){console.warn("[Worker] Invalid message format",{valueType:t===null?"null":Array.isArray(t)?"array":typeof t,hasRpcChannel:t?.channel==="rpc",hasContent:!!t?.content});return}let{kind:n,messageId:r,targetMethod:o,payload:i}=t.content;if(n!=="invoke")return;if(typeof r!="string"||r.length===0||r.length>256){console.warn("[Worker] Invalid RPC correlation ID");return}let s=typeof o=="string"&&Object.prototype.hasOwnProperty.call(Ai,o)?Ai[o]:void 0;if(typeof s!="function"){self.postMessage({channel:"rpc",content:{kind:"response",messageId:r,success:!1,errorMessage:`Unknown method: ${typeof o=="string"?o.slice(0,256):""}`}});return}if(!Array.isArray(i)){self.postMessage({channel:"rpc",content:{kind:"response",messageId:r,success:!1,errorMessage:"Worker RPC payload must be an array"}});return}try{Qa(o);let a=await s(...i),d={channel:"rpc",content:{kind:"response",messageId:r,success:!0,data:a}};if(o==="exportDatabase"&&a instanceof Uint8Array){let c=a.byteOffset===0&&a.byteLength===a.buffer.byteLength&&a.buffer instanceof ArrayBuffer?a:a.slice();d.content.data=c,self.postMessage(d,[c.buffer])}else self.postMessage(d)}catch(a){let d=Ne(a);console.error("[Worker] Method error:",o,d);let c;try{c=si(a)}catch{}self.postMessage({channel:"rpc",content:{kind:"response",messageId:r,success:!1,errorMessage:d,...c?{error:c}:{}}})}};})();