Skip to content

Commit a376199

Browse files
authoredJul 7, 2022
fix!: stream CSV results (#507)
1 parent 18d808c commit a376199

File tree

5 files changed

+43
-192
lines changed

5 files changed

+43
-192
lines changed
 

‎package-lock.json

-159
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

-4
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,15 @@
2828
"gaxios": "^5.0.0",
2929
"glob": "^8.0.1",
3030
"htmlparser2": "^8.0.1",
31-
"jsonexport": "^3.2.0",
3231
"marked": "^4.0.3",
3332
"meow": "^10.1.1",
3433
"mime": "^3.0.0",
3534
"server-destroy": "^1.0.1",
3635
"update-notifier": "^6.0.0"
3736
},
3837
"devDependencies": {
39-
"@types/chai": "^4.2.22",
4038
"@types/escape-html": "^1.0.1",
4139
"@types/glob": "^7.2.0",
42-
"@types/jsonexport": "^3.0.2",
4340
"@types/marked": "^4.0.0",
4441
"@types/mime": "^2.0.3",
4542
"@types/mocha": "^9.0.0",
@@ -48,7 +45,6 @@
4845
"@types/sinon": "^10.0.6",
4946
"@types/update-notifier": "^6.0.0",
5047
"c8": "^7.10.0",
51-
"chai": "^4.3.4",
5248
"codecov": "^3.8.2",
5349
"execa": "^6.0.0",
5450
"gts": "^4.0.0",

‎src/cli.ts

+31-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import meow from 'meow';
44
import updateNotifier from 'update-notifier';
55
import chalk from 'chalk';
6-
import jsonexport from 'jsonexport';
76
import fs from 'fs';
87
import {URL} from 'url';
98
import {Flags, getConfig} from './config.js';
@@ -147,6 +146,10 @@ async function main() {
147146
logger.error(`🏊‍♂️ crawling ${cli.input}`);
148147

149148
const checker = new LinkChecker();
149+
if (format === Format.CSV) {
150+
const header = 'url,status,state,parent,failureDetails';
151+
console.log(header);
152+
}
150153
checker.on('retry', (info: RetryInfo) => {
151154
logger.warn(`Retrying: ${info.url} in ${info.secondsUntilRetry} seconds.`);
152155
});
@@ -166,6 +169,16 @@ async function main() {
166169
logger.info(`${state} ${chalk.gray(link.url)}`);
167170
break;
168171
}
172+
if (format === Format.CSV) {
173+
const showIt = shouldShowResult(link, verbosity);
174+
if (showIt) {
175+
console.log(
176+
`"${link.url}",${link.status},${link.state},"${link.parent || ''}","${
177+
link.failureDetails || ''
178+
}"`
179+
);
180+
}
181+
}
169182
});
170183
const opts: CheckOptions = {
171184
path: cli.input,
@@ -203,27 +216,14 @@ async function main() {
203216
];
204217
}
205218
const result = await checker.check(opts);
206-
const filteredResults = result.links.filter(link => {
207-
switch (link.state) {
208-
case LinkState.OK:
209-
return verbosity <= LogLevel.WARNING;
210-
case LinkState.BROKEN:
211-
if (verbosity > LogLevel.DEBUG) {
212-
link.failureDetails = undefined;
213-
}
214-
return verbosity <= LogLevel.ERROR;
215-
case LinkState.SKIPPED:
216-
return verbosity <= LogLevel.INFO;
217-
}
218-
});
219+
const filteredResults = result.links.filter(link =>
220+
shouldShowResult(link, verbosity)
221+
);
219222
if (format === Format.JSON) {
220223
result.links = filteredResults;
221224
console.log(JSON.stringify(result, null, 2));
222225
return;
223226
} else if (format === Format.CSV) {
224-
result.links = filteredResults;
225-
const csv = await jsonexport(result.links);
226-
console.log(csv);
227227
return;
228228
} else {
229229
// Build a collection scanned links, collated by the parent link used in
@@ -351,4 +351,18 @@ function parseFormat(flags: Flags): Format {
351351
return Format[flags.format as keyof typeof Format];
352352
}
353353

354+
function shouldShowResult(link: LinkResult, verbosity: LogLevel) {
355+
switch (link.state) {
356+
case LinkState.OK:
357+
return verbosity <= LogLevel.WARNING;
358+
case LinkState.BROKEN:
359+
if (verbosity > LogLevel.DEBUG) {
360+
link.failureDetails = undefined;
361+
}
362+
return verbosity <= LogLevel.ERROR;
363+
case LinkState.SKIPPED:
364+
return verbosity <= LogLevel.INFO;
365+
}
366+
}
367+
354368
main();

‎test/test.cli.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {describe, it} from 'mocha';
22
import {execa} from 'execa';
3-
import {assert} from 'chai';
3+
import assert from 'assert';
44
import http from 'http';
55
import util from 'util';
66
import {URL} from 'url';
@@ -98,7 +98,7 @@ describe('cli', function () {
9898
'csv',
9999
'test/fixtures/markdown/README.md',
100100
]);
101-
assert.match(res.stdout, /README.md,200,OK,/);
101+
assert.match(res.stdout, /README.md",200,OK,/);
102102
});
103103

