princejs 1.3.4 → 1.3.6

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.
@@ -0,0 +1,110 @@
1
+ // @bun
2
+ // src/middleware.ts
3
+ var MIDDLEWARE_EXECUTED = Symbol("middlewareExecuted");
4
+ var cors = (options) => {
5
+ const origin = options?.origin || "*";
6
+ const methods = options?.methods || "GET,POST,PUT,DELETE,PATCH,OPTIONS";
7
+ const headers = options?.headers || "Content-Type,Authorization";
8
+ const credentials = options?.credentials || false;
9
+ return async (req, next) => {
10
+ if (req[MIDDLEWARE_EXECUTED]?.cors) {
11
+ return await next();
12
+ }
13
+ if (!req[MIDDLEWARE_EXECUTED]) {
14
+ req[MIDDLEWARE_EXECUTED] = {};
15
+ }
16
+ req[MIDDLEWARE_EXECUTED].cors = true;
17
+ if (req.method === "OPTIONS") {
18
+ return new Response(null, {
19
+ status: 204,
20
+ headers: {
21
+ "Access-Control-Allow-Origin": origin,
22
+ "Access-Control-Allow-Methods": methods,
23
+ "Access-Control-Allow-Headers": headers,
24
+ ...credentials ? { "Access-Control-Allow-Credentials": "true" } : {}
25
+ }
26
+ });
27
+ }
28
+ const res = await next();
29
+ if (!res)
30
+ return res;
31
+ const newHeaders = new Headers(res.headers);
32
+ newHeaders.set("Access-Control-Allow-Origin", origin);
33
+ if (credentials)
34
+ newHeaders.set("Access-Control-Allow-Credentials", "true");
35
+ return new Response(res.body, {
36
+ status: res.status,
37
+ statusText: res.statusText,
38
+ headers: newHeaders
39
+ });
40
+ };
41
+ };
42
+ var logger = (options) => {
43
+ const format = options?.format || "dev";
44
+ const colors = options?.colors !== false;
45
+ const colorize = (code, text) => {
46
+ if (!colors)
47
+ return text;
48
+ if (code >= 500)
49
+ return `\x1B[31m${text}\x1B[0m`;
50
+ if (code >= 400)
51
+ return `\x1B[33m${text}\x1B[0m`;
52
+ if (code >= 300)
53
+ return `\x1B[36m${text}\x1B[0m`;
54
+ if (code >= 200)
55
+ return `\x1B[32m${text}\x1B[0m`;
56
+ return text;
57
+ };
58
+ return async (req, next) => {
59
+ if (req[MIDDLEWARE_EXECUTED]?.logger) {
60
+ return await next();
61
+ }
62
+ if (!req[MIDDLEWARE_EXECUTED]) {
63
+ req[MIDDLEWARE_EXECUTED] = {};
64
+ }
65
+ req[MIDDLEWARE_EXECUTED].logger = true;
66
+ const start = Date.now();
67
+ const pathname = new URL(req.url).pathname;
68
+ const res = await next();
69
+ if (!res)
70
+ return res;
71
+ const duration = Date.now() - start;
72
+ const status = res.status;
73
+ if (format === "dev") {
74
+ console.log(`${colorize(status, req.method)} ${pathname} ${colorize(status, String(status))} ${duration}ms`);
75
+ } else if (format === "tiny") {
76
+ console.log(`${req.method} ${pathname} ${status} - ${duration}ms`);
77
+ } else {
78
+ const date = new Date().toISOString();
79
+ console.log(`[${date}] ${req.method} ${pathname} ${status} ${duration}ms`);
80
+ }
81
+ return res;
82
+ };
83
+ };
84
+ var rateLimit = (options) => {
85
+ const store = new Map;
86
+ return async (req, next) => {
87
+ const ip = req.headers.get("x-forwarded-for") || "unknown";
88
+ const now = Date.now();
89
+ const windowMs = options.window * 1000;
90
+ let record = store.get(ip);
91
+ if (!record || now > record.resetAt) {
92
+ record = { count: 1, resetAt: now + windowMs };
93
+ store.set(ip, record);
94
+ return await next();
95
+ }
96
+ if (record.count >= options.max) {
97
+ return new Response(JSON.stringify({ error: options.message || "Too many requests" }), {
98
+ status: 429,
99
+ headers: { "Content-Type": "application/json" }
100
+ });
101
+ }
102
+ record.count++;
103
+ return await next();
104
+ };
105
+ };
106
+ export {
107
+ rateLimit,
108
+ logger,
109
+ cors
110
+ };
package/dist/prince.js CHANGED
@@ -1,4 +1,129 @@
1
1
  // @bun
