azurajs 2.0.0 → 2.1.0

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
@@ -67,7 +67,7 @@ import { Router } from "azurajs/router";
67
67
  ### 1. Create `azura.config.ts`
68
68
 
69
69
  ```typescript
70
- import type { ConfigTypes } from "azurajs";
70
+ import type { ConfigTypes } from "azurajs/config";
71
71
 
72
72
  const config: ConfigTypes = {
73
73
  environment: "development",
@@ -100,19 +100,10 @@ export default config;
100
100
  ### 2. Create your server
101
101
 
102
102
  ```typescript
103
- import {
104
- AzuraClient,
105
- Controller,
106
- Get,
107
- Post,
108
- Body,
109
- Param,
110
- Query,
111
- Res,
112
- applyDecorators,
113
- createLoggingMiddleware
114
- } from "azurajs";
115
- import type { ResponseServer } from "azurajs";
103
+ import { AzuraClient, applyDecorators } from "azurajs";
104
+ import { Controller, Get, Post, Body, Param, Query, Res } from "azurajs/decorators";
105
+ import { createLoggingMiddleware } from "azurajs/middleware";
106
+ import type { ResponseServer } from "azurajs/types";
116
107
 
117
108
  @Controller("/api")
118
109
  class UserController {
@@ -349,7 +340,7 @@ res.location(url: string)
349
340
  ### Middleware
350
341
 
351
342
  ```typescript
352
- import { createLoggingMiddleware } from "azurajs";
343
+ import { createLoggingMiddleware } from "azurajs/middleware";
353
344
 
354
345
  const app = new AzuraClient();
355
346
 
@@ -416,8 +407,9 @@ type ConfigTypes = {
416
407
  ### Complete CRUD API
417
408
 
418
409
  ```typescript
419
- import { AzuraClient, Controller, Get, Post, Put, Delete, Body, Param, Res, applyDecorators } from "azurajs";
420
- import type { ResponseServer } from "azurajs";
410
+ import { AzuraClient, applyDecorators } from "azurajs";
411
+ import { Controller, Get, Post, Put, Delete, Body, Param, Res } from "azurajs/decorators";
412
+ import type { ResponseServer } from "azurajs/types";
421
413
 
422
414
  interface User {
423
415
  id: number;
@@ -563,12 +555,9 @@ AzuraJS is designed for high performance:
563
555
  Full TypeScript support with complete type definitions:
564
556
 
565
557
  ```typescript
566
- import type {
567
- RequestServer,
568
- ResponseServer,
569
- ConfigTypes,
570
- RequestHandler
571
- } from "azurajs";
558
+ import type { RequestServer, ResponseServer } from "azurajs/types";
559
+ import type { ConfigTypes } from "azurajs/config";
560
+ import type { RequestHandler } from "azurajs/types";
572
561
  ```
573
562
 
574
563
  > ⚠️ Azura is TypeScript-only.
package/package.json CHANGED
@@ -1,86 +1,136 @@
1
1
  {
2
2
  "name": "azurajs",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Modern TypeScript-first web framework with decorator-based routing, zero dependencies, and built for performance",
5
- "main": "src/index.ts",
6
- "module": "src/index.ts",
7
- "types": "src/index.ts",
5
+ "main": "./src/index.ts",
6
+ "module": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
8
  "type": "module",
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./src/index.ts",
12
12
  "import": "./src/index.ts",
13
- "require": "./src/index.ts"
13
+ "default": "./src/index.ts"
14
14
  },
15
15
  "./decorators": {
16
16
  "types": "./src/decorators/index.ts",
17
17
  "import": "./src/decorators/index.ts",
18
- "require": "./src/decorators/index.ts"
18
+ "default": "./src/decorators/index.ts"
19
19
  },
20
20
  "./middleware": {
21
21
  "types": "./src/middleware/index.ts",
22
22
  "import": "./src/middleware/index.ts",
23
- "require": "./src/middleware/index.ts"
23
+ "default": "./src/middleware/index.ts"
24
24
  },
25
25
  "./types": {
26
- "types": "./src/types/common.type.ts",
27
- "import": "./src/types/common.type.ts",
28
- "require": "./src/types/common.type.ts"
26
+ "types": "./src/types/index.ts",
27
+ "import": "./src/types/index.ts",
28
+ "default": "./src/types/index.ts"
29
+ },
30
+ "./infra": {
31
+ "types": "./src/infra/index.ts",
32
+ "import": "./src/infra/index.ts",
33
+ "default": "./src/infra/index.ts"
29
34
  },
30
35
  "./router": {
31
36
  "types": "./src/infra/Router.ts",
32
37
  "import": "./src/infra/Router.ts",
33
- "require": "./src/infra/Router.ts"
38
+ "default": "./src/infra/Router.ts"
34
39
  },
35
40
  "./config": {
36
- "types": "./src/shared/config/ConfigModule.ts",
37
- "import": "./src/shared/config/ConfigModule.ts",
38
- "require": "./src/shared/config/ConfigModule.ts"
41
+ "types": "./src/shared/config/index.ts",
42
+ "import": "./src/shared/config/index.ts",
43
+ "default": "./src/shared/config/index.ts"
44
+ },
45
+ "./plugins": {
46
+ "types": "./src/shared/plugins/index.ts",
47
+ "import": "./src/shared/plugins/index.ts",
48
+ "default": "./src/shared/plugins/index.ts"
39
49
  },
40
50
  "./cors": {
41
51
  "types": "./src/shared/plugins/CORSPlugin.ts",
42
52
  "import": "./src/shared/plugins/CORSPlugin.ts",
43
- "require": "./src/shared/plugins/CORSPlugin.ts"
53
+ "default": "./src/shared/plugins/CORSPlugin.ts"
44
54
  },
45
55
  "./rate-limit": {
46
56
  "types": "./src/shared/plugins/RateLimitPlugin.ts",
47
57
  "import": "./src/shared/plugins/RateLimitPlugin.ts",
48
- "require": "./src/shared/plugins/RateLimitPlugin.ts"
58
+ "default": "./src/shared/plugins/RateLimitPlugin.ts"
59
+ },
60
+ "./utils": {
61
+ "types": "./src/utils/index.ts",
62
+ "import": "./src/utils/index.ts",
63
+ "default": "./src/utils/index.ts"
49
64
  },
50
65
  "./cookies": {
51
- "types": "./src/utils/cookies/ParserCookie.ts",
52
- "import": "./src/utils/cookies/ParserCookie.ts",
53
- "require": "./src/utils/cookies/ParserCookie.ts"
66
+ "types": "./src/utils/cookies/index.ts",
67
+ "import": "./src/utils/cookies/index.ts",
68
+ "default": "./src/utils/cookies/index.ts"
54
69
  },
55
70
  "./validators": {
56
- "types": "./src/utils/validators/DTOValidator.ts",
57
- "import": "./src/utils/validators/DTOValidator.ts",
58
- "require": "./src/utils/validators/DTOValidator.ts"
71
+ "types": "./src/utils/validators/index.ts",
72
+ "import": "./src/utils/validators/index.ts",
73
+ "default": "./src/utils/validators/index.ts"
59
74
  },
60
75
  "./logger": {
61
76
  "types": "./src/utils/Logger.ts",
62
77
  "import": "./src/utils/Logger.ts",
63
- "require": "./src/utils/Logger.ts"
78
+ "default": "./src/utils/Logger.ts"
64
79
  },
65
80
  "./http-error": {
66
81
  "types": "./src/infra/utils/HttpError.ts",
67
82
  "import": "./src/infra/utils/HttpError.ts",
68
- "require": "./src/infra/utils/HttpError.ts"
69
- }
83
+ "default": "./src/infra/utils/HttpError.ts"
84
+ },
85
+ "./package.json": "./package.json"
70
86
  },
