Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug-pretty #441

Merged
merged 3 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.0",
"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.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.3.0.tgz#81345b3a15aaa5fa5f10159be72fd429dddd7321"
integrity sha512-8t4WbQ0FxMSJdWMDuvNhSRbxQiMAIN97CthZHtDpS9Zo8baG0nSvqTCCgcp4SKQdLD05LzWVYxWQyE2n820BfA==

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