import type { PluginApiClient } from "@termix/plugin-sdk/frontend"; import type { Snippet, SnippetAccessEntry, SnippetFolder } from "./types"; export interface NewSnippetInput { name: string; content: string; description?: string | null; folder?: string | null; order?: number | null; hostFilter?: unknown; isNote?: boolean; } export interface SnippetUpdateInput { name?: string; content?: string; description?: string | null; folder?: string | null; order?: number; hostFilter?: unknown; isNote?: boolean; } export interface SnippetReorderUpdate { id: number; order: number; folder?: string; } export interface SnippetExecutionResult { success: boolean; output: string; error?: string; } export interface ShareableUser { id: string; username: string; } export interface ShareableRole { id: number; name: string; displayName: string | null; } export interface SnippetShareInput { targetType: "user" | "role"; targetUserId?: string; targetRoleId?: number; expiresAt?: string | null; } /** * The snippets routes, through the plugin's own client. Paths are relative * to /plugin-api/snippets/, which the client already points at. */ export function createSnippetsApi(api: PluginApiClient) { const data = async (request: Promise<{ data: T }>) => (await request).data; return { list: () => data(api.get("/")), get: (id: number) => data(api.get(`/${id}`)), create: (body: NewSnippetInput) => data(api.post("/", body)), update: (id: number, body: SnippetUpdateInput) => data(api.put(`/${id}`, body)), remove: (id: number) => data(api.delete<{ success: boolean }>(`/${id}`)), execute: ( snippetId: number, hostId: number, inputValues?: Record, ) => data( api.post("/execute", { snippetId, hostId, inputValues, }), ), reorder: (updates: SnippetReorderUpdate[]) => data(api.put<{ success: boolean }>("/reorder", { snippets: updates })), export: () => data(api.get<{ snippets: unknown[]; folders: unknown[] }>("/export")), bulkImport: (body: { snippets?: unknown[]; folders?: unknown[]; overwrite?: boolean; }) => data(api.post<{ success: boolean }>("/bulk-import", body)), listFolders: () => data(api.get("/folders")), createFolder: (body: { name: string; color?: string | null; icon?: string | null; }) => data(api.post("/folders", body)), updateFolderMetadata: ( name: string, body: { color?: string | null; icon?: string | null }, ) => data( api.put( `/folders/${encodeURIComponent(name)}/metadata`, body, ), ), renameFolder: (oldName: string, newName: string) => data( api.put<{ success: boolean }>("/folders/rename", { oldName, newName }), ), deleteFolder: (name: string) => data( api.delete<{ success: boolean }>( `/folders/${encodeURIComponent(name)}`, ), ), share: (snippetId: number, body: SnippetShareInput) => data(api.post<{ success: boolean }>(`/${snippetId}/share`, body)), shareFolder: (folder: string, body: SnippetShareInput) => data( api.put<{ success: boolean; snippetsShared: number }>("/folder/share", { folder, ...body, }), ), getAccess: (snippetId: number) => data(api.get(`/${snippetId}/access`)), revokeAccess: (snippetId: number, accessId: number) => data( api.delete<{ success: boolean }>(`/${snippetId}/access/${accessId}`), ), shareTargetUsers: () => data(api.get<{ users: ShareableUser[] }>("/share-targets/users")), shareTargetRoles: () => data(api.get<{ roles: ShareableRole[] }>("/share-targets/roles")), listShared: () => data(api.get<{ sharedSnippets: Snippet[] }>("/shared")), }; } export type SnippetsApi = ReturnType;