Type-safe plugin builder utilities for DockStat plugins
npm install @dockstat/plugin-builder> Type-safe plugin builder utilities for creating DockStat plugins with full TypeScript support.
@dockstat/plugin-builder provides a lightweight, type-safe API for building DockStat plugins. It includes:
- Type-Safe Plugin Definition: Full TypeScript inference for plugin configuration
- Builder Pattern: Fluent API for constructing plugins step-by-step
- Helper Functions: Utilities for creating actions, routes, events, and frontend config
- Zero Runtime Dependencies: Types are bundled - no need to install internal packages
``bashnpm
npm install @dockstat/plugin-builder
Quick Start
`typescript
import { definePlugin, createActions } from "@dockstat/plugin-builder";// Define your table schema type
interface MyPluginData {
id: number;
name: string;
config: Record;
}
// Create type-safe actions
const actions = createActions({
getData: async ({ table, logger }) => {
logger.info("Fetching data");
return table?.select(["*"]).all() ?? [];
},
saveData: async ({ table, body, logger }) => {
logger.info("Saving data");
const result = table?.insert(body as MyPluginData);
return { success: true, id: result?.lastInsertRowid };
},
});
// Define the complete plugin
export default definePlugin({
name: "my-plugin",
description: "A sample DockStat plugin",
version: "1.0.0",
repository: "https://github.com/user/my-plugin",
repoType: "github",
manifest: "https://github.com/user/my-plugin/manifest.json",
author: { name: "Developer", email: "dev@example.com" },
tags: ["sample", "demo"],
config: {
table: {
name: "my_plugin_data",
columns: {
id: { type: "INTEGER", primaryKey: true, autoincrement: true },
name: { type: "TEXT", notNull: true },
config: { type: "JSON" },
},
parser: { JSON: ["config"] },
},
actions,
apiRoutes: {
"/data": { method: "GET", actions: ["getData"] },
"/save": { method: "POST", actions: ["saveData"] },
},
},
events: {
onContainerStart: async (container, { logger }) => {
logger.info(
Container started: ${container.id});
},
},
});
`API Reference
$3
The primary function for defining a complete plugin with full type safety.
`typescript
import { definePlugin } from "@dockstat/plugin-builder";export default definePlugin({
name: "example-plugin",
description: "An example plugin",
version: "1.0.0",
repository: "https://github.com/user/example-plugin",
repoType: "github",
manifest: "https://github.com/user/example-plugin/manifest.json",
author: { name: "Developer" },
config: {
// ... configuration
},
});
`$3
Create type-safe action handlers for your plugin.
`typescript
import { createActions } from "@dockstat/plugin-builder";interface MyData {
id: number;
value: string;
}
const actions = createActions({
fetchAll: async ({ table, logger }) => {
logger.debug("Fetching all records");
return table?.select(["*"]).all() ?? [];
},
create: async ({ table, body, logger }) => {
logger.info("Creating record");
return table?.insert(body as MyData);
},
});
`$3
Create a single type-safe action handler with explicit body and return types.
`typescript
import { createAction } from "@dockstat/plugin-builder";const myAction = createAction(
async ({ table, body, logger }) => {
logger.info(
Processing: ${body?.name});
return { success: true };
}
);
`$3
Create a type-safe API route configuration.
`typescript
import { createRoute } from "@dockstat/plugin-builder";const route = createRoute({
method: "POST",
actions: ["fetchAll", "create"],
});
`$3
Create a type-safe routes object.
`typescript
import { createApiRoutes } from "@dockstat/plugin-builder";const routes = createApiRoutes({
"/list": { method: "GET", actions: ["fetchAll"] },
"/create": { method: "POST", actions: ["create"] },
});
`$3
Create a type-safe table configuration.
`typescript
import { createTable } from "@dockstat/plugin-builder";const table = createTable({
name: "my_data",
columns: {
id: { type: "INTEGER", primaryKey: true, autoincrement: true },
value: { type: "TEXT", notNull: true },
},
parser: { JSON: [] },
});
`$3
Create type-safe event handlers.
`typescript
import { createEvents } from "@dockstat/plugin-builder";const events = createEvents({
onContainerStart: async (container, { logger, table }) => {
logger.info(
Container ${container.id} started);
},
onContainerStop: async (container, { logger }) => {
logger.info(Container ${container.id} stopped);
},
});
`$3
`typescript
import {
createFrontendConfig,
createFrontendRoute,
createFrontendLoader,
createFrontendAction,
} from "@dockstat/plugin-builder";const frontend = createFrontendConfig({
routes: [
createFrontendRoute({
path: "/dashboard",
template: { type: "container", children: [] },
meta: { title: "Dashboard", showInNav: true },
loaders: [
createFrontendLoader({
id: "data-loader",
apiRoute: "/data",
stateKey: "data",
}),
],
actions: [
createFrontendAction({
id: "refresh",
type: "reload",
loaderIds: ["data-loader"],
}),
],
}),
],
});
`$3
Fluent builder API for constructing plugins step-by-step.
`typescript
import { pluginBuilder } from "@dockstat/plugin-builder";const plugin = pluginBuilder()
.name("my-plugin")
.description("A plugin built with the fluent API")
.version("1.0.0")
.repository("https://github.com/user/my-plugin", "github")
.manifest("https://github.com/user/my-plugin/manifest.json")
.author({ name: "Developer", email: "dev@example.com" })
.tags(["example", "demo"])
.table({
name: "my_data",
columns: { id: { type: "INTEGER" }, value: { type: "TEXT" } },
parser: { JSON: [] },
})
.actions(actions)
.apiRoutes({
"/data": { method: "GET", actions: ["fetchAll"] },
})
.events({
onContainerStart: async (container, { logger }) => {
logger.info("Container started");
},
})
.build();
export default plugin;
`Type Exports
The package exports all necessary types for plugin development:
`typescript
import type {
// Core plugin types
PluginDefinition,
PluginMeta,
PluginAuthor,
PluginConfig,
PluginActions,
PluginActionContext,
PluginRoute,
TableConfig,
ActionHandler,
BuiltPlugin, // Frontend types
PluginFrontendConfig,
PluginFrontendRoute,
FrontendAction,
FrontendLoader,
// Event types
EVENTS,
// Database types
ColumnDefinition,
// Utility types
InferTableSchema,
ActionNames,
ValidateRouteActions,
} from "@dockstat/plugin-builder";
`Plugin Structure
A DockStat plugin consists of:
$3
-
name - Unique plugin identifier
- description - Short description
- version - Semver version string
- repository - Repository URL
- repoType - One of: "github", "gitlab", "local", "default"
- manifest - URL to the plugin manifest
- author - Author information (name, email, website)
- tags - Array of tags for categorization$3
-
table - Database table configuration (optional)
- actions - Action handlers for API routes
- apiRoutes - API endpoint definitions
- frontend - Frontend UI configuration (optional)$3
Docker and server lifecycle event handlers:
-
onContainerStart
- onContainerStop
- onContainerRestart
- onImagePull
- onImageRemove
- onServerBoot
- And more...Action Context
Actions receive a context object with:
`typescript
interface ActionContext {
table: QueryBuilder | null; // Plugin's database table
body: K | undefined; // Request body (POST/PUT)
logger: {
error: (msg: string) => void;
warn: (msg: string) => void;
info: (msg: string) => void;
debug: (msg: string) => void;
};
previousAction: unknown; // Result from previous action in chain
}
``- DockStat - The main DockStat project
- @dockstat/plugin-handler - Plugin runtime handler
MIT - Part of the DockStat project.