diff --git a/resources/electron/.prettierignore b/resources/electron/.prettierignore new file mode 100644 index 00000000..52a51424 --- /dev/null +++ b/resources/electron/.prettierignore @@ -0,0 +1,5 @@ +out +electron-plugin/dist +package-lock.json +eslint.config.js +.prettierrc.json diff --git a/resources/electron/.prettierrc b/resources/electron/.prettierrc new file mode 100644 index 00000000..091b9ef0 --- /dev/null +++ b/resources/electron/.prettierrc @@ -0,0 +1,8 @@ +{ + "plugins": ["prettier-plugin-organize-imports"], + "trailingComma": "all", + "tabWidth": 4, + "semi": true, + "singleQuote": true, + "printWidth": 120 +} diff --git a/resources/electron/build/notarize.js b/resources/electron/build/notarize.js index 8f2b6ccd..74f7b493 100644 --- a/resources/electron/build/notarize.js +++ b/resources/electron/build/notarize.js @@ -7,18 +7,26 @@ export default async (context) => { // And the current build target is macOS if (context.packager.platform.name !== 'mac') return; - console.log('aftersign hook triggered, start to notarize app.') - - if (!('NATIVEPHP_APPLE_ID' in process.env && 'NATIVEPHP_APPLE_ID_PASS' in process.env && 'NATIVEPHP_APPLE_TEAM_ID' in process.env)) { - console.warn('skipping notarizing, NATIVEPHP_APPLE_ID, NATIVEPHP_APPLE_ID_PASS and NATIVEPHP_APPLE_TEAM_ID env variables must be set.') - return + console.log('aftersign hook triggered, start to notarize app.'); + + if ( + !( + 'NATIVEPHP_APPLE_ID' in process.env && + 'NATIVEPHP_APPLE_ID_PASS' in process.env && + 'NATIVEPHP_APPLE_TEAM_ID' in process.env + ) + ) { + console.warn( + 'skipping notarizing, NATIVEPHP_APPLE_ID, NATIVEPHP_APPLE_ID_PASS and NATIVEPHP_APPLE_TEAM_ID env variables must be set.', + ); + return; } const appId = process.env.NATIVEPHP_APP_ID; - const {appOutDir} = context + const { appOutDir } = context; - const appName = context.packager.appInfo.productFilename + const appName = context.packager.appInfo.productFilename; try { await notarize({ @@ -28,10 +36,10 @@ export default async (context) => { appleIdPassword: process.env.NATIVEPHP_APPLE_ID_PASS, teamId: process.env.NATIVEPHP_APPLE_TEAM_ID, tool: 'notarytool', - }) + }); } catch (error) { - console.error(error) + console.error(error); } - console.log(`done notarizing ${appId}.`) -} + console.log(`done notarizing ${appId}.`); +}; diff --git a/resources/electron/electron-builder.mjs b/resources/electron/electron-builder.mjs index 8cb1558c..af28e71e 100644 --- a/resources/electron/electron-builder.mjs +++ b/resources/electron/electron-builder.mjs @@ -42,7 +42,7 @@ let updaterConfig = {}; try { updaterConfig = process.env.NATIVEPHP_UPDATER_CONFIG; updaterConfig = JSON.parse(updaterConfig); -} catch (e) { +} catch { updaterConfig = {}; } @@ -69,7 +69,7 @@ export default { beforePack: async (context) => { let arch = { 1: 'x64', - 3: 'arm64' + 3: 'arm64', }[context.arch]; if (arch === undefined) { @@ -83,14 +83,16 @@ export default { afterSign: 'build/notarize.js', win: { executableName: fileName, - ...(azurePublisherName && azureEndpoint && azureCertificateProfileName && azureCodeSigningAccountName ? { - azureSignOptions: { - publisherName: azurePublisherName, - endpoint: azureEndpoint, - certificateProfileName: azureCertificateProfileName, - codeSigningAccountName: azureCodeSigningAccountName - } - } : {}), + ...(azurePublisherName && azureEndpoint && azureCertificateProfileName && azureCodeSigningAccountName + ? { + azureSignOptions: { + publisherName: azurePublisherName, + endpoint: azureEndpoint, + certificateProfileName: azureCertificateProfileName, + codeSigningAccountName: azureCodeSigningAccountName, + }, + } + : {}), }, nsis: { artifactName: appName + '-${version}-setup.${ext}', @@ -106,14 +108,10 @@ export default { entitlementsInherit: 'build/entitlements.mac.plist', artifactName: appName + '-${version}-${arch}.${ext}', extendInfo: { - NSCameraUsageDescription: - "Application requests access to the device's camera.", - NSMicrophoneUsageDescription: - "Application requests access to the device's microphone.", - NSDocumentsFolderUsageDescription: - "Application requests access to the user's Documents folder.", - NSDownloadsFolderUsageDescription: - "Application requests access to the user's Downloads folder.", + NSCameraUsageDescription: "Application requests access to the device's camera.", + NSMicrophoneUsageDescription: "Application requests access to the device's microphone.", + NSDocumentsFolderUsageDescription: "Application requests access to the user's Documents folder.", + NSDownloadsFolderUsageDescription: "Application requests access to the user's Downloads folder.", }, }, dmg: { @@ -138,22 +136,15 @@ export default { { from: process.env.NATIVEPHP_BUILD_PATH, to: 'build', - filter: [ - '**/*', - '!{.git}', - ] - } + filter: ['**/*', '!{.git}'], + }, ], extraFiles: [ { from: join(process.env.APP_PATH, 'extras'), to: 'extras', - filter: [ - '**/*' - ] - } + filter: ['**/*'], + }, ], - ...updaterEnabled - ? { publish: updaterConfig } - : {} + ...(updaterEnabled ? { publish: updaterConfig } : {}), }; diff --git a/resources/electron/electron-plugin/.stylelintrc b/resources/electron/electron-plugin/.stylelintrc index fcc73d56..727392ed 100644 --- a/resources/electron/electron-plugin/.stylelintrc +++ b/resources/electron/electron-plugin/.stylelintrc @@ -1,18 +1,15 @@ { - "extends": [ - "stylelint-config-recommended", - "stylelint-config-sass-guidelines" - ], - "overrides": [ - { - "files": ["**/*.scss"], - "customSyntax": "postcss-scss" + "extends": ["stylelint-config-recommended", "stylelint-config-sass-guidelines"], + "overrides": [ + { + "files": ["**/*.scss"], + "customSyntax": "postcss-scss" + } + ], + "rules": { + "function-parentheses-space-inside": null, + "no-descending-specificity": null, + "max-nesting-depth": 2, + "selector-max-id": 1 } - ], - "rules": { - "function-parentheses-space-inside": null, - "no-descending-specificity": null, - "max-nesting-depth": 2, - "selector-max-id": 1 - } } diff --git a/resources/electron/electron-plugin/babel.config.js b/resources/electron/electron-plugin/babel.config.js index 8dc63557..a4845bef 100644 --- a/resources/electron/electron-plugin/babel.config.js +++ b/resources/electron/electron-plugin/babel.config.js @@ -1,6 +1,3 @@ export default { - presets: [ - ['@babel/preset-env', {targets: {node: 'current'}}], - '@babel/preset-typescript', - ], + presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], }; diff --git a/resources/electron/electron-plugin/src/index.ts b/resources/electron/electron-plugin/src/index.ts index 7eca5b0b..3c92d05e 100644 --- a/resources/electron/electron-plugin/src/index.ts +++ b/resources/electron/electron-plugin/src/index.ts @@ -1,180 +1,168 @@ -import CrossProcessExports from "electron"; -import { app, session, powerMonitor } from "electron"; -import { ChildProcessWithoutNullStreams } from "child_process"; -import { initialize } from "@electron/remote/main/index.js"; -import state from "./server/state.js"; -import { electronApp, optimizer } from "@electron-toolkit/utils"; +import { electronApp, optimizer } from '@electron-toolkit/utils'; +import { initialize } from '@electron/remote/main/index.js'; +import { ChildProcessWithoutNullStreams } from 'child_process'; +import CrossProcessExports, { app, powerMonitor, session } from 'electron'; +import killSync from 'kill-sync'; +import { resolve } from 'path'; +import ps from 'ps-node'; +import { stopAllProcesses } from './server/api/childProcess.js'; import { - retrieveNativePHPConfig, - retrievePhpIniSettings, - runScheduler, - killScheduler, - startAPI, - startPhpApp, -} from "./server/index.js"; -import { notifyLaravel } from "./server/utils.js"; -import { resolve } from "path"; -import { stopAllProcesses } from "./server/api/childProcess.js"; -import ps from "ps-node"; -import killSync from "kill-sync"; + killScheduler, + retrieveNativePHPConfig, + retrievePhpIniSettings, + runScheduler, + startAPI, + startPhpApp, +} from './server/index.js'; +import state from './server/state.js'; +import { notifyLaravel } from './server/utils.js'; // Workaround for CommonJS module import electronUpdater from 'electron-updater'; const { autoUpdater } = electronUpdater; class NativePHP { - processes: ChildProcessWithoutNullStreams[] = []; - mainWindow = null; - schedulerInterval = undefined; - - public bootstrap( - app: CrossProcessExports.App, - icon: string, - phpBinary: string, - cert: string, - appPath: string - ) { - initialize(); - - state.icon = icon; - state.php = phpBinary; - state.caCert = cert; - state.appPath = appPath; - - this.bootstrapApp(app); - this.addEventListeners(app); - } - - private addEventListeners(app: Electron.CrossProcessExports.App) { - app.on("open-url", (event, url) => { - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\App\\OpenedFromURL", - payload: [url], - }); - }); - - app.on("open-file", (event, path) => { - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\App\\OpenFile", - payload: [path], - }); - }); - - app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - app.quit(); - } - }); - - app.on("before-quit", () => { - if (this.schedulerInterval) { - clearInterval(this.schedulerInterval); - } - - // close all child processes from the app - stopAllProcesses(); - - this.killChildProcesses(); - }); - - // Default open or close DevTools by F12 in development - // and ignore CommandOrControl + R in production. - // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils - app.on("browser-window-created", (_, window) => { - optimizer.watchWindowShortcuts(window); - }); - - app.on("activate", function (event, hasVisibleWindows) { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (!hasVisibleWindows) { - notifyLaravel("booted"); - } - - event.preventDefault(); - }); - } - - private async bootstrapApp(app: Electron.CrossProcessExports.App) { - await app.whenReady(); - - const config = await this.loadConfig(); - - this.setDockIcon(); - this.setAppUserModelId(config); - this.setDeepLinkHandler(config); - this.startAutoUpdater(config); - - await this.startElectronApi(); - - state.phpIni = await this.loadPhpIni(); - - await this.startPhpApp(); - this.startScheduler(); - - powerMonitor.on("suspend", () => { - this.stopScheduler(); - }); - - powerMonitor.on("resume", () => { - this.stopScheduler(); - this.startScheduler(); - }); - - const filter = { - urls: [`http://127.0.0.1:${state.phpPort}/*`] - }; - - session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => { - details.requestHeaders['X-NativePHP-Secret'] = state.randomSecret; - - callback({ requestHeaders: details.requestHeaders }); - }); - - await notifyLaravel("booted"); - } - - private async loadConfig() { - let config = {}; - - try { - const result = await retrieveNativePHPConfig(); - - config = JSON.parse(result.stdout); - } catch (error) { - console.error(error); + processes: ChildProcessWithoutNullStreams[] = []; + mainWindow = null; + schedulerInterval = undefined; + + public bootstrap(app: CrossProcessExports.App, icon: string, phpBinary: string, cert: string, appPath: string) { + initialize(); + + state.icon = icon; + state.php = phpBinary; + state.caCert = cert; + state.appPath = appPath; + + this.bootstrapApp(app); + this.addEventListeners(app); } - return config; - } + private addEventListeners(app: Electron.CrossProcessExports.App) { + app.on('open-url', (event, url) => { + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\App\\OpenedFromURL', + payload: [url], + }); + }); + + app.on('open-file', (event, path) => { + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\App\\OpenFile', + payload: [path], + }); + }); + + app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } + }); + + app.on('before-quit', () => { + if (this.schedulerInterval) { + clearInterval(this.schedulerInterval); + } + + // close all child processes from the app + stopAllProcesses(); + + this.killChildProcesses(); + }); + + // Default open or close DevTools by F12 in development + // and ignore CommandOrControl + R in production. + // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils + app.on('browser-window-created', (_, window) => { + optimizer.watchWindowShortcuts(window); + }); + + app.on('activate', function (event, hasVisibleWindows) { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (!hasVisibleWindows) { + notifyLaravel('booted'); + } - private setDockIcon() { - // Only run this on macOS - if ( - process.platform === "darwin" && - process.env.NODE_ENV === "development" - ) { - app.dock.setIcon(state.icon); + event.preventDefault(); + }); } - } - private setAppUserModelId(config) { - electronApp.setAppUserModelId(config?.app_id); - } + private async bootstrapApp(app: Electron.CrossProcessExports.App) { + await app.whenReady(); + + const config = await this.loadConfig(); + + this.setDockIcon(); + this.setAppUserModelId(config); + this.setDeepLinkHandler(config); + this.startAutoUpdater(config); + + await this.startElectronApi(); + + state.phpIni = await this.loadPhpIni(); + + await this.startPhpApp(); + this.startScheduler(); + + powerMonitor.on('suspend', () => { + this.stopScheduler(); + }); + + powerMonitor.on('resume', () => { + this.stopScheduler(); + this.startScheduler(); + }); + + const filter = { + urls: [`http://127.0.0.1:${state.phpPort}/*`], + }; + + session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => { + details.requestHeaders['X-NativePHP-Secret'] = state.randomSecret; + + callback({ requestHeaders: details.requestHeaders }); + }); + + await notifyLaravel('booted'); + } - private setDeepLinkHandler(config) { - const deepLinkProtocol = config?.deeplink_scheme; + private async loadConfig() { + let config = {}; - if (deepLinkProtocol) { - if (process.defaultApp) { - if (process.argv.length >= 2) { - app.setAsDefaultProtocolClient(deepLinkProtocol, process.execPath, [ - resolve(process.argv[1]), - ]); + try { + const result = await retrieveNativePHPConfig(); + + config = JSON.parse(result.stdout); + } catch (error) { + console.error(error); } - } else { - app.setAsDefaultProtocolClient(deepLinkProtocol); - } + + return config; + } + + private setDockIcon() { + // Only run this on macOS + if (process.platform === 'darwin' && process.env.NODE_ENV === 'development') { + app.dock.setIcon(state.icon); + } + } + + private setAppUserModelId(config) { + electronApp.setAppUserModelId(config?.app_id); + } + + private setDeepLinkHandler(config) { + const deepLinkProtocol = config?.deeplink_scheme; + + if (deepLinkProtocol) { + if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient(deepLinkProtocol, process.execPath, [resolve(process.argv[1])]); + } + } else { + app.setAsDefaultProtocolClient(deepLinkProtocol); + } /** * Handle protocol url for windows and linux @@ -183,127 +171,119 @@ class NativePHP { * than the open-url event and Windows requiring additional code in order to * open the contents of the protocol link within the same Electron instance. */ - if (process.platform !== "darwin") { + if (process.platform !== 'darwin') { const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { app.quit(); return; } else { - app.on( - "second-instance", - (event, commandLine, workingDirectory) => { - // Someone tried to run a second instance, we should focus our window. - if (this.mainWindow) { - if (this.mainWindow.isMinimized()) - this.mainWindow.restore(); - this.mainWindow.focus(); - } - - // the commandLine is array of strings in which last element is deep link url - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\App\\OpenedFromURL", - payload: { - url: commandLine[commandLine.length - 1], - }, - }); - }, - ); + app.on('second-instance', (event, commandLine) => { + // Someone tried to run a second instance, we should focus our window. + if (this.mainWindow) { + if (this.mainWindow.isMinimized()) this.mainWindow.restore(); + this.mainWindow.focus(); + } + + // the commandLine is array of strings in which last element is deep link url + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\App\\OpenedFromURL', + payload: { + url: commandLine[commandLine.length - 1], + }, + }); + }); } } } } - private startAutoUpdater(config) { - if (config?.updater?.enabled === true) { - // If a public URL is configured for the current provider, use it for updates - const defaultProvider = config?.updater?.default; - const publicUrl = config?.updater?.providers?.[defaultProvider]?.public_url; - - if (publicUrl) { - autoUpdater.setFeedURL({ - provider: 'generic', - url: publicUrl - }); - } + private startAutoUpdater(config) { + if (config?.updater?.enabled === true) { + // If a public URL is configured for the current provider, use it for updates + const defaultProvider = config?.updater?.default; + const publicUrl = config?.updater?.providers?.[defaultProvider]?.public_url; + + if (publicUrl) { + autoUpdater.setFeedURL({ + provider: 'generic', + url: publicUrl, + }); + } - autoUpdater.checkForUpdatesAndNotify(); + autoUpdater.checkForUpdatesAndNotify(); + } } - } - private async startElectronApi() { - // Start an Express server so that the Electron app can be controlled from PHP via API - const electronApi = await startAPI(); + private async startElectronApi() { + // Start an Express server so that the Electron app can be controlled from PHP via API + const electronApi = await startAPI(); - state.electronApiPort = electronApi.port; + state.electronApiPort = electronApi.port; - console.log("Electron API server started on port", electronApi.port); - } - - private async loadPhpIni() { - let config = {}; - - try { - const result = await retrievePhpIniSettings(); - - config = JSON.parse(result.stdout); - } catch (error) { - console.error(error); + console.log('Electron API server started on port', electronApi.port); } - return config; - } - - private async startPhpApp() { - this.processes.push(await startPhpApp()); - } + private async loadPhpIni() { + let config = {}; + try { + const result = await retrievePhpIniSettings(); - private stopScheduler() { - if (this.schedulerInterval) { - clearInterval(this.schedulerInterval); - this.schedulerInterval = null; - } - killScheduler(); - } - - private startScheduler() { - const now = new Date(); - const delay = - (60 - now.getSeconds()) * 1000 + (1000 - now.getMilliseconds()); + config = JSON.parse(result.stdout); + } catch (error) { + console.error(error); + } - setTimeout(() => { - console.log("Running scheduler..."); + return config; + } - runScheduler(); + private async startPhpApp() { + this.processes.push(await startPhpApp()); + } - this.schedulerInterval = setInterval(() => { - console.log("Running scheduler..."); + private stopScheduler() { + if (this.schedulerInterval) { + clearInterval(this.schedulerInterval); + this.schedulerInterval = null; + } + killScheduler(); + } - runScheduler(); - }, 60 * 1000); - }, delay); - } + private startScheduler() { + const now = new Date(); + const delay = (60 - now.getSeconds()) * 1000 + (1000 - now.getMilliseconds()); - private killChildProcesses() { - this.stopScheduler(); + setTimeout(() => { + console.log('Running scheduler...'); - this.processes - .filter((p) => p !== undefined) - .forEach((process) => { - if (!process || !process.pid) return; - if (process.killed && process.exitCode !== null) return; + runScheduler(); - try { - // @ts-ignore - killSync(process.pid, 'SIGTERM', true); // Kill tree - ps.kill(process.pid); // Sometimes does not kill the subprocess of php server + this.schedulerInterval = setInterval(() => { + console.log('Running scheduler...'); - } catch (err) { - console.error(err); - } + runScheduler(); + }, 60 * 1000); + }, delay); + } - }); - } + private killChildProcesses() { + this.stopScheduler(); + + this.processes + .filter((p) => p !== undefined) + .forEach((process) => { + if (!process || !process.pid) return; + if (process.killed && process.exitCode !== null) return; + + try { + // @ts-ignore + killSync(process.pid, 'SIGTERM', true); // Kill tree + ps.kill(process.pid); // Sometimes does not kill the subprocess of php server + } catch (err) { + console.error(err); + } + }); + } } export default new NativePHP(); diff --git a/resources/electron/electron-plugin/src/libs/menubar/Menubar.ts b/resources/electron/electron-plugin/src/libs/menubar/Menubar.ts index 71fb39d5..8e2cb848 100644 --- a/resources/electron/electron-plugin/src/libs/menubar/Menubar.ts +++ b/resources/electron/electron-plugin/src/libs/menubar/Menubar.ts @@ -1,7 +1,7 @@ +import { BrowserWindow, Tray } from 'electron'; import { EventEmitter } from 'events'; import fs from 'fs'; import path from 'path'; -import { BrowserWindow, Tray } from 'electron'; import Positioner from '../positioner/index.js'; import type { Options } from './types.js'; @@ -14,313 +14,290 @@ import { getWindowPosition } from './util/getWindowPosition.js'; * @noInheritDoc */ export class Menubar extends EventEmitter { - private _app: Electron.App; - private _browserWindow?: BrowserWindow; - private _blurTimeout: NodeJS.Timeout | null = null; // track blur events with timeout - private _isVisible: boolean; // track visibility - private _cachedBounds?: Electron.Rectangle; // _cachedBounds are needed for double-clicked event - private _options: Options; - private _positioner: Positioner | undefined; - private _tray?: Tray; - - constructor(app: Electron.App, options?: Partial) { - super(); - this._app = app; - this._options = cleanOptions(options); - this._isVisible = false; - - if (app.isReady()) { - // See https://github.com/maxogden/menubar/pull/151 - process.nextTick(() => - this.appReady().catch((err) => console.error('menubar: ', err)), - ); - } else { - app.on('ready', () => { - this.appReady().catch((err) => console.error('menubar: ', err)); - }); - } - } - - /** - * The Electron [App](https://electronjs.org/docs/api/app) - * instance. - */ - get app(): Electron.App { - return this._app; - } - - /** - * The [electron-positioner](https://github.com/jenslind/electron-positioner) - * instance. - */ - get positioner(): Positioner { - if (!this._positioner) { - throw new Error( - 'Please access `this.positioner` after the `after-create-window` event has fired.', - ); + private _app: Electron.App; + private _browserWindow?: BrowserWindow; + private _blurTimeout: NodeJS.Timeout | null = null; // track blur events with timeout + private _isVisible: boolean; // track visibility + private _cachedBounds?: Electron.Rectangle; // _cachedBounds are needed for double-clicked event + private _options: Options; + private _positioner: Positioner | undefined; + private _tray?: Tray; + + constructor(app: Electron.App, options?: Partial) { + super(); + this._app = app; + this._options = cleanOptions(options); + this._isVisible = false; + + if (app.isReady()) { + // See https://github.com/maxogden/menubar/pull/151 + process.nextTick(() => this.appReady().catch((err) => console.error('menubar: ', err))); + } else { + app.on('ready', () => { + this.appReady().catch((err) => console.error('menubar: ', err)); + }); + } } - return this._positioner; - } - - /** - * The Electron [Tray](https://electronjs.org/docs/api/tray) instance. - */ - get tray(): Tray { - if (!this._tray) { - throw new Error( - 'Please access `this.tray` after the `ready` event has fired.', - ); + /** + * The Electron [App](https://electronjs.org/docs/api/app) + * instance. + */ + get app(): Electron.App { + return this._app; } - return this._tray; - } - - /** - * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window) - * instance, if it's present. - */ - get window(): BrowserWindow | undefined { - return this._browserWindow; - } - - /** - * Retrieve a menubar option. - * - * @param key - The option key to retrieve, see {@link Options}. - */ - getOption(key: K): Options[K] { - return this._options[key]; - } - - /** - * Hide the menubar window. - */ - hideWindow(): void { - if (!this._browserWindow || !this._isVisible) { - return; - } - this.emit('hide'); - this._browserWindow.hide(); - this.emit('after-hide'); - this._isVisible = false; - if (this._blurTimeout) { - clearTimeout(this._blurTimeout); - this._blurTimeout = null; - } - } - - /** - * Change an option after menubar is created. - * - * @param key - The option key to modify, see {@link Options}. - * @param value - The value to set. - */ - setOption(key: K, value: Options[K]): void { - this._options[key] = value; - } - - /** - * Show the menubar window. - * - * @param trayPos - The bounds to show the window in. - */ - async showWindow(trayPos?: Electron.Rectangle): Promise { - if (!this.tray) { - throw new Error('Tray should have been instantiated by now'); - } + /** + * The [electron-positioner](https://github.com/jenslind/electron-positioner) + * instance. + */ + get positioner(): Positioner { + if (!this._positioner) { + throw new Error('Please access `this.positioner` after the `after-create-window` event has fired.'); + } - if (!this._browserWindow) { - await this.createWindow(); + return this._positioner; } - // Use guard for TypeScript, to avoid ! everywhere - if (!this._browserWindow) { - throw new Error('Window has been initialized just above. qed.'); + /** + * The Electron [Tray](https://electronjs.org/docs/api/tray) instance. + */ + get tray(): Tray { + if (!this._tray) { + throw new Error('Please access `this.tray` after the `ready` event has fired.'); + } + + return this._tray; } - // 'Windows' taskbar: sync windows position each time before showing - // https://github.com/maxogden/menubar/issues/232 - if (['win32', 'linux'].includes(process.platform)) { - // Fill in this._options.windowPosition when taskbar position is available - this._options.windowPosition = getWindowPosition(this.tray); + /** + * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window) + * instance, if it's present. + */ + get window(): BrowserWindow | undefined { + return this._browserWindow; } - this.emit('show'); - - if (trayPos && trayPos.x !== 0) { - // Cache the bounds - this._cachedBounds = trayPos; - } else if (this._cachedBounds) { - // Cached value will be used if showWindow is called without bounds data - trayPos = this._cachedBounds; - } else if (this.tray.getBounds) { - // Get the current tray bounds - trayPos = this.tray.getBounds(); + /** + * Retrieve a menubar option. + * + * @param key - The option key to retrieve, see {@link Options}. + */ + getOption(key: K): Options[K] { + return this._options[key]; } - // Default the window to the right if `trayPos` bounds are undefined or null. - let noBoundsPosition = undefined; - if ( - (trayPos === undefined || trayPos.x === 0) && - this._options.windowPosition && - this._options.windowPosition.startsWith('tray') - ) { - noBoundsPosition = - process.platform === 'win32' ? 'bottomRight' : 'topRight'; + /** + * Hide the menubar window. + */ + hideWindow(): void { + if (!this._browserWindow || !this._isVisible) { + return; + } + this.emit('hide'); + this._browserWindow.hide(); + this.emit('after-hide'); + this._isVisible = false; + if (this._blurTimeout) { + clearTimeout(this._blurTimeout); + this._blurTimeout = null; + } } - const position = this.positioner.calculate( - this._options.windowPosition || noBoundsPosition, - trayPos, - ) as { x: number; y: number }; - - // Not using `||` because x and y can be zero. - const x = - this._options.browserWindow.x !== undefined - ? this._options.browserWindow.x - : position.x; - const y = - this._options.browserWindow.y !== undefined - ? this._options.browserWindow.y - : position.y; - - // `.setPosition` crashed on non-integers - // https://github.com/maxogden/menubar/issues/233 - this._browserWindow.setPosition(Math.round(x), Math.round(y)); - this._browserWindow.show(); - this._isVisible = true; - this.emit('after-show'); - return; - } - - private async appReady(): Promise { - if (this.app.dock && !this._options.showDockIcon) { - this.app.dock.hide(); + /** + * Change an option after menubar is created. + * + * @param key - The option key to modify, see {@link Options}. + * @param value - The value to set. + */ + setOption(key: K, value: Options[K]): void { + this._options[key] = value; } - if (this._options.activateWithApp) { - this.app.on('activate', (_event, hasVisibleWindows) => { - if (!hasVisibleWindows) { - this.showWindow().catch(console.error); + /** + * Show the menubar window. + * + * @param trayPos - The bounds to show the window in. + */ + async showWindow(trayPos?: Electron.Rectangle): Promise { + if (!this.tray) { + throw new Error('Tray should have been instantiated by now'); } - }); - } - let trayImage = - this._options.icon || path.join(this._options.dir, 'IconTemplate.png'); - if (typeof trayImage === 'string' && !fs.existsSync(trayImage)) { - trayImage = path.join(__dirname, '..', 'assets', 'IconTemplate.png'); // Default cat icon - } + if (!this._browserWindow) { + await this.createWindow(); + } - const defaultClickEvent = this._options.showOnRightClick - ? 'right-click' - : 'click'; + // Use guard for TypeScript, to avoid ! everywhere + if (!this._browserWindow) { + throw new Error('Window has been initialized just above. qed.'); + } - this._tray = this._options.tray || new Tray(trayImage); - // Type guards for TS not to complain - if (!this.tray) { - throw new Error('Tray has been initialized above'); - } - this.tray.on( - defaultClickEvent as Parameters[0], - this.clicked.bind(this), - ); - this.tray.on('double-click', this.clicked.bind(this)); - this.tray.setToolTip(this._options.tooltip); - - if (!this._options.windowPosition) { - this._options.windowPosition = getWindowPosition(this.tray); - } + // 'Windows' taskbar: sync windows position each time before showing + // https://github.com/maxogden/menubar/issues/232 + if (['win32', 'linux'].includes(process.platform)) { + // Fill in this._options.windowPosition when taskbar position is available + this._options.windowPosition = getWindowPosition(this.tray); + } - if (this._options.preloadWindow) { - await this.createWindow(); - } + this.emit('show'); + + if (trayPos && trayPos.x !== 0) { + // Cache the bounds + this._cachedBounds = trayPos; + } else if (this._cachedBounds) { + // Cached value will be used if showWindow is called without bounds data + trayPos = this._cachedBounds; + } else if (this.tray.getBounds) { + // Get the current tray bounds + trayPos = this.tray.getBounds(); + } - this.emit('ready'); - } - - /** - * Callback on tray icon click or double-click. - * - * @param e - * @param bounds - */ - private async clicked( - event?: Electron.KeyboardEvent, - bounds?: Electron.Rectangle, - ): Promise { - if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) { - return this.hideWindow(); - } + // Default the window to the right if `trayPos` bounds are undefined or null. + let noBoundsPosition = undefined; + if ( + (trayPos === undefined || trayPos.x === 0) && + this._options.windowPosition && + this._options.windowPosition.startsWith('tray') + ) { + noBoundsPosition = process.platform === 'win32' ? 'bottomRight' : 'topRight'; + } - // if blur was invoked clear timeout - if (this._blurTimeout) { - clearInterval(this._blurTimeout); + const position = this.positioner.calculate(this._options.windowPosition || noBoundsPosition, trayPos) as { + x: number; + y: number; + }; + + // Not using `||` because x and y can be zero. + const x = this._options.browserWindow.x !== undefined ? this._options.browserWindow.x : position.x; + const y = this._options.browserWindow.y !== undefined ? this._options.browserWindow.y : position.y; + + // `.setPosition` crashed on non-integers + // https://github.com/maxogden/menubar/issues/233 + this._browserWindow.setPosition(Math.round(x), Math.round(y)); + this._browserWindow.show(); + this._isVisible = true; + this.emit('after-show'); + return; } - if (this._browserWindow && this._isVisible) { - return this.hideWindow(); - } + private async appReady(): Promise { + if (this.app.dock && !this._options.showDockIcon) { + this.app.dock.hide(); + } - this._cachedBounds = bounds || this._cachedBounds; - await this.showWindow(this._cachedBounds); - } + if (this._options.activateWithApp) { + this.app.on('activate', (_event, hasVisibleWindows) => { + if (!hasVisibleWindows) { + this.showWindow().catch(console.error); + } + }); + } - private async createWindow(): Promise { - this.emit('create-window'); + let trayImage = this._options.icon || path.join(this._options.dir, 'IconTemplate.png'); + if (typeof trayImage === 'string' && !fs.existsSync(trayImage)) { + trayImage = path.join(__dirname, '..', 'assets', 'IconTemplate.png'); // Default cat icon + } - // We add some default behavior for menubar's browserWindow, to make it - // look like a menubar - const defaults = { - show: false, // Don't show it at first - frame: false, // Remove window frame - }; + const defaultClickEvent = this._options.showOnRightClick ? 'right-click' : 'click'; - this._browserWindow = new BrowserWindow({ - ...defaults, - ...this._options.browserWindow, - }); + this._tray = this._options.tray || new Tray(trayImage); + // Type guards for TS not to complain + if (!this.tray) { + throw new Error('Tray has been initialized above'); + } + this.tray.on(defaultClickEvent as Parameters[0], this.clicked.bind(this)); + this.tray.on('double-click', this.clicked.bind(this)); + this.tray.setToolTip(this._options.tooltip); - this._positioner = new Positioner(this._browserWindow); + if (!this._options.windowPosition) { + this._options.windowPosition = getWindowPosition(this.tray); + } - this._browserWindow.on('blur', () => { - if (!this._browserWindow) { - return; - } - - // hack to close if icon clicked when open - this._browserWindow.isAlwaysOnTop() - ? this.emit('focus-lost') - : (this._blurTimeout = setTimeout(() => { - this.hideWindow(); - }, 100)); - }); - - if (this._options.showOnAllWorkspaces !== false) { - // https://github.com/electron/electron/issues/37832#issuecomment-1497882944 - this._browserWindow.setVisibleOnAllWorkspaces(true, { - skipTransformProcessType: true, // Avoid damaging the original visible state of app.dock - }); + if (this._options.preloadWindow) { + await this.createWindow(); + } + + this.emit('ready'); + } + + /** + * Callback on tray icon click or double-click. + * + * @param event + * @param bounds + */ + private async clicked(event?: Electron.KeyboardEvent, bounds?: Electron.Rectangle): Promise { + if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) { + return this.hideWindow(); + } + + // if blur was invoked clear timeout + if (this._blurTimeout) { + clearInterval(this._blurTimeout); + } + + if (this._browserWindow && this._isVisible) { + return this.hideWindow(); + } + + this._cachedBounds = bounds || this._cachedBounds; + await this.showWindow(this._cachedBounds); } - this._browserWindow.on('close', this.windowClear.bind(this)); + private async createWindow(): Promise { + this.emit('create-window'); + + // We add some default behavior for menubar's browserWindow, to make it + // look like a menubar + const defaults = { + show: false, // Don't show it at first + frame: false, // Remove window frame + }; + + this._browserWindow = new BrowserWindow({ + ...defaults, + ...this._options.browserWindow, + }); + + this._positioner = new Positioner(this._browserWindow); + + this._browserWindow.on('blur', () => { + if (!this._browserWindow) { + return; + } + + // hack to close if icon clicked when open + if (this._browserWindow.isAlwaysOnTop()) { + this.emit('focus-lost'); + } else { + this._blurTimeout = setTimeout(() => { + this.hideWindow(); + }, 100); + } + }); + + if (this._options.showOnAllWorkspaces !== false) { + // https://github.com/electron/electron/issues/37832#issuecomment-1497882944 + this._browserWindow.setVisibleOnAllWorkspaces(true, { + skipTransformProcessType: true, // Avoid damaging the original visible state of app.dock + }); + } + + this._browserWindow.on('close', this.windowClear.bind(this)); - this.emit('before-load'); + this.emit('before-load'); - // If the user explicity set options.index to false, we don't loadURL - // https://github.com/maxogden/menubar/issues/255 - if (this._options.index !== false) { - await this._browserWindow.loadURL( - this._options.index, - this._options.loadUrlOptions, - ); + // If the user explicity set options.index to false, we don't loadURL + // https://github.com/maxogden/menubar/issues/255 + if (this._options.index !== false) { + await this._browserWindow.loadURL(this._options.index, this._options.loadUrlOptions); + } + this.emit('after-create-window'); } - this.emit('after-create-window'); - } - private windowClear(): void { - this._browserWindow = undefined; - this.emit('after-close'); - } + private windowClear(): void { + this._browserWindow = undefined; + this.emit('after-close'); + } } diff --git a/resources/electron/electron-plugin/src/libs/menubar/ambient.d.ts b/resources/electron/electron-plugin/src/libs/menubar/ambient.d.ts index 2ff6872e..4d71f6b5 100644 --- a/resources/electron/electron-plugin/src/libs/menubar/ambient.d.ts +++ b/resources/electron/electron-plugin/src/libs/menubar/ambient.d.ts @@ -1,11 +1,8 @@ // TODO https://github.com/jenslind/electron-positioner/issues/15 declare module 'electron-positioner' { - export default class { - constructor(window: Electron.BrowserWindow); + export default class { + constructor(window: Electron.BrowserWindow); - calculate( - position?: string, - rectangle?: Electron.Rectangle, - ): { x: number; y: number }; - } + calculate(position?: string, rectangle?: Electron.Rectangle): { x: number; y: number }; + } } diff --git a/resources/electron/electron-plugin/src/libs/menubar/index.ts b/resources/electron/electron-plugin/src/libs/menubar/index.ts index 6eba24dd..6e32030d 100644 --- a/resources/electron/electron-plugin/src/libs/menubar/index.ts +++ b/resources/electron/electron-plugin/src/libs/menubar/index.ts @@ -23,5 +23,5 @@ export { Menubar }; * {@link Options} */ export function menubar(options?: Partial): Menubar { - return new Menubar(app, options); + return new Menubar(app, options); } diff --git a/resources/electron/electron-plugin/src/libs/menubar/types.ts b/resources/electron/electron-plugin/src/libs/menubar/types.ts index cf37f654..51225240 100644 --- a/resources/electron/electron-plugin/src/libs/menubar/types.ts +++ b/resources/electron/electron-plugin/src/libs/menubar/types.ts @@ -1,104 +1,100 @@ -import type { - BrowserWindowConstructorOptions, - LoadURLOptions, - Tray, -} from 'electron'; +import type { BrowserWindowConstructorOptions, LoadURLOptions, Tray } from 'electron'; /** * Options for creating a menubar application */ export interface Options { - /** - * Listen on `app.on('activate')` to open menubar when app is activated. - * @default `true` - */ - activateWithApp?: boolean; - /** - * An Electron BrowserWindow instance, or an options object to be passed into - * the BrowserWindow constructor. - * @example - * ```typescript - * const options = { height: 640, width: 480 }; - * - * const mb = new Menubar({ - * browserWindow: options - * }); - * ``` - */ - browserWindow: BrowserWindowConstructorOptions; - /** - * The app source directory. - */ - dir: string; - /** - * The png icon to use for the menubar. A good size to start with is 20x20. - * To support retina, supply a 2x sized image (e.g. 40x40) with @2x added to - * the end of the name, so icon.png and icon@2x.png and Electron will - * automatically use your @2x version on retina screens. - */ - icon?: string | Electron.NativeImage; - /** - * The URL to load the menubar's browserWindow with. The url can be a remote - * address (e.g. `http://`) or a path to a local HTML file using the - * `file://` protocol. If false, then menubar won't call `loadURL` on - * start. - * @default `file:// + options.dir + index.html` - * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options - */ - index: string | false; - /** - * The options passed when loading the index URL in the menubar's - * browserWindow. Everything browserWindow.loadURL supports is supported; - * this object is simply passed onto browserWindow.loadURL - * @default `{}` - * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options - */ - loadUrlOptions?: LoadURLOptions; - /** - * Create BrowserWindow instance before it is used -- increasing resource - * usage, but making the click on the menubar load faster. - */ - preloadWindow?: boolean; - /** - * Configure the visibility of the application dock icon, macOS only. Calls - * [`app.dock.hide`](https://electronjs.org/docs/api/app#appdockhide-macos). - */ - showDockIcon?: boolean; - /** - * Makes the window available on all OS X workspaces. Calls - * [`setVisibleOnAllWorkspaces`](https://electronjs.org/docs/api/browser-window#winsetvisibleonallworkspacesvisible-options). - */ - showOnAllWorkspaces?: boolean; - /** - * Show the window on 'right-click' event instead of regular 'click'. - */ - showOnRightClick?: boolean; - /** - * Menubar tray icon tooltip text. Calls [`tray.setTooltip`](https://electronjs.org/docs/api/tray#traysettooltiptooltip). - */ - tooltip: string; - /** - * An electron Tray instance. If provided, `options.icon` will be ignored. - */ - tray?: Tray; - /** - * Sets the window position (x and y will still override this), check - * electron-positioner docs for valid values. - */ - windowPosition?: - | 'trayLeft' - | 'trayBottomLeft' - | 'trayRight' - | 'trayBottomRight' - | 'trayCenter' - | 'trayBottomCenter' - | 'topLeft' - | 'topRight' - | 'bottomLeft' - | 'bottomRight' - | 'topCenter' - | 'bottomCenter' - | 'leftCenter' - | 'rightCenter' - | 'center'; + /** + * Listen on `app.on('activate')` to open menubar when app is activated. + * @default `true` + */ + activateWithApp?: boolean; + /** + * An Electron BrowserWindow instance, or an options object to be passed into + * the BrowserWindow constructor. + * @example + * ```typescript + * const options = { height: 640, width: 480 }; + * + * const mb = new Menubar({ + * browserWindow: options + * }); + * ``` + */ + browserWindow: BrowserWindowConstructorOptions; + /** + * The app source directory. + */ + dir: string; + /** + * The png icon to use for the menubar. A good size to start with is 20x20. + * To support retina, supply a 2x sized image (e.g. 40x40) with @2x added to + * the end of the name, so icon.png and icon@2x.png and Electron will + * automatically use your @2x version on retina screens. + */ + icon?: string | Electron.NativeImage; + /** + * The URL to load the menubar's browserWindow with. The url can be a remote + * address (e.g. `http://`) or a path to a local HTML file using the + * `file://` protocol. If false, then menubar won't call `loadURL` on + * start. + * @default `file:// + options.dir + index.html` + * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options + */ + index: string | false; + /** + * The options passed when loading the index URL in the menubar's + * browserWindow. Everything browserWindow.loadURL supports is supported; + * this object is simply passed onto browserWindow.loadURL + * @default `{}` + * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options + */ + loadUrlOptions?: LoadURLOptions; + /** + * Create BrowserWindow instance before it is used -- increasing resource + * usage, but making the click on the menubar load faster. + */ + preloadWindow?: boolean; + /** + * Configure the visibility of the application dock icon, macOS only. Calls + * [`app.dock.hide`](https://electronjs.org/docs/api/app#appdockhide-macos). + */ + showDockIcon?: boolean; + /** + * Makes the window available on all OS X workspaces. Calls + * [`setVisibleOnAllWorkspaces`](https://electronjs.org/docs/api/browser-window#winsetvisibleonallworkspacesvisible-options). + */ + showOnAllWorkspaces?: boolean; + /** + * Show the window on 'right-click' event instead of regular 'click'. + */ + showOnRightClick?: boolean; + /** + * Menubar tray icon tooltip text. Calls [`tray.setTooltip`](https://electronjs.org/docs/api/tray#traysettooltiptooltip). + */ + tooltip: string; + /** + * An electron Tray instance. If provided, `options.icon` will be ignored. + */ + tray?: Tray; + /** + * Sets the window position (x and y will still override this), check + * electron-positioner docs for valid values. + */ + windowPosition?: + | 'trayLeft' + | 'trayBottomLeft' + | 'trayRight' + | 'trayBottomRight' + | 'trayCenter' + | 'trayBottomCenter' + | 'topLeft' + | 'topRight' + | 'bottomLeft' + | 'bottomRight' + | 'topCenter' + | 'bottomCenter' + | 'leftCenter' + | 'rightCenter' + | 'center'; } diff --git a/resources/electron/electron-plugin/src/libs/menubar/util/cleanOptions.ts b/resources/electron/electron-plugin/src/libs/menubar/util/cleanOptions.ts index d677340d..746b67ff 100644 --- a/resources/electron/electron-plugin/src/libs/menubar/util/cleanOptions.ts +++ b/resources/electron/electron-plugin/src/libs/menubar/util/cleanOptions.ts @@ -4,9 +4,9 @@ /** */ +import { app } from 'electron'; import path from 'path'; import url from 'url'; -import { app } from 'electron'; import type { Options } from '../types.js'; @@ -20,48 +20,44 @@ const DEFAULT_WINDOW_WIDTH = 400; * @ignore */ export function cleanOptions(opts?: Partial): Options { - const options: Partial = { ...opts }; - - if (options.activateWithApp === undefined) { - options.activateWithApp = true; - } - if (!options.dir) { - options.dir = app.getAppPath(); - } - if (!path.isAbsolute(options.dir)) { - options.dir = path.resolve(options.dir); - } - // Note: options.index can be `false` - if (options.index === undefined) { - options.index = url.format({ - pathname: path.join(options.dir, 'index.html'), - protocol: 'file:', - slashes: true, - }); - } - options.loadUrlOptions = options.loadUrlOptions || {}; - - options.tooltip = options.tooltip || ''; - - // `icon`, `preloadWindow`, `showDockIcon`, `showOnAllWorkspaces`, - // `showOnRightClick` don't need any special treatment - - // Now we take care of `browserWindow` - if (!options.browserWindow) { - options.browserWindow = {}; - } - - // Set width/height on options to be usable before the window is created - options.browserWindow.width = - // Note: not using `options.browserWindow.width || DEFAULT_WINDOW_WIDTH` so - // that users can put a 0 width - options.browserWindow.width !== undefined - ? options.browserWindow.width - : DEFAULT_WINDOW_WIDTH; - options.browserWindow.height = - options.browserWindow.height !== undefined - ? options.browserWindow.height - : DEFAULT_WINDOW_HEIGHT; - - return options as Options; + const options: Partial = { ...opts }; + + if (options.activateWithApp === undefined) { + options.activateWithApp = true; + } + if (!options.dir) { + options.dir = app.getAppPath(); + } + if (!path.isAbsolute(options.dir)) { + options.dir = path.resolve(options.dir); + } + // Note: options.index can be `false` + if (options.index === undefined) { + options.index = url.format({ + pathname: path.join(options.dir, 'index.html'), + protocol: 'file:', + slashes: true, + }); + } + options.loadUrlOptions = options.loadUrlOptions || {}; + + options.tooltip = options.tooltip || ''; + + // `icon`, `preloadWindow`, `showDockIcon`, `showOnAllWorkspaces`, + // `showOnRightClick` don't need any special treatment + + // Now we take care of `browserWindow` + if (!options.browserWindow) { + options.browserWindow = {}; + } + + // Set width/height on options to be usable before the window is created + options.browserWindow.width = + // Note: not using `options.browserWindow.width || DEFAULT_WINDOW_WIDTH` so + // that users can put a 0 width + options.browserWindow.width !== undefined ? options.browserWindow.width : DEFAULT_WINDOW_WIDTH; + options.browserWindow.height = + options.browserWindow.height !== undefined ? options.browserWindow.height : DEFAULT_WINDOW_HEIGHT; + + return options as Options; } diff --git a/resources/electron/electron-plugin/src/libs/menubar/util/getWindowPosition.ts b/resources/electron/electron-plugin/src/libs/menubar/util/getWindowPosition.ts index a4010a6b..64546c5a 100644 --- a/resources/electron/electron-plugin/src/libs/menubar/util/getWindowPosition.ts +++ b/resources/electron/electron-plugin/src/libs/menubar/util/getWindowPosition.ts @@ -9,15 +9,13 @@ import { type Rectangle, type Tray, screen as electronScreen } from 'electron'; const isLinux = process.platform === 'linux'; const trayToScreenRects = (tray: Tray): [Rectangle, Rectangle] => { - // There may be more than one screen, so we need to figure out on which screen our tray icon lives. - const { workArea, bounds: screenBounds } = electronScreen.getDisplayMatching( - tray.getBounds(), - ); + // There may be more than one screen, so we need to figure out on which screen our tray icon lives. + const { workArea, bounds: screenBounds } = electronScreen.getDisplayMatching(tray.getBounds()); - workArea.x -= screenBounds.x; - workArea.y -= screenBounds.y; + workArea.x -= screenBounds.x; + workArea.y -= screenBounds.y; - return [screenBounds, workArea]; + return [screenBounds, workArea]; }; type TaskbarLocation = 'top' | 'bottom' | 'left' | 'right'; @@ -30,42 +28,37 @@ type TaskbarLocation = 'top' | 'bottom' | 'left' | 'right'; * @param tray - The Electron Tray instance. */ export function taskbarLocation(tray: Tray): TaskbarLocation { - const [screenBounds, workArea] = trayToScreenRects(tray); - - // TASKBAR LEFT - if (workArea.x > 0) { - // Most likely Ubuntu hence assuming the window should be on top - if (isLinux && workArea.y > 0) return 'top'; - // The workspace starts more on the right - return 'left'; - } - - // TASKBAR TOP - if (workArea.y > 0) { - return 'top'; - } - - // TASKBAR RIGHT - // Here both workArea.y and workArea.x are 0 so we can no longer leverage them. - // We can use the workarea and display width though. - // Determine taskbar location - if (workArea.width < screenBounds.width) { - // The taskbar is either on the left or right, but since the LEFT case was handled above, - // we can be sure we're dealing with a right taskbar - return 'right'; - } - - // TASKBAR BOTTOM - // Since all the other cases were handled, we can be sure we're dealing with a bottom taskbar - return 'bottom'; + const [screenBounds, workArea] = trayToScreenRects(tray); + + // TASKBAR LEFT + if (workArea.x > 0) { + // Most likely Ubuntu hence assuming the window should be on top + if (isLinux && workArea.y > 0) return 'top'; + // The workspace starts more on the right + return 'left'; + } + + // TASKBAR TOP + if (workArea.y > 0) { + return 'top'; + } + + // TASKBAR RIGHT + // Here both workArea.y and workArea.x are 0 so we can no longer leverage them. + // We can use the workarea and display width though. + // Determine taskbar location + if (workArea.width < screenBounds.width) { + // The taskbar is either on the left or right, but since the LEFT case was handled above, + // we can be sure we're dealing with a right taskbar + return 'right'; + } + + // TASKBAR BOTTOM + // Since all the other cases were handled, we can be sure we're dealing with a bottom taskbar + return 'bottom'; } -type WindowPosition = - | 'trayCenter' - | 'topRight' - | 'trayBottomCenter' - | 'bottomLeft' - | 'bottomRight'; +type WindowPosition = 'trayCenter' | 'topRight' | 'trayBottomCenter' | 'bottomLeft' | 'bottomRight'; /** * Depending on where the taskbar is, determine where the window should be @@ -74,34 +67,34 @@ type WindowPosition = * @param tray - The Electron Tray instance. */ export function getWindowPosition(tray: Tray): WindowPosition { - switch (process.platform) { - // macOS - // Supports top taskbars - case 'darwin': - return 'trayCenter'; - // Linux - // Windows - // Supports top/bottom/left/right taskbar - case 'linux': - case 'win32': { - const traySide = taskbarLocation(tray); - - // Assign position for menubar - if (traySide === 'top') { - return isLinux ? 'topRight' : 'trayCenter'; - } - if (traySide === 'bottom') { - return 'bottomRight'; - } - if (traySide === 'left') { - return 'bottomLeft'; - } - if (traySide === 'right') { - return 'bottomRight'; - } + switch (process.platform) { + // macOS + // Supports top taskbars + case 'darwin': + return 'trayCenter'; + // Linux + // Windows + // Supports top/bottom/left/right taskbar + case 'linux': + case 'win32': { + const traySide = taskbarLocation(tray); + + // Assign position for menubar + if (traySide === 'top') { + return isLinux ? 'topRight' : 'trayCenter'; + } + if (traySide === 'bottom') { + return 'bottomRight'; + } + if (traySide === 'left') { + return 'bottomLeft'; + } + if (traySide === 'right') { + return 'bottomRight'; + } + } } - } - // When we really don't know, we just show the menubar on the top-right - return 'topRight'; + // When we really don't know, we just show the menubar on the top-right + return 'topRight'; } diff --git a/resources/electron/electron-plugin/src/libs/positioner/index.ts b/resources/electron/electron-plugin/src/libs/positioner/index.ts index eacd4c31..b1014b06 100644 --- a/resources/electron/electron-plugin/src/libs/positioner/index.ts +++ b/resources/electron/electron-plugin/src/libs/positioner/index.ts @@ -1,133 +1,92 @@ -"use strict"; +'use strict'; +import type { Screen } from 'electron'; +import { BrowserWindow, screen } from 'electron'; class Positioner { - browserWindow: any; - electronScreen: any; + browserWindow?: BrowserWindow; + electronScreen: Screen; - constructor(browserWindow: any) { + constructor(browserWindow?: BrowserWindow) { this.browserWindow = browserWindow; - this.electronScreen = require("electron").screen; + this.electronScreen = screen; } _getCoords(position, trayPosition) { - let screenSize = this._getScreenSize(trayPosition); - let windowSize = this._getWindowSize(); + const screenSize = this._getScreenSize(trayPosition); + const windowSize = this._getWindowSize(); if (trayPosition === undefined) trayPosition = {}; // Positions - let positions = { + const positions = { trayLeft: { x: Math.floor(trayPosition.x), y: screenSize.y, }, trayBottomLeft: { x: Math.floor(trayPosition.x), - y: Math.floor( - screenSize.height - (windowSize[1] - screenSize.y), - ), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), }, trayRight: { - x: Math.floor( - trayPosition.x - windowSize[0] + trayPosition.width, - ), + x: Math.floor(trayPosition.x - windowSize[0] + trayPosition.width), y: screenSize.y, }, trayBottomRight: { - x: Math.floor( - trayPosition.x - windowSize[0] + trayPosition.width, - ), - y: Math.floor( - screenSize.height - (windowSize[1] - screenSize.y), - ), + x: Math.floor(trayPosition.x - windowSize[0] + trayPosition.width), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), }, trayCenter: { - x: Math.floor( - trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2, - ), + x: Math.floor(trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2), y: screenSize.y, }, trayBottomCenter: { - x: Math.floor( - trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2, - ), - y: Math.floor( - screenSize.height - (windowSize[1] - screenSize.y), - ), + x: Math.floor(trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), }, topLeft: { x: screenSize.x, y: screenSize.y, }, topRight: { - x: Math.floor( - screenSize.x + (screenSize.width - windowSize[0]), - ), + x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])), y: screenSize.y, }, bottomLeft: { x: screenSize.x, - y: Math.floor( - screenSize.height - (windowSize[1] - screenSize.y), - ), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), }, bottomRight: { - x: Math.floor( - screenSize.x + (screenSize.width - windowSize[0]), - ), - y: Math.floor( - screenSize.height - (windowSize[1] - screenSize.y), - ), + x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), }, topCenter: { - x: Math.floor( - screenSize.x + (screenSize.width / 2 - windowSize[0] / 2), - ), + x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)), y: screenSize.y, }, bottomCenter: { - x: Math.floor( - screenSize.x + (screenSize.width / 2 - windowSize[0] / 2), - ), - y: Math.floor( - screenSize.height - (windowSize[1] - screenSize.y), - ), + x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), }, leftCenter: { x: screenSize.x, - y: - screenSize.y + - Math.floor(screenSize.height / 2) - - Math.floor(windowSize[1] / 2), + y: screenSize.y + Math.floor(screenSize.height / 2) - Math.floor(windowSize[1] / 2), }, rightCenter: { - x: Math.floor( - screenSize.x + (screenSize.width - windowSize[0]), - ), - y: - screenSize.y + - Math.floor(screenSize.height / 2) - - Math.floor(windowSize[1] / 2), + x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])), + y: screenSize.y + Math.floor(screenSize.height / 2) - Math.floor(windowSize[1] / 2), }, center: { - x: Math.floor( - screenSize.x + (screenSize.width / 2 - windowSize[0] / 2), - ), - y: Math.floor( - (screenSize.height + screenSize.y) / 2 - windowSize[1] / 2, - ), + x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)), + y: Math.floor((screenSize.height + screenSize.y) / 2 - windowSize[1] / 2), }, }; // Default to right if the window is bigger than the space left. // Because on Windows the window might get out of bounds and dissappear. - if (position.substr(0, 4) === "tray") { - if ( - positions[position].x + windowSize[0] > - screenSize.width + screenSize.x - ) { + if (position.substr(0, 4) === 'tray') { + if (positions[position].x + windowSize[0] > screenSize.width + screenSize.x) { return { - x: positions["topRight"].x, + x: positions['topRight'].x, y: positions[position].y, }; } @@ -142,18 +101,15 @@ class Positioner { _getScreenSize(trayPosition) { if (trayPosition) { - return this.electronScreen.getDisplayMatching(trayPosition) - .workArea; + return this.electronScreen.getDisplayMatching(trayPosition).workArea; } else { - return this.electronScreen.getDisplayNearestPoint( - this.electronScreen.getCursorScreenPoint(), - ).workArea; + return this.electronScreen.getDisplayNearestPoint(this.electronScreen.getCursorScreenPoint()).workArea; } } move(position, trayPos) { // Get positions coords - var coords = this._getCoords(position, trayPos); + const coords = this._getCoords(position, trayPos); // Set the windows position this.browserWindow.setPosition(coords.x, coords.y); @@ -161,7 +117,7 @@ class Positioner { calculate(position, trayPos) { // Get positions coords - var coords = this._getCoords(position, trayPos); + const coords = this._getCoords(position, trayPos); return { x: coords.x, diff --git a/resources/electron/electron-plugin/src/preload/index.mts b/resources/electron/electron-plugin/src/preload/index.mts index 66064510..71d787ed 100644 --- a/resources/electron/electron-plugin/src/preload/index.mts +++ b/resources/electron/electron-plugin/src/preload/index.mts @@ -1,5 +1,5 @@ -import remote from "@electron/remote"; -import {ipcRenderer, contextBridge} from "electron"; +import remote from '@electron/remote'; +import { contextBridge, ipcRenderer } from 'electron'; // ------------------------------------------------------------------- // The Native helper @@ -14,12 +14,12 @@ const Native = { if (event === data.event) { return callback(data.payload, event); } - }) + }); }, contextMenu: (template) => { - let menu = remote.Menu.buildFromTemplate(template); + const menu = remote.Menu.buildFromTemplate(template); menu.popup({ window: remote.getCurrentWindow() }); - } + }, }; contextBridge.exposeInMainWorld('Native', Native); @@ -27,50 +27,54 @@ contextBridge.exposeInMainWorld('Native', Native); // ------------------------------------------------------------------- // Log events // ------------------------------------------------------------------- -ipcRenderer.on('log', (event, {level, message, context}) => { +ipcRenderer.on('log', (event, { level, message, context }) => { if (level === 'error') { - console.error(`[${level}] ${message}`, context) + console.error(`[${level}] ${message}`, context); } else if (level === 'warn') { - console.warn(`[${level}] ${message}`, context) + console.warn(`[${level}] ${message}`, context); } else { - console.log(`[${level}] ${message}`, context) + console.log(`[${level}] ${message}`, context); } }); - // ------------------------------------------------------------------- // Livewire event listeners // ------------------------------------------------------------------- ipcRenderer.on('native-event', (event, data) => { - // Strip leading slashes data.event = data.event.replace(/^(\\)+/, ''); // Forward event to renderer context // Handler injected via Events\LivewireDispatcher - window.postMessage({ - type: 'native-event', - event: data.event, - payload: data.payload - }, '*'); -}) + window.postMessage( + { + type: 'native-event', + event: data.event, + payload: data.payload, + }, + '*', + ); +}); // ------------------------------------------------------------------- // Let the client know preload is fully evaluated // ------------------------------------------------------------------- -contextBridge.exposeInMainWorld('native:initialized', (function() { - // This is admittedly a bit hacky. Due to context isolation - // we don't have direct access to the renderer window object, - // but by assigning a bridge function that executes itself inside - // the renderer context we can hack around it. +contextBridge.exposeInMainWorld( + 'native:initialized', + (function () { + // This is admittedly a bit hacky. Due to context isolation + // we don't have direct access to the renderer window object, + // but by assigning a bridge function that executes itself inside + // the renderer context we can hack around it. - // It's recommended to use window.postMessage & dispatch an - // event from the renderer itself, but we're loading webcontent - // from localhost. We don't have a renderer process we can access. - // Though this is hacky it works well and is the simplest way to do this - // without sprinkling additional logic all over the place. + // It's recommended to use window.postMessage & dispatch an + // event from the renderer itself, but we're loading webcontent + // from localhost. We don't have a renderer process we can access. + // Though this is hacky it works well and is the simplest way to do this + // without sprinkling additional logic all over the place. - window.dispatchEvent(new CustomEvent('native:init')); + window.dispatchEvent(new CustomEvent('native:init')); - return true; -})()) + return true; + })(), +); diff --git a/resources/electron/electron-plugin/src/preload/livewire-dispatcher.js b/resources/electron/electron-plugin/src/preload/livewire-dispatcher.js index 3b4edff1..779134a0 100644 --- a/resources/electron/electron-plugin/src/preload/livewire-dispatcher.js +++ b/resources/electron/electron-plugin/src/preload/livewire-dispatcher.js @@ -1,5 +1,5 @@ -window.addEventListener("message", (event) => { - if (event.data.type === "native-event") { +window.addEventListener('message', (event) => { + if (event.data.type === 'native-event') { const { event: eventName, payload } = event.data; LivewireDispatcher.handle(eventName, payload); @@ -10,7 +10,7 @@ const LivewireDispatcher = { handle: function (eventName, payload) { // Livewire 3 if (window.Livewire) { - window.Livewire.dispatch("native:" + eventName, payload); + window.Livewire.dispatch('native:' + eventName, payload); } // Livewire 2 @@ -18,14 +18,11 @@ const LivewireDispatcher = { window.livewire.components.components().forEach((component) => { if (Array.isArray(component.listeners)) { component.listeners.forEach((event) => { - - if (event.startsWith("native")) { - let event_parts = event.split( - /(native:|native-)|:|,/, - ); + if (event.startsWith('native')) { + let event_parts = event.split(/(native:|native-)|:|,/); - if (event_parts[1] == "native:") { - event_parts.splice(2, 0, "private", undefined, "nativephp", undefined); + if (event_parts[1] === 'native:') { + event_parts.splice(2, 0, 'private', undefined, 'nativephp', undefined); } let [s1, signature, channel_type, s2, channel, s3, event_name] = event_parts; diff --git a/resources/electron/electron-plugin/src/server/ProcessResult.ts b/resources/electron/electron-plugin/src/server/ProcessResult.ts index d4c1df30..3df1271d 100644 --- a/resources/electron/electron-plugin/src/server/ProcessResult.ts +++ b/resources/electron/electron-plugin/src/server/ProcessResult.ts @@ -1,6 +1,6 @@ -import { ChildProcessWithoutNullStreams } from "child_process"; +import { ChildProcessWithoutNullStreams } from 'child_process'; export interface ProcessResult { - process: ChildProcessWithoutNullStreams; - port: number; + process: ChildProcessWithoutNullStreams; + port: number; } diff --git a/resources/electron/electron-plugin/src/server/api.ts b/resources/electron/electron-plugin/src/server/api.ts index 5ff685e5..57f0942b 100644 --- a/resources/electron/electron-plugin/src/server/api.ts +++ b/resources/electron/electron-plugin/src/server/api.ts @@ -1,79 +1,79 @@ -import express from "express"; -import bodyParser from "body-parser"; -import getPort, {portNumbers} from "get-port"; -import middleware from "./api/middleware.js"; +import bodyParser from 'body-parser'; +import express from 'express'; +import getPort, { portNumbers } from 'get-port'; +import middleware from './api/middleware.js'; -import clipboardRoutes from "./api/clipboard.js"; -import alertRoutes from "./api/alert.js"; -import appRoutes from "./api/app.js"; -import autoUpdaterRoutes from "./api/autoUpdater.js"; -import screenRoutes from "./api/screen.js"; -import dialogRoutes from "./api/dialog.js"; -import debugRoutes from "./api/debug.js"; -import broadcastingRoutes from "./api/broadcasting.js"; -import systemRoutes from "./api/system.js"; -import globalShortcutRoutes from "./api/globalShortcut.js"; -import notificationRoutes from "./api/notification.js"; -import dockRoutes from "./api/dock.js"; -import menuRoutes from "./api/menu.js"; -import menuBarRoutes from "./api/menuBar.js"; -import windowRoutes from "./api/window.js"; -import processRoutes from "./api/process.js"; -import contextMenuRoutes from "./api/contextMenu.js"; -import settingsRoutes from "./api/settings.js"; -import shellRoutes from "./api/shell.js"; -import progressBarRoutes from "./api/progressBar.js"; -import powerMonitorRoutes from "./api/powerMonitor.js"; -import childProcessRoutes from "./api/childProcess.js"; -import { Server } from "net"; +import { Server } from 'net'; +import alertRoutes from './api/alert.js'; +import appRoutes from './api/app.js'; +import autoUpdaterRoutes from './api/autoUpdater.js'; +import broadcastingRoutes from './api/broadcasting.js'; +import childProcessRoutes from './api/childProcess.js'; +import clipboardRoutes from './api/clipboard.js'; +import contextMenuRoutes from './api/contextMenu.js'; +import debugRoutes from './api/debug.js'; +import dialogRoutes from './api/dialog.js'; +import dockRoutes from './api/dock.js'; +import globalShortcutRoutes from './api/globalShortcut.js'; +import menuRoutes from './api/menu.js'; +import menuBarRoutes from './api/menuBar.js'; +import notificationRoutes from './api/notification.js'; +import powerMonitorRoutes from './api/powerMonitor.js'; +import processRoutes from './api/process.js'; +import progressBarRoutes from './api/progressBar.js'; +import screenRoutes from './api/screen.js'; +import settingsRoutes from './api/settings.js'; +import shellRoutes from './api/shell.js'; +import systemRoutes from './api/system.js'; +import windowRoutes from './api/window.js'; export interface APIProcess { - server: Server; - port: number; + server: Server; + port: number; } async function startAPIServer(randomSecret: string): Promise { - const port = await getPort({ - port: portNumbers(4000, 5000), - }); + const port = await getPort({ + port: portNumbers(4000, 5000), + }); - return new Promise((resolve, reject) => { - const httpServer = express(); - httpServer.use(middleware(randomSecret)); - httpServer.use(bodyParser.json()); - httpServer.use("/api/clipboard", clipboardRoutes); - httpServer.use("/api/alert", alertRoutes); - httpServer.use("/api/app", appRoutes); - httpServer.use("/api/auto-updater", autoUpdaterRoutes); - httpServer.use("/api/screen", screenRoutes); - httpServer.use("/api/dialog", dialogRoutes); - httpServer.use("/api/system", systemRoutes); - httpServer.use("/api/global-shortcuts", globalShortcutRoutes); - httpServer.use("/api/notification", notificationRoutes); - httpServer.use("/api/dock", dockRoutes); - httpServer.use("/api/menu", menuRoutes); - httpServer.use("/api/window", windowRoutes); - httpServer.use("/api/process", processRoutes); - httpServer.use("/api/settings", settingsRoutes); - httpServer.use("/api/shell", shellRoutes); - httpServer.use("/api/context", contextMenuRoutes); - httpServer.use("/api/menu-bar", menuBarRoutes); - httpServer.use("/api/progress-bar", progressBarRoutes); - httpServer.use("/api/power-monitor", powerMonitorRoutes); - httpServer.use("/api/child-process", childProcessRoutes); - httpServer.use("/api/broadcast", broadcastingRoutes); + return new Promise((resolve) => { + const httpServer = express(); + httpServer.use(middleware(randomSecret)); + httpServer.use(bodyParser.json()); + httpServer.use('/api/clipboard', clipboardRoutes); + httpServer.use('/api/alert', alertRoutes); + httpServer.use('/api/app', appRoutes); + httpServer.use('/api/auto-updater', autoUpdaterRoutes); + httpServer.use('/api/screen', screenRoutes); + httpServer.use('/api/dialog', dialogRoutes); + httpServer.use('/api/system', systemRoutes); + httpServer.use('/api/global-shortcuts', globalShortcutRoutes); + httpServer.use('/api/notification', notificationRoutes); + httpServer.use('/api/dock', dockRoutes); + httpServer.use('/api/menu', menuRoutes); + httpServer.use('/api/window', windowRoutes); + httpServer.use('/api/process', processRoutes); + httpServer.use('/api/settings', settingsRoutes); + httpServer.use('/api/shell', shellRoutes); + httpServer.use('/api/context', contextMenuRoutes); + httpServer.use('/api/menu-bar', menuBarRoutes); + httpServer.use('/api/progress-bar', progressBarRoutes); + httpServer.use('/api/power-monitor', powerMonitorRoutes); + httpServer.use('/api/child-process', childProcessRoutes); + httpServer.use('/api/broadcast', broadcastingRoutes); - if (process.env.NODE_ENV === "development") { - httpServer.use("/api/debug", debugRoutes); - } + if (process.env.NODE_ENV === 'development') { + httpServer.use('/api/debug', debugRoutes); + } - const server = httpServer.listen(port, () => { - resolve({ - server, - port, - }); + const server = httpServer.listen(port, () => { + resolve({ + server, + port, + }); + }); }); - }); } export default startAPIServer; diff --git a/resources/electron/electron-plugin/src/server/api/alert.ts b/resources/electron/electron-plugin/src/server/api/alert.ts index 30f31d09..2e3e0881 100644 --- a/resources/electron/electron-plugin/src/server/api/alert.ts +++ b/resources/electron/electron-plugin/src/server/api/alert.ts @@ -1,5 +1,5 @@ -import express from 'express' -import { dialog } from 'electron' +import { dialog } from 'electron'; +import express from 'express'; const router = express.Router(); router.post('/message', (req, res) => { @@ -11,10 +11,10 @@ router.post('/message', (req, res) => { detail: detail ?? undefined, buttons: buttons ?? undefined, defaultId: defaultId ?? undefined, - cancelId: cancelId ?? undefined + cancelId: cancelId ?? undefined, }); res.json({ - result + result, }); }); @@ -24,7 +24,7 @@ router.post('/error', (req, res) => { dialog.showErrorBox(title, message); res.json({ - result: true + result: true, }); }); diff --git a/resources/electron/electron-plugin/src/server/api/app.ts b/resources/electron/electron-plugin/src/server/api/app.ts index f33ad652..0e8d69eb 100644 --- a/resources/electron/electron-plugin/src/server/api/app.ts +++ b/resources/electron/electron-plugin/src/server/api/app.ts @@ -1,79 +1,79 @@ -import express from 'express' -import { app } from 'electron' +import { app } from 'electron'; +import express from 'express'; const router = express.Router(); router.post('/quit', (req, res) => { - app.quit() + app.quit(); res.sendStatus(200); }); -router.post('/relaunch', (req, res) => { - app.relaunch() - app.quit() +router.post('/relaunch', () => { + app.relaunch(); + app.quit(); }); router.post('/show', (req, res) => { - app.show() + app.show(); res.sendStatus(200); }); router.post('/hide', (req, res) => { - app.hide() + app.hide(); res.sendStatus(200); }); router.get('/is-hidden', (req, res) => { res.json({ is_hidden: app.isHidden(), - }) + }); }); router.get('/locale', (req, res) => { res.json({ locale: app.getLocale(), - }) + }); }); router.get('/locale-country-code', (req, res) => { res.json({ locale_country_code: app.getLocaleCountryCode(), - }) + }); }); router.get('/system-locale', (req, res) => { res.json({ system_locale: app.getSystemLocale(), - }) + }); }); router.get('/app-path', (req, res) => { res.json({ path: app.getAppPath(), - }) + }); }); router.get('/path/:name', (req, res) => { res.json({ // @ts-ignore path: app.getPath(req.params.name), - }) + }); }); router.get('/version', (req, res) => { res.json({ version: app.getVersion(), - }) + }); }); router.post('/badge-count', (req, res) => { - app.setBadgeCount(req.body.count) + app.setBadgeCount(req.body.count); res.sendStatus(200); }); router.get('/badge-count', (req, res) => { res.json({ count: app.getBadgeCount(), - }) + }); }); router.post('/recent-documents', (req, res) => { diff --git a/resources/electron/electron-plugin/src/server/api/autoUpdater.ts b/resources/electron/electron-plugin/src/server/api/autoUpdater.ts index 6f65e8e1..d7c8c782 100644 --- a/resources/electron/electron-plugin/src/server/api/autoUpdater.ts +++ b/resources/electron/electron-plugin/src/server/api/autoUpdater.ts @@ -1,38 +1,34 @@ -import express from "express"; +import type { ProgressInfo, UpdateDownloadedEvent, UpdateInfo } from 'electron-updater'; import electronUpdater from 'electron-updater'; +import express from 'express'; +import { notifyLaravel } from '../utils.js'; const { autoUpdater } = electronUpdater; -import type { - ProgressInfo, - UpdateDownloadedEvent, - UpdateInfo, -} from "electron-updater"; -import { notifyLaravel } from "../utils.js"; const router = express.Router(); -router.post("/check-for-updates", (req, res) => { +router.post('/check-for-updates', (req, res) => { autoUpdater.checkForUpdates(); res.sendStatus(200); }); -router.post("/download-update", (req, res) => { +router.post('/download-update', (req, res) => { autoUpdater.downloadUpdate(); res.sendStatus(200); }); -router.post("/quit-and-install", (req, res) => { +router.post('/quit-and-install', (req, res) => { autoUpdater.quitAndInstall(); res.sendStatus(200); }); -autoUpdater.addListener("checking-for-update", () => { - notifyLaravel("events", { +autoUpdater.addListener('checking-for-update', () => { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\AutoUpdater\\CheckingForUpdate`, }); }); -autoUpdater.addListener("update-available", (event: UpdateInfo) => { - notifyLaravel("events", { +autoUpdater.addListener('update-available', (event: UpdateInfo) => { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\AutoUpdater\\UpdateAvailable`, payload: { version: event.version, @@ -46,8 +42,8 @@ autoUpdater.addListener("update-available", (event: UpdateInfo) => { }); }); -autoUpdater.addListener("update-not-available", (event: UpdateInfo) => { - notifyLaravel("events", { +autoUpdater.addListener('update-not-available', (event: UpdateInfo) => { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\AutoUpdater\\UpdateNotAvailable`, payload: { version: event.version, @@ -61,8 +57,8 @@ autoUpdater.addListener("update-not-available", (event: UpdateInfo) => { }); }); -autoUpdater.addListener("error", (error: Error) => { - notifyLaravel("events", { +autoUpdater.addListener('error', (error: Error) => { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\AutoUpdater\\Error`, payload: { name: error.name, @@ -72,8 +68,8 @@ autoUpdater.addListener("error", (error: Error) => { }); }); -autoUpdater.addListener("download-progress", (progressInfo: ProgressInfo) => { - notifyLaravel("events", { +autoUpdater.addListener('download-progress', (progressInfo: ProgressInfo) => { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\AutoUpdater\\DownloadProgress`, payload: { total: progressInfo.total, @@ -85,8 +81,8 @@ autoUpdater.addListener("download-progress", (progressInfo: ProgressInfo) => { }); }); -autoUpdater.addListener("update-downloaded", (event: UpdateDownloadedEvent) => { - notifyLaravel("events", { +autoUpdater.addListener('update-downloaded', (event: UpdateDownloadedEvent) => { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\AutoUpdater\\UpdateDownloaded`, payload: { downloadedFile: event.downloadedFile, @@ -101,8 +97,8 @@ autoUpdater.addListener("update-downloaded", (event: UpdateDownloadedEvent) => { }); }); -autoUpdater.addListener("update-cancelled", (event: UpdateInfo) => { - notifyLaravel("events", { +autoUpdater.addListener('update-cancelled', (event: UpdateInfo) => { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\AutoUpdater\\UpdateCancelled`, payload: { version: event.version, diff --git a/resources/electron/electron-plugin/src/server/api/broadcasting.ts b/resources/electron/electron-plugin/src/server/api/broadcasting.ts index d0e3d844..a1e2d4a5 100644 --- a/resources/electron/electron-plugin/src/server/api/broadcasting.ts +++ b/resources/electron/electron-plugin/src/server/api/broadcasting.ts @@ -1,13 +1,13 @@ -import express from 'express' +import express from 'express'; import { broadcastToWindows } from '../utils.js'; const router = express.Router(); router.post('/', (req, res) => { - const {event, payload} = req.body; + const { event, payload } = req.body; - broadcastToWindows("native-event", { event, payload }); + broadcastToWindows('native-event', { event, payload }); - res.sendStatus(200) -}) + res.sendStatus(200); +}); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/childProcess.ts b/resources/electron/electron-plugin/src/server/api/childProcess.ts index bcf0b5d3..87be31cc 100644 --- a/resources/electron/electron-plugin/src/server/api/childProcess.ts +++ b/resources/electron/electron-plugin/src/server/api/childProcess.ts @@ -1,16 +1,16 @@ +import { utilityProcess, UtilityProcess } from 'electron'; import express from 'express'; -import {utilityProcess, UtilityProcess} from 'electron'; +import killSync from 'kill-sync'; +import { join } from 'path'; +import { fileURLToPath } from 'url'; +import { getAppPath, getDefaultEnvironmentVariables, getDefaultPhpIniSettings, runningSecureBuild } from '../php.js'; import state from '../state.js'; -import {notifyLaravel} from "../utils.js"; -import {getAppPath, getDefaultEnvironmentVariables, getDefaultPhpIniSettings, runningSecureBuild} from "../php.js"; -import killSync from "kill-sync"; -import {fileURLToPath} from "url"; -import {join} from "path"; +import { notifyLaravel } from '../utils.js'; const router = express.Router(); function startProcess(settings, useNodeRuntime = false) { - const {alias, cmd, cwd, env, persistent, spawnTimeout = 30000} = settings; + const { alias, cmd, cwd, env, spawnTimeout = 30000 } = settings; if (getProcess(alias) !== undefined) { return state.processes[alias]; @@ -27,9 +27,9 @@ function startProcess(settings, useNodeRuntime = false) { env: { ...process.env, ...env, - USE_NODE_RUNTIME: useNodeRuntime ? '1' : '0' - } - } + USE_NODE_RUNTIME: useNodeRuntime ? '1' : '0', + }, + }, ); // Set timeout to detect if process never spawns @@ -40,7 +40,7 @@ function startProcess(settings, useNodeRuntime = false) { // Attempt to clean up try { proc.kill(); - } catch (e) { + } catch { // Ignore kill errors } @@ -49,7 +49,7 @@ function startProcess(settings, useNodeRuntime = false) { payload: { alias, error: 'Startup timeout exceeded', - } + }, }); } }, spawnTimeout); @@ -60,7 +60,7 @@ function startProcess(settings, useNodeRuntime = false) { payload: { alias, data: data.toString(), - } + }, }); }); @@ -72,7 +72,7 @@ function startProcess(settings, useNodeRuntime = false) { payload: { alias, data: data.toString(), - } + }, }); }); @@ -99,12 +99,12 @@ function startProcess(settings, useNodeRuntime = false) { state.processes[alias] = { pid: proc.pid, proc, - settings + settings, }; notifyLaravel('events', { event: 'Native\\Desktop\\Events\\ChildProcess\\ProcessSpawned', - payload: [alias, proc.pid] + payload: [alias, proc.pid], }); }); @@ -117,10 +117,10 @@ function startProcess(settings, useNodeRuntime = false) { payload: { alias, code, - } + }, }); - const settings = {...getSettings(alias)}; + const settings = { ...getSettings(alias) }; delete state.processes[alias]; if (settings?.persistent) { @@ -133,7 +133,7 @@ function startProcess(settings, useNodeRuntime = false) { return { pid: null, proc, - settings + settings, }; } catch (error) { console.error(`Failed to create process [${alias}]: ${error.message}`); @@ -143,30 +143,33 @@ function startProcess(settings, useNodeRuntime = false) { payload: { alias, error: error.toString(), - } + }, }); return { pid: null, proc: null, settings, - error: error.message + error: error.message, }; } } function startPhpProcess(settings) { - const defaultEnv = getDefaultEnvironmentVariables( - state.randomSecret, - state.electronApiPort - ); + const defaultEnv = getDefaultEnvironmentVariables(state.randomSecret, state.electronApiPort); // Construct command args from ini settings const customIniSettings = settings.iniSettings || {}; - const iniSettings = {...getDefaultPhpIniSettings(), ...state.phpIni, ...customIniSettings}; - const iniArgs = Object.keys(iniSettings).map(key => { - return ['-d', `${key}=${iniSettings[key]}`]; - }).flat(); + const iniSettings = { + ...getDefaultPhpIniSettings(), + ...state.phpIni, + ...customIniSettings, + }; + const iniArgs = Object.keys(iniSettings) + .map((key) => { + return ['-d', `${key}=${iniSettings[key]}`]; + }) + .flat(); if (settings.cmd[0] === 'artisan' && runningSecureBuild()) { settings.cmd.unshift(join(getAppPath(), 'build', '__nativephp_app_bundle')); @@ -177,7 +180,7 @@ function startPhpProcess(settings) { // Prepend cmd with php executable path & ini settings cmd: [state.php, ...iniArgs, ...settings.cmd], // Mix in the internal NativePHP env - env: {...settings.env, ...defaultEnv} + env: { ...settings.env, ...defaultEnv }, }; return startProcess(settings); @@ -224,7 +227,7 @@ router.post('/start-node', (req, res) => { const proc = startProcess(req.body, true); res.json(proc); -}) +}); router.post('/start-php', (req, res) => { const proc = startPhpProcess(req.body); @@ -233,7 +236,7 @@ router.post('/start-php', (req, res) => { }); router.post('/stop', (req, res) => { - const {alias} = req.body; + const { alias } = req.body; stopProcess(alias); @@ -241,9 +244,9 @@ router.post('/stop', (req, res) => { }); router.post('/restart', async (req, res) => { - const {alias} = req.body; + const { alias } = req.body; - const settings = {...getSettings(alias)}; + const settings = { ...getSettings(alias) }; stopProcess(alias); @@ -259,7 +262,7 @@ router.post('/restart', async (req, res) => { if (Date.now() - start > timeout) { return; } - await new Promise(resolve => setTimeout(resolve, retry)); + await new Promise((resolve) => setTimeout(resolve, retry)); } }; @@ -271,7 +274,7 @@ router.post('/restart', async (req, res) => { }); router.get('/get/:alias', (req, res) => { - const {alias} = req.params; + const { alias } = req.params; const proc = state.processes[alias]; @@ -288,7 +291,7 @@ router.get('/', (req, res) => { }); router.post('/message', (req, res) => { - const {alias, message} = req.body; + const { alias, message } = req.body; const proc = getProcess(alias); diff --git a/resources/electron/electron-plugin/src/server/api/clipboard.ts b/resources/electron/electron-plugin/src/server/api/clipboard.ts index c823d1d3..37a66e0a 100644 --- a/resources/electron/electron-plugin/src/server/api/clipboard.ts +++ b/resources/electron/electron-plugin/src/server/api/clipboard.ts @@ -1,83 +1,83 @@ +import { clipboard, nativeImage } from 'electron'; import * as express from 'express'; const router = express.Router(); -import { clipboard, nativeImage } from 'electron' -const DEFAULT_TYPE = 'clipboard' +const DEFAULT_TYPE = 'clipboard'; router.get('/text', (req, res) => { - const {type} = req.query + const { type } = req.query; res.json({ // @ts-ignore - text: clipboard.readText(type || DEFAULT_TYPE) - }) + text: clipboard.readText(type || DEFAULT_TYPE), + }); }); router.post('/text', (req, res) => { - const {text} = req.body - const {type} = req.query + const { text } = req.body; + const { type } = req.query; // @ts-ignore - clipboard.writeText(text, type || DEFAULT_TYPE) + clipboard.writeText(text, type || DEFAULT_TYPE); res.json({ text, - }) + }); }); router.get('/html', (req, res) => { - const {type} = req.query + const { type } = req.query; res.json({ // @ts-ignore - html: clipboard.readHTML(type || DEFAULT_TYPE) - }) + html: clipboard.readHTML(type || DEFAULT_TYPE), + }); }); router.post('/html', (req, res) => { - const {html} = req.body - const {type} = req.query + const { html } = req.body; + const { type } = req.query; // @ts-ignore - clipboard.writeHTML(html, type || DEFAULT_TYPE) + clipboard.writeHTML(html, type || DEFAULT_TYPE); res.json({ - html, - }) + html, + }); }); router.get('/image', (req, res) => { - const {type} = req.query + const { type } = req.query; // @ts-ignore const image = clipboard.readImage(type || DEFAULT_TYPE); res.json({ - image: image.isEmpty() ? null : image.toDataURL() - }) + image: image.isEmpty() ? null : image.toDataURL(), + }); }); router.post('/image', (req, res) => { - const {image} = req.body - const {type} = req.query + const { image } = req.body; + const { type } = req.query; try { - const _nativeImage = nativeImage.createFromDataURL(image) - // @ts-ignore - clipboard.writeImage(_nativeImage, type || DEFAULT_TYPE) + const _nativeImage = nativeImage.createFromDataURL(image); + // @ts-ignore + clipboard.writeImage(_nativeImage, type || DEFAULT_TYPE); } catch (e) { - res.status(400).json({ - error: e.message, - }) - return + res.status(400).json({ + error: e.message, + }); + return; } res.sendStatus(200); }); router.delete('/', (req, res) => { - const {type} = req.query + const { type } = req.query; // @ts-ignore - clipboard.clear(type || DEFAULT_TYPE) + clipboard.clear(type || DEFAULT_TYPE); res.sendStatus(200); }); diff --git a/resources/electron/electron-plugin/src/server/api/contextMenu.ts b/resources/electron/electron-plugin/src/server/api/contextMenu.ts index 8f723c9c..2c167cc2 100644 --- a/resources/electron/electron-plugin/src/server/api/contextMenu.ts +++ b/resources/electron/electron-plugin/src/server/api/contextMenu.ts @@ -1,10 +1,10 @@ +import contextMenu from 'electron-context-menu'; import express from 'express'; -import { compileMenu } from "./helper/index.js"; -import contextMenu from "electron-context-menu"; +import { compileMenu } from './helper/index.js'; const router = express.Router(); -let contextMenuDisposable = null +let contextMenuDisposable = null; router.delete('/', (req, res) => { res.sendStatus(200); @@ -27,7 +27,7 @@ router.post('/', (req, res) => { showLookUpSelection: false, showSearchWithGoogle: false, showInspectElement: false, - prepend: (defaultActions, parameters, browserWindow) => { + prepend: () => { return req.body.entries.map(compileMenu); }, }); diff --git a/resources/electron/electron-plugin/src/server/api/debug.ts b/resources/electron/electron-plugin/src/server/api/debug.ts index 20504631..8c1a9ed8 100644 --- a/resources/electron/electron-plugin/src/server/api/debug.ts +++ b/resources/electron/electron-plugin/src/server/api/debug.ts @@ -1,13 +1,13 @@ -import express from 'express' +import express from 'express'; import { broadcastToWindows } from '../utils.js'; const router = express.Router(); router.post('/log', (req, res) => { - const {level, message, context} = req.body + const { level, message, context } = req.body; - broadcastToWindows('log', {level, message, context}); + broadcastToWindows('log', { level, message, context }); - res.sendStatus(200) -}) + res.sendStatus(200); +}); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/dialog.ts b/resources/electron/electron-plugin/src/server/api/dialog.ts index 74cb2a55..d52f20ac 100644 --- a/resources/electron/electron-plugin/src/server/api/dialog.ts +++ b/resources/electron/electron-plugin/src/server/api/dialog.ts @@ -1,11 +1,11 @@ -import express from 'express' -import {dialog} from 'electron' -import state from '../state.js' -import {trimOptions} from '../utils.js' +import { dialog } from 'electron'; +import express from 'express'; +import state from '../state.js'; +import { trimOptions } from '../utils.js'; const router = express.Router(); router.post('/open', (req, res) => { - const {title, buttonLabel, filters, properties, defaultPath, message, windowReference} = req.body + const { title, buttonLabel, filters, properties, defaultPath, message, windowReference } = req.body; let options = { title, @@ -13,27 +13,27 @@ router.post('/open', (req, res) => { buttonLabel, filters, message, - properties + properties, }; options = trimOptions(options); let result; - let browserWindow = state.findWindow(windowReference); + const browserWindow = state.findWindow(windowReference); if (browserWindow) { - result = dialog.showOpenDialogSync(browserWindow, options) + result = dialog.showOpenDialogSync(browserWindow, options); } else { - result = dialog.showOpenDialogSync(options) + result = dialog.showOpenDialogSync(options); } res.json({ - result - }) + result, + }); }); router.post('/save', (req, res) => { - const {title, buttonLabel, filters, properties, defaultPath, message, windowReference} = req.body + const { title, buttonLabel, filters, properties, defaultPath, message, windowReference } = req.body; let options = { title, @@ -41,23 +41,23 @@ router.post('/save', (req, res) => { buttonLabel, filters, message, - properties + properties, }; options = trimOptions(options); let result; - let browserWindow = state.findWindow(windowReference); + const browserWindow = state.findWindow(windowReference); if (browserWindow) { - result = dialog.showSaveDialogSync(browserWindow, options) + result = dialog.showSaveDialogSync(browserWindow, options); } else { - result = dialog.showSaveDialogSync(options) + result = dialog.showSaveDialogSync(options); } res.json({ - result - }) + result, + }); }); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/dock.ts b/resources/electron/electron-plugin/src/server/api/dock.ts index 3e1f15fb..37f6c1bd 100644 --- a/resources/electron/electron-plugin/src/server/api/dock.ts +++ b/resources/electron/electron-plugin/src/server/api/dock.ts @@ -1,7 +1,7 @@ -import express from 'express'; import { app, Menu } from 'electron'; -import { compileMenu } from './helper/index.js'; +import express from 'express'; import state from '../state.js'; +import { compileMenu } from './helper/index.js'; const router = express.Router(); diff --git a/resources/electron/electron-plugin/src/server/api/globalShortcut.ts b/resources/electron/electron-plugin/src/server/api/globalShortcut.ts index 5ff74c2e..b4414d08 100644 --- a/resources/electron/electron-plugin/src/server/api/globalShortcut.ts +++ b/resources/electron/electron-plugin/src/server/api/globalShortcut.ts @@ -1,34 +1,34 @@ -import express from 'express' -import {globalShortcut} from 'electron' -import {notifyLaravel} from "../utils.js"; +import { globalShortcut } from 'electron'; +import express from 'express'; +import { notifyLaravel } from '../utils.js'; const router = express.Router(); router.post('/', (req, res) => { - const {key, event} = req.body + const { key, event } = req.body; globalShortcut.register(key, () => { notifyLaravel('events', { event, - payload: [key] - }) - }) + payload: [key], + }); + }); - res.sendStatus(200) -}) + res.sendStatus(200); +}); router.delete('/', (req, res) => { - const {key} = req.body + const { key } = req.body; - globalShortcut.unregister(key) + globalShortcut.unregister(key); - res.sendStatus(200) + res.sendStatus(200); }); router.get('/:key', (req, res) => { - const {key} = req.params + const { key } = req.params; res.json({ - isRegistered: globalShortcut.isRegistered(key) + isRegistered: globalShortcut.isRegistered(key), }); }); diff --git a/resources/electron/electron-plugin/src/server/api/helper/index.ts b/resources/electron/electron-plugin/src/server/api/helper/index.ts index 8a80facf..177cf818 100644 --- a/resources/electron/electron-plugin/src/server/api/helper/index.ts +++ b/resources/electron/electron-plugin/src/server/api/helper/index.ts @@ -1,6 +1,6 @@ import { shell } from 'electron'; -import { notifyLaravel, goToUrl } from '../../utils.js'; import state from '../../state.js'; +import { goToUrl, notifyLaravel } from '../../utils.js'; function triggerMenuItemEvent(menuItem, combo) { notifyLaravel('events', { @@ -16,7 +16,7 @@ function triggerMenuItemEvent(menuItem, combo) { }); } -export function compileMenu (item) { +export function compileMenu(item) { if (item.submenu) { if (Array.isArray(item.submenu)) { item.submenu = item.submenu?.map(compileMenu); @@ -36,16 +36,15 @@ export function compileMenu (item) { return; } - if (! focusedWindow) { + if (!focusedWindow) { // TODO: Bring a window to the front? return; } - const id = Object.keys(state.windows) - .find(key => state.windows[key] === focusedWindow); + const id = Object.keys(state.windows).find((key) => state.windows[key] === focusedWindow); goToUrl(item.url, id); - } + }; return item; } @@ -60,8 +59,8 @@ export function compileMenu (item) { } if (item.type === 'role') { - let menuItem = { - role: item.role + const menuItem = { + role: item.role, }; if (item.label) { @@ -72,10 +71,10 @@ export function compileMenu (item) { } // Default click event - if (! item.click) { + if (!item.click) { item.click = (menuItem, focusedWindow, combo) => { triggerMenuItemEvent(item, combo); - } + }; } return item; diff --git a/resources/electron/electron-plugin/src/server/api/menu.ts b/resources/electron/electron-plugin/src/server/api/menu.ts index 47b55596..699a1a1a 100644 --- a/resources/electron/electron-plugin/src/server/api/menu.ts +++ b/resources/electron/electron-plugin/src/server/api/menu.ts @@ -1,5 +1,5 @@ -import express from 'express'; import { Menu } from 'electron'; +import express from 'express'; import { compileMenu } from './helper/index.js'; const router = express.Router(); diff --git a/resources/electron/electron-plugin/src/server/api/menuBar.ts b/resources/electron/electron-plugin/src/server/api/menuBar.ts index 5c5c7163..853a6699 100644 --- a/resources/electron/electron-plugin/src/server/api/menuBar.ts +++ b/resources/electron/electron-plugin/src/server/api/menuBar.ts @@ -1,16 +1,15 @@ -import express from "express"; -import { app, Menu, Tray } from "electron"; -import { compileMenu } from "./helper/index.js"; -import state from "../state.js"; -import { menubar } from "../../libs/menubar/index.js"; -import { notifyLaravel } from "../utils.js"; -import { fileURLToPath } from 'url' -import { enable } from "@electron/remote/main/index.js"; -import mergePreferences from "../webPreferences.js"; +import { enable } from '@electron/remote/main/index.js'; +import { app, Menu, Tray } from 'electron'; +import express from 'express'; +import { menubar } from '../../libs/menubar/index.js'; +import state from '../state.js'; +import { notifyLaravel } from '../utils.js'; +import mergePreferences from '../webPreferences.js'; +import { compileMenu } from './helper/index.js'; const router = express.Router(); -router.post("/label", (req, res) => { +router.post('/label', (req, res) => { res.sendStatus(200); const { label } = req.body; @@ -18,7 +17,7 @@ router.post("/label", (req, res) => { state.tray?.setTitle(label); }); -router.post("/tooltip", (req, res) => { +router.post('/tooltip', (req, res) => { res.sendStatus(200); const { tooltip } = req.body; @@ -26,7 +25,7 @@ router.post("/tooltip", (req, res) => { state.tray?.setToolTip(tooltip); }); -router.post("/icon", (req, res) => { +router.post('/icon', (req, res) => { res.sendStatus(200); const { icon } = req.body; @@ -34,7 +33,7 @@ router.post("/icon", (req, res) => { state.tray?.setImage(icon); }); -router.post("/context-menu", (req, res) => { +router.post('/context-menu', (req, res) => { res.sendStatus(200); const { contextMenu } = req.body; @@ -42,25 +41,25 @@ router.post("/context-menu", (req, res) => { state.tray?.setContextMenu(buildMenu(contextMenu)); }); -router.post("/show-context-menu", (req, res) => { +router.post('/show-context-menu', (req, res) => { res.sendStatus(200); state.tray?.popUpContextMenu(); }); -router.post("/show", (req, res) => { +router.post('/show', (req, res) => { res.sendStatus(200); state.activeMenuBar.showWindow(); }); -router.post("/hide", (req, res) => { +router.post('/hide', (req, res) => { res.sendStatus(200); state.activeMenuBar.hideWindow(); }); -router.post("/resize", (req, res) => { +router.post('/resize', (req, res) => { res.sendStatus(200); const { width, height } = req.body; @@ -68,7 +67,7 @@ router.post("/resize", (req, res) => { state.activeMenuBar.window.setSize(width, height); }); -router.post("/create", (req, res) => { +router.post('/create', (req, res) => { res.sendStatus(200); let shouldSendCreatedEvent = true; @@ -96,13 +95,11 @@ router.post("/create", (req, res) => { tooltip, resizable, webPreferences, - event, } = req.body; - if (onlyShowContextMenu) { // Create a tray icon - const tray = new Tray(icon || state.icon.replace("icon.png", "IconTemplate.png")); + const tray = new Tray(icon || state.icon.replace('icon.png', 'IconTemplate.png')); // Set the context menu tray.setContextMenu(buildMenu(contextMenu)); @@ -118,16 +115,15 @@ router.post("/create", (req, res) => { if (!showDockIcon) { app.dock.hide(); } - } else { state.activeMenuBar = menubar({ - icon: icon || state.icon.replace("icon.png", "IconTemplate.png"), + icon: icon || state.icon.replace('icon.png', 'IconTemplate.png'), preloadWindow: true, tooltip, index: url, showDockIcon, showOnAllWorkspaces: showOnAllWorkspaces ?? false, - windowPosition: windowPosition ?? "trayCenter", + windowPosition: windowPosition ?? 'trayCenter', activateWithApp: false, browserWindow: { width, @@ -137,15 +133,15 @@ router.post("/create", (req, res) => { vibrancy, backgroundColor, transparent: transparency, - webPreferences: mergePreferences(webPreferences) - } + webPreferences: mergePreferences(webPreferences), + }, }); - state.activeMenuBar.on("after-create-window", () => { + state.activeMenuBar.on('after-create-window', () => { enable(state.activeMenuBar.window.webContents); }); - state.activeMenuBar.on("ready", () => { + state.activeMenuBar.on('ready', () => { // Set the event listeners eventsForTray(state.activeMenuBar.tray, onlyShowContextMenu, contextMenu, shouldSendCreatedEvent); @@ -155,45 +151,38 @@ router.post("/create", (req, res) => { // Set the title state.tray.setTitle(label); - state.activeMenuBar.on("hide", () => { - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\MenuBar\\MenuBarHidden" + state.activeMenuBar.on('hide', () => { + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\MenuBar\\MenuBarHidden', }); }); - state.activeMenuBar.on("show", () => { - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\MenuBar\\MenuBarShown" + state.activeMenuBar.on('show', () => { + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\MenuBar\\MenuBarShown', }); }); - }); } - }); - - function eventsForTray(tray, onlyShowContextMenu, contextMenu, shouldSendCreatedEvent) { - if (shouldSendCreatedEvent) { - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\MenuBar\\MenuBarCreated" + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\MenuBar\\MenuBarCreated', }); } - tray.on("drop-files", (event, files) => { - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\MenuBar\\MenuBarDroppedFiles", - payload: [ - files - ] + tray.on('drop-files', (event, files) => { + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\MenuBar\\MenuBarDroppedFiles', + payload: [files], }); }); tray.on('click', (combo, bounds, position) => { notifyLaravel('events', { - event: "\\Native\\Desktop\\Events\\MenuBar\\MenuBarClicked", + event: '\\Native\\Desktop\\Events\\MenuBar\\MenuBarClicked', payload: { combo, bounds, @@ -202,13 +191,13 @@ function eventsForTray(tray, onlyShowContextMenu, contextMenu, shouldSendCreated }); }); - tray.on("right-click", (combo, bounds) => { - notifyLaravel("events", { - event: "\\Native\\Desktop\\Events\\MenuBar\\MenuBarRightClicked", + tray.on('right-click', (combo, bounds) => { + notifyLaravel('events', { + event: '\\Native\\Desktop\\Events\\MenuBar\\MenuBarRightClicked', payload: { combo, bounds, - } + }, }); if (!onlyShowContextMenu) { @@ -219,7 +208,7 @@ function eventsForTray(tray, onlyShowContextMenu, contextMenu, shouldSendCreated tray.on('double-click', (combo, bounds) => { notifyLaravel('events', { - event: "\\Native\\Desktop\\Events\\MenuBar\\MenuBarDoubleClicked", + event: '\\Native\\Desktop\\Events\\MenuBar\\MenuBarDoubleClicked', payload: { combo, bounds, @@ -229,7 +218,7 @@ function eventsForTray(tray, onlyShowContextMenu, contextMenu, shouldSendCreated } function buildMenu(contextMenu) { - let menu = Menu.buildFromTemplate([{ role: "quit" }]); + let menu = Menu.buildFromTemplate([{ role: 'quit' }]); if (contextMenu) { const menuEntries = contextMenu.map(compileMenu); diff --git a/resources/electron/electron-plugin/src/server/api/notification.ts b/resources/electron/electron-plugin/src/server/api/notification.ts index 0fc69f35..6c752393 100644 --- a/resources/electron/electron-plugin/src/server/api/notification.ts +++ b/resources/electron/electron-plugin/src/server/api/notification.ts @@ -1,9 +1,8 @@ -import express from 'express'; import { Notification } from 'electron'; -import {notifyLaravel, broadcastToWindows} from "../utils.js"; -declare const require: any; -import playSoundLib from 'play-sound'; +import express from 'express'; import fs from 'fs'; +import playSoundLib from 'play-sound'; +import { broadcastToWindows, notifyLaravel } from '../utils.js'; const isLocalFile = (sound: unknown) => { if (typeof sound !== 'string') return false; @@ -34,7 +33,7 @@ router.post('/', (req, res) => { const eventName = customEvent ?? '\\Native\\Desktop\\Events\\Notifications\\NotificationClicked'; - const notificationReference = reference ?? (Date.now() + '.' + Math.random().toString(36).slice(2, 9)); + const notificationReference = reference ?? Date.now() + '.' + Math.random().toString(36).slice(2, 9); const usingLocalFile = isLocalFile(sound); @@ -51,7 +50,7 @@ router.post('/', (req, res) => { urgency, actions, closeButtonText, - toastXml + toastXml, }); if (usingLocalFile && !silent) { @@ -60,7 +59,7 @@ router.post('/', (req, res) => { broadcastToWindows('log', { level: 'error', message: `Sound file not found: ${sound}`, - context: { sound } + context: { sound }, }); return; } @@ -69,7 +68,7 @@ router.post('/', (req, res) => { }); } - notification.on("click", (event) => { + notification.on('click', (event) => { notifyLaravel('events', { event: eventName || '\\Native\\Desktop\\Events\\Notifications\\NotificationClicked', payload: { @@ -79,7 +78,7 @@ router.post('/', (req, res) => { }); }); - notification.on("action", (event, index) => { + notification.on('action', (event, index) => { notifyLaravel('events', { event: '\\Native\\Desktop\\Events\\Notifications\\NotificationActionClicked', payload: { @@ -90,7 +89,7 @@ router.post('/', (req, res) => { }); }); - notification.on("reply", (event, reply) => { + notification.on('reply', (event, reply) => { notifyLaravel('events', { event: '\\Native\\Desktop\\Events\\Notifications\\NotificationReply', payload: { @@ -101,7 +100,7 @@ router.post('/', (req, res) => { }); }); - notification.on("close", (event) => { + notification.on('close', (event) => { notifyLaravel('events', { event: '\\Native\\Desktop\\Events\\Notifications\\NotificationClosed', payload: { diff --git a/resources/electron/electron-plugin/src/server/api/powerMonitor.ts b/resources/electron/electron-plugin/src/server/api/powerMonitor.ts index 8b7c81a5..bed3f781 100644 --- a/resources/electron/electron-plugin/src/server/api/powerMonitor.ts +++ b/resources/electron/electron-plugin/src/server/api/powerMonitor.ts @@ -1,108 +1,105 @@ -import express from 'express' -import { powerMonitor } from 'electron' +import { powerMonitor } from 'electron'; +import express from 'express'; import { notifyLaravel } from '../utils.js'; const router = express.Router(); router.get('/get-system-idle-state', (req, res) => { - let threshold = Number(req.query.threshold) || 60; + const threshold = Number(req.query.threshold) || 60; res.json({ result: powerMonitor.getSystemIdleState(threshold), - }) + }); }); router.get('/get-system-idle-time', (req, res) => { res.json({ result: powerMonitor.getSystemIdleTime(), - }) + }); }); router.get('/get-current-thermal-state', (req, res) => { res.json({ result: powerMonitor.getCurrentThermalState(), - }) + }); }); router.get('/is-on-battery-power', (req, res) => { res.json({ result: powerMonitor.isOnBatteryPower(), - }) + }); }); powerMonitor.addListener('on-ac', () => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\PowerStateChanged`, payload: { - state: 'on-ac' - } + state: 'on-ac', + }, }); -}) +}); powerMonitor.addListener('on-battery', () => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\PowerStateChanged`, payload: { - state: 'on-battery' - } + state: 'on-battery', + }, }); -}) +}); // @ts-ignore powerMonitor.addListener('thermal-state-change', (details) => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\ThermalStateChanged`, payload: { state: details.state, }, }); -}) +}); // @ts-ignore powerMonitor.addListener('speed-limit-change', (details) => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\SpeedLimitChanged`, payload: { limit: details.limit, }, }); -}) +}); // @ts-ignore powerMonitor.addListener('lock-screen', () => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\ScreenLocked`, }); -}) +}); // @ts-ignore powerMonitor.addListener('unlock-screen', () => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\ScreenUnlocked`, }); -}) - +}); // @ts-ignore powerMonitor.addListener('shutdown', () => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\Shutdown`, }); -}) - +}); // @ts-ignore powerMonitor.addListener('user-did-become-active', () => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\UserDidBecomeActive`, }); -}) - +}); // @ts-ignore powerMonitor.addListener('user-did-resign-active', () => { - notifyLaravel("events", { + notifyLaravel('events', { event: `\\Native\\Desktop\\Events\\PowerMonitor\\UserDidResignActive`, }); -}) +}); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/process.ts b/resources/electron/electron-plugin/src/server/api/process.ts index dc80a8e4..1b1e7c9f 100644 --- a/resources/electron/electron-plugin/src/server/api/process.ts +++ b/resources/electron/electron-plugin/src/server/api/process.ts @@ -7,8 +7,8 @@ router.get('/', (req, res) => { pid: process.pid, platform: process.platform, arch: process.arch, - uptime: process.uptime() - }) + uptime: process.uptime(), + }); }); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/progressBar.ts b/resources/electron/electron-plugin/src/server/api/progressBar.ts index fc455d73..48c0152a 100644 --- a/resources/electron/electron-plugin/src/server/api/progressBar.ts +++ b/resources/electron/electron-plugin/src/server/api/progressBar.ts @@ -1,15 +1,15 @@ -import express from 'express' -import state from "../state.js"; +import express from 'express'; +import state from '../state.js'; const router = express.Router(); router.post('/update', (req, res) => { - const {percent} = req.body + const { percent } = req.body; Object.values(state.windows).forEach((window) => { - window.setProgressBar(percent) + window.setProgressBar(percent); }); - res.sendStatus(200) -}) + res.sendStatus(200); +}); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/screen.ts b/resources/electron/electron-plugin/src/server/api/screen.ts index ba853f23..cfd54911 100644 --- a/resources/electron/electron-plugin/src/server/api/screen.ts +++ b/resources/electron/electron-plugin/src/server/api/screen.ts @@ -1,28 +1,28 @@ -import express from 'express' -import { screen } from 'electron' +import { screen } from 'electron'; +import express from 'express'; const router = express.Router(); router.get('/displays', (req, res) => { res.json({ - displays: screen.getAllDisplays() - }) + displays: screen.getAllDisplays(), + }); }); router.get('/primary-display', (req, res) => { res.json({ - primaryDisplay: screen.getPrimaryDisplay() - }) + primaryDisplay: screen.getPrimaryDisplay(), + }); }); router.get('/cursor-position', (req, res) => { - res.json(screen.getCursorScreenPoint()) + res.json(screen.getCursorScreenPoint()); }); router.get('/active', (req, res) => { - const cursor = screen.getCursorScreenPoint() + const cursor = screen.getCursorScreenPoint(); - res.json(screen.getDisplayNearestPoint(cursor)) + res.json(screen.getDisplayNearestPoint(cursor)); }); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/settings.ts b/resources/electron/electron-plugin/src/server/api/settings.ts index 84286349..05adb9c4 100644 --- a/resources/electron/electron-plugin/src/server/api/settings.ts +++ b/resources/electron/electron-plugin/src/server/api/settings.ts @@ -4,34 +4,34 @@ import state from '../state.js'; const router = express.Router(); router.get('/:key', (req, res) => { - const key = req.params.key; + const key = req.params.key; - const value = state.store.get(key, null); + const value = state.store.get(key, null); - res.json({value}); + res.json({ value }); }); router.post('/:key', (req, res) => { - const key = req.params.key; - const value = req.body.value; + const key = req.params.key; + const value = req.body.value; - state.store.set(key, value); + state.store.set(key, value); - res.sendStatus(200) + res.sendStatus(200); }); router.delete('/:key', (req, res) => { - const key = req.params.key; + const key = req.params.key; - state.store.delete(key); + state.store.delete(key); - res.sendStatus(200) + res.sendStatus(200); }); router.delete('/', (req, res) => { - state.store.clear(); + state.store.clear(); - res.sendStatus(200) + res.sendStatus(200); }); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/shell.ts b/resources/electron/electron-plugin/src/server/api/shell.ts index a39b94ea..7be4b7d4 100644 --- a/resources/electron/electron-plugin/src/server/api/shell.ts +++ b/resources/electron/electron-plugin/src/server/api/shell.ts @@ -1,50 +1,50 @@ -import express from "express"; -import { shell } from "electron"; +import { shell } from 'electron'; +import express from 'express'; const router = express.Router(); -router.post("/show-item-in-folder", (req, res) => { - const { path } = req.body; +router.post('/show-item-in-folder', (req, res) => { + const { path } = req.body; - shell.showItemInFolder(path); + shell.showItemInFolder(path); - res.sendStatus(200); + res.sendStatus(200); }); -router.post("/open-item", async (req, res) => { - const { path } = req.body; +router.post('/open-item', async (req, res) => { + const { path } = req.body; - let result = await shell.openPath(path); + const result = await shell.openPath(path); - res.json({ - result - }) + res.json({ + result, + }); }); -router.post("/open-external", async (req, res) => { - const { url } = req.body; +router.post('/open-external', async (req, res) => { + const { url } = req.body; - try { - await shell.openExternal(url); + try { + await shell.openExternal(url); - res.sendStatus(200); - } catch (e) { - res.status(500).json({ - error: e - }); - } + res.sendStatus(200); + } catch (e) { + res.status(500).json({ + error: e, + }); + } }); -router.delete("/trash-item", async (req, res) => { - const { path } = req.body; +router.delete('/trash-item', async (req, res) => { + const { path } = req.body; - try { - await shell.trashItem(path); + try { + await shell.trashItem(path); - res.sendStatus(200); - } catch (e) { - res.status(400).json(); - } + res.sendStatus(200); + } catch { + res.status(400).json(); + } }); export default router; diff --git a/resources/electron/electron-plugin/src/server/api/system.ts b/resources/electron/electron-plugin/src/server/api/system.ts index b46cf64c..35129fcd 100644 --- a/resources/electron/electron-plugin/src/server/api/system.ts +++ b/resources/electron/electron-plugin/src/server/api/system.ts @@ -1,5 +1,5 @@ +import { BrowserWindow, nativeTheme, safeStorage, systemPreferences } from 'electron'; import express from 'express'; -import {BrowserWindow, systemPreferences, safeStorage, nativeTheme} from 'electron'; const router = express.Router(); @@ -11,7 +11,7 @@ router.get('/can-prompt-touch-id', (req, res) => { router.post('/prompt-touch-id', async (req, res) => { try { - await systemPreferences.promptTouchID(req.body.reason) + await systemPreferences.promptTouchID(req.body.reason); res.sendStatus(200); } catch (e) { @@ -60,7 +60,7 @@ router.get('/printers', async (req, res) => { }); router.post('/print', async (req, res) => { - const {printer, html, settings} = req.body; + const { printer, html, settings } = req.body; let printWindow = new BrowserWindow({ show: false, @@ -87,7 +87,7 @@ router.post('/print', async (req, res) => { } if (printWindow) { printWindow.close(); // Close the window and the process - printWindow = null; // Free memory + printWindow = null; // Free memory } }); }); @@ -96,25 +96,28 @@ router.post('/print', async (req, res) => { }); router.post('/print-to-pdf', async (req, res) => { - const {html, settings} = req.body; + const { html, settings } = req.body; - let printWindow = new BrowserWindow({ + const printWindow = new BrowserWindow({ show: false, }); printWindow.webContents.on('did-finish-load', () => { - printWindow.webContents.printToPDF(settings ?? {}).then(data => { - printWindow.close(); + printWindow.webContents + .printToPDF(settings ?? {}) + .then((data) => { + printWindow.close(); res.json({ result: data.toString('base64'), }); - }).catch(e => { - printWindow.close(); + }) + .catch((e) => { + printWindow.close(); - res.status(400).json({ - error: e.message, + res.status(400).json({ + error: e.message, + }); }); - }); }); await printWindow.loadURL(`data:text/html;base64;charset=UTF-8,${html}`); diff --git a/resources/electron/electron-plugin/src/server/api/window.ts b/resources/electron/electron-plugin/src/server/api/window.ts index 8b5dcbe4..eda824c5 100644 --- a/resources/electron/electron-plugin/src/server/api/window.ts +++ b/resources/electron/electron-plugin/src/server/api/window.ts @@ -1,17 +1,16 @@ -import express from 'express'; import { BrowserWindow } from 'electron'; -import state from '../state.js'; -import { fileURLToPath } from 'url' -import { notifyLaravel, goToUrl, appendWindowIdToUrl } from '../utils.js'; import windowStateKeeper from 'electron-window-state'; -import mergePreferences from '../webPreferences.js' +import express from 'express'; +import state from '../state.js'; +import { appendWindowIdToUrl, goToUrl, notifyLaravel } from '../utils.js'; +import mergePreferences from '../webPreferences.js'; -import {enable} from "@electron/remote/main/index.js"; +import { enable } from '@electron/remote/main/index.js'; const router = express.Router(); router.post('/maximize', (req, res) => { - const {id} = req.body; + const { id } = req.body; state.windows[id]?.maximize(); @@ -19,7 +18,7 @@ router.post('/maximize', (req, res) => { }); router.post('/minimize', (req, res) => { - const {id} = req.body; + const { id } = req.body; state.windows[id]?.minimize(); @@ -27,7 +26,7 @@ router.post('/minimize', (req, res) => { }); router.post('/resize', (req, res) => { - const {id, width, height} = req.body; + const { id, width, height } = req.body; state.windows[id]?.setSize(parseInt(width), parseInt(height)); @@ -35,7 +34,7 @@ router.post('/resize', (req, res) => { }); router.post('/title', (req, res) => { - const {id, title} = req.body; + const { id, title } = req.body; state.windows[id]?.setTitle(title); @@ -43,7 +42,7 @@ router.post('/title', (req, res) => { }); router.post('/url', (req, res) => { - const {id, url} = req.body; + const { id, url } = req.body; goToUrl(url, id); @@ -51,7 +50,7 @@ router.post('/url', (req, res) => { }); router.post('/closable', (req, res) => { - const {id, closable} = req.body; + const { id, closable } = req.body; state.windows[id]?.setClosable(closable); @@ -59,7 +58,7 @@ router.post('/closable', (req, res) => { }); router.post('/window-button-visibility', (req, res) => { - const {id, windowButtonVisibility} = req.body; + const { id, windowButtonVisibility } = req.body; state.windows[id]?.setWindowButtonVisibility(windowButtonVisibility); @@ -67,7 +66,7 @@ router.post('/window-button-visibility', (req, res) => { }); router.post('/show-dev-tools', (req, res) => { - const {id} = req.body; + const { id } = req.body; state.windows[id]?.webContents.openDevTools(); @@ -75,7 +74,7 @@ router.post('/show-dev-tools', (req, res) => { }); router.post('/hide-dev-tools', (req, res) => { - const {id} = req.body; + const { id } = req.body; state.windows[id]?.webContents.closeDevTools(); @@ -83,7 +82,7 @@ router.post('/hide-dev-tools', (req, res) => { }); router.post('/set-zoom-factor', (req, res) => { - const {id, zoomFactor} = req.body; + const { id, zoomFactor } = req.body; state.windows[id]?.webContents.setZoomFactor(parseFloat(zoomFactor)); @@ -91,7 +90,7 @@ router.post('/set-zoom-factor', (req, res) => { }); router.post('/position', (req, res) => { - const {id, x, y, animate} = req.body; + const { id, x, y, animate } = req.body; state.windows[id]?.setPosition(parseInt(x), parseInt(y), animate); @@ -99,7 +98,7 @@ router.post('/position', (req, res) => { }); router.post('/reload', (req, res) => { - const {id} = req.body; + const { id } = req.body; state.windows[id]?.reload(); @@ -107,7 +106,7 @@ router.post('/reload', (req, res) => { }); router.post('/close', (req, res) => { - const {id} = req.body; + const { id } = req.body; if (state.windows[id]) { state.windows[id].close(); @@ -118,7 +117,7 @@ router.post('/close', (req, res) => { }); router.post('/hide', (req, res) => { - const {id} = req.body; + const { id } = req.body; if (state.windows[id]) { state.windows[id].hide(); @@ -138,7 +137,7 @@ router.post('/show', (req, res) => { }); router.post('/always-on-top', (req, res) => { - const {id, alwaysOnTop} = req.body; + const { id, alwaysOnTop } = req.body; state.windows[id]?.setAlwaysOnTop(alwaysOnTop); @@ -147,22 +146,22 @@ router.post('/always-on-top', (req, res) => { router.get('/current', (req, res) => { // Find the current window object - const currentWindow = Object.values(state.windows).find(window => window.id === BrowserWindow.getFocusedWindow().id); + const currentWindow = Object.values(state.windows).find( + (window) => window.id === BrowserWindow.getFocusedWindow().id, + ); // Get the developer-assigned id for that window - const id = Object.keys(state.windows).find(key => state.windows[key] === currentWindow); + const id = Object.keys(state.windows).find((key) => state.windows[key] === currentWindow); res.json(getWindowData(id)); }); router.get('/all', (req, res) => { - res.json( - Object.keys(state.windows).map(id => getWindowData(id)) - ); + res.json(Object.keys(state.windows).map((id) => getWindowData(id))); }); router.get('/get/:id', (req, res) => { - const {id} = req.params; + const { id } = req.params; if (state.windows[id] === undefined) { res.sendStatus(404); @@ -208,7 +207,7 @@ function getWindowData(id) { } router.post('/open', (req, res) => { - let { + const { id, x, y, @@ -223,7 +222,6 @@ router.post('/open', (req, res) => { skipTaskbar, hiddenInMissionControl, hasShadow, - url, resizable, movable, minimizable, @@ -268,12 +266,8 @@ router.post('/open', (req, res) => { } const window = new BrowserWindow({ - width: resizable - ? windowState?.width || parseInt(width) - : parseInt(width), - height: resizable - ? windowState?.height || parseInt(height) - : parseInt(height), + width: resizable ? windowState?.width || parseInt(width) : parseInt(width), + height: resizable ? windowState?.height || parseInt(height) : parseInt(height), frame: frame !== undefined ? frame : true, x: windowState?.x || x, y: windowState?.y || y, @@ -299,7 +293,7 @@ router.post('/open', (req, res) => { skipTaskbar, hiddenInMissionControl, autoHideMenuBar, - ...(process.platform === 'linux' ? {icon: state.icon} : {}), + ...(process.platform === 'linux' ? { icon: state.icon } : {}), webPreferences: mergePreferences(webPreferences), fullscreen, fullscreenable, @@ -318,7 +312,7 @@ router.post('/open', (req, res) => { if (suppressNewWindows) { window.webContents.setWindowOpenHandler(() => { - return { action: "deny" }; + return { action: 'deny' }; }); } @@ -329,42 +323,42 @@ router.post('/open', (req, res) => { window.on('blur', () => { notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowBlurred', - payload: [id] + payload: [id], }); }); window.on('focus', () => { notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowFocused', - payload: [id] + payload: [id], }); }); window.on('minimize', () => { notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowMinimized', - payload: [id] + payload: [id], }); }); window.on('maximize', () => { notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowMaximized', - payload: [id] + payload: [id], }); }); window.on('show', () => { notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowShown', - payload: [id] + payload: [id], }); }); window.on('resized', () => { notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowResized', - payload: [id, window.getSize()[0], window.getSize()[1]] + payload: [id, window.getSize()[0], window.getSize()[1]], }); }); @@ -372,26 +366,26 @@ router.post('/open', (req, res) => { evt.preventDefault(); }); - window.on('close', (evt) => { + window.on('close', () => { if (state.windows[id]) { delete state.windows[id]; } notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowClosed', - payload: [id] + payload: [id], }); }); // @ts-ignore - window.on('hide', (evt) => { + window.on('hide', () => { notifyLaravel('events', { event: 'Native\\Desktop\\Events\\Windows\\WindowHidden', - payload: [id] + payload: [id], }); }); - url = appendWindowIdToUrl(url, id); + const url = appendWindowIdToUrl(req.body.url, id); window.loadURL(url); diff --git a/resources/electron/electron-plugin/src/server/childProcess.ts b/resources/electron/electron-plugin/src/server/childProcess.ts index 5105cad5..33cbb01c 100644 --- a/resources/electron/electron-plugin/src/server/childProcess.ts +++ b/resources/electron/electron-plugin/src/server/childProcess.ts @@ -1,4 +1,4 @@ -import {spawn, fork} from "child_process"; +import { fork, spawn } from 'child_process'; const useNodeRuntime = process.env.USE_NODE_RUNTIME === '1'; const [command, ...args] = process.argv.slice(2); @@ -7,13 +7,13 @@ const [command, ...args] = process.argv.slice(2); // to use utilityProcess.fork. Otherwise, we can use utilityProcess.spawn const proc = useNodeRuntime ? fork(command, args, { - stdio: ['pipe', 'pipe', 'pipe', 'ipc'], - execPath: process.execPath - }) + stdio: ['pipe', 'pipe', 'pipe', 'ipc'], + execPath: process.execPath, + }) : spawn(command, args); process.parentPort.on('message', (message) => { - proc.stdin.write(message.data) + proc.stdin.write(message.data); }); // Handle normal output @@ -28,5 +28,5 @@ proc.stderr.on('data', (data) => { // Handle process exit proc.on('close', (code) => { - process.exit(code) + process.exit(code); }); diff --git a/resources/electron/electron-plugin/src/server/index.ts b/resources/electron/electron-plugin/src/server/index.ts index 58be7dfd..9714c758 100644 --- a/resources/electron/electron-plugin/src/server/index.ts +++ b/resources/electron/electron-plugin/src/server/index.ts @@ -1,44 +1,35 @@ -import startAPIServer, { APIProcess } from "./api.js"; -import { - retrieveNativePHPConfig, - retrievePhpIniSettings, - serveApp, - startScheduler, -} from "./php.js"; -import { appendCookie } from "./utils.js"; -import state from "./state.js"; -import { ChildProcess } from "child_process"; +import { ChildProcess } from 'child_process'; +import startAPIServer, { APIProcess } from './api.js'; +import { retrieveNativePHPConfig, retrievePhpIniSettings, serveApp, startScheduler } from './php.js'; +import state from './state.js'; +import { appendCookie } from './utils.js'; let schedulerProcess: ChildProcess | null = null; export async function startPhpApp() { - const result = await serveApp( - state.randomSecret, - state.electronApiPort, - state.phpIni - ); + const result = await serveApp(state.randomSecret, state.electronApiPort, state.phpIni); - state.phpPort = result.port; + state.phpPort = result.port; - await appendCookie(); + await appendCookie(); - return result.process; + return result.process; } export function runScheduler() { - killScheduler(); - schedulerProcess = startScheduler(state.randomSecret, state.electronApiPort, state.phpIni); + killScheduler(); + schedulerProcess = startScheduler(state.randomSecret, state.electronApiPort, state.phpIni); } export function killScheduler() { - if (schedulerProcess && !schedulerProcess.killed) { - schedulerProcess.kill(); - schedulerProcess = null; - } + if (schedulerProcess && !schedulerProcess.killed) { + schedulerProcess.kill(); + schedulerProcess = null; + } } export function startAPI(): Promise { - return startAPIServer(state.randomSecret); + return startAPIServer(state.randomSecret); } export { retrieveNativePHPConfig, retrievePhpIniSettings }; diff --git a/resources/electron/electron-plugin/src/server/php.ts b/resources/electron/electron-plugin/src/server/php.ts index 5463fdca..9e2e25ff 100644 --- a/resources/electron/electron-plugin/src/server/php.ts +++ b/resources/electron/electron-plugin/src/server/php.ts @@ -1,23 +1,23 @@ -import {mkdirSync, statSync, writeFileSync, existsSync} from 'fs' +import { existsSync, mkdirSync, statSync, writeFileSync } from 'fs'; import fs_extra from 'fs-extra'; -const {copySync, mkdirpSync} = fs_extra; +const { copySync, mkdirpSync } = fs_extra; -import Store from 'electron-store' -import {promisify} from 'util' -import {join, resolve} from 'path' -import {app} from 'electron' -import {execFile, spawn, spawnSync} from 'child_process' -import {createServer} from 'net' -import state from "./state.js"; -import getPort, {portNumbers} from 'get-port'; -import {ProcessResult} from "./ProcessResult.js"; +import { execFile, spawn, spawnSync } from 'child_process'; +import { app } from 'electron'; +import Store from 'electron-store'; +import getPort, { portNumbers } from 'get-port'; +import { createServer } from 'net'; +import { join } from 'path'; +import { promisify } from 'util'; +import { ProcessResult } from './ProcessResult.js'; +import state from './state.js'; // TODO: maybe in dev, don't go to the userData folder and stay in the Laravel app folder -const storagePath = join(app.getPath('userData'), 'storage') -const databasePath = join(app.getPath('userData'), 'database') -const databaseFile = join(databasePath, 'database.sqlite') -const bootstrapCache = join(app.getPath('userData'), 'bootstrap', 'cache') +const storagePath = join(app.getPath('userData'), 'storage'); +const databasePath = join(app.getPath('userData'), 'database'); +const databaseFile = join(databasePath, 'database.sqlite'); +const bootstrapCache = join(app.getPath('userData'), 'bootstrap', 'cache'); const argumentEnv = getArgumentEnv(); mkdirpSync(bootstrapCache); @@ -28,16 +28,14 @@ mkdirpSync(join(storagePath, 'framework', 'views')); mkdirpSync(join(storagePath, 'framework', 'testing')); function runningSecureBuild() { - return existsSync(join(getAppPath(), 'build', '__nativephp_app_bundle')) - && process.env.NODE_ENV !== 'development'; + return existsSync(join(getAppPath(), 'build', '__nativephp_app_bundle')) && process.env.NODE_ENV !== 'development'; } function shouldMigrateDatabase(store) { - return store.get('migrated_version') !== app.getVersion() - && process.env.NODE_ENV !== 'development'; + return store.get('migrated_version') !== app.getVersion() && process.env.NODE_ENV !== 'development'; } -function shouldOptimize(store) { +function shouldOptimize() { /* * For some weird reason, * the cached config is not picked up on subsequent launches, @@ -46,14 +44,13 @@ function shouldOptimize(store) { return process.env.NODE_ENV !== 'development'; // return runningSecureBuild(); - // return runningSecureBuild() && store.get('optimized_version') !== app.getVersion(); } async function getPhpPort() { // Try get-port first (fast path) const suggestedPort = await getPort({ host: '127.0.0.1', - port: portNumbers(8100, 9000) + port: portNumbers(8100, 9000), }); // Validate that we can actually bind to this port @@ -88,15 +85,19 @@ function canBindToPort(port: number): Promise { } async function retrievePhpIniSettings() { - const env = getDefaultEnvironmentVariables() as any; + const env: NodeJS.ProcessEnv = { + ...process.env, + ...getDefaultEnvironmentVariables(), + }; + const appPath = getAppPath(); const phpOptions = { cwd: appPath, - env + env, }; - let command = ['artisan', 'native:php-ini']; + const command = ['artisan', 'native:php-ini']; if (runningSecureBuild()) { command.unshift(join(appPath, 'build', '__nativephp_app_bundle')); @@ -106,15 +107,18 @@ async function retrievePhpIniSettings() { } async function retrieveNativePHPConfig() { - const env = getDefaultEnvironmentVariables() as any; - const appPath = getAppPath() + const env: NodeJS.ProcessEnv = { + ...process.env, + ...getDefaultEnvironmentVariables(), + }; + const appPath = getAppPath(); const phpOptions = { cwd: appPath, - env + env, }; - let command = ['artisan', 'native:config']; + const command = ['artisan', 'native:config']; if (runningSecureBuild()) { command.unshift(join(appPath, 'build', '__nativephp_app_bundle')); @@ -124,14 +128,13 @@ async function retrieveNativePHPConfig() { } function callPhp(args, options, phpIniSettings = {}) { - if (args[0] === 'artisan' && runningSecureBuild()) { args.unshift(join(getAppPath(), 'build', '__nativephp_app_bundle')); } - let iniSettings = Object.assign(getDefaultPhpIniSettings(), phpIniSettings); + const iniSettings = Object.assign(getDefaultPhpIniSettings(), phpIniSettings); - Object.keys(iniSettings).forEach(key => { + Object.keys(iniSettings).forEach((key) => { args.unshift('-d', `${key}=${iniSettings[key]}`); }); @@ -139,28 +142,23 @@ function callPhp(args, options, phpIniSettings = {}) { console.log('Calling PHP', state.php, args); } - return spawn( - state.php, - args, - { - cwd: options.cwd, - env: { - ...process.env, - ...options.env - }, - } - ); + return spawn(state.php, args, { + cwd: options.cwd, + env: { + ...process.env, + ...options.env, + }, + }); } function callPhpSync(args, options, phpIniSettings = {}) { - if (args[0] === 'artisan' && runningSecureBuild()) { args.unshift(join(getAppPath(), 'build', '__nativephp_app_bundle')); } - let iniSettings = Object.assign(getDefaultPhpIniSettings(), phpIniSettings); + const iniSettings = Object.assign(getDefaultPhpIniSettings(), phpIniSettings); - Object.keys(iniSettings).forEach(key => { + Object.keys(iniSettings).forEach((key) => { args.unshift('-d', `${key}=${iniSettings[key]}`); }); @@ -168,27 +166,23 @@ function callPhpSync(args, options, phpIniSettings = {}) { console.log('Calling PHP', state.php, args); } - return spawnSync( - state.php, - args, - { - cwd: options.cwd, - env: { - ...process.env, - ...options.env - } - } - ); + return spawnSync(state.php, args, { + cwd: options.cwd, + env: { + ...process.env, + ...options.env, + }, + }); } function getArgumentEnv() { - const envArgs = process.argv.filter(arg => arg.startsWith('--env.')); + const envArgs = process.argv.filter((arg) => arg.startsWith('--env.')); const env: { - TESTING?: number, - APP_PATH?: string + TESTING?: number; + APP_PATH?: string; } = {}; - envArgs.forEach(arg => { + envArgs.forEach((arg) => { const [key, value] = arg.slice(6).split('='); env[key] = value; }); @@ -197,7 +191,7 @@ function getArgumentEnv() { } function getAppPath() { - let appPath = state.appPath + let appPath = state.appPath; if (process.env.NODE_ENV === 'development' || argumentEnv.TESTING == 1) { appPath = process.env.APP_PATH || argumentEnv.APP_PATH; @@ -206,25 +200,24 @@ function getAppPath() { } function ensureAppFoldersAreAvailable() { - // if (!runningSecureBuild()) { console.log('Copying storage folder...'); console.log('Storage path:', storagePath); if (!existsSync(storagePath) || process.env.NODE_ENV === 'development') { const appPath = getAppPath(); - console.log("App path:", appPath); - copySync(join(appPath, 'storage'), storagePath) + console.log('App path:', appPath); + copySync(join(appPath, 'storage'), storagePath); } // } - mkdirSync(databasePath, {recursive: true}) + mkdirSync(databasePath, { recursive: true }); // Create a database file if it doesn't exist try { - statSync(databaseFile) - } catch (error) { - writeFileSync(databaseFile, '') + statSync(databaseFile); + } catch { + writeFileSync(databaseFile, ''); } } @@ -234,7 +227,7 @@ function startScheduler(secret, apiPort, phpIniSettings = {}) { const phpOptions = { cwd: appPath, - env + env, }; return callPhp(['artisan', 'schedule:run'], phpOptions, phpIniSettings); @@ -244,7 +237,7 @@ function getPath(name: string) { try { // @ts-ignore return app.getPath(name); - } catch (error) { + } catch { return ''; } } @@ -277,11 +270,13 @@ interface EnvironmentVariables { APP_ROUTES_CACHE?: string; APP_EVENTS_CACHE?: string; VIEW_COMPILED_PATH?: string; + + NIGHTWATCH_INGEST_URI?: string; } function getDefaultEnvironmentVariables(secret?: string, apiPort?: number): EnvironmentVariables { // Base variables with string values (no null values) - let variables: EnvironmentVariables = { + const variables: EnvironmentVariables = { APP_ENV: process.env.NODE_ENV === 'development' ? 'local' : 'production', APP_DEBUG: process.env.NODE_ENV === 'development' ? 'true' : 'false', LARAVEL_STORAGE_PATH: storagePath, @@ -324,95 +319,125 @@ function getDefaultEnvironmentVariables(secret?: string, apiPort?: number): Envi function getDefaultPhpIniSettings() { return { - 'memory_limit': '512M', + memory_limit: '512M', 'curl.cainfo': state.caCert, - 'openssl.cafile': state.caCert - } + 'openssl.cafile': state.caCert, + }; } -function serveApp(secret, apiPort, phpIniSettings): Promise { - return new Promise(async (resolve, reject) => { - const appPath = getAppPath(); - - console.log('Starting PHP server...', `${state.php} artisan serve`, appPath, phpIniSettings) - - ensureAppFoldersAreAvailable(); +async function serveApp(secret, apiPort, phpIniSettings): Promise { + const appPath = getAppPath(); - console.log('Making sure app folders are available') + console.log('Starting PHP server...', `${state.php} artisan serve`, appPath, phpIniSettings); - const env = getDefaultEnvironmentVariables(secret, apiPort); + ensureAppFoldersAreAvailable(); - const phpOptions = { - cwd: appPath, - env - }; + console.log('Making sure app folders are available'); - const store = new Store({ - name: 'nativephp', // So it doesn't conflict with settings of the app - }); + const env = getDefaultEnvironmentVariables(secret, apiPort); - // Cache the project - if (shouldOptimize(store)) { - console.log('Caching view and routes...'); + let phpNightWatchPort: number | undefined; + if (process.env.NIGHTWATCH_TOKEN) { + phpNightWatchPort = await getPhpPort(); + env.NIGHTWATCH_INGEST_URI = `127.0.0.1:${phpNightWatchPort}`; + } - let result = callPhpSync(['artisan', 'optimize'], phpOptions, phpIniSettings); + const phpOptions = { + cwd: appPath, + env, + }; - if (result.status !== 0) { - console.error('Failed to cache view and routes:', result.stderr.toString()); - } else { - store.set('optimized_version', app.getVersion()) - } - } + const store = new Store({ + name: 'nativephp', // So it doesn't conflict with settings of the app + }); - // Migrate the database - if (shouldMigrateDatabase(store)) { - console.log('Migrating database...'); + if (env.NIGHTWATCH_INGEST_URI && phpNightWatchPort) { + console.log('Starting Nightwatch server...'); + callPhp( + ['artisan', 'nightwatch:agent', `--listen-on=${env.NIGHTWATCH_INGEST_URI}`], + phpOptions, + phpIniSettings, + ); + console.log('Nightwatch server started on port:', phpNightWatchPort); + } - if(parseInt(process.env.SHELL_VERBOSITY) > 0) { - console.log('Database path:', databaseFile); - } + // Cache the project + if (shouldOptimize()) { + console.log('Caching view and routes...'); - let result = callPhpSync(['artisan', 'migrate', '--force'], phpOptions, phpIniSettings); + const result = callPhpSync(['artisan', 'optimize'], phpOptions, phpIniSettings); - if (result.status !== 0) { - console.error('Failed to migrate database:', result.stderr.toString()); - } else { - store.set('migrated_version', app.getVersion()) - } + if (result.status !== 0) { + console.error('Failed to cache view and routes:', result.stderr.toString()); + } else { + store.set('optimized_version', app.getVersion()); } + } - if (process.env.NODE_ENV === 'development') { - console.log('Skipping Database migration while in development.') - console.log('You may migrate manually by running: php artisan native:migrate') + // Migrate the database + if (shouldMigrateDatabase(store)) { + console.log('Migrating database...'); + + if (parseInt(process.env.SHELL_VERBOSITY) > 0) { + console.log('Database path:', databaseFile); } - let serverPath: string; - let cwd: string; + const result = callPhpSync(['artisan', 'migrate', '--force'], phpOptions, phpIniSettings); - if (runningSecureBuild()) { - serverPath = join(appPath, 'build', '__nativephp_app_bundle'); + if (result.status !== 0) { + console.error('Failed to migrate database:', result.stderr.toString()); } else { - console.log('* * * Running from source * * *'); - serverPath = join(appPath, 'vendor', 'laravel', 'framework', 'src', 'Illuminate', 'Foundation', 'resources', 'server.php'); - cwd = join(appPath, 'public'); + store.set('migrated_version', app.getVersion()); } + } + + if (process.env.NODE_ENV === 'development') { + console.log('Skipping Database migration while in development.'); + console.log('You may migrate manually by running: php artisan native:migrate'); + } - console.log('Starting PHP server...'); - const phpPort = await getPhpPort(); - const phpServer = callPhp(['-S', `127.0.0.1:${phpPort}`, serverPath], { + let serverPath: string; + let cwd: string; + + if (runningSecureBuild()) { + serverPath = join(appPath, 'build', '__nativephp_app_bundle'); + } else { + console.log('* * * Running from source * * *'); + serverPath = join( + appPath, + 'vendor', + 'laravel', + 'framework', + 'src', + 'Illuminate', + 'Foundation', + 'resources', + 'server.php', + ); + cwd = join(appPath, 'public'); + } + + console.log('Starting PHP server...'); + const phpPort = await getPhpPort(); + const phpServer = callPhp( + ['-S', `127.0.0.1:${phpPort}`, serverPath], + { cwd: cwd, - env - }, phpIniSettings) + env, + }, + phpIniSettings, + ); - const portRegex = /Development Server \(.*:([0-9]+)\) started/gm + const portRegex = /Development Server \(.*:([0-9]+)\) started/gm; + return new Promise((resolve, reject) => { // Show urls called phpServer.stdout.on('data', (data) => { // [Tue Jan 14 19:51:00 2025] 127.0.0.1:52779 [POST] URI: /_native/api/events if (parseInt(process.env.SHELL_VERBOSITY) > 0) { console.log(data.toString().trim()); } - }) + }); // Show PHP errors and indicate which port the server is running on phpServer.stderr.on('data', (data) => { @@ -421,44 +446,42 @@ function serveApp(secret, apiPort, phpIniSettings): Promise { if (match) { const port = parseInt(match[1]); - console.log("PHP Server started on port: ", port); + console.log('PHP Server started on port: ', port); resolve({ port, process: phpServer, }); - } else { - if (error.includes('[NATIVE_EXCEPTION]:')) { - let logFile = join(storagePath, 'logs'); - - console.log(); - console.error('Error in PHP:'); - console.error(' ' + error.split('[NATIVE_EXCEPTION]:')[1].trim()); - console.log('Please check your log files:'); - console.log(' ' + logFile); - console.log(); - } + } else if (error.includes('[NATIVE_EXCEPTION]:')) { + const logFile = join(storagePath, 'logs'); + + console.log(); + console.error('Error in PHP:'); + console.error(' ' + error.split('[NATIVE_EXCEPTION]:')[1].trim()); + console.log('Please check your log files:'); + console.log(' ' + logFile); + console.log(); } }); // Log when any error occurs (not started, not killed, couldn't send message, etc) phpServer.on('error', (error) => { - reject(error) + reject(error); }); // Log when the PHP server exits phpServer.on('close', (code) => { console.log(`PHP server exited with code ${code}`); }); - }) + }); } export { - startScheduler, - serveApp, getAppPath, - retrieveNativePHPConfig, - retrievePhpIniSettings, getDefaultEnvironmentVariables, getDefaultPhpIniSettings, - runningSecureBuild -} + retrieveNativePHPConfig, + retrievePhpIniSettings, + runningSecureBuild, + serveApp, + startScheduler, +}; diff --git a/resources/electron/electron-plugin/src/server/state.ts b/resources/electron/electron-plugin/src/server/state.ts index 503485e2..f2a7d725 100644 --- a/resources/electron/electron-plugin/src/server/state.ts +++ b/resources/electron/electron-plugin/src/server/state.ts @@ -1,69 +1,69 @@ -import {BrowserWindow, Tray, UtilityProcess} from "electron"; -import Store from "electron-store"; -import { notifyLaravel } from "./utils.js"; +import { BrowserWindow, Tray, UtilityProcess } from 'electron'; +import Store from 'electron-store'; +import type { Menubar } from '../libs/menubar/index.js'; +import { notifyLaravel } from './utils.js'; const settingsStore = new Store(); settingsStore.onDidAnyChange((newValue, oldValue) => { - // Only notify of the changed key/value pair - const changedKeys = Object.keys(newValue).filter((key) => newValue[key] !== oldValue[key]); + // Only notify of the changed key/value pair + const changedKeys = Object.keys(newValue).filter((key) => newValue[key] !== oldValue[key]); - changedKeys.forEach((key) => { - notifyLaravel("events", { - event: "Native\\Desktop\\Events\\Settings\\SettingChanged", - payload: { - key, - value: newValue[key] || null, - }, + changedKeys.forEach((key) => { + notifyLaravel('events', { + event: 'Native\\Desktop\\Events\\Settings\\SettingChanged', + payload: { + key, + value: newValue[key] || null, + }, + }); }); - }); }); interface State { - electronApiPort: number | null; - activeMenuBar: any; - tray: Tray | null; - php: string | null; - phpPort: number | null; - phpIni: any; - caCert: string | null; - appPath: string | null; - icon: string | null; - processes: Record}>; - windows: Record; - randomSecret: string; - store: Store; - findWindow: (id: string) => BrowserWindow | null; - dockBounce: number; + electronApiPort: number | null; + activeMenuBar: Menubar | null; + tray: Tray | null; + php: string | null; + phpPort: number | null; + phpIni: Record | null; + caCert: string | null; + appPath: string | null; + icon: string | null; + processes: Record }>; + windows: Record; + randomSecret: string; + store: Store; + findWindow: (id: string) => BrowserWindow | null; + dockBounce: number; } function generateRandomString(length: number) { - let result = ""; - const characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - const charactersLength = characters.length; + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const charactersLength = characters.length; - for (let i = 0; i < length; i += 1) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } + for (let i = 0; i < length; i += 1) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } - return result; + return result; } export default { - electronApiPort: null, - activeMenuBar: null, - tray: null, - php: null, - phpPort: null, - phpIni: null, - caCert: null, - appPath: null, - icon: null, - store: settingsStore, - randomSecret: generateRandomString(32), - processes: {}, - windows: {}, - findWindow(id: string) { - return this.windows[id] || null; - }, + electronApiPort: null, + activeMenuBar: null, + tray: null, + php: null, + phpPort: null, + phpIni: null, + caCert: null, + appPath: null, + icon: null, + store: settingsStore, + randomSecret: generateRandomString(32), + processes: {}, + windows: {}, + findWindow(id: string) { + return this.windows[id] || null; + }, } as State; diff --git a/resources/electron/electron-plugin/src/server/utils.ts b/resources/electron/electron-plugin/src/server/utils.ts index 57ed8964..97c771a5 100644 --- a/resources/electron/electron-plugin/src/server/utils.ts +++ b/resources/electron/electron-plugin/src/server/utils.ts @@ -1,11 +1,11 @@ +import axios from 'axios'; import { session } from 'electron'; import state from './state.js'; -import axios from 'axios'; export async function appendCookie() { const cookie = { url: `http://localhost:${state.phpPort}`, - name: "_php_native", + name: '_php_native', value: state.randomSecret, }; @@ -18,22 +18,18 @@ export async function notifyLaravel(endpoint: string, payload = {}) { } try { - await axios.post( - `http://127.0.0.1:${state.phpPort}/_native/api/${endpoint}`, - payload, - { - headers: { - "X-NativePHP-Secret": state.randomSecret, - }, - } - ); - } catch (e) { + await axios.post(`http://127.0.0.1:${state.phpPort}/_native/api/${endpoint}`, payload, { + headers: { + 'X-NativePHP-Secret': state.randomSecret, + }, + }); + } catch { // } } export function broadcastToWindows(event, payload) { - Object.values(state.windows).forEach(window => { + Object.values(state.windows).forEach((window) => { window.webContents.send(event, payload); }); @@ -45,8 +41,8 @@ export function broadcastToWindows(event, payload) { /** * Remove null and undefined values from an object */ -export function trimOptions(options: any): any { - Object.keys(options).forEach(key => options[key] == null && delete options[key]); +export function trimOptions>(options: T): T { + Object.keys(options).forEach((key) => options[key] == null && delete options[key]); return options; } diff --git a/resources/electron/electron-plugin/src/server/webPreferences.ts b/resources/electron/electron-plugin/src/server/webPreferences.ts index b53b631f..06cca45d 100644 --- a/resources/electron/electron-plugin/src/server/webPreferences.ts +++ b/resources/electron/electron-plugin/src/server/webPreferences.ts @@ -1,6 +1,6 @@ -import { fileURLToPath } from 'url' +import { fileURLToPath } from 'url'; -let preloadPath = fileURLToPath(new URL('../../electron-plugin/dist/preload/index.mjs', import.meta.url)); +const preloadPath = fileURLToPath(new URL('../../electron-plugin/dist/preload/index.mjs', import.meta.url)); const defaultWebPreferences = { spellcheck: false, @@ -12,13 +12,12 @@ const requiredWebPreferences = { sandbox: false, preload: preloadPath, contextIsolation: true, -} +}; -export default function(userWebPreferences: object = {}): object -{ +export default function (userWebPreferences: object = {}): object { return { ...defaultWebPreferences, ...userWebPreferences, - ...requiredWebPreferences - } + ...requiredWebPreferences, + }; } diff --git a/resources/electron/electron-plugin/tests/api.test.ts b/resources/electron/electron-plugin/tests/api.test.ts index 2bcb3b8c..826c4852 100644 --- a/resources/electron/electron-plugin/tests/api.test.ts +++ b/resources/electron/electron-plugin/tests/api.test.ts @@ -1,6 +1,6 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import startAPIServer, { APIProcess } from "../src/server/api"; -import axios from "axios"; +import axios from 'axios'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import startAPIServer, { APIProcess } from '../src/server/api'; vi.mock('electron-updater', () => { return { @@ -56,7 +56,7 @@ describe('API test', () => { response = await axios.get('/api/process', { headers: { 'x-nativephp-secret': 'randomSecret', - } + }, }); } finally { expect(response.status).toBe(200); diff --git a/resources/electron/electron-plugin/tests/mocking.test.ts b/resources/electron/electron-plugin/tests/mocking.test.ts index 494a4cec..569ca11d 100644 --- a/resources/electron/electron-plugin/tests/mocking.test.ts +++ b/resources/electron/electron-plugin/tests/mocking.test.ts @@ -1,9 +1,8 @@ -import { describe, it, expect, vi } from 'vitest'; -import {mockForNodeRequire} from "vitest-mock-commonjs"; +import { describe, expect, it, vi } from 'vitest'; vi.mock('electron'); -import electron, { app, powerMonitor } from 'electron'; // Import the module you want to test +import { app, powerMonitor } from 'electron'; // Import the module you want to test describe('My Electron Module Tests', () => { // it('should return an object for electron', () => { @@ -16,7 +15,7 @@ describe('My Electron Module Tests', () => { }); it('should check if the app is packed', async () => { - const isPackaged = app.isPackaged; // Call the mocked method + const isPackaged = app.isPackaged; // Call the mocked method expect(isPackaged).toBe(false); // Assert the return value }); diff --git a/resources/electron/electron-plugin/tests/setup.ts b/resources/electron/electron-plugin/tests/setup.ts index 79b95f7b..c73c9e96 100644 --- a/resources/electron/electron-plugin/tests/setup.ts +++ b/resources/electron/electron-plugin/tests/setup.ts @@ -1,8 +1,9 @@ // vitest-setup.ts -import { vi } from 'vitest'; -import { mockForNodeRequire } from "vitest-mock-commonjs" +// @ts-ignore import express from 'express'; +import { vi } from 'vitest'; +import { mockForNodeRequire } from 'vitest-mock-commonjs'; // Mock electron mockForNodeRequire('electron', () => ({ @@ -65,13 +66,15 @@ mockForNodeRequire('electron', () => ({ scaleFactor: 1, rotation: 0, }), - getAllDisplays: vi.fn().mockReturnValue([{ - id: 1, - bounds: { x: 0, y: 0, width: 1920, height: 1080 }, - workArea: { x: 0, y: 0, width: 1920, height: 1040 }, - scaleFactor: 1, - rotation: 0, - }]), + getAllDisplays: vi.fn().mockReturnValue([ + { + id: 1, + bounds: { x: 0, y: 0, width: 1920, height: 1080 }, + workArea: { x: 0, y: 0, width: 1920, height: 1040 }, + scaleFactor: 1, + rotation: 0, + }, + ]), }, dialog: { @@ -173,7 +176,7 @@ vi.mock('electron-store', () => { has: vi.fn(), delete: vi.fn(), clear: vi.fn(), - onDidAnyChange: vi.fn().mockImplementation(callback => { + onDidAnyChange: vi.fn().mockImplementation(() => { // Return an unsubscribe function return () => {}; }), diff --git a/resources/electron/electron-plugin/tests/utils.test.ts b/resources/electron/electron-plugin/tests/utils.test.ts index 99d10547..c3c55629 100644 --- a/resources/electron/electron-plugin/tests/utils.test.ts +++ b/resources/electron/electron-plugin/tests/utils.test.ts @@ -1,28 +1,26 @@ -import {describe, expect, it, vi} from 'vitest'; -import {notifyLaravel} from "../src/server/utils"; -import state from "../src/server/state"; -import axios from "axios"; +import axios from 'axios'; +import { describe, expect, it, vi } from 'vitest'; +import state from '../src/server/state'; +import { notifyLaravel } from '../src/server/utils'; vi.mock('axios'); vi.mock('electron-store'); describe('Utils test', () => { - it('notifies laravel', async () => { state.phpPort = 8000; state.randomSecret = 'i-am-secret'; - await notifyLaravel('endpoint', {payload: 'payload'}); + await notifyLaravel('endpoint', { payload: 'payload' }); expect(axios.post).toHaveBeenCalledWith( `http://127.0.0.1:8000/_native/api/endpoint`, - {payload: 'payload'}, + { payload: 'payload' }, { headers: { - "X-NativePHP-Secret": 'i-am-secret', - } - } + 'X-NativePHP-Secret': 'i-am-secret', + }, + }, ); }); - }); diff --git a/resources/electron/electron-plugin/tsconfig.json b/resources/electron/electron-plugin/tsconfig.json index 0b963786..5c1a4f06 100644 --- a/resources/electron/electron-plugin/tsconfig.json +++ b/resources/electron/electron-plugin/tsconfig.json @@ -11,19 +11,9 @@ "preserveConstEnums": true, "removeComments": true, "skipLibCheck": true, - "typeRoots": [ - "../node_modules/@types" - ], - "lib": [ - "es2019", - "dom" - ], - "types": [ - "node", - ] + "typeRoots": ["../node_modules/@types"], + "lib": ["es2019", "dom"], + "types": ["node"] }, - "include": [ - "./src/**/*.ts", - "./src/**/*.mts" - ] + "include": ["./src/**/*.ts", "./src/**/*.mts"] } diff --git a/resources/electron/electron-plugin/vitest.config.mts b/resources/electron/electron-plugin/vitest.config.mts index ee909ed3..2fe36b74 100644 --- a/resources/electron/electron-plugin/vitest.config.mts +++ b/resources/electron/electron-plugin/vitest.config.mts @@ -1,7 +1,7 @@ -import { defineConfig } from 'vitest/config' +import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { setupFiles: ['./tests/setup.ts'], - } -}) + }, +}); diff --git a/resources/electron/electron.vite.config.mjs b/resources/electron/electron.vite.config.mjs index 4af81f9c..45f9816f 100644 --- a/resources/electron/electron.vite.config.mjs +++ b/resources/electron/electron.vite.config.mjs @@ -1,5 +1,5 @@ -import { join } from 'path'; import { defineConfig, externalizeDepsPlugin } from 'electron-vite'; +import { join } from 'path'; export default defineConfig({ main: { @@ -9,12 +9,14 @@ export default defineConfig({ { name: 'watch-external', buildStart() { - this.addWatchFile(join(process.env.APP_PATH, 'app', 'Providers', 'NativeAppServiceProvider.php')); - } - } - ] + this.addWatchFile( + join(process.env.APP_PATH, 'app', 'Providers', 'NativeAppServiceProvider.php'), + ); + }, + }, + ], }, }, - plugins: [externalizeDepsPlugin()] - } + plugins: [externalizeDepsPlugin()], + }, }); diff --git a/resources/electron/eslint.config.js b/resources/electron/eslint.config.js index fb7840e3..fb072f7c 100644 --- a/resources/electron/eslint.config.js +++ b/resources/electron/eslint.config.js @@ -2,10 +2,16 @@ import globals from "globals"; import pluginJs from "@eslint/js"; import tseslint from "typescript-eslint"; import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; -import eslintPluginUnicorn from "eslint-plugin-unicorn"; +import { defineConfig, globalIgnores } from "eslint/config"; +// import eslintPluginUnicorn from "eslint-plugin-unicorn"; /** @type {import('eslint').Linter.Config[]} */ -export default [ +export default defineConfig([ + globalIgnores([ + "electron-plugin/dist/**/*", + "out/**/*", + 'electron-plugin/src/preload/livewire-dispatcher.js' + ]), { files: ["**/*.{js,mjs,cjs,ts}"], }, @@ -21,6 +27,25 @@ export default [ pluginJs.configs.recommended, ...tseslint.configs.recommended, eslintPluginPrettierRecommended, + { + rules: { + "@typescript-eslint/ban-ts-comment": [ + "error", + { + "ts-ignore": false, + "ts-expect-error": false, + "ts-nocheck": false, + "ts-check": false + } + ], + "prettier/prettier": [ + "error", + { + "singleQuote": true + } + ] + } + }, // { // languageOptions: { // globals: globals.builtin, @@ -32,4 +57,4 @@ export default [ // 'unicorn/prefer-module': 'error', // }, // }, -]; +]); diff --git a/resources/electron/package-lock.json b/resources/electron/package-lock.json index 7b818484..7e26d947 100644 --- a/resources/electron/package-lock.json +++ b/resources/electron/package-lock.json @@ -13,7 +13,7 @@ "@electron-toolkit/utils": "^4.0.0", "@electron/remote": "^2.1.2", "axios": "^1.7.9", - "body-parser": "^2.2.0", + "body-parser": "^2.2.1", "electron-context-menu": "^4.0.4", "electron-store": "^10.0.0", "electron-updater": "^6.3.9", @@ -59,6 +59,7 @@ "globals": "^16.0.0", "less": "^4.2.1", "prettier": "^3.4.2", + "prettier-plugin-organize-imports": "^4.3", "rimraf": "^6.0.1", "stylelint": "^16.12.0", "stylelint-config-recommended": "^16.0.0", @@ -1806,40 +1807,49 @@ "node": ">=6.9.0" } }, + "node_modules/@cacheable/memoize": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@cacheable/memoize/-/memoize-2.0.3.tgz", + "integrity": "sha512-hl9wfQgpiydhQEIv7fkjEzTGE+tcosCXLKFDO707wYJ/78FVOlowb36djex5GdbSyeHnG62pomYLMuV/OT8Pbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.0.3" + } + }, "node_modules/@cacheable/memory": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.7.tgz", - "integrity": "sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.4.tgz", + "integrity": "sha512-cCmJKCKlT1t7hNBI1+gFCwmKFd9I4pS3zqBeNGXTSODnpa0EeDmORHY8oEMTuozfdg3cgsVh8ojLaPYb6eC7Cg==", "dev": true, "license": "MIT", "dependencies": { - "@cacheable/utils": "^2.3.3", - "@keyv/bigmap": "^1.3.0", - "hookified": "^1.14.0", - "keyv": "^5.5.5" + "@cacheable/utils": "^2.2.0", + "@keyv/bigmap": "^1.1.0", + "hookified": "^1.12.2", + "keyv": "^5.5.3" } }, "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.0.tgz", - "integrity": "sha512-KT01GjzV6AQD5+IYrcpoYLkCu1Jod3nau1Z7EsEuViO3TZGRacSbO9MfHmbJ1WaOXFtWLxPVj169cn2WNKPkIg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.1.0.tgz", + "integrity": "sha512-MX7XIUNwVRK+hjZcAbNJ0Z8DREo+Weu9vinBOjGU1thEi9F6vPhICzBbk4CCf3eEefKRz7n6TfZXwUFZTSgj8Q==", "dev": true, "license": "MIT", "dependencies": { - "hashery": "^1.2.0", - "hookified": "^1.13.0" + "hookified": "^1.12.2" }, "engines": { "node": ">= 18" }, "peerDependencies": { - "keyv": "^5.5.4" + "keyv": "^5.5.3" } }, "node_modules/@cacheable/memory/node_modules/keyv": { - "version": "5.5.5", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.5.tgz", - "integrity": "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.3.tgz", + "integrity": "sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==", "dev": true, "license": "MIT", "dependencies": { @@ -1847,20 +1857,19 @@ } }, "node_modules/@cacheable/utils": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.3.3.tgz", - "integrity": "sha512-JsXDL70gQ+1Vc2W/KUFfkAJzgb4puKwwKehNLuB+HrNKWf91O736kGfxn4KujXCCSuh6mRRL4XEB0PkAFjWS0A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.2.0.tgz", + "integrity": "sha512-7xaQayO3msdVcxXLYcLU5wDqJBNdQcPPPHr6mdTEIQI7N7TbtSVVTpWOTfjyhg0L6AQwQdq7miKdWtTDBoBldQ==", "dev": true, "license": "MIT", "dependencies": { - "hashery": "^1.3.0", - "keyv": "^5.5.5" + "keyv": "^5.5.3" } }, "node_modules/@cacheable/utils/node_modules/keyv": { - "version": "5.5.5", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.5.tgz", - "integrity": "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.3.tgz", + "integrity": "sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==", "dev": true, "license": "MIT", "dependencies": { @@ -1914,26 +1923,6 @@ "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.22.tgz", - "integrity": "sha512-qBcx6zYlhleiFfdtzkRgwNC7VVoAwfK76Vmsw5t+PbvtdknO9StgRk7ROvq9so1iqbdW4uLIDAsXRsTfUrIoOw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - } - }, "node_modules/@csstools/css-tokenizer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", @@ -2759,9 +2748,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { @@ -2853,9 +2842,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2865,7 +2854,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", + "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -2924,9 +2913,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", "dev": true, "license": "MIT", "engines": { @@ -3060,6 +3049,19 @@ "node": ">=12" } }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", @@ -3098,6 +3100,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -3376,9 +3394,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", "cpu": [ "arm" ], @@ -3390,9 +3408,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", "cpu": [ "arm64" ], @@ -3404,9 +3422,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", "cpu": [ "arm64" ], @@ -3418,9 +3436,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz", + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", "cpu": [ "x64" ], @@ -3432,9 +3450,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", "cpu": [ "arm64" ], @@ -3446,9 +3464,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", "cpu": [ "x64" ], @@ -3460,9 +3478,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", "cpu": [ "arm" ], @@ -3474,9 +3492,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", "cpu": [ "arm" ], @@ -3488,9 +3506,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", "cpu": [ "arm64" ], @@ -3502,9 +3520,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", "cpu": [ "arm64" ], @@ -3516,23 +3534,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", "cpu": [ "loong64" ], @@ -3544,23 +3548,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", "cpu": [ "ppc64" ], @@ -3572,9 +3562,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", "cpu": [ "riscv64" ], @@ -3586,9 +3576,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", "cpu": [ "riscv64" ], @@ -3600,9 +3590,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", "cpu": [ "s390x" ], @@ -3614,9 +3604,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", "cpu": [ "x64" ], @@ -3628,9 +3618,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", "cpu": [ "x64" ], @@ -3641,24 +3631,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", "cpu": [ "arm64" ], @@ -3670,9 +3646,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", "cpu": [ "arm64" ], @@ -3684,9 +3660,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", "cpu": [ "ia32" ], @@ -3698,9 +3674,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", "cpu": [ "x64" ], @@ -3712,9 +3688,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", "cpu": [ "x64" ], @@ -3726,9 +3702,9 @@ ] }, "node_modules/@rushstack/eslint-patch": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", - "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.14.1.tgz", + "integrity": "sha512-jGTk8UD/RdjsNZW8qq10r0RBvxL8OWtoT+kImlzPDFilmozzM+9QmIJsmze9UiSBrFU45ZxhTYBypn9q9z/VfQ==", "dev": true, "license": "MIT" }, @@ -3828,9 +3804,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true, "license": "MIT" }, @@ -3924,15 +3900,15 @@ "license": "MIT" }, "node_modules/@types/express": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", - "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.5.tgz", + "integrity": "sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==", "dev": true, "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "^2" + "@types/serve-static": "^1" } }, "node_modules/@types/express-serve-static-core": { @@ -3987,6 +3963,13 @@ "@types/node": "*" } }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -3995,9 +3978,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz", - "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "version": "22.19.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.0.tgz", + "integrity": "sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -4063,13 +4046,25 @@ } }, "node_modules/@types/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "dev": true, "license": "MIT", "dependencies": { "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", "@types/node": "*" } }, @@ -4092,20 +4087,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.52.0.tgz", - "integrity": "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.3.tgz", + "integrity": "sha512-sbaQ27XBUopBkRiuY/P9sWGOWUW4rl8fDoHIUmLpZd8uldsTyB4/Zg6bWTegPoTLnKj9Hqgn3QD6cjPNB32Odw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.52.0", - "@typescript-eslint/type-utils": "8.52.0", - "@typescript-eslint/utils": "8.52.0", - "@typescript-eslint/visitor-keys": "8.52.0", - "ignore": "^7.0.5", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.3", + "@typescript-eslint/type-utils": "8.46.3", + "@typescript-eslint/utils": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4115,23 +4111,23 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.52.0", + "@typescript-eslint/parser": "^8.46.3", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.52.0.tgz", - "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.3.tgz", + "integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.52.0", - "@typescript-eslint/types": "8.52.0", - "@typescript-eslint/typescript-estree": "8.52.0", - "@typescript-eslint/visitor-keys": "8.52.0", - "debug": "^4.4.3" + "@typescript-eslint/scope-manager": "8.46.3", + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/typescript-estree": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4146,15 +4142,15 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.52.0.tgz", - "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.3.tgz", + "integrity": "sha512-Fz8yFXsp2wDFeUElO88S9n4w1I4CWDTXDqDr9gYvZgUpwXQqmZBr9+NTTql5R3J7+hrJZPdpiWaB9VNhAKYLuQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.52.0", - "@typescript-eslint/types": "^8.52.0", - "debug": "^4.4.3" + "@typescript-eslint/tsconfig-utils": "^8.46.3", + "@typescript-eslint/types": "^8.46.3", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4168,14 +4164,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.52.0.tgz", - "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.3.tgz", + "integrity": "sha512-FCi7Y1zgrmxp3DfWfr+3m9ansUUFoy8dkEdeQSgA9gbm8DaHYvZCdkFRQrtKiedFf3Ha6VmoqoAaP68+i+22kg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.52.0", - "@typescript-eslint/visitor-keys": "8.52.0" + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4186,9 +4182,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz", - "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.3.tgz", + "integrity": "sha512-GLupljMniHNIROP0zE7nCcybptolcH8QZfXOpCfhQDAdwJ/ZTlcaBOYebSOZotpti/3HrHSw7D3PZm75gYFsOA==", "dev": true, "license": "MIT", "engines": { @@ -4203,17 +4199,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.52.0.tgz", - "integrity": "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.3.tgz", + "integrity": "sha512-ZPCADbr+qfz3aiTTYNNkCbUt+cjNwI/5McyANNrFBpVxPt7GqpEYz5ZfdwuFyGUnJ9FdDXbGODUu6iRCI6XRXw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.52.0", - "@typescript-eslint/typescript-estree": "8.52.0", - "@typescript-eslint/utils": "8.52.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/typescript-estree": "8.46.3", + "@typescript-eslint/utils": "8.46.3", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4228,9 +4224,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.52.0.tgz", - "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.3.tgz", + "integrity": "sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA==", "dev": true, "license": "MIT", "engines": { @@ -4242,21 +4238,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz", - "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.3.tgz", + "integrity": "sha512-f/NvtRjOm80BtNM5OQtlaBdM5BRFUv7gf381j9wygDNL+qOYSNOgtQ/DCndiYi80iIOv76QqaTmp4fa9hwI0OA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.52.0", - "@typescript-eslint/tsconfig-utils": "8.52.0", - "@typescript-eslint/types": "8.52.0", - "@typescript-eslint/visitor-keys": "8.52.0", - "debug": "^4.4.3", - "minimatch": "^9.0.5", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" + "@typescript-eslint/project-service": "8.46.3", + "@typescript-eslint/tsconfig-utils": "8.46.3", + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4283,16 +4280,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.52.0.tgz", - "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.3.tgz", + "integrity": "sha512-VXw7qmdkucEx9WkmR3ld/u6VhRyKeiF1uxWwCy/iuNfokjJ7VhsgLSOTjsol8BunSw190zABzpwdNsze2Kpo4g==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.52.0", - "@typescript-eslint/types": "8.52.0", - "@typescript-eslint/typescript-estree": "8.52.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.3", + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/typescript-estree": "8.46.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4307,13 +4304,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz", - "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.3.tgz", + "integrity": "sha512-uk574k8IU0rOF/AjniX8qbLSGURJVUCeM5e4MIMKBFFi8weeiLrG1fyQejyLXQpRZbU/1BuQasleV/RfHC3hHg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/types": "8.46.3", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -4654,15 +4651,13 @@ } }, "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=8" } }, "node_modules/ansi-styles": { @@ -5036,9 +5031,9 @@ } }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", + "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -5116,9 +5111,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.11", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", - "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", + "version": "2.8.23", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", + "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5167,9 +5162,9 @@ } }, "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", @@ -5178,7 +5173,7 @@ "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", - "qs": "^6.14.1", + "qs": "^6.14.0", "raw-body": "^3.0.1", "type-is": "^2.0.1" }, @@ -5190,6 +5185,22 @@ "url": "https://opencollective.com/express" } }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", + "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -5221,9 +5232,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", "dev": true, "funding": [ { @@ -5241,11 +5252,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" @@ -5545,17 +5556,18 @@ } }, "node_modules/cacheable": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.1.tgz", - "integrity": "sha512-yr+FSHWn1ZUou5LkULX/S+jhfgfnLbuKQjE40tyEd4fxGZVMbBL5ifno0J0OauykS8UiCSgHi+DV/YD+rjFxFg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.1.1.tgz", + "integrity": "sha512-LmF4AXiSNdiRbI2UjH8pAp9NIXxeQsTotpEaegPiDcnN0YPygDJDV3l/Urc0mL72JWdATEorKqIHEx55nDlONg==", "dev": true, "license": "MIT", "dependencies": { - "@cacheable/memory": "^2.0.6", - "@cacheable/utils": "^2.3.2", - "hookified": "^1.14.0", - "keyv": "^5.5.5", - "qified": "^0.5.3" + "@cacheable/memoize": "^2.0.3", + "@cacheable/memory": "^2.0.3", + "@cacheable/utils": "^2.1.0", + "hookified": "^1.12.2", + "keyv": "^5.5.3", + "qified": "^0.5.0" } }, "node_modules/cacheable-lookup": { @@ -5586,9 +5598,9 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.5.5", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.5.tgz", - "integrity": "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.3.tgz", + "integrity": "sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==", "dev": true, "license": "MIT", "dependencies": { @@ -5635,9 +5647,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001762", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz", - "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==", + "version": "1.0.30001753", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", + "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", "dev": true, "funding": [ { @@ -5690,9 +5702,9 @@ } }, "node_modules/check-error": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", - "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", "engines": { @@ -5858,16 +5870,6 @@ "node": ">=12" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -5900,19 +5902,6 @@ "node": ">=8" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -6108,9 +6097,9 @@ } }, "node_modules/config-file-ts/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { @@ -6152,16 +6141,15 @@ "license": "ISC" }, "node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "safe-buffer": "5.2.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "engines": { + "node": ">= 0.6" } }, "node_modules/content-type": { @@ -6212,13 +6200,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", - "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", + "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.28.0" + "browserslist": "^4.26.3" }, "funding": { "type": "opencollective", @@ -6673,19 +6661,6 @@ "node": ">=12" } }, - "node_modules/dmg-builder/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/dmg-builder/node_modules/jsonfile": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", @@ -6814,9 +6789,9 @@ } }, "node_modules/electron": { - "version": "38.7.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-38.7.2.tgz", - "integrity": "sha512-BcjR0IHqp3uv4ytVQwW2/9zAWo17Rjwrydn6RS+g+vqhpcPTzmBHDCHKaEcqheSl/7zzKPgFZdvT21BoSfrxRQ==", + "version": "38.5.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-38.5.0.tgz", + "integrity": "sha512-dbC7V+eZweerYMJfxQldzHOg37a1VdNMCKxrJxlkp3cA30gOXtXSg4ZYs07L5+QwI19WOy1uyvtEUgbw1RRsCQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -6930,9 +6905,9 @@ } }, "node_modules/electron-chromedriver": { - "version": "38.7.2", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-38.7.2.tgz", - "integrity": "sha512-YeBGZdefDqwI4IiGTDIbTKFAOhWKOgjBjX9raz5OC9GNBIvZVXM0z2qjd11R8HZ9FGCdp5Jy6jYZtjjYeP5ucQ==", + "version": "38.4.0", + "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-38.4.0.tgz", + "integrity": "sha512-7VEWRdEZ8b8sNV6GoFCg+ILiw66O0ImyFxcqtrp1Zx1E7WefGtlq9LTxf8KXwwClU1rAiATNb6VwbEmWDROYDw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7054,32 +7029,32 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.244", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", "dev": true, "license": "ISC" }, "node_modules/electron-updater": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.7.3.tgz", - "integrity": "sha512-EgkT8Z9noqXKbwc3u5FkJA+r48jwZ5DTUiOkJMOTEEH//n5Am6wfQGz7nvSFEA2oIAMv9jRzn5JKTyWeSKOPgg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.6.2.tgz", + "integrity": "sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==", "license": "MIT", "dependencies": { - "builder-util-runtime": "9.5.1", + "builder-util-runtime": "9.3.1", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", - "semver": "~7.7.3", + "semver": "^7.6.3", "tiny-typed-emitter": "^2.1.0" } }, "node_modules/electron-updater/node_modules/builder-util-runtime": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", - "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz", + "integrity": "sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==", "license": "MIT", "dependencies": { "debug": "^4.3.4", @@ -7196,20 +7171,6 @@ "iconv-lite": "^0.6.2" } }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -7402,9 +7363,9 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", "dependencies": { @@ -7414,7 +7375,7 @@ "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", + "@eslint/js": "9.39.1", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -7677,9 +7638,9 @@ } }, "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7777,9 +7738,9 @@ } }, "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -7794,19 +7755,18 @@ "license": "Apache-2.0" }, "node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "license": "MIT", "dependencies": { "accepts": "^2.0.0", - "body-parser": "^2.2.1", + "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", - "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", @@ -7986,9 +7946,9 @@ } }, "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { @@ -8053,9 +8013,9 @@ } }, "node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -8066,11 +8026,7 @@ "statuses": "^2.0.1" }, "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.8" } }, "node_modules/find-exec": { @@ -8128,6 +8084,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fix-path/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/fix-path/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -8200,9 +8183,9 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -8263,9 +8246,9 @@ "peer": true }, "node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -8352,16 +8335,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/gauge/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8394,19 +8367,6 @@ "node": ">=8" } }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -8745,6 +8705,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -8802,19 +8769,6 @@ "dev": true, "license": "ISC" }, - "node_modules/hashery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.4.0.tgz", - "integrity": "sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "hookified": "^1.14.0" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -8828,9 +8782,9 @@ } }, "node_modules/hookified": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.0.tgz", - "integrity": "sha512-51w+ZZGt7Zw5q7rM3nC4t3aLn/xvKDETsXqMczndvwyVQhAHfUmUuFBRFcos8Iyebtk7OAE9dL26wFNzZVVOkw==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.12.2.tgz", + "integrity": "sha512-aokUX1VdTpI0DUsndvW+OiwmBpKCu/NgRsSSkuSY0zq8PY6Q6a+lmOfAFDXAAOtBqJELvcWY9L1EVtzjbQcMdg==", "dev": true, "license": "MIT" }, @@ -8887,23 +8841,28 @@ "license": "BSD-2-Clause" }, "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" } }, "node_modules/http-proxy-agent": { @@ -8984,17 +8943,6 @@ "node": "^8.11.2 || >=10" } }, - "node_modules/iconv-corefoundation/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/iconv-corefoundation/node_modules/cli-truncate": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", @@ -9064,34 +9012,17 @@ "node": ">=8" } }, - "node_modules/iconv-corefoundation/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/iconv-lite": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", - "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" } }, "node_modules/ieee754": { @@ -9231,9 +9162,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "dev": true, "license": "MIT", "engines": { @@ -9454,9 +9385,9 @@ "peer": true }, "node_modules/isbinaryfile": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", - "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", "dev": true, "license": "MIT", "engines": { @@ -9514,9 +9445,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -9559,9 +9490,9 @@ "license": "MIT" }, "node_modules/json-schema-typed": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", - "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.1.tgz", + "integrity": "sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==", "license": "BSD-2-Clause" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -9689,11 +9620,10 @@ } }, "node_modules/less": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/less/-/less-4.5.1.tgz", - "integrity": "sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/less/-/less-4.4.2.tgz", + "integrity": "sha512-j1n1IuTX1VQjIy3tT7cyGbX7nvQOsFLoIqobZv4ttI5axP923gA44zUj6miiA6R5Aoms4sEGVIIcucXUbRI14g==", "dev": true, - "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "copy-anything": "^2.0.1", @@ -10151,19 +10081,15 @@ } }, "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.6" } }, "node_modules/mimic-fn": { @@ -10394,20 +10320,6 @@ "node": ">= 4.4.x" } }, - "node_modules/needle/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -10418,9 +10330,9 @@ } }, "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "version": "3.80.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.80.0.tgz", + "integrity": "sha512-LyPuZJcI9HVwzXK1GPxWNzrr+vr8Hp/3UqlmWxxh8p54U1ZbclOqbSog9lWHaCX+dBaiGi6n/hIX+mKu74GmPA==", "dev": true, "license": "MIT", "dependencies": { @@ -10538,9 +10450,9 @@ "license": "MIT" }, "node_modules/nodemon": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz", - "integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", "license": "MIT", "dependencies": { "chokidar": "^3.5.2", @@ -10834,29 +10746,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -11261,9 +11150,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", - "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, "license": "MIT", "dependencies": { @@ -11292,9 +11181,9 @@ } }, "node_modules/prettier": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", - "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -11308,9 +11197,9 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", - "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "license": "MIT", "dependencies": { @@ -11320,6 +11209,23 @@ "node": ">=6.0.0" } }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", + "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0 || 3" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -11436,22 +11342,22 @@ } }, "node_modules/qified": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/qified/-/qified-0.5.3.tgz", - "integrity": "sha512-kXuQdQTB6oN3KhI6V4acnBSZx8D2I4xzZvn9+wFLLFCoBNQY/sFnCW6c43OL7pOQ2HvGV4lnWIXNmgfp7cTWhQ==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.5.1.tgz", + "integrity": "sha512-+BtFN3dCP+IaFA6IYNOu/f/uK1B8xD2QWyOeCse0rjtAebBmkzgd2d1OAXi3ikAzJMIBSdzZDNZ3wZKEUDQs5w==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.13.0" + "hookified": "^1.12.2" }, "engines": { "node": ">=20" } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -11506,20 +11412,36 @@ } }, "node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" }, "engines": { "node": ">= 0.10" } }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/read-binary-file-arch": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", @@ -11839,13 +11761,13 @@ } }, "node_modules/rimraf": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", - "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.0.tgz", + "integrity": "sha512-DxdlA1bdNzkZK7JiNWH+BAx1x4tEJWoTofIopFo6qWUU94jYrFZ0ubY05TqH3nWPJ1nKa1JWVFDINZ3fnrle/A==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "glob": "^13.0.0", + "glob": "^11.0.3", "package-json-from-dist": "^1.0.1" }, "bin": { @@ -11859,16 +11781,22 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", - "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "dependencies": { - "minimatch": "^10.1.1", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, "engines": { "node": "20 || >=22" }, @@ -11876,12 +11804,28 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", - "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "node_modules/rimraf/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "dev": true, + "license": "ISC", "engines": { "node": "20 || >=22" } @@ -11913,9 +11857,9 @@ } }, "node_modules/rimraf/node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -11948,9 +11892,9 @@ } }, "node_modules/rollup": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz", + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", "dev": true, "license": "MIT", "dependencies": { @@ -11964,31 +11908,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", + "@rollup/rollup-android-arm-eabi": "4.52.5", + "@rollup/rollup-android-arm64": "4.52.5", + "@rollup/rollup-darwin-arm64": "4.52.5", + "@rollup/rollup-darwin-x64": "4.52.5", + "@rollup/rollup-freebsd-arm64": "4.52.5", + "@rollup/rollup-freebsd-x64": "4.52.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", + "@rollup/rollup-linux-arm-musleabihf": "4.52.5", + "@rollup/rollup-linux-arm64-gnu": "4.52.5", + "@rollup/rollup-linux-arm64-musl": "4.52.5", + "@rollup/rollup-linux-loong64-gnu": "4.52.5", + "@rollup/rollup-linux-ppc64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-musl": "4.52.5", + "@rollup/rollup-linux-s390x-gnu": "4.52.5", + "@rollup/rollup-linux-x64-gnu": "4.52.5", + "@rollup/rollup-linux-x64-musl": "4.52.5", + "@rollup/rollup-openharmony-arm64": "4.52.5", + "@rollup/rollup-win32-arm64-msvc": "4.52.5", + "@rollup/rollup-win32-ia32-msvc": "4.52.5", + "@rollup/rollup-win32-x64-gnu": "4.52.5", + "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" } }, @@ -12036,7 +11977,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -12070,9 +12010,9 @@ } }, "node_modules/sax": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.2.tgz", + "integrity": "sha512-FySGAa0RGcFiN6zfrO9JvK1r7TB59xuzCcTHOBXBNoKgDejlOQCR2KL/FGk3/iDlsqyYg1ELZpOmlg09B01Czw==", "license": "BlueOak-1.0.0" }, "node_modules/semver": { @@ -12092,29 +12032,25 @@ "optional": true }, "node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", "dependencies": { - "debug": "^4.4.3", + "debug": "^4.3.5", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", - "statuses": "^2.0.2" + "statuses": "^2.0.1" }, "engines": { "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" } }, "node_modules/serialize-error": { @@ -12147,9 +12083,9 @@ } }, "node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", @@ -12159,10 +12095,6 @@ }, "engines": { "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" } }, "node_modules/set-blocking": { @@ -12216,6 +12148,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/shell-env/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/shell-env/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/shell-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/shell-path/-/shell-path-3.1.0.tgz", @@ -12631,16 +12590,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -12658,20 +12607,19 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/strip-ansi": { + "node_modules/string-width/node_modules/strip-ansi": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", @@ -12686,8 +12634,7 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", + "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -12700,12 +12647,16 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { "node": ">=8" } @@ -12788,9 +12739,9 @@ "license": "ISC" }, "node_modules/stylelint": { - "version": "16.26.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.26.1.tgz", - "integrity": "sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==", + "version": "16.25.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.25.0.tgz", + "integrity": "sha512-Li0avYWV4nfv1zPbdnxLYBGq4z8DVZxbRgx4Kn6V+Uftz1rMoF1qiEI3oL4kgWqyYgCgs7gT5maHNZ82Gk03vQ==", "dev": true, "funding": [ { @@ -12805,7 +12756,6 @@ "license": "MIT", "dependencies": { "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-syntax-patches-for-csstree": "^1.0.19", "@csstools/css-tokenizer": "^3.0.4", "@csstools/media-query-list-parser": "^4.0.3", "@csstools/selector-specificity": "^5.0.0", @@ -12818,7 +12768,7 @@ "debug": "^4.4.3", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^11.1.1", + "file-entry-cache": "^10.1.4", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -12894,28 +12844,35 @@ } }, "node_modules/stylelint-scss": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.14.0.tgz", - "integrity": "sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA==", + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.12.1.tgz", + "integrity": "sha512-UJUfBFIvXfly8WKIgmqfmkGKPilKB4L5j38JfsDd+OCg2GBdU0vGUV08Uw82tsRZzd4TbsUURVVNGeOhJVF7pA==", "dev": true, "license": "MIT", "dependencies": { "css-tree": "^3.0.1", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.37.0", - "mdn-data": "^2.25.0", + "known-css-properties": "^0.36.0", + "mdn-data": "^2.21.0", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.6", - "postcss-selector-parser": "^7.1.1", + "postcss-selector-parser": "^7.1.0", "postcss-value-parser": "^4.2.0" }, "engines": { "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.8.2" + "stylelint": "^16.0.2" } }, + "node_modules/stylelint-scss/node_modules/known-css-properties": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", + "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", + "dev": true, + "license": "MIT" + }, "node_modules/stylelint-scss/node_modules/mdn-data": { "version": "2.25.0", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.25.0.tgz", @@ -12923,16 +12880,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/stylelint/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/stylelint/node_modules/balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", @@ -12948,25 +12895,25 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.1.tgz", - "integrity": "sha512-TPVFSDE7q91Dlk1xpFLvFllf8r0HyOMOlnWy7Z2HBku5H3KhIeOGInexrIeg2D64DosVB/JXkrrk6N/7Wriq4A==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.4.tgz", + "integrity": "sha512-5XRUFc0WTtUbjfGzEwXc42tiGxQHBmtbUG1h9L2apu4SulCGN3Hqm//9D6FAolf8MYNL7f/YlJl9vy08pj5JuA==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.19" + "flat-cache": "^6.1.13" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.19", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.19.tgz", - "integrity": "sha512-l/K33newPTZMTGAnnzaiqSl6NnH7Namh8jBNjrgjprWxGmZUuxx/sJNIRaijOh3n7q7ESbhNZC+pvVZMFdeU4A==", + "version": "6.1.18", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.18.tgz", + "integrity": "sha512-JUPnFgHMuAVmLmoH9/zoZ6RHOt5n9NlUw/sDXsTbROJ2SFoS2DS4s+swAV6UTeTbGH/CAsZIE6M8TaG/3jVxgQ==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^2.2.0", + "cacheable": "^2.1.0", "flatted": "^3.3.3", - "hookified": "^1.13.0" + "hookified": "^1.12.0" } }, "node_modules/stylelint/node_modules/is-fullwidth-code-point": { @@ -13004,19 +12951,6 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -13137,16 +13071,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/table/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -13204,19 +13128,6 @@ "node": ">=8" } }, - "node_modules/table/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -13490,9 +13401,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { @@ -13607,16 +13518,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.52.0.tgz", - "integrity": "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA==", + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.3.tgz", + "integrity": "sha512-bAfgMavTuGo+8n6/QQDVQz4tZ4f7Soqg53RbrlZQEoAltYop/XR4RAts/I0BrO3TTClTSTFJ0wYbla+P8cEWJA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.52.0", - "@typescript-eslint/parser": "8.52.0", - "@typescript-eslint/typescript-estree": "8.52.0", - "@typescript-eslint/utils": "8.52.0" + "@typescript-eslint/eslint-plugin": "8.46.3", + "@typescript-eslint/parser": "8.46.3", + "@typescript-eslint/typescript-estree": "8.46.3", + "@typescript-eslint/utils": "8.46.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -13793,9 +13704,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", "dev": true, "funding": [ { @@ -13891,13 +13802,13 @@ } }, "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "version": "7.1.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", + "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", + "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -13988,490 +13899,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" - } - }, "node_modules/vite/node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -14654,16 +14081,6 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/wide-align/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -14696,19 +14113,6 @@ "node": ">=8" } }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -14756,16 +14160,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -14798,29 +14192,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -14853,19 +14224,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -14955,16 +14313,6 @@ "node": ">=12" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -14997,19 +14345,6 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yauzl": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.2.0.tgz", diff --git a/resources/electron/package.json b/resources/electron/package.json index 31d231f4..0fdd3dad 100644 --- a/resources/electron/package.json +++ b/resources/electron/package.json @@ -44,7 +44,7 @@ "@electron-toolkit/utils": "^4.0.0", "@electron/remote": "^2.1.2", "axios": "^1.7.9", - "body-parser": "^2.2.0", + "body-parser": "^2.2.1", "electron-context-menu": "^4.0.4", "electron-store": "^10.0.0", "electron-updater": "^6.3.9", @@ -90,6 +90,7 @@ "globals": "^16.0.0", "less": "^4.2.1", "prettier": "^3.4.2", + "prettier-plugin-organize-imports": "^4.3", "rimraf": "^6.0.1", "stylelint": "^16.12.0", "stylelint-config-recommended": "^16.0.0", diff --git a/resources/electron/php.js b/resources/electron/php.js index e9f3ed96..4efd272a 100644 --- a/resources/electron/php.js +++ b/resources/electron/php.js @@ -1,9 +1,8 @@ -import fs from "fs"; +import fs from 'fs'; import fs_extra from 'fs-extra'; -const { copySync, removeSync, ensureDirSync } = fs_extra; -import { join } from "path"; -import unzip from "yauzl"; - +import { join } from 'path'; +import unzip from 'yauzl'; +const { removeSync, ensureDirSync } = fs_extra; const isBuilding = Boolean(process.env.NATIVEPHP_BUILDING); const phpBinaryPath = process.env.NATIVEPHP_PHP_BINARY_PATH; @@ -11,15 +10,15 @@ const phpVersion = process.env.NATIVEPHP_PHP_BINARY_VERSION; // Differentiates for Serving and Building const isArm64 = isBuilding ? process.argv.includes('--arm64') : process.arch.includes('arm64'); -const isWindows = isBuilding ? process.argv.includes('--win') : process.platform.includes('win32'); -const isLinux = isBuilding ? process.argv.includes('--linux') : process.platform.includes('linux'); -const isDarwin = isBuilding ? process.argv.includes('--mac') : process.platform.includes('darwin'); +const isWindows = isBuilding ? process.argv.includes('--win') : process.platform.includes('win32'); +const isLinux = isBuilding ? process.argv.includes('--linux') : process.platform.includes('linux'); +const isDarwin = isBuilding ? process.argv.includes('--mac') : process.platform.includes('darwin'); // false because string mapping is done in is{OS} checks const platform = { os: false, arch: false, - phpBinary: 'php' + phpBinary: 'php', }; if (isWindows) { @@ -65,10 +64,10 @@ if (platform.phpBinary) { ensureDirSync(binaryDestDir); // Unzip the files - unzip.open(binarySrcDir, {lazyEntries: true}, function (err, zipfile) { + unzip.open(binarySrcDir, { lazyEntries: true }, function (err, zipfile) { if (err) throw err; zipfile.readEntry(); - zipfile.on("entry", function (entry) { + zipfile.on('entry', function (entry) { zipfile.openReadStream(entry, function (err, readStream) { if (err) throw err; @@ -77,7 +76,7 @@ if (platform.phpBinary) { readStream.pipe(writeStream); - writeStream.on("close", function() { + writeStream.on('close', function () { console.log('Copied PHP binary to ', binaryPath); // Add execute permissions diff --git a/resources/electron/src/main/index.js b/resources/electron/src/main/index.js index 1c37002f..187e68b1 100644 --- a/resources/electron/src/main/index.js +++ b/resources/electron/src/main/index.js @@ -1,26 +1,20 @@ -import {app} from 'electron' -import NativePHP from '#plugin' -import path from 'path' +import NativePHP from '#plugin'; +import { app } from 'electron'; +import path from 'path'; // Inherit User's PATH in Process & ChildProcess import fixPath from 'fix-path'; fixPath(); const buildPath = path.resolve(import.meta.dirname, import.meta.env.MAIN_VITE_NATIVEPHP_BUILD_PATH); -const defaultIcon = path.join(buildPath, 'icon.png') -const certificate = path.join(buildPath, 'cacert.pem') +const defaultIcon = path.join(buildPath, 'icon.png'); +const certificate = path.join(buildPath, 'cacert.pem'); const executable = process.platform === 'win32' ? 'php.exe' : 'php'; -const phpBinary = path.join(buildPath,'php', executable); -const appPath = path.join(buildPath, 'app') +const phpBinary = path.join(buildPath, 'php', executable); +const appPath = path.join(buildPath, 'app'); /** * Turn on the lights for the NativePHP app. */ -NativePHP.bootstrap( - app, - defaultIcon, - phpBinary, - certificate, - appPath -); +NativePHP.bootstrap(app, defaultIcon, phpBinary, certificate, appPath);