kempo-server 1.8.2 → 1.8.3

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.
@@ -1 +1 @@
1
- export function createResponseWrapper(response){let sent=!1;const enhancedResponse={...response,status(code){if(sent)throw new Error("Cannot set status after response has been sent");return response.statusCode=code,enhancedResponse},set(field,value){if(sent)throw new Error("Cannot set headers after response has been sent");return"object"==typeof field?Object.entries(field).forEach(([key,val])=>{response.setHeader(key,val)}):response.setHeader(field,value),enhancedResponse},get:field=>response.getHeader(field),type(contentType){if(sent)throw new Error("Cannot set content type after response has been sent");const mimeType={html:"text/html",json:"application/json",xml:"application/xml",text:"text/plain",css:"text/css",js:"application/javascript"}[contentType]||contentType;return response.setHeader("Content-Type",mimeType),enhancedResponse},json(obj){if(sent)throw new Error("Cannot send response after it has already been sent");sent=!0,response.setHeader("Content-Type","application/json");try{const jsonString=JSON.stringify(obj);response.end(jsonString)}catch(error){throw new Error("Failed to stringify object to JSON")}return enhancedResponse},send(data){if(sent)throw new Error("Cannot send response after it has already been sent");return sent=!0,null==data?(response.end(),enhancedResponse):("object"==typeof data?(response.setHeader("Content-Type","application/json"),response.end(JSON.stringify(data))):"string"==typeof data?(response.getHeader("Content-Type")||response.setHeader("Content-Type","text/html"),response.end(data)):Buffer.isBuffer(data)?response.end(data):(response.getHeader("Content-Type")||response.setHeader("Content-Type","text/plain"),response.end(String(data))),enhancedResponse)},html(htmlString){if(sent)throw new Error("Cannot send response after it has already been sent");return sent=!0,response.setHeader("Content-Type","text/html"),response.end(htmlString),enhancedResponse},text(textString){if(sent)throw new Error("Cannot send response after it has already been sent");return sent=!0,response.setHeader("Content-Type","text/plain"),response.end(String(textString)),enhancedResponse},redirect(url,statusCode=302){if(sent)throw new Error("Cannot redirect after response has been sent");return sent=!0,response.statusCode=statusCode,response.setHeader("Location",url),response.end(),enhancedResponse},cookie(name,value,options={}){if(sent)throw new Error("Cannot set cookies after response has been sent");let cookieString=`${name}=${encodeURIComponent(value)}`;options.maxAge&&(cookieString+=`; Max-Age=${options.maxAge}`),options.domain&&(cookieString+=`; Domain=${options.domain}`),options.path&&(cookieString+=`; Path=${options.path}`),options.secure&&(cookieString+="; Secure"),options.httpOnly&&(cookieString+="; HttpOnly"),options.sameSite&&(cookieString+=`; SameSite=${options.sameSite}`);const existingCookies=response.getHeader("Set-Cookie")||[],cookies=Array.isArray(existingCookies)?existingCookies:[existingCookies];return cookies.push(cookieString),response.setHeader("Set-Cookie",cookies),enhancedResponse},clearCookie(name,options={}){return this.cookie(name,"",{...options,maxAge:0})}};return enhancedResponse}export default createResponseWrapper;
1
+ export function createResponseWrapper(response){let sent=!1;const enhancedResponse={...response,status(code){if(sent)throw new Error("Cannot set status after response has been sent");return response.statusCode=code,enhancedResponse},set(field,value){if(sent)throw new Error("Cannot set headers after response has been sent");return"object"==typeof field?Object.entries(field).forEach(([key,val])=>{response.setHeader(key,val)}):response.setHeader(field,value),enhancedResponse},get:field=>response.getHeader(field),type(contentType){if(sent)throw new Error("Cannot set content type after response has been sent");const mimeType={html:"text/html",json:"application/json",xml:"application/xml",text:"text/plain",css:"text/css",js:"application/javascript"}[contentType]||contentType;return response.setHeader("Content-Type",mimeType),enhancedResponse},json(obj){if(sent)throw new Error("Cannot send response after it has already been sent");sent=!0,response.setHeader("Content-Type","application/json");try{const jsonString=JSON.stringify(obj);response.end(jsonString)}catch(error){throw new Error("Failed to stringify object to JSON")}return enhancedResponse},send(data){if(sent)throw new Error("Cannot send response after it has already been sent");if(sent=!0,null==data)return response.end(),enhancedResponse;if("object"==typeof data)response.setHeader("Content-Type","application/json"),response.end(JSON.stringify(data));else if("string"==typeof data){if(response.getHeader("Content-Type")){const contentType=response.getHeader("Content-Type");contentType&&contentType.startsWith("text/")&&!contentType.includes("charset=")&&response.setHeader("Content-Type",`${contentType}; charset=utf-8`)}else response.setHeader("Content-Type","text/html; charset=utf-8");response.end(data)}else if(Buffer.isBuffer(data))response.end(data);else{if(response.getHeader("Content-Type")){const contentType=response.getHeader("Content-Type");contentType&&contentType.startsWith("text/")&&!contentType.includes("charset=")&&response.setHeader("Content-Type",`${contentType}; charset=utf-8`)}else response.setHeader("Content-Type","text/plain; charset=utf-8");response.end(String(data))}return enhancedResponse},html(htmlString){if(sent)throw new Error("Cannot send response after it has already been sent");return sent=!0,response.setHeader("Content-Type","text/html; charset=utf-8"),response.end(htmlString),enhancedResponse},text(textString){if(sent)throw new Error("Cannot send response after it has already been sent");return sent=!0,response.setHeader("Content-Type","text/plain; charset=utf-8"),response.end(String(textString)),enhancedResponse},redirect(url,statusCode=302){if(sent)throw new Error("Cannot redirect after response has been sent");return sent=!0,response.statusCode=statusCode,response.setHeader("Location",url),response.end(),enhancedResponse},cookie(name,value,options={}){if(sent)throw new Error("Cannot set cookies after response has been sent");let cookieString=`${name}=${encodeURIComponent(value)}`;options.maxAge&&(cookieString+=`; Max-Age=${options.maxAge}`),options.domain&&(cookieString+=`; Domain=${options.domain}`),options.path&&(cookieString+=`; Path=${options.path}`),options.secure&&(cookieString+="; Secure"),options.httpOnly&&(cookieString+="; HttpOnly"),options.sameSite&&(cookieString+=`; SameSite=${options.sameSite}`);const existingCookies=response.getHeader("Set-Cookie")||[],cookies=Array.isArray(existingCookies)?existingCookies:[existingCookies];return cookies.push(cookieString),response.setHeader("Set-Cookie",cookies),enhancedResponse},clearCookie(name,options={}){return this.cookie(name,"",{...options,maxAge:0})}};return enhancedResponse}export default createResponseWrapper;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kempo-server",
3
3
  "type": "module",