104104
it('should provide JSON if asked nicely', async () => {
@@ -118,7 +118,7 @@ describe('cli', function () {
118118
'--silent',
119119
'test/fixtures/markdown/README.md',
120120
]);
121-
assert.notMatch(res.stdout, /\[/);
121+
assert.doesNotMatch(res.stdout, /\[/);
122122
});
123123

124124
it('should not show 200 links if verbosity is ERROR with JSON', async () => {
@@ -274,7 +274,7 @@ describe('cli', function () {
274274
requestCount++;
275275
firstRequestTime = Date.now();
276276
} else {
277-
assert.isAtLeast(Date.now(), firstRequestTime + delayMillis);
277+
assert.ok(Date.now() >= firstRequestTime + delayMillis);
278278
res.writeHead(200);
279279
}
280280
res.end();
@@ -288,6 +288,6 @@ describe('cli', function () {
288288
'test/fixtures/retryCLI',
289289
]);
290290
assert.strictEqual(res.exitCode, 0);
291-
assert.include(res.stdout, `Retrying: http://localhost:${port}`);
291+
assert.match(res.stdout, new RegExp(`Retrying: http://localhost:${port}/`));
292292
});
293293
});

‎test/test.retry.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {assert} from 'chai';
1+
import assert from 'assert';
22
import nock from 'nock';
33
import sinon from 'sinon';
44
import {describe, it, afterEach} from 'mocha';
@@ -111,12 +111,12 @@ describe('retries', () => {
111111
'retry-after': '3',
112112
})
113113
.get('/1', () => {
114-
assert.isAtLeast(Date.now(), 3000);
114+
assert.ok(Date.now() >= 3000);
115115
return true;
116116
})
117117
.reply(200)
118118
.get('/2', () => {
119-
assert.isAtLeast(Date.now(), 3000);
119+
assert.ok(Date.now() >= 3000);
120120
return true;
121121
})
122122
.reply(200)
@@ -125,7 +125,7 @@ describe('retries', () => {
125125
'retry-after': '3',
126126
})
127127
.get('/3', () => {
128-
assert.isAtLeast(Date.now(), 3000);
128+
assert.ok(Date.now() >= 3000);
129129
return true;
130130
})
131131
.reply(200);
@@ -158,12 +158,12 @@ describe('retries', () => {
158158
// make sure the /3 route reset it to 9 seconds here. This is common
159159
// when a flood of requests come through and the retry-after gets
160160
// extended.
161-
assert.isAtLeast(Date.now(), 9000);
161+
assert.ok(Date.now() >= 9000);
162162
return true;
163163
})
164164
.reply(200)
165165
.get('/2', () => {
166-
assert.isAtLeast(Date.now(), 9000);
166+
assert.ok(Date.now() >= 9000);
167167
return true;
168168
})
169169
.reply(200)
@@ -172,7 +172,7 @@ describe('retries', () => {
172172
'retry-after': '9',
173173
})
174174
.get('/3', () => {
175-
assert.isAtLeast(Date.now(), 9000);
175+
assert.ok(Date.now() >= 9000);
176176
return true;
177177
})
178178
.reply(200);

0 commit comments

Comments
 (0)
Please sign in to comment.