@meridianjs/framework 0.1.11 → 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 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/dist/index.d.ts CHANGED
@@ -173,8 +173,20 @@ declare class ConsoleLogger implements ILogger {
173
173
 
174
174
  declare function createServer(container: MeridianContainer, config: MeridianConfig): Express;
175
175
 
176
- /** Strict limiter for auth endpoints: 10 requests per minute per IP. */
176
+ /**
177
+ * Strict limiter for password-based auth endpoints (login, register).
178
+ * 10 requests per minute per IP — guards against brute-force attacks.
179
+ */
177
180
  declare const authRateLimit: express_rate_limit.RateLimitRequestHandler;
181
+ /**
182
+ * Loose limiter for OAuth redirect/callback endpoints.
183
+ * 30 requests per minute per IP — a complete OAuth flow (initiate → callback →
184
+ * exchange) consumes 3 requests, so 30/min allows ~10 flows per minute.
185
+ * OAuth routes are not brute-forceable at the application level because they
186
+ * require a real interaction with the external identity provider and a
187
+ * cryptographic CSRF nonce.
188
+ */
189
+ declare const oauthRateLimit: express_rate_limit.RateLimitRequestHandler;
178
190
  /** General API limiter: 300 requests per minute per IP. */
179
191
  declare const apiRateLimit: express_rate_limit.RateLimitRequestHandler;
180
192
 
@@ -211,4 +223,4 @@ declare class SseManager {
211
223
  /** Singleton shared across all routes and subscribers. */
212
224
  declare const sseManager: SseManager;
213
225
 
214
- export { type BootstrapOptions, ConsoleLogger, type MeridianApp, type MiddlewareRoute, type MiddlewaresConfig, SseManager, apiRateLimit, authRateLimit, bootstrap, createMeridianContainer, createServer, defineConfig, defineMiddlewares, loadConfig, loadJobs, loadLinks, loadModules, loadPlugins, loadRoutes, loadSubscribers, resolveModuleDefinition, sseManager, validate };
226
+ export { type BootstrapOptions, ConsoleLogger, type MeridianApp, type MiddlewareRoute, type MiddlewaresConfig, SseManager, apiRateLimit, authRateLimit, bootstrap, createMeridianContainer, createServer, defineConfig, defineMiddlewares, loadConfig, loadJobs, loadLinks, loadModules, loadPlugins, loadRoutes, loadSubscribers, oauthRateLimit, resolveModuleDefinition, sseManager, validate };
package/dist/index.js CHANGED
@@ -730,6 +730,11 @@ var authRateLimit = rateLimit({
730
730
  max: 10,
731
731
  ...sharedOpts
732
732
  });
733
+ var oauthRateLimit = rateLimit({
734
+ windowMs: 6e4,
735
+ max: 30,
736
+ ...sharedOpts
737
+ });
733
738
  var apiRateLimit = rateLimit({
734
739
  windowMs: 6e4,
735
740
  max: 300,
@@ -820,6 +825,7 @@ export {
820
825
  loadPlugins,
821
826
  loadRoutes,
822
827
  loadSubscribers,
828
+ oauthRateLimit,
823
829
  resolveModuleDefinition,
824
830
  sseManager,
825
831
  validate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meridianjs/framework",
3
- "version": "0.1.11",
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",