@meridianjs/framework 0.1.12 → 0.1.13
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.
- package/README.md +154 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# @meridianjs/framework
|
|
2
|
+
|
|
3
|
+
The MeridianJS application runtime. Handles bootstrapping, the Awilix DI container, Express server setup, file-based route / subscriber / job / link loading, plugin registration, rate limiting, input validation, and SSE.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @meridianjs/framework
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// src/main.ts
|
|
15
|
+
import { bootstrap } from "@meridianjs/framework"
|
|
16
|
+
import path from "node:path"
|
|
17
|
+
import { fileURLToPath } from "node:url"
|
|
18
|
+
|
|
19
|
+
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
20
|
+
const app = await bootstrap({ rootDir })
|
|
21
|
+
await app.start()
|
|
22
|
+
|
|
23
|
+
process.on("SIGTERM", async () => { await app.stop(); process.exit(0) })
|
|
24
|
+
process.on("SIGINT", async () => { await app.stop(); process.exit(0) })
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`bootstrap()` reads `meridian.config.ts` from `rootDir`, loads all modules and plugins, registers file-based routes and subscribers, and returns a `MeridianApp` handle.
|
|
28
|
+
|
|
29
|
+
## Configuration
|
|
30
|
+
|
|
31
|
+
Define your config in `meridian.config.ts` at the project root:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { defineConfig } from "@meridianjs/framework"
|
|
35
|
+
import dotenv from "dotenv"
|
|
36
|
+
dotenv.config()
|
|
37
|
+
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
projectConfig: {
|
|
40
|
+
databaseUrl: process.env.DATABASE_URL!,
|
|
41
|
+
jwtSecret: process.env.JWT_SECRET!,
|
|
42
|
+
httpPort: Number(process.env.PORT) || 9000,
|
|
43
|
+
cors: {
|
|
44
|
+
origin: process.env.CORS_ORIGIN ?? "http://localhost:5174",
|
|
45
|
+
credentials: true,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
modules: [
|
|
49
|
+
{ resolve: "@meridianjs/event-bus-local" },
|
|
50
|
+
{ resolve: "@meridianjs/job-queue-local" },
|
|
51
|
+
],
|
|
52
|
+
plugins: [
|
|
53
|
+
{ resolve: "@meridianjs/meridian" },
|
|
54
|
+
],
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## File-based Routes
|
|
59
|
+
|
|
60
|
+
Create route files under `src/api/` and export named HTTP method handlers:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
src/api/admin/projects/route.ts → GET /admin/projects, POST /admin/projects
|
|
64
|
+
src/api/admin/projects/[id]/route.ts → GET /admin/projects/:id, PUT, DELETE
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// src/api/admin/projects/route.ts
|
|
69
|
+
import type { Request, Response } from "express"
|
|
70
|
+
|
|
71
|
+
export const GET = async (req: Request, res: Response) => {
|
|
72
|
+
const svc = req.scope.resolve("projectModuleService") as any
|
|
73
|
+
const projects = await svc.listProjects()
|
|
74
|
+
res.json({ projects })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const POST = async (req: Request, res: Response) => {
|
|
78
|
+
const svc = req.scope.resolve("projectModuleService") as any
|
|
79
|
+
const project = await svc.createProject(req.body)
|
|
80
|
+
res.status(201).json({ project })
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Middleware
|
|
85
|
+
|
|
86
|
+
Define route-level middleware in `src/api/middlewares.ts`:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { authenticateJWT } from "@meridianjs/auth"
|
|
90
|
+
import { apiRateLimit, authRateLimit } from "@meridianjs/framework"
|
|
91
|
+
|
|
92
|
+
export default {
|
|
93
|
+
routes: [
|
|
94
|
+
{ matcher: "/auth", middlewares: [authRateLimit] },
|
|
95
|
+
{ matcher: "/admin", middlewares: [apiRateLimit, authenticateJWT] },
|
|
96
|
+
],
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Rate Limiting
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { authRateLimit, oauthRateLimit, apiRateLimit } from "@meridianjs/framework"
|
|
104
|
+
|
|
105
|
+
// authRateLimit — 20 req / 15 min (for /auth endpoints)
|
|
106
|
+
// oauthRateLimit — 30 req / 15 min (for OAuth flows)
|
|
107
|
+
// apiRateLimit — 200 req / 15 min (for /admin endpoints)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Input Validation
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { validate } from "@meridianjs/framework"
|
|
114
|
+
import { z } from "zod"
|
|
115
|
+
|
|
116
|
+
const schema = z.object({ name: z.string().min(1), color: z.string() })
|
|
117
|
+
|
|
118
|
+
export const POST = async (req: Request, res: Response) => {
|
|
119
|
+
const body = validate(req.body, schema) // throws 400 with field errors on failure
|
|
120
|
+
// body is typed as z.infer<typeof schema>
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## SSE — Server-Sent Events
|
|
125
|
+
|
|
126
|
+
Push real-time updates to connected dashboard clients:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { sseManager } from "@meridianjs/framework"
|
|
130
|
+
|
|
131
|
+
// In a subscriber or route handler:
|
|
132
|
+
sseManager.broadcast({ type: "issue.updated", payload: { id: issue.id } })
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Clients connect via `GET /admin/events`. The dashboard uses this to invalidate TanStack Query caches without polling.
|
|
136
|
+
|
|
137
|
+
## Exports
|
|
138
|
+
|
|
139
|
+
| Export | Description |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `bootstrap(options)` | Boot the application, return `MeridianApp` |
|
|
142
|
+
| `defineConfig(config)` | Type-safe config helper |
|
|
143
|
+
| `defineMiddlewares(config)` | Type-safe middleware config helper |
|
|
144
|
+
| `createMeridianContainer()` | Create a raw Awilix container |
|
|
145
|
+
| `ConsoleLogger` | Default logger implementation |
|
|
146
|
+
| `validate(data, schema)` | Zod validation with auto 400 response |
|
|
147
|
+
| `authRateLimit` | Rate limiter for auth routes |
|
|
148
|
+
| `apiRateLimit` | Rate limiter for API routes |
|
|
149
|
+
| `sseManager` | SSE broadcast singleton |
|
|
150
|
+
| `loadRoutes`, `loadModules`, `loadSubscribers`, `loadJobs`, `loadLinks`, `loadPlugins` | Low-level loaders (plugin authors) |
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT
|
package/package.json
CHANGED