diff --git a/assistant/.gitignore b/assistant/.gitignore new file mode 100644 index 0000000..c8906bf --- /dev/null +++ b/assistant/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store + +dist + +pack-dist + +assistant-app diff --git a/assistant/bun.config.mjs b/assistant/bun.config.mjs new file mode 100644 index 0000000..4678546 --- /dev/null +++ b/assistant/bun.config.mjs @@ -0,0 +1,19 @@ +// @ts-check +// https://bun.sh/docs/bundler +// @ts-ignore +import pkg from './package.json'; +// bun run src/index.ts -- +await Bun.build({ + target: 'node', + format: 'esm', + entrypoints: ['./src/index.ts'], + outdir: './dist', + naming: { + entry: 'assistant.mjs', + }, + + define: { + ENVISION_VERSION: JSON.stringify(pkg.version), + }, + env: 'ENVISION_*', +}); diff --git a/assistant/package.json b/assistant/package.json new file mode 100644 index 0000000..94b10dd --- /dev/null +++ b/assistant/package.json @@ -0,0 +1,48 @@ +{ + "name": "@kevisual/assistant-cli", + "version": "0.0.1", + "description": "", + "main": "dist/assistant.mjs", + "keywords": [ + "kevisual", + "cli", + "assistant" + ], + "author": "abearxiong (https://www.xiongxiao.me)", + "license": "MIT", + "packageManager": "pnpm@10.7.0", + "type": "module", + "files": [ + "dist", + "bin", + "bun.config.mjs" + ], + "scripts": { + "dev": "bun run src/run.ts ", + "dev:serve": "bun --watch src/serve.ts", + "build": "rimraf dist && bun run bun.config.mjs" + }, + "devDependencies": { + "@kevisual/load": "^0.0.6", + "@kevisual/query": "0.0.17", + "@kevisual/query-login": "0.0.5", + "@kevisual/router": "^0.0.13", + "@kevisual/use-config": "^1.0.11", + "@types/bun": "^1.2.10", + "@types/node": "^22.14.1", + "@types/send": "^0.17.4", + "chalk": "^5.4.1", + "commander": "^13.1.0", + "inquirer": "^12.5.2", + "pino": "^9.6.0", + "pino-pretty": "^13.0.0", + "send": "^1.2.0", + "zustand": "^5.0.3" + }, + "engines": { + "node": ">=22.0.0" + }, + "publishConfig": { + "access": "public" + } +} \ No newline at end of file diff --git a/assistant/pem/https-cert.pem b/assistant/pem/https-cert.pem new file mode 100644 index 0000000..cdd8681 --- /dev/null +++ b/assistant/pem/https-cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICXTCCAcagAwIBAgIJUmN5oWFZdxK8MA0GCSqGSIb3DQEBBQUAMF8xCjAIBgNV +BAMTASoxCzAJBgNVBAYTAkNOMREwDwYDVQQIEwhaaGVKaWFuZzERMA8GA1UEBxMI +SGFuZ3pob3UxETAPBgNVBAoTCEVudmlzaW9uMQswCQYDVQQLEwJJVDAeFw0yNTA0 +MjQxODExMjZaFw0yNjA0MjQxODExMjZaMF8xCjAIBgNVBAMTASoxCzAJBgNVBAYT +AkNOMREwDwYDVQQIEwhaaGVKaWFuZzERMA8GA1UEBxMISGFuZ3pob3UxETAPBgNV +BAoTCEVudmlzaW9uMQswCQYDVQQLEwJJVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAirpqS9Lwh5JNY7N303wphXCR/HZDgfw1HnP6b62WVJTHtU97hLKjrTXx +zUYPEyySXLzFGjptKSjT3ZgulV1I9YBXg2gdDibxxxZUZHoJ8j0oh+MSxRv1fTzw ++HEBErUJQJ4lHnf9nbi7Tf48XiNWqh9Lce3XvyDFQoRDASX5yeUCAwEAAaMhMB8w +HQYDVR0RBBYwFIIBKoIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEBBQUAA4GB +AGCYapPzhY0zUVZxo6CsijdDQpuHe2G3cDs4bzpF2YHRGN3t8/cPwROt7FWCkzBt +b7g/Tar+200fGspmLS95QisjiKo0fAKfaEE8CHXr2jlt8+omOz0tPg9LCZi2GtgI +8EC+Vvvcd9UjzHmoPBZQF4qAvJ2IyOwBh6Vwyh8las+e +-----END CERTIFICATE----- diff --git a/assistant/pem/https-private-key.pem b/assistant/pem/https-private-key.pem new file mode 100644 index 0000000..2c99f5b --- /dev/null +++ b/assistant/pem/https-private-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCKumpL0vCHkk1js3fTfCmFcJH8dkOB/DUec/pvrZZUlMe1T3uE +sqOtNfHNRg8TLJJcvMUaOm0pKNPdmC6VXUj1gFeDaB0OJvHHFlRkegnyPSiH4xLF +G/V9PPD4cQEStQlAniUed/2duLtN/jxeI1aqH0tx7de/IMVChEMBJfnJ5QIDAQAB +AoGAGmBUKoN6OQSPk0fBniOqz1S2ZP5lWncF8HrToF0sSnuZNvdcQEAoz5uElGdg +IWClmV1IynJWY+9/zM+M99grMT6it3VHHVM3MQoTf1Am4Vy0qgKR6Y1TzE0XLrVW +3e3ezDph3gG0EQsRxVbn/goCEfstuhJaFyxHvsQRtPY+Z1ECQQC8ffbjV8hb911o +iUw67FquOL9AYrFfQfohkQZ1TrDv0VTCAYpB7e5ml4dBhUL1dQbFV7avZIufD5fl +pxCKkAPNAkEAvGnQPByrKj6ggf2l1CzgjXzZ24wm3AkJutWkFjAcf5EFy0+MIBOi +ejyrGcGi9eovXCLGLrgzaBeAHa4XNkX2eQJAEZE73VxlFA0t63xAWo2EthAb4whP +t60SfuZhT7WR0AgWei5ikFp4iZ89v+GHqBDMHMBcCmS4jo6JfaHgbMmXUQJAAIDL +1I1DC77VEOPLgJCKHPabYlGyfN3tT7loUcLZIKITgOJ6fk9vHKJy1oPE2qFAdR+G +pfNJ99owNmQTncp8CQJAI3fp5VABViB3uha4cHmpRUvoGNWmmh9Ob6LypDsGtd8z +8ah+4Ek1DvsQC4XDuwgwnQsCmEYfa2P1T/GIdqPadw== +-----END RSA PRIVATE KEY----- diff --git a/assistant/readme.md b/assistant/readme.md new file mode 100644 index 0000000..fb15f68 --- /dev/null +++ b/assistant/readme.md @@ -0,0 +1,7 @@ +# assistant cli + +## 初始化路径 + +## 启动服务 + +## 配置 diff --git a/assistant/src/app.ts b/assistant/src/app.ts new file mode 100644 index 0000000..c457edf --- /dev/null +++ b/assistant/src/app.ts @@ -0,0 +1,19 @@ +import { App } from '@kevisual/router'; +import { AssistantConfig } from '@/module/assistant/index.ts'; +import { HttpsPem } from '@/module/assistant/https/sign.ts'; +import path from 'node:path'; + +export const configDir = path.resolve(process.env.assistantConfigDir || process.cwd()); +export const assistantConfig = new AssistantConfig({ + configDir, + init: true, +}); +const httpsPem = new HttpsPem(assistantConfig); +export const app = new App({ + serverOptions: { + path: '/client/router', + httpType: 'https', + httpsCert: httpsPem.cert, + httpsKey: httpsPem.key, + }, +}); diff --git a/assistant/src/command/init/index.ts b/assistant/src/command/init/index.ts new file mode 100644 index 0000000..ee0deef --- /dev/null +++ b/assistant/src/command/init/index.ts @@ -0,0 +1,24 @@ +import { program, Command } from '@/program.ts'; +import { AssistantInit } from '@/services/init/index.ts'; +import path from 'node:path'; + +type InitCommandOptions = { + path?: string; +}; +const Init = new Command('init') + .description('初始化一个助手客户端,生成配置文件。') + .option('-p --path ', '助手路径,默认为执行命令的目录,如果助手路径不存在则创建。') + .action((opts: InitCommandOptions) => { + // 如果path参数存在,检测path是否是相对路径,如果是相对路径,则转换为绝对路径 + if (opts.path && !opts.path.startsWith('/')) { + opts.path = path.join(process.cwd(), opts.path); + } else if (opts.path) { + opts.path = path.resolve(opts.path); + } + const assistantInit = new AssistantInit({ + path: opts.path, + }); + assistantInit.init(); + }); + +program.addCommand(Init); diff --git a/assistant/src/index.ts b/assistant/src/index.ts new file mode 100644 index 0000000..dcf71d1 --- /dev/null +++ b/assistant/src/index.ts @@ -0,0 +1,20 @@ +import { program, runProgram } from '@/program.ts'; +import './command/init/index.ts'; + +/** + * 通过命令行解析器解析参数 + * args[0] 是执行的命令, example: node + * args[1] 是执行的脚本, example: index.ts + * @param argv + */ +export const runParser = async (argv: string[]) => { + // program.parse(process.argv); + // console.log('argv', argv); + try { + program.parse(argv); + } catch (error) { + console.error('执行错误:', error.message); + } +}; + +export { runProgram }; diff --git a/assistant/src/module/assistant/config/index.ts b/assistant/src/module/assistant/config/index.ts new file mode 100644 index 0000000..d6bf318 --- /dev/null +++ b/assistant/src/module/assistant/config/index.ts @@ -0,0 +1,175 @@ +import path from 'path'; +import { homedir } from 'os'; +import fs from 'fs'; +import { checkFileExists, createDir } from '../file/index.ts'; +import { ProxyInfo } from '../proxy/proxy.ts'; + +/** + * 助手配置文件路径, 全局配置文件目录 + */ +const configDir = createDir(path.join(homedir(), '.config/envision/assistant-app')); + +/** + * 助手配置文件初始化 + * @param configRootPath + * @returns + */ +export const initConfig = (configRootPath: string) => { + const configDir = createDir(path.join(configRootPath, 'assistant-app')); + const configPath = path.join(configDir, 'assistant-config.json'); + const appConfigPath = path.join(configDir, 'assistant-app-config.json'); + const appDir = createDir(path.join(configDir, 'frontend')); + const serviceDir = createDir(path.join(configDir, 'services')); + const serviceConfigPath = path.join(serviceDir, 'assistant-service-config.json'); + const appPidPath = path.join(configDir, 'assistant-app.pid'); + return { + /** + * 助手配置文件路径 + */ + configDir, + /** + * 助手配置文件路径, assistant-config.json + */ + configPath, + /** + * 服务目录, 后端服务目录 + */ + serviceDir, + /** + * 服务配置文件路径 assistant-service-config.json + */ + serviceConfigPath, + /** + * 应用目录, 前端应用目录 + */ + appDir, + /** + * 应用配置文件路径, assistant-app-config.json + */ + appConfigPath, + /** + * 应用进程pid文件路径 + */ + appPidPath, + }; +}; +export type ReturnInitConfigType = ReturnType; + +type AssistantConfigData = { + pageApi?: string; // https://kevisual.silkyai.cn + proxy?: { user: string; key: string; path: string }[]; + apiProxyList?: ProxyInfo[]; + description?: string; +}; +let assistantConfig: AssistantConfigData; +type AssistantConfigOptions = { + configDir?: string; + init?: boolean; +}; +export class AssistantConfig { + config: AssistantConfigData; + configPath: ReturnInitConfigType; + configDir: string; + constructor(opts?: AssistantConfigOptions) { + this.configDir = opts?.configDir || configDir; + if (opts?.init) { + this.init(); + } + } + init() { + this.configPath = initConfig(this.configDir); + } + getConfig() { + try { + if (!checkFileExists(this.configPath.configPath)) { + fs.writeFileSync(this.configPath.configPath, JSON.stringify({ proxy: [] }, null, 2)); + return { + pageApi: '', + proxy: [], + }; + } + assistantConfig = JSON.parse(fs.readFileSync(this.configPath.configPath, 'utf8')); + return assistantConfig; + } catch (error) { + console.error('file read', error.message); + return { + pageApi: '', + proxy: [], + }; + } + } + getCacheAssistantConfig() { + if (this.config) { + return this.config; + } + return this.getConfig(); + } + /** + * 设置 assistant-config.json 配置 + * @param config + * @returns + */ + setConfig(config?: AssistantConfigData) { + const myConfig = this.getCacheAssistantConfig(); + const newConfig = { ...myConfig, ...config }; + this.config = newConfig; + fs.writeFileSync(this.configPath.configPath, JSON.stringify(newConfig, null, 2)); + return newConfig; + } + /** + * 应用配置 + * @returns + */ + getAppConfig(): AppConfig { + const { appConfigPath } = this.configPath; + if (!checkFileExists(appConfigPath)) { + return { + list: [], + }; + } + return JSON.parse(fs.readFileSync(appConfigPath, 'utf8')); + } + setAppConfig(config?: AppConfig) { + const _config = this.getAppConfig(); + const _saveConfig = { ..._config, ...config }; + const { appConfigPath } = this.configPath; + + fs.writeFileSync(appConfigPath, JSON.stringify(_saveConfig, null, 2)); + return _saveConfig; + } + assAppConfig(app: any) { + const config = this.getAppConfig(); + const assistantConfig = this.getCacheAssistantConfig(); + const _apps = config.list; + const _proxy = assistantConfig.proxy || []; + const { user, key } = app; + const newProxyInfo = { + user, + key, + path: `/${user}/${key}`, + }; + const _proxyIndex = _proxy.findIndex((_proxy: any) => _proxy.path === newProxyInfo.path); + if (_proxyIndex !== -1) { + _proxy[_proxyIndex] = newProxyInfo; + } else { + _proxy.push(newProxyInfo); + } + + const _app = _apps.findIndex((_app: any) => _app.id === app.id); + if (_app !== -1) { + _apps[_app] = app; + } else { + _apps.push(app); + } + this.setAppConfig({ ...config, list: _apps }); + this.setConfig({ ...assistantConfig, proxy: _proxy }); + return config; + } + getAppList() { + return this.getAppConfig().list; + } +} + +type AppConfig = { + list: any[]; +}; diff --git a/assistant/src/module/assistant/file/index.ts b/assistant/src/module/assistant/file/index.ts new file mode 100644 index 0000000..a9e6fcf --- /dev/null +++ b/assistant/src/module/assistant/file/index.ts @@ -0,0 +1,26 @@ +import fs from 'node:fs'; + +/** + * 检查文件是否存在 + * @param filePath 文件路径 + * @param checkIsFile 是否检查文件类型 default: false + * @returns + */ +export const checkFileExists = (filePath: string, checkIsFile = false) => { + try { + fs.accessSync(filePath); + if (checkIsFile) { + return fs.statSync(filePath).isFile(); + } + return true; + } catch (error) { + return false; + } +}; + +export const createDir = (dirPath: string) => { + if (!checkFileExists(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } + return dirPath; +}; diff --git a/assistant/src/module/assistant/https/cookie-rewrite.ts b/assistant/src/module/assistant/https/cookie-rewrite.ts new file mode 100644 index 0000000..cdfda22 --- /dev/null +++ b/assistant/src/module/assistant/https/cookie-rewrite.ts @@ -0,0 +1,27 @@ +export function rewriteCookieDomain(cookie: string, domainRewrite: string | Record) { + if (!domainRewrite) return cookie; + + // 解析 Cookie 的属性 + const parts = cookie.split(';').map((part) => part.trim()); + const nameValue = parts[0]; + const attributes = parts.slice(1); + + // 查找并替换 Domain 属性 + const newAttributes = attributes.map((attr) => { + if (attr.startsWith('Domain=')) { + const originalDomain = attr.slice(7); // 去掉 "Domain=" + let newDomain = domainRewrite; + + // 如果 domainRewrite 是对象,根据映射关系替换 + if (typeof domainRewrite === 'object') { + newDomain = domainRewrite[originalDomain] || originalDomain; + } + + return `Domain=${newDomain}`; + } + return attr; + }); + + // 重新组合 Cookie + return [nameValue, ...newAttributes].join('; '); +} diff --git a/assistant/src/module/assistant/https/sign.ts b/assistant/src/module/assistant/https/sign.ts new file mode 100644 index 0000000..a9e2e2f --- /dev/null +++ b/assistant/src/module/assistant/https/sign.ts @@ -0,0 +1,79 @@ +import { createCert } from '@kevisual/router/sign'; +import path from 'node:path'; +import fs from 'node:fs'; +import { AssistantConfig } from '../config/index.ts'; +import { checkFileExists } from '../file/index.ts'; +import { chalk } from '@/module/chalk.ts'; +type Attributes = { + name: string; + value: string; +}; +type AltNames = { + type: number; + value?: string; + ip?: string; +}; +export class HttpsPem { + assistantConfig: AssistantConfig; + key: string; + cert: string; + constructor(assistantConfig: AssistantConfig) { + this.assistantConfig = assistantConfig; + const { key, cert } = this.getCert(); + this.key = key; + this.cert = cert; + } + getPemDir() { + const configDir = this.assistantConfig.configPath?.configDir || process.cwd(); + const pemDir = path.join(configDir, 'pem'); + if (!checkFileExists(pemDir)) { + fs.mkdirSync(pemDir, { recursive: true }); + } + return pemDir; + } + getCert() { + const pemDir = this.getPemDir(); + const pemPath = { + key: path.join(pemDir, 'https-private-key.pem'), + cert: path.join(pemDir, 'https-cert.pem'), + }; + if (!checkFileExists(pemPath.key) || !checkFileExists(pemPath.cert)) { + const { key, cert } = this.createCert(); + fs.writeFileSync(pemPath.key, key); + fs.writeFileSync(pemPath.cert, cert); + console.log(chalk.green('证书创建成功')) + return { + key, + cert, + }; + } + const key = fs.readFileSync(pemPath.key, 'utf-8'); + const cert = fs.readFileSync(pemPath.cert, 'utf-8'); + return { + key, + cert, + }; + } + createCert(attrs?: Attributes[], altNames?: AltNames[]) { + const attributes = attrs || []; + const altNamesList = altNames || []; + const { key, cert } = createCert( + [ + { + name: 'commonName', + value: 'localhost', + }, + { + name: 'organizationName', + value: 'kevisual', + }, + ...attributes, + ], + altNamesList, + ); + return { + key, + cert, + }; + } +} diff --git a/assistant/src/module/assistant/index.ts b/assistant/src/module/assistant/index.ts new file mode 100644 index 0000000..f0f3010 --- /dev/null +++ b/assistant/src/module/assistant/index.ts @@ -0,0 +1,7 @@ +export * from './install/index.ts'; +export * from './config/index.ts'; +export * from './file/index.ts'; + +export * from './process/index.ts'; + +export * from './proxy/index.ts'; diff --git a/assistant/src/module/assistant/install/index.ts b/assistant/src/module/assistant/install/index.ts new file mode 100644 index 0000000..9be450b --- /dev/null +++ b/assistant/src/module/assistant/install/index.ts @@ -0,0 +1,121 @@ +import path from 'node:path'; +import fs from 'node:fs'; +import { checkFileExists } from '../file/index.ts'; + +type DownloadTask = { + downloadPath: string; + downloadUrl: string; + user: string; + key: string; + version: string; +}; +export type Package = { + id: string; + name?: string; + version?: string; + description?: string; + title?: string; + user?: string; + key?: string; + [key: string]: any; +}; +type InstallAppOpts = { + appDir?: string; + kevisualUrl?: string; + /** + * 是否是客户端, 下载到 assistant-config的下面 + */ +}; +export const installApp = async (app: Package, opts: InstallAppOpts = {}) => { + // const _app = demoData; + const { appDir = '', kevisualUrl = 'https://kevisual.cn' } = opts; + const _app = app; + try { + let files = _app.data.files || []; + const version = _app.version; + const user = _app.user; + const key = _app.key; + + const downFiles = files.map((file: any) => { + const noVersionPath = file.path.replace(`/${version}`, ''); + return { + ...file, + downloadPath: path.join(appDir, noVersionPath), + downloadUrl: `${kevisualUrl}/${noVersionPath}`, + }; + }); + const downloadTasks: DownloadTask[] = downFiles as any; + for (const file of downloadTasks) { + const downloadPath = file.downloadPath; + const downloadUrl = file.downloadUrl; + const dir = path.dirname(downloadPath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + const res = await fetch(downloadUrl); + const blob = await res.blob(); + fs.writeFileSync(downloadPath, Buffer.from(await blob.arrayBuffer())); + } + let indexHtml = files.find((file: any) => file.name === 'index.html'); + if (!indexHtml) { + files.push({ + name: 'index.html', + path: `${user}/${key}/index.html`, + }); + fs.writeFileSync(path.join(appDir, `${user}/${key}/index.html`), JSON.stringify(app, null, 2)); + } + _app.data.files = files; + return { + code: 200, + data: _app, + message: 'Install app success', + }; + } catch (error) { + console.error(error); + return { + code: 500, + message: 'Install app failed', + }; + } +}; +export const checkAppDir = (appDir: string) => { + const files = fs.readdirSync(appDir); + if (files.length === 0) { + fs.rmSync(appDir, { recursive: true }); + } +}; + +type UninstallAppOpts = { + appDir?: string; +}; +export const uninstallApp = async (app: Partial, opts: UninstallAppOpts = {}) => { + const { appDir = '' } = opts; + try { + const { user, key } = app; + const keyDir = path.join(appDir, user, key); + const parentDir = path.join(appDir, user); + if (!checkFileExists(appDir) || !checkFileExists(keyDir)) { + return { + code: 200, + message: 'uninstall app success', + }; + } + try { + // 删除appDir和文件 + fs.rmSync(keyDir, { recursive: true }); + } catch (error) { + console.error(error); + } + checkAppDir(parentDir); + return { + code: 200, + message: 'Uninstall app success', + }; + } catch (error) { + console.error(error); + return { + code: 500, + message: 'Uninstall app failed', + }; + } +}; diff --git a/assistant/src/module/assistant/process/index.ts b/assistant/src/module/assistant/process/index.ts new file mode 100644 index 0000000..1b9dfc7 --- /dev/null +++ b/assistant/src/module/assistant/process/index.ts @@ -0,0 +1,82 @@ +import { ChildProcess, fork, ForkOptions } from 'child_process'; +class BaseProcess { + private process: ChildProcess; + status: 'running' | 'stopped' | 'error' = 'stopped'; + appPath: string; + args: any[] = []; + opts: ForkOptions = {}; + /* + * 重启次数, 默认0, TODO, 错误检测,当重启次数超过一定次数,则认为进程已崩溃 + */ + restartCount: number = 0; + constructor(appPath?: string, args?: any[], opts?: ForkOptions) { + this.appPath = appPath; + this.args = args || []; + this.opts = opts || {}; + // this.createProcess(appPath); + } + createProcess(appPath: string = this.appPath, args: any[] = [], opts: ForkOptions = {}) { + if (this.process) { + this.process.kill(); + } + this.appPath = appPath || this.appPath; + this.args = args || this.args; + this.opts = { + ...this.opts, + ...opts, + }; + + this.process = fork(appPath, args, { + stdio: 'inherit', + ...this.opts, + env: { + ...process.env, + NODE_ENV_PARENT: 'fork', + ...this.opts?.env, + }, + }); + return this; + } + kill(signal?: NodeJS.Signals | number) { + if (this.process) { + this.process.kill(signal); + } + return this; + } + public send(message: any) { + this.process.send(message); + } + + public on(event: string, callback: (message: any) => void) { + this.process.on(event, callback); + } + + public onExit(callback: (code: number) => void) { + this.process.on('exit', callback); + } + + public onError(callback: (error: Error) => void) { + this.process.on('error', callback); + } + + public onMessage(callback: (message: any) => void) { + this.process.on('message', callback); + } + + public onClose(callback: () => void) { + this.process.on('close', callback); + } + + public onDisconnect(callback: () => void) { + this.process.on('disconnect', callback); + } + restart() { + this.kill(); + this.createProcess(); + } +} +export class AssistantProcess extends BaseProcess { + constructor(appPath: string) { + super(appPath); + } +} diff --git a/assistant/src/module/assistant/proxy/api-proxy.ts b/assistant/src/module/assistant/proxy/api-proxy.ts new file mode 100644 index 0000000..9fdbe2f --- /dev/null +++ b/assistant/src/module/assistant/proxy/api-proxy.ts @@ -0,0 +1,91 @@ +import http from 'node:http'; +import https from 'node:https'; +import { rewriteCookieDomain } from '../https/cookie-rewrite.ts'; +import { ProxyInfo } from './proxy.ts'; +export const defaultApiProxy = [ + { + path: '/api/router', + target: 'https://kevisual.cn', + }, + { + path: '/v1', + target: 'https://kevisual.cn', + }, +]; +/** + * 创建api代理 + * @param api + * @param paths ['/api/router', '/v1' ] + * @returns + */ +export const createApiProxy = (api: string, paths: string[] = ['/api', '/v1']) => { + const pathList = paths.map((item) => { + return { + path: item, + target: new URL(api).origin, + }; + }); + return pathList; +}; + +export const apiProxy = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => { + const { target } = proxyApi; + const _u = new URL(req.url, `${target}`); + console.log('proxyApi', { url: req.url, target: _u.href }); + // 设置代理请求的目标 URL 和请求头 + let header: any = {}; + if (req.headers?.['Authorization'] && !req.headers?.['authorization']) { + header.authorization = req.headers['Authorization']; + } + if (req.headers?.['cookie'] || req.headers?.['Cookie']) { + // 处理大小写不一致的cookie + header.cookie = req.headers['cookie'] || req.headers['Cookie']; + } + // 提取req的headers中的非HOST的header + const headers = Object.keys(req.headers).filter((item) => item && item.toLowerCase() !== 'host'); + headers.forEach((item) => { + if (item.toLowerCase() === 'origin') { + header.origin = new URL(target).origin; + return; + } + if (item.toLowerCase() === 'referer') { + header.referer = new URL(req.url, target).href; + return; + } + header[item] = req.headers[item]; + }); + const options: http.RequestOptions = { + host: _u.hostname, + path: req.url, + method: req.method, + headers: { + ...header, + }, + }; + // console.log('options', JSON.stringify(options, null, 2)); + if (_u.port) { + // @ts-ignore + options.port = _u.port; + } + const httpProxy = _u.protocol === 'https:' ? https : http; + // 创建代理请求 + const proxyReq = httpProxy.request(options, (proxyRes) => { + // Modify the 'set-cookie' headers using rewriteCookieDomain + if (proxyRes.headers['set-cookie']) { + proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map((cookie) => rewriteCookieDomain(cookie, 'localhost')); + } + // 将代理服务器的响应头和状态码返回给客户端 + res.writeHead(proxyRes.statusCode, proxyRes.headers); + // 将代理响应流写入客户端响应 + proxyRes.pipe(res, { end: true }); + }); + // 处理代理请求的错误事件 + proxyReq.on('error', (err) => { + console.error(`Proxy request error: ${err.message}`); + res.writeHead(500, { 'Content-Type': 'text/plain' }); + res.write(`Proxy request error: ${err.message}`); + }); + // 处理 POST 请求的请求体(传递数据到目标服务器),end:true 表示当请求体结束时,关闭请求 + req.pipe(proxyReq, { end: true }); + return; +}; diff --git a/assistant/src/module/assistant/proxy/file-proxy.ts b/assistant/src/module/assistant/proxy/file-proxy.ts new file mode 100644 index 0000000..de6247e --- /dev/null +++ b/assistant/src/module/assistant/proxy/file-proxy.ts @@ -0,0 +1,49 @@ +import http from 'node:http'; +import send from 'send'; +import fs from 'node:fs'; +import path from 'path'; +import { ProxyInfo } from './proxy.ts'; +import { checkFileExists } from '../file/index.ts'; + +export const fileProxy = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => { + // url开头的文件 + const url = new URL(req.url, 'http://localhost'); + const [user, key, _info] = url.pathname.split('/'); + const pathname = url.pathname.slice(1); + const { indexPath = '', target = '', rootPath = process.cwd() } = proxyApi; + try { + // 检测文件是否存在,如果文件不存在,则返回404 + let filePath = ''; + let exist = false; + if (_info) { + filePath = path.join(rootPath, target, pathname); + exist = checkFileExists(filePath, true); + } + if (!exist) { + filePath = path.join(rootPath, target, indexPath); + exist = checkFileExists(filePath, true); + } + console.log('filePath', filePath, exist); + + if (!exist) { + res.statusCode = 404; + res.end('Not Found File'); + return; + } + const ext = path.extname(filePath); + let maxAge = 24 * 60 * 60 * 1000; // 24小时 + if (ext === '.html') { + maxAge = 0; + } + let sendFilePath = path.relative(rootPath, filePath); + const file = send(req, sendFilePath, { + root: rootPath, + maxAge, + }); + file.pipe(res); + } catch (error) { + res.statusCode = 404; + res.end('Error:Not Found File'); + return; + } +}; diff --git a/assistant/src/module/assistant/proxy/index.ts b/assistant/src/module/assistant/proxy/index.ts new file mode 100644 index 0000000..3af7f79 --- /dev/null +++ b/assistant/src/module/assistant/proxy/index.ts @@ -0,0 +1,5 @@ +export * from './proxy.ts'; +export * from './file-proxy.ts'; +export { default as send } from 'send'; +export * from './api-proxy.ts'; +export * from './ws-proxy.ts'; \ No newline at end of file diff --git a/assistant/src/module/assistant/proxy/proxy.ts b/assistant/src/module/assistant/proxy/proxy.ts new file mode 100644 index 0000000..793db74 --- /dev/null +++ b/assistant/src/module/assistant/proxy/proxy.ts @@ -0,0 +1,50 @@ +export type ProxyInfo = { + path?: string; + /** + * 目标地址 + */ + target?: string; + /** + * 类型 + */ + type?: 'static' | 'dynamic' | 'minio'; + /** + * 是否使用websocket + * @default false + */ + ws?: boolean; + /** + * 首要文件,比如index.html, 设置了首要文件,如果文件不存在,则访问首要文件 + */ + indexPath?: string; + /** + * 根路径, 默认是process.cwd() + */ + rootPath?: string; +}; +export type ApiList = { + path: string; + /** + * url或者相对路径 + */ + target: string; + /** + * 目标地址 + */ + ws?: boolean; + /** + * 类型 + */ + type?: 'static' | 'dynamic' | 'minio'; +}[]; + +/** + +[ + { + path: '/api/v1/user', + target: 'http://localhost:3000/api/v1/user', + type: 'dynamic', + }, +] + */ diff --git a/assistant/src/module/assistant/proxy/ws-proxy.ts b/assistant/src/module/assistant/proxy/ws-proxy.ts new file mode 100644 index 0000000..d8cc5ff --- /dev/null +++ b/assistant/src/module/assistant/proxy/ws-proxy.ts @@ -0,0 +1,49 @@ +import { Server } from 'http'; +import WebSocket from 'ws'; +import { ProxyInfo } from './proxy.ts'; +/** + * websocket代理 + * apiList: [{ path: '/api/router', target: 'https://kevisual.xiongxiao.me' }] + * @param server + * @param config + */ +export const wsProxy = (server: Server, config: { apiList: ProxyInfo[] }) => { + console.log('Upgrade initialization started'); + + server.on('upgrade', (req, socket, head) => { + const proxyApiList: ProxyInfo[] = config?.apiList || []; + const proxyApi = proxyApiList.find((item) => req.url.startsWith(item.path)); + + if (proxyApi && proxyApi.ws) { + const _u = new URL(req.url, `${proxyApi.target}`); + const isHttps = _u.protocol === 'https:'; + const wsProtocol = isHttps ? 'wss' : 'ws'; + const wsUrl = `${wsProtocol}://${_u.hostname}${_u.pathname}`; + + const proxySocket = new WebSocket(wsUrl, { + headers: req.headers, + }); + + proxySocket.on('open', () => { + socket.on('data', (data) => { + proxySocket.send(data); + }); + + proxySocket.on('message', (message) => { + socket.write(message); + }); + }); + + proxySocket.on('error', (err) => { + console.error(`WebSocket proxy error: ${err.message}`); + socket.end(); + }); + + socket.on('error', () => { + proxySocket.close(); + }); + } else { + socket.end(); + } + }); +}; diff --git a/assistant/src/module/chalk.ts b/assistant/src/module/chalk.ts new file mode 100644 index 0000000..ebd384e --- /dev/null +++ b/assistant/src/module/chalk.ts @@ -0,0 +1,2 @@ +import { Chalk } from 'chalk'; +export const chalk = new Chalk({ level: 3 }); diff --git a/assistant/src/module/logger.ts b/assistant/src/module/logger.ts new file mode 100644 index 0000000..2a4a0b3 --- /dev/null +++ b/assistant/src/module/logger.ts @@ -0,0 +1,42 @@ +import { pino } from 'pino'; + +export const logger = pino({ + level: process.env.LOG_LEVEL || 'info', + transport: { + target: 'pino-pretty', + options: { + colorize: true, + translateTime: 'SYS:standard', + ignore: 'pid,hostname', + }, + }, + serializers: { + error: pino.stdSerializers.err, + req: pino.stdSerializers.req, + res: pino.stdSerializers.res, + }, + base: { + app: 'assistant', + env: process.env.NODE_ENV || 'production', + }, +}); +export const console = { + log: logger.info, + error: logger.error, + warn: logger.warn, + info: logger.info, + debug: logger.debug, +}; + +export const logError = (message: string, data?: any) => logger.error({ data }, message); +export const logWarning = (message: string, data?: any) => logger.warn({ data }, message); +export const logInfo = (message: string, data?: any) => logger.info({ data }, message); +export const logDebug = (message: string, data?: any) => logger.debug({ data }, message); + +export const log = { + log: logInfo, + error: logError, + warn: logWarning, + info: logInfo, + debug: logDebug, +}; diff --git a/assistant/src/program.ts b/assistant/src/program.ts new file mode 100644 index 0000000..6dcfa9d --- /dev/null +++ b/assistant/src/program.ts @@ -0,0 +1,28 @@ +import { program, Command } from 'commander'; +import fs from 'fs'; +// 将多个子命令加入主程序中 +let version = '0.0.1'; +try { + // @ts-ignore + if (ENVISION_VERSION) version = ENVISION_VERSION; +} catch (e) {} +// @ts-ignore +program.name('app').description('A CLI tool with envison').version(version); + +const ls = new Command('ls').description('List files in the current directory').action(() => { + console.log('List files'); + console.log(fs.readdirSync(process.cwd())); +}); +program.addCommand(ls); + +export { program, Command }; + +/** + * 在命令行中运行程序 + * 当前命令参数去执行 其他的应用模块 + * @param args + */ +export const runProgram = (args: string[]) => { + const [_app, _command] = process.argv; + program.parse([_app, _command, ...args]); +}; diff --git a/assistant/src/run.ts b/assistant/src/run.ts new file mode 100644 index 0000000..9086961 --- /dev/null +++ b/assistant/src/run.ts @@ -0,0 +1,6 @@ +import { runParser } from './index.ts'; + +/** + * test run parser + */ +runParser(process.argv); diff --git a/assistant/src/serve.ts b/assistant/src/serve.ts new file mode 100644 index 0000000..82e5601 --- /dev/null +++ b/assistant/src/serve.ts @@ -0,0 +1,8 @@ +import { app } from './app.ts'; +import { proxyRoute } from './services/proxy/proxy-page-index.ts'; + +app.listen(51015, () => { + console.log('Server is running on http://localhost:51015'); +}); + +app.server.on(proxyRoute); diff --git a/assistant/src/services/init/index.ts b/assistant/src/services/init/index.ts new file mode 100644 index 0000000..987e1ec --- /dev/null +++ b/assistant/src/services/init/index.ts @@ -0,0 +1,44 @@ +import path from 'node:path'; +import { checkFileExists, AssistantConfig } from '@/module/assistant/index.ts'; +import { chalk } from '@/module/chalk.ts'; +export type AssistantInitOptions = { + path?: string; +}; +/** + * 助手初始化类 + * @class AssistantInit + */ +export class AssistantInit extends AssistantConfig { + constructor(opts?: AssistantInitOptions) { + const configDir = opts?.path || process.cwd(); + super({ + configDir, + }); + } + + async init() { + // 1. 检查助手路径是否存在 + if (!this.checkConfigPath()) { + console.log(chalk.blue('助手路径不存在,正在创建...')); + super.init(); + this.createAssistantConfig(); + } else { + super.init(); + console.log(chalk.yellow('助手路径已存在')); + return; + } + } + checkConfigPath() { + const assistantPath = path.join(this.configDir, 'assistant-config.json'); + return checkFileExists(assistantPath); + } + createAssistantConfig() { + const assistantPath = this.configPath?.configPath; + if (!checkFileExists(assistantPath, true)) { + this.setConfig({ + description: '助手配置文件', + }); + console.log(chalk.green('助手配置文件创建成功')); + } + } +} diff --git a/assistant/src/services/proxy/local-proxy.ts b/assistant/src/services/proxy/local-proxy.ts new file mode 100644 index 0000000..a92ff00 --- /dev/null +++ b/assistant/src/services/proxy/local-proxy.ts @@ -0,0 +1,84 @@ +import fs from 'node:fs'; +import { AssistantConfig, checkFileExists } from '@/module/assistant/index.ts'; +import path from 'node:path'; + +export const localProxyProxyList = [ + { + user: 'root', + key: 'assistant-base-app', + path: '/root/assistant-base-app', + indexPath: 'root/assistant-base-app/index.html', + }, + { + user: 'root', + key: 'talkshow-admin', + path: '/root/talkshow-admin', + indexPath: 'root/talkshow-admin/index.html', + }, + { + user: 'root', + key: 'center', + path: '/root/center', + indexPath: 'root/center/index.html', + }, +]; + +type ProxyType = { + user: string; + key: string; + path: string; + indexPath: string; + absolutePath?: string; +}; +export type LocalProxyOpts = { + assistantConfig?: AssistantConfig; // 前端应用路径 +}; +export class LocalProxy { + localProxyProxyList: ProxyType[] = []; + assistantConfig?: AssistantConfig; + constructor(opts?: LocalProxyOpts) { + this.assistantConfig = opts?.assistantConfig; + if (this.assistantConfig) { + this.init(); + } + } + init() { + const frontAppDir = this.assistantConfig.configPath?.appDir; + console.log('frontAppDir', frontAppDir); + if (frontAppDir) { + const userList = fs.readdirSync(frontAppDir); + const localProxyProxyList: ProxyType[] = []; + userList.forEach((user) => { + const userPath = path.join(frontAppDir, user); + const stat = fs.statSync(userPath); + if (stat.isDirectory()) { + const appList = fs.readdirSync(userPath); + appList.forEach((app) => { + const appPath = path.join(userPath, app); + const indexPath = path.join(appPath, 'index.html'); + if (!checkFileExists(indexPath, true)) { + return; + } + // const appPath = `${appPath}/index.html`; + if (checkFileExists(indexPath, true)) { + localProxyProxyList.push({ + user: user, + key: app, + path: `/${user}/${app}`, + indexPath: `${user}/${app}/index.html`, + absolutePath: appPath, + }); + } + }); + } + }); + this.localProxyProxyList = localProxyProxyList; + } + } + getLocalProxyList() { + return this.localProxyProxyList; + } + reload() { + // 重新加载本地代理列表 + } +} diff --git a/assistant/src/services/proxy/proxy-page-index.ts b/assistant/src/services/proxy/proxy-page-index.ts new file mode 100644 index 0000000..a2682f0 --- /dev/null +++ b/assistant/src/services/proxy/proxy-page-index.ts @@ -0,0 +1,85 @@ +import { fileProxy, apiProxy, createApiProxy } from '@/module/assistant/index.ts'; +import http from 'http'; +import { LocalProxy } from './local-proxy.ts'; +import { assistantConfig } from '@/app.ts'; +import { log } from '@/module/logger.ts'; +const localProxy = new LocalProxy({ + assistantConfig, +}); +export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResponse) => { + const _assistantConfig = assistantConfig.getCacheAssistantConfig(); + const appDir = assistantConfig.configPath?.appDir; + const url = new URL(req.url, 'http://localhost'); + const pathname = url.pathname; + if (pathname.startsWith('/favicon.ico')) { + res.statusCode = 404; + res.end('Not Found Favicon'); + return; + } + if (pathname.startsWith('/client')) { + console.log('handle by router'); + return; + } + // client, api, v1, serve 开头的拦截 + const apiProxyList = _assistantConfig?.apiProxyList || []; + const defaultApiProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn'); + const apiBackendProxy = [...apiProxyList, ...defaultApiProxy].find((item) => pathname.startsWith(item.path)); + if (apiBackendProxy) { + console.log('apiBackendProxy', apiBackendProxy, req.url); + return apiProxy(req, res, { + path: apiBackendProxy.path, + target: apiBackendProxy.target, + }); + } + const urls = pathname.split('/'); + const [_, _user, _app] = urls; + if (!_app) { + res.statusCode = 404; + res.end('Not Found Proxy'); + return; + } + if (_app && urls.length === 3) { + // 重定向到 + res.writeHead(302, { Location: `${req.url}/` }); + return res.end(); + } + const proxyApiList = _assistantConfig?.proxy || []; + const proxyApi = proxyApiList.find((item) => pathname.startsWith(item.path)); + if (proxyApi) { + log.log('proxyApi', { proxyApi, pathname }); + const { user, key } = proxyApi; + return fileProxy(req, res, { + path: proxyApi.path, // 代理路径, 比如/root/center + rootPath: appDir, // 根路径 + indexPath: `${user}/${key}/index.html`, // 首页路径 + }); + } + const localProxyProxyList = localProxy.getLocalProxyList(); + const localProxyProxy = localProxyProxyList.find((item) => pathname.startsWith(item.path)); + if (localProxyProxy) { + log.log('localProxyProxy', { localProxyProxy, url: req.url }); + return fileProxy(req, res, { + path: localProxyProxy.path, + rootPath: assistantConfig.configPath?.appDir, + indexPath: localProxyProxy.indexPath, + }); + } + console.log('handle by router 404', req.url); + const creatCenterProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn', ['/root']); + const centerProxy = creatCenterProxy.find((item) => pathname.startsWith(item.path)); + if (centerProxy) { + console.log('centerProxy', centerProxy, req.url); + return apiProxy(req, res, { + path: centerProxy.path, + target: centerProxy.target, + type: 'static', + }); + } + res.statusCode = 404; + res.end('Not Found Proxy'); + // console.log('getCacheAssistantConfig().pageApi', getCacheAssistantConfig().pageApi); + // return apiProxy(req, res, { + // path: url.pathname, + // target: getCacheAssistantConfig().pageApi, + // }); +}; diff --git a/assistant/tsconfig.json b/assistant/tsconfig.json new file mode 100644 index 0000000..f3f7926 --- /dev/null +++ b/assistant/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "module": "nodenext", + "target": "esnext", + "noImplicitAny": false, + "outDir": "./dist", + "sourceMap": false, + "newLine": "LF", + "baseUrl": "./", + "typeRoots": [ + "node_modules/@types", + ], + "declaration": true, + "noEmit": false, + "allowImportingTsExtensions": true, + "emitDeclarationOnly": true, + "moduleResolution": "NodeNext", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "paths": { + "@/*": [ + "src/*" + ], + } + }, + "include": [ + "src/**/*.ts", + ], + "exclude": [], +} \ No newline at end of file diff --git a/bin/assistant.js b/bin/assistant.js new file mode 100644 index 0000000..e69de29 diff --git a/bin/envision.js b/bin/envision.js index a16df57..6020036 100755 --- a/bin/envision.js +++ b/bin/envision.js @@ -1,4 +1,4 @@ #!/usr/bin/env node -import { runParser } from '../dist/app.mjs'; +import { runParser } from '../dist/envision.mjs'; runParser(process.argv); diff --git a/bun.config.mjs b/bun.config.mjs index 2a81474..763fd42 100644 --- a/bun.config.mjs +++ b/bun.config.mjs @@ -1,6 +1,7 @@ // @ts-check // https://bun.sh/docs/bundler -import pkg from './package.json' assert { type: 'json' }; +// @ts-ignore +import pkg from './package.json'; // bun run src/index.ts -- await Bun.build({ target: 'node', @@ -8,7 +9,7 @@ await Bun.build({ entrypoints: ['./src/index.ts'], outdir: './dist', naming: { - entry: 'app.mjs', + entry: 'envision.mjs', }, define: { diff --git a/package.json b/package.json index 58bb9a9..8dd50a9 100644 --- a/package.json +++ b/package.json @@ -9,23 +9,23 @@ "app": { "key": "envision-cli", "entry": "dist/app.mjs", - "type": "pm2-system-app", - "files": [ - "dist" - ] + "type": "pm2-system-app" }, "bin": { "envision": "bin/envision.js", "ev": "bin/envision.js", - "kv": "bin/envision.js" + "assistant": "bin/assistant.js", + "asst": "bin/assistant.js" }, "files": [ "dist", - "bin" + "bin", + "bun.config.mjs" ], "scripts": { "dev": "bun run src/run.ts ", - "build": "rimraf dist && bun run bun.config.mjs" + "build": "rimraf dist && bun run bun.config.mjs", + "dts": "dts-bundle-generator --external-inlines=@types/jsonwebtoken src/index.ts -o dist/index.d.ts " }, "keywords": [ "kevisual", @@ -49,7 +49,10 @@ "ignore": "^7.0.3", "inquirer": "^12.5.2", "jsonwebtoken": "^9.0.2", - "tar": "^7.4.3" + "rollup": "^4.40.0", + "rollup-plugin-dts": "^6.2.1", + "tar": "^7.4.3", + "zustand": "^5.0.3" }, "engines": { "node": ">=22.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 20cf3e6..93da3ae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 0.0.17(encoding@0.1.13)(ws@8.18.0) '@kevisual/query-login': specifier: 0.0.5 - version: 0.0.5(@kevisual/query@0.0.17(encoding@0.1.13)(ws@8.18.0)) + version: 0.0.5(@kevisual/query@0.0.17(encoding@0.1.13)(ws@8.18.0))(rollup@4.40.0)(typescript@5.8.2) '@types/bun': specifier: ^1.2.10 version: 1.2.10 @@ -56,15 +56,72 @@ importers: jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 + rollup: + specifier: ^4.40.0 + version: 4.40.0 + rollup-plugin-dts: + specifier: ^6.2.1 + version: 6.2.1(rollup@4.40.0)(typescript@5.8.2) tar: specifier: ^7.4.3 version: 7.4.3 + zustand: + specifier: ^5.0.3 + version: 5.0.3 + + assistant: + devDependencies: + '@kevisual/load': + specifier: ^0.0.6 + version: 0.0.6 + '@kevisual/query': + specifier: 0.0.17 + version: 0.0.17(encoding@0.1.13)(ws@8.18.0) + '@kevisual/query-login': + specifier: 0.0.5 + version: 0.0.5(@kevisual/query@0.0.17(encoding@0.1.13)(ws@8.18.0))(rollup@4.40.0)(typescript@5.8.2) + '@kevisual/router': + specifier: ^0.0.13 + version: 0.0.13 + '@kevisual/use-config': + specifier: ^1.0.11 + version: 1.0.11(dotenv@16.5.0) + '@types/bun': + specifier: ^1.2.10 + version: 1.2.10 + '@types/node': + specifier: ^22.14.1 + version: 22.14.1 + '@types/send': + specifier: ^0.17.4 + version: 0.17.4 + chalk: + specifier: ^5.4.1 + version: 5.4.1 + commander: + specifier: ^13.1.0 + version: 13.1.0 + inquirer: + specifier: ^12.5.2 + version: 12.5.2(@types/node@22.14.1) + pino: + specifier: ^9.6.0 + version: 9.6.0 + pino-pretty: + specifier: ^13.0.0 + version: 13.0.0 + send: + specifier: ^1.2.0 + version: 1.2.0 + zustand: + specifier: ^5.0.3 + version: 5.0.3 submodules/kevisual-query-login: dependencies: '@kevisual/cache': specifier: ^0.0.2 - version: 0.0.2(rollup@4.39.0)(tslib@2.8.1)(typescript@5.8.2) + version: 0.0.2(rollup@4.40.0)(tslib@2.8.1)(typescript@5.8.2) '@kevisual/query': specifier: ^0.0.17 version: 0.0.17(encoding@0.1.13)(ws@8.18.0) @@ -400,6 +457,14 @@ packages: '@kevisual/query@0.0.17': resolution: {integrity: sha512-WMvWM+3pNlPKNhoxPX9fldMp1tOeJrkRM/tXA4bvOnftIoX2yeI4v0wTpbGJXES/bLlo7OC2kV8SeKF0K6dnxQ==} + '@kevisual/router@0.0.13': + resolution: {integrity: sha512-raji8aKXr0jigmJVOKBXb5gpstiAuyoIDy9m6SyPf4lRjCU3pspVI1bpscOUCBlaPICo6TLzPQxXhyTvvvtdWw==} + + '@kevisual/use-config@1.0.11': + resolution: {integrity: sha512-ccilQTRZTpO075L67ZBXhr8Lp3i73/W5cCMT5enMjVrnJT5K0i5JH5IbzBhF6WY5Rj8dmVsAyyjJe24ClyM7Eg==} + peerDependencies: + dotenv: ^16.4.7 + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -461,101 +526,201 @@ packages: cpu: [arm] os: [android] + '@rollup/rollup-android-arm-eabi@4.40.0': + resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm64@4.39.0': resolution: {integrity: sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==} cpu: [arm64] os: [android] + '@rollup/rollup-android-arm64@4.40.0': + resolution: {integrity: sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==} + cpu: [arm64] + os: [android] + '@rollup/rollup-darwin-arm64@4.39.0': resolution: {integrity: sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==} cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-arm64@4.40.0': + resolution: {integrity: sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.39.0': resolution: {integrity: sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==} cpu: [x64] os: [darwin] + '@rollup/rollup-darwin-x64@4.40.0': + resolution: {integrity: sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-freebsd-arm64@4.39.0': resolution: {integrity: sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==} cpu: [arm64] os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.40.0': + resolution: {integrity: sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==} + cpu: [arm64] + os: [freebsd] + '@rollup/rollup-freebsd-x64@4.39.0': resolution: {integrity: sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==} cpu: [x64] os: [freebsd] + '@rollup/rollup-freebsd-x64@4.40.0': + resolution: {integrity: sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==} + cpu: [x64] + os: [freebsd] + '@rollup/rollup-linux-arm-gnueabihf@4.39.0': resolution: {integrity: sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': + resolution: {integrity: sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.39.0': resolution: {integrity: sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.40.0': + resolution: {integrity: sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.39.0': resolution: {integrity: sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.40.0': + resolution: {integrity: sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.39.0': resolution: {integrity: sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.40.0': + resolution: {integrity: sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-loongarch64-gnu@4.39.0': resolution: {integrity: sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==} cpu: [loong64] os: [linux] + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': + resolution: {integrity: sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==} + cpu: [loong64] + os: [linux] + '@rollup/rollup-linux-powerpc64le-gnu@4.39.0': resolution: {integrity: sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==} cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': + resolution: {integrity: sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.39.0': resolution: {integrity: sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.40.0': + resolution: {integrity: sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.39.0': resolution: {integrity: sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.40.0': + resolution: {integrity: sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.39.0': resolution: {integrity: sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==} cpu: [s390x] os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.40.0': + resolution: {integrity: sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.39.0': resolution: {integrity: sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.40.0': + resolution: {integrity: sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.39.0': resolution: {integrity: sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.40.0': + resolution: {integrity: sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==} + cpu: [x64] + os: [linux] + '@rollup/rollup-win32-arm64-msvc@4.39.0': resolution: {integrity: sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==} cpu: [arm64] os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.40.0': + resolution: {integrity: sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.39.0': resolution: {integrity: sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==} cpu: [ia32] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.40.0': + resolution: {integrity: sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.39.0': resolution: {integrity: sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==} cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.40.0': + resolution: {integrity: sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==} + cpu: [x64] + os: [win32] + '@types/bun@1.2.10': resolution: {integrity: sha512-eilv6WFM3M0c9ztJt7/g80BDusK98z/FrFwseZgT4bXCq2vPhXD4z8R3oddmAn+R/Nmz9vBn4kweJKmGTZj+lg==} @@ -571,12 +736,18 @@ packages: '@types/jsonwebtoken@9.0.9': resolution: {integrity: sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==} + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} '@types/node-fetch@2.6.12': resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} + '@types/node-forge@1.3.11': + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + '@types/node@18.19.80': resolution: {integrity: sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ==} @@ -586,6 +757,9 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -620,6 +794,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -676,6 +854,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -702,6 +883,9 @@ packages: crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + debug@4.4.0: resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} @@ -719,6 +903,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dotenv@16.5.0: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} @@ -733,15 +921,25 @@ packages: ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + encoding@0.1.13: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -763,9 +961,16 @@ packages: engines: {node: '>=18'} hasBin: true + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -777,10 +982,20 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -823,6 +1038,10 @@ packages: resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} engines: {node: '>= 12.20'} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -863,6 +1082,13 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -881,6 +1107,9 @@ packages: resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==} engines: {node: '>= 4'} + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inquirer@12.5.2: resolution: {integrity: sha512-qoDk/vdSTIaXNXAoNnlg7ubexpJfUo7t8GT2vylxvE49BrLhToFuPPdMViidG2boHV7+AcP1TCkJs/+PPoF2QQ==} engines: {node: '>=18'} @@ -999,14 +1228,25 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1048,10 +1288,25 @@ packages: encoding: optional: true + node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + openai@4.88.0: resolution: {integrity: sha512-Ll2ZJCdX/56WcCF/wLtAFou+zWRyLeneoXy+qya5T5/wm5LkIr6heJfSn53c5ujXWPB+24cgumiOetbFqcppFA==} hasBin: true @@ -1082,6 +1337,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1093,6 +1352,20 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-pretty@13.0.0: + resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==} + hasBin: true + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.6.0: + resolution: {integrity: sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==} + hasBin: true + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -1119,6 +1392,12 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1126,10 +1405,21 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} @@ -1158,6 +1448,11 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rollup@4.40.0: + resolution: {integrity: sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-async@3.0.0: resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} engines: {node: '>=0.12.0'} @@ -1171,14 +1466,32 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + semver@7.6.3: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + engines: {node: '>= 18'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1191,6 +1504,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1199,6 +1515,14 @@ packages: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1215,6 +1539,10 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -1235,6 +1563,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} @@ -1250,6 +1581,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -1333,6 +1668,9 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.18.0: resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} @@ -1353,6 +1691,24 @@ packages: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} + zustand@5.0.3: + resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + snapshots: '@babel/code-frame@7.26.2': @@ -1586,13 +1942,13 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@kevisual/cache@0.0.2(rollup@4.39.0)(tslib@2.8.1)(typescript@5.8.2)': + '@kevisual/cache@0.0.2(rollup@4.40.0)(tslib@2.8.1)(typescript@5.8.2)': dependencies: - '@rollup/plugin-commonjs': 28.0.3(rollup@4.39.0) - '@rollup/plugin-node-resolve': 16.0.1(rollup@4.39.0) - '@rollup/plugin-typescript': 12.1.2(rollup@4.39.0)(tslib@2.8.1)(typescript@5.8.2) + '@rollup/plugin-commonjs': 28.0.3(rollup@4.40.0) + '@rollup/plugin-node-resolve': 16.0.1(rollup@4.40.0) + '@rollup/plugin-typescript': 12.1.2(rollup@4.40.0)(tslib@2.8.1)(typescript@5.8.2) idb-keyval: 6.2.1 - rollup-plugin-dts: 6.2.1(rollup@4.39.0)(typescript@5.8.2) + rollup-plugin-dts: 6.2.1(rollup@4.40.0)(typescript@5.8.2) transitivePeerDependencies: - rollup - tslib @@ -1602,9 +1958,9 @@ snapshots: dependencies: eventemitter3: 5.0.1 - '@kevisual/query-login@0.0.5(@kevisual/query@0.0.17(encoding@0.1.13)(ws@8.18.0))': + '@kevisual/query-login@0.0.5(@kevisual/query@0.0.17(encoding@0.1.13)(ws@8.18.0))(rollup@4.40.0)(typescript@5.8.2)': dependencies: - '@kevisual/cache': 0.0.2(rollup@4.39.0)(tslib@2.8.1)(typescript@5.8.2) + '@kevisual/cache': 0.0.2(rollup@4.40.0)(tslib@2.8.1)(typescript@5.8.2) '@kevisual/query': 0.0.17(encoding@0.1.13)(ws@8.18.0) dotenv: 16.5.0 transitivePeerDependencies: @@ -1620,6 +1976,16 @@ snapshots: - ws - zod + '@kevisual/router@0.0.13': + dependencies: + path-to-regexp: 8.2.0 + selfsigned: 2.4.1 + + '@kevisual/use-config@1.0.11(dotenv@16.5.0)': + dependencies: + '@kevisual/load': 0.0.6 + dotenv: 16.5.0 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1635,9 +2001,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@rollup/plugin-commonjs@28.0.3(rollup@4.39.0)': + '@rollup/plugin-commonjs@28.0.3(rollup@4.40.0)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.39.0) + '@rollup/pluginutils': 5.1.2(rollup@4.40.0) commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.4.0(picomatch@4.0.2) @@ -1645,95 +2011,155 @@ snapshots: magic-string: 0.30.11 picomatch: 4.0.2 optionalDependencies: - rollup: 4.39.0 + rollup: 4.40.0 - '@rollup/plugin-node-resolve@16.0.1(rollup@4.39.0)': + '@rollup/plugin-node-resolve@16.0.1(rollup@4.40.0)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.39.0) + '@rollup/pluginutils': 5.1.2(rollup@4.40.0) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.8 optionalDependencies: - rollup: 4.39.0 + rollup: 4.40.0 - '@rollup/plugin-typescript@12.1.2(rollup@4.39.0)(tslib@2.8.1)(typescript@5.8.2)': + '@rollup/plugin-typescript@12.1.2(rollup@4.40.0)(tslib@2.8.1)(typescript@5.8.2)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.39.0) + '@rollup/pluginutils': 5.1.2(rollup@4.40.0) resolve: 1.22.8 typescript: 5.8.2 optionalDependencies: - rollup: 4.39.0 + rollup: 4.40.0 tslib: 2.8.1 - '@rollup/pluginutils@5.1.2(rollup@4.39.0)': + '@rollup/pluginutils@5.1.2(rollup@4.40.0)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.39.0 + rollup: 4.40.0 '@rollup/rollup-android-arm-eabi@4.39.0': optional: true + '@rollup/rollup-android-arm-eabi@4.40.0': + optional: true + '@rollup/rollup-android-arm64@4.39.0': optional: true + '@rollup/rollup-android-arm64@4.40.0': + optional: true + '@rollup/rollup-darwin-arm64@4.39.0': optional: true + '@rollup/rollup-darwin-arm64@4.40.0': + optional: true + '@rollup/rollup-darwin-x64@4.39.0': optional: true + '@rollup/rollup-darwin-x64@4.40.0': + optional: true + '@rollup/rollup-freebsd-arm64@4.39.0': optional: true + '@rollup/rollup-freebsd-arm64@4.40.0': + optional: true + '@rollup/rollup-freebsd-x64@4.39.0': optional: true + '@rollup/rollup-freebsd-x64@4.40.0': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.39.0': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.39.0': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.40.0': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.39.0': optional: true + '@rollup/rollup-linux-arm64-gnu@4.40.0': + optional: true + '@rollup/rollup-linux-arm64-musl@4.39.0': optional: true + '@rollup/rollup-linux-arm64-musl@4.40.0': + optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.39.0': optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': + optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.39.0': optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.39.0': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.40.0': + optional: true + '@rollup/rollup-linux-riscv64-musl@4.39.0': optional: true + '@rollup/rollup-linux-riscv64-musl@4.40.0': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.39.0': optional: true + '@rollup/rollup-linux-s390x-gnu@4.40.0': + optional: true + '@rollup/rollup-linux-x64-gnu@4.39.0': optional: true + '@rollup/rollup-linux-x64-gnu@4.40.0': + optional: true + '@rollup/rollup-linux-x64-musl@4.39.0': optional: true + '@rollup/rollup-linux-x64-musl@4.40.0': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.39.0': optional: true + '@rollup/rollup-win32-arm64-msvc@4.40.0': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.39.0': optional: true + '@rollup/rollup-win32-ia32-msvc@4.40.0': + optional: true + '@rollup/rollup-win32-x64-msvc@4.39.0': optional: true + '@rollup/rollup-win32-x64-msvc@4.40.0': + optional: true + '@types/bun@1.2.10': dependencies: bun-types: 1.2.10 @@ -1749,6 +2175,8 @@ snapshots: '@types/ms': 0.7.34 '@types/node': 22.14.1 + '@types/mime@1.3.5': {} + '@types/ms@0.7.34': {} '@types/node-fetch@2.6.12': @@ -1756,6 +2184,10 @@ snapshots: '@types/node': 22.14.1 form-data: 4.0.2 + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 22.14.1 + '@types/node@18.19.80': dependencies: undici-types: 5.26.5 @@ -1766,6 +2198,11 @@ snapshots: '@types/resolve@1.20.2': {} + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.14.1 + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -1792,6 +2229,8 @@ snapshots: asynckit@0.4.0: {} + atomic-sleep@1.0.0: {} + balanced-match@1.0.2: {} brace-expansion@2.0.1: @@ -1838,6 +2277,8 @@ snapshots: color-name@1.1.4: {} + colorette@2.0.20: {} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -1858,6 +2299,8 @@ snapshots: crypto-js@4.2.0: {} + dateformat@4.6.3: {} + debug@4.4.0: dependencies: ms: 2.1.3 @@ -1866,6 +2309,8 @@ snapshots: delayed-stream@1.0.0: {} + depd@2.0.0: {} + dotenv@16.5.0: {} dunder-proto@1.0.1: @@ -1880,15 +2325,23 @@ snapshots: dependencies: safe-buffer: 5.2.1 + ee-first@1.1.1: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} + encodeurl@2.0.0: {} + encoding@0.1.13: dependencies: iconv-lite: 0.6.3 optional: true + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -1932,8 +2385,12 @@ snapshots: '@esbuild/win32-ia32': 0.25.0 '@esbuild/win32-x64': 0.25.0 + escape-html@1.0.3: {} + estree-walker@2.0.2: {} + etag@1.8.1: {} + event-target-shim@5.0.1: {} eventemitter3@5.0.1: {} @@ -1944,6 +2401,8 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + fast-copy@3.0.2: {} + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1952,6 +2411,10 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-redact@3.5.0: {} + + fast-safe-stringify@2.1.1: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -1989,6 +2452,8 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 4.0.0-beta.3 + fresh@2.0.0: {} + fsevents@2.3.3: optional: true @@ -2037,6 +2502,16 @@ snapshots: dependencies: function-bind: 1.1.2 + help-me@5.0.0: {} + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + humanize-ms@1.2.1: dependencies: ms: 2.1.3 @@ -2054,6 +2529,8 @@ snapshots: ignore@7.0.3: {} + inherits@2.0.4: {} + inquirer@12.5.2(@types/node@22.14.1): dependencies: '@inquirer/core': 10.1.10(@types/node@22.14.1) @@ -2166,14 +2643,22 @@ snapshots: mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 + minimist@1.2.8: {} + minipass@7.1.2: {} minizlib@3.0.1: @@ -2204,8 +2689,20 @@ snapshots: optionalDependencies: encoding: 0.1.13 + node-forge@1.3.1: {} + object-assign@4.1.1: {} + on-exit-leak-free@2.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + openai@4.88.0(encoding@0.1.13)(ws@8.18.0): dependencies: '@types/node': 18.19.80 @@ -2233,12 +2730,50 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-to-regexp@8.2.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} picomatch@4.0.2: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.0.0: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.2 + secure-json-parse: 2.7.0 + sonic-boom: 4.2.0 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.0.0: {} + + pino@9.6.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.1 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pirates@4.0.6: {} postcss-load-config@6.0.1(postcss@8.5.3): @@ -2254,12 +2789,25 @@ snapshots: source-map-js: 1.2.1 optional: true + process-warning@4.0.1: {} + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + punycode@2.3.1: {} queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + + range-parser@1.2.1: {} + readdirp@4.1.2: {} + real-require@0.2.0: {} + resolve-from@5.0.0: {} resolve@1.22.8: @@ -2274,10 +2822,10 @@ snapshots: dependencies: glob: 10.4.5 - rollup-plugin-dts@6.2.1(rollup@4.39.0)(typescript@5.8.2): + rollup-plugin-dts@6.2.1(rollup@4.40.0)(typescript@5.8.2): dependencies: magic-string: 0.30.17 - rollup: 4.39.0 + rollup: 4.40.0 typescript: 5.8.2 optionalDependencies: '@babel/code-frame': 7.26.2 @@ -2308,6 +2856,32 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.39.0 fsevents: 2.3.3 + rollup@4.40.0: + dependencies: + '@types/estree': 1.0.7 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.40.0 + '@rollup/rollup-android-arm64': 4.40.0 + '@rollup/rollup-darwin-arm64': 4.40.0 + '@rollup/rollup-darwin-x64': 4.40.0 + '@rollup/rollup-freebsd-arm64': 4.40.0 + '@rollup/rollup-freebsd-x64': 4.40.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.0 + '@rollup/rollup-linux-arm-musleabihf': 4.40.0 + '@rollup/rollup-linux-arm64-gnu': 4.40.0 + '@rollup/rollup-linux-arm64-musl': 4.40.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.0 + '@rollup/rollup-linux-riscv64-gnu': 4.40.0 + '@rollup/rollup-linux-riscv64-musl': 4.40.0 + '@rollup/rollup-linux-s390x-gnu': 4.40.0 + '@rollup/rollup-linux-x64-gnu': 4.40.0 + '@rollup/rollup-linux-x64-musl': 4.40.0 + '@rollup/rollup-win32-arm64-msvc': 4.40.0 + '@rollup/rollup-win32-ia32-msvc': 4.40.0 + '@rollup/rollup-win32-x64-msvc': 4.40.0 + fsevents: 2.3.3 + run-async@3.0.0: {} run-parallel@1.2.0: @@ -2320,10 +2894,37 @@ snapshots: safe-buffer@5.2.1: {} + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} + secure-json-parse@2.7.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + semver@7.6.3: {} + send@1.2.0: + dependencies: + debug: 4.4.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + 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.1 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -2332,6 +2933,10 @@ snapshots: signal-exit@4.1.0: {} + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + source-map-js@1.2.1: optional: true @@ -2339,6 +2944,10 @@ snapshots: dependencies: whatwg-url: 7.1.0 + split2@4.2.0: {} + + statuses@2.0.1: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -2359,6 +2968,8 @@ snapshots: dependencies: ansi-regex: 6.1.0 + strip-json-comments@3.1.1: {} + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.8 @@ -2388,6 +2999,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + tinyexec@0.3.2: {} tinyglobby@0.2.12: @@ -2403,6 +3018,8 @@ snapshots: dependencies: is-number: 7.0.0 + toidentifier@1.0.1: {} + tr46@0.0.3: {} tr46@1.0.1: @@ -2489,9 +3106,13 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + wrappy@1.0.2: {} + ws@8.18.0: optional: true yallist@5.0.0: {} yoctocolors-cjs@2.1.2: {} + + zustand@5.0.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d7cf5d1..c8e25c5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,4 @@ packages: - 'submodules/*' + - 'assistant' + - '!submodules/assistant-center' \ No newline at end of file diff --git a/rollup.config.mjs b/rollup.config.mjs new file mode 100644 index 0000000..2c8a828 --- /dev/null +++ b/rollup.config.mjs @@ -0,0 +1,11 @@ +import dts from 'rollup-plugin-dts'; + +export default { + input: 'src/index.ts', + output: { + file: 'dist/index.d.ts', + format: 'es', + }, + plugins: [dts()], +}; + diff --git a/tsconfig.json b/tsconfig.json index 93c39bf..f3f7926 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,6 @@ "noImplicitAny": false, "outDir": "./dist", "sourceMap": false, - "allowJs": true, "newLine": "LF", "baseUrl": "./", "typeRoots": [ @@ -18,21 +17,16 @@ "moduleResolution": "NodeNext", "experimentalDecorators": true, "emitDecoratorMetadata": true, + "allowSyntheticDefaultImports": true, "esModuleInterop": true, "paths": { "@/*": [ "src/*" ], - }, - "resolveJsonModule": true + } }, "include": [ - "typings.d.ts", "src/**/*.ts", - "./bun.config.mjs" - ], - "exclude": [ - "node_modules", - "dist", ], + "exclude": [], } \ No newline at end of file