From cb98d8dc3dfe9e9f65bbd6a41e68f58bffeb7ab9 Mon Sep 17 00:00:00 2001 From: TomatoCake <60300461+DEVTomatoCake@users.noreply.github.com> Date: Sat, 27 Jul 2024 12:23:30 +0200 Subject: [PATCH] File refreshing & short "stat" cache --- .vscodeignore | 1 + eslint.config.js | 1 + package-lock.json | 18 +++++++++--------- package.json | 20 +++++++++++++++++--- src/extension.ts | 39 +++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 16 deletions(-) diff --git a/.vscodeignore b/.vscodeignore index 0fffbb3..9f567f4 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -5,3 +5,4 @@ out/src/*.js.map .gitignore tsconfig.json +eslint.config.js diff --git a/eslint.config.js b/eslint.config.js index b264b3f..d2c5d98 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -10,6 +10,7 @@ module.exports = [ languageOptions: { globals: { fetch: "readonly", + setTimeout: "readonly", Response: "readonly" }, parser: require("@typescript-eslint/parser") diff --git a/package-lock.json b/package-lock.json index 82453f4..dba2e6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1384,9 +1384,9 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -1560,9 +1560,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz", - "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.2.tgz", + "integrity": "sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==", "dev": true }, "node_modules/emoji-regex": { @@ -4163,9 +4163,9 @@ "dev": true }, "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", "dev": true }, "node_modules/undici-types": { diff --git a/package.json b/package.json index 1ff9d0e..f895b23 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "pterodactyl-vsc", "displayName": "Pterodactyl file system", "description": "Open a Pterodactyl server folder as a remote workspace.", - "version": "1.0.3", + "version": "1.1.0", "publisher": "tomatocake", "license": "MIT", "main": "./out/src/extension", @@ -15,7 +15,7 @@ "url": "https://github.com/DEVTomatoCake/Pterodactyl-vsc.git" }, "engines": { - "vscode": "^1.88.0" + "vscode": "^1.91.0" }, "categories": [ "Other" @@ -35,12 +35,20 @@ "commands": [ { "command": "pterodactyl-vsc.init", - "title": "Connect to server", + "title": "Setup/Connect to server", + "shortTitle": "Setup", "category": "Pterodactyl" }, { "command": "pterodactyl-vsc.reset", "title": "Reset workspace config", + "shortTitle": "Reset", + "category": "Pterodactyl" + }, + { + "command": "pterodactyl-vsc.refresh", + "title": "Refresh server files", + "shortTitle": "Refresh", "category": "Pterodactyl" } ], @@ -53,6 +61,10 @@ { "command": "pterodactyl-vsc.reset", "when": "workbenchState == workspace" + }, + { + "command": "pterodactyl-vsc.refresh", + "when": "workbenchState == workspace" } ] }, @@ -106,7 +118,9 @@ "watch": "tsc -watch -p ./", "pack": "vsce pack -o ./out/pterodactyl-vsc.vsix -t web", "pack-files": "vsce ls", + "--comment-publish": "https://dev.azure.com/tomatocake/_usersSettings/tokens", "publish": "vsce publish", + "--comment-publish-openvsx": "https://open-vsx.org/user-settings/tokens", "publish-openvsx": "npx ovsx publish ./out/pterodactyl-vsc.vsix", "sideload": "npx serve --cors -l 5000 --ssl-cert $HOME/certs/localhost.pem --ssl-key $HOME/certs/localhost-key.pem", "sideload-win": "npx serve --cors -l 5000 --ssl-cert %userprofile%\\certs\\localhost.pem --ssl-key %userprofile%\\certs\\localhost-key.pem" diff --git a/src/extension.ts b/src/extension.ts index af6c645..6f920e0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -92,6 +92,9 @@ const addPanel = async () => { }) } +const responseCache = new Map() +const responseCacheHits = new Map() + export class PterodactylFileSystemProvider implements vscode.FileSystemProvider { private readonly _eventEmitter: vscode.EventEmitter @@ -278,6 +281,11 @@ export class PterodactylFileSystemProvider implements vscode.FileSystemProvider public async stat(uri: vscode.Uri): Promise { if (serverApiUrl == "") throw vscode.FileSystemError.Unavailable("No server API URL set, please init the extension first.") + if (responseCache.has("stat:" + uri.toString())) { + responseCacheHits.set("stat:" + uri.toString(), responseCacheHits.get("stat:" + uri.toString()) + 1) + return responseCache.get("stat:" + uri.toString()) + } + if (uri.path == "/") return { ctime: 0, mtime: 0, @@ -303,7 +311,7 @@ export class PterodactylFileSystemProvider implements vscode.FileSystemProvider const file = json.data.find((f: any) => f.attributes.name == uri.path.split("/").pop())?.attributes if (!file) throw vscode.FileSystemError.FileNotFound(uri) - return { + const response = { ctime: new Date(file.created_at).getTime(), mtime: new Date(file.modified_at).getTime(), permissions: file.mode[2] == "w" ? void 0 : vscode.FilePermission.Readonly, @@ -312,6 +320,17 @@ export class PterodactylFileSystemProvider implements vscode.FileSystemProvider ? (file.is_symlink ? vscode.FileType.File | vscode.FileType.SymbolicLink : vscode.FileType.File) : (file.is_symlink ? vscode.FileType.Directory | vscode.FileType.SymbolicLink : vscode.FileType.Directory) } + + responseCache.set("stat:" + uri.toString(), response) + responseCacheHits.set("stat:" + uri.toString(), 0) + setTimeout(() => { + log(responseCacheHits.get("stat:" + uri.toString()) + " cache hits for stat requests on " + uri.toString()) + + responseCache.delete("stat:" + uri.toString()) + responseCacheHits.delete("stat:" + uri.toString()) + }, 1000 * 10) + + return response } public async writeFile(uri: vscode.Uri, content: Uint8Array, options: { create: boolean, overwrite: boolean }): Promise { @@ -359,10 +378,13 @@ export const activate = (context: vscode.ExtensionContext) => { context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(event => { log("Detected configuration change") if (event.affectsConfiguration("pterodactyl-vsc.panelUrl") || event.affectsConfiguration("pterodactyl-vsc.serverId")) { + const serverId = vscode.workspace.getConfiguration("pterodactyl-vsc").get("serverId") + if (!serverId) return log("-> No server ID set, not updating server API URL") + const parsedUrl = vscode.Uri.parse(vscode.workspace.getConfiguration("pterodactyl-vsc").get("panelUrl") || "") - log("Setting server api URL to " + parsedUrl.scheme + "://" + parsedUrl.authority + "/api/client/servers/" + - vscode.workspace.getConfiguration("pterodactyl-vsc").get("serverId") + "/files") - serverApiUrl = parsedUrl.scheme + "://" + parsedUrl.authority + "/api/client/servers/" + vscode.workspace.getConfiguration("pterodactyl-vsc").get("serverId") + "/files" + + log("Setting server api URL to " + parsedUrl.scheme + "://" + parsedUrl.authority + "/api/client/servers/" + serverId + "/files") + serverApiUrl = parsedUrl.scheme + "://" + parsedUrl.authority + "/api/client/servers/" + serverId + "/files" } if (event.affectsConfiguration("pterodactyl-vsc.apiKey")) authHeader = "Bearer " + vscode.workspace.getConfiguration("pterodactyl-vsc").get("apiKey") @@ -380,4 +402,13 @@ export const activate = (context: vscode.ExtensionContext) => { log("Reset workspace") })) + + context.subscriptions.push(vscode.commands.registerCommand("pterodactyl-vsc.refresh", () => { + log("Refreshing workspace server files...") + + vscode.workspace.updateWorkspaceFolders(0, vscode.workspace.workspaceFolders?.length || 0, { + uri: vscode.Uri.parse("pterodactyl:/"), + name: "Pterodactyl" + }) + })) }