@synchjs/ewb 1.0.0 → 1.0.2

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 CHANGED
@@ -1,17 +1,17 @@
1
1
  # @synchjs/ewb
2
2
 
3
- A robust, decorator-based web server framework built on top of **Express** and optimized for **Bun**. It provides a structured way to build scalable APIs with built-in support for **OpenAPI (Swagger)**, **Validation**, **Authentication**, and **Frontend Asset Serving** (with Tailwind CSS support).
3
+ A robust, decorator-based web server framework built on top of **Express** and optimized for **Bun**. It provides a structured way to build scalable APIs with built-in support for **OpenAPI (Swagger)**, **Validation**, **Custom User Management**, and **Frontend Asset Serving** with **HMR (Hot Module Replacement)**.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - 🏗 **Decorator-based Routing**: Define controllers and routes using concise decorators (`@Controller`, `@Get`, `@Post`).
8
- - 🔒 **Built-in Authentication**: Easy-to-use Bearer Token authentication (`@BearerAuth`).
8
+ - 👥 **Flexible User Management**: Pluggable `UserHandler` for custom Auth/Identity logic (JWT, Session, Database, etc.).
9
9
  - 📜 **Auto-generated Swagger Docs**: Your API documentation is generated automatically from your code.
10
- - ✅ **Request Validation**: Schema-based validation using AJV.
11
- - 🎨 **Frontend Serving**: Serve HTML/CSS/JS assets from memory, with built-in **Tailwind CSS** processing via Bun plugins.
12
- - 🧩 **Dependency Injection**: Support for IoC containers.
13
- - 🚀 **Bun Optimized**: Leverages Bun's build capabilities for static assets.
14
- - 🖥 **TUI-style Logs**: Clean and informative startup messages.
10
+ - ✅ **Request Validation**: Strict schema-based validation using AJV.
11
+ - 🔥 **Hot Module Replacement (HMR)**: Real-time frontend updates without full page reloads using Socket.io and hot script swapping.
12
+ - 🎨 **Frontend Serving**: Serve HTML/CSS/JS assets from memory, with built-in **Tailwind CSS** processing.
13
+ - 🐚 **Security Hardened**: Built-in protection with **Helmet**, **CORS**, **Rate Limiting**, and path traversal protection.
14
+ - 🖥 **Premium TUI Logs**: Clean, informative, and beautiful startup messages.
15
15
 
16
16
  ## Installation
17
17
 
@@ -26,16 +26,14 @@ bun add @synchjs/ewb
26
26
  Create a file `controllers/HomeController.ts`:
27
27
 
28
28
  ```typescript
29
- import { Controller, Get } from "ewb";
30
- import type { Request, Response } from "express";
29
+ import { Controller, Get } from "@synchjs/ewb";
31
30
 
32
31
  @Controller("/")
33
32
  export class HomeController {
34
33
  @Get("/", {
35
34
  summary: "Welcome endpoint",
36
- description: "Returns a welcome message.",
37
35
  })
38
- public index(req: Request, res: Response) {
36
+ public index() {
39
37
  return { message: "Hello from @synchjs/ewb!" };
40
38
  }
41
39
  }
@@ -46,246 +44,128 @@ export class HomeController {
46
44
  Create `index.ts`:
47
45
 
48
46
  ```typescript
49
- import { Server } from "ewb";
47
+ import { Server } from "@synchjs/ewb";
50
48
 
51
49
  const server = new Server({
52
50
  id: "main",
53
51
  port: 3000,
54
- controllersDir: "controllers", // Directory where your controllers are located
55
- enableSwagger: true, // Enable Swagger UI at /api-docs
52
+ controllersDir: "controllers",
56
53
  });
57
54
 
58
- server.init();
55
+ await server.init();
59
56
  ```
60
57
 
61
- Run with Bun:
62
-
63
- ```bash
64
- bun run index.ts
65
- ```
58
+ ## Authentication & User Management
66
59
 
67
- ### 3. Customize Swagger Path
60
+ The framework uses a `UserHandler` system to give you full control over identity.
68
61
 
69
- You can change where Swagger UI is served:
62
+ ### 1. Define your User Handler
70
63
 
71
64
  ```typescript
