wirejs-scripts 3.0.9 → 3.0.10

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/README.md ADDED
@@ -0,0 +1,3 @@
1
+ Experimental.
2
+
3
+ If this package interests you, contact the author.
package/bin.js CHANGED
@@ -4,11 +4,13 @@ import process from 'process';
4
4
  import http from 'http';
5
5
  import fs from 'fs';
6
6
  import path from 'path';
7
+ import { Worker } from 'worker_threads';
7
8
 
8
9
  import webpack from 'webpack';
9
10
  import webpackConfigure from './configs/webpack.config.js';
10
11
  import { rimraf } from 'rimraf';
11
12
  import esbuild from 'esbuild';
13
+ import { contentType } from 'mime-types';
12
14
 
13
15
  import { JSDOM } from 'jsdom';
14
16
  import { useJSDOM } from 'wirejs-dom/v2';
@@ -115,7 +117,7 @@ async function handleApiResponse(req, res) {
115
117
  const calls = JSON.parse(body);
116
118
  logger.info('handling API request', body);
117
119
 
118
- const apiPath = path.join(CWD, 'api', 'index.js');
120
+ const apiPath = path.join(CWD, 'api', 'dist', 'index.js');
119
121
  const api = await import(`${apiPath}?cache-id=${new Date().getTime()}`);
120
122
 
121
123
  const responses = [];
@@ -174,13 +176,7 @@ async function tryStaticPath(req, res) {
174
176
  if (!fs.existsSync(fullPath)) return false;
175
177
  logger.info('static found');
176
178
 
177
- if (fullPath.endsWith(".html")) {
178
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
179
- } else if (fullPath.endsWith(".js")) {
180
- res.setHeader('Content-Type', 'text/javascript; charset=utf-8');
181
- } else {
182
- res.setHeader('Content-Type', 'text/plain; charset=utf-8');
183
- }
179
+ res.setHeader('Content-Type', contentType(path.extname(fullPath)));
184
180
 
185
181
  try {
186
182
  res.end(fs.readFileSync(fullPath));
@@ -284,26 +280,32 @@ async function trySSRPath(req, res) {
284
280
  const module = self.exports;
285
281
  if (typeof module.generate === 'function') {
286
282
  const doc = await module.generate(context);
287
- const doctype = doc.parentNode.doctype?.name || '';
288
-
289
- let hydrationsFound = 0;
290
- while (globalThis.pendingDehydrations?.length > 0) {
291
- globalThis.pendingDehydrations.shift()(doc);
292
- hydrationsFound++;
293
- }
283
+ if (typeof doc.outerHTML === 'undefined') {
284
+ res.setHeader('Content-Type', contentType(
285
+ context.location.pathname.split('.').pop()
286
+ ));
287
+ res.end(doc);
288
+ } else {
289
+ const doctype = doc.parentNode.doctype?.name || '';
294
290
 
295
- if (hydrationsFound) {
296
- const script = doc.parentNode.createElement('script');
297
- script.src = asJSPath;
298
- doc.parentNode.body.appendChild(script);
291
+ let hydrationsFound = 0;
292
+ while (globalThis.pendingDehydrations?.length > 0) {
293
+ globalThis.pendingDehydrations.shift()(doc);
294
+ hydrationsFound++;
295
+ }
296
+
297
+ if (hydrationsFound) {
298
+ const script = doc.parentNode.createElement('script');
299
+ script.src = asJSPath;
300
+ doc.parentNode.body.appendChild(script);
301
+ }
302
+
303
+ res.setHeader('Content-type', 'text/html; charset=utf-8');
304
+ res.end([
305
+ doctype ? `<!doctype ${doctype}>\n` : '',
306
+ doc.outerHTML
307
+ ].join(''));
299
308
  }
300
-
301
- res.setHeader('Content-type', 'text/html; charset=utf-8');
302
- res.end([
303
- doctype ? `<!doctype ${doctype}>\n` : '',
304
- doc.outerHTML
305
- ].join(''));
306
-
307
309
  return true;
308
310
  } else {
309
311
  logger.info('SSR module missing generate function');
@@ -367,6 +369,25 @@ async function compile(watch = false) {
367
369
  const stats = await new Promise(async (resolve, reject) => {
368
370
  let compiler;
369
371
  if (watch) {
372
+
373
+ const apiDir = path.join(CWD, 'api');
374
+ const prebuildApiWatch = await esbuild.context({
375
+ entryPoints: [path.join(CWD, 'api', '**', '*.ts')],
376
+ outdir: path.join(apiDir, 'dist'),
377
+ platform: 'node',
378
+ bundle: true,
379
+ external: ['./node_modules/*'],
380
+ format: 'esm',
381
+ plugins: [{
382
+ name: 'post-build-rebuild-api-client',
383
+ setup(build) {
384
+ build.onEnd(() => prebuildApi(apiDir))
385
+ }
386
+ }]
387
+ });
388
+ await prebuildApiWatch.rebuild();
389
+ prebuildApiWatch.watch();
390
+
370
391
  const prebuild = await esbuild.context({
371
392
  entryPoints: [`${CWD}/src/**/*.ts`],
372
393
  outdir: `${CWD}/pre-dist`,
@@ -376,6 +397,7 @@ async function compile(watch = false) {
376
397
  });
377
398
  await prebuild.rebuild();
378
399
  prebuild.watch();
400
+
379
401
  webpack({
380
402
  ...getWebpackConfig(),
381
403
  mode: 'development',
@@ -390,6 +412,7 @@ async function compile(watch = false) {
390
412
  server.listen(3000).on('listening', () => {
391
413
  console.log('Started listening on http://localhost:3000/')
392
414
  });
415
+
393
416
  } else {
394
417
  logger.log('prebundling JS');
395
418
  await esbuild.build({
@@ -470,13 +493,13 @@ const engine = {
470
493
  async ['prebuild-api']() {
471
494
  logger.log("prebuilding api ...");
472
495
  await esbuild.build({
473
- entryPoints: [`${CWD}/**/*.ts`],
474
- outdir: CWD,
496
+ entryPoints: [path.join(CWD, '**', '*.ts')],
497
+ outdir: path.join(CWD, 'dist'),
475
498
  platform: 'node',
476
499
  bundle: false,
477
500
  format: 'esm',
478
501
  });
479
- await prebuildApi();
502
+ await prebuildApi(CWD);
480
503
  logger.log("api prebuild finished");
481
504
  },
482
505
  };
@@ -1,28 +1,14 @@
1
- import { useJSDOM } from 'wirejs-dom/v2';
2
- import fs from 'fs';
3
1
  import path from 'path';
4
2
  import glob from 'glob';
5
3
  import process from 'process';
6
4
  import CopyWebpackPlugin from 'copy-webpack-plugin';
7
- import marked from 'marked';
8
- import { JSDOM } from 'jsdom';
9
-
5
+ import { execSync } from 'child_process';
10
6
 
11
7
  const CWD = process.cwd();
12
8
  const SRC = 'pre-dist';
13
9
 
14
- // https://marked.js.org/using_advanced
15
- marked.setOptions({
16
- highlight: function (code, lang) {
17
- try {
18
- const highlighter = require('highlight.js');
19
- const language = highlighter.getLanguage(lang) ? lang : 'plaintext';
20
- return highlighter.highlight(code, { language }).value;
21
- } catch (e) {
22
- console.log("highlight.js not installed. Skipping syntax highlighting.");
23
- }
24
- }
25
- });
10
+ const __filename = import.meta.url.replace(/^file:/, '');
11
+ const SELF_DIR = path.dirname(__filename);
26
12
 
27
13
  function distPath({ subpathOut = '', subpathIn = '', extensionOut } = {}) {
28
14
  return function ({ context, absoluteFilename }) {
@@ -37,90 +23,24 @@ function distPath({ subpathOut = '', subpathIn = '', extensionOut } = {}) {
37
23
  };
38
24
  };
39
25
 
40
- const layouts = {};
41
- const CollectLayouts = {
42
- transformer: (content, path) => {
43
- // add one to dirname prefix to include separating slash
44
- const relativePath = path.slice(CWD.length + 1);
45
- layouts[relativePath] = content.toString();
46
- return layouts[relativePath];
47
- }
48
- };
49
-
50
- const SSG = {
51
- transformer: async (content, _path) => {
52
- let _meta = {};
53
-
54
- let body;
55
- try {
56
- body = _path.endsWith('.md') ? marked(content.toString()) : content.toString();
57
- } catch (err) {
58
- console.error(`Could not parse page ${_path}`, err);
59
- throw err;
60
- }
61
-
62
- // apply no layout if the document has already provided the
63
- // overarching html structure.
64
- if (!_meta.layout && body && (
65
- String(body).startsWith('<!doctype html>')
66
- || String(body).startsWith('<html'))
67
- ) {
68
- return body;
69
- }
70
-
71
- const layoutPath = path.join(
72
- SRC,
73
- 'layouts',
74
- (_meta.layout || 'default')
75
- ) + '.html';
76
-
77
- const layout = layouts[layoutPath];
78
-
79
- try {
80
- return layout;
81
- } catch (err) {
82
- console.error(`Could not parse layout ${layoutPath}`, err);
83
- throw err;
84
- }
85
- }
86
- };
87
-
88
26
  const Generated = {
89
27
  transformer: async (content, contentPath) => {
90
- useJSDOM(JSDOM);
91
-
92
28
  try {
93
29
  if (contentPath.endsWith('.js')) {
94
- const module = await import(contentPath + '?' + new Date() + Math.random());
95
- if (typeof module.generate === 'function') {
96
- const doc = await module.generate(contentPath);
97
- const doctype = doc.parentNode.doctype?.name || '';
98
-
99
- let hydrationsFound = 0;
100
- while (globalThis.pendingDehydrations?.length > 0) {
101
- globalThis.pendingDehydrations.shift()(doc);
102
- hydrationsFound++;
103
- }
104
-
105
- if (hydrationsFound) {
106
- const script = doc.parentNode.createElement('script');
107
- script.src = contentPath.substring((`${CWD}/${SRC}/ssg`).length);
108
- doc.parentNode.body.appendChild(script);
30
+ // generated in a subprocess to ensure imports are clean, especially
31
+ // when in watch mode.
32
+ const generatedContent = execSync(
33
+ `node ${SELF_DIR}/../ssg.js ${CWD}/${SRC} ${contentPath}`,
34
+ {
35
+ stdio: [ 'pipe', 'pipe', 'pipe' ]
109
36
  }
110
-
111
- return [
112
- doctype ? `<!doctype ${doctype}>\n` : '',
113
- doc.outerHTML
114
- ].join('');
115
- } else {
116
- return;
117
- }
37
+ );
38
+ return generatedContent;
118
39
  } else {
119
40
  return content.toString();
120
41
  }
121
42
  } catch (err) {
122
43
  console.error(`Could not generate page ${contentPath}`, err);
123
- throw err;
124
44
  }
125
45
  }
126
46
  };
@@ -177,25 +97,6 @@ export default (env, argv) => {
177
97
  target: 'web',
178
98
  devtool,
179
99
  plugins: [
180
-
181
- // TODO: does it make sense to actually handle static assets
182
- // first? then layouts? then everything else?
183
-
184
- // handle layouts first. other things depend on them.
185
- new CopyWebpackPlugin({
186
- patterns: [
187
- {
188
- from: `./${SRC}/layouts/**/*.html`,
189
- to: distPath({
190
- subpathIn: `${SRC}/layouts`,
191
- subpathOut: 'layouts'
192
- }),
193
- transform: CollectLayouts,
194
- noErrorOnMissing: true,
195
- },
196
- ]
197
- }),
198
-
199
100
  // now pages, etc.
200
101
  new CopyWebpackPlugin({
201
102
  patterns: [
@@ -211,111 +112,8 @@ export default (env, argv) => {
211
112
  noErrorOnMissing: true,
212
113
  priority: 5
213
114
  },
214
- // {
215
- // from: './src/routes/**/*.md',
216
- // to: distPath({ subpathIn: 'src/routes' }),
217
- // transform: SSG,
218
- // noErrorOnMissing: true,
219
- // priority: 3,
220
- // },
221
- // {
222
- // from: './src/routes/**/*.html',
223
- // to: distPath({ subpathIn: 'src/routes' }),
224
- // transform: SSG,
225
- // noErrorOnMissing: true,
226
- // priority: 3,
227
- // },
228
- // {
229
- // from: './src/routes/**/*.xml',
230
- // to: distPath({ subpathIn: 'src/routes' }),
231
- // transform: SSG,
232
- // noErrorOnMissing: true,
233
- // priority: 3,
234
- // },
235
- // {
236
- // from: './src/routes/**/*.rss',
237
- // to: distPath({ subpathIn: 'src/routes' }),
238
- // transform: SSG,
239
- // noErrorOnMissing: true,
240
- // priority: 3,
241
- // },
242
- // {
243
- // from: './src/routes/**/*.css',
244
- // to: distPath({ subpathIn: 'src/routes' }),
245
- // noErrorOnMissing: true,
246
- // // trasform: ???
247
- // priority: 3,
248
- // },
249
- // {
250
- // from: './src/routes/**/*.png',
251
- // to: distPath({ subpathIn: 'src/routes' }),
252
- // noErrorOnMissing: true,
253
- // priority: 3,
254
- // },
255
- // {
256
- // from: './src/routes/**/*.jpg',
257
- // to: distPath({ subpathIn: 'src/routes' }),
258
- // noErrorOnMissing: true,
259
- // priority: 3,
260
- // },
261
- // {
262
- // from: './src/routes/**/*.json',
263
- // to: distPath({ subpathIn: 'src/routes' }),
264
- // noErrorOnMissing: true,
265
- // priority: 3,
266
- // },
267
- // {
268
- // from: './src/routes/**/*.svg',
269
- // to: distPath({ subpathIn: 'src/routes' }),
270
- // noErrorOnMissing: true,
271
- // priority: 3,
272
- // },
273
- // {
274
- // from: './src/routes/**/*.mp3',
275
- // to: distPath({ subpathIn: 'src/routes' }),
276
- // noErrorOnMissing: true,
277
- // priority: 3,
278
- // },
279
115
  ],
280
116
  }),
281
117
  ],
282
- module: {
283
- rules: [
284
- {
285
- test: /\.css$/,
286
- use: [
287
- "style-loader",
288
- // path.resolve(__dirname, '../node_modules/style-loader'),
289
- {
290
- loader: "css-loader",
291
- // loader: path.resolve(__dirname, '../node_modules/css-loader'),
292
- options: {
293
- // don't try to require() url assets
294
- url: false
295
- }
296
- }
297
- ]
298
- },
299
- {
300
- test: /\.html$/,
301
- loader: "file-loader",
302
- // loader: path.resolve(__dirname, '../node_modules/file-loader'),
303
- options: {
304
- name: "[name].[ext]",
305
- }
306
- },
307
- {
308
- test: /\.mjs$/,
309
- resolve: {
310
- fullySpecified: false
311
- }
312
- },
313
- {
314
- test: /\.(md|tpl)$/,
315
- use: "raw-loader",
316
- // use: path.resolve(__dirname, '../node_modules/raw-loader')
317
- },
318
- ]
319
- }
320
118
  };
321
119
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wirejs-scripts",
3
- "version": "3.0.9",
3
+ "version": "3.0.10",
4
4
  "description": "Basic build and start commands for wirejs apps",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,11 +28,12 @@
28
28
  "glob": "^7.2.0",
29
29
  "jsdom": "^25.0.1",
30
30
  "marked": "^2.0.1",
31
+ "mime-types": "^2.1.35",
31
32
  "raw-loader": "^4.0.2",
32
33
  "rimraf": "^6.0.1",
33
34
  "style-loader": "^2.0.0",
34
35
  "webpack": "^5.97.1",
35
36
  "wirejs-dom": "^1.0.38",
36
- "wirejs-resources": "^0.1.11"
37
+ "wirejs-resources": "^0.1.12"
37
38
  }
38
- }
39
+ }
package/ssg.js ADDED
@@ -0,0 +1,42 @@
1
+ import process from 'process';
2
+ import { JSDOM } from 'jsdom';
3
+ import { useJSDOM } from 'wirejs-dom/v2';
4
+
5
+ const SRC_DIR = process.argv[2];
6
+
7
+ async function build(filename) {
8
+ useJSDOM(JSDOM);
9
+
10
+ try {
11
+ const module = await import(filename);
12
+
13
+ if (typeof module.generate === 'function') {
14
+ const doc = await module.generate(filename);
15
+ const doctype = doc.parentNode.doctype?.name || '';
16
+
17
+ let hydrationsFound = 0;
18
+ while (globalThis.pendingDehydrations?.length > 0) {
19
+ globalThis.pendingDehydrations.shift()(doc);
20
+ hydrationsFound++;
21
+ }
22
+
23
+ if (hydrationsFound) {
24
+ const script = doc.parentNode.createElement('script');
25
+ script.src = filename.substring((`${SRC_DIR}/ssg`).length);
26
+ doc.parentNode.body.appendChild(script);
27
+ }
28
+
29
+ return [
30
+ doctype ? `<!doctype ${doctype}>\n` : '',
31
+ doc.outerHTML
32
+ ].join('');
33
+ } else {
34
+ return;
35
+ }
36
+ } catch (err) {
37
+ console.error(`Could not generate page ${filename}`, err);
38
+ process.exit(1);
39
+ }
40
+ }
41
+
42
+ console.log(await build(process.argv[3]));