fix(gpt-runner-web): state not share different host
This commit is contained in:
@@ -62,6 +62,8 @@
|
||||
"find-free-ports": "*",
|
||||
"ip": "*",
|
||||
"minimatch": "*",
|
||||
"socket.io": "*",
|
||||
"socket.io-client": "*",
|
||||
"zod": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -72,6 +74,8 @@
|
||||
"find-free-ports": "^3.1.1",
|
||||
"ip": "^1.1.8",
|
||||
"minimatch": "^9.0.1",
|
||||
"socket.io": "^4.6.2",
|
||||
"socket.io-client": "^4.6.2",
|
||||
"zod": "^3.21.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -79,4 +83,4 @@
|
||||
"@types/ip": "^1.1.0",
|
||||
"express": "^4.18.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,10 +86,21 @@ export function tryParseJson(str: string) {
|
||||
return JSON.parse(str)
|
||||
}
|
||||
catch (e) {
|
||||
console.error('tryParseJson error: ', e)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export function tryStringifyJson(obj: any) {
|
||||
try {
|
||||
return JSON.stringify(obj)
|
||||
}
|
||||
catch (e) {
|
||||
console.error('tryStringifyJson error: ', e)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
export function debounce<T extends (...args: any[]) => any>(callback: T, wait: number) {
|
||||
let timeout: ReturnType<typeof setTimeout> | undefined
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ interface EnvVarConfig {
|
||||
|
||||
/**
|
||||
* if true, this env var will only be available on server side
|
||||
* window.__config__ will not have this env var
|
||||
* window.__env__ will not have this env var
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
@@ -26,7 +26,9 @@ const config: Record<EnvName, EnvVarConfig> = {
|
||||
NODE_ENV: {
|
||||
defaultValue: 'production',
|
||||
},
|
||||
OPENAI_KEY: {},
|
||||
OPENAI_KEY: {
|
||||
serverSideOnly: true,
|
||||
},
|
||||
GPTR_BASE_SERVER_URL: {
|
||||
defaultValue: 'http://localhost:3003',
|
||||
},
|
||||
@@ -42,7 +44,7 @@ export class EnvConfig {
|
||||
|
||||
// client side
|
||||
if (typeof window !== 'undefined' && !serverSideOnly)
|
||||
return window?.__config__?.[key] ?? defaultValue ?? ''
|
||||
return window?.__env__?.[key] ?? defaultValue ?? ''
|
||||
|
||||
// server side
|
||||
return process.env[key] ?? defaultValue ?? ''
|
||||
@@ -51,7 +53,7 @@ export class EnvConfig {
|
||||
/**
|
||||
* get all env vars on server or client side
|
||||
* @param type server or client, get all allowed env vars on that scope
|
||||
* @param getWays all or process, get env vars both on process and window.__config__ or only process.env
|
||||
* @param getWays all or process, get env vars both on process and window.__env__ or only process.env
|
||||
* @returns env vars key value map
|
||||
*/
|
||||
static getAllEnvVarsOnScopes(
|
||||
@@ -93,7 +95,7 @@ export class EnvConfig {
|
||||
|
||||
/**
|
||||
* for /api/config
|
||||
* @returns env vars key value map for window.__config__
|
||||
* @returns env vars key value map for window.__env__
|
||||
*/
|
||||
static getClientEnvVarsInServerSide(): Partial<Record<EnvName, string>> {
|
||||
return EnvConfig.getAllEnvVarsOnScopes('client', 'process')
|
||||
@@ -106,6 +108,6 @@ declare global {
|
||||
}
|
||||
|
||||
interface Window {
|
||||
__config__?: Partial<Env>
|
||||
__env__?: Partial<Env>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,6 @@ export * from './create-filter-pattern'
|
||||
export * from './debug'
|
||||
export * from './env-config'
|
||||
export * from './is'
|
||||
export * from './request'
|
||||
export * from './socket'
|
||||
export * from './verify-zod'
|
||||
|
||||
17
packages/gpt-runner-shared/src/common/helpers/request.ts
Normal file
17
packages/gpt-runner-shared/src/common/helpers/request.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { FailResponse, SuccessResponse } from '../types'
|
||||
|
||||
export function buildSuccessResponse<T>(options: Omit<SuccessResponse<T>, 'type'>): SuccessResponse<T> {
|
||||
return {
|
||||
type: 'Success',
|
||||
status: options.status || 200,
|
||||
...options,
|
||||
}
|
||||
}
|
||||
|
||||
export function buildFailResponse<T>(options: Omit<FailResponse<T>, 'type'>): FailResponse<T> {
|
||||
return {
|
||||
type: 'Fail',
|
||||
status: options.status || 400,
|
||||
...options,
|
||||
}
|
||||
}
|
||||
178
packages/gpt-runner-shared/src/common/helpers/socket.ts
Normal file
178
packages/gpt-runner-shared/src/common/helpers/socket.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import * as uuid from 'uuid'
|
||||
import type { BrowserSocket, MaybePromise, NodeServerSocket, Socket, WssActionName, WssActionNameRequestMap } from '../types'
|
||||
import { EnvConfig } from './env-config'
|
||||
|
||||
type SocketQueueFn = (socket: Socket) => void
|
||||
export class WssUtils {
|
||||
static _instance: WssUtils | undefined
|
||||
static defaultWssUrl = `http://${new URL(EnvConfig.get('GPTR_BASE_SERVER_URL')).host}`
|
||||
#wssUrl: string
|
||||
#socketQueue: SocketQueueFn[] = []
|
||||
#hasConnected = false
|
||||
|
||||
static get instance() {
|
||||
if (!this._instance)
|
||||
this._instance = new WssUtils()
|
||||
|
||||
return this._instance
|
||||
}
|
||||
|
||||
constructor(wssUrl?: string) {
|
||||
this.#wssUrl = wssUrl ?? WssUtils.defaultWssUrl
|
||||
}
|
||||
|
||||
static get isBrowser() {
|
||||
return typeof window !== 'undefined'
|
||||
}
|
||||
|
||||
static isNodeServerSocket(socket: Socket | undefined): socket is NodeServerSocket {
|
||||
return typeof window === 'undefined' && Boolean(socket)
|
||||
}
|
||||
|
||||
static isBrowserSocket(socket: Socket | undefined): socket is BrowserSocket {
|
||||
return WssUtils.isBrowser && Boolean(socket)
|
||||
}
|
||||
|
||||
get wsUrl() {
|
||||
return this.#wssUrl
|
||||
}
|
||||
|
||||
#wss: Socket | undefined
|
||||
|
||||
#setWss = (socket: Socket) => {
|
||||
this.#wss = socket
|
||||
this.#socketQueue.forEach(fn => fn(socket))
|
||||
this.#socketQueue = []
|
||||
}
|
||||
|
||||
get wss() {
|
||||
return this.#wss
|
||||
}
|
||||
|
||||
connect = async (params?: {
|
||||
server: any // http.createServer(expressApp);
|
||||
}) => {
|
||||
if (this.wss || this.#hasConnected)
|
||||
return this.wss
|
||||
|
||||
console.log('Connecting to WS...')
|
||||
const { server } = params || {}
|
||||
|
||||
try {
|
||||
if (WssUtils.isBrowser)
|
||||
await this.#connectBrowserSocket()
|
||||
else
|
||||
server && await this.#connectNodeSocket(server)
|
||||
|
||||
this.#hasConnected = true
|
||||
|
||||
return this.wss
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error connecting to WS', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// for nodejs
|
||||
#connectNodeSocket = async (server: any) => {
|
||||
if (WssUtils.isBrowser || this.wss)
|
||||
return
|
||||
|
||||
const { Server } = await import('socket.io')
|
||||
|
||||
const serverSocket = new Server(server, {
|
||||
cors: {
|
||||
origin: '*',
|
||||
},
|
||||
})
|
||||
|
||||
serverSocket.on('connection', (socket) => {
|
||||
this.#setWss(socket)
|
||||
this.#handleConnection()
|
||||
})
|
||||
}
|
||||
|
||||
// for browser
|
||||
#connectBrowserSocket = async () => {
|
||||
if (!WssUtils.isBrowser || this.wss)
|
||||
return
|
||||
|
||||
const { io } = await import('socket.io-client')
|
||||
const socket = io(this.wsUrl)
|
||||
this.#setWss(socket)
|
||||
|
||||
// if (!WssUtils.isBrowserSocket(this.wss))
|
||||
// return
|
||||
|
||||
// socket.on('connect', () => {
|
||||
// this.#handleConnection()
|
||||
// })
|
||||
}
|
||||
|
||||
#handleConnection = async () => {
|
||||
console.log('Connected to Socket server')
|
||||
}
|
||||
|
||||
on = <T extends WssActionName>(eventName: T, callback: (message: WssActionNameRequestMap[T]) => MaybePromise<void>) => {
|
||||
if (!this.wss) {
|
||||
this.#socketQueue.push((socket) => {
|
||||
socket.on(eventName, callback as any)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
(this.wss as NodeServerSocket).on(eventName, callback as any)
|
||||
}
|
||||
|
||||
emit = <T extends WssActionName>(eventName: T, message: WssActionNameRequestMap[T]) => {
|
||||
if (!this.wss) {
|
||||
this.#socketQueue.push((socket) => {
|
||||
socket.emit(eventName, message)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.wss.emit(eventName, message)
|
||||
}
|
||||
|
||||
off = <T extends WssActionName>(eventName: T, callback: (message: WssActionNameRequestMap[T]) => MaybePromise<void>) => {
|
||||
if (!this.wss) {
|
||||
this.#socketQueue.push((socket) => {
|
||||
socket.off(eventName, callback as any)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.wss.off(eventName, callback as any)
|
||||
}
|
||||
|
||||
emitAndWaitForRes = async <T extends WssActionName>(eventName: T, message: WssActionNameRequestMap[T]) => {
|
||||
return new Promise<WssActionNameRequestMap[T]>((resolve, reject) => {
|
||||
let destroyFn: () => void
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
destroyFn?.()
|
||||
reject(new Error(`WS timeout, actionName: ${eventName}`))
|
||||
}, 10000)
|
||||
|
||||
const __id__ = uuid.v4()
|
||||
this.emit(eventName, { ...message, __id__ })
|
||||
|
||||
const handler = (message: WssActionNameRequestMap[T]) => {
|
||||
if (message.__id__ !== __id__)
|
||||
return
|
||||
|
||||
destroyFn?.()
|
||||
resolve(message)
|
||||
}
|
||||
|
||||
this.on(eventName, handler)
|
||||
|
||||
destroyFn = () => {
|
||||
clearTimeout(timeout)
|
||||
this.off(eventName, handler)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -26,3 +26,11 @@ export enum ServerStorageName {
|
||||
FrontendState = 'frontend-state',
|
||||
WebPreset = 'web-preset',
|
||||
}
|
||||
|
||||
export enum WssActionName {
|
||||
Error = 'error',
|
||||
StorageGetItem = 'storageGetItem',
|
||||
StorageSetItem = 'storageSetItem',
|
||||
StorageRemoveItem = 'storageRemoveItem',
|
||||
StorageClear = 'storageClear',
|
||||
}
|
||||
|
||||
@@ -4,3 +4,4 @@ export * from './config'
|
||||
export * from './enum'
|
||||
export * from './eventemitter'
|
||||
export * from './server'
|
||||
export * from './socket'
|
||||
|
||||
@@ -36,22 +36,35 @@ export interface GetUserConfigResData {
|
||||
userConfig: UserConfig
|
||||
}
|
||||
|
||||
export interface GetStorageReqParams {
|
||||
export interface StorageGetItemReqParams {
|
||||
storageName: ServerStorageName
|
||||
key: string
|
||||
}
|
||||
|
||||
export type ServerStorageValue = Record<string, any> | null | undefined
|
||||
|
||||
export interface GetStorageResData {
|
||||
export interface StorageGetItemResData {
|
||||
value: ServerStorageValue
|
||||
cacheDir: string
|
||||
}
|
||||
|
||||
export interface SaveStorageReqParams {
|
||||
export interface StorageSetItemReqParams {
|
||||
storageName: ServerStorageName
|
||||
key: string
|
||||
value?: ServerStorageValue
|
||||
}
|
||||
|
||||
export type SaveStorageResData = null
|
||||
export type StorageSetItemResData = null
|
||||
|
||||
export interface StorageRemoveItemReqParams {
|
||||
storageName: ServerStorageName
|
||||
key: string
|
||||
}
|
||||
|
||||
export type StorageRemoveItemResData = null
|
||||
|
||||
export interface StorageClearReqParams {
|
||||
storageName: ServerStorageName
|
||||
}
|
||||
|
||||
export type StorageClearResData = null
|
||||
|
||||
67
packages/gpt-runner-shared/src/common/types/socket.ts
Normal file
67
packages/gpt-runner-shared/src/common/types/socket.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import type { Socket as BrowserSocket } from 'socket.io-client'
|
||||
import type { Socket as NodeServerSocket } from 'socket.io'
|
||||
import type { MaybePromise } from './common'
|
||||
import type { WssActionName } from './enum'
|
||||
|
||||
import type {
|
||||
BaseResponse,
|
||||
StorageClearReqParams,
|
||||
StorageClearResData,
|
||||
StorageGetItemReqParams,
|
||||
StorageGetItemResData,
|
||||
StorageRemoveItemReqParams,
|
||||
StorageRemoveItemResData,
|
||||
StorageSetItemReqParams,
|
||||
StorageSetItemResData,
|
||||
} from './server'
|
||||
|
||||
export interface IWssActionNameRequestMap extends Record<WssActionName, {
|
||||
reqParams?: Record<string, any>
|
||||
resData?: any
|
||||
}> {
|
||||
[WssActionName.Error]: {
|
||||
reqParams?: {
|
||||
error: Error
|
||||
}
|
||||
resData?: Error
|
||||
}
|
||||
|
||||
[WssActionName.StorageGetItem]: {
|
||||
reqParams?: StorageGetItemReqParams
|
||||
resData?: StorageGetItemResData
|
||||
}
|
||||
|
||||
[WssActionName.StorageSetItem]: {
|
||||
reqParams?: StorageSetItemReqParams
|
||||
resData?: StorageSetItemResData
|
||||
}
|
||||
|
||||
[WssActionName.StorageRemoveItem]: {
|
||||
reqParams?: StorageRemoveItemReqParams
|
||||
resData?: StorageRemoveItemResData
|
||||
}
|
||||
|
||||
[WssActionName.StorageClear]: {
|
||||
reqParams?: StorageClearReqParams
|
||||
resData?: StorageClearResData
|
||||
}
|
||||
}
|
||||
|
||||
export type WssActionNameRequestMap = {
|
||||
[K in keyof IWssActionNameRequestMap]: {
|
||||
__id__?: string
|
||||
reqParams?: IWssActionNameRequestMap[K]['reqParams']
|
||||
res?: BaseResponse<IWssActionNameRequestMap[K]['resData']>
|
||||
}
|
||||
}
|
||||
|
||||
export type WssEventsMap = {
|
||||
[K in keyof WssActionNameRequestMap]: (message: WssActionNameRequestMap[K]) => MaybePromise<void>;
|
||||
}
|
||||
|
||||
// export type NodeServerSocket = InstanceType<typeof Server<WssEventsMap>>
|
||||
// export type BrowserSocket = InstanceType<typeof ClientSocket<WssEventsMap>>
|
||||
// export type Socket = NodeServerSocket | BrowserSocket
|
||||
|
||||
export type { BrowserSocket, NodeServerSocket }
|
||||
export type Socket = BrowserSocket | NodeServerSocket
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod'
|
||||
import type { ChatStreamReqParams, GetGptFilesReqParams, GetStorageReqParams, GetUserConfigReqParams, SaveStorageReqParams } from '../types'
|
||||
import type { ChatStreamReqParams, GetGptFilesReqParams, GetUserConfigReqParams, StorageClearReqParams, StorageGetItemReqParams, StorageRemoveItemReqParams, StorageSetItemReqParams } from '../types'
|
||||
import { SingleChatMessageSchema, SingleFileConfigSchema } from './config.zod'
|
||||
import { ServerStorageNameSchema } from './enum.zod'
|
||||
|
||||
@@ -19,13 +19,22 @@ export const GetUserConfigReqParamsSchema = z.object({
|
||||
rootPath: z.string(),
|
||||
}) satisfies z.ZodType<GetUserConfigReqParams>
|
||||
|
||||
export const GetStorageReqParamsSchema = z.object({
|
||||
export const StorageGetItemReqParamsSchema = z.object({
|
||||
storageName: ServerStorageNameSchema,
|
||||
key: z.string(),
|
||||
}) satisfies z.ZodType<GetStorageReqParams>
|
||||
}) satisfies z.ZodType<StorageGetItemReqParams>
|
||||
|
||||
export const SaveStorageReqParamsSchema = z.object({
|
||||
export const StorageSetItemReqParamsSchema = z.object({
|
||||
storageName: ServerStorageNameSchema,
|
||||
key: z.string(),
|
||||
value: z.record(z.any()).nullable().optional(),
|
||||
}) satisfies z.ZodType<SaveStorageReqParams>
|
||||
}) satisfies z.ZodType<StorageSetItemReqParams>
|
||||
|
||||
export const StorageRemoveItemReqParamsSchema = z.object({
|
||||
storageName: ServerStorageNameSchema,
|
||||
key: z.string(),
|
||||
}) satisfies z.ZodType<StorageRemoveItemReqParams>
|
||||
|
||||
export const StorageClearReqParamsSchema = z.object({
|
||||
storageName: ServerStorageNameSchema,
|
||||
}) satisfies z.ZodType<StorageClearReqParams>
|
||||
|
||||
@@ -1,23 +1,7 @@
|
||||
import type { Response } from 'express'
|
||||
import type { z } from 'zod'
|
||||
import type { FailResponse, SuccessResponse } from '../../common'
|
||||
import { verifyZod } from '../../common'
|
||||
|
||||
export function buildSuccessResponse<T>(options: Omit<SuccessResponse<T>, 'type'>): SuccessResponse<T> {
|
||||
return {
|
||||
type: 'Success',
|
||||
status: options.status || 200,
|
||||
...options,
|
||||
}
|
||||
}
|
||||
|
||||
export function buildFailResponse<T>(options: Omit<FailResponse<T>, 'type'>): FailResponse<T> {
|
||||
return {
|
||||
type: 'Fail',
|
||||
status: options.status || 400,
|
||||
...options,
|
||||
}
|
||||
}
|
||||
import { buildFailResponse, buildSuccessResponse, verifyZod } from '../../common'
|
||||
|
||||
export function sendSuccessResponse<T>(res: Response, options: Omit<SuccessResponse<T>, 'type'>): Response {
|
||||
return res.status(options.status || 200).json(buildSuccessResponse(options))
|
||||
|
||||
@@ -50,7 +50,13 @@
|
||||
},
|
||||
{
|
||||
"command": "gpt-runner.restartServer",
|
||||
"title": "GPT Runner Restart Server",
|
||||
"title": "Restart GPT Runner Server",
|
||||
"category": "GPT Runner"
|
||||
},
|
||||
{
|
||||
"command": "gpt-runner.openChat",
|
||||
"title": "Open GPT Runner Chat",
|
||||
"icon": "res/logo.svg",
|
||||
"category": "GPT Runner"
|
||||
}
|
||||
],
|
||||
@@ -64,6 +70,15 @@
|
||||
"description": "Disable the GPT Runner extension"
|
||||
}
|
||||
}
|
||||
},
|
||||
"menus": {
|
||||
"editor/title": [
|
||||
{
|
||||
"command": "gpt-runner.openChat",
|
||||
"group": "navigation",
|
||||
"icon": "res/logo.svg"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
@@ -84,4 +99,4 @@
|
||||
"execa": "^7.1.1",
|
||||
"fs-extra": "^11.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 30 KiB |
13
packages/gpt-runner-vscode/res/logo.svg
Normal file
13
packages/gpt-runner-vscode/res/logo.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="117.75479999999999"
|
||||
y="0" viewBox="7.552000045776367 18.47899627685547 87.46800231933594 64.28099822998047"
|
||||
enable-background="new 0 0 100 100" xml:space="preserve" height="580.8952" width="800.13947561559701" class="icon-s-0"
|
||||
data-fill-palette-color="accent" id="s-0">
|
||||
<path
|
||||
d="M31.805 41.953c0-5.497 2.443-10.57 6.546-14.639-0.238-0.004-0.474-0.013-0.712-0.013-16.615 0-30.087 9.948-30.087 22.221 0 9.36 7.837 17.36 18.926 20.634l-0.585 12.604 8.693-11.016c0 0 1.642 0 3.053 0 7.925 0 15.129-2.267 20.502-5.965C43.185 63.725 31.805 53.826 31.805 41.953z"
|
||||
fill="#19c37d" data-fill-palette-color="accent" />
|
||||
<g fill="#19c37d" data-fill-palette-color="accent">
|
||||
<path
|
||||
d="M76.966 82.062l-11.95-15.139h-2.081c-17.693 0-32.089-10.865-32.089-24.223 0-13.355 14.396-24.221 32.089-24.221 17.691 0 32.085 10.866 32.085 24.221 0 9.637-7.348 18.172-18.857 22.078L76.966 82.062zM62.935 22.48c-15.487 0-28.089 9.071-28.089 20.221 0 11.15 12.602 20.223 28.089 20.223h4.021l5.437 6.889-0.369-7.949 1.504-0.443C84.153 58.281 91.02 50.934 91.02 42.701 91.02 31.551 78.421 22.48 62.935 22.48z"
|
||||
fill="#19c37d" data-fill-palette-color="accent" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 30 KiB |
@@ -4,6 +4,7 @@ export const EXT_DISPLAY_NAME = 'GPT Runner'
|
||||
export enum Commands {
|
||||
Reload = `${EXT_NAME}.reload`,
|
||||
RestartServer = `${EXT_NAME}.restartServer`,
|
||||
OpenChat = `${EXT_NAME}.openChat`,
|
||||
OpenInBrowser = `${EXT_NAME}.openInBrowser`,
|
||||
InsertCodes = `${EXT_NAME}.insertCodes`,
|
||||
DiffCodes = `${EXT_NAME}.diffCodes`,
|
||||
|
||||
@@ -2,8 +2,9 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
import type { ExtensionContext } from 'vscode'
|
||||
import * as vscode from 'vscode'
|
||||
import * as uuid from 'uuid'
|
||||
import type { ContextLoader } from '../contextLoader'
|
||||
import { EXT_NAME } from '../constant'
|
||||
import { Commands, EXT_DISPLAY_NAME, EXT_NAME } from '../constant'
|
||||
import { createHash, getServerBaseUrl } from '../utils'
|
||||
import { state } from '../state'
|
||||
import { EventType, emitter } from '../emitter'
|
||||
@@ -29,28 +30,50 @@ class ChatViewProvider implements vscode.WebviewViewProvider {
|
||||
_context: vscode.WebviewViewResolveContext,
|
||||
_token: vscode.CancellationToken,
|
||||
) {
|
||||
const { extensionUri } = this.#extContext
|
||||
this.#view = webviewView
|
||||
state.sidebarWebviewView = webviewView
|
||||
|
||||
webviewView.webview.onDidReceiveMessage(({ eventName, eventData }) => {
|
||||
ChatViewProvider.updateWebview(webviewView.webview, this.#extContext, this.#projectPath)
|
||||
}
|
||||
|
||||
static createWebviewPanel(extContext: ExtensionContext, projectPath: string): vscode.WebviewPanel {
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
uuid.v4(),
|
||||
EXT_DISPLAY_NAME,
|
||||
{
|
||||
viewColumn: vscode.ViewColumn.Two,
|
||||
},
|
||||
{ retainContextWhenHidden: true },
|
||||
)
|
||||
|
||||
state.webviewPanel = panel
|
||||
|
||||
ChatViewProvider.updateWebview(panel.webview, extContext, projectPath)
|
||||
|
||||
return panel
|
||||
}
|
||||
|
||||
static updateWebview(webview: vscode.Webview, extContext: ExtensionContext, projectPath: string) {
|
||||
const { extensionUri } = extContext
|
||||
|
||||
webview.onDidReceiveMessage(({ eventName, eventData }) => {
|
||||
emitter.emit(eventName, eventData, EventType.ReceiveMessage)
|
||||
})
|
||||
|
||||
const baseUri = vscode.Uri.joinPath(extensionUri, './node_modules/@nicepkg/gpt-runner-web/dist/browser')
|
||||
|
||||
webviewView.webview.options = {
|
||||
webview.options = {
|
||||
// Allow scripts in the webview
|
||||
enableScripts: true,
|
||||
|
||||
localResourceRoots: [baseUri],
|
||||
}
|
||||
|
||||
webviewView.webview.html = this.#getHtmlForWebview(webviewView.webview)
|
||||
webview.html = ChatViewProvider.getHtmlForWebview(webview, extContext, projectPath)
|
||||
}
|
||||
|
||||
#getHtmlForWebview(webview: vscode.Webview) {
|
||||
const { extensionUri } = this.#extContext
|
||||
static getHtmlForWebview(webview: vscode.Webview, extContext: ExtensionContext, projectPath: string) {
|
||||
const { extensionUri } = extContext
|
||||
|
||||
const baseUri = vscode.Uri.joinPath(extensionUri, './node_modules/@nicepkg/gpt-runner-web/dist/browser')
|
||||
|
||||
@@ -69,7 +92,7 @@ class ChatViewProvider implements vscode.WebviewViewProvider {
|
||||
window.vscode = acquireVsCodeApi()
|
||||
|
||||
window.__GLOBAL_CONFIG__ = {
|
||||
rootPath: '${this.#projectPath}',
|
||||
rootPath: '${projectPath}',
|
||||
serverBaseUrl: '${getServerBaseUrl()}',
|
||||
initialRoutePath: '/chat',
|
||||
showDiffCodesBtn: true,
|
||||
@@ -106,16 +129,25 @@ export async function registerWebview(
|
||||
ext: ExtensionContext,
|
||||
) {
|
||||
const provider = new ChatViewProvider(ext, cwd)
|
||||
let webviewDisposer: vscode.Disposable | undefined
|
||||
let sidebarWebviewDisposer: vscode.Disposable | undefined
|
||||
let webviewPanelDisposer: vscode.Disposable | undefined
|
||||
|
||||
const dispose = () => {
|
||||
webviewDisposer?.dispose?.()
|
||||
sidebarWebviewDisposer?.dispose?.()
|
||||
webviewPanelDisposer?.dispose?.()
|
||||
}
|
||||
|
||||
const registerProvider = () => {
|
||||
dispose()
|
||||
webviewDisposer = vscode.window.registerWebviewViewProvider(ChatViewProvider.viewType, provider)
|
||||
return webviewDisposer
|
||||
|
||||
sidebarWebviewDisposer = vscode.window.registerWebviewViewProvider(ChatViewProvider.viewType, provider)
|
||||
webviewPanelDisposer = vscode.commands.registerCommand(Commands.OpenChat, () => {
|
||||
ChatViewProvider.createWebviewPanel(ext, cwd)
|
||||
})
|
||||
|
||||
return vscode.Disposable.from({
|
||||
dispose,
|
||||
})
|
||||
}
|
||||
|
||||
ext.subscriptions.push(registerProvider())
|
||||
|
||||
@@ -4,6 +4,7 @@ export interface State {
|
||||
serverPort: number | null
|
||||
statusBarItem: vscode.StatusBarItem | null
|
||||
sidebarWebviewView: vscode.WebviewView | null
|
||||
webviewPanel: vscode.WebviewPanel | null
|
||||
insertCodes: string
|
||||
diffCodes: string
|
||||
}
|
||||
@@ -12,6 +13,7 @@ export const state: State = {
|
||||
serverPort: null,
|
||||
statusBarItem: null,
|
||||
sidebarWebviewView: null,
|
||||
webviewPanel: null,
|
||||
insertCodes: '',
|
||||
diffCodes: 'aaa',
|
||||
}
|
||||
|
||||
@@ -23,6 +23,22 @@
|
||||
<script>
|
||||
// before-script
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function createEl(tag, attrs = {}) {
|
||||
const el = document.createElement(tag)
|
||||
Object.keys(attrs).forEach((key) => {
|
||||
el.setAttribute(key, attrs[key])
|
||||
})
|
||||
return el
|
||||
}
|
||||
|
||||
const script = createEl('script', {
|
||||
src: `${window.getGlobalConfig().serverBaseUrl || ''}/api/config/env.js`,
|
||||
})
|
||||
|
||||
document.head.appendChild(script)
|
||||
</script>
|
||||
<base href="/">
|
||||
<link href="/codicon/codicon.css" rel="stylesheet" />
|
||||
</head>
|
||||
@@ -35,4 +51,4 @@
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getSearchParams } from '@nicepkg/gpt-runner-shared/browser'
|
||||
import { EnvConfig } from '@nicepkg/gpt-runner-shared/common'
|
||||
|
||||
export interface GlobalConfig {
|
||||
rootPath: string
|
||||
@@ -11,7 +12,7 @@ export interface GlobalConfig {
|
||||
window.__DEFAULT_GLOBAL_CONFIG__ = {
|
||||
rootPath: getSearchParams('rootPath') || '/Users/yangxiaoming/Documents/codes/gpt-runner',
|
||||
initialRoutePath: '/',
|
||||
serverBaseUrl: '',
|
||||
serverBaseUrl: EnvConfig.get('GPTR_BASE_SERVER_URL'),
|
||||
showDiffCodesBtn: false,
|
||||
showInsertCodesBtn: false,
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { BaseResponse, GetStorageReqParams, GetStorageResData, SaveStorageReqParams, SaveStorageResData } from '@nicepkg/gpt-runner-shared/common'
|
||||
import type { BaseResponse, StorageGetItemReqParams, StorageGetItemResData, StorageSetItemReqParams, StorageSetItemResData } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { getGlobalConfig } from '../helpers/global-config'
|
||||
|
||||
export interface GetServerStorageParams extends GetStorageReqParams {
|
||||
export interface GetServerStorageParams extends StorageGetItemReqParams {
|
||||
}
|
||||
|
||||
export type GetServerStorageRes = BaseResponse<GetStorageResData>
|
||||
export type GetServerStorageRes = BaseResponse<StorageGetItemResData>
|
||||
|
||||
export async function getServerStorage(params: GetServerStorageParams): Promise<GetServerStorageRes> {
|
||||
const { storageName, key } = params
|
||||
@@ -19,10 +19,10 @@ export async function getServerStorage(params: GetServerStorageParams): Promise<
|
||||
return data
|
||||
}
|
||||
|
||||
export interface SaveServerStorageParams extends SaveStorageReqParams {
|
||||
export interface SaveServerStorageParams extends StorageSetItemReqParams {
|
||||
}
|
||||
|
||||
export type SaveServerStorageRes = BaseResponse<SaveStorageResData>
|
||||
export type SaveServerStorageRes = BaseResponse<StorageSetItemResData>
|
||||
|
||||
export async function saveServerStorage(params: SaveServerStorageParams): Promise<SaveServerStorageRes> {
|
||||
const { storageName, key, value } = params
|
||||
|
||||
@@ -141,7 +141,9 @@ export const createSidebarTreeSlice: StateCreator<
|
||||
|
||||
if (item.type === GptFileTreeItemType.File) {
|
||||
gptFileIds.push(item.id)
|
||||
|
||||
const chatIds = currentGptFileIdChatIdsMap.get(item.id) || []
|
||||
|
||||
result.children = chatIds.map((chatId) => {
|
||||
const chatInfo = state.getChatInfo(chatId)
|
||||
chatInfo.parentId = item.id
|
||||
|
||||
@@ -20,7 +20,7 @@ async function getStateFromServerOnce(key: string) {
|
||||
}
|
||||
|
||||
// will save each action state to server
|
||||
const debounceSaveStateToServer = debounce(async (key: string, value: ServerStorageValue) => {
|
||||
const debounceSaveStateToServerFn = debounce(async (key: string, value: ServerStorageValue) => {
|
||||
if (hasUpdateStateFromRemote !== 'finish')
|
||||
return
|
||||
|
||||
@@ -31,6 +31,13 @@ const debounceSaveStateToServer = debounce(async (key: string, value: ServerStor
|
||||
})
|
||||
}, 1000)
|
||||
|
||||
function debounceSaveStateToServer(key: string, value: ServerStorageValue) {
|
||||
if (hasUpdateStateFromRemote !== 'finish')
|
||||
return
|
||||
|
||||
debounceSaveStateToServerFn(key, value)
|
||||
}
|
||||
|
||||
export class CustomStorage implements StateStorage {
|
||||
#storage: Storage
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ export function resetAllState() {
|
||||
|
||||
export function createStore(devtoolsName: string) {
|
||||
const newCreate = (store: any) => {
|
||||
const defaultState = create(store).getState()
|
||||
let result: any
|
||||
|
||||
// https://github.com/pmndrs/zustand/issues/852#issuecomment-1059783350
|
||||
@@ -30,11 +29,13 @@ export function createStore(devtoolsName: string) {
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
result = create(store)
|
||||
else {
|
||||
result = create(store)
|
||||
}
|
||||
|
||||
// reset state of this store
|
||||
result.resetState = () => {
|
||||
const defaultState = create(store).getState()
|
||||
result.setState(cloneDeep(defaultState), true)
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"build:server": "unbuild",
|
||||
"dev": "pnpm dev:server & pnpm dev:client",
|
||||
"dev:client": "vite --config ./client/vite.config.ts",
|
||||
"dev:server": "cross-env NODE_OPTIONS='--experimental-fetch' NODE_NO_WARNINGS='1' DEBUG='enabled' pnpm esno server/start-server.ts --auto-free-port",
|
||||
"dev:server": "cross-env NODE_ENV=development NODE_OPTIONS='--experimental-fetch' NODE_NO_WARNINGS='1' DEBUG='enabled' pnpm esno server/start-server.ts --auto-free-port",
|
||||
"start": "cross-env NODE_OPTIONS='--experimental-fetch' NODE_NO_WARNINGS='1' DEBUG='enabled' node dist/start-server.cjs --auto-free-port",
|
||||
"stub": "unbuild --stub"
|
||||
},
|
||||
@@ -104,4 +104,4 @@
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"vite": "^4.3.9"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import './src/proxy'
|
||||
import path from 'node:path'
|
||||
import http from 'node:http'
|
||||
import type { Express } from 'express'
|
||||
import express from 'express'
|
||||
import cors from 'cors'
|
||||
@@ -49,7 +50,11 @@ export async function startServer(props: StartServerProps): Promise<Express> {
|
||||
|
||||
app.use(errorHandlerMiddleware)
|
||||
|
||||
app.listen(finalPort, () => console.log(`Server is running on port ${finalPort}`))
|
||||
const server = http.createServer(app)
|
||||
|
||||
// await processWsControllers(server)
|
||||
|
||||
server.listen(finalPort, () => console.log(`Server is running on port ${finalPort}`))
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Request, Response } from 'express'
|
||||
import type { ChatStreamReqParams, FailResponse, SuccessResponse } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { ChatStreamReqParamsSchema, EnvConfig } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { PathUtils, buildFailResponse, buildSuccessResponse, sendFailResponse, sendSuccessResponse, verifyParamsByZod } from '@nicepkg/gpt-runner-shared/node'
|
||||
import { ChatStreamReqParamsSchema, EnvConfig, buildFailResponse, buildSuccessResponse } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { PathUtils, sendFailResponse, sendSuccessResponse, verifyParamsByZod } from '@nicepkg/gpt-runner-shared/node'
|
||||
import { loadUserConfig } from '@nicepkg/gpt-runner-core'
|
||||
import { chatgptChain } from '../services'
|
||||
import type { ControllerConfig } from './../types'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PathUtils, sendFailResponse, sendSuccessResponse, verifyParamsByZod } from '@nicepkg/gpt-runner-shared/node'
|
||||
import type { GetUserConfigReqParams, GetUserConfigResData } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { GetUserConfigReqParamsSchema, resetUserConfigUnsafeKey } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { EnvConfig, GetUserConfigReqParamsSchema, resetUserConfigUnsafeKey } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { loadUserConfig } from '@nicepkg/gpt-runner-core'
|
||||
import pkg from '../../../package.json'
|
||||
import type { ControllerConfig } from '../types'
|
||||
@@ -19,6 +19,17 @@ export const configControllers: ControllerConfig = {
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
url: '/env.js',
|
||||
method: 'get',
|
||||
handler: async (req, res) => {
|
||||
const envMap = EnvConfig.getClientEnvVarsInServerSide()
|
||||
|
||||
// response a javascript file
|
||||
res.setHeader('Content-Type', 'application/javascript')
|
||||
res.send(`window.__env__ = ${JSON.stringify(envMap)}`)
|
||||
},
|
||||
},
|
||||
{
|
||||
url: '/user-config',
|
||||
method: 'get',
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { NextFunction, Router } from 'express'
|
||||
import { WssActionName, WssUtils, buildFailResponse } from '@nicepkg/gpt-runner-shared/common'
|
||||
import type { Controller, ControllerConfig } from '../types'
|
||||
import { chatgptControllers } from './chatgpt.controller'
|
||||
import { configControllers } from './config.controller'
|
||||
import { gptFilesControllers } from './gpt-files.controller'
|
||||
import { storageControllers } from './storage.controller'
|
||||
import { allWsControllersConfig } from './ws'
|
||||
|
||||
export function processControllers(router: Router) {
|
||||
const allControllersConfig: ControllerConfig[] = [
|
||||
@@ -33,3 +35,34 @@ export function processControllers(router: Router) {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function processWsControllers(server: any) {
|
||||
await WssUtils.instance.connect({ server })
|
||||
|
||||
allWsControllersConfig.forEach((controllerConfig) => {
|
||||
const { controllers } = controllerConfig
|
||||
|
||||
controllers.forEach((controller) => {
|
||||
const { actionName, handler } = controller
|
||||
|
||||
WssUtils.instance.on(actionName, async (params: Record<string, any>) => {
|
||||
console.log(`[WS] ${actionName} params:`, params)
|
||||
try {
|
||||
return await handler(params as any)
|
||||
}
|
||||
catch (error: any) {
|
||||
const errRes = buildFailResponse({ data: error, message: error?.message || String(error) })
|
||||
|
||||
WssUtils.instance.emit(actionName, {
|
||||
reqParams: params as any,
|
||||
res: errRes,
|
||||
})
|
||||
|
||||
WssUtils.instance.emit(WssActionName.Error, {
|
||||
res: errRes,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getStorage, sendSuccessResponse, verifyParamsByZod } from '@nicepkg/gpt-runner-shared/node'
|
||||
import type { GetStorageReqParams, GetStorageResData, SaveStorageReqParams, SaveStorageResData } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { GetStorageReqParamsSchema, SaveStorageReqParamsSchema } from '@nicepkg/gpt-runner-shared/common'
|
||||
import type { StorageClearReqParams, StorageClearResData, StorageGetItemReqParams, StorageGetItemResData, StorageRemoveItemReqParams, StorageRemoveItemResData, StorageSetItemReqParams, StorageSetItemResData } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { StorageClearReqParamsSchema, StorageGetItemReqParamsSchema, StorageRemoveItemReqParamsSchema, StorageSetItemReqParamsSchema } from '@nicepkg/gpt-runner-shared/common'
|
||||
import type { ControllerConfig } from '../types'
|
||||
|
||||
export const storageControllers: ControllerConfig = {
|
||||
@@ -10,9 +10,9 @@ export const storageControllers: ControllerConfig = {
|
||||
url: '/',
|
||||
method: 'get',
|
||||
handler: async (req, res) => {
|
||||
const query = req.query as GetStorageReqParams
|
||||
const query = req.query as StorageGetItemReqParams
|
||||
|
||||
verifyParamsByZod(query, GetStorageReqParamsSchema)
|
||||
verifyParamsByZod(query, StorageGetItemReqParamsSchema)
|
||||
|
||||
const { key, storageName } = query
|
||||
|
||||
@@ -23,7 +23,7 @@ export const storageControllers: ControllerConfig = {
|
||||
data: {
|
||||
value,
|
||||
cacheDir,
|
||||
} satisfies GetStorageResData,
|
||||
} satisfies StorageGetItemResData,
|
||||
})
|
||||
},
|
||||
},
|
||||
@@ -31,27 +31,53 @@ export const storageControllers: ControllerConfig = {
|
||||
url: '/',
|
||||
method: 'post',
|
||||
handler: async (req, res) => {
|
||||
const body = req.body as SaveStorageReqParams
|
||||
const body = req.body as StorageSetItemReqParams
|
||||
|
||||
verifyParamsByZod(body, SaveStorageReqParamsSchema)
|
||||
verifyParamsByZod(body, StorageSetItemReqParamsSchema)
|
||||
|
||||
const { storageName, key, value } = body
|
||||
|
||||
const { storage } = await getStorage(storageName)
|
||||
|
||||
switch (value) {
|
||||
case undefined:
|
||||
// remove
|
||||
await storage.delete(key)
|
||||
break
|
||||
default:
|
||||
// set
|
||||
await storage.set(key, value)
|
||||
break
|
||||
}
|
||||
await storage.set(key, value)
|
||||
|
||||
sendSuccessResponse(res, {
|
||||
data: null satisfies SaveStorageResData,
|
||||
data: null satisfies StorageSetItemResData,
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
url: '/',
|
||||
method: 'delete',
|
||||
handler: async (req, res) => {
|
||||
const body = req.body as StorageRemoveItemReqParams
|
||||
|
||||
verifyParamsByZod(body, StorageRemoveItemReqParamsSchema)
|
||||
|
||||
const { key, storageName } = body
|
||||
const { storage } = await getStorage(storageName)
|
||||
|
||||
await storage.delete(key)
|
||||
|
||||
sendSuccessResponse(res, {
|
||||
data: null satisfies StorageRemoveItemResData,
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
url: '/clear',
|
||||
method: 'post',
|
||||
handler: async (req, res) => {
|
||||
const body = req.body as StorageClearReqParams
|
||||
|
||||
verifyParamsByZod(body, StorageClearReqParamsSchema)
|
||||
|
||||
const { storageName } = body
|
||||
const { storage } = await getStorage(storageName)
|
||||
|
||||
await storage.clear()
|
||||
|
||||
sendSuccessResponse(res, {
|
||||
data: null satisfies StorageClearResData,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import type { WssControllerConfig } from '../../types'
|
||||
import { storageControllers } from './storage.ws-controller'
|
||||
|
||||
export const allWsControllersConfig: WssControllerConfig[] = [storageControllers]
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { StorageClearResData, StorageGetItemReqParams, StorageGetItemResData, StorageRemoveItemReqParams, StorageRemoveItemResData, StorageSetItemReqParams, StorageSetItemResData } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { StorageClearReqParamsSchema, StorageGetItemReqParamsSchema, StorageRemoveItemReqParamsSchema, StorageSetItemReqParamsSchema, WssActionName, WssUtils, buildSuccessResponse } from '@nicepkg/gpt-runner-shared/common'
|
||||
import { getStorage, verifyParamsByZod } from '@nicepkg/gpt-runner-shared/node'
|
||||
import type { WssControllerConfig } from '../../types'
|
||||
|
||||
export const storageControllers: WssControllerConfig = {
|
||||
controllers: [
|
||||
{
|
||||
actionName: WssActionName.StorageGetItem,
|
||||
handler: async (params: StorageGetItemReqParams) => {
|
||||
verifyParamsByZod(params, StorageGetItemReqParamsSchema)
|
||||
|
||||
const { key, storageName } = params
|
||||
|
||||
const { storage, cacheDir } = await getStorage(storageName)
|
||||
const value = await storage.get(key)
|
||||
|
||||
WssUtils.instance.emit(WssActionName.StorageGetItem, {
|
||||
reqParams: params,
|
||||
res: buildSuccessResponse({
|
||||
data: {
|
||||
value,
|
||||
cacheDir,
|
||||
} satisfies StorageGetItemResData,
|
||||
}),
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
actionName: WssActionName.StorageSetItem,
|
||||
handler: async (params: StorageSetItemReqParams) => {
|
||||
verifyParamsByZod(params, StorageSetItemReqParamsSchema)
|
||||
|
||||
const { storageName, key, value } = params
|
||||
|
||||
const { storage } = await getStorage(storageName)
|
||||
await storage.set(key, value)
|
||||
|
||||
WssUtils.instance.emit(WssActionName.StorageSetItem, {
|
||||
reqParams: params,
|
||||
res: buildSuccessResponse({
|
||||
data: null satisfies StorageSetItemResData,
|
||||
}),
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
actionName: WssActionName.StorageRemoveItem,
|
||||
handler: async (params: StorageRemoveItemReqParams) => {
|
||||
verifyParamsByZod(params, StorageRemoveItemReqParamsSchema)
|
||||
|
||||
const { key, storageName } = params
|
||||
|
||||
const { storage } = await getStorage(storageName)
|
||||
await storage.delete(key)
|
||||
|
||||
WssUtils.instance.emit(WssActionName.StorageRemoveItem, {
|
||||
reqParams: params,
|
||||
res: buildSuccessResponse({
|
||||
data: null satisfies StorageRemoveItemResData,
|
||||
}),
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
actionName: WssActionName.StorageClear,
|
||||
handler: async (params) => {
|
||||
verifyParamsByZod(params, StorageClearReqParamsSchema)
|
||||
|
||||
const { storageName } = params
|
||||
|
||||
const { storage } = await getStorage(storageName)
|
||||
await storage.clear()
|
||||
|
||||
WssUtils.instance.emit(WssActionName.StorageClear, {
|
||||
reqParams: params,
|
||||
res: buildSuccessResponse({
|
||||
data: null satisfies StorageClearResData,
|
||||
}),
|
||||
})
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -1,11 +1,21 @@
|
||||
import type { WssActionName } from '@nicepkg/gpt-runner-shared/common'
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
|
||||
export interface ControllerConfig {
|
||||
namespacePath: string
|
||||
controllers: Controller[]
|
||||
}
|
||||
export interface Controller {
|
||||
url: string
|
||||
method: 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head'
|
||||
handler: (req: Request<Record<string, any>, any, any, Record<string, any>>, res: Response, next: NextFunction) => Promise<void>
|
||||
}
|
||||
export interface ControllerConfig {
|
||||
namespacePath: string
|
||||
controllers: Controller[]
|
||||
}
|
||||
|
||||
export interface WssController {
|
||||
actionName: WssActionName
|
||||
handler: (params: any) => Promise<void>
|
||||
}
|
||||
|
||||
export interface WssControllerConfig {
|
||||
controllers: WssController[]
|
||||
}
|
||||
|
||||
124
pnpm-lock.yaml
generated
124
pnpm-lock.yaml
generated
@@ -335,6 +335,12 @@ importers:
|
||||
minimatch:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
socket.io:
|
||||
specifier: ^4.6.2
|
||||
version: 4.6.2
|
||||
socket.io-client:
|
||||
specifier: ^4.6.2
|
||||
version: 4.6.2
|
||||
zod:
|
||||
specifier: ^3.21.4
|
||||
version: 3.21.4
|
||||
@@ -3968,6 +3974,10 @@ packages:
|
||||
webpack-sources: 3.2.3
|
||||
dev: false
|
||||
|
||||
/@socket.io/component-emitter@3.1.0:
|
||||
resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==}
|
||||
dev: false
|
||||
|
||||
/@surma/rollup-plugin-off-main-thread@2.2.3:
|
||||
resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==}
|
||||
dependencies:
|
||||
@@ -4354,13 +4364,11 @@ packages:
|
||||
|
||||
/@types/cookie@0.4.1:
|
||||
resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==}
|
||||
dev: true
|
||||
|
||||
/@types/cors@2.8.13:
|
||||
resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==}
|
||||
dependencies:
|
||||
'@types/node': 18.16.9
|
||||
dev: true
|
||||
|
||||
/@types/debug@4.1.7:
|
||||
resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==}
|
||||
@@ -5524,6 +5532,11 @@ packages:
|
||||
/base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
/base64id@2.0.0:
|
||||
resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
|
||||
engines: {node: ^4.5.0 || >= 5.9}
|
||||
dev: false
|
||||
|
||||
/batch@0.6.1:
|
||||
resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==}
|
||||
dev: false
|
||||
@@ -6295,7 +6308,6 @@ packages:
|
||||
/cookie@0.4.2:
|
||||
resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: true
|
||||
|
||||
/cookie@0.5.0:
|
||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
||||
@@ -7368,6 +7380,45 @@ packages:
|
||||
once: 1.4.0
|
||||
dev: false
|
||||
|
||||
/engine.io-client@6.4.0:
|
||||
resolution: {integrity: sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==}
|
||||
dependencies:
|
||||
'@socket.io/component-emitter': 3.1.0
|
||||
debug: 4.3.4
|
||||
engine.io-parser: 5.0.7
|
||||
ws: 8.11.0
|
||||
xmlhttprequest-ssl: 2.0.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/engine.io-parser@5.0.7:
|
||||
resolution: {integrity: sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dev: false
|
||||
|
||||
/engine.io@6.4.2:
|
||||
resolution: {integrity: sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dependencies:
|
||||
'@types/cookie': 0.4.1
|
||||
'@types/cors': 2.8.13
|
||||
'@types/node': 18.16.9
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
cookie: 0.4.2
|
||||
cors: 2.8.5
|
||||
debug: 4.3.4
|
||||
engine.io-parser: 5.0.7
|
||||
ws: 8.11.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/enhanced-resolve@5.14.1:
|
||||
resolution: {integrity: sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
@@ -14459,6 +14510,55 @@ packages:
|
||||
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
|
||||
dev: true
|
||||
|
||||
/socket.io-adapter@2.5.2:
|
||||
resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==}
|
||||
dependencies:
|
||||
ws: 8.11.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/socket.io-client@4.6.2:
|
||||
resolution: {integrity: sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dependencies:
|
||||
'@socket.io/component-emitter': 3.1.0
|
||||
debug: 4.3.4
|
||||
engine.io-client: 6.4.0
|
||||
socket.io-parser: 4.2.4
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/socket.io-parser@4.2.4:
|
||||
resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dependencies:
|
||||
'@socket.io/component-emitter': 3.1.0
|
||||
debug: 4.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/socket.io@4.6.2:
|
||||
resolution: {integrity: sha512-Vp+lSks5k0dewYTfwgPT9UeGGd+ht7sCpB7p0e83VgO4X/AHYWhXITMrNk/pg8syY2bpx23ptClCQuHhqi2BgQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dependencies:
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
debug: 4.3.4
|
||||
engine.io: 6.4.2
|
||||
socket.io-adapter: 2.5.2
|
||||
socket.io-parser: 4.2.4
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/sockjs@0.3.24:
|
||||
resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==}
|
||||
dependencies:
|
||||
@@ -16827,6 +16927,19 @@ packages:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/ws@8.11.0:
|
||||
resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: ^5.0.2
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/ws@8.13.0:
|
||||
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -16860,6 +16973,11 @@ packages:
|
||||
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
||||
dev: true
|
||||
|
||||
/xmlhttprequest-ssl@2.0.0:
|
||||
resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
||||
Reference in New Issue
Block a user