@makano/rew 1.2.53 → 1.2.55
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/lib/rew/const/opt.js +2 -1
- package/lib/rew/functions/export.js +1 -1
- package/lib/rew/functions/import.js +4 -2
- package/lib/rew/functions/require.js +17 -1
- package/lib/rew/modules/compiler.js +17 -12
- package/lib/rew/modules/context.js +1 -1
- package/lib/rew/modules/runtime.js +11 -12
- package/lib/rew/pkgs/serve.js +370 -0
- package/lib/rew/pkgs/stream.js +10 -0
- package/lib/rew/pkgs/web.js +498 -0
- package/package.json +5 -5
- package/runtime.d.ts +674 -148
package/lib/rew/const/opt.js
CHANGED
|
@@ -2,9 +2,10 @@ const execOptions = {
|
|
|
2
2
|
sharedContext: true,
|
|
3
3
|
resolveExtensions: ['.coffee', { ext: '.js', options: { type: 'js' } }, { ext: '.qrew', options: { qrew: true } }],
|
|
4
4
|
nativeRequire: false,
|
|
5
|
+
useImport: false,
|
|
5
6
|
cwdAlias: '$',
|
|
6
7
|
jsxPragma: 'createElement',
|
|
7
|
-
jsx: false
|
|
8
|
+
jsx: false
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
module.exports.execOptions = execOptions;
|
|
@@ -8,7 +8,9 @@ const jsYaml = require('js-yaml');
|
|
|
8
8
|
const { execOptions } = require('../const/opt');
|
|
9
9
|
|
|
10
10
|
const cachedFiles = [];
|
|
11
|
-
|
|
11
|
+
module.exports.cleanCache = () => {
|
|
12
|
+
while(cachedFiles.length) cachedFiles.pop();
|
|
13
|
+
};
|
|
12
14
|
const lookUpInOtherApps = (fullPath) => {
|
|
13
15
|
const con = conf({});
|
|
14
16
|
const name = fullPath.indexOf('/') ? fullPath.split('/')[0] : fullPath;
|
|
@@ -87,7 +89,7 @@ module.exports.imp = function (runPath, context) {
|
|
|
87
89
|
).context.module.exports;
|
|
88
90
|
|
|
89
91
|
if (ispkg) {
|
|
90
|
-
const pkg = getPackage(filename)(context);
|
|
92
|
+
const pkg = getPackage(filename)(context, options);
|
|
91
93
|
exports = pkg._onImport ? pkg._onImport() : pkg;
|
|
92
94
|
} else if (foundCache) {
|
|
93
95
|
} else if (type == 'coffee') {
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const { execOptions } = require('../const/opt');
|
|
4
|
+
const { wait } = require('./wait');
|
|
5
|
+
|
|
6
|
+
const cahcedRequires = {};
|
|
7
|
+
|
|
8
|
+
const doImp = (path) => wait(async () => await import(resolvedPath));
|
|
3
9
|
|
|
4
10
|
module.exports.customRequire = function customRequire(modulePath, filePath) {
|
|
11
|
+
const pathname = modulePath;
|
|
12
|
+
if (modulePath.startsWith('./') || modulePath.startsWith('../') || path.isAbsolute(modulePath)) {
|
|
13
|
+
pathname = path.resolve(modulePath);
|
|
14
|
+
}
|
|
15
|
+
if(cahcedRequires[pathname]) {
|
|
16
|
+
return cahcedRequires[pathname];
|
|
17
|
+
}
|
|
5
18
|
const resolvedPath = resolveModulePath(modulePath, filePath);
|
|
6
19
|
if(!resolvedPath) throw new Error('Module '+modulePath+' not found');
|
|
7
|
-
|
|
20
|
+
const r = cahcedRequires[resolvedPath] ? cahcedRequires[resolvedPath] : execOptions.useImport ? doImp(resolvedPath) : require(resolvedPath);
|
|
21
|
+
if(!cahcedRequires[resolvedPath]) cahcedRequires[resolvedPath] = r;
|
|
22
|
+
if(!cahcedRequires[pathname]) cahcedRequires[pathname] = r;
|
|
23
|
+
return r;
|
|
8
24
|
};
|
|
9
25
|
|
|
10
26
|
function resolveModulePath(modulePath, filePath) {
|
|
@@ -115,18 +115,22 @@ function compileRewStuff(content, options) {
|
|
|
115
115
|
const token = tokens[i];
|
|
116
116
|
let { token: nextToken, n } = gnextToken(i, 1, tokens) || {};
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
if (token.type === 'IDENTIFIER' && token.value === 'opt.set') {
|
|
119
120
|
const { token: nextNextToken } = gnextToken(i, 2, tokens) || {};
|
|
120
|
-
if (nextNextToken && nextNextToken.value == 'jsxPragma') {
|
|
121
|
+
if (nextNextToken && nextNextToken.value.slice(1).slice(0, -1) == 'jsxPragma') {
|
|
121
122
|
const { token: nextLastToken } = gnextToken(i, 5, tokens) || {};
|
|
122
123
|
execOptions.jsxPragma = nextLastToken.value.slice(1).slice(0, -1);
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
if (token.type === 'COMMENT' && token.value.slice(1).trim()
|
|
127
|
+
if (token.type === 'COMMENT' && token.value.slice(1).trim().startsWith('@jsx')) {
|
|
127
128
|
options.jsx = true;
|
|
129
|
+
if(token.value.split('@jsx')[1].trim()){
|
|
130
|
+
options.jsxPragma = token.value.split('@jsx')[1].trim();
|
|
131
|
+
}
|
|
128
132
|
}
|
|
129
|
-
|
|
133
|
+
|
|
130
134
|
if (token.type === 'COMMENT' && token.value.slice(1).trim() === '@cls') {
|
|
131
135
|
options.cls = true;
|
|
132
136
|
}
|
|
@@ -146,7 +150,7 @@ function compileRewStuff(content, options) {
|
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
|
|
149
|
-
if (token.type === 'IDENTIFIER' && token.value === 'let') {
|
|
153
|
+
if (token.type === 'IDENTIFIER' && token.value === 'let' && !options.keepImports) {
|
|
150
154
|
result += '`'
|
|
151
155
|
hooks.push({
|
|
152
156
|
index: fnextToken(i, tokens, 'OTHER', ';').ti,
|
|
@@ -154,11 +158,11 @@ function compileRewStuff(content, options) {
|
|
|
154
158
|
});
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
if (token.type === 'IDENTIFIER' && token.value === 'export') {
|
|
161
|
+
if (token.type === 'IDENTIFIER' && token.value === 'export' && !options.keepImports) {
|
|
158
162
|
token.value = 'pub';
|
|
159
163
|
}
|
|
160
164
|
|
|
161
|
-
if (token.type === 'IDENTIFIER' && token.value === 'import') {
|
|
165
|
+
if (token.type === 'IDENTIFIER' && token.value === 'import' && !options.keepImports) {
|
|
162
166
|
// console.log(nextToken.type);
|
|
163
167
|
let ind = i + n + 2;
|
|
164
168
|
|
|
@@ -224,7 +228,7 @@ function compileRewStuff(content, options) {
|
|
|
224
228
|
nextToken &&
|
|
225
229
|
nextToken.type === 'IDENTIFIER' &&
|
|
226
230
|
nextToken.value &&
|
|
227
|
-
nextToken.value !== 'undefined'
|
|
231
|
+
nextToken.value !== 'undefined' && !options.keepImports
|
|
228
232
|
) {
|
|
229
233
|
let next = {...nextToken};
|
|
230
234
|
if(next.value == 'default'){
|
|
@@ -259,13 +263,13 @@ const cpl = (module.exports.compile = function (file, options = {}) {
|
|
|
259
263
|
let c = options.type == 'js' || options.compile == false ? file.content : compile(compileRewStuff(file.content, options), {
|
|
260
264
|
...options,
|
|
261
265
|
filename: file.path,
|
|
262
|
-
bare: false,
|
|
266
|
+
bare: options.bare ?? false,
|
|
263
267
|
inlineMap: false,
|
|
264
|
-
});
|
|
268
|
+
});2
|
|
265
269
|
// console.log(c);
|
|
266
270
|
if (execOptions.jsx || options.jsx) {
|
|
267
271
|
c = babel.transformSync(c, {
|
|
268
|
-
presets: [[babelReact, { pragma: execOptions.jsxPragma }]],
|
|
272
|
+
presets: [[babelReact, { pragma: options.jsxPragma || execOptions.jsxPragma }]],
|
|
269
273
|
plugins: [],
|
|
270
274
|
}).code;
|
|
271
275
|
}
|
|
@@ -273,7 +277,8 @@ const cpl = (module.exports.compile = function (file, options = {}) {
|
|
|
273
277
|
});
|
|
274
278
|
|
|
275
279
|
module.exports.compileFile = function (filepath, options = {}) {
|
|
276
|
-
const f = getFile(filepath);
|
|
280
|
+
const f = typeof filepath == "object" ? filepath : getFile(filepath);
|
|
281
|
+
if(typeof filepath == "object") filepath = filepath.path;
|
|
277
282
|
let qrew = false;
|
|
278
283
|
|
|
279
284
|
if(options.qrew || path.extname(filepath) == '.qrew') {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const vm = require('vm');
|
|
2
|
-
const { compileFile } = require('./compiler');
|
|
2
|
+
const { compileFile, compile } = require('./compiler');
|
|
3
3
|
const { prepareContext } = require('./context');
|
|
4
4
|
const { existsSync, readFileSync } = require('fs');
|
|
5
5
|
const { CONFIG_PATH } = require('../const/config_path');
|
|
@@ -7,37 +7,36 @@ const path = require('path');
|
|
|
7
7
|
|
|
8
8
|
const preScript = readFileSync(path.join(__dirname, '../const/pre-exec.js'), { encoding: 'utf-8' });
|
|
9
9
|
|
|
10
|
-
const exec = (module.exports.exec = function (code, context) {
|
|
11
|
-
return vm.runInNewContext(code, vm.createContext(context), {
|
|
10
|
+
const exec = (module.exports.exec = function (code, context, original = '') {
|
|
11
|
+
return vm.runInNewContext(code, context.do ? null : vm.createContext(context), {
|
|
12
12
|
filename: context.module.filepath,
|
|
13
|
-
lineOffset:
|
|
13
|
+
lineOffset: (original.split('\n').length + preScript.split('\n').length) - code.split('\n').length,
|
|
14
14
|
displayErrors: true,
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
module.exports.runPath = function runPath(filepath, options = {}, custom_context = {}) {
|
|
19
19
|
if(filepath.endsWith('.js')) options.type = 'js';
|
|
20
|
-
let { compiled_code, file } = compileFile(filepath, options);
|
|
21
|
-
const context = prepareContext(custom_context, options, file.path, runPath);
|
|
22
|
-
|
|
23
|
-
context.
|
|
24
|
-
context.process.exit = (int) => process.exit(int);
|
|
20
|
+
let { compiled_code, file } = compileFile(options.code ? { content: options.code, path: filepath } : filepath, options);
|
|
21
|
+
const context = options.import?.takeThisContext ? custom_context : prepareContext(custom_context, options, file.path, runPath);
|
|
22
|
+
// context.module.compiled = compiled_code;
|
|
23
|
+
// context.process.exit = (int) => process.exit(int);
|
|
25
24
|
|
|
26
25
|
if(context.app){
|
|
27
26
|
const p = path.join(CONFIG_PATH, context.app.config.manifest.package, 'app');
|
|
28
27
|
if(existsSync(p) && context.app.path !== p){
|
|
29
28
|
console.log("App with the same package name has been installed. Conflicts happened. \nTo fix this, change your app's package name or remove the app making the conflict.");
|
|
30
29
|
return {
|
|
31
|
-
context: { exports: null },
|
|
30
|
+
context: { module: { exports: null } },
|
|
32
31
|
returns: null
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
compiled_code = preScript+compiled_code;
|
|
36
|
+
compiled_code = preScript+'\n'+compiled_code;
|
|
38
37
|
|
|
39
38
|
return {
|
|
40
39
|
context,
|
|
41
|
-
returns: exec(compiled_code, context),
|
|
40
|
+
returns: exec(compiled_code, context, file.content),
|
|
42
41
|
};
|
|
43
42
|
};
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
const { readdirSync, existsSync } = require('fs');
|
|
2
|
+
const http = require('http');
|
|
3
|
+
const { IttyRouter, AutoRouter, Router, createResponse, cors, error, StatusError, html, json, withCookies, withContent, withParams, jpeg, png, webp, text, status } = require('itty-router');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { run } = require('../main');
|
|
6
|
+
const { runPath } = require('../modules/runtime');
|
|
7
|
+
const { cleanCache } = require('../functions/import');
|
|
8
|
+
module.exports = (context) => {
|
|
9
|
+
|
|
10
|
+
// http.createServer((req, res) => {
|
|
11
|
+
// res.end();
|
|
12
|
+
// }).listen(1400);
|
|
13
|
+
|
|
14
|
+
const imp = (file) => context.imp(file);
|
|
15
|
+
const Web = imp('web');
|
|
16
|
+
|
|
17
|
+
function mkReq(req) {
|
|
18
|
+
const url = `http://${req.headers.host}${req.url}`;
|
|
19
|
+
const options = {
|
|
20
|
+
method: req.method,
|
|
21
|
+
headers: req.headers,
|
|
22
|
+
body: req.body
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return new Request(url, options);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class Server {
|
|
29
|
+
_server = {};
|
|
30
|
+
routers = {};
|
|
31
|
+
|
|
32
|
+
constructor(options){
|
|
33
|
+
this.options = options;
|
|
34
|
+
this._server = http.createServer((req, res) => {
|
|
35
|
+
options.handler ? options.handler(req, res) : this.handleRequest(req, res);
|
|
36
|
+
});
|
|
37
|
+
if(options.routers){
|
|
38
|
+
options.routers.forEach(router => router.to(this));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async handleRequest(req, res){
|
|
43
|
+
try {
|
|
44
|
+
let response = new Response();
|
|
45
|
+
const request = mkReq(req);
|
|
46
|
+
if(this.options.fetch == 'router'){
|
|
47
|
+
if(!Object.keys(this.options.routers).length) throw new Error('No fetch function nor routers found');
|
|
48
|
+
response = await this.options.routers[Object.keys(this.options.routers)[0]].fetch(request);
|
|
49
|
+
} else {
|
|
50
|
+
response = await this.options.fetch(request);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if(!response){
|
|
54
|
+
res.end('Cannot '+req.method+' '+req.url);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
response.headers.forEach((value, name) => {
|
|
59
|
+
res.setHeader(name, value);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
res.writeHead(response.status);
|
|
63
|
+
|
|
64
|
+
const buffer = await response.arrayBuffer();
|
|
65
|
+
res.end(Buffer.from(buffer));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
// Handle errors
|
|
68
|
+
console.error("Error:", error);
|
|
69
|
+
res.writeHead(500, {'Content-Type': 'text/plain'});
|
|
70
|
+
res.end("Internal Server Error");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get listen(){
|
|
75
|
+
this._server.listen(this.options.port);
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set listen(port){
|
|
80
|
+
this.options.port = port;
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
port(port){
|
|
85
|
+
this.listen = port;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
log(string){
|
|
90
|
+
console.log(string.replace(/\$([A-Za-z0-9_]+)/g, (_, name) => this.options[name] || _));
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
class SvrRouter {
|
|
96
|
+
static new(Class, options, props){
|
|
97
|
+
const router = Class(options);
|
|
98
|
+
for(let i in props) router[i] = props[i];
|
|
99
|
+
router.to = (server) => {
|
|
100
|
+
if(server instanceof Server){
|
|
101
|
+
server.routers[this.id] = this;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
return router;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function findLayoutFiles(filePath, root, isClientSide = true, resolveExtensions = ['.coffee', '.js', '.jsx']) {
|
|
109
|
+
const layouts = [];
|
|
110
|
+
const rootDir = root;
|
|
111
|
+
let currentDir = path.dirname(filePath);
|
|
112
|
+
|
|
113
|
+
while (currentDir !== rootDir) {
|
|
114
|
+
for (const ext of resolveExtensions) {
|
|
115
|
+
const layoutFile = path.join(currentDir, `layout${isClientSide ? '' : '.s'}${ext}`);
|
|
116
|
+
if (existsSync(layoutFile)) {
|
|
117
|
+
layouts.push(layoutFile);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
currentDir = path.dirname(currentDir);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for (const ext of resolveExtensions) {
|
|
124
|
+
const layoutFile = path.join(currentDir, `layout${isClientSide ? '' : '.s'}${ext}`);
|
|
125
|
+
if (existsSync(layoutFile)) {
|
|
126
|
+
layouts.push(layoutFile);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return layouts.reverse();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const defaultBundlerEntry = (file, layouts, data) => `
|
|
134
|
+
import * as target from "${file}";
|
|
135
|
+
${layouts.map((layout, ind) => `import * as layout${ind} from "${layout}";`).join('\n')}
|
|
136
|
+
let page = target.render ? target.render(${JSON.stringify(data)}) : target.default ? target.default(${JSON.stringify(data)}) : null;
|
|
137
|
+
${layouts.reverse().map((_, ind) => `if (layout${ind}.render) page = layout${ind}.render(${JSON.stringify(data)}, page);`).join('\n')}
|
|
138
|
+
`;
|
|
139
|
+
|
|
140
|
+
const defaultSsrBundlerEntry = (file, layouts, data) => `
|
|
141
|
+
files = "${layouts.join(',')},${file}".split(',')
|
|
142
|
+
|
|
143
|
+
renderers = []
|
|
144
|
+
staticRendering = false
|
|
145
|
+
|
|
146
|
+
for key, file of files
|
|
147
|
+
renderers.push imp file
|
|
148
|
+
|
|
149
|
+
staticRendering = true if renderers[renderers.length-1].staticRendering
|
|
150
|
+
|
|
151
|
+
render = (req, data) ->
|
|
152
|
+
target = renderers.pop()
|
|
153
|
+
page = target.render req, data
|
|
154
|
+
for renderer in renderers
|
|
155
|
+
page = renderer.render req, data, page
|
|
156
|
+
page
|
|
157
|
+
|
|
158
|
+
exports { render, staticRendering }
|
|
159
|
+
`;
|
|
160
|
+
|
|
161
|
+
function createFileRouter({
|
|
162
|
+
onError = () => error(404, 'Path not found'),
|
|
163
|
+
root = '',
|
|
164
|
+
basePath = '',
|
|
165
|
+
resolveExtensions = ['.coffee', '.js', '.jsx'],
|
|
166
|
+
bundlerOptions = {},
|
|
167
|
+
bundlerEntry = defaultBundlerEntry,
|
|
168
|
+
ssrBundlerEntry = defaultSsrBundlerEntry,
|
|
169
|
+
}) {
|
|
170
|
+
|
|
171
|
+
const lookUpFiles = ['route', 'page', 'page.s'];
|
|
172
|
+
|
|
173
|
+
const params = {};
|
|
174
|
+
|
|
175
|
+
function lookUp(pathname) {
|
|
176
|
+
const routeParts = pathname.split('/').filter(Boolean);
|
|
177
|
+
let routePath = root;
|
|
178
|
+
|
|
179
|
+
Object.keys(params).forEach(key => delete params[key]);
|
|
180
|
+
|
|
181
|
+
for (const part of routeParts) {
|
|
182
|
+
const dir = readdirSync(routePath);
|
|
183
|
+
|
|
184
|
+
const match = dir.find(d => d === part || d.match(/^\[.*\]$/));
|
|
185
|
+
if (!match) return null;
|
|
186
|
+
|
|
187
|
+
if (match.match(/^\[.*\]$/)) {
|
|
188
|
+
const paramName = match.slice(1, -1);
|
|
189
|
+
params[paramName] = part;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
routePath = path.join(routePath, match);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (const base of lookUpFiles) {
|
|
196
|
+
for (const ext of resolveExtensions) {
|
|
197
|
+
const filePath = path.join(routePath, `${base}${ext}`);
|
|
198
|
+
if (existsSync(filePath)) {
|
|
199
|
+
return filePath;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function getReqProps(req) {
|
|
208
|
+
return {
|
|
209
|
+
params: {
|
|
210
|
+
...params,
|
|
211
|
+
...(req.params || {})
|
|
212
|
+
},
|
|
213
|
+
query: req.query,
|
|
214
|
+
url: req.url,
|
|
215
|
+
method: req.method
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const w = new Web();
|
|
220
|
+
|
|
221
|
+
async function renderPage(file, basename, req){
|
|
222
|
+
const page = w.create({ viewportMeta: true });
|
|
223
|
+
let staticRendering = false;
|
|
224
|
+
if(basename.endsWith('.s')){
|
|
225
|
+
// SSR is enabled, do only ssr
|
|
226
|
+
const layouts = findLayoutFiles(file, root, false);
|
|
227
|
+
const fileContext = runPath(file, { code: ssrBundlerEntry(file, layouts) }).context.module.exports || {};
|
|
228
|
+
if(typeof fileContext.render !== "function") throw new ReferenceError("Route does not export function render");
|
|
229
|
+
let pageContent = fileContext.render(req, { page, ...getReqProps(req) });
|
|
230
|
+
if(fileContext.staticRendering) staticRendering = true;
|
|
231
|
+
if(!w.isNode(pageContent)) throw new TypeError("Route.render does not return an element");
|
|
232
|
+
if(pageContent?.type?.element == 'head'){
|
|
233
|
+
page.root.props.children.splice(page.root.props.children.indexOf(page.head), 1);
|
|
234
|
+
page.head = pageContent;
|
|
235
|
+
page.root.add(pageContent);
|
|
236
|
+
} else if(pageContent?.type?.element == 'body'){
|
|
237
|
+
page.root.props.children.splice(page.root.props.children.indexOf(page.body), 1);
|
|
238
|
+
page.body = pageContent;
|
|
239
|
+
page.root.add(pageContent);
|
|
240
|
+
} else if(pageContent?.type?.element == 'html'){
|
|
241
|
+
page.root = pageContent;
|
|
242
|
+
page.body = pageContent.find('body');
|
|
243
|
+
page.head = pageContent.find('head');
|
|
244
|
+
} else {
|
|
245
|
+
page.add(pageContent);
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
const layouts = findLayoutFiles(file, root, true);
|
|
249
|
+
const scriptString = await w.bundle(path.join(root, 'bundle.js'), {
|
|
250
|
+
...bundlerOptions,
|
|
251
|
+
code: bundlerEntry(file, layouts, getReqProps(req))
|
|
252
|
+
});
|
|
253
|
+
page.script(scriptString);
|
|
254
|
+
staticRendering = true;
|
|
255
|
+
}
|
|
256
|
+
return html(page.render(staticRendering));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function handleRequest(req, file) {
|
|
260
|
+
const ext = path.extname(file);
|
|
261
|
+
const basename = path.basename(file, ext);
|
|
262
|
+
|
|
263
|
+
if (basename.startsWith('route')) {
|
|
264
|
+
const fileContext = run(file).context;
|
|
265
|
+
const handlers = fileContext.module.exports;
|
|
266
|
+
const method = req.method.toUpperCase();
|
|
267
|
+
if (handlers[method]) {
|
|
268
|
+
return await handlers[method](req, getReqProps(req));
|
|
269
|
+
} else {
|
|
270
|
+
return error(405, `Method ${method} not allowed`);
|
|
271
|
+
}
|
|
272
|
+
} else if (basename.startsWith('page')) {
|
|
273
|
+
return await renderPage(file, basename, req);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
return async (req) => {
|
|
279
|
+
const url = new URL(req.url);
|
|
280
|
+
const pathname = basePath ? url.pathname.replace(new RegExp('^'+basePath), '') : url.pathname;
|
|
281
|
+
const file = lookUp(pathname);
|
|
282
|
+
cleanCache();
|
|
283
|
+
|
|
284
|
+
if (file) {
|
|
285
|
+
const response = handleRequest(req, file);
|
|
286
|
+
response.catch(() => onError());
|
|
287
|
+
return await response;
|
|
288
|
+
} else {
|
|
289
|
+
return onError();
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class Svr {
|
|
297
|
+
create(options){
|
|
298
|
+
return new Server(options);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
router({ id = '/', type = 'normal', ...options }){
|
|
302
|
+
let router;
|
|
303
|
+
if(type == 'default') router = SvrRouter.new(IttyRouter, {...options}, { id });
|
|
304
|
+
if(type == 'auto') router = SvrRouter.new(AutoRouter, {...options}, { id });
|
|
305
|
+
if(type == 'normal') router = SvrRouter.new(Router, {...options}, { id });
|
|
306
|
+
|
|
307
|
+
return router;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
createResponse(format, transform, type = 'normal'){
|
|
311
|
+
return type == 'json' ? json(format, transform) : createResponse(format, transform);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
html(string, options = {}){
|
|
315
|
+
return html(string, options);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
json(object, options = {}){
|
|
319
|
+
return json(object, options);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
jpeg(image, options = {}){
|
|
323
|
+
return jpeg(image, options);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
png(image, options = {}){
|
|
327
|
+
return png(image, options);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
webp(image, options = {}){
|
|
331
|
+
return webp(image, options);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
text(string, options = {}){
|
|
335
|
+
return text(string, options);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
status(code, options = {}){
|
|
339
|
+
return status(code, options);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
cors(options = {}){
|
|
343
|
+
return cors(options);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
error(status, body){
|
|
347
|
+
return error(status, body);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
createFileRouter(o){
|
|
351
|
+
return createFileRouter(o);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
class SvrResponse extends Response {}
|
|
356
|
+
class SvrRequest extends Request {}
|
|
357
|
+
|
|
358
|
+
Svr.prototype.Response = SvrResponse;
|
|
359
|
+
Svr.prototype.Request = SvrRequest;
|
|
360
|
+
Svr.prototype.URL = URL;
|
|
361
|
+
Svr.prototype.StatusError = StatusError;
|
|
362
|
+
|
|
363
|
+
Svr.prototype.withContent = withContent;
|
|
364
|
+
Svr.prototype.withCookies = withCookies;
|
|
365
|
+
Svr.prototype.withParams = withParams;
|
|
366
|
+
|
|
367
|
+
IttyRouter
|
|
368
|
+
|
|
369
|
+
return Svr;
|
|
370
|
+
}
|