@webqit/webflo 0.20.4-next.1 → 0.20.4-next.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.
- package/package.json +5 -20
- package/site/.vitepress/config.ts +1 -1
- package/site/docs/concepts/realtime.md +57 -53
- package/site/docs/concepts/{request-response.md → requests-responses.md} +1 -1
- package/site/docs/concepts/state.md +1 -1
- package/site/docs/getting-started.md +40 -40
- package/src/{Context.js → CLIContext.js} +9 -8
- package/src/build-pi/esbuild-plugin-livejs-transform.js +35 -0
- package/src/{runtime-pi/webflo-client/webflo-codegen.js → build-pi/index.js} +145 -141
- package/src/index.js +3 -1
- package/src/init-pi/index.js +6 -3
- package/src/init-pi/templates/pwa/package.json +2 -2
- package/src/init-pi/templates/web/package.json +2 -2
- package/src/runtime-pi/AppBootstrap.js +38 -0
- package/src/runtime-pi/WebfloRuntime.js +50 -47
- package/src/runtime-pi/apis.js +9 -0
- package/src/runtime-pi/index.js +2 -4
- package/src/runtime-pi/webflo-client/WebfloClient.js +31 -35
- package/src/runtime-pi/webflo-client/WebfloRootClient1.js +16 -14
- package/src/runtime-pi/webflo-client/WebfloSubClient.js +13 -13
- package/src/runtime-pi/webflo-client/bootstrap.js +37 -0
- package/src/runtime-pi/webflo-client/index.js +2 -8
- package/src/runtime-pi/webflo-client/webflo-devmode.js +3 -3
- package/src/runtime-pi/webflo-fetch/LiveResponse.js +127 -96
- package/src/runtime-pi/webflo-fetch/index.js +435 -5
- package/src/runtime-pi/webflo-routing/HttpCookies.js +1 -1
- package/src/runtime-pi/webflo-routing/HttpEvent.js +5 -6
- package/src/runtime-pi/webflo-routing/HttpUser.js +7 -7
- package/src/runtime-pi/webflo-server/ServerSideCookies.js +3 -1
- package/src/runtime-pi/webflo-server/ServerSideSession.js +2 -1
- package/src/runtime-pi/webflo-server/WebfloServer.js +98 -195
- package/src/runtime-pi/webflo-server/bootstrap.js +59 -0
- package/src/runtime-pi/webflo-server/index.js +2 -6
- package/src/runtime-pi/webflo-server/webflo-devmode.js +13 -24
- package/src/runtime-pi/webflo-worker/WebfloWorker.js +11 -15
- package/src/runtime-pi/webflo-worker/WorkerSideCookies.js +2 -1
- package/src/runtime-pi/webflo-worker/bootstrap.js +38 -0
- package/src/runtime-pi/webflo-worker/index.js +3 -7
- package/src/webflo-cli.js +1 -2
- package/src/runtime-pi/webflo-fetch/cookies.js +0 -10
- package/src/runtime-pi/webflo-fetch/fetch.js +0 -16
- package/src/runtime-pi/webflo-fetch/formdata.js +0 -54
- package/src/runtime-pi/webflo-fetch/headers.js +0 -151
- package/src/runtime-pi/webflo-fetch/message.js +0 -49
- package/src/runtime-pi/webflo-fetch/request.js +0 -62
- package/src/runtime-pi/webflo-fetch/response.js +0 -110
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import Fs from 'fs';
|
|
2
2
|
import Path from 'path';
|
|
3
|
+
import Url from 'url';
|
|
3
4
|
import Jsdom from 'jsdom';
|
|
4
5
|
import EsBuild from 'esbuild';
|
|
5
6
|
import { gzipSync, brotliCompressSync } from 'zlib';
|
|
6
7
|
import { _afterLast, _beforeLast } from '@webqit/util/str/index.js';
|
|
7
8
|
import { _isObject, _isArray } from '@webqit/util/js/index.js';
|
|
8
9
|
import { jsFile } from '@webqit/backpack/src/dotfile/index.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
scanRoots,
|
|
16
|
-
scanRouteHandlers,
|
|
17
|
-
} from '../../deployment-pi/util.js';
|
|
18
|
-
import '../webflo-url/urlpattern.js';
|
|
10
|
+
import { bootstrap as serverBootstrap } from '../runtime-pi/webflo-server/bootstrap.js';
|
|
11
|
+
import { bootstrap as clientBootstrap } from '../runtime-pi/webflo-client/bootstrap.js';
|
|
12
|
+
import { bootstrap as workerBootstrap } from '../runtime-pi/webflo-worker/bootstrap.js';
|
|
13
|
+
import { LiveJSTransform } from './esbuild-plugin-livejs-transform.js';
|
|
14
|
+
import { CLIContext } from '../CLIContext.js';
|
|
15
|
+
import '../runtime-pi/webflo-url/urlpattern.js';
|
|
19
16
|
|
|
20
17
|
function declareConfig({ $source, configExport, indentation = 0 }) {
|
|
21
18
|
const varName = 'config';
|
|
@@ -51,20 +48,25 @@ function declareConfig({ $source, configExport, indentation = 0 }) {
|
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
function declareRoutes({ $context, $
|
|
51
|
+
function declareRoutes({ $context, $source, bootstrap }) {
|
|
55
52
|
const { flags: FLAGS, logger: LOGGER } = $context;
|
|
56
53
|
LOGGER?.log(LOGGER.style.keyword(`> `) + `Declaring routes...`);
|
|
54
|
+
|
|
57
55
|
// Define vars
|
|
58
56
|
const varName = 'routes';
|
|
59
|
-
const targetDir =
|
|
57
|
+
const targetDir = FLAGS.outdir || bootstrap.outdir;
|
|
58
|
+
|
|
60
59
|
// >> Routes mapping
|
|
61
60
|
$source.code.push(`const ${varName} = {};`);
|
|
61
|
+
|
|
62
62
|
// Route entries
|
|
63
63
|
let routeCount = 0;
|
|
64
|
-
|
|
64
|
+
for (const route of Object.keys(bootstrap.routes)) {
|
|
65
|
+
const file = bootstrap.routes[route];
|
|
66
|
+
const fstat = Fs.statSync(file);
|
|
65
67
|
// The "import" code
|
|
66
68
|
const routeId = 'route' + (++routeCount);
|
|
67
|
-
const importPath =
|
|
69
|
+
const importPath = file;
|
|
68
70
|
$source.imports[importPath] = '* as ' + routeId;
|
|
69
71
|
// The route def
|
|
70
72
|
$source.code.push(`${varName}['${route}'] = ${routeId};`);
|
|
@@ -72,35 +74,52 @@ function declareRoutes({ $context, $config, $source, which, offset, roots = [] }
|
|
|
72
74
|
LOGGER?.log(
|
|
73
75
|
LOGGER.style.comment(` [${route}]: `) + LOGGER.style.url(importPath) + LOGGER.style.comment(` (${fstat.size / 1024} KB)`)
|
|
74
76
|
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
$source.code.push(`Object.defineProperty(${varName}, '$root', { value: '${offset}' });`);
|
|
78
|
-
$source.code.push(`Object.defineProperty(${varName}, '$sparoots', { value: ${JSON.stringify(roots)} });`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
79
|
if (!routeCount) {
|
|
80
80
|
LOGGER?.log(LOGGER.style.comment(` (none)`));
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function writeImportWebflo($source, which) {
|
|
85
|
-
|
|
85
|
+
const importUrl = Url.fileURLToPath(import.meta.url);
|
|
86
|
+
const importPath = Path.join(Path.dirname(importUrl), `../runtime-pi/webflo-${which}/index.js`);
|
|
87
|
+
$source.imports[importPath] = `{ start }`;
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
function writeScriptBody({ $context, $
|
|
90
|
+
function writeScriptBody({ $context, $source, bootstrap, configExport, which }) {
|
|
91
|
+
// >> Init
|
|
92
|
+
if (bootstrap.$init) {
|
|
93
|
+
const importPath = bootstrap.$init;
|
|
94
|
+
$source.imports[importPath] = `* as init`;
|
|
95
|
+
} else {
|
|
96
|
+
$source.code.push(`const init = null;`);
|
|
97
|
+
}
|
|
98
|
+
|
|
89
99
|
// >> Config
|
|
90
100
|
$source.code.push(`// >> Config export`);
|
|
91
101
|
declareConfig({ $source, configExport });
|
|
92
102
|
$source.code.push(``);
|
|
103
|
+
|
|
93
104
|
// >> Routes mapping
|
|
94
105
|
$source.code.push(`// >> Routes`);
|
|
95
|
-
declareRoutes({ $context, $
|
|
106
|
+
declareRoutes({ $context, $source, bootstrap, which });
|
|
107
|
+
$source.code.push(``);
|
|
108
|
+
|
|
109
|
+
// >> Specials
|
|
110
|
+
$source.code.push(`// >> Routes`);
|
|
111
|
+
$source.code.push(`const $root = '${bootstrap.offset || null}';`);
|
|
112
|
+
$source.code.push(`const $roots = ${bootstrap.$roots?.length ? JSON.stringify(bootstrap.$roots) : '[]'};`);
|
|
113
|
+
$source.code.push(`const $sparoots = ${bootstrap.$sparoots?.length ? JSON.stringify(bootstrap.$sparoots) : '[]'};`);
|
|
96
114
|
$source.code.push(``);
|
|
115
|
+
|
|
97
116
|
// >> Startup
|
|
98
117
|
$source.code.push(`// >> Startup`);
|
|
99
|
-
$source.code.push(`
|
|
100
|
-
$source.code.push(`
|
|
118
|
+
$source.code.push(`globalThis.webqit = globalThis.webqit || {};`);
|
|
119
|
+
$source.code.push(`globalThis.webqit.app = await start({ init, config, routes, $root, $roots, $sparoots });`);
|
|
101
120
|
}
|
|
102
121
|
|
|
103
|
-
async function bundleScript({ $context, $source, which, outfile, asModule =
|
|
122
|
+
async function bundleScript({ $context, $source, which, outfile, asModule = true, ...restParams }) {
|
|
104
123
|
const { flags: FLAGS, logger: LOGGER } = $context;
|
|
105
124
|
// >> Show banner...
|
|
106
125
|
LOGGER?.log(LOGGER.style.keyword(`---`));
|
|
@@ -126,11 +145,14 @@ async function bundleScript({ $context, $source, which, outfile, asModule = fals
|
|
|
126
145
|
const bundlingConfig = {
|
|
127
146
|
entryPoints: [moduleFile],
|
|
128
147
|
outfile,
|
|
129
|
-
bundle: true,
|
|
148
|
+
bundle: which === 'server' ? false : true,
|
|
130
149
|
minify: true,
|
|
150
|
+
format: asModule ? 'esm' : 'iife',
|
|
151
|
+
platform: which === 'server' ? 'node' : 'browser', // optional but good for clarity
|
|
152
|
+
treeShaking: true, // Important optimization
|
|
131
153
|
banner: { js: '/** @webqit/webflo */', },
|
|
132
154
|
footer: { js: '', },
|
|
133
|
-
|
|
155
|
+
plugins: [ LiveJSTransform() ],
|
|
134
156
|
...(restParams.buildParams || {})
|
|
135
157
|
};
|
|
136
158
|
if (!asModule) {
|
|
@@ -248,38 +270,35 @@ function handleEmbeds($context, embeds, targetDocumentFile) {
|
|
|
248
270
|
|
|
249
271
|
// -------------
|
|
250
272
|
|
|
251
|
-
async function generateClientScript({ $context,
|
|
273
|
+
async function generateClientScript({ $context, bootstrap, ...restParams }) {
|
|
252
274
|
const { flags: FLAGS, logger: LOGGER } = $context;
|
|
253
|
-
|
|
254
|
-
const inSplitMode = !!roots.length || !!offset;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
// The source code
|
|
275
|
+
|
|
276
|
+
const inSplitMode = !!bootstrap.$roots.length || !!bootstrap.offset;
|
|
277
|
+
|
|
278
|
+
const targetDocumentFile = Path.join(FLAGS.outdir || bootstrap.outdir, 'index.html');
|
|
279
|
+
const publicBaseUrl = bootstrap.config.CLIENT.public_base_url;
|
|
280
|
+
|
|
281
|
+
const sharedBuild_filename = bootstrap.config.CLIENT.filename.replace(/\.js$/, '.webflo.js');
|
|
282
|
+
const outfile_sharedBuild = Path.join(bootstrap.config.LAYOUT.PUBLIC_DIR, sharedBuild_filename);
|
|
283
|
+
const outfile_sharedBuildPublic = Path.join(publicBaseUrl, sharedBuild_filename);
|
|
284
|
+
|
|
285
|
+
const outfile_clientBuild = Path.join(FLAGS.outdir || bootstrap.outdir, bootstrap.config.CLIENT.filename);
|
|
286
|
+
const outfile_clientBuildPublic = Path.join(publicBaseUrl, Path.relative(bootstrap.config.LAYOUT.PUBLIC_DIR, outfile_clientBuild));
|
|
287
|
+
|
|
267
288
|
const $source = { imports: {}, code: [] };
|
|
268
289
|
const embeds = { all: [], current: [] };
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
scope: $config.WORKER.scope
|
|
290
|
+
|
|
291
|
+
const configExport = structuredClone({ ENV: bootstrap.config.ENV, CLIENT: bootstrap.config.CLIENT, WORKER: {} });
|
|
292
|
+
if (bootstrap.config.CLIENT.capabilities?.service_worker === true) {
|
|
293
|
+
configExport.WORKER = {
|
|
294
|
+
filename: Path.join(publicBaseUrl.replace(/^\//, ''), bootstrap.config.WORKER.filename),
|
|
295
|
+
scope: bootstrap.config.WORKER.scope
|
|
276
296
|
};
|
|
277
297
|
}
|
|
278
|
-
|
|
298
|
+
|
|
279
299
|
const outfiles = [];
|
|
280
300
|
if (inSplitMode) {
|
|
281
|
-
if (!offset) {
|
|
282
|
-
// We're building the Webflo client as a standalone script
|
|
301
|
+
if (!bootstrap.offset) {
|
|
283
302
|
LOGGER?.log(LOGGER.style.keyword(`---`));
|
|
284
303
|
LOGGER?.log(`[SPLIT_MODE] Base Build`);
|
|
285
304
|
LOGGER?.log(LOGGER.style.keyword(`---`));
|
|
@@ -290,79 +309,64 @@ async function generateClientScript({ $context, $config, offset = '', roots = []
|
|
|
290
309
|
$context,
|
|
291
310
|
$source: $$source,
|
|
292
311
|
which: 'client',
|
|
293
|
-
outfile:
|
|
312
|
+
outfile: outfile_sharedBuild,
|
|
294
313
|
asModule: true
|
|
295
314
|
});
|
|
296
315
|
outfiles.push(..._outfiles);
|
|
297
316
|
}
|
|
298
317
|
if (FLAGS['auto-embed']) {
|
|
299
|
-
embeds.current.push(
|
|
300
|
-
embeds.current.push(
|
|
318
|
+
embeds.current.push(outfile_sharedBuildPublic);
|
|
319
|
+
embeds.current.push(outfile_clientBuildPublic);
|
|
301
320
|
}
|
|
302
321
|
} else {
|
|
303
|
-
// We're building the Webflo client as part of the main script
|
|
304
322
|
writeImportWebflo($source, 'client');
|
|
305
323
|
if (FLAGS['auto-embed']) {
|
|
306
|
-
embeds.current.push(
|
|
324
|
+
embeds.current.push(outfile_clientBuildPublic);
|
|
307
325
|
}
|
|
308
326
|
}
|
|
309
|
-
|
|
327
|
+
|
|
310
328
|
writeScriptBody({
|
|
311
329
|
$context,
|
|
312
|
-
$config,
|
|
313
330
|
$source,
|
|
314
|
-
|
|
315
|
-
offset,
|
|
316
|
-
roots,
|
|
331
|
+
bootstrap,
|
|
317
332
|
configExport,
|
|
333
|
+
which: 'client',
|
|
318
334
|
...restParams
|
|
319
335
|
});
|
|
320
|
-
|
|
336
|
+
|
|
321
337
|
const _outfiles = await bundleScript({
|
|
322
338
|
$context,
|
|
323
339
|
$source,
|
|
324
340
|
which: 'client',
|
|
325
|
-
outfile:
|
|
341
|
+
outfile: outfile_clientBuild,
|
|
326
342
|
asModule: true,
|
|
327
343
|
...restParams
|
|
328
344
|
});
|
|
329
345
|
outfiles.push(..._outfiles);
|
|
330
|
-
|
|
331
|
-
embeds.all.push(
|
|
332
|
-
embeds.all.push(
|
|
346
|
+
|
|
347
|
+
embeds.all.push(outfile_sharedBuildPublic);
|
|
348
|
+
embeds.all.push(outfile_clientBuildPublic);
|
|
333
349
|
handleEmbeds($context, embeds, targetDocumentFile);
|
|
334
|
-
|
|
335
|
-
if (FLAGS.recursive && roots.length) {
|
|
336
|
-
const $roots = roots.slice(0);
|
|
337
|
-
const _outfiles = await generateClientScript({
|
|
338
|
-
$context,
|
|
339
|
-
$config,
|
|
340
|
-
offset: $roots.shift(),
|
|
341
|
-
roots: $roots,
|
|
342
|
-
...restParams
|
|
343
|
-
});
|
|
344
|
-
return outfiles.concat(_outfiles);
|
|
345
|
-
}
|
|
350
|
+
|
|
346
351
|
return outfiles;
|
|
347
352
|
}
|
|
348
353
|
|
|
349
|
-
async function generateWorkerScript({ $context,
|
|
354
|
+
async function generateWorkerScript({ $context, bootstrap, ...restParams }) {
|
|
350
355
|
const { flags: FLAGS } = $context;
|
|
351
|
-
|
|
352
|
-
const outfile_mainBuild = Path.join(offset, $config.WORKER.filename);
|
|
356
|
+
|
|
353
357
|
const $source = { imports: {}, code: [] };
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
358
|
+
|
|
359
|
+
const outfile_workerBuild = Path.join(FLAGS.outdir || bootstrap.outdir, bootstrap.config.WORKER.filename);
|
|
360
|
+
|
|
361
|
+
const configExport = structuredClone({ ENV: bootstrap.config.ENV, CLIENT: { capabilities: {} }, WORKER: bootstrap.config.WORKER });
|
|
362
|
+
if (bootstrap.config.CLIENT.capabilities?.webpush === true) {
|
|
363
|
+
configExport.CLIENT.capabilities = {
|
|
359
364
|
webpush: true
|
|
360
365
|
};
|
|
361
366
|
}
|
|
362
|
-
|
|
367
|
+
|
|
363
368
|
for (const strategy of ['cache_first_urls', 'cache_only_urls']) {
|
|
364
369
|
if (configExport.WORKER[strategy].length) {
|
|
365
|
-
// Separate URLs from patterns
|
|
366
370
|
const [urls, patterns] = configExport.WORKER[strategy].reduce(([urls, patterns], url) => {
|
|
367
371
|
const patternInstance = new URLPattern(url, 'http://localhost');
|
|
368
372
|
const isPattern = patternInstance.isPattern();
|
|
@@ -371,20 +375,17 @@ async function generateWorkerScript({ $context, $config, offset = '', roots = []
|
|
|
371
375
|
}
|
|
372
376
|
return isPattern ? [urls, patterns.concat(patternInstance)] : [urls.concat(url), patterns];
|
|
373
377
|
}, [[], []]);
|
|
374
|
-
// Resolve patterns
|
|
375
378
|
if (patterns.length) {
|
|
376
|
-
// List all files
|
|
377
379
|
function scanDir(dir) {
|
|
378
380
|
Fs.readdirSync(dir).reduce((result, f) => {
|
|
379
381
|
const resource = Path.join(dir, f);
|
|
380
382
|
if (f.startsWith('.')) return result;
|
|
381
383
|
return result.concat(
|
|
382
|
-
Fs.statSync(resource).isDirectory() ? scanDir(resource) : '/' + Path.relative(
|
|
384
|
+
Fs.statSync(resource).isDirectory() ? scanDir(resource) : '/' + Path.relative(bootstrap.config.LAYOUT.PUBLIC_DIR, resource)
|
|
383
385
|
);
|
|
384
386
|
}, []);
|
|
385
387
|
}
|
|
386
|
-
const files = scanDir(
|
|
387
|
-
// Resolve patterns from files
|
|
388
|
+
const files = scanDir(bootstrap.config.LAYOUT.PUBLIC_DIR);
|
|
388
389
|
configExport.WORKER[strategy] = patterns.reduce((all, pattern) => {
|
|
389
390
|
const matchedFiles = files.filter((file) => pattern.test(file, 'http://localhost'));
|
|
390
391
|
if (matchedFiles.length) return all.concat(matchedFiles);
|
|
@@ -393,77 +394,80 @@ async function generateWorkerScript({ $context, $config, offset = '', roots = []
|
|
|
393
394
|
}
|
|
394
395
|
}
|
|
395
396
|
}
|
|
396
|
-
|
|
397
|
+
|
|
397
398
|
writeImportWebflo($source, 'worker');
|
|
398
|
-
// 3. Write the body and bundle
|
|
399
399
|
writeScriptBody({
|
|
400
400
|
$context,
|
|
401
|
-
$config,
|
|
402
401
|
$source,
|
|
403
|
-
|
|
404
|
-
offset,
|
|
405
|
-
roots,
|
|
402
|
+
bootstrap,
|
|
406
403
|
configExport,
|
|
404
|
+
which: 'worker',
|
|
407
405
|
...restParams
|
|
408
406
|
});
|
|
409
|
-
|
|
410
|
-
|
|
407
|
+
|
|
408
|
+
return await bundleScript({
|
|
411
409
|
$context,
|
|
412
410
|
$source,
|
|
413
411
|
which: 'worker',
|
|
414
|
-
outfile:
|
|
415
|
-
asModule:
|
|
412
|
+
outfile: outfile_workerBuild,
|
|
413
|
+
asModule: true,
|
|
414
|
+
...restParams
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async function generateServerScript({ $context, bootstrap, ...restParams }) {
|
|
419
|
+
const $source = { imports: {}, code: [] };
|
|
420
|
+
const outfile_serverBuild = Path.join(bootstrap.outdir, 'app.js'); // Must not consult FLAGS.outdir
|
|
421
|
+
|
|
422
|
+
writeImportWebflo($source, 'server');
|
|
423
|
+
writeScriptBody({
|
|
424
|
+
$context,
|
|
425
|
+
$source,
|
|
426
|
+
bootstrap,
|
|
427
|
+
configExport: bootstrap.config,
|
|
428
|
+
which: 'server',
|
|
429
|
+
...restParams
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
return await bundleScript({
|
|
433
|
+
$context,
|
|
434
|
+
$source,
|
|
435
|
+
which: 'server',
|
|
436
|
+
outfile: outfile_serverBuild,
|
|
437
|
+
asModule: true,
|
|
416
438
|
...restParams
|
|
417
439
|
});
|
|
418
|
-
// -----------
|
|
419
|
-
if (FLAGS.recursive && roots.length) {
|
|
420
|
-
const $roots = roots.slice(0);
|
|
421
|
-
const _outfiles = await generateWorkerScript({
|
|
422
|
-
$context,
|
|
423
|
-
$config,
|
|
424
|
-
offset: $roots.shift(),
|
|
425
|
-
roots: $roots,
|
|
426
|
-
...restParams
|
|
427
|
-
});
|
|
428
|
-
return outfiles.concat(_outfiles);
|
|
429
|
-
}
|
|
430
|
-
return outfiles;
|
|
431
440
|
}
|
|
432
441
|
|
|
433
|
-
export async function
|
|
442
|
+
export async function build() {
|
|
434
443
|
const $context = this;
|
|
435
|
-
if (!($context instanceof
|
|
436
|
-
throw new Error(`The "this" context must be a Webflo
|
|
444
|
+
if (!($context instanceof CLIContext)) {
|
|
445
|
+
throw new Error(`The "this" context must be a Webflo CLIContext object.`);
|
|
437
446
|
}
|
|
438
|
-
|
|
439
|
-
const
|
|
440
|
-
LAYOUT: await readLayoutConfig($context),
|
|
441
|
-
ENV: { ...await readEnvConfig($context), data: {} },
|
|
442
|
-
CLIENT: await readClientConfig($context),
|
|
443
|
-
WORKER: await readWorkerConfig($context),
|
|
444
|
-
};
|
|
445
|
-
if ($config.CLIENT.copy_public_variables) {
|
|
446
|
-
const publicEnvPattern = /(?:^|_)PUBLIC(?:_|$)/;
|
|
447
|
-
for (const key in process.env) {
|
|
448
|
-
if (publicEnvPattern.test(key)) {
|
|
449
|
-
$config.ENV.data[key] = process.env[key];
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
// Build
|
|
447
|
+
|
|
448
|
+
const buildParams = {};
|
|
454
449
|
const outfiles = [];
|
|
455
|
-
if (client) {
|
|
456
|
-
const
|
|
457
|
-
const _outfiles = await generateClientScript({ $context,
|
|
450
|
+
if ($context.flags.client) {
|
|
451
|
+
const bootstrap = await clientBootstrap($context);
|
|
452
|
+
const _outfiles = await generateClientScript({ $context, bootstrap, buildParams });
|
|
453
|
+
outfiles.push(..._outfiles);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if ($context.flags.worker) {
|
|
457
|
+
const bootstrap = await workerBootstrap($context);
|
|
458
|
+
const _outfiles = await generateWorkerScript({ $context, bootstrap, buildParams });
|
|
458
459
|
outfiles.push(..._outfiles);
|
|
459
460
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const
|
|
461
|
+
|
|
462
|
+
if (false) { // TODO: WebfloServer needs to be buildable first
|
|
463
|
+
const bootstrap = await serverBootstrap($context);
|
|
464
|
+
const _outfiles = await generateServerScript({ $context, bootstrap, buildParams });
|
|
463
465
|
outfiles.push(..._outfiles);
|
|
464
466
|
}
|
|
467
|
+
|
|
465
468
|
if (process.send) {
|
|
466
469
|
process.send({ outfiles });
|
|
467
470
|
}
|
|
471
|
+
|
|
468
472
|
return { outfiles };
|
|
469
473
|
}
|
package/src/index.js
CHANGED
|
@@ -3,12 +3,14 @@ import * as deployment from './deployment-pi/index.js';
|
|
|
3
3
|
import * as runtime from './runtime-pi/index.js';
|
|
4
4
|
import * as services from './services-pi/index.js';
|
|
5
5
|
import * as starter from './init-pi/index.js';
|
|
6
|
+
import * as build from './build-pi/index.js';
|
|
6
7
|
|
|
7
|
-
export {
|
|
8
|
+
export { CLIContext } from './CLIContext.js';
|
|
8
9
|
export {
|
|
9
10
|
config,
|
|
10
11
|
deployment,
|
|
11
12
|
runtime,
|
|
12
13
|
services,
|
|
13
14
|
starter,
|
|
15
|
+
build,
|
|
14
16
|
}
|
package/src/init-pi/index.js
CHANGED
|
@@ -4,7 +4,8 @@ import Path from 'path';
|
|
|
4
4
|
import { exec } from 'child_process';
|
|
5
5
|
import { _toTitle } from '@webqit/util/str/index.js';
|
|
6
6
|
import { readInitConfig } from '../deployment-pi/util.js';
|
|
7
|
-
import {
|
|
7
|
+
import { CLIContext } from '../CLIContext.js';
|
|
8
|
+
import * as deployment from '../deployment-pi/index.js';
|
|
8
9
|
|
|
9
10
|
export const desc = {
|
|
10
11
|
init: 'Generate a preset Webflo starter app.',
|
|
@@ -12,9 +13,11 @@ export const desc = {
|
|
|
12
13
|
|
|
13
14
|
export async function init(projectName = 'my-webflo-app', projectTitle = '', projectDescription = '') {
|
|
14
15
|
const $context = this;
|
|
16
|
+
//middlewares: [ deployment.origins.webhook ],
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
if (!($context instanceof CLIContext)) {
|
|
20
|
+
throw new Error(`The "this" context must be a Webflo CLIContext object.`);
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
const { flags: FLAGS, logger: LOGGER } = $context;
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build:html": "oohtml bundle --recursive --outdir=public/assets --auto-embed=app",
|
|
8
|
-
"build:js": "webflo
|
|
8
|
+
"build:js": "webflo build --client --worker --server --recursive --outdir=public/assets --auto-embed",
|
|
9
9
|
"build": "npm run build:html && npm run build:js",
|
|
10
|
-
"dev": "webflo start --dev --build-sensitivity=
|
|
10
|
+
"dev": "webflo start --dev --build-sensitivity=1",
|
|
11
11
|
"start": "webflo start"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build:html": "oohtml bundle --recursive --outdir=public/assets --auto-embed=app",
|
|
8
|
-
"build:js": "webflo
|
|
8
|
+
"build:js": "webflo build --client --worker --server --recursive --outdir=public/assets --auto-embed",
|
|
9
9
|
"build": "npm run build:html && npm run build:js",
|
|
10
|
-
"dev": "webflo start --dev --build-sensitivity=
|
|
10
|
+
"dev": "webflo start --dev --build-sensitivity=1",
|
|
11
11
|
"start": "webflo start"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { CLIContext } from '../CLIContext.js';
|
|
2
|
+
|
|
3
|
+
export class AppBootstrap {
|
|
4
|
+
|
|
5
|
+
#json;
|
|
6
|
+
#cx;
|
|
7
|
+
#init;
|
|
8
|
+
|
|
9
|
+
constructor(json = {}) {
|
|
10
|
+
this.#json = json;
|
|
11
|
+
this.#cx = new CLIContext(json.cx || {});
|
|
12
|
+
this.#init = { ...(json.init || {})};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// cx
|
|
16
|
+
get cx() { return this.#cx; }
|
|
17
|
+
|
|
18
|
+
// init
|
|
19
|
+
get init() { return this.#init; }
|
|
20
|
+
|
|
21
|
+
// $root
|
|
22
|
+
get $root() { return this.#json.offset || ''; }
|
|
23
|
+
|
|
24
|
+
// $roots
|
|
25
|
+
get $roots() { return this.#json.$roots || []; }
|
|
26
|
+
|
|
27
|
+
// $sparoots
|
|
28
|
+
get $sparoots() { return this.#json.$sparoots || []; }
|
|
29
|
+
|
|
30
|
+
// config
|
|
31
|
+
get config() { return this.#json.config || {}; }
|
|
32
|
+
|
|
33
|
+
// routes
|
|
34
|
+
get routes() { return this.#json.routes || {}; }
|
|
35
|
+
|
|
36
|
+
// middlewares
|
|
37
|
+
get middlewares() { return this.#json.middlewares || []; }
|
|
38
|
+
}
|