diff --git a/.vitepress/sidebars/guides.ts b/.vitepress/sidebars/guides.ts index 5b5c75c..24fd614 100644 --- a/.vitepress/sidebars/guides.ts +++ b/.vitepress/sidebars/guides.ts @@ -33,10 +33,6 @@ export const guidesSidebar: DefaultTheme.SidebarItem[] = [ text: "Customizing Context Menus", link: "/guides/components/menu", }, - { - text: "Handling Backend Events", - link: "/guides/components/backend_events", - }, { text: "Using the Component Library", link: "/guides/components/styling", @@ -50,6 +46,10 @@ export const guidesSidebar: DefaultTheme.SidebarItem[] = [ text: "Creating and Calling a Custom Function", link: "/guides/components/rpc", }, + { + text: "Handling Backend Events", + link: "/guides/components/backend_events", + }, { text: "Sending HTTP Requests", link: "/guides/components/request", @@ -83,6 +83,10 @@ export const guidesSidebar: DefaultTheme.SidebarItem[] = [ { text: "Shared", items: [ + { + text: "Adding Files", + link: "/guides/components/files", + }, { text: "Using Environment Variables", link: "/guides/components/env", diff --git a/src/_images/backend_assets_key.png b/src/_images/backend_assets_key.png new file mode 100644 index 0000000..fcd7fde Binary files /dev/null and b/src/_images/backend_assets_key.png differ diff --git a/src/_images/frontend_assets_key.png b/src/_images/frontend_assets_key.png new file mode 100644 index 0000000..fed87cf Binary files /dev/null and b/src/_images/frontend_assets_key.png differ diff --git a/src/_images/view_file_frontend.png b/src/_images/view_file_frontend.png new file mode 100644 index 0000000..35f42eb Binary files /dev/null and b/src/_images/view_file_frontend.png differ diff --git a/src/guides/components/fetch.md b/src/guides/components/fetch.md index f5bbba9..256c78a 100644 --- a/src/guides/components/fetch.md +++ b/src/guides/components/fetch.md @@ -103,7 +103,7 @@ To view the entire script, expand the following:
Full Script -``` js +``` ts import type { SDK, DefineAPI } from "caido:plugin"; import { Request as FetchRequest, fetch } from "caido:http"; @@ -188,7 +188,7 @@ To view how the endpoint can be called with a frontend plugin, expand the follow
Full Script -``` js +``` ts import type { Caido } from "@caido/sdk-frontend"; import type { API } from "../../backend/src/index.ts"; diff --git a/src/guides/components/files.md b/src/guides/components/files.md new file mode 100644 index 0000000..cdcb910 --- /dev/null +++ b/src/guides/components/files.md @@ -0,0 +1,181 @@ +# Adding Files + +To include additional files in your Caido plugins, you can add the `assets` property key to either the frontend or backend component objects in the `caido.config.ts` file. The key value is an array that stores the locations of any files accessible to the plugin. + +In this guide we'll cover how to add a file to a plugin named `myfile.txt`. + +## Shared Steps + +In the root directory of your plugin package, create a new directory named `assets`. Within this directory, create the `myfile.txt` file, write content to it, and save it. The file can now be referenced with: + +``` ts +assets : ["./assets/myfile.txt"] +``` + +::: tip TIPS + +Glob syntax (`*`) is supported to reference multiple files: + +- `/path/*.txt`: Will include all `.txt` files in the path directory. +- `/**/file.txt`: Will include any `file.txt` within any directory. + +Files and directories are included differently: + +- For a file, it will copy it at the root of the output assets directory. +- For a directory, it will copy it recursively in the output assets directory. +::: + +::: info +The `assets` key can also be added to a plugin's `manifest.json` file. However, multiple locations can not be defined with this method. +::: + +## Adding Files to the Frontend Component + +Open the `caido.config.ts` file and add the property to the `frontend` component object: + +Event output. + +### /packages/frontend/src/index.ts + +To read the file, the `sdk.assets.get()` method can be called. + +``` ts +const file = await sdk.assets.get("myfile.txt"); +``` + +::: tip +To view the entire frontend script, expand the following: + +
+Full Script + +``` ts +import "./styles/index.css"; + +import type { FrontendSDK } from "./types"; + +// Note that the init function is async to account for fetching the files. +export const init = async (sdk: FrontendSDK) => { + + const root = document.createElement("div"); + Object.assign(root.style, { + height: "100%", + width: "100%", + }); + + root.id = `plugin--frontend-vanilla`; + + const parent = document.createElement("div"); + parent.classList.add("h-full", "flex", "justify-center", "items-center"); + + const container = document.createElement("div"); + container.classList.add("flex", "flex-col", "gap-1", "p-4"); + + const file = await sdk.assets.get("myfile.txt"); + // For large files or to process in chunks, use file.asReadableStream() instead. + const content = await file.asString(); + container.textContent = content; + + parent.appendChild(container); + + root.appendChild(parent); + + sdk.navigation.addPage("/view-file-plugin", { + body: root, + }); + + sdk.sidebar.registerItem("View File Plugin", "/view-file-plugin"); +}; +``` + +
+::: + +## Adding Files to the Backend Component + +Open the `caido.config.ts` file and add the property to the `backend` component object: + +Event output. + +### /packages/backend/src/index.ts + +By [creating a custom backend function](./rpc.md) to read the file, we can later call it from the frontend: + +``` ts +import type { DefineAPI, SDK } from "caido:plugin"; +import { readFile } from 'fs/promises'; +import path from "path"; + +const readMyFile = async (sdk: SDK) => { + try { + const filePath = path.join(sdk.meta.assetsPath(), "myfile.txt"); + const contents = await readFile(filePath, { encoding: 'utf8' }); + sdk.console.log(contents); + return contents; + } catch (err: any) { + sdk.console.error(err.message); + throw err; + } +}; + +export type API = DefineAPI<{ + readMyFile: typeof readMyFile; +}>; + +export function init(sdk: SDK) { + sdk.api.register("readMyFile", readMyFile); +} +``` + +::: tip +To view the entire frontend script, expand the following: + +
+Full Script + +``` ts +import "./styles/index.css"; + +import type { FrontendSDK } from "./types"; + +export const init = async (sdk: FrontendSDK) => { + const root = document.createElement("div"); + Object.assign(root.style, { + height: "100%", + width: "100%", + }); + + root.id = `plugin--frontend-vanilla`; + + const parent = document.createElement("div"); + parent.classList.add("h-full", "flex", "justify-center", "items-center"); + + const container = document.createElement("div"); + container.classList.add("flex", "flex-col", "gap-1", "p-4"); + + try { + // Call the backend readMyFile() function to read myfile.txt. + const content = await sdk.backend.readMyFile(); + container.textContent = content; + } catch (error: any) { + container.textContent = `Error reading file: ${error.message}`; + } + + parent.appendChild(container); + + root.appendChild(parent); + + sdk.navigation.addPage("/view-file-plugin", { + body: root, + }); + + sdk.sidebar.registerItem("View File Plugin", "/view-file-plugin"); +}; +``` + +
+::: + +## The Result + +Event output.