From e377557587483209740ccc79c1eceb5cd606d559 Mon Sep 17 00:00:00 2001 From: xiongxiao Date: Sun, 22 Feb 2026 00:07:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9B=B4=E6=96=B0=20@kevisual/api=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E8=87=B3=200.0.59=EF=BC=8C=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=9C=AC=E5=9C=B0=E7=94=A8=E6=88=B7=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cnb.yml | 30 +--- assistant/package.json | 2 +- .../local-app-manager/assistant-app.ts | 167 +++++++++++------- assistant/src/module/assistant/query/index.ts | 4 - assistant/src/module/light-code/index.ts | 8 +- assistant/src/server.ts | 9 +- assistant/src/test/cnb.ts | 40 +++++ package.json | 2 +- pnpm-lock.yaml | 39 ++-- 9 files changed, 172 insertions(+), 129 deletions(-) create mode 100644 assistant/src/test/cnb.ts diff --git a/.cnb.yml b/.cnb.yml index 77c96db..54c8217 100644 --- a/.cnb.yml +++ b/.cnb.yml @@ -4,8 +4,7 @@ include: .common_env: &common_env env: - TO_REPO: kevisual/cli - TO_URL: git.xiongxiao.me + USERNAME: root imports: - https://cnb.cool/kevisual/env/-/blob/main/.env.development @@ -16,29 +15,6 @@ $: services: - vscode - docker + env: !reference [.common_env, env] imports: !reference [.common_env, imports] - # 开发环境启动后会执行的任务 - # stages: - # - name: pnpm install - # script: pnpm install - stages: !reference [.dev_tempalte, stages] - -.common_sync_to_gitea: &common_sync_to_gitea - - <<: *common_env - services: !reference [.common_sync_to_gitea_template, services] - stages: !reference [.common_sync_to_gitea_template, stages] - -.common_sync_from_gitea: &common_sync_from_gitea - - <<: *common_env - services: !reference [.common_sync_from_gitea_template, services] - stages: !reference [.common_sync_from_gitea_template, stages] - -main: - web_trigger_sync_to_gitea: - - <<: *common_sync_to_gitea - web_trigger_sync_from_gitea: - - <<: *common_sync_from_gitea - api_trigger_sync_to_gitea: - - <<: *common_sync_to_gitea - api_trigger_sync_from_gitea: - - <<: *common_sync_from_gitea \ No newline at end of file + stages: !reference [.dev_template, stages] \ No newline at end of file diff --git a/assistant/package.json b/assistant/package.json index 31d7117..7333351 100644 --- a/assistant/package.json +++ b/assistant/package.json @@ -44,7 +44,7 @@ "devDependencies": { "@inquirer/prompts": "^8.2.1", "@kevisual/ai": "^0.0.24", - "@kevisual/api": "^0.0.58", + "@kevisual/api": "^0.0.59", "@kevisual/load": "^0.0.6", "@kevisual/local-app-manager": "^0.1.32", "@kevisual/logger": "^0.0.4", diff --git a/assistant/src/module/assistant/local-app-manager/assistant-app.ts b/assistant/src/module/assistant/local-app-manager/assistant-app.ts index 604962d..b096070 100644 --- a/assistant/src/module/assistant/local-app-manager/assistant-app.ts +++ b/assistant/src/module/assistant/local-app-manager/assistant-app.ts @@ -37,6 +37,23 @@ export class AssistantApp extends Manager { this.config = config; this.resolver = new ModuleResolver(config.configPath.configDir); } + async init(opts?: { isServer?: boolean }) { + const manager = this; + await manager.load({ runtime: 'client' }); + console.log('Assistant App Loaded'); + await manager.checkLocalUser(); + const token = await assistantQuery.getToken(); + if (token) { + console.log('用户已登录,正在初始化远程应用连接...'); + await manager.initRemoteApp({ token }); + await manager.initRemoteApp(); + await manager.initRouterProxyLightApp(); + } + await manager.initRouterProxyApp(); + if (opts?.isServer) { + await manager.initRoutes(); + } + } async pageList() { const pages = await glob(['*/*/package.json'], { cwd: this.pagesPath, @@ -99,7 +116,11 @@ export class AssistantApp extends Manager { } let token = opts?.token; if (!token) { - token = await assistantQuery.queryLogin.getToken(); + token = await assistantQuery.getToken(); + } + if (!token) { + logger.error('[remote-app] cli当前未登录,无法连接远程app'); + return; } let shareUrl = share?.url; if (!shareUrl) { @@ -161,11 +182,10 @@ export class AssistantApp extends Manager { * - lightcode: 轻代码模块配置 * @returns */ - async initRouterApp() { + async initRouterProxyApp() { const config = this.config.getConfig(); - const routerProxy = config?.router?.proxy || []; + let routerProxy = config?.router?.proxy || []; const base = config.router?.base ?? false; - const lightcode = config.router?.lightcode ?? true; if (base) { routerProxy.push({ type: 'router', @@ -174,42 +194,13 @@ export class AssistantApp extends Manager { } }) } - if (lightcode) { - routerProxy.push({ - type: 'lightcode', - lightcode: { - id: 'main', - sync: 'remote', - rootPath: path.join(this.config.configPath.appsDir, 'light-code', 'code'), - } - }) - } + routerProxy = routerProxy.filter(item => item.type === 'router'); if (routerProxy.length === 0) { return } for (const proxyInfo of routerProxy) { - if (proxyInfo.type !== 'router' && proxyInfo.type !== 'lightcode') { - console.warn('路由的type必须是"router", 或者lightcode'); - continue; - } - if (proxyInfo.type === 'lightcode') { - const schema = z.object({ - rootPath: z.string().describe('light-code 代码存放路径'), - sync: z.enum(['remote', 'local', 'both']).describe('同步方式,remote: 仅从远程拉取,local: 仅上传本地代码,both: 双向同步').default('remote'), - }); - const parseRes = schema.safeParse(proxyInfo.lightcode); - if (!parseRes.success) { - console.warn('lightcode 配置错误', parseRes.error); - continue; - } - const lightcodeConfig = parseRes.data; - - initLightCode({ - router: this.mainApp, - config: this.config, - sync: lightcodeConfig.sync, - rootPath: lightcodeConfig.rootPath, - }); + if (proxyInfo.type !== 'router') { + console.warn('路由的type必须是"router"'); continue; } const url = proxyInfo.router!.url; @@ -236,6 +227,49 @@ export class AssistantApp extends Manager { } } } + + async initRouterProxyLightApp() { + const config = this.config.getConfig(); + let routerProxy = config?.router?.proxy || []; + const lightcode = config.router?.lightcode ?? true; + if (lightcode) { + routerProxy.push({ + type: 'lightcode', + lightcode: { + id: 'main', + sync: 'remote', + rootPath: path.join(this.config.configPath.appsDir, 'light-code', 'code'), + } + }) + } + routerProxy = routerProxy.filter(item => item.type === 'lightcode'); + if (routerProxy.length === 0) { + return + } + for (const proxyInfo of routerProxy) { + if (proxyInfo.type !== 'lightcode') { + console.warn('路由的type必须是"lightcode"'); + continue; + } + const schema = z.object({ + rootPath: z.string().describe('light-code 代码存放路径'), + sync: z.enum(['remote', 'local', 'both']).describe('同步方式,remote: 仅从远程拉取,local: 仅上传本地代码,both: 双向同步').default('remote'), + }); + const parseRes = schema.safeParse(proxyInfo.lightcode); + if (!parseRes.success) { + console.warn('lightcode 配置错误', parseRes.error); + continue; + } + const lightcodeConfig = parseRes.data; + + await initLightCode({ + router: this.mainApp, + config: this.config, + sync: lightcodeConfig.sync, + rootPath: lightcodeConfig.rootPath, + }); + } + } /** * 动态加载文件插件模块的应用模块 * @info 不需要登录 @@ -265,34 +299,49 @@ export class AssistantApp extends Manager { const checkLocalUser = async (opts: { assistantApp: AssistantApp }) => { const { assistantApp } = opts; const config = assistantApp.config.getConfig(); - const auth = config?.auth; - let checkCNB = false; - if (!auth?.username) { - checkCNB = true; - // 没有登录过,自动检测ci进行登录 - // 检测条件1:环境变量中存在 CNB_TOKEN - } else { - let temp = await assistantQuery.getToken() - logger.info('[assistant] 当前登录用户', auth.username, 'token有效性检查结果', !!temp); + const auth = config?.auth || {}; + const isLogin = await assistantQuery.queryLogin.getToken(); + logger.log('[assistant] 正在检查本地用户登录状态...', auth, '是否已登录', !!isLogin); + + const saveAuth = (auth: typeof config.auth, opts: { appId?: string, username: string; share: 'protected' | 'private' }) => { + auth.username = opts.username; + auth.share = opts.share; + const app = config?.app || {}; + if (!app?.id) { + app.id = opts.appId || 'dev-cnb' + } + assistantApp.config.setConfig({ + auth, + app + }); } - const cnbToken = useKey('CNB_TOKEN'); - if (!checkCNB && cnbToken) { + if (!auth?.username && isLogin) { + // 没有登录过,自动检测ci进行登录 + // 检测条件1:环境变量中存在 CNB_API_KEY + // 检测条件2:本地没有登录过 + const userInfo = await assistantQuery.queryLogin.checkLocalUser() + saveAuth(auth, { username: userInfo.username, share: 'protected' }) + return; + } + if (isLogin) return; + // 没有登录,尝试根据环境变量进行登录 + + // 尝试使用 CNB_API_KEY 登录, 并设置管理员用户 + const cnbToken = useKey('CNB_API_KEY'); + if (cnbToken) { + logger.info('[cnb]检测到 CNB_API_KEY,正在尝试使用 CNB_API_KEY 登录...'); const res = await assistantQuery.queryLogin.loginByCnb({ cnbToken }) if (res.code === 200) { - logger.info('CNB登录成功,用户信息已更新'); const userInfo = await assistantQuery.queryLogin.checkLocalUser() - auth.username = userInfo.username; - auth.share = 'protected' - const app = config?.app || {}; - if (!app?.id) { - app.id = 'dev-cnb' - } - assistantApp.config.setConfig({ - auth, - app - }); + saveAuth(auth, { username: userInfo.username, share: 'protected' }) + return } else { - console.error('CNB登录失败,无法获取用户信息', res); + logger.error('CNB登录失败,无法获取用户信息', res); } } + const kevisualToken = useKey('KEVISUAL_TOKEN'); + if (kevisualToken) { + logger.info('[cnb]检测到 KEVISUAL_TOKEN,正在尝试使用 KEVISUAL_TOKEN 登录...'); + const res = await assistantQuery.queryLogin.refreshLoginUser(kevisualToken) + } } \ No newline at end of file diff --git a/assistant/src/module/assistant/query/index.ts b/assistant/src/module/assistant/query/index.ts index 7bb6918..3f44d7d 100644 --- a/assistant/src/module/assistant/query/index.ts +++ b/assistant/src/module/assistant/query/index.ts @@ -37,10 +37,6 @@ export class AssistantQuery { } async getToken() { const token = await this.queryLogin.getToken(); - if (!token) return ''; - const isExpired = await this.queryLogin.checkTokenValid() - console.log('Token 是否过期', isExpired, token); - console.log('info', this.queryLogin.cacheStore.cacheData) return token; } } diff --git a/assistant/src/module/light-code/index.ts b/assistant/src/module/light-code/index.ts index 1f21f1c..292554b 100644 --- a/assistant/src/module/light-code/index.ts +++ b/assistant/src/module/light-code/index.ts @@ -45,11 +45,15 @@ type LightCodeFile = { id?: string, code?: string, hash?: string, filepath: string } export const initLightCode = async (opts: Opts) => { + const token = await assistantQuery.getToken(); + if (!token) { + console.error('[light-code] 当前未登录,无法初始化 light-code'); + return; + } // 注册 light-code 路由 - console.log('初始化 light-code 路由'); const config = opts.config as AssistantInit; const app = opts.router; - const token = await assistantQuery.getToken(); + console.log('初始化 light-code 路由'); const query = config.query; const sync = opts.sync ?? 'remote'; if (!config || !app) { diff --git a/assistant/src/server.ts b/assistant/src/server.ts index b235c72..4c3228a 100644 --- a/assistant/src/server.ts +++ b/assistant/src/server.ts @@ -48,14 +48,7 @@ export const runServer = async (port: number = 51515, listenPath = '127.0.0.1') ]); const manager = useContextKey('manager', new AssistantApp(assistantConfig, app)); setTimeout(async () => { - await manager.load({ runtime: 'client' }); - console.log('Assistant App Loaded'); - await manager.checkLocalUser() - await manager.initRemoteApp(); - await manager.initRouterApp(); - if (runtime.isServer) { - await manager.initRoutes(); - } + manager.init({ isServer: runtime.isServer }); }, 1000); return { diff --git a/assistant/src/test/cnb.ts b/assistant/src/test/cnb.ts new file mode 100644 index 0000000..74ca8ec --- /dev/null +++ b/assistant/src/test/cnb.ts @@ -0,0 +1,40 @@ +import { CNB } from '@kevisual/cnb' +import { useKey } from '@kevisual/context' +import { QueryLoginNode } from '@kevisual/api/query-login-node' +import { Query } from '@kevisual/query' +const queryLogin = new QueryLoginNode({ + query: new Query({ url: 'https://kevisual.cn/api/router' }) +}) +await queryLogin.cacheStore.init() +const cnb = new CNB({ + token: useKey('CNB_TOKEN'), +}) +// export const cnbLogin = async () => { +// const userInfo = await cnb.user.getUser() +// console.log('CNB用户信息', userInfo); +// } +// cnbLogin() + +const testCnbLogin = async () => { + const res = await queryLogin.loginByCnb({ + cnbToken: useKey('CNB_TOKEN') || '', + }) + console.log('CNB登录结果', res); + if (res.code === 200) { + const userInfo = await queryLogin.checkLocalUser() + console.log('CNB登录成功,用户信息', userInfo); + } else { + console.log('CNB登录失败', res); + } +} + +// testCnbLogin() + +const getCNBLocalUser = async () => { + const res = await queryLogin.checkLocalUser() + console.log('查询本地用户信息', res); + const token = await queryLogin.getToken() + console.log('检查token是否过期', token); +} + +getCNBLocalUser() \ No newline at end of file diff --git a/package.json b/package.json index a5db9f9..5edbe94 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "unstorage": "^1.17.4" }, "devDependencies": { - "@kevisual/api": "^0.0.58", + "@kevisual/api": "^0.0.59", "@kevisual/cnb": "^0.0.28", "@kevisual/dts": "^0.0.4", "@kevisual/load": "^0.0.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc17fd4..6f7d525 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,8 +58,8 @@ importers: version: 1.17.4(idb-keyval@6.2.2)(ioredis@5.9.3(supports-color@10.2.2)) devDependencies: '@kevisual/api': - specifier: ^0.0.58 - version: 0.0.58(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^0.0.59 + version: 0.0.59(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@kevisual/cnb': specifier: ^0.0.28 version: 0.0.28(dotenv@17.3.1)(idb-keyval@6.2.2)(ioredis@5.9.3) @@ -170,8 +170,8 @@ importers: specifier: ^0.0.24 version: 0.0.24 '@kevisual/api': - specifier: ^0.0.58 - version: 0.0.58(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^0.0.59 + version: 0.0.59(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@kevisual/load': specifier: ^0.0.6 version: 0.0.6 @@ -1290,8 +1290,8 @@ packages: '@kevisual/api@0.0.28': resolution: {integrity: sha512-WQluRlu2qGM1qktIhPLODie8x382a6jEMfFOcay/rnkCgXK0BRpnqOKwlX7IMLdMqka7GY/BD69kSMnK1Exf5g==} - '@kevisual/api@0.0.58': - resolution: {integrity: sha512-ontJswmD5LS4EjYZDGF/SI1oYI1/zCM6ovC8rviNzxI22294yQ5y8Lb/rYV2qsKaxJbC3uuOjjsjPWap0nSvAQ==} + '@kevisual/api@0.0.59': + resolution: {integrity: sha512-2w6GBG2mS92dz8afB0hLfjTw8lBGD5oXU5bw/QglFugHHp24fISZkEW1Hc+jP/jOiYlMzphws2/31DIXdDoGkg==} '@kevisual/app@0.0.1': resolution: {integrity: sha512-PEx8P3l0iNSqrz9Ib9kVCYfqNMX6/LfNu+cEafmY6ECP1cV5Vmv+TH2fuasMosKjtbH2fAdDi97sbd29tdEK+g==} @@ -3036,15 +3036,6 @@ packages: supports-color: optional: true - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -6609,7 +6600,7 @@ snapshots: fuse.js: 7.1.0 nanoid: 5.1.6 - '@kevisual/api@0.0.58(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@kevisual/api@0.0.59(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@kevisual/context': 0.0.8 '@kevisual/js-filter': 0.0.5 @@ -8850,12 +8841,6 @@ snapshots: optionalDependencies: supports-color: 10.2.2 - debug@4.4.0(supports-color@10.2.2): - dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 10.2.2 - debug@4.4.3(supports-color@10.2.2): dependencies: ms: 2.1.3 @@ -10456,7 +10441,7 @@ snapshots: pm2-axon-rpc@0.7.1(supports-color@10.2.2): dependencies: - debug: 4.4.0(supports-color@10.2.2) + debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -10464,7 +10449,7 @@ snapshots: dependencies: amp: 0.3.1 amp-message: 0.1.2 - debug: 4.4.0(supports-color@10.2.2) + debug: 4.4.3(supports-color@10.2.2) escape-string-regexp: 4.0.0 transitivePeerDependencies: - supports-color @@ -10481,7 +10466,7 @@ snapshots: pm2-sysmonit@1.2.8(supports-color@10.2.2): dependencies: async: 3.2.6 - debug: 4.4.0(supports-color@10.2.2) + debug: 4.4.3(supports-color@10.2.2) pidusage: 2.0.21 systeminformation: 5.25.11 tx2: 1.0.5 @@ -10557,7 +10542,7 @@ snapshots: proxy-agent@6.4.0(supports-color@10.2.2): dependencies: agent-base: 7.1.3 - debug: 4.4.0(supports-color@10.2.2) + debug: 4.4.3(supports-color@10.2.2) http-proxy-agent: 7.0.2(supports-color@10.2.2) https-proxy-agent: 7.0.6(supports-color@10.2.2) lru-cache: 7.18.3 @@ -10832,7 +10817,7 @@ snapshots: require-in-the-middle@5.2.0(supports-color@10.2.2): dependencies: - debug: 4.4.0(supports-color@10.2.2) + debug: 4.4.3(supports-color@10.2.2) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: