Skip to content

Commit 2112ede

Browse files
committed
feat(cli): add error handling
1 parent 7ce598f commit 2112ede

4 files changed

Lines changed: 73 additions & 31 deletions

File tree

src/cli/index.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { installGithubActions } from "./install-ga";
1313
import { installLintStaged } from "./install-lint-staged";
1414
import { installPrettier } from "./install-prettier";
1515

16+
const REPO_URL = "https://github.com/Solvro/lib-web-solvro-config";
17+
1618
// Types
1719
interface CliOptions {
1820
force?: boolean;
@@ -54,9 +56,9 @@ async function main() {
5456
const warningMessage = `
5557
${c.red(c.bold(`⚠️ OSTRZEŻENIE: ${packageManager} nie jest obsługiwany ⚠️`))}
5658
57-
Próbujesz uruchomić ten skrypt z ${c.yellow(packageManager)}'em, ale @solvro/config działa tylko z ${c.yellow("npm'em")}.
59+
Próbujesz uruchomić ten skrypt z ${c.yellow(packageManager)}'em, ale @solvro/config obecnie działa tylko z ${c.yellow("npm")}'em.
5860
59-
Support dla innych menedżerów pakietów nie jest planowany - chcemy jednolitego stacku technologicznego dla projektów w naszym kochanym kole Solvro.
61+
Support dla innych menedżerów pakietów jest planowany w nadchodzących wersjach - zagwiazdkuj i spróbuj ponownie wkrótce!.
6062
6163
Użyj zamiast tego npm'a:
6264
${c.cyan("npx @solvro/config")}`;
@@ -249,18 +251,33 @@ ${c.cyan("npx @solvro/config")}`;
249251

250252
await packageJson.clearInstall();
251253

252-
if (isNonInteractive) {
253-
console.log("✅ Konfiguracja zakończona pomyślnie!");
254-
} else {
255-
p.outro("✅ Konfiguracja zakończona pomyślnie!");
256-
}
254+
const printSuccess = isNonInteractive ? console.info : p.outro;
255+
printSuccess("✅ Konfiguracja zakończona pomyślnie!");
257256
}
258257

259-
// Run the main function
260-
try {
261-
// eslint-disable-next-line unicorn/prefer-top-level-await
262-
void main();
263-
} catch (error: unknown) {
264-
console.error("Wystąpił błąd:", error);
265-
process.exit(1);
258+
async function mainWrapper() {
259+
try {
260+
await main();
261+
} catch (error: unknown) {
262+
if (process.env.NODE_ENV === "development") {
263+
console.error(
264+
c.red("Unhandled error in main:"),
265+
error instanceof Error ? error.message : error,
266+
);
267+
} else {
268+
const errorMessage =
269+
"Wystąpił nieoczekiwany błąd :( Proszę zgłosić go twórcom:";
270+
const errorLink = `${REPO_URL}/issues/new`;
271+
if (isNonInteractive) {
272+
console.error(errorMessage);
273+
console.error(errorLink);
274+
} else {
275+
p.cancel(`${errorMessage} ${errorLink}`);
276+
}
277+
}
278+
process.exit(1);
279+
}
266280
}
281+
282+
// eslint-disable-next-line unicorn/prefer-top-level-await
283+
void mainWrapper();

src/eslint/configs/comments.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export function comments(): ConfigWithExtends[] {
77
{
88
name: "solvro/eslint-comments/rules",
99
plugins: {
10-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1110
"eslint-comments": pluginComments,
1211
},
1312
rules: {

src/utils/package-json.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import semver from "semver";
77

88
import { $$ } from "./$$";
99
import { projectRoot } from "./git-root";
10-
import { runIfInteractive } from "./run-if-interactive";
10+
import { runWithSpinner } from "./run-with-spinner";
1111

1212
export class PackageJson {
1313
public json: Awaited<ReturnType<typeof loadPackageJSON>> = null;
@@ -121,14 +121,13 @@ export class PackageJson {
121121
const isInstalled = await this.hasPackage(package_);
122122

123123
if (!isInstalled) {
124-
const spinner = p.spinner();
125-
runIfInteractive(() => {
126-
spinner.start(`Instalowanie ${package_}`);
127-
});
128-
129-
await $$`npm i ${options?.dev === true ? "-D" : ""} ${package_}@latest`;
130-
runIfInteractive(() => {
131-
spinner.stop(`${package_} zainstalowany 😍`);
124+
await runWithSpinner({
125+
start: `Instalowanie ${package_}`,
126+
stop: `${package_} zainstalowany 😍`,
127+
error: `Instalacja pakietu ${package_} nie powiodła się 🥶`,
128+
callback: async () => {
129+
await $$`npm i ${options?.dev === true ? "-D" : ""} ${package_}@latest`;
130+
},
132131
});
133132

134133
await this.load();
@@ -144,13 +143,13 @@ export class PackageJson {
144143
!semver.satisfies(info.version, options.minVersion)) ||
145144
options?.alwaysUpdate === true
146145
) {
147-
const spinner = p.spinner();
148-
runIfInteractive(() => {
149-
spinner.start(`Aktualizowanie ${package_}`);
150-
});
151-
await $$`npm i ${options.dev === true ? "-D" : ""} ${package_}@latest`;
152-
runIfInteractive(() => {
153-
spinner.stop(`${package_} zaktualizowany 😍`);
146+
await runWithSpinner({
147+
start: `Aktualizowanie ${package_}`,
148+
stop: `${package_} zaktualizowany 😍`,
149+
error: `Aktualiacja pakietu ${package_} nie powiodła się 🥶`,
150+
callback: async () => {
151+
await $$`npm i ${options.dev === true ? "-D" : ""} ${package_}@latest`;
152+
},
154153
});
155154

156155
await this.load();

src/utils/run-with-spinner.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import * as p from "@clack/prompts";
2+
3+
import { runIfInteractive } from "./run-if-interactive";
4+
5+
/** Executes a callback using a clack spinner, printing the provided messages, with error handling. */
6+
export const runWithSpinner = async (options: {
7+
start: string;
8+
stop: string;
9+
error: string;
10+
callback: () => void | Promise<void>;
11+
}) => {
12+
const spinner = p.spinner();
13+
runIfInteractive(() => {
14+
spinner.start(options.start);
15+
});
16+
try {
17+
await options.callback();
18+
} catch (error) {
19+
runIfInteractive(() => {
20+
spinner.error(options.error);
21+
});
22+
throw error;
23+
}
24+
runIfInteractive(() => {
25+
spinner.stop(options.stop);
26+
});
27+
};

0 commit comments

Comments
 (0)