Skip to content

Commit

Permalink
Merge pull request #441 from preactjs/debug-pretty
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinhagemeister authored Mar 18, 2021
2 parents 0907685 + 1e8b01b commit a8fe8c2
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/gorgeous-pants-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'wmr': patch
---

Add colored namespaces to debug output when `DEBUG=true` is set.
2 changes: 1 addition & 1 deletion packages/wmr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"husky": "^4.2.5",
"jest": "^26.1.0",
"jest-puppeteer": "^4.4.0",
"kolorist": "^1.2.7",
"kolorist": "^1.3.2",
"lint-staged": "^10.2.11",
"magic-string": "^0.25.7",
"ncp": "^2.0.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/wmr/src/lib/normalize-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { promises as fs } from 'fs';
import url from 'url';
import { readEnvFiles } from './environment.js';
import { compileSingleModule } from './compile-single-module.js';
import { debug } from './output-utils.js';

/**
* @template {Options} T
Expand Down Expand Up @@ -101,6 +102,8 @@ export async function normalizeOptions(options, mode) {
if (custom[mode]) await custom[mode](options);
}

debug('wmr:config')(options);

// @ts-ignore-next
return options;
}
Expand Down
79 changes: 79 additions & 0 deletions packages/wmr/src/lib/output-utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as kl from 'kolorist';
import * as util from 'util';
import { relative } from 'path';

/** @param {import('rollup').RollupOutput} bundle */
export function bundleStats(bundle) {
Expand Down Expand Up @@ -85,3 +87,80 @@ export function codeFrame(code, loc) {
}
return frame;
}

// Taken from https://github.com/visionmedia/debug/blob/e47f96de3de5921584364b4ac91e2769d22a3b1f/src/node.js#L35
// prettier-ignore
const colors = [
20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68,
69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134,
135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 214, 215, 220, 221
];

// Taken from: https://github.com/visionmedia/debug/blob/e47f96de3de5921584364b4ac91e2769d22a3b1f/src/common.js#L41-L50
function selectColor(namespace) {
let hash = 0;

for (let i = 0; i < namespace.length; i++) {
hash = (hash << 5) - hash + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}

return colors[Math.abs(hash) % colors.length];
}

/**
* Print namespaced log messages when the DEBUG environment
* variable is set.
* @param {string} namespace
* @param {number} [color]
* @returns {(...args: any[]) => void}
*/
export function debug(namespace, color = selectColor(namespace)) {
const ns = kl.ansi256(color)(` ${namespace} `);
return (...args) => {
if (process.env.DEBUG) {
const str = args.map(arg => {
const value = arg === null || typeof arg !== 'object' ? arg : util.inspect(arg, false, null, true);

return value
.split('\n')
.map(line => ns + line)
.join('\n');
});
console.log.apply(console, str);
}
};
}

/**
* Serialize path to display special characters such as
* the null byte of necessary.
* @param {string} path
* @returns {string}
*/
export function formatPath(path) {
path = path || 'null';
if (typeof path === 'object') {
path = path.id;
}
if (path.startsWith('\b') || path.startsWith('\0')) {
path = JSON.stringify(path);
}
if (path.startsWith(process.cwd())) {
path = relative(process.cwd(), path);
}

return path;
}

/**
* @param {string} from
* @param {import('rollup').ResolvedId | string | null} to
*/
export function formatResolved(from, to) {
from = formatPath(from);
to = formatPath(to);
return `${kl.cyan(from)} -> ${kl.dim(to)}`;
}
15 changes: 11 additions & 4 deletions packages/wmr/src/lib/rollup-plugin-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { resolve, relative, dirname, sep, posix } from 'path';
import { createHash } from 'crypto';
import { promises as fs } from 'fs';
import * as acorn from 'acorn';
import acornClassFields from 'acorn-class-fields';
import * as kl from 'kolorist';
import acornClassFields from 'acorn-class-fields';
import { debug, formatResolved, formatPath } from './output-utils.js';

// Rollup respects "module", Node 14 doesn't.
const cjsDefault = m => ('default' in m ? m.default : m);
Expand Down Expand Up @@ -156,6 +157,10 @@ export function createPluginContainer(plugins, opts = {}) {
}
};

