diff options
Diffstat (limited to 'src/write/build-modes')
| -rw-r--r-- | src/write/build-modes/index.js | 1 | ||||
| -rw-r--r-- | src/write/build-modes/live-dev-server.js | 31 | ||||
| -rw-r--r-- | src/write/build-modes/sort.js | 76 | ||||
| -rw-r--r-- | src/write/build-modes/static-build.js | 101 |
4 files changed, 85 insertions, 124 deletions
diff --git a/src/write/build-modes/index.js b/src/write/build-modes/index.js index 4b61619d..3ae2cfc6 100644 --- a/src/write/build-modes/index.js +++ b/src/write/build-modes/index.js @@ -1,4 +1,3 @@ export * as 'live-dev-server' from './live-dev-server.js'; export * as 'repl' from './repl.js'; -export * as 'sort' from './sort.js'; export * as 'static-build' from './static-build.js'; diff --git a/src/write/build-modes/live-dev-server.js b/src/write/build-modes/live-dev-server.js index cd84dcc0..aebdb234 100644 --- a/src/write/build-modes/live-dev-server.js +++ b/src/write/build-modes/live-dev-server.js @@ -1,6 +1,7 @@ import {spawn} from 'node:child_process'; import * as http from 'node:http'; import {open, stat} from 'node:fs/promises'; +import * as os from 'node:os'; import * as path from 'node:path'; import {pipeline} from 'node:stream/promises'; import {inspect as nodeInspect} from 'node:util'; @@ -141,7 +142,7 @@ export async function go({ const showError = (error) => { if (niceShowAggregate) { if (error.errors || error.cause) { - niceShowAggregate(error); + niceShowAggregate(error, {showTraces: true}); return; } } @@ -202,7 +203,7 @@ export async function go({ try { pathAggregate.close(); } catch (error) { - niceShowAggregate(error); + niceShowAggregate(error, {showTraces: true}); logWarn`Failed to compute page paths for some targets.`; logWarn`This means some pages that normally exist will be 404s.`; fileIssue(); @@ -252,7 +253,7 @@ export async function go({ let url; try { url = new URL(request.url, `http://${request.headers.host}`); - } catch (error) { + } catch { response.writeHead(500, contentTypePlain); response.end('Failed to parse request URL\n'); return; @@ -299,7 +300,7 @@ export async function go({ let filePath; try { filePath = path.resolve(localDirectory, decodeURI(safePath.split('/').join(path.sep))); - } catch (error) { + } catch { response.writeHead(404, contentTypePlain); response.end(`File not found for: ${safePath}`); console.log(`${requestHead} [404] ${pathname}`); @@ -355,6 +356,10 @@ export async function go({ if (error.code === 'ERR_STREAM_PREMATURE_CLOSE') { // Connection was dropped, this is OK. return; + } else if (error.code === 'ERR_STREAM_UNABLE_TO_PIPE') { + // "Cannot pipe to a closed or destroyed stream" + // Sus-amongus networking error. Give up, it's probably OK. + return; } else { throw error; } @@ -492,7 +497,13 @@ export async function go({ } }); - const address = `http://${host}:${port}/`; + const addresses = + (host === '0.0.0.0' + ? [`http://localhost:${port}/`, + `http://${os.hostname()}:${port}/`] + : host === '127.0.0.1' + ? [`http://localhost:${port}/`] + : [`http://${host}:${port}/`]); server.on('error', error => { if (error.code === 'EADDRINUSE') { @@ -509,7 +520,15 @@ export async function go({ }); server.on('listening', () => { - logInfo`${'All done!'} Listening at: ${address}`; + if (addresses.length === 1) { + logInfo`${'All done!'} Listening at: ${addresses[0]}`; + } else { + logInfo`${`All done!`} Listening at:`; + for (const address of addresses) { + logInfo`- ${address}`; + } + } + logInfo`Press ^C here (control+C) to stop the server and exit.`; if (showTimings && loudResponses) { logInfo`Printing all HTTP responses, plus page generation timings.`; diff --git a/src/write/build-modes/sort.js b/src/write/build-modes/sort.js deleted file mode 100644 index 1a738ac8..00000000 --- a/src/write/build-modes/sort.js +++ /dev/null @@ -1,76 +0,0 @@ -export const description = `Update data files in-place to satisfy custom sorting rules`; - -import {logInfo} from '#cli'; -import {empty} from '#sugar'; -import thingConstructors from '#things'; - -export const config = { - fileSizes: { - applicable: false, - }, - - languageReloading: { - applicable: false, - }, - - mediaValidation: { - applicable: false, - }, - - search: { - applicable: false, - }, - - thumbs: { - applicable: false, - }, - - webRoutes: { - applicable: false, - }, - - sort: { - applicable: false, - }, -}; - -export function getCLIOptions() { - return {}; -} - -export async function go({wikiData, dataPath}) { - if (empty(wikiData.sortingRules)) { - logInfo`There aren't any sorting rules in for this wiki.`; - return true; - } - - const {SortingRule} = thingConstructors; - - let numUpdated = 0; - let numActive = 0; - - for await (const result of SortingRule.go({wikiData, dataPath})) { - numActive++; - - const niceMessage = `"${result.rule.message}"`; - - if (result.changed) { - numUpdated++; - logInfo`Updating to satisfy ${niceMessage}.`; - } else { - logInfo`Already good: ${niceMessage}`; - } - } - - if (numUpdated > 1) { - logInfo`Updated data files to satisfy ${numUpdated} sorting rules.`; - } else if (numUpdated === 1) { - logInfo`Updated data files to satisfy ${1} sorting rule.` - } else if (numActive >= 1) { - logInfo`All sorting rules were already satisfied. Good to go!`; - } else { - logInfo`No sorting rules are currently active.`; - } - - return true; -} diff --git a/src/write/build-modes/static-build.js b/src/write/build-modes/static-build.js index 2baed816..71553de3 100644 --- a/src/write/build-modes/static-build.js +++ b/src/write/build-modes/static-build.js @@ -1,14 +1,7 @@ import * as path from 'node:path'; -import { - copyFile, - cp, - mkdir, - stat, - symlink, - writeFile, - unlink, -} from 'node:fs/promises'; +import {cp, mkdir, readFile, stat, symlink, writeFile, unlink} + from 'node:fs/promises'; import {rimraf} from 'rimraf'; @@ -95,6 +88,11 @@ export function getCLIOptions() { type: 'value', }, + 'paths': { + help: `Skip rest and build only pages matching paths in this text file`, + type: 'value', + }, + // NOT for neatly ena8ling or disa8ling specific features of the site! // This is only in charge of what general groups of files to write. // They're here to make development quicker when you're only working @@ -115,8 +113,6 @@ export async function go({ universalUtilities, - mediaPath, - defaultLanguage, languages, urls, @@ -128,6 +124,7 @@ export async function go({ const outputPath = cliOptions['out-path'] || process.env.HSMUSIC_OUT; const appendIndexHTML = cliOptions['append-index-html'] ?? false; const writeOneLanguage = cliOptions['lang'] ?? null; + const pathsFromFile = cliOptions['paths'] ?? null; if (!outputPath) { logError`Expected ${'--out-path'} option or ${'HSMUSIC_OUT'} to be set`; @@ -147,6 +144,36 @@ export async function go({ logInfo`Writing all languages.`; } + let filterPaths = null; + if (pathsFromFile) { + let pathsText; + try { + pathsText = await readFile(pathsFromFile, 'utf8'); + } catch (error) { + logError`Failed to read file specified in ${'--paths'}:`; + logError`${error.code}: ${pathsFromFile}`; + return false; + } + + filterPaths = pathsText.split('\n').filter(Boolean); + + if (empty(filterPaths)) { + logWarn`Specified to build only paths in file ${'--paths'}:`; + logWarn`${pathsFromFile}`; + logWarn`But this file is totally empty...`; + } + + if (filterPaths.some(path => !path.startsWith('/'))) { + logError`All lines in ${'--paths'} file should start with slash ('${'/'}')`; + logError`These lines don't:`; + console.error(filterPaths.filter(path => !path.startsWith('/')).join('\n')); + logError`Please check file contents, or specified path, and try again.`; + return false; + } + + logInfo`Writing ${filterPaths.length} paths specified in: ${pathsFromFile} (${'--paths'})`; + } + const selectedPageFlags = Object.keys(cliOptions) .filter(key => pageFlags.includes(key)); @@ -166,11 +193,6 @@ export async function go({ }); if (writeAll) { - await writeFavicon({ - mediaPath, - outputPath, - }); - await writeSharedFilesAndPages({ outputPath, randomLinkDataJSON: generateRandomLinkDataJSON({wikiData}), @@ -225,6 +247,27 @@ export async function go({ // TODO: Validate each pathsForTargets entry } + if (!empty(filterPaths)) { + paths = + paths.filter(path => + filterPaths.includes( + (path.type === 'page' + ? '/' + + getPagePathname({ + baseDirectory: '', + pagePath: path.path, + urls, + }) + : path.type === 'redirect' + ? '/' + + getPagePathname({ + baseDirectory: '', + pagePath: path.fromPath, + urls, + }) + : null))); + } + paths = paths.filter(path => path.condition?.() ?? true); @@ -342,7 +385,7 @@ export async function go({ ({pageHTML, oEmbedJSON} = html.resolve(topLevelResult)); } catch (error) { logError`\rError generating page: ${pathname}`; - niceShowAggregate(error); + niceShowAggregate(error, {showTraces: true}); errored = true; return; } @@ -595,30 +638,6 @@ async function writeWebRouteCopies({ } } -async function writeFavicon({ - mediaPath, - outputPath, -}) { - const faviconFile = 'favicon.ico'; - - try { - await stat(path.join(mediaPath, faviconFile)); - } catch (error) { - return; - } - - try { - await copyFile( - path.join(mediaPath, faviconFile), - path.join(outputPath, faviconFile)); - } catch (error) { - logWarn`Failed to copy favicon! ${error.message}`; - return; - } - - logInfo`Copied favicon to site root.`; -} - async function writeSharedFilesAndPages({ outputPath, randomLinkDataJSON, |