kempo-server 3.0.2 → 3.0.4
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/CHANGELOG.md +43 -0
- package/dist/templating/index.js +1 -1
- package/dist/templating/parse.js +1 -1
- package/docs/caching.html +18 -13
- package/docs/cli-utils.html +16 -13
- package/docs/configuration.html +18 -13
- package/docs/examples.html +16 -13
- package/docs/fs-utils.html +16 -13
- package/docs/getting-started.html +16 -13
- package/docs/index.html +16 -13
- package/docs/middleware.html +16 -13
- package/docs/request-response.html +18 -13
- package/docs/routing.html +16 -13
- package/docs/templating.html +87 -31
- package/docs-src/advanced-links.global.html +10 -0
- package/docs-src/caching.page.html +2 -0
- package/docs-src/configuration.page.html +2 -0
- package/docs-src/getting-started-links.global.html +7 -0
- package/docs-src/index.page.html +3 -0
- package/docs-src/nav.fragment.html +1 -13
- package/docs-src/request-response.page.html +2 -0
- package/docs-src/templating.page.html +71 -18
- package/package.json +2 -2
- package/src/templating/index.js +37 -4
- package/src/templating/parse.js +28 -5
- package/tests/templating-parse.node-test.js +43 -9
- package/tests/templating-render.node-test.js +91 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `kempo-server` are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [3.0.0] - 2026-04-09
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- **Config file format changed from `.config.json` to `.config.js`.** The server now looks for `.config.js` (ES module with a default export) by default, with `.config.json` as a fallback.
|
|
10
|
+
- **Templating file extensions are now disallowed from being served.** Files ending in `.template.html`, `.fragment.html`, and `.page.html` are blocked by default via `disallowedRegex`.
|
|
11
|
+
- **`.config` disallowed pattern replaced** with more specific `.config.js` and `.config.json` patterns.
|
|
12
|
+
|
|
13
|
+
**Migration:**
|
|
14
|
+
```javascript
|
|
15
|
+
// Before (.config.json)
|
|
16
|
+
{ "port": 3000 }
|
|
17
|
+
|
|
18
|
+
// After (.config.js)
|
|
19
|
+
export default { port: 3000 };
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **Templating system** with support for templates (`.template.html`), pages (`.page.html`), and fragments (`.fragment.html`). Includes slot-based composition, nested fragment inclusion, and variable interpolation.
|
|
25
|
+
- `templating` config section with `preRender`, `ssr`, `ssrPriority`, `globals`, `state`, and `maxFragmentDepth` options.
|
|
26
|
+
- `kempo-server-render` CLI command for pre-rendering templated pages.
|
|
27
|
+
- `kempo-server/templating` module export.
|
|
28
|
+
- Wildcard route patterns now normalize leading slashes for consistent matching.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## [2.2.0] - 2026-04-08
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- `rescan` utility module (`kempo-server/rescan`) that exposes a programmatic API to trigger file rescans. Provides `onRescan` for listening and a default export function that returns a promise resolving with the new file count.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## [2.1.1] - 2026-04-05
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- Dynamic custom routes with `[param]` directory segments now resolve correctly. A new `walkDynamic` traversal walks the directory tree matching literal and `[param]` directories, passing extracted params through to route handlers.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
5
48
|
## [2.1.0] - 2026-04-05
|
|
6
49
|
|
|
7
50
|
### Added
|
package/dist/templating/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFile,writeFile,mkdir,readdir}from"fs/promises";import path from"path";import{extractAttrs,extractContentBlocks,replaceLocations,resolveVars,resolveIfs,resolveForeach,resolveFragmentTags}from"./parse.js";import{readFileSync,statSync}from"fs";const findFileUpSync=(filename,startDir,rootDir)=>{let dir=startDir;const root=path.resolve(rootDir);for(;;){const candidate=path.join(dir,filename);try{return statSync(candidate),candidate}catch(e){}if(path.resolve(dir)===root)return null;const parent=path.dirname(dir);if(parent===dir)return null;dir=parent}},loadVersion=rootDir=>{try{return JSON.parse(readFileSync(path.join(rootDir,"package.json"),"utf8")).version||""}catch(e){return""}},renderPage=async(pageFilePath,rootDir,globals={},state={},maxDepth=10)=>{const pageContent=await readFile(pageFilePath,"utf8"),pageTagMatch=pageContent.match(/^[\s\S]*?<page\s([^>]*)>/);if(!pageTagMatch)throw new Error(`Invalid page file: missing <page> root element in ${pageFilePath}`);const pageAttrs=extractAttrs(pageTagMatch[1]),templateName=pageAttrs.template||"default";delete pageAttrs.template;const
|
|
1
|
+
import{readFile,writeFile,mkdir,readdir}from"fs/promises";import path from"path";import{extractAttrs,extractContentBlocks,mergeContentBlocks,replaceLocations,resolveVars,resolveIfs,resolveForeach,resolveFragmentTags}from"./parse.js";import{readFileSync,statSync}from"fs";const findFileUpSync=(filename,startDir,rootDir)=>{let dir=startDir;const root=path.resolve(rootDir);for(;;){const candidate=path.join(dir,filename);try{return statSync(candidate),candidate}catch(e){}if(path.resolve(dir)===root)return null;const parent=path.dirname(dir);if(parent===dir)return null;dir=parent}},loadVersion=rootDir=>{try{return JSON.parse(readFileSync(path.join(rootDir,"package.json"),"utf8")).version||""}catch(e){return""}},walkGlobals=async dir=>{const entries=await readdir(dir,{withFileTypes:!0}),results=[];for(const entry of entries){const full=path.join(dir,entry.name);entry.isDirectory()?results.push(...await walkGlobals(full)):entry.name.endsWith(".global.html")&&results.push(full)}return results},loadGlobalContent=async rootDir=>{const files=await walkGlobals(rootDir),maps=await Promise.all(files.map(async f=>extractContentBlocks(await readFile(f,"utf8"))));return mergeContentBlocks(...maps)},renderPage=async(pageFilePath,rootDir,globals={},state={},maxDepth=10,preloadedGlobalContent=null)=>{const pageContent=await readFile(pageFilePath,"utf8"),pageTagMatch=pageContent.match(/^[\s\S]*?<page\s([^>]*)>/);if(!pageTagMatch)throw new Error(`Invalid page file: missing <page> root element in ${pageFilePath}`);const pageAttrs=extractAttrs(pageTagMatch[1]),templateName=pageAttrs.template||"default";delete pageAttrs.template;const pageDir=path.dirname(pageFilePath),templateFile=findFileUpSync(`${templateName}.template.html`,pageDir,rootDir);if(!templateFile)throw new Error(`Template not found: ${templateName}.template.html (searched from ${pageDir} to ${rootDir})`);const globalContent=preloadedGlobalContent??await loadGlobalContent(rootDir),rawPageBlocks=extractContentBlocks(pageContent),pageBlocks={};for(const[name,entries]of Object.entries(rawPageBlocks))pageBlocks[name]=entries.map(e=>({...e,html:replaceLocations(e.html,globalContent)}));const contentBlocks=mergeContentBlocks(pageBlocks,globalContent);let templateHtml=readFileSync(templateFile,"utf8");templateHtml=resolveFragmentTags(templateHtml,name=>{const filePath=findFileUpSync(name+".fragment.html",pageDir,rootDir);return filePath?readFileSync(filePath,"utf8"):null},0,maxDepth),templateHtml=replaceLocations(templateHtml,contentBlocks);const rel=path.relative(rootDir,path.dirname(pageFilePath)),depth=rel?rel.split(path.sep).length:0,now=new Date,vars={pathToRoot:depth>0?"../".repeat(depth):"./",year:String(now.getFullYear()),date:now.toISOString().slice(0,10),datetime:now.toISOString(),timestamp:String(Date.now()),version:loadVersion(rootDir),env:process.env.NODE_ENV||"",...globals,...state,...pageAttrs};for(const[key,val]of Object.entries(vars))"function"==typeof val&&(vars[key]=val());return templateHtml=resolveIfs(templateHtml,vars),templateHtml=resolveForeach(templateHtml,vars),templateHtml=resolveVars(templateHtml,vars),templateHtml},walkPages=async dir=>{const entries=await readdir(dir,{withFileTypes:!0}),results=[];for(const entry of entries){const full=path.join(dir,entry.name);entry.isDirectory()?results.push(...await walkPages(full)):entry.name.endsWith(".page.html")&&results.push(full)}return results},renderDir=async(inputDir,outputDir,globals={},state={},maxDepth=10)=>{const[pages,globalContent]=await Promise.all([walkPages(inputDir),loadGlobalContent(inputDir)]);let count=0;for(const page of pages){const outRel=path.relative(inputDir,page).replace(/\.page\.html$/,".html"),outPath=path.join(outputDir,outRel);await mkdir(path.dirname(outPath),{recursive:!0});const html=await renderPage(page,inputDir,globals,state,maxDepth,globalContent);await writeFile(outPath,html,"utf8"),count++}return count};export{renderPage,renderDir};
|
package/dist/templating/parse.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const extractAttrs=tagString=>{const attrs={},re=/(\w[\w-]*)=(?:"([^"]*)"|'([^']*)')/g;let match;for(;null!==(match=re.exec(tagString));)attrs[match[1]]=match[2]??match[3];return attrs},extractContentBlocks=xml=>{const blocks={},re=/<content(?:\s+
|
|
1
|
+
const extractAttrs=tagString=>{const attrs={},re=/(\w[\w-]*)=(?:"([^"]*)"|'([^']*)')/g;let match;for(;null!==(match=re.exec(tagString));)attrs[match[1]]=match[2]??match[3];return attrs},extractContentBlocks=xml=>{const blocks={},re=/<content(?:\s+([^>]*))?\s*>([\s\S]*?)<\/content>/g;let match;for(;null!==(match=re.exec(xml));){const attrs=extractAttrs(match[1]||""),name=attrs.location||"default",priority=parseInt(attrs.priority||"0",10);blocks[name]||(blocks[name]=[]),blocks[name].push({html:match[2],priority:priority})}return blocks},mergeContentBlocks=(...maps)=>{const merged={};for(const map of maps)for(const[name,entries]of Object.entries(map))merged[name]||(merged[name]=[]),merged[name].push(...entries);return merged},resolveLocation=entries=>entries?.length?[...entries].sort((a,b)=>b.priority-a.priority).map(e=>e.html).join(""):null,replaceLocations=(html,contentMap)=>html.replace(/<location(?:\s+name="([^"]*)")?>([\s\S]*?)<\/location>/g,(_,name,fallback)=>resolveLocation(contentMap[name||"default"])??fallback).replace(/<location(?:\s+name="([^"]*)")?\s*\/>/g,(_,name)=>resolveLocation(contentMap[name||"default"])??""),stripFragmentWrapper=xml=>{const match=xml.match(/^\s*<fragment\b[^>]*>([\s\S]*)<\/fragment>\s*$/);return match?match[1]:xml},resolvePath=(obj,dotPath)=>dotPath.split(".").reduce((cur,key)=>cur?.[key],obj),resolveVars=(html,vars)=>html.replace(/\{\{([^}]+)\}\}/g,(_,key)=>{const trimmed=key.trim(),val=resolvePath(vars,trimmed);return"function"==typeof val?val():val??""}),resolveIfs=(html,vars)=>{const re=/<if\s+condition="([^"]+)">([\s\S]*?)<\/if>/g;let prev,result=html;do{prev=result,result=result.replace(re,(_,condition,inner)=>evalCondition(condition,vars)?inner:"")}while(result!==prev);return result},resolveForeach=(html,vars)=>{const re=/<foreach\s+in="([^"]+)"\s+as="([^"]+)">([\s\S]*?)<\/foreach>/g;let prev,result=html;do{prev=result,result=result.replace(re,(_,inAttr,asAttr,inner)=>{const arr=resolvePath(vars,inAttr.trim());return Array.isArray(arr)?arr.map(item=>{const scopedVars={...vars,[asAttr]:item};return resolveVars(inner,scopedVars)}).join(""):""})}while(result!==prev);return result},resolveFragmentTags=(html,findFragmentFile,depth,maxDepth)=>{if(depth>maxDepth)throw new Error(`Fragment depth exceeded maximum of ${maxDepth}`);return html.replace(/<fragment\s+name="([^"]+)"(?:\s*\/>|>([\s\S]*?)<\/fragment>)/g,(_,name,fallback)=>{const content=findFragmentFile(name);if(null===content)return fallback??"";const stripped=stripFragmentWrapper(content);return resolveFragmentTags(stripped,findFragmentFile,depth+1,maxDepth)})},TOKEN_TYPES_NUMBER="NUMBER",TOKEN_TYPES_STRING="STRING",TOKEN_TYPES_BOOLEAN="BOOLEAN",TOKEN_TYPES_IDENTIFIER="IDENTIFIER",TOKEN_TYPES_OPERATOR="OPERATOR",TOKEN_TYPES_NOT="NOT",TOKEN_TYPES_LPAREN="LPAREN",TOKEN_TYPES_RPAREN="RPAREN",evalCondition=(expression,vars)=>!!((tokens,vars)=>{let pos=0;const peek=()=>tokens[pos],advance=()=>tokens[pos++],parsePrimary=()=>{const tok=peek();if(!tok)throw new Error("Unexpected end of expression");if(tok.type===TOKEN_TYPES_NOT)return advance(),!parsePrimary();if(tok.type===TOKEN_TYPES_LPAREN){advance();const val=parseOr();if(!peek()||peek().type!==TOKEN_TYPES_RPAREN)throw new Error("Missing closing parenthesis");return advance(),val}if(tok.type===TOKEN_TYPES_NUMBER||tok.type===TOKEN_TYPES_STRING||tok.type===TOKEN_TYPES_BOOLEAN)return advance(),tok.value;if(tok.type===TOKEN_TYPES_IDENTIFIER)return advance(),resolvePath(vars,tok.value);throw new Error(`Unexpected token: ${JSON.stringify(tok)}`)},parseComparison=()=>{let left=parsePrimary();for(;peek()&&peek().type===TOKEN_TYPES_OPERATOR&&["===","!==",">","<",">=","<="].includes(peek().value);){const op=advance().value,right=parsePrimary();switch(op){case"===":left=left===right;break;case"!==":left=left!==right;break;case">":left=left>right;break;case"<":left=left<right;break;case">=":left=left>=right;break;case"<=":left=left<=right}}return left},parseAnd=()=>{let left=parseComparison();for(;peek()&&peek().type===TOKEN_TYPES_OPERATOR&&"&&"===peek().value;){advance();const right=parseComparison();left=left&&right}return left},parseOr=()=>{let left=parseAnd();for(;peek()&&peek().type===TOKEN_TYPES_OPERATOR&&"||"===peek().value;){advance();const right=parseAnd();left=left||right}return left},result=parseOr();if(pos<tokens.length)throw new Error(`Unexpected token after expression: ${JSON.stringify(tokens[pos])}`);return result})((expr=>{const tokens=[];let i=0;for(;i<expr.length;){if(/\s/.test(expr[i])){i++;continue}if("("===expr[i]){tokens.push({type:TOKEN_TYPES_LPAREN}),i++;continue}if(")"===expr[i]){tokens.push({type:TOKEN_TYPES_RPAREN}),i++;continue}if("!"===expr[i]&&"="!==expr[i+1]){tokens.push({type:TOKEN_TYPES_NOT}),i++;continue}const opMatch=expr.slice(i).match(/^(===|!==|>=|<=|&&|\|\||>|<)/);if(opMatch){tokens.push({type:TOKEN_TYPES_OPERATOR,value:opMatch[1]}),i+=opMatch[1].length;continue}if('"'===expr[i]||"'"===expr[i]){const quote=expr[i];let str="";for(i++;i<expr.length&&expr[i]!==quote;)str+=expr[i],i++;if(i>=expr.length)throw new Error(`Unterminated string in condition: ${expr}`);i++,tokens.push({type:TOKEN_TYPES_STRING,value:str});continue}const numMatch=expr.slice(i).match(/^(\d+(\.\d+)?)/);if(numMatch){tokens.push({type:TOKEN_TYPES_NUMBER,value:Number(numMatch[1])}),i+=numMatch[1].length;continue}const idMatch=expr.slice(i).match(/^([a-zA-Z_$][\w$.]*)/);if(idMatch){const id=idMatch[1];"true"===id||"false"===id?tokens.push({type:TOKEN_TYPES_BOOLEAN,value:"true"===id}):tokens.push({type:TOKEN_TYPES_IDENTIFIER,value:id}),i+=id.length;continue}throw new Error(`Unexpected character '${expr[i]}' in condition: ${expr}`)}return tokens})(expression),vars);export{extractAttrs,extractContentBlocks,mergeContentBlocks,replaceLocations,stripFragmentWrapper,resolveVars,resolveIfs,resolveForeach,resolveFragmentTags,evalCondition,resolvePath};
|
package/docs/caching.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
|
@@ -121,6 +124,7 @@
|
|
|
121
124
|
}</code></pre>
|
|
122
125
|
|
|
123
126
|
<h2>Configuration Options</h2>
|
|
127
|
+
<div class="table-wrapper mb">
|
|
124
128
|
<table>
|
|
125
129
|
<thead>
|
|
126
130
|
<tr>
|
|
@@ -181,6 +185,7 @@
|
|
|
181
185
|
</tr>
|
|
182
186
|
</tbody>
|
|
183
187
|
</table>
|
|
188
|
+
</div>
|
|
184
189
|
|
|
185
190
|
<h2>Environment-Specific Configuration</h2>
|
|
186
191
|
<p>Use separate configuration files for different environments instead of nested objects:</p>
|
package/docs/cli-utils.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
package/docs/configuration.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
|
@@ -304,6 +307,7 @@
|
|
|
304
307
|
<pre><code class="hljs json">{<br /> <span class="hljs-attr">"cache"</span>: {<br /> <span class="hljs-attr">"enabled"</span>: <span class="hljs-literal">true</span>,<br /> <span class="hljs-attr">"maxSize"</span>: <span class="hljs-number">1000</span>,<br /> <span class="hljs-attr">"ttlMs"</span>: <span class="hljs-number">3600000</span>,<br /> <span class="hljs-attr">"maxMemoryUsageMB"</span>: <span class="hljs-number">500</span>,<br /> <span class="hljs-attr">"checkIntervalMs"</span>: <span class="hljs-number">30000</span>,<br /> <span class="hljs-attr">"fileWatching"</span>: <span class="hljs-literal">true</span><br /> }<br />}</code></pre>
|
|
305
308
|
|
|
306
309
|
<h4>Cache Configuration Options</h4>
|
|
310
|
+
<div class="table-wrapper mb">
|
|
307
311
|
<table>
|
|
308
312
|
<thead>
|
|
309
313
|
<tr>
|
|
@@ -352,6 +356,7 @@
|
|
|
352
356
|
</tr>
|
|
353
357
|
</tbody>
|
|
354
358
|
</table>
|
|
359
|
+
</div>
|
|
355
360
|
|
|
356
361
|
<h4>Environment-Specific Cache Settings</h4>
|
|
357
362
|
<h5>Development (.config.dev.json)</h5>
|
package/docs/examples.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
package/docs/fs-utils.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
package/docs/index.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
package/docs/middleware.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|
|
@@ -124,6 +127,7 @@
|
|
|
124
127
|
|
|
125
128
|
<h3 id="body-parsing">Body Parsing</h3>
|
|
126
129
|
<p><code>request.body</code> is eagerly parsed before your route handler runs. The parsing strategy depends on the <code>Content-Type</code> header:</p>
|
|
130
|
+
<div class="table-wrapper mb">
|
|
127
131
|
<table>
|
|
128
132
|
<thead>
|
|
129
133
|
<tr><th>Content-Type</th><th><code>request.body</code> value</th></tr>
|
|
@@ -135,6 +139,7 @@
|
|
|
135
139
|
<tr><td>Any other Content-Type</td><td>Raw string</td></tr>
|
|
136
140
|
</tbody>
|
|
137
141
|
</table>
|
|
142
|
+
</div>
|
|
138
143
|
<p>The convenience methods <code>request.json()</code>, <code>request.text()</code>, and <code>request.buffer()</code> still exist and return promises for backward compatibility, but they resolve immediately from the cached body.</p>
|
|
139
144
|
|
|
140
145
|
<h2>Response Object</h2>
|
package/docs/routing.html
CHANGED
|
@@ -55,19 +55,22 @@
|
|
|
55
55
|
<h1 class="tc-primary">Kempo Server</h1>
|
|
56
56
|
<img src="./media/icon128.png" alt="Kempo UI Icon" />
|
|
57
57
|
</a>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
|
|
59
|
+
<h3 class="mt mb0">Advanced Features</h3>
|
|
60
|
+
<a href="configuration.html" class="d-b pq pl">Configuration</a>
|
|
61
|
+
<a href="templating.html" class="d-b pq pl">Templating</a>
|
|
62
|
+
<a href="middleware.html" class="d-b pq pl">Middleware</a>
|
|
63
|
+
<a href="caching.html" class="d-b pq pl">Module Caching</a>
|
|
64
|
+
<a href="cli-utils.html" class="d-b pq pl">CLI Utilities</a>
|
|
65
|
+
<a href="fs-utils.html" class="d-b pq pl">File System Utilities</a>
|
|
66
|
+
<a href="examples.html" class="d-b pq pl">Examples & Demos</a>
|
|
67
|
+
|
|
68
|
+
<h3 class="mt mb0">Getting Started</h3>
|
|
69
|
+
<a href="./" class="d-b pq pl">Quick Start</a>
|
|
70
|
+
<a href="./routing.html" class="d-b pq pl">Routing</a>
|
|
71
|
+
<a href="./request-response.html" class="d-b pq pl">Request & Response</a>
|
|
72
|
+
<br /><br />
|
|
73
|
+
|
|
71
74
|
</menu>
|
|
72
75
|
</k-aside>
|
|
73
76
|
<script src="https://cdn.jsdelivr.net/npm/kempo-ui@0.3.5/src/components/Aside.js" type="module"></script>
|