2
+ // src/middleware.ts
3
+ var MIDDLEWARE_EXECUTED = Symbol("middlewareExecuted");
4
+ var cors = (options) => {
5
+ const origin = options?.origin || "*";
6
+ const methods = options?.methods || "GET,POST,PUT,DELETE,PATCH,OPTIONS";
7
+ const headers = options?.headers || "Content-Type,Authorization";
8
+ const credentials = options?.credentials || false;
9
+ return async (req, next) => {
10
+ if (req[MIDDLEWARE_EXECUTED]?.cors) {
11
+ return await next();
12
+ }
13
+ if (!req[MIDDLEWARE_EXECUTED]) {
14
+ req[MIDDLEWARE_EXECUTED] = {};
15
+ }
16
+ req[MIDDLEWARE_EXECUTED].cors = true;
17
+ if (req.method === "OPTIONS") {
18
+ return new Response(null, {
19
+ status: 204,
20
+ headers: {
21
+ "Access-Control-Allow-Origin": origin,
22
+ "Access-Control-Allow-Methods": methods,
23
+ "Access-Control-Allow-Headers": headers,
24
+ ...credentials ? { "Access-Control-Allow-Credentials": "true" } : {}
25
+ }
26
+ });
27
+ }
28
+ const res = await next();
29
+ if (!res)
30
+ return res;
31
+ const newHeaders = new Headers(res.headers);
32
+ newHeaders.set("Access-Control-Allow-Origin", origin);
33
+ if (credentials)
34
+ newHeaders.set("Access-Control-Allow-Credentials", "true");
35
+ return new Response(res.body, {
36
+ status: res.status,
37
+ statusText: res.statusText,
38
+ headers: newHeaders
39
+ });
40
+ };
41
+ };
42
+ var logger = (options) => {
43
+ const format = options?.format || "dev";
44
+ const colors = options?.colors !== false;
45
+ const colorize = (code, text) => {
46
+ if (!colors)
47
+ return text;
48
+ if (code >= 500)
49
+ return `\x1B[31m${text}\x1B[0m`;
50
+ if (code >= 400)
51
+ return `\x1B[33m${text}\x1B[0m`;
52
+ if (code >= 300)
53
+ return `\x1B[36m${text}\x1B[0m`;
54
+ if (code >= 200)
55
+ return `\x1B[32m${text}\x1B[0m`;
56
+ return text;
57
+ };
58
+ return async (req, next) => {
59
+ if (req[MIDDLEWARE_EXECUTED]?.logger) {
60
+ return await next();
61
+ }
62
+ if (!req[MIDDLEWARE_EXECUTED]) {
63
+ req[MIDDLEWARE_EXECUTED] = {};
64
+ }
65
+ req[MIDDLEWARE_EXECUTED].logger = true;
66
+ const start = Date.now();
67
+ const pathname = new URL(req.url).pathname;
68
+ const res = await next();
69
+ if (!res)
70
+ return res;
71
+ const duration = Date.now() - start;
72
+ const status = res.status;
73
+ if (format === "dev") {
74
+ console.log(`${colorize(status, req.method)} ${pathname} ${colorize(status, String(status))} ${duration}ms`);
75
+ } else if (format === "tiny") {
76
+ console.log(`${req.method} ${pathname} ${status} - ${duration}ms`);
77
+ } else {
78
+ const date = new Date().toISOString();
79
+ console.log(`[${date}] ${req.method} ${pathname} ${status} ${duration}ms`);
80
+ }
81
+ return res;
82
+ };
83
+ };
84
+ var rateLimit = (options) => {
85
+ const store = new Map;
86
+ return async (req, next) => {
87
+ const ip = req.headers.get("x-forwarded-for") || "unknown";
88
+ const now = Date.now();
89
+ const windowMs = options.window * 1000;
90
+ let record = store.get(ip);
91
+ if (!record || now > record.resetAt) {
92
+ record = { count: 1, resetAt: now + windowMs };
93
+ store.set(ip, record);
94
+ return await next();
95
+ }
96
+ if (record.count >= options.max) {
97
+ return new Response(JSON.stringify({ error: options.message || "Too many requests" }), {
98
+ status: 429,
99
+ headers: { "Content-Type": "application/json" }
100
+ });
101
+ }
102
+ record.count++;
103
+ return await next();
104
+ };
105
+ };
106
+
107
+ // src/validation.ts
108
+ var validate = (schema, source = "body") => {
109
+ return async (req, next) => {
110
+ try {
111
+ const data = source === "body" ? req.body : source === "query" ? req.query : req.params;
112
+ const validated = schema.parse(data);
113
+ req[`validated${source.charAt(0).toUpperCase() + source.slice(1)}`] = validated;
114
+ return await next();
115
+ } catch (err) {
116
+ return new Response(JSON.stringify({
117
+ error: "Validation failed",
118
+ details: err.errors || err.message
119
+ }), {
120
+ status: 400,
121
+ headers: { "Content-Type": "application/json" }
122
+ });
123
+ }
124
+ };
125
+ };
126
+
2
127
  // src/prince.ts
3
128
  class TrieNode {
4
129
  children = Object.create(null);
@@ -57,6 +182,21 @@ class Prince {
57
182
  constructor(devMode = false) {
58
183
  this.devMode = devMode;
59
184
  }
185
+ useCors(options) {
186
+ this.use(cors(options));
187
+ return this;
188
+ }
189
+ useLogger(options) {
190
+ this.use(logger(options));
191
+ return this;
192
+ }
193
+ useRateLimit(options) {
194
+ this.use(rateLimit(options));
195
+ return this;
196
+ }
197
+ validate(schema, source = "body") {
198
+ return validate(schema, source);
199
+ }
60
200
  use(mw) {
61
201
  this.middlewares.push(mw);
62
202
  return this;
@@ -0,0 +1,23 @@
1
+ // @bun
2
+ // src/validation.ts
3
+ var validate = (schema, source = "body") => {
4
+ return async (req, next) => {
5
+ try {
6
+ const data = source === "body" ? req.body : source === "query" ? req.query : req.params;
7
+ const validated = schema.parse(data);
8
+ req[`validated${source.charAt(0).toUpperCase() + source.slice(1)}`] = validated;
9
+ return await next();
10
+ } catch (err) {
11
+ return new Response(JSON.stringify({
12
+ error: "Validation failed",
13
+ details: err.errors || err.message
14
+ }), {
15
+ status: 400,
16
+ headers: { "Content-Type": "application/json" }
17
+ });
18
+ }
19
+ };
20
+ };
21
+ export {
22
+ validate
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "princejs",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "An easy and fast backend framework — by a 13yo developer, for developers.",
5
5
  "main": "dist/prince.js",
6
6
  "types": "dist/prince.d.ts",