Pretty logging

This commit is contained in:
Thibault “Adædra” Hamel 2024-06-27 10:58:54 +02:00
parent 80ece66a0f
commit 8ad05aae80
10 changed files with 92 additions and 28 deletions

View File

@ -3,17 +3,11 @@ import { css } from "../lib/tasks/css.ts";
import { fonts } from "../lib/tasks/fonts.ts";
import { images } from "../lib/tasks/images.ts";
import { svg } from "../lib/tasks/svg.ts";
import { error } from "../lib/log.ts";
import { Task, wrapTask } from "../lib/task.ts";
import { argv, exit } from "node:process";
type Task = () => Promise<void>;
const wrapTask = (name: string, task: Task) => async () => {
console.log("[start]", name);
await task();
console.log("[end]", name);
};
const TASKS = new Map<string, Task>(Object.entries({
articles: wrapTask("articles", articles),
css: wrapTask("css", css),
@ -28,7 +22,7 @@ const args = argv.slice(2);
await (args.length ? args : ALL_TASKS)
.map((task: string) => {
if (!TASKS.has(task)) {
console.error("Unknown task", task);
error("Unknown task", { task });
exit(1);
}

View File

@ -1,8 +1,9 @@
import chokidar from "chokidar";
import { debug, info } from "../lib/log.ts";
const watch = (glob: string | string[], task: string) =>
chokidar.watch(glob).on("change", (path: string) => {
console.log("[change]", path, "->", task);
debug("File changed", { path, task });
return new Promise<void>((resolve) => {
const worker = new Worker(import.meta.resolve("../lib/watch-worker.ts"), { type: "module" });
worker.addEventListener("message", () => {
@ -20,3 +21,5 @@ watch("src/*.svg", "svg");
watch("dist/_assets/fonts.manifest", "css");
watch("dist/_assets/css.manifest", "articles");
info("Started");

View File

@ -1,6 +1,8 @@
{
"imports": {
"@std/fmt": "jsr:@std/fmt@^0.225.4",
"@std/io": "jsr:@std/io@^0.224.2",
"@std/log": "jsr:@std/log@^0.224.3",
"asciidoctor": "https://esm.sh/asciidoctor@^3.0.4",
"chokidar": "npm:chokidar@^3.6.0",
"cssnano": "npm:cssnano@^7.0.2",

View File

@ -2,6 +2,10 @@
"version": "3",
"packages": {
"specifiers": {
"jsr:@std/fmt@^0.225.4": "jsr:@std/fmt@0.225.4",
"jsr:@std/fs@^1.0.0-rc.1": "jsr:@std/fs@1.0.0-rc.1",
"jsr:@std/io@^0.224.2": "jsr:@std/io@0.224.2",
"jsr:@std/log@^0.224.3": "jsr:@std/log@0.224.3",
"npm:@mapbox/rehype-prism@^0.9.0": "npm:@mapbox/rehype-prism@0.9.0",
"npm:@types/node": "npm:@types/node@18.16.19",
"npm:chokidar@^3.6.0": "npm:chokidar@3.6.0",
@ -22,6 +26,25 @@
"npm:unified@^11.0.4": "npm:unified@11.0.5",
"npm:unist-util-visit@^5.0.0": "npm:unist-util-visit@5.0.0"
},
"jsr": {
"@std/fmt@0.225.4": {
"integrity": "584c681cf422b70e28959b57e59012823609c087384cbf12d05f67814797fda3"
},
"@std/fs@1.0.0-rc.1": {
"integrity": "10a78e43d89507deda6e2ce9c7aac24ba2ee468bf74da1101d95b0fbeb463aca"
},
"@std/io@0.224.2": {
"integrity": "25ecd4f674527d660ab09e571e15eb541e8eb8a4575f2d20bdbf029374a609b5"
},
"@std/log@0.224.3": {
"integrity": "601af539ff0c80d117fcb6cab7d9339242872d7f7f5fe4862aaf32152d86b9bf",
"dependencies": [
"jsr:@std/fmt@^0.225.4",
"jsr:@std/fs@^1.0.0-rc.1",
"jsr:@std/io@^0.224.2"
]
}
},
"npm": {
"@csstools/selector-resolve-nested@1.1.0_postcss-selector-parser@6.1.0": {
"integrity": "sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==",
@ -1745,7 +1768,9 @@
},
"workspace": {
"dependencies": [
"jsr:@std/fmt@^0.225.4",
"jsr:@std/io@^0.224.2",
"jsr:@std/log@^0.224.3",
"npm:@mapbox/rehype-prism@^0.9.0",
"npm:chokidar@^3.6.0",
"npm:cssnano@^7.0.2",

23
lib/log.ts Normal file
View File

@ -0,0 +1,23 @@
import { ConsoleHandler, LogRecord, setup } from "@std/log";
import { bold, dim, magenta } from "@std/fmt/colors";
import { PRODUCTION } from "./environment.ts";
const formatter = (record: LogRecord): string => {
const params = Object.entries(record.args[0] || {}).map(([key, value]) => `${magenta(key)}: ${value.toString()}`)
.join(", ");
return `${dim(record.datetime.toISOString())} ${record.levelName.substring(0, 1)}, ${bold(record.msg)} ${params}`;
};
setup({
handlers: {
default: new ConsoleHandler("DEBUG", { formatter, useColors: false }),
},
loggers: {
default: {
level: PRODUCTION ? "INFO" : "DEBUG",
handlers: ["default"],
},
},
});
export { debug, error, info } from "@std/log";

View File

@ -5,6 +5,7 @@ import { mkdir, writeFile } from "node:fs/promises";
import { Glob } from "glob";
import { VFile } from "vfile";
import { read } from "to-vfile";
import { info } from "./log.ts";
export function dest(prefix: string) {
return async (file: VFile) => {
@ -13,7 +14,7 @@ export function dest(prefix: string) {
await mkdir(dirname(actualPath), { recursive: true });
}
await writeFile(actualPath, file.value);
console.log("[-] Written", actualPath);
info("Written", { path: actualPath });
return file;
};

11
lib/task.ts Normal file
View File

@ -0,0 +1,11 @@
import { debug, info } from "./log.ts";
import { DateTime } from "luxon";
export type Task = () => Promise<void>;
export const wrapTask = (name: string, task: Task) => async () => {
debug("Running task", { name });
const start = DateTime.now();
await task();
info("Task finished", { name, time: `${-start.diffNow("milliseconds")} ms` });
};

View File

@ -1,11 +1,16 @@
import { mergeMap } from "rxjs";
import hashPaths from "../hash.ts";
import { dest, fromGlob } from "../rx-utils.ts";
import { tap } from "rxjs";
import { lastValueFrom } from "rxjs";
export const images = () =>
export const images = async () => {
await lastValueFrom(
fromGlob("src/*.avif")
.pipe(
tap((f) => (f.path = f.basename!)),
hashPaths("images.manifest"),
)
.forEach(dest("dist/_assets"));
mergeMap(dest("dist/_assets")),
),
);
};

View File

@ -1,8 +1,11 @@
import { tap } from "rxjs";
import { lastValueFrom, tap } from "rxjs";
import { dest, fromGlob } from "../rx-utils.ts";
import { mergeMap } from "rxjs";
// SVG `use` has no way of allowing cross-origin, so we need to keep them with the HTML files.
export const svg = () =>
export const svg = async () => {
await lastValueFrom(
fromGlob("src/*.svg")
.pipe(tap((f) => (f.path = f.basename!)))
.forEach(dest("dist"));
.pipe(tap((f) => (f.path = f.basename!)), mergeMap(dest("dist"))),
);
};

View File

@ -3,15 +3,12 @@ import { css } from "./tasks/css.ts";
import { fonts } from "./tasks/fonts.ts";
import { images } from "./tasks/images.ts";
import { svg } from "./tasks/svg.ts";
import { wrapTask } from "./task.ts";
const TASKS: { [task: string]: () => Promise<void> } = { articles, css, fonts, images, svg };
self.addEventListener("message", async (message) => {
const { task } = message.data;
console.log("[start]", task);
await TASKS[task]();
console.log("[done]", task);
await wrapTask(task, TASKS[task])();
self.postMessage({ done: true });
});