@coderbuzz/ken 0.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.
@@ -0,0 +1,269 @@
1
+ import {
2
+ EMPTY_PARAMS,
3
+ EMPTY_QUERY
4
+ } from "./chunk-DPU3PBLP.js";
5
+
6
+ // src/context/base.ts
7
+ var BaseContext = class {
8
+ _schema;
9
+ _rawParams;
10
+ _getRemoteInfo;
11
+ // Cache fields (initialized for V8 monomorphic shape)
12
+ _params = null;
13
+ _query = null;
14
+ _headers = null;
15
+ _cookies = null;
16
+ _json = null;
17
+ _text = null;
18
+ _form = null;
19
+ _remoteInfo = null;
20
+ _onFinishCallbacks = null;
21
+ _setCookies = null;
22
+ // State is managed as plain object, typed via Context interface
23
+ state = {};
24
+ constructor(params, getRemoteInfo, schema) {
25
+ this._rawParams = params;
26
+ this._getRemoteInfo = getRemoteInfo;
27
+ this._schema = schema;
28
+ this.state = {};
29
+ }
30
+ /**
31
+ * Register callback to be called after handler finishes (success or failure).
32
+ */
33
+ onFinish(callback) {
34
+ if (this._onFinishCallbacks === null) {
35
+ this._onFinishCallbacks = [];
36
+ }
37
+ this._onFinishCallbacks.push(callback);
38
+ }
39
+ /**
40
+ * Set a cookie to be sent with the response.
41
+ * Cookies are collected and applied to the response via onFinish callback.
42
+ *
43
+ * @param name - Cookie name
44
+ * @param value - Cookie value
45
+ * @param options - Cookie options (path, domain, maxAge, expires, httpOnly, secure, sameSite)
46
+ */
47
+ setCookie(name, value, options) {
48
+ if (this._setCookies === null) {
49
+ this._setCookies = [];
50
+ }
51
+ let cookie = `${name}=${value}`;
52
+ if (options) {
53
+ if (options.path) cookie += `; Path=${options.path}`;
54
+ if (options.domain) cookie += `; Domain=${options.domain}`;
55
+ if (options.maxAge !== void 0) cookie += `; Max-Age=${options.maxAge}`;
56
+ if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
57
+ if (options.httpOnly) cookie += "; HttpOnly";
58
+ if (options.secure) cookie += "; Secure";
59
+ if (options.sameSite) cookie += `; SameSite=${options.sameSite}`;
60
+ }
61
+ this._setCookies.push(cookie);
62
+ if (this._setCookies.length === 1) {
63
+ const setCookies = this._setCookies;
64
+ this.onFinish((resp) => {
65
+ if (resp !== void 0) {
66
+ const headers = resp.headers;
67
+ for (let i = 0; i < setCookies.length; i++) {
68
+ headers.append("Set-Cookie", setCookies[i]);
69
+ }
70
+ }
71
+ });
72
+ }
73
+ }
74
+ /**
75
+ * Internal: Execute all registered onFinish callbacks.
76
+ *
77
+ * Error Handling Strategy (Fastify/Elysia pattern):
78
+ * - Each callback is individually try-catch wrapped
79
+ * - Errors are logged but don't stop remaining callbacks
80
+ *
81
+ * Execution Order: FIFO (First In First Out)
82
+ */
83
+ _executeFinishCallbacks(resp) {
84
+ const callbacks = this._onFinishCallbacks;
85
+ if (callbacks === null) return;
86
+ const len = callbacks.length;
87
+ if (len === 1) {
88
+ try {
89
+ callbacks[0](resp);
90
+ } catch (err) {
91
+ console.error("Error in onFinish callback:", err);
92
+ }
93
+ this._onFinishCallbacks = null;
94
+ return;
95
+ }
96
+ for (let i = 0; i < len; i++) {
97
+ try {
98
+ callbacks[i](resp);
99
+ } catch (err) {
100
+ console.error(`Error in onFinish callback ${i + 1}/${len}:`, err);
101
+ }
102
+ }
103
+ this._onFinishCallbacks = null;
104
+ }
105
+ /**
106
+ * Remote info with proxy header detection + runtime fallback
107
+ */
108
+ get remoteInfo() {
109
+ if (this._remoteInfo) return this._remoteInfo;
110
+ let address = "";
111
+ let port = 0;
112
+ const headers = this._getRawHeaders();
113
+ const getHeader = (key) => {
114
+ if (typeof headers.get === "function") {
115
+ return headers.get(key);
116
+ }
117
+ const val = headers[key];
118
+ return Array.isArray(val) ? val[0] : val;
119
+ };
120
+ let ip = getHeader("cf-connecting-ip");
121
+ if (!ip) {
122
+ ip = getHeader("x-real-ip");
123
+ }
124
+ if (!ip) {
125
+ ip = getHeader("x-forwarded-for");
126
+ if (ip) {
127
+ const commaIndex = ip.indexOf(",");
128
+ ip = commaIndex === -1 ? ip : ip.substring(0, commaIndex);
129
+ }
130
+ }
131
+ if (!ip) {
132
+ ip = getHeader("true-client-ip");
133
+ }
134
+ if (ip) {
135
+ address = ip.trim();
136
+ } else {
137
+ const info = this._getRemoteInfo();
138
+ address = info.address;
139
+ port = info.port;
140
+ }
141
+ this._remoteInfo = { address, port };
142
+ return this._remoteInfo;
143
+ }
144
+ /**
145
+ * Lazily parses and validates route parameters.
146
+ */
147
+ get params() {
148
+ let cached = this._params;
149
+ if (cached !== null) return cached;
150
+ const schema = this._schema?.params;
151
+ if (schema !== void 0) {
152
+ const rawParams = this._rawParams;
153
+ const result = {};
154
+ for (const key in schema) {
155
+ const validator = schema[key];
156
+ const rawValue = rawParams[key];
157
+ result[key] = validator(rawValue);
158
+ }
159
+ this._params = result;
160
+ return result;
161
+ }
162
+ cached = Object.keys(this._rawParams).length === 0 ? EMPTY_PARAMS : this._rawParams;
163
+ this._params = cached;
164
+ return cached;
165
+ }
166
+ /**
167
+ * Lazily parses and validates query parameters.
168
+ * Heavily optimized query parser.
169
+ */
170
+ get query() {
171
+ let cached = this._query;
172
+ if (cached !== null) return cached;
173
+ const url = this._getRawUrl();
174
+ const queryIndex = url.indexOf("?");
175
+ if (queryIndex === -1) {
176
+ cached = EMPTY_QUERY;
177
+ this._query = cached;
178
+ return cached;
179
+ }
180
+ const rawQuery = {};
181
+ const queryStr = url.substring(queryIndex + 1);
182
+ const hashIndex = queryStr.indexOf("#");
183
+ const cleanQuery = hashIndex === -1 ? queryStr : queryStr.substring(0, hashIndex);
184
+ let pairStart = 0;
185
+ let pairEnd = 0;
186
+ const len = cleanQuery.length;
187
+ while (pairEnd <= len) {
188
+ while (pairEnd < len && cleanQuery.charCodeAt(pairEnd) !== 38) pairEnd++;
189
+ if (pairEnd > pairStart) {
190
+ let eqIndex = pairStart;
191
+ while (eqIndex < pairEnd && cleanQuery.charCodeAt(eqIndex) !== 61) eqIndex++;
192
+ if (eqIndex === pairEnd) {
193
+ const key = cleanQuery.substring(pairStart, pairEnd);
194
+ rawQuery[key.indexOf("%") !== -1 ? decodeURIComponent(key) : key] = "";
195
+ } else {
196
+ const rawKey = cleanQuery.substring(pairStart, eqIndex);
197
+ const rawValue = cleanQuery.substring(eqIndex + 1, pairEnd);
198
+ const key = rawKey.indexOf("%") !== -1 ? decodeURIComponent(rawKey) : rawKey;
199
+ const value = rawValue.indexOf("%") !== -1 ? decodeURIComponent(rawValue) : rawValue;
200
+ rawQuery[key] = value;
201
+ }
202
+ }
203
+ pairStart = ++pairEnd;
204
+ }
205
+ const schema = this._schema?.query;
206
+ if (schema !== void 0) {
207
+ const result = {};
208
+ for (const key in schema) {
209
+ const validator = schema[key];
210
+ result[key] = validator(rawQuery[key]);
211
+ }
212
+ this._query = result;
213
+ return result;
214
+ }
215
+ this._query = rawQuery;
216
+ return rawQuery;
217
+ }
218
+ /**
219
+ * Lazily parses and validates cookies.
220
+ * Optimized parsing without split() allocation.
221
+ */
222
+ get cookies() {
223
+ const cached = this._cookies;
224
+ if (cached !== null) return cached;
225
+ const headers = this._getRawHeaders();
226
+ const cookieHeader = typeof headers.get === "function" ? headers.get("cookie") : headers["cookie"];
227
+ const cookies = cookieHeader ? {} : EMPTY_QUERY;
228
+ if (cookieHeader) {
229
+ const len = cookieHeader.length;
230
+ let start = 0;
231
+ let end = 0;
232
+ while (end <= len) {
233
+ while (end < len && cookieHeader.charCodeAt(end) !== 59) end++;
234
+ if (end > start) {
235
+ let eqIndex = start;
236
+ while (eqIndex < end && cookieHeader.charCodeAt(eqIndex) !== 61) eqIndex++;
237
+ if (eqIndex < end) {
238
+ while (start < eqIndex && cookieHeader.charCodeAt(start) === 32) start++;
239
+ let keyEnd = eqIndex;
240
+ while (keyEnd > start && cookieHeader.charCodeAt(keyEnd - 1) === 32) keyEnd--;
241
+ let valStart = eqIndex + 1;
242
+ while (valStart < end && cookieHeader.charCodeAt(valStart) === 32) valStart++;
243
+ let valEnd = end;
244
+ while (valEnd > valStart && cookieHeader.charCodeAt(valEnd - 1) === 32) valEnd--;
245
+ cookies[cookieHeader.substring(start, keyEnd)] = cookieHeader.substring(valStart, valEnd);
246
+ }
247
+ }
248
+ start = ++end;
249
+ }
250
+ }
251
+ const schema = this._schema?.cookies;
252
+ if (schema !== void 0) {
253
+ const result = {};
254
+ for (const key in schema) {
255
+ const validator = schema[key];
256
+ result[key] = validator(cookies[key]);
257
+ }
258
+ this._cookies = result;
259
+ return result;
260
+ }
261
+ this._cookies = cookies;
262
+ return cookies;
263
+ }
264
+ };
265
+
266
+ export {
267
+ BaseContext
268
+ };
269
+ //# sourceMappingURL=chunk-2MK26YDD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context/base.ts"],"sourcesContent":["/**\n * Ken Framework - Base Context\n * Shared parsing/validation logic for all Context implementations\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport {\n type Context,\n type Schema,\n type RemoteInfo,\n type GetRemoteInfo,\n type InferObject,\n type InferValidator,\n type ParamsFromPath,\n EMPTY_PARAMS,\n EMPTY_QUERY,\n} from './types';\n\n/**\n * Headers-like interface for both Web Headers and Node.js headers\n */\nexport interface HeadersLike {\n get?(key: string): string | null;\n [key: string]: any;\n}\n\n/**\n * BaseContext - Shared parsing/validation logic\n * Runtime-specific classes extend this\n * \n * CRITICAL: All contexts receive getRemoteInfo from runtime\n * Used as fallback when proxy headers are missing\n * \n * @template S - Schema type for validation\n * @template Path - Route path string for param extraction\n * @template TState - Accumulated state from middleware\n */\nexport abstract class BaseContext<S extends Schema = {}, Path extends string = string, TState = {}>\n implements Context<S, Path, TState> {\n\n protected readonly _schema: S | undefined;\n protected readonly _rawParams: Record<string, string>;\n protected readonly _getRemoteInfo: GetRemoteInfo;\n\n // Cache fields (initialized for V8 monomorphic shape)\n protected _params: any = null;\n protected _query: any = null;\n protected _headers: any = null;\n protected _cookies: any = null;\n protected _json: any = null;\n protected _text: any = null;\n protected _form: any = null;\n protected _remoteInfo: RemoteInfo | null = null;\n protected _onFinishCallbacks: Array<(resp?: Response) => void> | null = null;\n protected _setCookies: string[] | null = null;\n\n // State is managed as plain object, typed via Context interface\n public state: any = {};\n\n constructor(\n params: Record<string, string>,\n getRemoteInfo: GetRemoteInfo,\n schema?: S\n ) {\n this._rawParams = params;\n this._getRemoteInfo = getRemoteInfo;\n this._schema = schema;\n // Re-initialize state for consistent monomorphic shape\n this.state = {} as any;\n }\n\n // Abstract methods - runtime-specific\n abstract get url(): string;\n abstract get method(): string;\n abstract get body(): any;\n protected abstract _getRawHeaders(): HeadersLike;\n protected abstract _getRawUrl(): string;\n\n /**\n * Register callback to be called after handler finishes (success or failure).\n */\n onFinish(callback: (resp?: Response) => void): void {\n if (this._onFinishCallbacks === null) {\n this._onFinishCallbacks = [];\n }\n this._onFinishCallbacks.push(callback);\n }\n\n /**\n * Set a cookie to be sent with the response.\n * Cookies are collected and applied to the response via onFinish callback.\n * \n * @param name - Cookie name\n * @param value - Cookie value\n * @param options - Cookie options (path, domain, maxAge, expires, httpOnly, secure, sameSite)\n */\n setCookie(\n name: string,\n value: string,\n options?: {\n path?: string;\n domain?: string;\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'Strict' | 'Lax' | 'None';\n }\n ): void {\n if (this._setCookies === null) {\n this._setCookies = [];\n }\n\n // Build cookie string\n let cookie = `${name}=${value}`;\n\n if (options) {\n if (options.path) cookie += `; Path=${options.path}`;\n if (options.domain) cookie += `; Domain=${options.domain}`;\n if (options.maxAge !== undefined) cookie += `; Max-Age=${options.maxAge}`;\n if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;\n if (options.httpOnly) cookie += '; HttpOnly';\n if (options.secure) cookie += '; Secure';\n if (options.sameSite) cookie += `; SameSite=${options.sameSite}`;\n }\n\n this._setCookies.push(cookie);\n\n // Register onFinish callback on first cookie (length === 1)\n if (this._setCookies.length === 1) {\n const setCookies = this._setCookies;\n this.onFinish((resp) => {\n if (resp !== undefined) {\n // Directly modify response headers (Headers objects are mutable)\n const headers = resp.headers;\n for (let i = 0; i < setCookies.length; i++) {\n headers.append('Set-Cookie', setCookies[i]);\n }\n }\n });\n }\n }\n\n /**\n * Internal: Execute all registered onFinish callbacks.\n * \n * Error Handling Strategy (Fastify/Elysia pattern):\n * - Each callback is individually try-catch wrapped\n * - Errors are logged but don't stop remaining callbacks\n * \n * Execution Order: FIFO (First In First Out)\n */\n _executeFinishCallbacks(resp?: Response): void {\n const callbacks = this._onFinishCallbacks;\n if (callbacks === null) return;\n\n const len = callbacks.length;\n\n // Fast path: single callback (most common case)\n if (len === 1) {\n try {\n callbacks[0](resp);\n } catch (err) {\n console.error('Error in onFinish callback:', err);\n }\n this._onFinishCallbacks = null;\n return;\n }\n\n // Multiple callbacks: execute all even if one fails\n for (let i = 0; i < len; i++) {\n try {\n callbacks[i](resp);\n } catch (err) {\n console.error(`Error in onFinish callback ${i + 1}/${len}:`, err);\n }\n }\n\n this._onFinishCallbacks = null;\n }\n\n /**\n * Remote info with proxy header detection + runtime fallback\n */\n get remoteInfo(): RemoteInfo {\n if (this._remoteInfo) return this._remoteInfo;\n\n let address = '';\n let port = 0;\n\n // Check proxy headers in priority order\n const headers = this._getRawHeaders();\n const getHeader = (key: string): string | null | undefined => {\n if (typeof headers.get === 'function') {\n return headers.get(key);\n }\n // Node.js headers object\n const val = headers[key];\n return Array.isArray(val) ? val[0] : val;\n };\n\n // 1. CF-Connecting-IP (Cloudflare)\n let ip = getHeader('cf-connecting-ip');\n if (!ip) {\n // 2. X-Real-IP (nginx)\n ip = getHeader('x-real-ip');\n }\n if (!ip) {\n // 3. X-Forwarded-For (standard proxy, first IP)\n ip = getHeader('x-forwarded-for');\n if (ip) {\n const commaIndex = ip.indexOf(',');\n ip = commaIndex === -1 ? ip : ip.substring(0, commaIndex);\n }\n }\n if (!ip) {\n // 4. True-Client-IP (Akamai)\n ip = getHeader('true-client-ip');\n }\n\n if (ip) {\n address = ip.trim();\n } else {\n // 5. Fallback to runtime-provided getRemoteInfo\n const info = this._getRemoteInfo();\n address = info.address;\n port = info.port;\n }\n\n this._remoteInfo = { address, port };\n return this._remoteInfo;\n }\n\n /**\n * Lazily parses and validates route parameters.\n */\n get params(): InferObject<S['params'], ParamsFromPath<Path>> {\n let cached = this._params;\n if (cached !== null) return cached;\n\n const schema = this._schema?.params;\n if (schema !== undefined) {\n const rawParams = this._rawParams;\n const result: any = {};\n\n for (const key in schema) {\n const validator = schema[key];\n const rawValue = rawParams[key];\n result[key] = validator(rawValue);\n }\n\n this._params = result;\n return result;\n }\n\n // No schema: return raw params (reuse if empty)\n cached = Object.keys(this._rawParams).length === 0 ? EMPTY_PARAMS : this._rawParams;\n this._params = cached;\n return cached as any;\n }\n\n /**\n * Lazily parses and validates query parameters.\n * Heavily optimized query parser.\n */\n get query(): InferObject<S['query'], Record<string, string>> {\n let cached = this._query;\n if (cached !== null) return cached;\n\n const url = this._getRawUrl();\n const queryIndex = url.indexOf('?');\n\n // Fast path: no query string\n if (queryIndex === -1) {\n cached = EMPTY_QUERY;\n this._query = cached;\n return cached as any;\n }\n\n // Parse query string with minimal allocations\n const rawQuery: Record<string, string> = {};\n const queryStr = url.substring(queryIndex + 1);\n // Remove hash if present\n const hashIndex = queryStr.indexOf('#');\n const cleanQuery = hashIndex === -1 ? queryStr : queryStr.substring(0, hashIndex);\n\n let pairStart = 0;\n let pairEnd = 0;\n const len = cleanQuery.length;\n\n // Manual loop is faster than split('&')\n while (pairEnd <= len) {\n while (pairEnd < len && cleanQuery.charCodeAt(pairEnd) !== 38) pairEnd++; // 38 = '&'\n\n if (pairEnd > pairStart) {\n let eqIndex = pairStart;\n while (eqIndex < pairEnd && cleanQuery.charCodeAt(eqIndex) !== 61) eqIndex++; // 61 = '='\n\n if (eqIndex === pairEnd) {\n const key = cleanQuery.substring(pairStart, pairEnd);\n rawQuery[key.indexOf('%') !== -1 ? decodeURIComponent(key) : key] = '';\n } else {\n const rawKey = cleanQuery.substring(pairStart, eqIndex);\n const rawValue = cleanQuery.substring(eqIndex + 1, pairEnd);\n const key = rawKey.indexOf('%') !== -1 ? decodeURIComponent(rawKey) : rawKey;\n const value = rawValue.indexOf('%') !== -1 ? decodeURIComponent(rawValue) : rawValue;\n rawQuery[key] = value;\n }\n }\n\n pairStart = ++pairEnd;\n }\n\n // Validation path\n const schema = this._schema?.query;\n if (schema !== undefined) {\n const result: any = {};\n for (const key in schema) {\n const validator = schema[key];\n result[key] = validator(rawQuery[key]);\n }\n this._query = result;\n return result;\n }\n\n this._query = rawQuery;\n return rawQuery as any;\n }\n\n /**\n * Lazily parses and validates cookies.\n * Optimized parsing without split() allocation.\n */\n get cookies(): InferObject<S['cookies'], Record<string, string>> {\n const cached = this._cookies;\n if (cached !== null) return cached;\n\n const headers = this._getRawHeaders();\n const cookieHeader = typeof headers.get === 'function'\n ? headers.get('cookie')\n : headers['cookie'];\n\n const cookies: Record<string, string> = cookieHeader ? {} : EMPTY_QUERY;\n\n if (cookieHeader) {\n const len = cookieHeader.length;\n let start = 0;\n let end = 0;\n\n while (end <= len) {\n while (end < len && cookieHeader.charCodeAt(end) !== 59) end++; // 59 = ';'\n\n if (end > start) {\n let eqIndex = start;\n while (eqIndex < end && cookieHeader.charCodeAt(eqIndex) !== 61) eqIndex++; // 61 = '='\n\n if (eqIndex < end) {\n // Trim manually\n while (start < eqIndex && cookieHeader.charCodeAt(start) === 32) start++;\n let keyEnd = eqIndex;\n while (keyEnd > start && cookieHeader.charCodeAt(keyEnd - 1) === 32) keyEnd--;\n\n let valStart = eqIndex + 1;\n while (valStart < end && cookieHeader.charCodeAt(valStart) === 32) valStart++;\n let valEnd = end;\n while (valEnd > valStart && cookieHeader.charCodeAt(valEnd - 1) === 32) valEnd--;\n\n cookies[cookieHeader.substring(start, keyEnd)] = cookieHeader.substring(valStart, valEnd);\n }\n }\n\n start = ++end;\n }\n }\n\n const schema = this._schema?.cookies;\n if (schema !== undefined) {\n const result: any = {};\n for (const key in schema) {\n const validator = schema[key];\n result[key] = validator(cookies[key]);\n }\n this._cookies = result;\n return result;\n }\n\n this._cookies = cookies;\n return cookies as any;\n\n }\n\n // Abstract body parsing methods - implemented by subclasses\n abstract get headers(): InferObject<S['headers'], Record<string, string>>;\n abstract get json(): Promise<InferValidator<S['json'], any>>;\n abstract get text(): Promise<InferValidator<S['text'], string>>;\n abstract get form(): Promise<InferObject<S['form'], FormData>>;\n}\n"],"mappings":"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","names":[]}