72
- const server = new Server({
73
- id: "main",
74
- port: 3000,
75
- enableSwagger: true,
76
- swaggerPath: "/docs", // Now available at http://localhost:3000/docs
77
- });
78
- ```
79
-
80
- ## Detailed Usage
81
-
82
- ### Controllers & Routing
83
-
84
- Use `@Controller` to define a base path and HTTP method decorators for routes.
85
-
86
- ```typescript
87
- import { Controller, Get, Post, Put, Delete } from "ewb";
65
+ import { UserHandler } from "@synchjs/ewb";
88
66
  import type { Request, Response } from "express";
89
67
 
90
- @Controller("/users", { tags: ["Users"] })
91
- export class UserController {
92
- @Get("/:id")
93
- public getUser(req: Request, res: Response) {
94
- const { id } = req.params;
95
- return { id, name: "User " + id };
68
+ class MyUserHandler extends UserHandler {
69
+ // Determine who the user is for every request
70
+ public async authenticate(req: Request, res: Response) {
71
+ const token = req.headers.authorization?.replace("Bearer ", "");
72
+ if (token === "admin-secret") {
73
+ return { id: 1, name: "Admin", roles: ["admin"] };
74
+ }
75
+ return null;
96
76
  }
97
77
 
98
- @Post("/", {
99
- summary: "Create User",
100
- responses: {
101
- 201: { description: "User created" },
102
- },
103
- })
104
- public createUser(req: Request, res: Response) {
105
- // Logic to create user
106
- return { id: 1, ...req.body };
78
+ // Optional: Automatic routes for /auth/signin, signup, logout
79
+ public signin(req: Request, res: Response) {
80
+ /* ... */
107
81
  }
108
- }
109
- ```
110
-
111
- ### Authentication
112
-
113
- Secure your endpoints using `@BearerAuth`. It integrates with JWT verification automatically.
114
-
115
- - **Class Level:** Protects all routes in the controller.
116
- - **Method Level:** Protects specific routes.
117
- - **@Public():** Excludes a route from class-level auth.
118
-
119
- ```typescript
120
- import { Controller, Get, BearerAuth, Public } from "ewb";
121
-
122
- @Controller("/secure")
123
- @BearerAuth("my_secret_key") // Optional: Custom secret, defaults to process.env.JWT_SECRET
124
- export class SecureController {
125
- @Get("/dashboard")
126
- public dashboard(req: Request, res: Response) {
127
- // Access user data attached by middleware (req.user)
128
- const user = (req as any).user;
129
- return { message: "Secret data", user };
82
+ public signup(req: Request, res: Response) {
83
+ /* ... */
130
84
  }
131
-
132
- @Get("/status")
133
- @Public() // Accessible without token
134
- public status(req: Request, res: Response) {
135
- return { status: "OK" };
85
+ public logout(req: Request, res: Response) {
86
+ /* ... */
136
87
  }
137
88
  }
138
89
  ```
139
90
 
140
- #### Advanced Security (@Security, @OAuth, @ApiKey)
91
+ ### 2. Protect Routes
141
92
 
142
- For other authentication methods like OAuth2 or API Keys, use generic decorators:
93
+ Use `@Authorized` to require a user, or specify roles.
143
94
 
144
95
  ```typescript
145
- import { Controller, Get, OAuth, ApiKey } from "ewb";
96
+ import { Controller, Get, Authorized } from "@synchjs/ewb";
146
97
 
147
- @Controller("/api")
148
- export class ApiController {
98
+ @Controller("/dashboard")
99
+ export class DashboardController {
149
100
  @Get("/profile")
150
- @OAuth(["read:profile"]) // Marks route as requiring OAuth2 with specific scope
151
- public getProfile() {
152
- return { name: "John Doe" };
101
+ @Authorized() // Requires a non-null return from your UserHandler
102
+ public getProfile({ user }: { user: any }) {
103
+ return { message: `Hello ${user.name}` };
153
104
  }
154
105
 
155
- @Get("/data")
156
- @ApiKey("X-API-KEY") // Custom security scheme name
157
- public getData() {
158
- return { sensitive: "data" };
106
+ @Get("/admin")
107
+ @Authorized(["admin"]) // Checks roles array from UserHandler
108
+ public adminOnly() {
109
+ return { message: "Admin area" };
159
110
  }
160
111
  }
161
112
  ```
162
113
 
163
- **Configure Handlers and Schemes:**
114
+ ### 3. Register the Handler
164
115
 
165
116
  ```typescript
166
- const server = new Server({
167
- // ...,
168
- securitySchemes: {
169
- oauth2: {
170
- type: "oauth2",
171
- flows: {
172
- /* ... standard OpenAPI flow definition ... */
173
- },
174
- },
175
- },
176
- securityHandlers: {
177
- oauth2: (req, res, next) => {
178
- // Your OAuth validation logic here
179
- next();
180
- },
181
- },
182
- });
117
+ const server = new Server({ ... });
118
+ server.setUserHandler(new MyUserHandler()); // Routes /auth/* are created automatically
119
+ await server.init();
183
120
  ```
184
121
 
185
- ### Request Validation
186
-
187
- Define a JSON schema in the `@Post` (or other method) decorator to automatically validate the request body using AJV.
122
+ ## Hot Module Replacement (HMR)
188
123
 
189
- ```typescript
190
- @Post("/register", {
191
- summary: "Register new user",
192
- requestBody: {
193
- content: {
194
- "application/json": {
195
- schema: {
196
- type: "object",
197
- properties: {
198
- username: { type: "string" },
199
- email: { type: "string", format: "email" },
200
- age: { type: "integer", minimum: 18 }
201
- },
202
- required: ["username", "email"]
203
- }
204
- }
205
- }
206
- }
207
- })
208
- public register(req: Request, res: Response) {
209
- // If execution reaches here, req.body is valid
210
- return { success: true };
211
- }
212
- ```
124
+ HMR is active by default when `NODE_ENV` is not set to `production`. It uses Socket.io to sync changes.
213
125
 
214
- ### Serving Frontend Assets (with Tailwind CSS)
126
+ - **Fast Refresh**: Specifically optimized for React applications.
127
+ - **Hot Script Swapping**: Updates code in the browser without losing state or full page reloads.
128
+ - **Cache Control**: Automatically disables browser caching during development.
215
129
 
216
- You can serve compiled HTML and automatically process Tailwind CSS using the `@Serve` and `@Tailwindcss` decorators.
130
+ ## Serving Frontend Assets
217
131
 
218
- 1. **Project Structure**:
219
-
220
- ```
221
- /views
222
- src/
223
- index.html
224
- index.css (imports tailwind, or handled via plugin)
225
- frontend.tsx
226
- ```
227
-
228
- 2. **Controller Setup**:
132
+ Use `@Serve` to bundle and serve frontend entry points.
229
133
 
230
134
  ```typescript
231
- import { Controller, Get, Serve, Tailwindcss } from "ewb";
135
+ import { Controller, Get, Serve, Tailwindcss } from "@synchjs/ewb";
232
136
 
233
137
  @Controller("/")
234
- @Tailwindcss({
235
- enable: true,
236
- plugins: [
237
- /* Bun plugins or custom PostCSS wrappers */
238
- ],
239
- })
138
+ @Tailwindcss({ enable: true })
240
139
  export class FrontendController {
241
140
  @Get("/")
242
- @Serve("views/src/index.html") // Path to your HTML entry point
243
- public app(req: Request, res: Response) {
244
- // The decorator handles the response.
141
+ @Serve("views/src/index.html")
142
+ public app() {
143
+ // Handled by memory store
245
144
  }
246
145
  }
247
146
  ```
248
147
 
249
- ### Middleware
250
-
251
- Apply custom Express middleware to controllers or routes using `@Middleware`.
252
-
253
- ```typescript
254
- import { Controller, Get, Middleware } from "ewb";
255
-
256
- const logAccess = (req: Request, res: Response, next: NextFunction) => {
257
- console.log("Accessed!");
258
- next();
259
- };
148
+ ## Security & Best Practices
260
149
 
261
- @Controller("/audit")
262
- @Middleware(logAccess)
263
- export class AuditController {
264
- @Get("/")
265
- public index(req: Request, res: Response) {
266
- return { message: "Audited" };
267
- }
268
- }
269
- ```
150
+ - **Strict Validation**: AJV validates all request bodies defined in Swagger options. It automatically removes additional properties and enforces strict types.
151
+ - **Rate Limiting**: Protects your API from brute-force/DoS. (Static assets are automatically exempt).
152
+ - **Security Headers**: Powered by Helmet, with dynamic CSP adjustments for HMR.
153
+ - **Error Handling**: Production mode masks internal errors and stack traces.
270
154
 
271
155
  ## Server Configuration
272
156
 
273
- The `Server` class accepts the following options:
274
-
275
- | Option | Type | Description |
276
- | ------------------ | ------------------ | ---------------------------------------------------------------- |
277
- | `id` | `string` | Unique identifier for the server instance. |
278
- | `port` | `number` | Port to listen on. |
279
- | `controllersDir` | `string` | Directory containing controller files. |
280
- | `enableSwagger` | `boolean` | Enable OpenAPI documentation. |
281
- | `swaggerPath` | `string` | Custom path for Swagger UI (default: `/api-docs`). |
282
- | `logging` | `boolean` | Enable/disable TUI startup messages (default: true). |
283
- | `corsOptions` | `CorsOptions` | Configuration for CORS. |
284
- | `helmetOptions` | `HelmetOptions` | Configuration for Helmet security headers. |
285
- | `rateLimitOptions` | `RateLimitOptions` | Configuration for rate limiting. |
286
- | `securitySchemes` | `object` | custom OpenAPI security schemes definitions. |
287
- | `securityHandlers` | `object` | Middleware handlers for security schemes. |
288
- | `container` | `object` | IoC container for dependency injection (must have `get` method). |
157
+ | Option | Type | Description |
158
+ | ------------------ | ---------- | ------------------------------------------------------ |
159
+ | `id` | `string` | ID for logging and console output. |
160
+ | `port` | `number` | Port to listen on. |
161
+ | `controllersDir` | `string` | Location of your controllers (default: `controllers`). |
162
+ | `viewsDir` | `string` | Base directory for frontend views. |
163
+ | `enableSwagger` | `boolean` | Enable Swagger UI (default: `false`). |
164
+ | `swaggerPath` | `string` | Path for docs (default: `/api-docs`). |
165
+ | `helmetOptions` | `object` | Custom Helmet configuration. |
166
+ | `corsOptions` | `object` | Custom CORS configuration. |
167
+ | `rateLimitOptions` | `object` | Custom Rate Limit configuration. |
168
+ | `roleHandler` | `function` | Custom function for advanced role checking logic. |
289
169
 
290
170
  ## License
291
171
 
@@ -3,12 +3,26 @@ export declare class ServeMemoryStore {
3
3
  private static _instance;
4
4
  private _assets;
5
5
  private _htmlCache;
6
+ private _cacheDir;
7
+ private _devMode;
8
+ private _watchers;
9
+ private _listeners;
6
10
  private constructor();
11
+ private ensureCacheDir;
12
+ clearCache(): void;
7
13
  static get instance(): ServeMemoryStore;
8
- getAsset(path: string): {
14
+ setDevMode(enabled: boolean): void;
15
+ onRebuild(listener: (data?: {
16
+ html: string;
17
+ }) => void): void;
18
+ private notify;
19
+ getAsset(rawPath: string): {
9
20
  type: string;
10
21
  content: Uint8Array;
11
22
  };
23
+ private getCacheKey;
24
+ private loadFromDisk;
25
+ private setupWatcher;
12
26
  buildAndCache(htmlPath: string, options?: TailwindOptions): Promise<string>;
13
27
  }
14
28
  //# sourceMappingURL=ServeMemoryStore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ServeMemoryStore.d.ts","sourceRoot":"","sources":["../../src/Components/ServeMemoryStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAmB;IAC3C,OAAO,CAAC,OAAO,CACH;IACZ,OAAO,CAAC,UAAU,CAAkC;IAEpD,OAAO;IAEP,WAAkB,QAAQ,IAAI,gBAAgB,CAK7C;IAEM,QAAQ,CAAC,IAAI,EAAE,MAAM;cAbS,MAAM;iBAAW,UAAU;;IAmBnD,aAAa,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAgD,GACxD,OAAO,CAAC,MAAM,CAAC;CAsEnB"}
1
+ {"version":3,"file":"ServeMemoryStore.d.ts","sourceRoot":"","sources":["../../src/Components/ServeMemoryStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK/D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAmB;IAC3C,OAAO,CAAC,OAAO,CACH;IACZ,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,UAAU,CAA6C;IAE/D,OAAO;IAIP,OAAO,CAAC,cAAc;IAUf,UAAU;IAgBjB,WAAkB,QAAQ,IAAI,gBAAgB,CAK7C;IAEM,UAAU,CAAC,OAAO,EAAE,OAAO;IAI3B,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI;IAI5D,OAAO,CAAC,MAAM;IAIP,QAAQ,CAAC,OAAO,EAAE,MAAM;cAzDM,MAAM;iBAAW,UAAU;;IAgEhE,OAAO,CAAC,WAAW;YAQL,YAAY;IAyB1B,OAAO,CAAC,YAAY;IA4CP,aAAa,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAgD,GACxD,OAAO,CAAC,MAAM,CAAC;CA4JnB"}