Package Exports
- @mandujs/core
- @mandujs/core/a11y
- @mandujs/core/agent
- @mandujs/core/auth
- @mandujs/core/auth/login
- @mandujs/core/auth/password
- @mandujs/core/auth/reset
- @mandujs/core/auth/verification
- @mandujs/core/bundler
- @mandujs/core/bundler/analyzer
- @mandujs/core/bundler/budget
- @mandujs/core/bundler/generate-static-params
- @mandujs/core/bundler/hmr-types
- @mandujs/core/bundler/manifest-schema
- @mandujs/core/bundler/plugins
- @mandujs/core/bundler/plugins/block-generated-imports
- @mandujs/core/bundler/prerender
- @mandujs/core/bundler/safe-build
- @mandujs/core/bundler/scenario-matrix
- @mandujs/core/bundler/types
- @mandujs/core/bundler/vendor-cache-types
- @mandujs/core/client
- @mandujs/core/client/hydrate
- @mandujs/core/client/rpc
- @mandujs/core/components/Image
- @mandujs/core/config
- @mandujs/core/config/mandu
- @mandujs/core/config/validate
- @mandujs/core/content
- @mandujs/core/content/collection
- @mandujs/core/content/llms-txt
- @mandujs/core/content/prebuild
- @mandujs/core/content/schema
- @mandujs/core/content/sidebar
- @mandujs/core/content/slug
- @mandujs/core/contract
- @mandujs/core/contract/rpc
- @mandujs/core/db
- @mandujs/core/db/migrations
- @mandujs/core/db/migrations/history-table
- @mandujs/core/db/migrations/runner
- @mandujs/core/deploy
- @mandujs/core/design
- @mandujs/core/desktop
- @mandujs/core/desktop/worker
- @mandujs/core/dev-error-overlay
- @mandujs/core/diagnose
- @mandujs/core/email
- @mandujs/core/error
- @mandujs/core/filling
- @mandujs/core/filling/cookie-codec
- @mandujs/core/filling/session-sqlite
- @mandujs/core/guard
- @mandujs/core/guard/define-rule
- @mandujs/core/guard/design-inline-class
- @mandujs/core/guard/rule-presets
- @mandujs/core/guard/tsgolint-bridge
- @mandujs/core/i18n
- @mandujs/core/id
- @mandujs/core/kitchen
- @mandujs/core/logging
- @mandujs/core/middleware
- @mandujs/core/middleware/bridge
- @mandujs/core/middleware/compose
- @mandujs/core/middleware/csrf
- @mandujs/core/middleware/define
- @mandujs/core/middleware/oauth
- @mandujs/core/middleware/rate-limit
- @mandujs/core/middleware/secure
- @mandujs/core/middleware/session
- @mandujs/core/observability
- @mandujs/core/openapi/generator
- @mandujs/core/perf
- @mandujs/core/perf/hmr-markers
- @mandujs/core/perf/user-marks
- @mandujs/core/plugins
- @mandujs/core/plugins/define
- @mandujs/core/plugins/runner
- @mandujs/core/resource
- @mandujs/core/resource/ddl/diff
- @mandujs/core/resource/ddl/emit
- @mandujs/core/resource/ddl/snapshot
- @mandujs/core/resource/ddl/type-map
- @mandujs/core/resource/ddl/types
- @mandujs/core/resource/generator-repo
- @mandujs/core/resource/parser
- @mandujs/core/resource/schema
- @mandujs/core/router
- @mandujs/core/routes
- @mandujs/core/runtime
- @mandujs/core/runtime/cache
- @mandujs/core/runtime/fast-refresh-types
- @mandujs/core/runtime/router
- @mandujs/core/runtime/server
- @mandujs/core/scheduler
- @mandujs/core/storage/s3
- @mandujs/core/testing
- @mandujs/core/testing/db
- @mandujs/core/testing/mocks
- @mandujs/core/testing/reporter
- @mandujs/core/testing/server
- @mandujs/core/testing/session
- @mandujs/core/testing/snapshot
Readme
@mandujs/core
Mandu Framework Core
Runtime, FS Routes, Guard, Bundler, Contract, Filling
English | 한국어
Installation
bun add @mandujs/coreTypically used through
@mandujs/cli. Direct usage is for advanced use cases.
Quick Start
Basic API Handler (Filling)
import { Mandu } from "@mandujs/core";
export default Mandu.filling()
.guard((ctx) => {
if (!ctx.get("user")) return ctx.unauthorized("Login required");
})
.get(async (ctx) => {
const users = await db.users.findMany();
return ctx.ok({ data: users });
})
.post(async (ctx) => {
const body = await ctx.body<{ name: string }>();
const user = await db.users.create({ data: body });
return ctx.created({ data: user });
});Type-Safe Contract
import { Mandu } from "@mandujs/core";
import { z } from "zod";
const userContract = Mandu.contract({
request: {
GET: { query: z.object({ id: z.string() }) },
POST: { body: z.object({ name: z.string() }) }
},
response: {
200: z.object({ data: z.any() }),
400: z.object({ error: z.string() })
}
});
const handlers = Mandu.handler(userContract, {
GET: (ctx) => ({ data: fetchUser(ctx.query.id) }),
POST: (ctx) => ({ data: createUser(ctx.body) })
});Module Overview
@mandujs/core
├── router/ # FS Routes - file-system based routing
├── guard/ # Mandu Guard - architecture enforcement
│ ├── healing # Self-Healing Guard with auto-fix
│ ├── decision-memory # ADR storage (RFC-001)
│ ├── semantic-slots # Constraint validation (RFC-001)
│ └── negotiation # AI-Framework dialog (RFC-001)
├── runtime/ # Server, SSR, streaming
├── filling/ # Handler chain API (Mandu.filling())
├── contract/ # Type-safe API contracts
├── content/ # Content Layer - build-time content loading 🆕
│ └── loaders # file(), glob(), api() loaders
├── bundler/ # Client bundling, HMR
├── client/ # Island hydration, client router
├── brain/ # Doctor, Watcher, Architecture analyzer
├── change/ # Transaction & history
└── spec/ # Manifest schema & validationFS Routes
File-system based routing system.
import { scanRoutes, generateManifest, watchFSRoutes } from "@mandujs/core/router";
// Scan routes from app/ directory
const result = await scanRoutes("/path/to/project");
console.log(result.routes);
// Generate manifest
const { manifest } = await generateManifest("/path/to/project", {
outputPath: ".mandu/manifest.json"
});
// Watch for changes
const watcher = await watchFSRoutes("/path/to/project", {
onChange: (result) => console.log("Routes updated!", result.routes.length)
});Route Patterns
import { pathToPattern, parseSegments } from "@mandujs/core/router";
// Convert path to URL pattern
pathToPattern("users/[id]/posts"); // → "/users/:id/posts"
pathToPattern("docs/[...slug]"); // → "/docs/:slug*"
pathToPattern("(auth)/login"); // → "/login" (group ignored)
// Parse segments
parseSegments("[id]"); // → [{ type: "dynamic", name: "id" }]
parseSegments("[...slug]"); // → [{ type: "catch-all", name: "slug" }]Mandu Guard
Real-time architecture enforcement with preset support.
import {
createGuardWatcher,
checkDirectory,
getPreset,
listPresets
} from "@mandujs/core/guard";
// One-time check
const report = await checkDirectory(
{ preset: "mandu" },
process.cwd()
);
console.log(`Violations: ${report.totalViolations}`);
// Real-time watching
const watcher = createGuardWatcher({
config: { preset: "mandu", srcDir: "src" },
rootDir: process.cwd(),
onViolation: (v) => console.log(`${v.filePath}: ${v.ruleDescription}`),
});
watcher.start();
// List available presets
listPresets().forEach(p => console.log(p.name, p.description));Presets (6)
| Preset | Layers | Use Case |
|---|---|---|
mandu |
client/, shared/(contracts, types, utils/, schema, env), server/* | Fullstack (default) |
fsd |
app, pages, widgets, features, entities, shared | Frontend |
clean |
api, application, domain, infra, shared | Backend |
hexagonal |
adapters, ports, application, domain | DDD |
atomic |
pages, templates, organisms, molecules, atoms | UI |
cqrs |
commands, queries, events, dto, application, domain | Event-sourced apps |
AST-based Analysis
import { extractImportsAST, analyzeModuleAST } from "@mandujs/core/guard";
// Extract imports with AST (more accurate than regex)
const imports = extractImportsAST(code);
// → [{ path: "./utils", type: "static", line: 1, namedImports: ["foo"] }]
// Full module analysis
const analysis = analyzeModuleAST(code, "src/features/user/api.ts");Statistics & Trends
import {
createScanRecord,
addScanRecord,
analyzeTrend,
generateGuardMarkdownReport
} from "@mandujs/core/guard";
// Save scan for trend analysis
const record = createScanRecord(report, "mandu");
await addScanRecord(rootDir, record);
// Analyze improvement trend
const trend = analyzeTrend(records, 7); // 7 days
console.log(trend.trend); // "improving" | "stable" | "degrading"
// Generate reports
const markdown = generateGuardMarkdownReport(report, trend);Self-Healing Guard (RFC-001) 🆕
import { checkWithHealing, healAll, explainRule } from "@mandujs/core/guard";
// Detect violations with fix suggestions
const result = await checkWithHealing({ preset: "mandu" }, process.cwd());
// Auto-fix all fixable violations
if (result.items.length > 0) {
const healResult = await healAll(result);
console.log(`Fixed: ${healResult.fixed}, Failed: ${healResult.failed}`);
}
// Explain any rule
const explanation = explainRule("layer-dependency");
console.log(explanation.description, explanation.examples);Decision Memory (RFC-001) 🆕
import {
searchDecisions,
saveDecision,
checkConsistency,
getCompactArchitecture
} from "@mandujs/core/guard";
// Search past decisions
const results = await searchDecisions(rootDir, ["auth", "jwt"]);
// Save new decision (ADR)
await saveDecision(rootDir, {
id: "ADR-002",
title: "Use PostgreSQL",
status: "accepted",
context: "Need relational database",
decision: "Use PostgreSQL with Drizzle ORM",
consequences: ["Need to manage migrations"],
tags: ["database", "orm"]
});
// Check implementation consistency
const consistency = await checkConsistency(rootDir);Architecture Negotiation (RFC-001) 🆕
import { negotiate, generateScaffold } from "@mandujs/core/guard";
// AI negotiates with framework before implementation
const plan = await negotiate({
intent: "Add user authentication",
requirements: ["JWT based", "Refresh tokens"],
constraints: ["Use existing User model"]
}, projectRoot);
if (plan.approved) {
// Generate scaffold files
await generateScaffold(plan.structure, projectRoot);
}Filling API
Handler chain for business logic.
import { Mandu } from "@mandujs/core";
export default Mandu.filling()
// Lifecycle hooks
.onRequest((ctx) => {
ctx.set("requestId", crypto.randomUUID());
})
// Guard (return Response to block)
.guard((ctx) => {
if (!ctx.get("user")) return ctx.unauthorized("Login required");
})
// Handlers
.get(async (ctx) => {
return ctx.ok({ users: await fetchUsers() });
})
.post(async (ctx) => {
const body = await ctx.body();
return ctx.created({ user: await createUser(body) });
})
// After response
.afterResponse((ctx) => {
console.log("Request completed:", ctx.get("requestId"));
});Middleware (Compose-style)
export default Mandu.filling()
.middleware(async (ctx, next) => {
console.log("before");
await next();
console.log("after");
})
.get((ctx) => ctx.ok({ ok: true }));Context API
| Method | Description |
|---|---|
ctx.ok(data) |
200 OK |
ctx.created(data) |
201 Created |
ctx.noContent() |
204 No Content |
ctx.error(message) |
400 Bad Request |
ctx.unauthorized(message) |
401 Unauthorized |
ctx.forbidden(message) |
403 Forbidden |
ctx.notFound(message) |
404 Not Found |
ctx.fail(message) |
500 Internal Server Error |
ctx.body<T>() |
Parse request body |
ctx.params |
Route parameters |
ctx.query |
Query parameters |
ctx.set(key, value) |
Store in context |
ctx.get<T>(key) |
Retrieve from context |
Contract API
Type-safe API contracts with Zod.
import { Mandu } from "@mandujs/core";
import { z } from "zod";
// Define contract
const userContract = Mandu.contract({
request: {
GET: { query: z.object({ id: z.string() }) },
POST: { body: z.object({ name: z.string() }) }
},
response: {
200: z.object({ data: z.any() }),
400: z.object({ error: z.string() })
}
});
// Create typed handlers
const handlers = Mandu.handler(userContract, {
GET: (ctx) => ({ data: fetchUser(ctx.query.id) }),
POST: (ctx) => ({ data: createUser(ctx.body) })
});
// Type-safe client
const client = Mandu.client(userContract, { baseUrl: "/api/users" });
const result = await client.GET({ query: { id: "123" } });Client-safe Contract
Limit schemas exposed to client-side usage (forms/UI validation):
const clientContract = Mandu.clientContract(userContract, {
request: {
POST: { body: true },
},
response: [201],
includeErrors: true,
});
const client = Mandu.client(clientContract, { baseUrl: "/api/users" });Runtime
Server and SSR.
import { startServer, registerApiHandler, registerPageLoader } from "@mandujs/core";
// Register handlers
registerApiHandler("getUsers", async (req) => ({ users: [] }));
registerPageLoader("home", () => import("./pages/Home"));
// Start server
const server = startServer(manifest, { port: 3000 });Streaming SSR
import { renderToStream } from "@mandujs/core";
const stream = await renderToStream(<App />, {
bootstrapScripts: ["/client.js"],
onError: (err) => console.error(err)
});Client (Islands & Router)
Island Hydration
import { createIsland, partial } from "@mandujs/core/client";
// Define island
const CounterIsland = createIsland({
name: "counter",
component: Counter,
priority: "visible"
});
// Partial (smaller than island)
const ButtonPartial = partial("submit-btn", SubmitButton);Client Router
import { useRouter, useParams, Link, NavLink } from "@mandujs/core/client";
function Navigation() {
const router = useRouter();
const params = useParams();
return (
<nav>
<NavLink href="/users" activeClass="active">Users</NavLink>
<button onClick={() => router.push("/settings")}>Settings</button>
</nav>
);
}Content Layer 🆕
Astro-inspired build-time content loading system.
// content.config.ts
import { defineContentConfig, glob, file, api } from "@mandujs/core/content";
import { z } from "zod";
const postSchema = z.object({
title: z.string(),
date: z.coerce.date(),
tags: z.array(z.string()).default([]),
});
export default defineContentConfig({
collections: {
// Markdown files with frontmatter
posts: {
loader: glob({ pattern: "content/posts/**/*.md" }),
schema: postSchema,
},
// Single JSON/YAML file
settings: {
loader: file({ path: "data/settings.json" }),
},
// External API
products: {
loader: api({
url: "https://api.example.com/products",
headers: () => ({ Authorization: `Bearer ${process.env.API_KEY}` }),
cacheTTL: 3600,
}),
},
},
});Querying Content
import { getCollection, getEntry } from "@mandujs/core/content";
// Get all entries
const posts = await getCollection("posts");
posts.forEach(post => {
console.log(post.id, post.data.title);
});
// Get single entry
const post = await getEntry("posts", "hello-world");
console.log(post?.data.title, post?.body);Built-in Loaders
| Loader | Description | Example |
|---|---|---|
file() |
Single file (JSON, YAML, TOML) | file({ path: "data/config.json" }) |
glob() |
Pattern matching (Markdown, JSON) | glob({ pattern: "content/**/*.md" }) |
api() |
HTTP API with caching | api({ url: "https://...", cacheTTL: 3600 }) |
Features
- Digest-based caching: Only re-parse changed files
- Zod validation: Type-safe content with schema validation
- Frontmatter support: YAML frontmatter in Markdown files
- Dev mode watching: Auto-reload on content changes
- Incremental updates: Efficient builds with change detection
Brain (AI Assistant)
Doctor and architecture analyzer.
import {
initializeBrain,
getBrain,
analyzeViolations,
initializeArchitectureAnalyzer
} from "@mandujs/core";
// Initialize
await initializeBrain();
const brain = getBrain();
// Analyze violations with suggestions
const analysis = await analyzeViolations(violations, { useLLM: true });
console.log(analysis.patches); // Suggested fixes
// Architecture analyzer
const analyzer = initializeArchitectureAnalyzer(rootDir);
const locationResult = await analyzer.checkLocation({ path: "src/features/user.ts" });
const importResult = await analyzer.checkImports({
sourceFile: "src/features/user.ts",
imports: ["../entities/product"]
});Bundler
Client bundling with HMR.
import { buildClientBundle, createDevBundler } from "@mandujs/core/bundler";
// Production build
const result = await buildClientBundle(manifest, {
outDir: ".mandu/client",
minify: true,
sourcemap: true
});
// Development with HMR
const devBundler = await createDevBundler(manifest, {
rootDir: process.cwd(),
isDev: true
});Transaction API
Atomic changes with rollback.
import { beginChange, commitChange, rollbackChange } from "@mandujs/core";
// Start transaction
const { changeId, snapshotId } = await beginChange(rootDir, "Add user API");
// Make changes...
// Commit or rollback
await commitChange(rootDir);
// or
await rollbackChange(rootDir);Types
import type {
// Spec
RoutesManifest,
RouteSpec,
// Guard
GuardPreset,
GuardConfig,
Violation,
ViolationReport,
// Router
ScanResult,
FSRouteConfig,
// Contract
ContractDefinition,
ContractHandlers,
// Filling
ManduContext,
// Content Layer
DataEntry,
ContentConfig,
CollectionConfig,
Loader,
LoaderContext,
} from "@mandujs/core";Requirements
- Bun >= 1.0.0
- React >= 19.0.0
- Zod >= 3.0.0
Related Packages
- @mandujs/cli - CLI tool
- @mandujs/mcp - MCP server for AI agents
License
MIT