@danxbot/plugin-sdk 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,135 @@
1
+ /** The lockfiles a project may carry; the archive must hold one so the download installs the exact versions it was built with. */
2
+ declare const LOCKFILE_NAMES: string[];
3
+ /**
4
+ * The files of a plugin project's source archive, sorted. Inside git: tracked plus untracked-unignored. Outside git: everything the top-level
5
+ * `.gitignore` does not ignore. Both drop `node_modules`, `.git`, a top-level `dist` and every `.env*` file.
6
+ */
7
+ declare function sourceFiles(projectDir: string): Promise<string[]>;
8
+ /** The project's source as a gzip-compressed tar archive, ready for `source_archive_base64`. The same files give the same bytes (fixed mtime, `portable`). */
9
+ declare function archiveSource(projectDir: string): Promise<Buffer>;
10
+
11
+ /** One file of the built plugin, other than the manifest itself (a file cannot hold its own hash). */
12
+ interface PluginManifestFile {
13
+ /** Relative to the output folder, `/` separated. */
14
+ readonly path: string;
15
+ readonly size: number;
16
+ /** Lowercase hex. */
17
+ readonly sha256: string;
18
+ }
19
+ interface PluginManifest {
20
+ /** The ES module the app `import()`s, a `path` in `files`. */
21
+ readonly entry: string;
22
+ /** The stylesheets to add with the module, each a `path` in `files`; empty when the plugin ships none. */
23
+ readonly styles: readonly string[];
24
+ /** DX-5171: a screenshot taken at publish, a listed `.png` or `.webp` shown to the approver; absent when there is none. */
25
+ readonly screenshot?: string;
26
+ /** Each shared library's major the plugin was built against (`PLUGIN_RUNTIME_LIBRARIES`), compared with what the app serves. */
27
+ readonly runtime: Readonly<Record<string, number>>;
28
+ readonly files: readonly PluginManifestFile[];
29
+ }
30
+
31
+ /** The project's build output folder: the SDK's Vite preset builds into Vite's default `dist`. */
32
+ declare const PLUGIN_DIST_DIR = "dist";
33
+ /** One built file, as the upload route takes it. */
34
+ interface BuiltFile {
35
+ readonly path: string;
36
+ readonly bytes: Buffer;
37
+ }
38
+ interface BuiltPlugin {
39
+ readonly manifest: PluginManifest;
40
+ readonly files: readonly BuiltFile[];
41
+ }
42
+ /**
43
+ * Runs the project's own `npm run build` in a short-lived child process (the DX-4727 pattern): everything Vite loads belongs to that
44
+ * process and is released when it exits, so the long-lived MCP server never holds a file of the plugin's project. A non-zero exit
45
+ * rejects with the tail of the build's output.
46
+ */
47
+ declare function runProjectBuild(projectDir: string): Promise<void>;
48
+ /**
49
+ * Reads what a build left in `<projectDir>/dist`: the `danx-plugin.json` manifest the `danxPlugin()` preset wrote and the bytes of every
50
+ * file it lists. Whether the manifest is valid is the dashboard's to say (`manifest-validation.ts`); this only refuses a build that left
51
+ * no manifest, because there is nothing to upload then.
52
+ */
53
+ declare function readBuiltPlugin(projectDir: string): Promise<BuiltPlugin>;
54
+ /** Builds the project and reads the result. */
55
+ declare function buildPlugin(projectDir: string): Promise<BuiltPlugin>;
56
+
57
+ /** Where a screenshot lands in the bundle; the manifest's `screenshot` field names it (DX-5171). */
58
+ declare const PLUGIN_SCREENSHOT_FILE = "screenshot.png";
59
+ /**
60
+ * The built plugin with a screenshot added to the upload: the PNG joins the files, and the manifest lists it (size and sha256 like every other
61
+ * file) and names it in `screenshot`. Only the upload carries it; the project's `dist/` is untouched, so a rebuild from the source download
62
+ * yields the same files minus this one.
63
+ */
64
+ declare function withScreenshot(built: BuiltPlugin, png: Buffer): BuiltPlugin;
65
+
66
+ /**
67
+ * DX-5237 - the one seam between the publish flow and the dashboard. The MCP tool passes its authenticated `DashboardHttpClient`; the
68
+ * `danx-plugin` CLI passes {@link fetchTransport}. The flow never builds a URL or a header, so neither caller's credential handling leaks into it.
69
+ */
70
+ /** A 2xx answer or a 4xx refusal, the body parsed and untouched: a refusal's named reason must reach the caller verbatim. 5xx and network failures throw. */
71
+ interface TransportResult {
72
+ readonly ok: boolean;
73
+ readonly status: number;
74
+ readonly body: unknown;
75
+ }
76
+ interface PluginTransport {
77
+ request(call: {
78
+ method: "GET" | "POST";
79
+ path: string;
80
+ query?: Record<string, string | number>;
81
+ body?: unknown;
82
+ }): Promise<TransportResult>;
83
+ }
84
+ /** A transport over `fetch` for a person's own API key (`Authorization: Bearer`, `.claude/rules/dashboard.md` "Scripting the API"). */
85
+ declare function fetchTransport(config: {
86
+ baseUrl: string;
87
+ apiKey: string;
88
+ }, fetchImpl?: typeof fetch): PluginTransport;
89
+
90
+ /** The Settings page that lists a plugin's revisions and approves them (`frontend/src/app/settings-nav.ts`, `plugins`). */
91
+ declare const PLUGINS_SETTINGS_PATH = "/settings/team/plugins";
92
+ interface PublishInput {
93
+ /** The plugin's stable key within the team (lowercase letters, digits, - and _). Created on the first publish. */
94
+ readonly plugin: string;
95
+ /** The display name given to a plugin this publish creates; ignored when the plugin exists. Defaults to the key. */
96
+ readonly name?: string;
97
+ /** What this revision changes, shown to the approver. */
98
+ readonly note: string;
99
+ readonly built: BuiltPlugin;
100
+ /** The project's `source.tar.gz`. */
101
+ readonly source: Buffer;
102
+ /** The dashboard's base URL, the front of the approval link. */
103
+ readonly dashboardUrl: string;
104
+ }
105
+ /** What a published revision answers. */
106
+ interface PublishedRevision {
107
+ readonly plugin: string;
108
+ readonly plugin_id: number;
109
+ readonly revision_id: string;
110
+ readonly revision_no: number;
111
+ /** Where a team admin approves it: Settings > Plugins. */
112
+ readonly approval_url: string;
113
+ }
114
+ /** `ok: true` carries the revision; a refusal is the dashboard's, untouched, with the step it came from (`find`, `create` or `upload`). */
115
+ type PublishResult = {
116
+ readonly ok: true;
117
+ readonly status: number;
118
+ readonly body: PublishedRevision;
119
+ } | {
120
+ readonly ok: false;
121
+ readonly status: number;
122
+ readonly body: unknown;
123
+ readonly step: "find" | "create" | "upload";
124
+ };
125
+ /** The one rule for a blank note. The MCP tool and the CLI call it first, before the build, so a blank note costs nothing; `uploadRevision` calls it too. */
126
+ declare function assertNote(note: string): void;
127
+ /**
128
+ * Uploads a built plugin as a new revision: finds the plugin by key (creating it when the key is new), then posts the bundle and its source in
129
+ * one request. The dashboard is the only validator: a refusal (a manifest rule, a size cap, a runtime-major mismatch, a missing permission)
130
+ * comes back verbatim in {@link PublishResult}, with the step that was refused.
131
+ */
132
+ declare function uploadRevision(transport: PluginTransport, input: PublishInput): Promise<PublishResult>;
133
+
134
+ export { LOCKFILE_NAMES, PLUGINS_SETTINGS_PATH, PLUGIN_DIST_DIR, PLUGIN_SCREENSHOT_FILE, archiveSource, assertNote, buildPlugin, fetchTransport, readBuiltPlugin, runProjectBuild, sourceFiles, uploadRevision, withScreenshot };
135
+ export type { BuiltFile, BuiltPlugin, PluginTransport, PublishInput, PublishResult, PublishedRevision, TransportResult };