4
- "version": "1.8.2",
4
+ "version": "1.8.3",
5
5
  "description": "A lightweight, zero-dependency, file based routing server.",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
@@ -103,7 +103,13 @@ export function createResponseWrapper(response) {
103
103
  } else if (typeof data === 'string') {
104
104
  // If Content-Type not set, default to text/html for strings
105
105
  if (!response.getHeader('Content-Type')) {
106
- response.setHeader('Content-Type', 'text/html');
106
+ response.setHeader('Content-Type', 'text/html; charset=utf-8');
107
+ } else {
108
+ // If Content-Type is set and is a text type, add charset if not present
109
+ const contentType = response.getHeader('Content-Type');
110
+ if (contentType && contentType.startsWith('text/') && !contentType.includes('charset=')) {
111
+ response.setHeader('Content-Type', `${contentType}; charset=utf-8`);
112
+ }
107
113
  }
108
114
  response.end(data);
109
115
  } else if (Buffer.isBuffer(data)) {
@@ -112,7 +118,13 @@ export function createResponseWrapper(response) {
112
118
  } else {
113
119
  // Convert to string
114
120
  if (!response.getHeader('Content-Type')) {
115
- response.setHeader('Content-Type', 'text/plain');
121
+ response.setHeader('Content-Type', 'text/plain; charset=utf-8');
122
+ } else {
123
+ // If Content-Type is set and is a text type, add charset if not present
124
+ const contentType = response.getHeader('Content-Type');
125
+ if (contentType && contentType.startsWith('text/') && !contentType.includes('charset=')) {
126
+ response.setHeader('Content-Type', `${contentType}; charset=utf-8`);
127
+ }
116
128
  }
117
129
  response.end(String(data));
118
130
  }
@@ -127,7 +139,7 @@ export function createResponseWrapper(response) {
127
139
  }
128
140
 
129
141
  sent = true;
130
- response.setHeader('Content-Type', 'text/html');
142
+ response.setHeader('Content-Type', 'text/html; charset=utf-8');
131
143
  response.end(htmlString);
132
144
  return enhancedResponse;
133
145
  },
@@ -139,7 +151,7 @@ export function createResponseWrapper(response) {
139
151
  }
140
152
 
141
153
  sent = true;
142
- response.setHeader('Content-Type', 'text/plain');
154
+ response.setHeader('Content-Type', 'text/plain; charset=utf-8');
143
155
  response.end(String(textString));
144
156
  return enhancedResponse;
145
157
  },
@@ -29,7 +29,7 @@ export default {
29
29
  const res1 = createMockRes();
30
30
  createResponseWrapper(res1).send('hello');
31
31
  // Content-Type defaults to text/html for string when not set
32
- if(res1.getHeader('Content-Type') !== 'text/html') return fail('string content-type');
32
+ if(res1.getHeader('Content-Type') !== 'text/html; charset=utf-8') return fail('string content-type');
33
33
  if(res1.getBody().toString() !== 'hello') return fail('string body');
34
34
 
35
35
  const res2 = createMockRes();
@@ -51,11 +51,11 @@ export default {
51
51
  'html and text helpers': async ({pass, fail}) => {
52
52
  const r1 = createMockRes();
53
53
  createResponseWrapper(r1).html('<h1>Ok</h1>');
54
- if(r1.getHeader('Content-Type') !== 'text/html') return fail('html type');
54
+ if(r1.getHeader('Content-Type') !== 'text/html; charset=utf-8') return fail('html type');
55
55
 
56
56
  const r2 = createMockRes();
57
57
  createResponseWrapper(r2).text('plain');
58
- if(r2.getHeader('Content-Type') !== 'text/plain') return fail('text type');
58
+ if(r2.getHeader('Content-Type') !== 'text/plain; charset=utf-8') return fail('text type');
59
59
 
60
60
  pass('helpers');
61
61
  },