@webqit/webflo 0.8.77 → 0.9.1
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/package.json +5 -12
- package/src/Cli.js +131 -0
- package/src/Configurator.js +97 -0
- package/src/Context.js +76 -0
- package/src/config-pi/deployment/Env.js +69 -0
- package/src/config-pi/deployment/Layout.js +65 -0
- package/src/config-pi/deployment/Origins.js +133 -0
- package/src/config-pi/deployment/Virtualization.js +65 -0
- package/src/config-pi/deployment/index.js +18 -0
- package/src/config-pi/index.js +16 -0
- package/src/config-pi/runtime/Client.js +59 -0
- package/src/config-pi/runtime/Server.js +174 -0
- package/src/config-pi/runtime/client/Worker.js +117 -0
- package/src/config-pi/runtime/client/index.js +12 -0
- package/src/config-pi/runtime/index.js +18 -0
- package/src/config-pi/runtime/server/Headers.js +90 -0
- package/src/config-pi/runtime/server/Redirects.js +108 -0
- package/src/config-pi/runtime/server/index.js +14 -0
- package/src/config-pi/static/Manifest.js +321 -0
- package/src/config-pi/static/Ssg.js +72 -0
- package/src/config-pi/static/index.js +14 -0
- package/src/deployment-pi/index.js +10 -0
- package/src/{services → deployment-pi}/origins/index.js +88 -58
- package/src/index.js +14 -147
- package/src/{runtime → runtime-pi}/Router.js +19 -19
- package/src/runtime-pi/client/Context.js +7 -0
- package/src/{runtime → runtime-pi}/client/Router.js +2 -2
- package/src/{runtime/client/Navigator.js → runtime-pi/client/Runtime.js} +148 -103
- package/src/runtime-pi/client/RuntimeClient.js +114 -0
- package/src/{runtime → runtime-pi}/client/Storage.js +1 -1
- package/src/{runtime → runtime-pi}/client/Url.js +2 -6
- package/src/{runtime/client/WorkerClient.js → runtime-pi/client/WorkerComm.js} +2 -2
- package/src/runtime-pi/client/generate.js +242 -0
- package/src/runtime-pi/client/generate.oohtml.js +7 -0
- package/src/runtime-pi/client/index.js +18 -0
- package/src/runtime-pi/client/whatwag.js +27 -0
- package/src/runtime-pi/client/worker/Context.js +7 -0
- package/src/runtime-pi/client/worker/Worker.js +243 -0
- package/src/runtime-pi/client/worker/WorkerClient.js +46 -0
- package/src/runtime-pi/client/worker/index.js +18 -0
- package/src/runtime-pi/index.js +14 -0
- package/src/runtime-pi/server/Context.js +16 -0
- package/src/{runtime → runtime-pi}/server/Router.js +6 -6
- package/src/runtime-pi/server/Runtime.js +531 -0
- package/src/runtime-pi/server/RuntimeClient.js +103 -0
- package/src/runtime-pi/server/index.js +41 -0
- package/src/runtime-pi/server/whatwag.js +35 -0
- package/src/{runtime → runtime-pi}/util.js +0 -0
- package/src/{runtime/_FormData.js → runtime-pi/xFormData.js} +2 -2
- package/src/{runtime/_Headers.js → runtime-pi/xHeaders.js} +4 -4
- package/src/runtime-pi/xHttpEvent.js +93 -0
- package/src/runtime-pi/xHttpMessage.js +179 -0
- package/src/runtime-pi/xRequest.js +67 -0
- package/src/runtime-pi/xRequestHeaders.js +95 -0
- package/src/runtime-pi/xResponse.js +62 -0
- package/src/{runtime/_ResponseHeaders.js → runtime-pi/xResponseHeaders.js} +38 -18
- package/src/{runtime/_URL.js → runtime-pi/xURL.js} +4 -4
- package/src/runtime-pi/xfetch.js +7 -0
- package/src/{services → services-pi}/certbot/http-auth-hook.js +0 -0
- package/src/{services → services-pi}/certbot/http-cleanup-hook.js +0 -0
- package/src/{services → services-pi}/certbot/index.js +21 -15
- package/src/services-pi/index.js +9 -0
- package/src/static-pi/index.js +11 -0
- package/src/webflo.js +33 -0
- package/test/index.test.js +26 -0
- package/src/build/client/index.js +0 -261
- package/src/build/index.js +0 -5
- package/src/config/client.js +0 -191
- package/src/config/headers.js +0 -121
- package/src/config/index.js +0 -14
- package/src/config/layout.js +0 -83
- package/src/config/manifest.js +0 -341
- package/src/config/origins.js +0 -165
- package/src/config/prerendering.js +0 -100
- package/src/config/redirects.js +0 -137
- package/src/config/server.js +0 -201
- package/src/config/variables.js +0 -102
- package/src/config/vhosts.js +0 -93
- package/src/runtime/_MessageStream.js +0 -195
- package/src/runtime/_NavigationEvent.js +0 -91
- package/src/runtime/_Request.js +0 -59
- package/src/runtime/_RequestHeaders.js +0 -72
- package/src/runtime/_Response.js +0 -56
- package/src/runtime/client/NavigationEvent.js +0 -21
- package/src/runtime/client/Runtime.js +0 -126
- package/src/runtime/client/Worker.js +0 -317
- package/src/runtime/client/archive/Cache.js +0 -38
- package/src/runtime/client/archive/Http.js +0 -225
- package/src/runtime/client/archive/StdRequest.js +0 -74
- package/src/runtime/client/archive/WorkerComm.js +0 -183
- package/src/runtime/client/effects/sounds.js +0 -64
- package/src/runtime/index.js +0 -5
- package/src/runtime/server/NavigationEvent.js +0 -39
- package/src/runtime/server/Runtime.js +0 -593
- package/src/runtime/server/index.js +0 -183
- package/src/runtime/server/index.mjs +0 -10
- package/src/services/index.js +0 -6
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import _isGlobe from 'is-glob';
|
|
6
|
+
import Minimatch from 'minimatch';
|
|
7
|
+
import { _any } from '@webqit/util/arr/index.js';
|
|
8
|
+
import { _after, _afterLast } from '@webqit/util/str/index.js';
|
|
9
|
+
import { HttpEvent, Request, Response } from '../Runtime.js';
|
|
10
|
+
import { Observer } from '../Runtime.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* ---------------------------
|
|
14
|
+
* The Worker Initializer
|
|
15
|
+
* ---------------------------
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export default class Worker {
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Runtime
|
|
22
|
+
*
|
|
23
|
+
* @param Object cx
|
|
24
|
+
* @param Function clientCallback
|
|
25
|
+
*
|
|
26
|
+
* @return void
|
|
27
|
+
*/
|
|
28
|
+
constructor(cx, clientCallback) {
|
|
29
|
+
|
|
30
|
+
// ---------------
|
|
31
|
+
this.cx = cx;
|
|
32
|
+
this.clients = new Map;
|
|
33
|
+
this.mockSessionStore = {};
|
|
34
|
+
// ---------------
|
|
35
|
+
this.cx.runtime = this;
|
|
36
|
+
let client = clientCallback(this.cx, '*');
|
|
37
|
+
if (!client || !client.handle) throw new Error(`Application instance must define a ".handle()" method.`);
|
|
38
|
+
this.clients.set('*', client);
|
|
39
|
+
|
|
40
|
+
// -------------
|
|
41
|
+
// ONINSTALL
|
|
42
|
+
self.addEventListener('install', evt => {
|
|
43
|
+
if (this.cx.params.skip_waiting) { self.skipWaiting(); }
|
|
44
|
+
// Manage CACHE
|
|
45
|
+
if (this.cx.params.cache_name && (this.cx.params.cache_only_urls || []).length) {
|
|
46
|
+
// Add files to cache
|
|
47
|
+
evt.waitUntil( self.caches.open(this.cx.params.cache_name).then(cache => {
|
|
48
|
+
if (this.cx.logger) { this.cx.logger.log('[ServiceWorker] Pre-caching resources.'); }
|
|
49
|
+
const cache_only_urls = (this.cx.params.cache_only_urls || []).map(c => c.trim()).filter(c => c);
|
|
50
|
+
return cache.addAll(cache_only_urls.filter(url => !_isGlobe(url) && !_afterLast(url, '.').includes('/')));
|
|
51
|
+
}) );
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// -------------
|
|
56
|
+
// ONACTIVATE
|
|
57
|
+
self.addEventListener('activate', evt => {
|
|
58
|
+
evt.waitUntil( new Promise(async resolve => {
|
|
59
|
+
if (this.cx.params.skip_waiting) { await self.clients.claim(); }
|
|
60
|
+
// Manage CACHE
|
|
61
|
+
if (this.cx.params.cache_name) {
|
|
62
|
+
// Clear outdated CACHES
|
|
63
|
+
await self.caches.keys().then(keyList => {
|
|
64
|
+
return Promise.all(keyList.map(key => {
|
|
65
|
+
if (key !== this.cx.params.cache_name && key !== this.cx.params.cache_name + '_json') {
|
|
66
|
+
if (this.cx.logger) { this.cx.logger.log('[ServiceWorker] Removing old cache:', key); }
|
|
67
|
+
return self.caches.delete(key);
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
resolve();
|
|
73
|
+
}) );
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// -------------
|
|
77
|
+
// ONFETCH
|
|
78
|
+
self.addEventListener('fetch', async evt => {
|
|
79
|
+
// URL schemes that might arrive here but not supported; e.g.: chrome-extension://
|
|
80
|
+
if (!evt.request.url.startsWith('http')) return;
|
|
81
|
+
const requestInit = [
|
|
82
|
+
'method', 'headers', 'body', 'mode', 'credentials', 'cache', 'redirect', 'referrer', 'integrity',
|
|
83
|
+
].reduce((init, prop) => ({ [prop]: evt.request[prop], ...init }), {});
|
|
84
|
+
evt.respondWith(this.go(evt.request.url, requestInit, { event: evt }));
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// ---------------
|
|
88
|
+
Observer.set(this, 'location', {});
|
|
89
|
+
Observer.set(this, 'network', {});
|
|
90
|
+
// ---------------
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Performs a request.
|
|
95
|
+
*
|
|
96
|
+
* @param object|string url
|
|
97
|
+
* @param object init
|
|
98
|
+
* @param object detail
|
|
99
|
+
*
|
|
100
|
+
* @return Response
|
|
101
|
+
*/
|
|
102
|
+
async go(url, init = {}, detail = {}) {
|
|
103
|
+
// ------------
|
|
104
|
+
url = typeof url === 'string' ? new URL(url) : url;
|
|
105
|
+
init = { referrer: this.location.href, ...init };
|
|
106
|
+
// ------------
|
|
107
|
+
// The request object
|
|
108
|
+
let request = this.generateRequest(url.href, init);
|
|
109
|
+
// The navigation event
|
|
110
|
+
let httpEvent = new HttpEvent(request, detail, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
|
|
111
|
+
httpEvent.port.listen(message => {
|
|
112
|
+
if (message.$type === 'handler:hints' && message.session) {
|
|
113
|
+
// TODO: Sync sesseion data from client
|
|
114
|
+
return Promise.resolve();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// Response
|
|
118
|
+
let response;
|
|
119
|
+
if (httpEvent.request.url.startsWith(self.origin)/* && httpEvent.request.mode === 'navigate'*/) {
|
|
120
|
+
response = await this.clients.get('*').handle(httpEvent, (...args) => this.remoteFetch(...args));
|
|
121
|
+
} else {
|
|
122
|
+
response = await this.remoteFetch(httpEvent.request);
|
|
123
|
+
}
|
|
124
|
+
let finalResponse = this.handleResponse(httpEvent, response);
|
|
125
|
+
// Return value
|
|
126
|
+
return finalResponse;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Generates request object
|
|
130
|
+
generateRequest(href, init) {
|
|
131
|
+
// Now, the following is key:
|
|
132
|
+
// The browser likes to use "force-cache" for "navigate" requests
|
|
133
|
+
// when, for example, the back button was used.
|
|
134
|
+
// Thus the origin server would still not be contacted by the self.fetch() below, leading to inconsistencies in responses.
|
|
135
|
+
// So, we detect this scenerio and avoid it.
|
|
136
|
+
if (init.mode === 'navigate' && init.cache === 'force-cache') {
|
|
137
|
+
init = { ...init, cache: 'default' };
|
|
138
|
+
}
|
|
139
|
+
let request = new Request(href, init);
|
|
140
|
+
return request;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Generates session object
|
|
144
|
+
getSession(e, id = null, persistent = false) {
|
|
145
|
+
return {
|
|
146
|
+
get: () => this.mockSessionStore,
|
|
147
|
+
set: value => { this.mockSessionStore = value },
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Initiates remote fetch and sets the status
|
|
152
|
+
remoteFetch(request) {
|
|
153
|
+
const execFetch = () => {
|
|
154
|
+
if (_any((this.cx.params.cache_only_urls || []).map(c => c.trim()).filter(c => c), pattern => Minimatch.Minimatch(request.url, pattern))) {
|
|
155
|
+
Observer.set(this.network, 'strategy', 'cache-only');
|
|
156
|
+
return this.cacheFetch(request, { networkFallback: false, cacheRefresh: false });
|
|
157
|
+
}
|
|
158
|
+
// network_only_urls
|
|
159
|
+
if (_any((this.cx.params.network_only_urls || []).map(c => c.trim()).filter(c => c), pattern => Minimatch.Minimatch(request.url, pattern))) {
|
|
160
|
+
Observer.set(this.network, 'strategy', 'network-only');
|
|
161
|
+
return this.networkFetch(request, { cacheFallback: false, cacheRefresh: false });
|
|
162
|
+
}
|
|
163
|
+
// cache_first_urls
|
|
164
|
+
if (_any((this.cx.params.cache_first_urls || []).map(c => c.trim()).filter(c => c), pattern => Minimatch.Minimatch(request.url, pattern))) {
|
|
165
|
+
Observer.set(this.network, 'strategy', 'cache-first');
|
|
166
|
+
return this.cacheFetch(request, { networkFallback: true, cacheRefresh: true });
|
|
167
|
+
}
|
|
168
|
+
Observer.set(this.network, 'strategy', 'network-first');
|
|
169
|
+
return this.networkFetch(request, { cacheFallback: true, cacheRefresh: true });
|
|
170
|
+
};
|
|
171
|
+
let response = execFetch(request);
|
|
172
|
+
// This catch() is NOT intended to handle failure of the fetch
|
|
173
|
+
response.catch(e => Observer.set(this.network, 'error', e.message));
|
|
174
|
+
// Return xResponse
|
|
175
|
+
return response.then(_response => new Response(_response));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Caching strategy: cache_first
|
|
179
|
+
cacheFetch(request, params = {}) {
|
|
180
|
+
return this.getRequestCache(request).then(cache => cache.match(request).then(response => {
|
|
181
|
+
// Nothing cache, use network
|
|
182
|
+
if (!response && params.networkFallback) return this.networkFetch(request, { ...params, cacheFallback: false });
|
|
183
|
+
// Note: fetch, but for refreshing purposes only... not the returned response
|
|
184
|
+
if (response && params.cacheRefresh) this.networkFetch(request, { ...params, justRefreshing: true });
|
|
185
|
+
Observer.set(this.network, 'cache', true);
|
|
186
|
+
return response;
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Caching strategy: network_first
|
|
191
|
+
networkFetch(request, params = {}) {
|
|
192
|
+
if (params.forceNetwork) {
|
|
193
|
+
let url = new URL(request.url);
|
|
194
|
+
url.searchParams.set('$force-cache', '1');
|
|
195
|
+
request.attr.url = url.toString();
|
|
196
|
+
}
|
|
197
|
+
if (!params.cacheFallback) {
|
|
198
|
+
Observer.set(this.network, 'remote', true);
|
|
199
|
+
return self.fetch(request);
|
|
200
|
+
}
|
|
201
|
+
return self.fetch(request).then(response => {
|
|
202
|
+
if (params.cacheRefresh) this.refreshCache(request, response);
|
|
203
|
+
Observer.set(this.network, 'remote', true);
|
|
204
|
+
return response;
|
|
205
|
+
}).catch(() => this.getRequestCache(request).then(cache => {
|
|
206
|
+
Observer.set(this.network, 'cache', true);
|
|
207
|
+
return cache.match(request);
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Caches response
|
|
212
|
+
refreshCache(request, response) {
|
|
213
|
+
// Check if we received a valid response
|
|
214
|
+
if (request.method !== 'GET' || !response || response.status !== 200 || (response.type !== 'basic' && response.type !== 'cors')) {
|
|
215
|
+
return response;
|
|
216
|
+
}
|
|
217
|
+
// IMPORTANT: Clone the response. A response is a stream
|
|
218
|
+
// and because we want the browser to consume the response
|
|
219
|
+
// as well as the cache consuming the response, we need
|
|
220
|
+
// to clone it so we have two streams.
|
|
221
|
+
var responseToCache = response.clone();
|
|
222
|
+
this.getRequestCache(request).then(cache => {
|
|
223
|
+
Observer.set(this.network, 'cacheRefresh', true);
|
|
224
|
+
cache.put(request, responseToCache);
|
|
225
|
+
});
|
|
226
|
+
return response;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Returns either the regular cache or a json-specific cache
|
|
230
|
+
getRequestCache(request) {
|
|
231
|
+
let cacheName = request.headers.get('Accept') === 'application/json'
|
|
232
|
+
? this.cx.params.cache_name + '_json'
|
|
233
|
+
: this.cx.params.cache_name;
|
|
234
|
+
return self.caches.open(cacheName);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Handles response object
|
|
238
|
+
handleResponse(e, response) {
|
|
239
|
+
if (!(response instanceof Response)) { response = new Response(response); }
|
|
240
|
+
return response;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import Router from '../Router.js';
|
|
6
|
+
|
|
7
|
+
export default class WorkerClient {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* WorkerClient
|
|
11
|
+
*
|
|
12
|
+
* @param Context cx
|
|
13
|
+
*/
|
|
14
|
+
constructor(cx) {
|
|
15
|
+
this.cx = cx;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Handles HTTP events.
|
|
20
|
+
*
|
|
21
|
+
* @param HttpEvent httpEvent
|
|
22
|
+
* @param Function remoteFetch
|
|
23
|
+
*
|
|
24
|
+
* @return Response
|
|
25
|
+
*/
|
|
26
|
+
async handle(httpEvent, remoteFetch) {
|
|
27
|
+
// The app router
|
|
28
|
+
const router = new Router(this.cx, httpEvent.url.pathname);
|
|
29
|
+
const handle = async () => {
|
|
30
|
+
// --------
|
|
31
|
+
// ROUTE FOR DATA
|
|
32
|
+
// --------
|
|
33
|
+
let httpMethodName = httpEvent.request.method.toLowerCase();
|
|
34
|
+
let response = await router.route([httpMethodName === 'delete' ? 'del' : httpMethodName, 'default'], httpEvent, {}, async event => {
|
|
35
|
+
return remoteFetch(event.request);
|
|
36
|
+
}, remoteFetch);
|
|
37
|
+
if (!(response instanceof httpEvent.Response)) {
|
|
38
|
+
response = new httpEvent.Response(response);
|
|
39
|
+
}
|
|
40
|
+
return response;
|
|
41
|
+
};
|
|
42
|
+
return handle();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import Context from './Context.js';
|
|
6
|
+
import WorkerClient from './WorkerClient.js';
|
|
7
|
+
import Worker from './Worker.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @start
|
|
11
|
+
*/
|
|
12
|
+
export async function start(clientCallback = null) {
|
|
13
|
+
const cx = this || {};
|
|
14
|
+
const defaultClientCallback = _cx => new WorkerClient(_cx);
|
|
15
|
+
return new Worker(Context.create(cx), ( ...args ) => {
|
|
16
|
+
return clientCallback ? clientCallback( ...args.concat( defaultClientCallback ) ) : defaultClientCallback( ...args );
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -23,8 +23,8 @@ export default class Router extends _Router {
|
|
|
23
23
|
if (_segmentOnFile.index) return _segmentOnFile;
|
|
24
24
|
var _currentPath = thisTick.trailOnFile.concat(_seg).join('/'),
|
|
25
25
|
routeHandlerFile;
|
|
26
|
-
return Fs.existsSync(routeHandlerFile = Path.join(this.
|
|
27
|
-
Fs.existsSync(Path.join(this.
|
|
26
|
+
return Fs.existsSync(routeHandlerFile = Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, _currentPath, 'index.js')) ? { seg: _seg, index: routeHandlerFile } : (
|
|
27
|
+
Fs.existsSync(Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, _currentPath)) ? { seg: _seg, dirExists: true } : _segmentOnFile
|
|
28
28
|
);
|
|
29
29
|
}, { seg: null });
|
|
30
30
|
thisTick.trail.push(thisTick.currentSegment);
|
|
@@ -33,7 +33,7 @@ export default class Router extends _Router {
|
|
|
33
33
|
} else {
|
|
34
34
|
thisTick.trail = [];
|
|
35
35
|
thisTick.trailOnFile = [];
|
|
36
|
-
thisTick.currentSegmentOnFile = { index: Path.join(this.
|
|
36
|
+
thisTick.currentSegmentOnFile = { index: Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, 'index.js') };
|
|
37
37
|
thisTick.exports = Fs.existsSync(thisTick.currentSegmentOnFile.index)
|
|
38
38
|
? await import(Url.pathToFileURL(thisTick.currentSegmentOnFile.index))
|
|
39
39
|
: null;
|
|
@@ -58,9 +58,9 @@ export default class Router extends _Router {
|
|
|
58
58
|
*
|
|
59
59
|
* @return Promise
|
|
60
60
|
*/
|
|
61
|
-
|
|
61
|
+
file(event) {
|
|
62
62
|
var filename = event.url.pathname;
|
|
63
|
-
var _filename = Path.join(this.
|
|
63
|
+
var _filename = Path.join(this.cx.CWD, this.cx.layout.PUBLIC_DIR, decodeURIComponent(filename));
|
|
64
64
|
var autoIndex;
|
|
65
65
|
if (Fs.existsSync(_filename)) {
|
|
66
66
|
// based on the URL path, extract the file extention. e.g. .js, .doc, ...
|
|
@@ -115,7 +115,7 @@ export default class Router extends _Router {
|
|
|
115
115
|
* @return bool
|
|
116
116
|
*/
|
|
117
117
|
putPreRendered(filename, content) {
|
|
118
|
-
var _filename = Path.join(this.layout.PUBLIC_DIR, '.', filename);
|
|
118
|
+
var _filename = Path.join(this.cx.layout.PUBLIC_DIR, '.', filename);
|
|
119
119
|
if (!Path.parse(filename).ext && filename.lastIndexOf('.') < filename.lastIndexOf('/')) {
|
|
120
120
|
_filename = Path.join(_filename, '/index.html');
|
|
121
121
|
}
|