barejs 0.1.44 → 0.1.47

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.
@@ -9,10 +9,11 @@ export interface NotFoundResponse {
9
9
  export declare class BareJS extends BareRouter {
10
10
  private tree;
11
11
  private pool;
12
- private poolIdx;
13
12
  private hotFetch?;
14
13
  private compiled;
15
14
  private poolMask;
15
+ private _useLog;
16
+ useLog(enabled?: boolean): this;
16
17
  constructor(poolSize?: number);
17
18
  private notFoundHandler;
18
19
  setNotFound(handler: () => NotFoundResponse): void;
@@ -0,0 +1,11 @@
1
+ export interface BareConfig {
2
+ hash: {
3
+ algorithm: "argon2id" | "bcrypt";
4
+ memoryCost: number;
5
+ timeCost: number;
6
+ };
7
+ port: number;
8
+ }
9
+ export declare const DEFAULT_CONFIG: BareConfig;
10
+ export declare let BARE_CONFIG: BareConfig;
11
+ export declare const initConfig: (userConfig?: Partial<BareConfig>) => BareConfig;
@@ -11,6 +11,7 @@ export declare class Context {
11
11
  _headers?: Record<string, string> | undefined;
12
12
  store: Map<string, any>;
13
13
  body: any;
14
+ query: Record<string, string>;
14
15
  constructor();
15
16
  jsonBody(): Promise<any>;
16
17
  reset(req: Request): this;
@@ -19,4 +20,5 @@ export declare class Context {
19
20
  set(key: string, value: any): this;
20
21
  get(key: string): any;
21
22
  setHeader(name: string, value: string): this;
23
+ send(message: string, extra?: Record<string, any>): Response;
22
24
  }
@@ -0,0 +1 @@
1
+ export declare function bootstrapConfig(): Promise<import("./config").BareConfig>;
@@ -1,13 +1,9 @@
1
- import { type Middleware, type Handler } from './context';
1
+ import { type Middleware, type Handler } from '../core/context';
2
2
  type HandlersChain = (Middleware | Handler)[];
3
3
  export declare class BareRouter {
4
4
  prefix: string;
5
5
  groupMiddleware: any[];
6
- routes: {
7
- method: string;
8
- path: string;
9
- handlers: any[];
10
- }[];
6
+ routes: any[];
11
7
  constructor(prefix?: string, groupMiddleware?: any[]);
12
8
  private _add;
13
9
  get: (path: string, ...h: HandlersChain) => this;
@@ -16,10 +12,6 @@ export declare class BareRouter {
16
12
  patch: (path: string, ...h: HandlersChain) => this;
17
13
  delete: (path: string, ...h: HandlersChain) => this;
18
14
  group: (path: string, ...args: any[]) => this;
19
- /**
20
- * 🔗 Use: Mounts a router or middleware
21
- * Supports nested routers with automatic path prefixing
22
- */
23
15
  use(mw: any): this;
24
16
  }
25
17
  export {};
@@ -4,28 +4,20 @@
4
4
  * Built for Bun with Mechanical Sympathy
5
5
  * Optimized to outperform competitors by 55% [2026-01-05]
6
6
  */
7
- export { BareJS } from './bare';
7
+ export { BareJS } from './core/bare';
8
8
  /**
9
9
  * Plugin Interface for BareJS
10
10
  */
11
11
  export interface BarePlugin {
12
12
  install: (app: any) => void;
13
13
  }
14
- export type { Middleware, Handler, Next, Context, Params, AuthUser } from './context';
15
- /**
16
- * รองรับทั้ง T, Type และ TypeBox
17
- * ใช้สำหรับสร้าง Schema เช่น T.String() หรือ Type.Number()
18
- */
14
+ export type { Middleware, Handler, Next, Context, Params, AuthUser } from './core/context';
19
15
  import { Type } from "@sinclair/typebox";
20
16
  export { Type, Type as T, Type as TypeBox };
21
- /**
22
- * รองรับทั้ง t, typebox และ v, validate (Auto)
23
- * สำหรับ Zod รองรับทั้ง Z (Builder) และ z (Middleware)
24
- */
25
- import { typebox, zod, native, validate, Z } from './validators';
17
+ import { typebox, zod, native, validate, Z } from './security/validators';
26
18
  export { typebox, typebox as t, zod, zod as z, Z, Z as Zod, native, native as n, validate, validate as v };
27
- export { logger } from './logger';
28
- export { cors } from './cors';
29
- export { staticFile } from './static';
30
- export { BareRouter } from './router';
31
- export { bareAuth, createToken, Hash as Password, Hash } from './auth';
19
+ export { cors } from './security/cors';
20
+ export { staticFile } from './utils/static';
21
+ export { BareRouter } from './core/router';
22
+ export { bareAuth, createToken } from './security/auth';
23
+ export { Hash as Password, Hash } from './security/hash';
@@ -1,4 +1,4 @@
1
- import type { Next } from './context';
1
+ import type { Next } from '../core/context';
2
2
  /**
3
3
  * 4. TOKEN GENERATOR (Standard JWT)
4
4
  */
@@ -16,15 +16,6 @@ export declare const basicAuth: (credentials: {
16
16
  user: string;
17
17
  pass: string;
18
18
  }) => (ctx: any, next: Next) => Promise<any>;
19
- /**
20
- * 3. PASSWORD UTILS (Bun Native)
21
- * Uses Argon2id - the gold standard for password hashing
22
- */
23
- export declare const Hash: {
24
- make: (data: string) => Promise<string>;
25
- verify: (data: string, hash: string) => Promise<boolean>;
26
- needsRehash: (hash: string) => boolean;
27
- };
28
19
  /**
29
20
  * 5. ROLE AUTHORIZATION (Bonus Max Function)
30
21
  * Ensures user has specific permissions after bareAuth
@@ -1,4 +1,4 @@
1
- import type { Middleware } from './context';
1
+ import type { Middleware } from '../core/context';
2
2
  export declare const cors: (options?: {
3
3
  origin?: string;
4
4
  methods?: string;
@@ -0,0 +1,5 @@
1
+ export declare const Hash: {
2
+ make: (data: string) => Promise<string>;
3
+ verify: (data: string, hash: string) => Promise<boolean>;
4
+ needsRehash: (hash: string) => boolean;
5
+ };
@@ -4,7 +4,7 @@
4
4
  * Optimized for Bun Runtime & Mechanical Sympathy [2026-01-05]
5
5
  */
6
6
  import { z } from 'zod';
7
- import type { Middleware } from './context';
7
+ import type { Middleware } from '../core/context';
8
8
  export declare const Z: typeof z;
9
9
  /**
10
10
  * TypeBox JIT Engine (t)
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "barejs",
3
- "version": "0.1.44",
4
- "author": "xarhang",
5
- "description": "High-performance JIT-specialized web framework for Bun",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
- "types": "./dist/types/index.d.ts",
9
- "type": "module",
10
- "exports": {
11
- ".": {
12
- "import": "./dist/index.js",
13
- "types": "./dist/types/index.d.ts"
14
- }
15
- },
16
- "sideEffects": false,
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/xarhang/barejs.git"
20
- },
21
- "scripts": {
22
- "test": "bun test",
23
- "benchs": "bun run benchmarks/index.ts",
24
- "bench": "bun run benchmarks/head-to-head.ts",
25
- "dev": "bun --watch src/index.ts",
26
- "build": "bun ./scripts/build.ts",
27
- "prepublishOnly": "bun run build",
28
- "release": "bun run build && npm version patch && npm publish --access public"
29
- },
30
- "keywords": [
31
- "bun",
32
- "framework",
33
- "fastest",
34
- "jit",
35
- "typebox",
36
- "zod",
37
- "barejs",
38
- "http-server"
39
- ],
40
- "license": "MIT",
41
- "peerDependencies": {
42
- "@sinclair/typebox": "^0.34.46",
43
- "zod": "^3.0.0"
44
- },
45
- "peerDependenciesMeta": {
46
- "@sinclair/typebox": {
47
- "optional": true
48
- },
49
- "zod": {
50
- "optional": true
51
- }
52
- },
53
- "devDependencies": {
54
- "@sinclair/typebox": "^0.34.46",
55
- "@types/bun": "^1.3.5",
56
- "elysia": "latest",
57
- "hono": "latest",
58
- "mitata": "^1.0.34",
59
- "typescript": "latest",
60
- "zod": "^3.23.8"
61
- },
62
- "files": [
63
- "dist",
64
- "src",
65
- "README.md",
66
- "LICENSE"
67
- ]
68
- }
1
+ {
2
+ "name": "barejs",
3
+ "version": "0.1.47",
4
+ "author": "xarhang",
5
+ "description": "High-performance JIT-specialized web framework for Bun",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/types/index.d.ts",
9
+ "type": "module",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/types/index.d.ts"
14
+ }
15
+ },
16
+ "sideEffects": false,
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/xarhang/barejs.git"
20
+ },
21
+ "scripts": {
22
+ "test": "bun test",
23
+ "benchs": "bun run benchmarks/index.ts",
24
+ "bench": "bun run benchmarks/head-to-head.ts",
25
+ "dev": "bun --watch example/index.ts",
26
+ "build": "bun ./scripts/build.ts",
27
+ "prepublishOnly": "bun run build",
28
+ "release": "bun run build && npm version patch && npm publish --access public"
29
+ },
30
+ "keywords": [
31
+ "bun",
32
+ "framework",
33
+ "fastest",
34
+ "jit",
35
+ "typebox",
36
+ "zod",
37
+ "barejs",
38
+ "http-server"
39
+ ],
40
+ "license": "MIT",
41
+ "peerDependencies": {
42
+ "@sinclair/typebox": "^0.34.46",
43
+ "zod": "^3.0.0"
44
+ },
45
+ "peerDependenciesMeta": {
46
+ "@sinclair/typebox": {
47
+ "optional": true
48
+ },
49
+ "zod": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "devDependencies": {
54
+ "@sinclair/typebox": "^0.34.47",
55
+ "@types/bun": "^1.3.5",
56
+ "elysia": "latest",
57
+ "hono": "latest",
58
+ "mitata": "^1.0.34",
59
+ "typescript": "latest",
60
+ "zod": "^3.25.76"
61
+ },
62
+ "files": [
63
+ "dist",
64
+ "src",
65
+ "README.md",
66
+ "LICENSE"
67
+ ]
68
+ }
@@ -4,6 +4,8 @@ import { Context } from './context';
4
4
  import { Type as typebox, Type as t } from '@sinclair/typebox';
5
5
  import { join } from "node:path";
6
6
  import { readFileSync } from "node:fs";
7
+ import { bootstrapConfig } from "./loader";
8
+
7
9
  export interface NotFoundResponse {
8
10
  status: number;
9
11
  message: string;
@@ -12,13 +14,18 @@ export interface NotFoundResponse {
12
14
  export class BareJS extends BareRouter {
13
15
  private tree = new RadixNode();
14
16
  private pool: Context[] = [];
15
- private poolIdx = 0;
17
+ // private poolIdx = 0;
16
18
  private hotFetch?: (req: Request) => any;
17
19
  private compiled = false;
18
20
  private poolMask: number;
19
-
21
+ private _useLog: boolean = false;
22
+ public useLog(enabled: boolean = true): this {
23
+ this._useLog = enabled;
24
+ return this;
25
+ }
20
26
  constructor(poolSize: number = 1024) {
21
27
  super();
28
+ bootstrapConfig();
22
29
  const size = Math.pow(2, Math.ceil(Math.log2(poolSize)));
23
30
  this.poolMask = size - 1;
24
31
  for (let i = 0; i < size; i++) {
@@ -58,34 +65,41 @@ export class BareJS extends BareRouter {
58
65
 
59
66
  // Inline Finalizer
60
67
  const finalizeCode = `
61
- if (res instanceof Response) return res;
62
- // Smart Finalizer: Handle String vs Object vs Null
68
+ if (res instanceof Response) {
69
+ if (typeof doLog === 'function') doLog(res.status);
70
+ return res;
71
+ }
72
+
73
+ const finalStatus = ctx._status || 200;
74
+ if (typeof doLog === 'function') doLog(finalStatus);
75
+
63
76
  if (typeof res === 'string') {
64
77
  return new Response(res, {
65
- status: ctx._status,
78
+ status: finalStatus,
66
79
  headers: ctx._headers || { "content-type": "text/plain" }
67
80
  });
68
81
  }
69
82
 
70
- // FASTEST PATH: 200 OK + No Custom Headers -> Use Cached Init
71
- if (ctx._status === 200 && !ctx._headers) {
72
- return Response.json(res ?? null, json200);
73
- }
74
-
75
83
  return Response.json(res ?? null, {
76
- status: ctx._status,
84
+ status: finalStatus,
77
85
  headers: ctx._headers && ctx._headers["content-type"] ? ctx._headers : { "content-type": "application/json" }
78
86
  });
79
87
  `;
80
88
 
81
89
  if (len === 1) {
82
- // 🚀 Fast path: no middleware (just the handler)
90
+ // Fast path: no middleware (just the handler)
83
91
  const fn0 = pipeline[0];
84
- return new Function('fn0', 'json200', `return function(ctx) {
92
+ return new Function('fn0', 'json200', `return function(ctx, doLog) {
85
93
  const res = fn0(ctx);
86
94
  if (res && res.then) return res.then(v => { const res = v; ${finalizeCode} });
87
95
  ${finalizeCode}
88
96
  }`)(fn0, json200);
97
+
98
+ // return new Function('fn0', 'json200', `return function(ctx) {
99
+ // const res = fn0(ctx);
100
+ // if (res && res.then) return res.then(v => { const res = v; ${finalizeCode} });
101
+ // ${finalizeCode}
102
+ // }`)(fn0, json200);
89
103
  }
90
104
 
91
105
  // Check async
@@ -131,13 +145,16 @@ export class BareJS extends BareRouter {
131
145
 
132
146
  const noop = () => { };
133
147
 
134
- const fnHeader = isAsync ? 'return async function(ctx)' : 'return function(ctx)';
135
-
148
+ // const fnHeader = isAsync ? 'return async function(ctx)' : 'return function(ctx)';
149
+ const fnHeader = pipeline.some(fn => fn.constructor.name === 'AsyncFunction')
150
+ ? 'return async function(ctx, doLog)' // ⚡️ รับ doLog เข้ามา
151
+ : 'return function(ctx, doLog)';
136
152
  // Construct Function: (...fns, noop, json200) -> return function(ctx) { ... }
137
153
  return new Function(...fnNames, 'noop', 'json200', `${fnHeader} { ${code} }`)(...pipeline, noop, json200);
138
154
  }
139
155
 
140
156
  public compile() {
157
+ const isLog = this._useLog;
141
158
  this.tree = new RadixNode();
142
159
  for (const route of this.routes) {
143
160
  this.tree.insert(route.path, route.method, this.compileHandler(route.handlers));
@@ -151,7 +168,7 @@ export class BareJS extends BareRouter {
151
168
  const hError = (err: any) => ({
152
169
  status: 500,
153
170
  message: err.message || "Internal Server Error",
154
- stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
171
+ stack: process.env.NODE_ENV !== 'production' ? err.stack : undefined
155
172
  });
156
173
 
157
174
  // JIT Compiler: Create all Code instead of tree.lookup
@@ -163,7 +180,9 @@ export class BareJS extends BareRouter {
163
180
  };
164
181
 
165
182
  const routerCode = tree.jitCompile(register);
166
-
183
+ // console.log("--- GENERATED JIT CODE ---");
184
+ // console.log(routerCode);
185
+ // console.log("--------------------------");
167
186
  // Create seamless Fetcher (JIT Edition)
168
187
  // We send nodes into the closure so the code can use them
169
188
  const EMPTY_PARAMS = Object.freeze({});
@@ -172,42 +191,58 @@ export class BareJS extends BareRouter {
172
191
  const args = ['pool', 'pIdx', 'mask', 'hNotFound', 'hError', 'EMPTY_PARAMS', ...hNames];
173
192
  const values = [pool, pIdx, mask, hNotFound, hError, EMPTY_PARAMS, ...hoistedHandlers];
174
193
 
175
- const fnBody = `
176
- return function(req) {
177
- const url = req.url;
178
- // Start searching after "http://" (7) or "https://" (8)
179
- let s = url.indexOf('/', 8);
180
-
181
- // Handle root path or missing slash
182
- if (s === -1) {
183
- s = url.length;
184
- } else if (url.charCodeAt(s) === 47) {
185
- // Skip the leading slash to match split() behavior (['users'] not ['/users'])
186
- s++;
187
- }
188
-
189
- const method = req.method;
190
- const ctx = pool[(++pIdx) & mask];
191
- try {
192
- // INLINED Context.reset() for max speed (No function call overhead)
193
- ctx.req = req;
194
- ctx._status = 200;
195
- ctx._headers = undefined;
196
- if (ctx.store.size > 0) ctx.store.clear();
197
- ctx.params = EMPTY_PARAMS;
198
- ctx.body = undefined;
199
-
200
- // JIT Generated Code Start
201
- ${routerCode}
202
- // JIT Generated Code End
203
- const errorBody = hNotFound();
204
- return Response.json(errorBody, { status: errorBody.status || 404 });
205
- } catch (e) {
206
- const errorBody = hError(e);
207
- return Response.json(errorBody, { status: errorBody.status || 500 });
208
- }
209
- }
210
- `;
194
+
195
+ // ส่วนใน compile() method (หาบรรทัดที่สร้าง fnBody)
196
+
197
+ const fnBody = `
198
+ return function(req) {
199
+ const start = performance.now();
200
+ const url = req.url + " ";
201
+ const urlLen = req.url.length; // ✅ ความยาวจริงของ URL
202
+
203
+ let s = url.indexOf('/', 8);
204
+ if (s !== -1) s++;
205
+ else s = urlLen; // ✅ เปลี่ยนจาก url.length เป็น urlLen
206
+
207
+ const method = req.method;
208
+ const ctx = pool[(++pIdx) & mask];
209
+
210
+ const doLog = (status) => {
211
+ if (!${isLog}) return;
212
+ const duration = (performance.now() - start).toFixed(3);
213
+ console.log(
214
+ \` \\x1b[90m\${new Date().toLocaleTimeString()}\\x1b[0m \` +
215
+ \`\\x1b[1m\\x1b[38;5;117m\${method.padEnd(7)}\\x1b[0m \` +
216
+ \`\\x1b[38;5;250m\${req.url.substring(req.url.indexOf('/', 8))}\\x1b[0m \` +
217
+ \`\${status >= 400 ? '\\x1b[33m' : '\\x1b[32m'}\${status}\\x1b[0m \` +
218
+ \`\\x1b[90m(\${duration}ms)\\x1b[0m\`
219
+ );
220
+ };
221
+
222
+ try {
223
+ ctx.req = req;
224
+ ctx._status = 200;
225
+ ctx._headers = undefined;
226
+ if (ctx.store.size > 0) ctx.store.clear();
227
+ ctx.params = EMPTY_PARAMS;
228
+ ctx.body = undefined;
229
+
230
+ // ⚡️ รัน JIT Code (ต้อง replace url.length เป็น urlLen)
231
+ ${routerCode
232
+ .replace(/h(\d+)\(ctx\)/g, 'h$1(ctx, doLog)')
233
+ .replace(/url\.length/g, 'urlLen')}
234
+
235
+ const errorBody = hNotFound();
236
+ const status = errorBody.status || 404;
237
+ doLog(status);
238
+ return Response.json(errorBody, { status });
239
+
240
+ } catch (e) {
241
+ doLog(500);
242
+ return Response.json(hError(e), { status: 500 });
243
+ }
244
+ }
245
+ `;
211
246
 
212
247
  this.hotFetch = new Function(...args, fnBody)(...values);
213
248
  this.compiled = true;
@@ -224,25 +259,32 @@ export class BareJS extends BareRouter {
224
259
  };
225
260
  public name: string = "App";
226
261
 
227
- public listen(port: number = 3000, hostname: string = '0.0.0.0', reusePort: boolean = true) {
262
+ public listen(port?: number, hostname: string = '0.0.0.0', reusePort: boolean = true) {
228
263
  if (!this.compiled) this.compile();
264
+
265
+ // ดึงค่า Config ล่าสุดมาใช้
266
+ const { BARE_CONFIG } = require("./config");
267
+
268
+ // ลำดับความสำคัญ: Parameter > Config File > Default (3000)
269
+ const finalPort = port || BARE_CONFIG.port || 3000;
229
270
  const isProd = process.env.NODE_ENV === 'production';
230
271
 
231
272
  if (!isProd) {
232
273
  console.log(`
233
- \x1b[33m ____ _ ____ \x1b[0m
234
- \x1b[33m | __ ) __ _ _ __ ___ | / ___| \x1b[0m
235
- \x1b[33m | _ \\ / _\` | '__/ _ \\ _ | \\___ \\ \x1b[0m
236
- \x1b[33m | |_) | (_| | | | __/| |_| |___) |\x1b[0m
237
- \x1b[33m |____/ \\__,_|_| \\___| \\___/|____/ \x1b[0m
238
-
239
- \x1b[32m🚀 ${this.name} is running in development mode\x1b[0m
240
- \x1b[90m⚙️ Pool Size: ${this.pool.length} | JIT: Enabled | Port: ${port}\x1b[0m
274
+ \x1b[33m ____ _ _____ \x1b[0m
275
+ \x1b[33m | __ ) __ _ _ __ ___ | | ____|\x1b[0m
276
+ \x1b[33m | _ \\ / _\` | '__/ _ \\ _ | | _| \x1b[0m
277
+ \x1b[33m | |_) | (_| | | | __/| |_| | |___ \x1b[0m
278
+ \x1b[33m |____/ \\__,_|_| \\___| \\___/|_____|\x1b[0m
279
+
280
+ \x1b[32m🚀 ${this.name} is running in development mode\x1b[0m
281
+ \x1b[90m⚙️ Pool Size: ${this.pool.length} | JIT: Enabled | Port: ${finalPort}\x1b[0m
282
+ \x1b[36m🛡️ Hash: ${BARE_CONFIG.hash.algorithm} (${BARE_CONFIG.hash.memoryCost / 1024}MB) | Iterations: ${BARE_CONFIG.hash.timeCost}\x1b[0m
241
283
  `);
242
284
  }
243
285
 
244
286
  const server = Bun.serve({
245
- port,
287
+ port: finalPort,
246
288
  hostname,
247
289
  fetch: this.fetch,
248
290
  reusePort: reusePort,
@@ -0,0 +1,32 @@
1
+ // src/core/config.ts
2
+
3
+ export interface BareConfig {
4
+ hash: {
5
+ algorithm: "argon2id" | "bcrypt";
6
+ memoryCost: number;
7
+ timeCost: number;
8
+ };
9
+ port: number;
10
+
11
+ }
12
+
13
+ export const DEFAULT_CONFIG: BareConfig = {
14
+ hash: {
15
+ algorithm: "argon2id",
16
+ memoryCost: 65536, // 64MB
17
+ timeCost: 2
18
+ },
19
+ port: 3000
20
+ };
21
+
22
+ export let BARE_CONFIG = DEFAULT_CONFIG;
23
+
24
+
25
+ export const initConfig = (userConfig: Partial<BareConfig> = {}) => {
26
+ BARE_CONFIG = {
27
+ ...DEFAULT_CONFIG,
28
+ ...userConfig,
29
+ hash: { ...DEFAULT_CONFIG.hash, ...userConfig.hash }
30
+ };
31
+ return BARE_CONFIG;
32
+ };