@webqit/webflo 0.20.4-next.2 → 0.20.4-next.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/package.json +13 -34
- package/site/docs/concepts/realtime.md +45 -44
- package/site/docs/getting-started.md +40 -40
- package/src/{Context.js → CLIContext.js} +9 -8
- package/src/build-pi/esbuild-plugin-uselive-transform.js +42 -0
- package/src/{runtime-pi/webflo-client/webflo-codegen.js → build-pi/index.js} +148 -142
- package/src/index.js +3 -1
- package/src/init-pi/index.js +7 -4
- package/src/init-pi/templates/pwa/.gitignore +6 -0
- package/src/init-pi/templates/pwa/.webqit/webflo/client.json +15 -0
- package/src/init-pi/templates/pwa/.webqit/webflo/layout.json +7 -0
- package/src/init-pi/templates/pwa/package.json +2 -2
- package/src/init-pi/templates/pwa/public/manifest.json +2 -2
- package/src/init-pi/templates/web/.gitignore +6 -0
- package/src/init-pi/templates/web/.webqit/webflo/client.json +12 -0
- package/src/init-pi/templates/web/.webqit/webflo/layout.json +7 -0
- package/src/init-pi/templates/web/package.json +2 -2
- package/src/runtime-pi/AppBootstrap.js +38 -0
- package/src/runtime-pi/WebfloRuntime.js +68 -56
- package/src/runtime-pi/apis.js +9 -0
- package/src/runtime-pi/index.js +2 -4
- package/src/runtime-pi/webflo-client/DeviceCapabilities.js +1 -1
- package/src/runtime-pi/webflo-client/WebfloClient.js +33 -36
- package/src/runtime-pi/webflo-client/WebfloRootClient1.js +23 -17
- package/src/runtime-pi/webflo-client/WebfloRootClient2.js +1 -1
- package/src/runtime-pi/webflo-client/WebfloSubClient.js +14 -14
- package/src/runtime-pi/webflo-client/bootstrap.js +38 -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 +154 -116
- package/src/runtime-pi/webflo-fetch/index.js +436 -5
- package/src/runtime-pi/webflo-messaging/wq-message-port.js +1 -1
- package/src/runtime-pi/webflo-routing/HttpCookies.js +1 -1
- package/src/runtime-pi/webflo-routing/HttpEvent.js +12 -11
- package/src/runtime-pi/webflo-routing/HttpUser.js +7 -7
- package/src/runtime-pi/webflo-routing/WebfloRouter.js +12 -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 +138 -200
- 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 +24 -31
- package/src/runtime-pi/webflo-url/Url.js +1 -1
- package/src/runtime-pi/webflo-url/xURL.js +1 -1
- 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 +39 -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 { UseLiveTransform } from './esbuild-plugin-uselive-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
|
-
|
|
130
|
-
|
|
148
|
+
format: asModule ? 'esm' : 'iife',
|
|
149
|
+
platform: which === 'server' ? 'node' : 'browser', // optional but good for clarity
|
|
150
|
+
bundle: which === 'server' ? false : true,
|
|
151
|
+
minify: which === 'server' ? false : true,
|
|
152
|
+
treeShaking: true, // Important optimization
|
|
131
153
|
banner: { js: '/** @webqit/webflo */', },
|
|
132
154
|
footer: { js: '', },
|
|
133
|
-
|
|
155
|
+
plugins: [UseLiveTransform()],
|
|
134
156
|
...(restParams.buildParams || {})
|
|
135
157
|
};
|
|
136
158
|
if (!asModule) {
|
|
@@ -248,38 +270,37 @@ 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
|
-
|
|
290
|
+
|
|
291
|
+
const configExport = structuredClone({ ENV: bootstrap.config.ENV, CLIENT: bootstrap.config.CLIENT, WORKER: {} });
|
|
292
|
+
if (bootstrap.config.CLIENT.capabilities?.service_worker === true) {
|
|
293
|
+
const outfile_workerBuild = Path.join(FLAGS.outdir || bootstrap.outdir, bootstrap.config.WORKER.filename);
|
|
294
|
+
const outfile_workerBuildPublic = Path.join(publicBaseUrl, Path.relative(bootstrap.config.LAYOUT.PUBLIC_DIR, outfile_workerBuild));
|
|
295
|
+
configExport.WORKER = {
|
|
296
|
+
filename: outfile_workerBuildPublic,
|
|
297
|
+
scope: bootstrap.config.WORKER.scope
|
|
276
298
|
};
|
|
277
299
|
}
|
|
278
|
-
|
|
300
|
+
|
|
279
301
|
const outfiles = [];
|
|
280
302
|
if (inSplitMode) {
|
|
281
|
-
if (!offset) {
|
|
282
|
-
// We're building the Webflo client as a standalone script
|
|
303
|
+
if (!bootstrap.offset) {
|
|
283
304
|
LOGGER?.log(LOGGER.style.keyword(`---`));
|
|
284
305
|
LOGGER?.log(`[SPLIT_MODE] Base Build`);
|
|
285
306
|
LOGGER?.log(LOGGER.style.keyword(`---`));
|
|
@@ -290,79 +311,64 @@ async function generateClientScript({ $context, $config, offset = '', roots = []
|
|
|
290
311
|
$context,
|
|
291
312
|
$source: $$source,
|
|
292
313
|
which: 'client',
|
|
293
|
-
outfile:
|
|
314
|
+
outfile: outfile_sharedBuild,
|
|
294
315
|
asModule: true
|
|
295
316
|
});
|
|
296
317
|
outfiles.push(..._outfiles);
|
|
297
318
|
}
|
|
298
319
|
if (FLAGS['auto-embed']) {
|
|
299
|
-
embeds.current.push(
|
|
300
|
-
embeds.current.push(
|
|
320
|
+
embeds.current.push(outfile_sharedBuildPublic);
|
|
321
|
+
embeds.current.push(outfile_clientBuildPublic);
|
|
301
322
|
}
|
|
302
323
|
} else {
|
|
303
|
-
// We're building the Webflo client as part of the main script
|
|
304
324
|
writeImportWebflo($source, 'client');
|
|
305
325
|
if (FLAGS['auto-embed']) {
|
|
306
|
-
embeds.current.push(
|
|
326
|
+
embeds.current.push(outfile_clientBuildPublic);
|
|
307
327
|
}
|
|
308
328
|
}
|
|
309
|
-
|
|
329
|
+
|
|
310
330
|
writeScriptBody({
|
|
311
331
|
$context,
|
|
312
|
-
$config,
|
|
313
332
|
$source,
|
|
314
|
-
|
|
315
|
-
offset,
|
|
316
|
-
roots,
|
|
333
|
+
bootstrap,
|
|
317
334
|
configExport,
|
|
335
|
+
which: 'client',
|
|
318
336
|
...restParams
|
|
319
337
|
});
|
|
320
|
-
|
|
338
|
+
|
|
321
339
|
const _outfiles = await bundleScript({
|
|
322
340
|
$context,
|
|
323
341
|
$source,
|
|
324
342
|
which: 'client',
|
|
325
|
-
outfile:
|
|
343
|
+
outfile: outfile_clientBuild,
|
|
326
344
|
asModule: true,
|
|
327
345
|
...restParams
|
|
328
346
|
});
|
|
329
347
|
outfiles.push(..._outfiles);
|
|
330
|
-
|
|
331
|
-
embeds.all.push(
|
|
332
|
-
embeds.all.push(
|
|
348
|
+
|
|
349
|
+
embeds.all.push(outfile_sharedBuildPublic);
|
|
350
|
+
embeds.all.push(outfile_clientBuildPublic);
|
|
333
351
|
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
|
-
}
|
|
352
|
+
|
|
346
353
|
return outfiles;
|
|
347
354
|
}
|
|
348
355
|
|
|
349
|
-
async function generateWorkerScript({ $context,
|
|
356
|
+
async function generateWorkerScript({ $context, bootstrap, ...restParams }) {
|
|
350
357
|
const { flags: FLAGS } = $context;
|
|
351
|
-
|
|
352
|
-
const outfile_mainBuild = Path.join(offset, $config.WORKER.filename);
|
|
358
|
+
|
|
353
359
|
const $source = { imports: {}, code: [] };
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
360
|
+
|
|
361
|
+
const outfile_workerBuild = Path.join(FLAGS.outdir || bootstrap.outdir, bootstrap.config.WORKER.filename);
|
|
362
|
+
|
|
363
|
+
const configExport = structuredClone({ ENV: bootstrap.config.ENV, CLIENT: { capabilities: {} }, WORKER: bootstrap.config.WORKER });
|
|
364
|
+
if (bootstrap.config.CLIENT.capabilities?.webpush === true) {
|
|
365
|
+
configExport.CLIENT.capabilities = {
|
|
359
366
|
webpush: true
|
|
360
367
|
};
|
|
361
368
|
}
|
|
362
|
-
|
|
369
|
+
|
|
363
370
|
for (const strategy of ['cache_first_urls', 'cache_only_urls']) {
|
|
364
371
|
if (configExport.WORKER[strategy].length) {
|
|
365
|
-
// Separate URLs from patterns
|
|
366
372
|
const [urls, patterns] = configExport.WORKER[strategy].reduce(([urls, patterns], url) => {
|
|
367
373
|
const patternInstance = new URLPattern(url, 'http://localhost');
|
|
368
374
|
const isPattern = patternInstance.isPattern();
|
|
@@ -371,20 +377,17 @@ async function generateWorkerScript({ $context, $config, offset = '', roots = []
|
|
|
371
377
|
}
|
|
372
378
|
return isPattern ? [urls, patterns.concat(patternInstance)] : [urls.concat(url), patterns];
|
|
373
379
|
}, [[], []]);
|
|
374
|
-
// Resolve patterns
|
|
375
380
|
if (patterns.length) {
|
|
376
|
-
// List all files
|
|
377
381
|
function scanDir(dir) {
|
|
378
382
|
Fs.readdirSync(dir).reduce((result, f) => {
|
|
379
383
|
const resource = Path.join(dir, f);
|
|
380
384
|
if (f.startsWith('.')) return result;
|
|
381
385
|
return result.concat(
|
|
382
|
-
Fs.statSync(resource).isDirectory() ? scanDir(resource) : '/' + Path.relative(
|
|
386
|
+
Fs.statSync(resource).isDirectory() ? scanDir(resource) : '/' + Path.relative(bootstrap.config.LAYOUT.PUBLIC_DIR, resource)
|
|
383
387
|
);
|
|
384
388
|
}, []);
|
|
385
389
|
}
|
|
386
|
-
const files = scanDir(
|
|
387
|
-
// Resolve patterns from files
|
|
390
|
+
const files = scanDir(bootstrap.config.LAYOUT.PUBLIC_DIR);
|
|
388
391
|
configExport.WORKER[strategy] = patterns.reduce((all, pattern) => {
|
|
389
392
|
const matchedFiles = files.filter((file) => pattern.test(file, 'http://localhost'));
|
|
390
393
|
if (matchedFiles.length) return all.concat(matchedFiles);
|
|
@@ -393,77 +396,80 @@ async function generateWorkerScript({ $context, $config, offset = '', roots = []
|
|
|
393
396
|
}
|
|
394
397
|
}
|
|
395
398
|
}
|
|
396
|
-
|
|
399
|
+
|
|
397
400
|
writeImportWebflo($source, 'worker');
|
|
398
|
-
// 3. Write the body and bundle
|
|
399
401
|
writeScriptBody({
|
|
400
402
|
$context,
|
|
401
|
-
$config,
|
|
402
403
|
$source,
|
|
403
|
-
|
|
404
|
-
offset,
|
|
405
|
-
roots,
|
|
404
|
+
bootstrap,
|
|
406
405
|
configExport,
|
|
406
|
+
which: 'worker',
|
|
407
407
|
...restParams
|
|
408
408
|
});
|
|
409
|
-
|
|
410
|
-
|
|
409
|
+
|
|
410
|
+
return await bundleScript({
|
|
411
411
|
$context,
|
|
412
412
|
$source,
|
|
413
413
|
which: 'worker',
|
|
414
|
-
outfile:
|
|
415
|
-
asModule:
|
|
414
|
+
outfile: outfile_workerBuild,
|
|
415
|
+
asModule: true,
|
|
416
|
+
...restParams
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async function generateServerScript({ $context, bootstrap, ...restParams }) {
|
|
421
|
+
const $source = { imports: {}, code: [] };
|
|
422
|
+
const outfile_serverBuild = Path.join(bootstrap.outdir, 'app.js'); // Must not consult FLAGS.outdir
|
|
423
|
+
|
|
424
|
+
writeImportWebflo($source, 'server');
|
|
425
|
+
writeScriptBody({
|
|
426
|
+
$context,
|
|
427
|
+
$source,
|
|
428
|
+
bootstrap,
|
|
429
|
+
configExport: bootstrap.config,
|
|
430
|
+
which: 'server',
|
|
431
|
+
...restParams
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
return await bundleScript({
|
|
435
|
+
$context,
|
|
436
|
+
$source,
|
|
437
|
+
which: 'server',
|
|
438
|
+
outfile: outfile_serverBuild,
|
|
439
|
+
asModule: true,
|
|
416
440
|
...restParams
|
|
417
441
|
});
|
|
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
442
|
}
|
|
432
443
|
|
|
433
|
-
export async function
|
|
444
|
+
export async function build() {
|
|
434
445
|
const $context = this;
|
|
435
|
-
if (!($context instanceof
|
|
436
|
-
throw new Error(`The "this" context must be a Webflo
|
|
446
|
+
if (!($context instanceof CLIContext)) {
|
|
447
|
+
throw new Error(`The "this" context must be a Webflo CLIContext object.`);
|
|
437
448
|
}
|
|
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
|
|
449
|
+
|
|
450
|
+
const buildParams = {};
|
|
454
451
|
const outfiles = [];
|
|
455
|
-
if (client) {
|
|
456
|
-
const
|
|
457
|
-
const _outfiles = await generateClientScript({ $context,
|
|
452
|
+
if ($context.flags.client) {
|
|
453
|
+
const bootstrap = await clientBootstrap($context);
|
|
454
|
+
const _outfiles = await generateClientScript({ $context, bootstrap, buildParams });
|
|
455
|
+
outfiles.push(..._outfiles);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if ($context.flags.worker) {
|
|
459
|
+
const bootstrap = await workerBootstrap($context);
|
|
460
|
+
const _outfiles = await generateWorkerScript({ $context, bootstrap, buildParams });
|
|
458
461
|
outfiles.push(..._outfiles);
|
|
459
462
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const
|
|
463
|
+
|
|
464
|
+
if (false) { // TODO: WebfloServer needs to be buildable first
|
|
465
|
+
const bootstrap = await serverBootstrap($context);
|
|
466
|
+
const _outfiles = await generateServerScript({ $context, bootstrap, buildParams });
|
|
463
467
|
outfiles.push(..._outfiles);
|
|
464
468
|
}
|
|
469
|
+
|
|
465
470
|
if (process.send) {
|
|
466
471
|
process.send({ outfiles });
|
|
467
472
|
}
|
|
473
|
+
|
|
468
474
|
return { outfiles };
|
|
469
475
|
}
|
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;
|
|
@@ -37,7 +40,7 @@ export async function init(projectName = 'my-webflo-app', projectTitle = '', pro
|
|
|
37
40
|
process.exit(1);
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
LOGGER?.log(LOGGER.style.keyword(`> `) + `Initializing your webflo app
|
|
43
|
+
LOGGER?.log(LOGGER.style.keyword(`> `) + `Initializing your webflo app "${projectName}" using template "${template}"...\n`);
|
|
41
44
|
|
|
42
45
|
// 1. Create project dir
|
|
43
46
|
await Fs2.mkdir(targetDir, { recursive: true });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"filename": "app.js",
|
|
3
|
+
"public_base_url": "/",
|
|
4
|
+
"copy_public_variables": true,
|
|
5
|
+
"spa_routing": true,
|
|
6
|
+
"capabilities": {
|
|
7
|
+
"service_worker": true,
|
|
8
|
+
"webpush": true,
|
|
9
|
+
"custom_install": true,
|
|
10
|
+
"exposed": [
|
|
11
|
+
"display-mode",
|
|
12
|
+
"notifications"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -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": {
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
"scope": "/",
|
|
11
11
|
"icons": [
|
|
12
12
|
{
|
|
13
|
-
"src": "/assets
|
|
13
|
+
"src": "/assets/logo.png",
|
|
14
14
|
"sizes": "192x192",
|
|
15
15
|
"type": "image/png"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
-
"src": "/assets
|
|
18
|
+
"src": "/assets/logo.png",
|
|
19
19
|
"sizes": "512x512",
|
|
20
20
|
"type": "image/png",
|
|
21
21
|
"purpose": "maskable"
|
|
@@ -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
|
+
}
|