71
87
  "typesVersions": {
72
88
  "*": {
73
- "decorators": ["./src/decorators/index.ts"],
74
- "middleware": ["./src/middleware/index.ts"],
75
- "types": ["./src/types/common.type.ts"],
76
- "router": ["./src/infra/Router.ts"],
77
- "config": ["./src/shared/config/ConfigModule.ts"],
78
- "cors": ["./src/shared/plugins/CORSPlugin.ts"],
79
- "rate-limit": ["./src/shared/plugins/RateLimitPlugin.ts"],
80
- "cookies": ["./src/utils/cookies/ParserCookie.ts"],
81
- "validators": ["./src/utils/validators/DTOValidator.ts"],
82
- "logger": ["./src/utils/Logger.ts"],
83
- "http-error": ["./src/infra/utils/HttpError.ts"]
89
+ "*": [
90
+ "./src/*"
91
+ ],
92
+ "decorators": [
93
+ "./src/decorators/index.ts"
94
+ ],
95
+ "middleware": [
96
+ "./src/middleware/index.ts"
97
+ ],
98
+ "types": [
99
+ "./src/types/index.ts"
100
+ ],
101
+ "infra": [
102
+ "./src/infra/index.ts"
103
+ ],
104
+ "router": [
105
+ "./src/infra/Router.ts"
106
+ ],
107
+ "config": [
108
+ "./src/shared/config/index.ts"
109
+ ],
110
+ "plugins": [
111
+ "./src/shared/plugins/index.ts"
112
+ ],
113
+ "cors": [
114
+ "./src/shared/plugins/CORSPlugin.ts"
115
+ ],
116
+ "rate-limit": [
117
+ "./src/shared/plugins/RateLimitPlugin.ts"
118
+ ],
119
+ "utils": [
120
+ "./src/utils/index.ts"
121
+ ],
122
+ "cookies": [
123
+ "./src/utils/cookies/index.ts"
124
+ ],
125
+ "validators": [
126
+ "./src/utils/validators/index.ts"
127
+ ],
128
+ "logger": [
129
+ "./src/utils/Logger.ts"
130
+ ],
131
+ "http-error": [
132
+ "./src/infra/utils/HttpError.ts"
133
+ ]
84
134
  }
85
135
  },