const logResolve = debug('wmr:resolve');
const logTransform = debug('wmr:transform');
const logLoad = debug('wmr:load');

const container = {
ctx,

Expand Down Expand Up @@ -221,6 +226,7 @@ export function createPluginContainer(plugins, opts = {}) {
* @returns {Promise<import('rollup').ResolveIdResult>}
*/
async resolveId(id, importer, _skip) {
let originalId = id;
const key = identifierPair(id, importer);

const opts = {};
Expand Down Expand Up @@ -250,9 +256,7 @@ export function createPluginContainer(plugins, opts = {}) {
Object.assign(opts, result);
}

if (process.env.DEBUG) {
console.log(` ${kl.dim('plugin:') + kl.bold(kl.yellow(p.name))} ${JSON.stringify(id)}`);
}
logResolve(`${formatResolved(originalId, id)} [${p.name}]`);
// resolveId() is hookFirst - first non-null result is returned.
break;
}
Expand All @@ -270,6 +274,8 @@ export function createPluginContainer(plugins, opts = {}) {
if (!plugin.transform) continue;
const result = await plugin.transform.call(ctx, code, id);
if (!result) continue;

logTransform(`${kl.dim(formatPath(id))} [${plugin.name}]`);
if (typeof result === 'object') {
code = result.code;
} else {
Expand All @@ -288,6 +294,7 @@ export function createPluginContainer(plugins, opts = {}) {
if (!plugin.load) continue;
const result = await plugin.load.call(ctx, id);
if (result) {
logLoad(`${formatPath(id)} [${plugin.name}]`);
return result;
}
}
Expand Down
6 changes: 5 additions & 1 deletion packages/wmr/src/plugins/aliases-plugin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { dirname, resolve } from 'path';
import { promises as fs } from 'fs';
import { debug, formatResolved } from '../lib/output-utils.js';

/**
* Package.json "aliases" field: {"a":"b"}
Expand All @@ -9,6 +10,7 @@ import { promises as fs } from 'fs';
* @returns {import('rollup').Plugin}
*/
export default function aliasesPlugin({ aliases = {}, cwd } = {}) {
const log = debug('aliases');
let pkgFilename;
let aliasesLoaded;
async function fromPackageJson() {
Expand Down Expand Up @@ -67,7 +69,9 @@ export default function aliasesPlugin({ aliases = {}, cwd } = {}) {
if (aliased === id) return;
// now allow other resolvers to handle the aliased version
// (this is important since they may mark as external!)
return await this.resolve(aliased, importer, { skipSelf: true });
const resolved = await this.resolve(aliased, importer, { skipSelf: true });
log(formatResolved(id, resolved));
return resolved;
}
};
}
4 changes: 4 additions & 0 deletions packages/wmr/src/plugins/bundle-plugin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { relative } from 'path';
import * as kl from 'kolorist';
import { debug } from '../lib/output-utils.js';

/**
* @param {object} [options]
Expand All @@ -7,6 +9,7 @@ import { relative } from 'path';
* @returns {import('rollup').Plugin}
*/
export default function bundlePlugin({ cwd = '.', inline } = {}) {
const log = debug('bundle');
return {
name: 'bundle-plugin',
async resolveId(id, importer) {
Expand All @@ -15,6 +18,7 @@ export default function bundlePlugin({ cwd = '.', inline } = {}) {
if (resolved) {
if (inline) {
const url = '/' + relative(cwd, resolved.id).replace(/^\./, '');
log(`[inline] ${kl.dim(url)}`);
return {
id: `data:text/javascript,export default${encodeURIComponent(JSON.stringify(url))}`,
external: true
Expand Down
19 changes: 14 additions & 5 deletions packages/wmr/test/fixtures.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import path from 'path';
import { promises as fs } from 'fs';
import { setupTest, teardown, loadFixture, runWmrFast, getOutput, get } from './test-helpers.js';
import {
setupTest,
teardown,
loadFixture,
runWmrFast,
getOutput,
get,
waitForMessage,
waitForNotMessage
} from './test-helpers.js';
import { rollup } from 'rollup';
import nodeBuiltinsPlugin from '../src/plugins/node-builtins-plugin.js';

Expand Down Expand Up @@ -64,28 +73,28 @@ describe('fixtures', () => {
it('should print warning for missing index.html file in public dir', async () => {
await loadFixture('empty', env);
instance = await runWmrFast(env.tmp.path);
expect(instance.output.join('\n')).toMatch(`missing "index.html" file`);
await waitForMessage(instance.output, 'missing "index.html" file');
expect(await getOutput(env, instance)).toMatch(`Not Found`);
});

it('should print warning for missing index.html file (no public dir)', async () => {
await loadFixture('empty-nopublic', env);
instance = await runWmrFast(env.tmp.path);
expect(instance.output.join('\n')).toMatch(`missing "index.html" file`);
await waitForMessage(instance.output, 'missing "index.html" file');
expect(await getOutput(env, instance)).toMatch(`Not Found`);
});

it('should start successfully with only an HTML file in public dir', async () => {
await loadFixture('htmlonly', env);
instance = await runWmrFast(env.tmp.path);
expect(instance.output.join('\n')).not.toMatch(`missing an "index.html"`);
await waitForNotMessage(instance.output, `missing an "index.html"`);
expect(await getOutput(env, instance)).toMatch(`<h1>Hello wmr</h1>`);
});

it('should start successfully with only an HTML file (no public dir)', async () => {
await loadFixture('htmlonly-nopublic', env);
instance = await runWmrFast(env.tmp.path);
expect(instance.output.join('\n')).not.toMatch(`missing an "index.html"`);
await waitForNotMessage(instance.output, `missing an "index.html"`);
expect(await getOutput(env, instance)).toMatch(`<h1>Hello wmr</h1>`);
});
});
Expand Down
19 changes: 16 additions & 3 deletions packages/wmr/test/test-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,13 @@ export async function waitFor(fn, timeout = 2000) {
/**
* @param {string[]} haystack
* @param {string | RegExp} message
* @param {number} timeout
* @param {number} [timeout]
* @returns {Promise<void>}
*/
export async function waitForMessage(haystack, message, timeout = 5000) {
const found = await waitFor(() => {
if (typeof message === 'string') {
if (haystack.includes(message)) {
if (haystack.some(line => line.includes(message))) {
return true;
}
} else {
Expand All @@ -175,10 +175,23 @@ export async function waitForMessage(haystack, message, timeout = 5000) {
});

if (!found) {
throw new Error(`Message ${message} didn't appear in ${timeout}ms`);
throw new Error(`Message ${message} didn't appear in ${timeout}ms\n\nActual output:\n\n${haystack.join('\n')}`);
}
}

/**
* @param {string[]} haystack
* @param {string | RegExp} message
* @param {number} [timeout]
* @returns {Promise<void>}
*/
export async function waitForNotMessage(haystack, message, timeout = 1000) {
try {
await waitForMessage(haystack, message, timeout);
throw new Error(`Expected message to not be present: ${message}`);
} catch (err) {}
}

/**
* @param {WmrInstance} instance
* @param {string} urlPath
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5025,10 +5025,10 @@ kleur@^4.1.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d"
integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==

kolorist@^1.2.7:
version "1.2.10"
resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.2.10.tgz#0f97a3f3a1dd75e980765c7cec8a1de258e580c6"
integrity sha512-S3QtGjCHyINclP4LSClgHw4gi/NxTFcSorqD9SWfrREHKtMyGfi6pyDCTbpQaqyZrMAjB4Exde8eco6kejkqQg==
kolorist@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.3.2.tgz#3d939b3b2e42e7cf9b2ac1f385c33041cfe42207"
integrity sha512-0AABCl2usZg6CptLfHW4N3ZhGUT6vgHO6CtBOsRJKQGgvhKRWryUtXGfADLpK2XxbLh/VOXFX7EluitkSgP/eA==

latest-version@^5.0.0:
version "5.1.0"
Expand Down

0 comments on commit a8fe8c2

Please sign in to comment.