@rhseung/ps-cli 1.0.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,21 +4,21 @@ import {
4
4
  } from "../chunk-EIFFWFLS.js";
5
5
  import {
6
6
  detectProblemIdFromPath,
7
+ getProblemDirPath,
7
8
  getProblemId
8
- } from "../chunk-OOTPZD7O.js";
9
+ } from "../chunk-BM3ZMA4K.js";
9
10
  import {
10
11
  detectLanguageFromFile,
11
12
  getSupportedLanguages,
12
13
  getSupportedLanguagesString
13
14
  } from "../chunk-TQXMB7XV.js";
14
- import {
15
- LoadingSpinner
16
- } from "../chunk-IJLJBKLK.js";
15
+ import "../chunk-CIG2LEJC.js";
17
16
  import "../chunk-FYS2JH42.js";
18
17
 
19
18
  // src/commands/test.tsx
20
19
  import { useEffect, useState } from "react";
21
20
  import { render, Box as Box2, Text as Text2 } from "ink";
21
+ import { Alert } from "@inkjs/ui";
22
22
  import chokidar from "chokidar";
23
23
  import { readdir as readdir2 } from "fs/promises";
24
24
  import { join as join2 } from "path";
@@ -134,8 +134,12 @@ async function runAllTests({
134
134
  return { results, summary: buildSummary(results) };
135
135
  }
136
136
 
137
+ // src/commands/test.tsx
138
+ import { Spinner } from "@inkjs/ui";
139
+
137
140
  // src/components/test-result.tsx
138
141
  import { Box, Text } from "ink";
142
+ import { Badge, StatusMessage } from "@inkjs/ui";
139
143
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
140
144
  function truncate(text = "", max = 200) {
141
145
  return text.length > max ? `${text.slice(0, max)}...` : text;
@@ -145,14 +149,11 @@ function formatDuration(ms) {
145
149
  return `${(ms / 1e3).toFixed(2)}s`;
146
150
  }
147
151
  function ResultRow({ result }) {
148
- const statusIcon = result.status === "pass" ? "\u2713" : result.status === "fail" ? "\u2717" : "!";
149
- const statusColor = result.status === "pass" ? "green" : result.status === "fail" ? "red" : "yellow";
152
+ const badgeColor = result.status === "pass" ? "green" : result.status === "fail" ? "red" : "yellow";
150
153
  const statusText = result.status === "pass" ? "PASS" : result.status === "fail" ? "FAIL" : "ERROR";
151
154
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
152
155
  /* @__PURE__ */ jsxs(Box, { children: [
153
- /* @__PURE__ */ jsx(Text, { color: statusColor, bold: true, children: statusIcon }),
154
- /* @__PURE__ */ jsx(Text, { children: " " }),
155
- /* @__PURE__ */ jsx(Text, { color: statusColor, bold: true, children: statusText }),
156
+ /* @__PURE__ */ jsx(Badge, { color: badgeColor, children: statusText }),
156
157
  /* @__PURE__ */ jsx(Text, { children: " " }),
157
158
  /* @__PURE__ */ jsxs(Text, { children: [
158
159
  "\uCF00\uC774\uC2A4 ",
@@ -185,47 +186,13 @@ function ResultRow({ result }) {
185
186
  }
186
187
  function TestResultView({ summary, results }) {
187
188
  const allPassed = summary.failed === 0 && summary.errored === 0;
188
- const summaryColor = allPassed ? "green" : "red";
189
+ const summaryVariant = allPassed ? "success" : "error";
190
+ const summaryText = `\uCD1D ${summary.total}\uAC1C | Pass ${summary.passed}${summary.failed > 0 ? ` | Fail ${summary.failed}` : ""}${summary.errored > 0 ? ` | Error ${summary.errored}` : ""}`;
189
191
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
190
- /* @__PURE__ */ jsxs(
191
- Box,
192
- {
193
- borderStyle: "round",
194
- borderColor: summaryColor,
195
- paddingX: 1,
196
- alignSelf: "flex-start",
197
- flexDirection: "column",
198
- children: [
199
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { bold: true, children: "\uD14C\uC2A4\uD2B8 \uACB0\uACFC" }) }),
200
- /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
201
- /* @__PURE__ */ jsxs(Text, { children: [
202
- "\uCD1D ",
203
- /* @__PURE__ */ jsx(Text, { bold: true, children: summary.total }),
204
- "\uAC1C"
205
- ] }),
206
- /* @__PURE__ */ jsx(Text, { children: " | " }),
207
- /* @__PURE__ */ jsxs(Text, { color: "green", children: [
208
- "Pass ",
209
- /* @__PURE__ */ jsx(Text, { bold: true, children: summary.passed })
210
- ] }),
211
- summary.failed > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
212
- /* @__PURE__ */ jsx(Text, { children: " | " }),
213
- /* @__PURE__ */ jsxs(Text, { color: "red", children: [
214
- "Fail ",
215
- /* @__PURE__ */ jsx(Text, { bold: true, children: summary.failed })
216
- ] })
217
- ] }),
218
- summary.errored > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
219
- /* @__PURE__ */ jsx(Text, { children: " | " }),
220
- /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
221
- "Error ",
222
- /* @__PURE__ */ jsx(Text, { bold: true, children: summary.errored })
223
- ] })
224
- ] })
225
- ] })
226
- ]
227
- }
228
- ),
192
+ /* @__PURE__ */ jsxs(StatusMessage, { variant: summaryVariant, children: [
193
+ "\uD14C\uC2A4\uD2B8 \uACB0\uACFC: ",
194
+ summaryText
195
+ ] }),
229
196
  /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: results.map((r) => /* @__PURE__ */ jsx(ResultRow, { result: r }, r.caseId)) })
230
197
  ] });
231
198
  }
@@ -296,16 +263,13 @@ function TestCommand({
296
263
  return void 0;
297
264
  }, [status, watch, onComplete]);
298
265
  if (status === "loading") {
299
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
300
- /* @__PURE__ */ jsx2(Text2, { children: "\uD14C\uC2A4\uD2B8 \uC2E4\uD589 \uC911..." }),
301
- /* @__PURE__ */ jsx2(LoadingSpinner, {})
302
- ] });
266
+ return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: /* @__PURE__ */ jsx2(Spinner, { label: "\uD14C\uC2A4\uD2B8 \uC2E4\uD589 \uC911..." }) });
303
267
  }
304
268
  if (status === "error") {
305
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
306
- /* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u2717 \uD14C\uC2A4\uD2B8 \uC2E4\uD589 \uC2E4\uD328" }),
307
- error && /* @__PURE__ */ jsx2(Text2, { color: "gray", children: error })
308
- ] });
269
+ return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: /* @__PURE__ */ jsxs2(Alert, { variant: "error", children: [
270
+ "\uD14C\uC2A4\uD2B8 \uC2E4\uD589 \uC2E4\uD328",
271
+ error ? `: ${error}` : ""
272
+ ] }) });
309
273
  }
310
274
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
311
275
  /* @__PURE__ */ jsxs2(Box2, { marginBottom: 1, children: [
@@ -335,7 +299,7 @@ async function detectLanguage(problemDir) {
335
299
  }
336
300
  async function testCommand(options = {}) {
337
301
  const currentPathProblemId = detectProblemIdFromPath(process.cwd());
338
- const problemDir = options.id && currentPathProblemId !== options.id ? join2(process.cwd(), "problems", String(options.id)) : process.cwd();
302
+ const problemDir = options.id && currentPathProblemId !== options.id ? getProblemDirPath(options.id) : process.cwd();
339
303
  const language = options.language ?? await detectLanguage(problemDir);
340
304
  return new Promise((resolve) => {
341
305
  const { unmount } = render(
package/dist/index.js CHANGED
@@ -9359,6 +9359,7 @@ var meow = (helpText, options = {}) => {
9359
9359
  import { readdir } from "fs/promises";
9360
9360
  import { join, dirname } from "path";
9361
9361
  import { fileURLToPath as fileURLToPath3 } from "url";
9362
+ import { existsSync } from "fs";
9362
9363
  function getCommandsDir() {
9363
9364
  const __filename = fileURLToPath3(import.meta.url);
9364
9365
  const __dirname = dirname(__filename);
@@ -9495,6 +9496,30 @@ async function main() {
9495
9496
  process.exit(1);
9496
9497
  return;
9497
9498
  }
9499
+ if (command !== "init") {
9500
+ let currentDir = process.cwd();
9501
+ let found = false;
9502
+ const rootPath = process.platform === "win32" ? currentDir.split("\\")[0] + "\\" : "/";
9503
+ while (currentDir !== rootPath && !found) {
9504
+ const projectConfigPath = join(currentDir, ".ps-cli.json");
9505
+ if (existsSync(projectConfigPath)) {
9506
+ found = true;
9507
+ break;
9508
+ }
9509
+ const parentDir = dirname(currentDir);
9510
+ if (parentDir === currentDir) {
9511
+ break;
9512
+ }
9513
+ currentDir = parentDir;
9514
+ }
9515
+ if (!found) {
9516
+ console.error("\uC624\uB958: \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uAC00 ps-cli \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2D9\uB2C8\uB2E4.");
9517
+ console.error("\uD504\uB85C\uC81D\uD2B8\uB97C \uCD08\uAE30\uD654\uD558\uB824\uBA74 \uB2E4\uC74C \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD558\uC138\uC694:");
9518
+ console.error(" $ ps init");
9519
+ process.exit(1);
9520
+ return;
9521
+ }
9522
+ }
9498
9523
  await commandDef.execute(args, cli.flags);
9499
9524
  }
9500
9525
  main().catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhseung/ps-cli",
3
- "version": "1.0.0",
3
+ "version": "1.3.0",
4
4
  "description": "백준(BOJ) 문제 해결을 위한 통합 CLI 도구",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,7 +13,10 @@
13
13
  "scripts": {
14
14
  "build": "tsup && node scripts/add-shebang.js",
15
15
  "dev": "tsup --watch",
16
- "typecheck": "tsc --noEmit"
16
+ "typecheck": "tsc --noEmit",
17
+ "release:patch": "npm version patch && bun publish --access=public",
18
+ "release:minor": "npm version minor && bun publish --access=public",
19
+ "release:major": "npm version major && bun publish --access=public"
17
20
  },
18
21
  "keywords": [
19
22
  "boj",
@@ -41,8 +44,7 @@
41
44
  "execa": "^9.4.0",
42
45
  "gradient-string": "^2.0.2",
43
46
  "ink": "^5.0.1",
44
- "ink-select-input": "^5.0.0",
45
- "ink-spinner": "^5.0.0",
47
+ "@inkjs/ui": "^2.0.0",
46
48
  "meow": "^14.0.0",
47
49
  "react": "^18.3.1"
48
50
  },