@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.
Files changed (2) hide show
  1. package/README.md +154 -0
  2. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meridianjs/framework",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "Core Meridian framework: bootstrap, DI container, module/route/subscriber/job loaders",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",