86
136
  "files": [
@@ -34,23 +34,31 @@ export class Router {
34
34
  find(method: string, path: string): MatchResult {
35
35
  const segments = path.split("/").filter(Boolean);
36
36
  let node = this.root;
37
-
38
37
  const params: Record<string, string> = {};
39
- for (const seg of segments) {
40
- if (node.children.has(seg)) {
41
- node = node.children.get(seg)!;
42
- } else if (node.children.has(":")) {
43
- node = node.children.get(":")!;
44
-
45
- if (node.isParam && node.paramName) {
46
- params[node.paramName] = seg;
47
- }
38
+
39
+ for (let i = 0; i < segments.length; i++) {
40
+ const seg = segments[i];
41
+ let child = node.children.get(seg);
42
+
43
+ if (child) {
44
+ node = child;
48
45
  } else {
49
- throw new HttpError(404, "Route not found");
46
+ child = node.children.get(":");
47
+ if (child) {
48
+ node = child;
49
+ if (node.paramName) {
50
+ params[node.paramName] = seg;
51
+ }
52
+ } else {
53
+ throw new HttpError(404, "Route not found");
54
+ }
50
55
  }
51
56
  }
52
57
 
53
58
  const handlers = node.handlers.get(method.toUpperCase()) as Handler[];
59
+ if (!handlers) {
60
+ throw new HttpError(404, "Route not found");
61
+ }
54
62
  return { handlers, params };
55
63
  }
56
64
  }
@@ -139,14 +139,15 @@ export class AzuraClient {
139
139
  await this.initPromise;
140
140
 
141
141
  const url = new URL(request.url);
142
- const [urlPath, qs] = url.pathname.split("?");
142
+ const urlPath = url.pathname;
143
143
 
144
- // Parse query
145
- const rawQuery = parseQS(url.search.slice(1) || "");
146
144
  const safeQuery: Record<string, string> = {};
147
- for (const k in rawQuery) {
148
- const v = rawQuery[k];
149
- safeQuery[k] = Array.isArray(v) ? v[0] || "" : (v as string) || "";
145
+ if (url.search) {
146
+ const rawQuery = parseQS(url.search.slice(1));
147
+ for (const k in rawQuery) {
148
+ const v = rawQuery[k];
149
+ safeQuery[k] = Array.isArray(v) ? v[0] || "" : v as string;
150
+ }
150
151
  }
151
152
 
152
153
  const cookieHeader = request.headers.get("cookie") || "";
@@ -202,7 +203,6 @@ export class AzuraClient {
202
203
  ips: request.headers.get("x-forwarded-for")?.split(/\s*,\s*/) || [],
203
204
  };
204
205
 
205
- // Response builder
206
206
  let statusCode = 200;
207
207
  const responseHeaders = new Headers();
208
208
  let responseBody: any = null;
@@ -0,0 +1,3 @@
1
+ export { Server } from "./Server";
2
+ export { Router } from "./Router";
3
+ export { HttpError } from "./utils/HttpError";
@@ -0,0 +1,2 @@
1
+ export { ConfigModule } from "./ConfigModule";
2
+ export type { ConfigTypes } from "./ConfigModule";
@@ -0,0 +1,2 @@
1
+ export { cors } from "./CORSPlugin";
2
+ export { rateLimit } from "./RateLimitPlugin";
@@ -0,0 +1,5 @@
1
+ export type { RequestServer } from "./http/request.type";
2
+ export type { ResponseServer } from "./http/response.type";
3
+ export type { RequestHandler, HttpContext } from "./common.type";
4
+ export type { RouteDefinition, ParamDefinition, ParamSource } from "./routes.type";
5
+ export type { Schema as ValidationSchema } from "./validations.type";
@@ -1,16 +1,28 @@
1
1
  export function parseQS(qs: string): Record<string, string | string[]> {
2
2
  const out: Record<string, string | string[]> = {};
3
3
  if (!qs) return out;
4
- const parts = qs.replace(/^\?/, "").split("&");
5
- for (const p of parts) {
4
+
5
+ const parts = qs.split("&");
6
+ for (let i = 0; i < parts.length; i++) {
7
+ const p = parts[i];
6
8
  if (!p) continue;
9
+
7
10
  const idx = p.indexOf("=");
8
- const k = idx === -1 ? decodeURIComponent(p) : decodeURIComponent(p.slice(0, idx));
9
- const v = idx === -1 ? "" : decodeURIComponent(p.slice(idx + 1));
10
- if (Object.prototype.hasOwnProperty.call(out, k)) {
11
- const cur = out[k];
12
- if (Array.isArray(cur)) cur.push(v);
13
- else out[k] = [cur as string, v];
11
+ if (idx === -1) {
12
+ out[decodeURIComponent(p)] = "";
13
+ continue;
14
+ }
15
+
16
+ const k = decodeURIComponent(p.slice(0, idx));
17
+ const v = decodeURIComponent(p.slice(idx + 1));
18
+
19
+ const existing = out[k];
20
+ if (existing !== undefined) {
21
+ if (Array.isArray(existing)) {
22
+ existing.push(v);
23
+ } else {
24
+ out[k] = [existing as string, v];
25
+ }
14
26
  } else {
15
27
  out[k] = v;
16
28
  }
@@ -0,0 +1,2 @@
1
+ export { parseCookiesHeader } from "./ParserCookie";
2
+ export { serializeCookie } from "./SerializeCookie";
@@ -0,0 +1,4 @@
1
+ export { logger } from "./Logger";
2
+ export { parseQS } from "./Parser";
3
+ export * from "./cookies";
4
+ export * from "./validators";
@@ -0,0 +1,2 @@
1
+ export { validateDto, getDtoValidators } from "./DTOValidator";
2
+ export { validateSchema } from "./SchemaValidator";