diff --git a/frontend/core/local-db/src/jsMain/kotlin/at/mocode/frontend/core/localdb/DatabaseDriverFactory.js.kt b/frontend/core/local-db/src/jsMain/kotlin/at/mocode/frontend/core/localdb/DatabaseDriverFactory.js.kt index e03f3732..02ecca33 100644 --- a/frontend/core/local-db/src/jsMain/kotlin/at/mocode/frontend/core/localdb/DatabaseDriverFactory.js.kt +++ b/frontend/core/local-db/src/jsMain/kotlin/at/mocode/frontend/core/localdb/DatabaseDriverFactory.js.kt @@ -3,15 +3,16 @@ package at.mocode.frontend.core.localdb import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.worker.WebWorkerDriver import org.w3c.dom.Worker +import org.w3c.dom.WorkerOptions +import org.w3c.dom.WorkerType +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") actual class DatabaseDriverFactory { actual suspend fun createDriver(): SqlDriver { - // Load the worker script. - // We use a simple string path instead of `new URL(..., import.meta.url)` to prevent Webpack - // from trying to resolve/bundle this file at build time. - // The file 'sqlite.worker.js' is copied to the root of the distribution by the Gradle build script. - val worker = Worker("sqlite.worker.js") - + // Wir nutzen eine Helper-Funktion, um den Worker zu erstellen. + // Dies ermöglicht uns, 'new URL(..., import.meta.url)' in JS zu verwenden, + // was Webpack dazu bringt, den Pfad korrekt aufzulösen. + val worker = createWorker() val driver = WebWorkerDriver(worker) // Initialize schema asynchronously @@ -20,3 +21,10 @@ actual class DatabaseDriverFactory { return driver } } + +// Helper function to create the worker using proper URL resolution +private fun createWorker(): Worker { + return js(""" + new Worker(new URL('sqlite.worker.js', import.meta.url), { type: 'module' }) + """) +} diff --git a/frontend/core/local-db/src/jsMain/resources/sqlite.worker.js b/frontend/core/local-db/src/jsMain/resources/sqlite.worker.js index 22e644d3..36d16a62 100644 --- a/frontend/core/local-db/src/jsMain/resources/sqlite.worker.js +++ b/frontend/core/local-db/src/jsMain/resources/sqlite.worker.js @@ -1,10 +1,14 @@ import sqlite3InitModule from '@sqlite.org/sqlite-wasm'; +console.log("Worker: sqlite.worker.js loaded. Starting initialization..."); + // Minimal worker protocol compatible with SQLDelight's `web-worker-driver`. // Mirrors the message format used by SQLDelight's `sqljs.worker.js` implementation. function runWorker({ driver }) { + console.log("Worker: runWorker called"); let db = null; const open = (name) => { + console.log("Worker: Opening database", name); db = driver.open(name); }; @@ -41,28 +45,59 @@ function runWorker({ driver }) { throw new Error(`Unsupported action: ${data && data.action}`); } } catch (err) { + console.error("Worker: Error processing message", err); return postMessage({ id: data && data.id, error: err?.message ?? String(err) }); } }; } -sqlite3InitModule({ - print: console.log, - printErr: console.error, -}).then((sqlite3) => { - const opfsAvailable = 'opfs' in sqlite3; +// Error handling wrapper +self.onerror = function(event) { + console.error("Error in Web Worker (onerror):", event.message, event.filename, event.lineno); + // Optionally, send the error back to the main thread + self.postMessage({ type: 'error', message: event.message, filename: event.filename, lineno: event.lineno }); +}; - runWorker({ - driver: { - open: (name) => { - if (opfsAvailable) { - console.log("Initialisiere persistente OPFS Datenbank: " + name); - return new sqlite3.oo1.OpfsDb(name); - } else { - console.warn("OPFS nicht verfügbar, Fallback auf In-Memory"); - return new sqlite3.oo1.DB(name); +// Manually fetch the WASM file to bypass Webpack/sqlite-wasm loading issues +async function init() { + try { + console.log("Worker: Fetching sqlite3.wasm manually..."); + const response = await fetch('/sqlite3.wasm'); + if (!response.ok) { + throw new Error(`Failed to fetch sqlite3.wasm: ${response.status} ${response.statusText}`); + } + const wasmBinary = await response.arrayBuffer(); + console.log("Worker: sqlite3.wasm fetched successfully, size:", wasmBinary.byteLength); + + console.log("Worker: Calling sqlite3InitModule with wasmBinary..."); + const sqlite3 = await sqlite3InitModule({ + print: console.log, + printErr: console.error, + wasmBinary: wasmBinary // Provide the binary directly! + }); + + console.log("Worker: sqlite3InitModule resolved successfully"); + const opfsAvailable = 'opfs' in sqlite3; + console.log("Worker: OPFS available:", opfsAvailable); + + runWorker({ + driver: { + open: (name) => { + if (opfsAvailable) { + console.log("Initialisiere persistente OPFS Datenbank: " + name); + return new sqlite3.oo1.OpfsDb(name); + } else { + console.warn("OPFS nicht verfügbar, Fallback auf In-Memory"); + return new sqlite3.oo1.DB(name); + } } } - } - }); -}); + }); + + } catch (e) { + console.error("Database initialization error in worker:", e); + self.postMessage({ type: 'error', message: 'Database initialization failed: ' + e.message }); + } +} + +init(); diff --git a/frontend/core/local-db/src/wasmJsMain/resources/sqlite.worker.js b/frontend/core/local-db/src/wasmJsMain/resources/sqlite.worker.js index 464046e7..d9ccb0bd 100644 --- a/frontend/core/local-db/src/wasmJsMain/resources/sqlite.worker.js +++ b/frontend/core/local-db/src/wasmJsMain/resources/sqlite.worker.js @@ -44,23 +44,40 @@ function runWorker({ driver }) { }; } -sqlite3InitModule({ - print: console.log, - printErr: console.error, -}).then((sqlite3) => { - const opfsAvailable = 'opfs' in sqlite3; +// Error handling wrapper +self.onerror = function(event) { + console.error("Error in Web Worker:", event.message, event.filename, event.lineno); + // Optionally, send the error back to the main thread + self.postMessage({ type: 'error', message: event.message, filename: event.filename, lineno: event.lineno }); +}; - runWorker({ - driver: { - open: (name) => { - if (opfsAvailable) { - console.log("Initialisiere persistente OPFS Datenbank: " + name); - return new sqlite3.oo1.OpfsDb(name); - } else { - console.warn("OPFS nicht verfügbar, Fallback auf In-Memory"); - return new sqlite3.oo1.DB(name); +try { + sqlite3InitModule({ + print: console.log, + printErr: console.error, + }).then((sqlite3) => { + try { + const opfsAvailable = 'opfs' in sqlite3; + + runWorker({ + driver: { + open: (name) => { + if (opfsAvailable) { + console.log("Initialisiere persistente OPFS Datenbank: " + name); + return new sqlite3.oo1.OpfsDb(name); + } else { + console.warn("OPFS nicht verfügbar, Fallback auf In-Memory"); + return new sqlite3.oo1.DB(name); + } + } } - } + }); + } catch (e) { + console.error("Database initialization error in worker (inner):", e); + self.postMessage({ type: 'error', message: 'Database initialization failed (inner): ' + e.message }); } }); -}); +} catch (e) { + console.error("Database initialization error in worker (outer):", e); + self.postMessage({ type: 'error', message: 'Database initialization failed (outer): ' + e.message }); +} diff --git a/frontend/features/ping-feature/src/commonMain/kotlin/at/mocode/ping/feature/presentation/PingViewModel.kt b/frontend/features/ping-feature/src/commonMain/kotlin/at/mocode/ping/feature/presentation/PingViewModel.kt index f5ea55d0..78ad8d22 100644 --- a/frontend/features/ping-feature/src/commonMain/kotlin/at/mocode/ping/feature/presentation/PingViewModel.kt +++ b/frontend/features/ping-feature/src/commonMain/kotlin/at/mocode/ping/feature/presentation/PingViewModel.kt @@ -50,7 +50,7 @@ class PingViewModel( fun performSimplePing() { viewModelScope.launch { - uiState = uiState.copy(isLoading = true) + uiState = uiState.copy(isLoading = true, errorMessage = null) addLog("SimplePing", "Sending request...") try { val response = apiClient.simplePing() @@ -60,7 +60,8 @@ class PingViewModel( ) addLog("SimplePing", "Success: ${response.status} from ${response.service}") } catch (e: Exception) { - uiState = uiState.copy(isLoading = false) + val msg = "Simple ping failed: ${e.message}" + uiState = uiState.copy(isLoading = false, errorMessage = msg) addLog("SimplePing", "Failed: ${e.message}", isError = true) } } @@ -68,7 +69,7 @@ class PingViewModel( fun performEnhancedPing(simulate: Boolean = false) { viewModelScope.launch { - uiState = uiState.copy(isLoading = true) + uiState = uiState.copy(isLoading = true, errorMessage = null) addLog("EnhancedPing", "Sending request (simulate=$simulate)...") try { val response = apiClient.enhancedPing(simulate) @@ -78,7 +79,8 @@ class PingViewModel( ) addLog("EnhancedPing", "Success: CB=${response.circuitBreakerState}, Time=${response.responseTime}ms") } catch (e: Exception) { - uiState = uiState.copy(isLoading = false) + val msg = "Enhanced ping failed: ${e.message}" + uiState = uiState.copy(isLoading = false, errorMessage = msg) addLog("EnhancedPing", "Failed: ${e.message}", isError = true) } } @@ -86,7 +88,7 @@ class PingViewModel( fun performHealthCheck() { viewModelScope.launch { - uiState = uiState.copy(isLoading = true) + uiState = uiState.copy(isLoading = true, errorMessage = null) addLog("HealthCheck", "Checking system health...") try { val response = apiClient.healthCheck() @@ -96,7 +98,8 @@ class PingViewModel( ) addLog("HealthCheck", "Status: ${response.status}, Healthy: ${response.healthy}") } catch (e: Exception) { - uiState = uiState.copy(isLoading = false) + val msg = "Health check failed: ${e.message}" + uiState = uiState.copy(isLoading = false, errorMessage = msg) addLog("HealthCheck", "Failed: ${e.message}", isError = true) } } @@ -104,7 +107,7 @@ class PingViewModel( fun performSecurePing() { viewModelScope.launch { - uiState = uiState.copy(isLoading = true) + uiState = uiState.copy(isLoading = true, errorMessage = null) addLog("SecurePing", "Sending authenticated request...") try { val response = apiClient.securePing() @@ -114,7 +117,8 @@ class PingViewModel( ) addLog("SecurePing", "Success: Authorized access granted.") } catch (e: Exception) { - uiState = uiState.copy(isLoading = false) + val msg = "Secure ping failed: ${e.message}" + uiState = uiState.copy(isLoading = false, errorMessage = msg) addLog("SecurePing", "Access Denied/Error: ${e.message}", isError = true) } } @@ -122,7 +126,7 @@ class PingViewModel( fun triggerSync() { viewModelScope.launch { - uiState = uiState.copy(isSyncing = true) + uiState = uiState.copy(isSyncing = true, errorMessage = null) addLog("Sync", "Starting delta sync...") try { syncService.syncPings() @@ -133,7 +137,8 @@ class PingViewModel( ) addLog("Sync", "Sync completed successfully.") } catch (e: Exception) { - uiState = uiState.copy(isSyncing = false) + val msg = "Sync failed: ${e.message}" + uiState = uiState.copy(isSyncing = false, errorMessage = msg) addLog("Sync", "Sync failed: ${e.message}", isError = true) } } diff --git a/frontend/shells/meldestelle-portal/build.gradle.kts b/frontend/shells/meldestelle-portal/build.gradle.kts index 4b16773b..f34482c8 100644 --- a/frontend/shells/meldestelle-portal/build.gradle.kts +++ b/frontend/shells/meldestelle-portal/build.gradle.kts @@ -110,6 +110,8 @@ kotlin { jsMain.dependencies { implementation(compose.html.core) + // Benötigt für custom webpack config (wasm.js) + implementation(devNpm("copy-webpack-plugin", "11.0.0")) } /* @@ -138,27 +140,100 @@ kotlin { // relative to the Kotlin JS package folder (root build dir). We therefore copy the worker into // that folder before webpack runs. -val copySqliteWorkerJs by tasks.registering(Copy::class) { +// HACK: Overwrite sqlite3.wasm in node_modules with a dummy JS file to fool Webpack +val patchSqliteWasmInNodeModules by tasks.registering(Copy::class) { + dependsOn(rootProject.tasks.named("kotlinNpmInstall")) val localDb = project(":frontend:core:local-db") dependsOn(localDb.tasks.named("jsProcessResources")) + // We take our dummy.js + from(localDb.layout.buildDirectory.file("processedResources/js/main/dummy.js")) { + rename { "sqlite3.wasm" } // Rename it to sqlite3.wasm + } + + // And copy it OVER the original wasm file in node_modules + into(rootProject.layout.buildDirectory.dir("js/node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm")) + + // Force overwrite + duplicatesStrategy = DuplicatesStrategy.INCLUDE +} + +val copySqliteAssetsToWebpackSource by tasks.registering(Copy::class) { + val localDb = project(":frontend:core:local-db") + dependsOn(localDb.tasks.named("jsProcessResources"), rootProject.tasks.named("kotlinNpmInstall")) + + // Explicit dependency on the patch task to ensure we copy the REAL wasm file before it gets patched? + // NO! We want to copy the REAL wasm file to the output, but PATCH the one in node_modules. + // So we must copy the real one BEFORE patching. + // But wait, copySqliteAssetsToWebpackSource copies FROM node_modules. + // If we patch node_modules first, we copy the dummy file! + + // So: copySqliteAssetsToWebpackSource must run BEFORE patchSqliteWasmInNodeModules? + // Or we copy from a different source (e.g. the original npm package cache? No access). + + // Better: We copy the real wasm file from node_modules to a temporary location FIRST, + // then patch node_modules, then copy from temp to output. + + // Actually, we can just copy from node_modules BEFORE the patch task runs. + // But Gradle task ordering is tricky. + + // Let's change the source of the copy. We can't easily access the original npm package. + // But we know that `kotlinNpmInstall` restores the original files. + + // So the order must be: + // 1. kotlinNpmInstall (restores original sqlite3.wasm) + // 2. copySqliteAssetsToWebpackSource (copies original sqlite3.wasm to output) + // 3. patchSqliteWasmInNodeModules (overwrites sqlite3.wasm with dummy.js) + // 4. webpack (uses dummy.js) + + mustRunAfter(rootProject.tasks.named("kotlinNpmInstall")) + from(localDb.layout.buildDirectory.file("processedResources/js/main/sqlite.worker.js")) + from(rootProject.layout.buildDirectory.file("js/node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3.wasm")) // Root build directory where Kotlin JS packages are assembled. - // Use a concrete path (instead of a Provider) so the Copy task always materializes the directory. - // The package name is constructed from the project path: Meldestelle-frontend-shells-meldestelle-portal - // Note: We use rootProject.layout.buildDirectory because Kotlin JS plugin puts packages in root build dir. + // This is one of the directories served by webpack-dev-server for static content. into(rootProject.layout.buildDirectory.dir("js/packages/${rootProject.name}-frontend-shells-meldestelle-portal/kotlin")) } -// Ensure the worker is present for the production bundle. -tasks.named("jsBrowserProductionWebpack") { - dependsOn(copySqliteWorkerJs) +// Additional task to copy the worker and its wasm dependency to the distribution folder (for production build) +val copySqliteAssetsToDist by tasks.registering(Copy::class) { + val localDb = project(":frontend:core:local-db") + dependsOn(localDb.tasks.named("jsProcessResources"), rootProject.tasks.named("kotlinNpmInstall")) + + // Same logic here: copy before patch + mustRunAfter(rootProject.tasks.named("kotlinNpmInstall")) + + from(localDb.layout.buildDirectory.file("processedResources/js/main/sqlite.worker.js")) + from(rootProject.layout.buildDirectory.file("js/node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3.wasm")) + + // Copy to the distribution directory where index.html resides + into(layout.buildDirectory.dir("dist/js/productionExecutable")) } -// Ensure the worker is present for the development bundle. +// Ensure the assets are present for the production bundle. +tasks.named("jsBrowserProductionWebpack") { + dependsOn(copySqliteAssetsToWebpackSource) + dependsOn(patchSqliteWasmInNodeModules) + + // Enforce order: Copy real assets first, then patch node_modules + // patchSqliteWasmInNodeModules must run AFTER copySqliteAssetsToWebpackSource + // But wait, dependsOn doesn't guarantee order. + // We need to configure the tasks themselves. + + finalizedBy(copySqliteAssetsToDist) +} + +// Configure task ordering +patchSqliteWasmInNodeModules { + mustRunAfter(copySqliteAssetsToWebpackSource) + // Removed circular dependency: mustRunAfter(copySqliteAssetsToDist) +} + +// Ensure the assets are present for the development bundle. tasks.named("jsBrowserDevelopmentWebpack") { - dependsOn(copySqliteWorkerJs) + dependsOn(copySqliteAssetsToWebpackSource) + dependsOn(patchSqliteWasmInNodeModules) } // KMP Compile-Optionen diff --git a/frontend/shells/meldestelle-portal/src/jsMain/resources/dummy.js b/frontend/shells/meldestelle-portal/src/jsMain/resources/dummy.js new file mode 100644 index 00000000..1ad26507 --- /dev/null +++ b/frontend/shells/meldestelle-portal/src/jsMain/resources/dummy.js @@ -0,0 +1,14 @@ +// This is a dummy file to satisfy Webpack's requirement for sqlite3.wasm and other modules. +// It mimics the structure of the sqlite3-wasm module to prevent build errors. + +// The worker code imports it like this: +// import sqlite3InitModule from '@sqlite.org/sqlite-wasm'; + +// So we need a default export that is a function. +// This function should mimic the behavior of sqlite3InitModule, which returns a Promise. +export default function dummySqlite3InitModule() { + // Since we are manually loading the WASM binary in the worker, this dummy module + // is primarily here to satisfy Webpack's resolution and prevent errors. + // It doesn't need to actually load the WASM. + return Promise.resolve({}); +}; diff --git a/frontend/shells/meldestelle-portal/webpack.config.d/ignore-sqlite-wasm.js b/frontend/shells/meldestelle-portal/webpack.config.d/ignore-sqlite-wasm.js new file mode 100644 index 00000000..7ab3877b --- /dev/null +++ b/frontend/shells/meldestelle-portal/webpack.config.d/ignore-sqlite-wasm.js @@ -0,0 +1,104 @@ +// This file contains Webpack configuration adjustments for WebAssembly modules, +// specifically to handle `skiko.wasm` and `sqlite3.wasm` correctly. + +var pathModule; +try { + pathModule = path; +} catch (e) { + pathModule = require('path'); +} + +var webpackModule; +try { + webpackModule = webpack; +} catch (e) { + webpackModule = require('webpack'); +} + +// 1. Enable WebAssembly experiments in Webpack 5 +config.experiments = config.experiments || {}; +config.experiments.asyncWebAssembly = true; + +config.module = config.module || {}; +config.module.rules = config.module.rules || []; + +// 2. Add a rule to correctly handle .wasm files (like skiko.wasm) as WebAssembly modules +config.module.rules.push({ + test: /\.wasm$/, + type: 'webassembly/async' +}); + +// 3. NormalModuleReplacementPlugin to redirect 'sqlite3.wasm' AND other internal sqlite-wasm modules to our dummy JS file. +// This is needed because the `sqlite-wasm` library tries to `require` these files in a Webpack environment. +// We want these `require` calls to return an empty JS object (from dummy.js) instead of failing. +// Our worker will manually fetch the real sqlite3.wasm. + +const dummyPath = pathModule.resolve(__dirname, "../../../../frontend/shells/meldestelle-portal/build/processedResources/js/main/dummy.js"); + +// Redirect sqlite3.wasm +config.plugins.push( + new webpackModule.NormalModuleReplacementPlugin( + /sqlite3\.wasm$/, + dummyPath + ) +); + +// Redirect other internal sqlite-wasm modules that might be causing issues +// The error log showed: Can't resolve './sqlite-wasm/jswasm/sqlite3.mjs' and 'sqlite3-worker1-promiser.mjs' +// We redirect them to dummy.js as well, assuming we don't need them for our manual loading approach. +// Be careful not to redirect the main entry point if it's needed. +// The errors seem to come from inside the node_modules package trying to resolve relative paths. + +// Let's try to be more specific. If these are optional dependencies or part of the node-loading logic, +// replacing them with dummy.js should be fine. +config.plugins.push( + new webpackModule.NormalModuleReplacementPlugin( + /sqlite3\.mjs$/, + function(resource) { + // Only replace if it's inside the sqlite-wasm package structure we want to avoid + if (resource.context.includes('@sqlite.org/sqlite-wasm')) { + resource.request = dummyPath; + } + } + ) +); + +config.plugins.push( + new webpackModule.NormalModuleReplacementPlugin( + /sqlite3-worker1-promiser\.mjs$/, + dummyPath + ) +); + + +// 4. Handle WASI imports for skiko.wasm (env, wasi_snapshot_preview1) +// Webpack needs to know how to resolve these "magic" imports. +// We can treat them as externals or empty modules. +// Since we are in a browser environment, these are often provided by the runtime or polyfilled. +// Mapping them to false tells Webpack to ignore them (empty module). + +config.resolve = config.resolve || {}; +config.resolve.fallback = config.resolve.fallback || {}; + +// Fallbacks for Node.js core modules that might be required by libraries +config.resolve.fallback.fs = false; +config.resolve.fallback.path = false; +config.resolve.fallback.crypto = false; + +// Ignore WASI imports +config.ignoreWarnings = config.ignoreWarnings || []; +config.ignoreWarnings.push(/Critical dependency: the request of a dependency is an expression/); + +// Use externals to handle WASI imports if fallback doesn't work +config.externals = config.externals || {}; +// config.externals['env'] = 'env'; // This might expect a global 'env' variable +// config.externals['wasi_snapshot_preview1'] = 'wasi_snapshot_preview1'; + +// Better approach for WASI in Webpack 5 with asyncWebAssembly: +// Webpack should handle this if we don't interfere. +// The error "Can't resolve 'env'" suggests it's looking for a module named 'env'. +// We can provide a dummy module for these. + +config.resolve.alias = config.resolve.alias || {}; +config.resolve.alias['env'] = dummyPath; +config.resolve.alias['wasi_snapshot_preview1'] = dummyPath; diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 69db4ec8..d25e6c6b 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -95,6 +95,27 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + "@sqlite.org/sqlite-wasm@3.51.1-build2": version "3.51.1-build2" resolved "https://registry.yarnpkg.com/@sqlite.org/sqlite-wasm/-/sqlite-wasm-3.51.1-build2.tgz#822497fdd05cbee3b1e8209aa46ffe1bafc70dbb" @@ -667,6 +688,18 @@ cookie@0.7.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== +copy-webpack-plugin@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== + dependencies: + fast-glob "^3.2.11" + glob-parent "^6.0.1" + globby "^13.1.1" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -733,6 +766,13 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + dns-packet@^5.2.2: version "5.6.1" resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" @@ -896,6 +936,17 @@ fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-glob@^3.2.11, fast-glob@^3.3.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + fast-uri@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" @@ -906,6 +957,13 @@ fastest-levenshtein@^1.0.12: resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== +fastq@^1.6.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" + integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== + dependencies: + reusify "^1.0.4" + faye-websocket@^0.11.3: version "0.11.4" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" @@ -1000,13 +1058,20 @@ get-proto@^1.0.1: dunder-proto "^1.0.1" es-object-atoms "^1.0.0" -glob-parent@~5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob-to-regex.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/glob-to-regex.js/-/glob-to-regex.js-1.0.1.tgz#f71cc9cb8441471a9318626160bc8a35e1306b21" @@ -1017,6 +1082,17 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== +globby@^13.1.1: + version "13.2.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" + integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.3.0" + ignore "^5.2.4" + merge2 "^1.4.1" + slash "^4.0.0" + gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" @@ -1129,6 +1205,11 @@ iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +ignore@^5.2.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + import-local@^3.0.2: version "3.2.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" @@ -1186,7 +1267,7 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -1327,12 +1408,17 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^4.0.2: +micromatch@^4.0.2, micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -1507,6 +1593,11 @@ path-to-regexp@0.1.12: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -1544,6 +1635,11 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -1638,11 +1734,23 @@ retry@^0.13.1: resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + run-applescript@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.1.0.tgz#2e9e54c4664ec3106c5b5630e249d3d6595c4911" integrity sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q== +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -1700,7 +1808,7 @@ send@0.19.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.2: +serialize-javascript@^6.0.0, serialize-javascript@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== @@ -1804,6 +1912,11 @@ side-channel@^1.0.6: side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + sockjs@^0.3.24: version "0.3.24" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce"