@studiometa/forge-core
v0.2.5
Published
Shared business logic for Laravel Forge tools — executors and dependency injection
Maintainers
Readme
@studiometa/forge-core
Shared business logic for Laravel Forge tools — pure executor functions with injectable dependencies. Used internally by @studiometa/forge-mcp.
Architecture
Executors are pure functions with dependency injection via ExecutorContext:
import { listServers, createTestExecutorContext } from "@studiometa/forge-core";
const ctx = createTestExecutorContext({
client: mockClient,
});
const result = await listServers({}, ctx);
console.log(result.text); // "2 server(s): ..."
console.log(result.data); // ForgeServer[]Constants
RESOURCES and ACTIONS are the single source of truth for the entire monorepo:
import { RESOURCES, ACTIONS } from "@studiometa/forge-core";
// RESOURCES: ['servers', 'sites', 'deployments', 'certificates', 'databases',
// 'database-users', 'daemons', 'env', 'nginx', 'firewall-rules', 'ssh-keys',
// 'security-rules', 'redirect-rules', 'nginx-templates', 'monitors', 'recipes',
// 'backups', 'commands', 'scheduled-jobs', 'user', 'batch']
// ACTIONS: ['list', 'get', 'create', 'update', 'delete', 'deploy', 'reboot', 'restart',
// 'activate', 'run', 'resolve', 'help', 'schema', 'context']Executors
Servers
listServers(options, ctx)— List all serversgetServer({ server_id }, ctx)— Get a servercreateServer(data, ctx)— Create a serverdeleteServer({ server_id }, ctx)— Delete a serverrebootServer({ server_id }, ctx)— Reboot a serverresolveServers({ query }, ctx)— Resolve servers by name (partial, case-insensitive); returnsResolveResultwithquery,matches(id+name), andtotal
Sites
listSites({ server_id }, ctx)— List sites on a servergetSite({ server_id, site_id }, ctx)— Get a sitecreateSite({ server_id, ...data }, ctx)— Create a sitedeleteSite({ server_id, site_id }, ctx)— Delete a siteresolveSites({ server_id, query }, ctx)— Resolve sites by domain name (partial, case-insensitive); returnsResolveSiteResultwithquery,matches(id+name), andtotal
Deployments
listDeployments({ server_id, site_id }, ctx)— List deploymentsdeploySite({ server_id, site_id }, ctx)— Trigger deploymentdeploySiteAndWait({ server_id, site_id, timeout_ms?, poll_interval_ms? }, ctx)— Deploy and poll until complete, returnsDeployResultwith status, log, and elapsed timegetDeploymentLog({ server_id, site_id }, ctx)— Get the latest deployment loggetDeploymentOutput({ server_id, site_id, deployment_id }, ctx)— Get outputgetDeploymentScript({ server_id, site_id }, ctx)— Get deploy scriptupdateDeploymentScript({ server_id, site_id, content }, ctx)— Update script
Certificates
listCertificates,getCertificate,createCertificate,deleteCertificate,activateCertificate
Databases
listDatabases,getDatabase,createDatabase,deleteDatabase
Database Users
listDatabaseUsers,getDatabaseUser,createDatabaseUser,deleteDatabaseUser
Daemons
listDaemons,getDaemon,createDaemon,deleteDaemon,restartDaemon
Firewall Rules
listFirewallRules,getFirewallRule,createFirewallRule,deleteFirewallRule
SSH Keys
listSshKeys,getSshKey,createSshKey,deleteSshKey
Security Rules
listSecurityRules,getSecurityRule,createSecurityRule,deleteSecurityRule
Redirect Rules
listRedirectRules,getRedirectRule,createRedirectRule,deleteRedirectRule
Monitors
listMonitors,getMonitor,createMonitor,deleteMonitor
Nginx Templates
listNginxTemplates,getNginxTemplate,createNginxTemplate,updateNginxTemplate,deleteNginxTemplate
Recipes
listRecipes,getRecipe,createRecipe,deleteRecipe,runRecipe
Backups
listBackupConfigs,getBackupConfig,createBackupConfig,deleteBackupConfig
Commands
listCommands,getCommand,createCommand
Scheduled Jobs
listScheduledJobs,getScheduledJob,createScheduledJob,deleteScheduledJob
User
getUser(options, ctx)— Get the authenticated user's profile
Utilities
matchByName(items, query, getName)
Case-insensitive exact and partial name matching — used internally by resolveServers and resolveSites, but exported for reuse:
import { matchByName } from "@studiometa/forge-core";
const result = matchByName(servers, "my-server", (s) => s.name);
// result.exact — items whose name matches exactly (case-insensitive)
// result.partial — items whose name contains the query (includes exact matches)Signature:
function matchByName<T>(items: T[], query: string, getName: (item: T) => string): NameMatch<T>;
interface NameMatch<T> {
exact: T[];
partial: T[];
}Audit Logging
A shared audit logger for tracking write operations across MCP and CLI:
import { createAuditLogger } from "@studiometa/forge-core";
const logger = createAuditLogger("mcp"); // or 'cli'
logger.log({
source: "mcp",
resource: "servers",
action: "reboot",
args: { id: "123" },
status: "success",
});- Logs JSON lines via pino to
~/.config/forge-tools/audit.log - Override path with
FORGE_AUDIT_LOGenvironment variable - Sensitive fields (
apiToken,token,password,secret,key,credentials) are automatically redacted - Silent no-op on failure — never interrupts the actual operation
Utilities
sanitizeArgs(args)— Strip sensitive fields from an args objectgetAuditLogPath()— Resolve the audit log file path
Testing
import { createTestExecutorContext } from "@studiometa/forge-core";
// Creates a context with a proxy client that throws on unmocked methods
const ctx = createTestExecutorContext();
// Override specific methods
const ctx = createTestExecutorContext({
client: {
get: async () => ({ servers: [{ id: 1, name: "test" }] }),
} as never,
});License
MIT © Studio Meta
