Skip to main content

stacks-server

Use when working with the Stacks development or production server - server configuration, server middleware, or server startup. Covers @stacksjs/server and storage/framework/server/.

Informações da origem

Repositório
stacksjs/stacks
Última atividade na origem
30 de setembro de 2026 às 02:26
Idioma detectado do SKILL.md
inglês
Estrelas
631
Forks
20

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
stacks-server
description
Use when working with the Stacks development or production server - server configuration, server middleware, or server startup. Covers @stacksjs/server and storage/framework/server/.
license
MIT
compatibility
Bun >= 1.3.0, TypeScript
allowed-tools
Read Edit Write Bash Grep Glob
# Stacks Server ## Key Paths - Core package: `storage/framework/core/server/src/` (published as `@stacksjs/server`) - Server runtime: `storage/framework/server/` (the actual Bun HTTP server + Docker build) - Server types: `storage/framework/core/types/src/server.ts` - Ports types: `storage/framework/core/types/src/ports.ts` - Package (core): `storage/framework/core/server/package.json` - Package (runtime): `storage/framework/server/package.json` ## Source Files ``` core/server/src/ ├── index.ts # Re-exports: config, controllers/base, imports, maintenance ├── config.ts # config() factory — maps ServerOptions.type to host/port ├── config-production.ts # Minimal env-based config for compiled production binaries ├── imports.ts # Auto-import system: scan models/jobs/controllers, register bun plugin ├── maintenance.ts # Laravel-like maintenance mode (down/up/bypass) └── controllers/ └── base.ts # Base Controller class with json/success/error helpers server/ ├── src/ │ ├── index.ts # Bun.serve() entry point — HTTP + WebSocket + job worker │ └── utils.ts # Docker build helpers (cleanCopy, buildDockerImage, useCustomOrDefaultServerConfig) ├── build.ts # Full build pipeline: bundle server + app, post-process, optionally build Docker ├── dev # Shell script for local/remote Docker dev (mounts volumes) ├── Dockerfile # Multi-stage Bun Docker image (oven/bun:1.3.10) ├── package.json # stacks-server v0.70.23 ├── tsconfig.json # Extends core tsconfig ├── tsconfig.docker.json # Docker-specific tsconfig with path aliases ├── .dockerignore # Excludes Dockerfile, .git, node_modules, etc. └── .gitignore # Excludes app/, config/, dist/, storage/ (build artifacts) ``` ## Server Entry Point (server/src/index.ts) The runtime server uses `Bun.serve()` directly. It handles two modes based on environment variables: ### HTTP Server Mode (default) ```typescript import type { Server, ServerWebSocket } from 'bun' const server = Bun.serve({ port: Number(process.env.PORT) || 3000, development: process.env.APP_ENV?.toLowerCase() !== 'production', async fetch(request: Request, server: Server<any>): Promise<Response | undefined> { // Attempt WebSocket upgrade first if (server.upgrade(request)) return // Delegate to the Stacks router return serverResponse(request) }, websocket: { open(_ws: ServerWebSocket): void {}, message(_ws: ServerWebSocket, _message: string): void {}, close(_ws: ServerWebSocket, _code: number, _reason?: string): void {}, }, }) ``` Key details: - `serverResponse()` is imported from `@stacksjs/router` and handles all route matching, middleware, and response generation - WebSocket upgrade is attempted before HTTP routing - `development` mode is enabled when `APP_ENV` is not `production` or `prod` - SIGINT handler gracefully exits the process ### Queue Worker Mode When `QUEUE_WORKER` env var is set, the same entry point runs a single job instead of starting the HTTP server: ```typescript if (process.env.QUEUE_WORKER) { const jobName = process.env.JOB.replace(/\.ts$/, '').replace(/[^a-zA-Z0-9_-]/g, '') const jobModule = await import(`./app/Jobs/${jobName}`) await retry(() => jobModule.default.handle(), { backoffFactor: Number(process.env.JOB_BACKOFF_FACTOR) || 2, retries: Number(process.env.JOB_RETRIES) || 3, initialDelay: Number(process.env.JOB_INITIAL_DELAY) || 1000, jitter: process.env.JOB_JITTER === 'true', }) process.exit(0) } ``` Environment variables for job execution: - `QUEUE_WORKER` -- enables worker mode (any truthy value) - `JOB` -- job file name (e.g., `SendEmail.ts`), sanitized to prevent path traversal - `JOB_RETRIES` -- retry count (default: 3) - `JOB_BACKOFF_FACTOR` -- exponential backoff multiplier (default: 2) - `JOB_INITIAL_DELAY` -- initial retry delay in ms (default: 1000) - `JOB_JITTER` -- enable jitter on retries (`'true'` to enable) ## Server Config (core/server/src/config.ts) ```typescript function config(options: ServerOptions): { host: string, port: number, open: boolean } ``` Maps a `ServerOptions.type` to a host/port pair using the `ports` config object. Supported types: | Type | Port Source | |---------------|---------------------| | `frontend` | `ports.frontend` | | `backend` | `ports.backend` | | `api` | `ports.api` | | `admin` | `ports.admin` | | `library` | `ports.library` | | `desktop` | `ports.desktop` | | `docs` | `ports.docs` | | `email` | `ports.email` | | `inspect` | `ports.inspect` | | `system-tray` | `ports.systemTray` | | `database` | `ports.database` | All types resolve to `host: 'localhost'`. If no type is provided or it doesn't match, falls back to `host: options.host || 'stacks.localhost'` and `port: options.port || 3000`. ### ServerOptions Type ```typescript interface ServerOptions { type?: 'frontend' | 'backend' | 'api' | 'library' | 'desktop' | 'docs' | 'email' | 'admin' | 'system-tray' | 'database' host?: string port?: number open?: boolean } ``` ### Ports Interface ```typescript interface Ports { frontend: number backend: number // proxies api admin: number library: number desktop: number email: number docs: number inspect: number api: number // the bun server systemTray: number database: number // i.e. DynamoDB local } ``` ## Production Config (core/server/src/config-production.ts) Minimal config for compiled binaries -- no runtime file loading, all env-based: ```typescript const config = { app: { name: process.env.APP_NAME || 'Stacks', env: process.env.APP_ENV || 'production', debug: process.env.APP_DEBUG === 'true' || false, url: process.env.APP_URL || 'https://stacksjs.com', }, server: { port: Number(process.env.PORT) || 3000, host: '0.0.0.0', }, logging: { level: process.env.LOG_LEVEL || 'info', }, } ``` Used by `start.ts` (the production binary entry point) with `SKIP_CONFIG_LOADING=true` to bypass dynamic config imports. ## Production Start (core/server/src/start.ts) Entry point for compiled production binaries. Sequence: 1. Sets `__STACKS_BINARY_MODE__ = true` on `globalThis` (prevents auto-registration in routes) 2. Sets `SKIP_CONFIG_LOADING = 'true'` env var 3. Imports `loadRoutes` and `serve` from `@stacksjs/router` 4. Loads routes from the `app/Routes.ts` registry via `loadRoutes(routeRegistry)` 5. Loads ORM auto-generated routes from `../../orm/routes` (model CRUD endpoints) 6. Calls `serve({ port, host })` to start the Bun HTTP server ```typescript // Production startup flow loadRoutes(routeRegistry) .then(async () => { await import('../../orm/routes') // ORM auto-routes (after manual routes) serve({ port: config.server.port, host: config.server.host }) }) ``` ## Auto-Imports System (core/server/src/imports.ts) ### initiateImports() ```typescript function initiateImports(): void ``` Registers a Bun bundler plugin (`bun-plugin-auto-imports`) that makes models, jobs, controllers, and resource functions available globally without explicit imports. Scan order (user overrides framework overrides defaults): - **Models**: `app/Models/` > `storage/framework/defaults/app/Models/` > `storage/framework/defaults/app/Models/` - **Jobs**: `app/Jobs/` - **Controllers**: `app/Controllers/` > `storage/framework/defaults/app/Controllers/` - **Functions**: `resources/functions/` Outputs: - `.d.ts` file: `storage/framework/types/server-auto-imports.d.ts` - ESLint config: `storage/framework/server-auto-imports.json` - Runtime index files: `storage/framework/auto-imports/` (see below) ### generateAutoImportFiles() ```typescript async function generateAutoImportFiles(): Promise<void> ``` Generates runtime-importable index files under `storage/framework/auto-imports/`: - `functions.ts` -- re-exports from `resources/functions/` - `models.ts` -- re-exports default exports from model definition files as named exports - `jobs.ts` -- re-exports default exports from job definition files - `controllers.ts` -- re-exports default exports from controller definition files - `index.ts` -- combined re-export of all above - `globals.ts` -- script that assigns all exports to `globalThis` ### injectGlobalAutoImports() ```typescript async function injectGlobalAutoImports(): Promise<void> ``` Dynamically imports `storage/framework/auto-imports/index.ts` and assigns all exports to `globalThis`. Call this early in application startup to make models available globally (e.g., `Post.where('title', 'test')` without imports). ### scanDefineModelExports(dir: string): ExportInfo[] Internal helper that scans a directory for `.ts` files (excluding `.d.ts`, `index.ts`, `README*`) and returns file names as export info. Used for models, jobs, and controllers that use `export default defineModel(...)` pattern. ## Base Controller (core/server/src/controllers/base.ts) ```typescript class Controller { protected json(data: any, status?: number): ResponseData // default status: 200 protected success(data: any): ResponseData // alias for json(data, 200) protected created(data: any): ResponseData // json(data, 201) protected noContent(): any // response.noContent() protected error(message: string, status?: number): ResponseData // json({ error }, 500) protected notFound(message?: string): ResponseData // error(msg, 404) protected unauthorized(message?: string): ResponseData // error(msg, 401) protected forbidden(message?: string): ResponseData // error(msg, 403) protected validate(request: Request, rules: Record<string, any>): Promise<void> } ``` Usage: ```typescript import { Controller } from '@stacksjs/server' class UserController extends Controller { async index() { const users = await User.all() return this.success(users) } async store(request: Request) { await this.validate(request, { name: 'required', email: 'required|email' }) const user = await User.create(request.body) return this.created(user) } async show(id: number) { const user = await User.find(id) if (!user) return this.notFound('User not found') return this.success(user) } } ``` ## Maintenance Mode (core/server/src/maintenance.ts) Laravel-like maintenance mode that writes/removes a `storage/framework/down` file. ### Core Functions ```typescript async function down(options?: Partial<MaintenancePayload>): Promise<void> async function up(): Promise<void> async function isDownForMaintenance(): Promise<boolean> async function maintenancePayload(): Promise<MaintenancePayload | null> ``` ### MaintenancePayload ```typescript interface MaintenancePayload { time: number // When maintenance was activated (Date.now()) message?: string // Display message (default: 'We are currently performing maintenance...') retry?: number // Retry-After header value in seconds secret?: string // Bypass token allowed?: string[] // Allowed IP addresses status?: number // HTTP status (default: 503) template?: string // Custom template path redirect?: string // Redirect URL instead of showing maintenance page } ``` ### Bypass Helpers ```typescript function isAllowedIp(ip: string, allowed?: string[]): boolean // Localhost IPs ('127.0.0.1', '::1', 'localhost') are always allowed function hasValidBypassCookie(cookies: Record<string, string>, secret: string): boolean // Checks for cookie: stacks_maintenance_bypass=<secret> function isSecretPath(path: string, secret: string): boolean // Matches /<secret> or /<secret>/... function bypassCookieValue(secret: string): string // Returns: 'stacks_maintenance_bypass=<secret>; Path=/; HttpOnly; SameSite=Lax' ``` ### Response Helpers ```typescript
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub