Skip to content

Commit ea2917c

Browse files
committed
fix: add missing null checks around values
Also uses `getColumns` for note wrapping and changes the `types` script to run `tsc` so we can catch these errors in CI in future.
1 parent 3280bc0 commit ea2917c

File tree

11 files changed

+144
-135
lines changed

11 files changed

+144
-135
lines changed

.changeset/kind-yaks-clean.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@clack/prompts": patch
3+
"@clack/core": patch
4+
---
5+
6+
Add missing nullish checks around values.

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ charset = utf-8
77
trim_trailing_whitespace = true
88
insert_final_newline = true
99

10-
[*.yml]
10+
[*.{yml,json,yaml}]
1111
indent_style = space
1212
indent_size = 2

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"dev": "pnpm --filter @example/changesets run start",
1010
"format": "biome check --write",
1111
"lint": "biome lint --write --unsafe",
12-
"types": "biome lint --write --unsafe",
12+
"types": "tsc --noEmit",
1313
"deps": "pnpm exec knip --production",
1414
"test": "pnpm --color -r run test",
1515
"pretest": "pnpm run build"

packages/core/src/prompts/multi-select.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ export default class MultiSelectPrompt<T extends { value: any }> extends Prompt<
2121
}
2222

2323
private toggleInvert() {
24-
const notSelected = this.options.filter((v) => !this.value.includes(v.value));
24+
const value = this.value;
25+
if (!value) {
26+
return;
27+
}
28+
const notSelected = this.options.filter((v) => !value.includes(v.value));
2529
this.value = notSelected.map((v) => v.value);
2630
}
2731

packages/core/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"extends": "../../tsconfig.json"
2+
"extends": "../../tsconfig.json",
3+
"include": ["src"]
34
}

packages/prompts/src/note.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import process from 'node:process';
22
import type { Writable } from 'node:stream';
33
import { stripVTControlCharacters as strip } from 'node:util';
4+
import { getColumns } from '@clack/core';
45
import { wrapAnsi } from 'fast-wrap-ansi';
56
import color from 'picocolors';
67
import {
@@ -13,13 +14,14 @@ import {
1314
S_STEP_SUBMIT,
1415
} from './common.js';
1516

17+
type FormatFn = (line: string) => string;
1618
export interface NoteOptions extends CommonOptions {
17-
format?: (line: string) => string;
19+
format?: FormatFn;
1820
}
1921

2022
const defaultNoteFormatter = (line: string): string => color.dim(line);
2123

22-
const wrapWithFormat = (message: string, width: number, format: NoteOptions['format']): string => {
24+
const wrapWithFormat = (message: string, width: number, format: FormatFn): string => {
2325
const wrapMsg = wrapAnsi(message, width).split('\n');
2426
const maxWidthNormal = wrapMsg.reduce((sum, ln) => Math.max(strip(ln).length, sum), 0);
2527
const maxWidthFormat = wrapMsg
@@ -32,7 +34,7 @@ const wrapWithFormat = (message: string, width: number, format: NoteOptions['for
3234
export const note = (message = '', title = '', opts?: NoteOptions) => {
3335
const output: Writable = opts?.output ?? process.stdout;
3436
const format = opts?.format ?? defaultNoteFormatter;
35-
const wrapMsg = wrapWithFormat(message, output.columns - 6, format);
37+
const wrapMsg = wrapWithFormat(message, getColumns(output) - 6, format);
3638
const lines = ['', ...wrapMsg.split('\n').map(format), ''];
3739
const titleLen = strip(title).length;
3840
const len =

packages/prompts/test/__snapshots__/note.test.ts.snap

Lines changed: 112 additions & 120 deletions
Large diffs are not rendered by default.

packages/prompts/test/note.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ describe.each(['true', 'false'])('note (isCI = %s)', (isCI) => {
6565
});
6666

6767
test("don't overflow", () => {
68-
const input = `${'test string '.repeat(32)}\n`.repeat(4).trim();
69-
prompts.note(input, 'title', {
68+
const message = `${'test string '.repeat(32)}\n`.repeat(4).trim();
69+
prompts.note(message, 'title', {
7070
input,
7171
output: Object.assign(output, { columns: 75 }),
7272
});
@@ -75,8 +75,8 @@ describe.each(['true', 'false'])('note (isCI = %s)', (isCI) => {
7575
});
7676

7777
test("don't overflow with formatter", () => {
78-
const input = `${'test string '.repeat(32)}\n`.repeat(4).trim();
79-
prompts.note(input, 'title', {
78+
const message = `${'test string '.repeat(32)}\n`.repeat(4).trim();
79+
prompts.note(message, 'title', {
8080
format: (line) => colors.red(`* ${colors.cyan(line)} *`),
8181
input,
8282
output: Object.assign(output, { columns: 75 }),

packages/prompts/test/password.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ describe.each(['true', 'false'])('password (isCI = %s)', (isCI) => {
7777
const result = prompts.password({
7878
message: 'foo',
7979
validate: (value) => {
80-
if (value.length < 2) {
80+
if (!value || value.length < 2) {
8181
return 'Password must be at least 2 characters';
8282
}
8383

packages/prompts/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"extends": "../../tsconfig.json"
2+
"extends": "../../tsconfig.json",
3+
"include": ["src"]
34
}

0 commit comments

Comments
 (0)