@rhseung/ps-cli 1.10.2 → 1.11.1

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- openBrowser
4
- } from "./chunk-QGMWUOJ3.js";
3
+ useOpenBrowser
4
+ } from "./chunk-3LR2NGRC.js";
5
5
  import {
6
6
  Command,
7
7
  CommandBuilder,
@@ -17,55 +17,8 @@ import {
17
17
  import { StatusMessage, Alert, Spinner } from "@inkjs/ui";
18
18
  import { Text, Box } from "ink";
19
19
 
20
- // src/hooks/use-open-browser.ts
21
- import { useEffect, useState } from "react";
22
- var BOJ_BASE_URL = "https://www.acmicpc.net";
23
- function useOpenBrowser({
24
- problemId,
25
- workbookId,
26
- onComplete
27
- }) {
28
- const [status, setStatus] = useState(
29
- "loading"
30
- );
31
- const [error, setError] = useState(null);
32
- const [url, setUrl] = useState("");
33
- useEffect(() => {
34
- async function handleOpenBrowser() {
35
- try {
36
- let targetUrl;
37
- if (workbookId !== void 0) {
38
- targetUrl = `${BOJ_BASE_URL}/workbook/view/${workbookId}`;
39
- } else if (problemId !== void 0) {
40
- targetUrl = `${BOJ_BASE_URL}/problem/${problemId}`;
41
- } else {
42
- throw new Error("\uBB38\uC81C \uBC88\uD638 \uB610\uB294 \uBB38\uC81C\uC9D1 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.");
43
- }
44
- setUrl(targetUrl);
45
- await openBrowser(targetUrl);
46
- setStatus("success");
47
- setTimeout(() => {
48
- onComplete?.();
49
- }, 1500);
50
- } catch (err) {
51
- setStatus("error");
52
- setError(err instanceof Error ? err.message : String(err));
53
- setTimeout(() => {
54
- onComplete?.();
55
- }, 2e3);
56
- }
57
- }
58
- void handleOpenBrowser();
59
- }, [problemId, workbookId, onComplete]);
60
- return {
61
- status,
62
- error,
63
- url
64
- };
65
- }
66
-
67
20
  // src/hooks/use-open-editor.ts
68
- import { useEffect as useEffect2, useState as useState2 } from "react";
21
+ import { useEffect, useState } from "react";
69
22
 
70
23
  // src/utils/editor.ts
71
24
  import { execaCommand } from "execa";
@@ -83,11 +36,11 @@ function useOpenEditor({
83
36
  path,
84
37
  onComplete
85
38
  }) {
86
- const [status, setStatus] = useState2(
39
+ const [status, setStatus] = useState(
87
40
  "loading"
88
41
  );
89
- const [error, setError] = useState2(null);
90
- useEffect2(() => {
42
+ const [error, setError] = useState(null);
43
+ useEffect(() => {
91
44
  async function handleOpenEditor() {
92
45
  if (!path) {
93
46
  setStatus("error");
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ openBrowser
4
+ } from "./chunk-QGMWUOJ3.js";
5
+
6
+ // src/hooks/use-open-browser.ts
7
+ import { useEffect, useState } from "react";
8
+ var BOJ_BASE_URL = "https://www.acmicpc.net";
9
+ function useOpenBrowser({
10
+ problemId,
11
+ workbookId,
12
+ onComplete
13
+ }) {
14
+ const [status, setStatus] = useState(
15
+ "loading"
16
+ );
17
+ const [error, setError] = useState(null);
18
+ const [url, setUrl] = useState("");
19
+ useEffect(() => {
20
+ async function handleOpenBrowser() {
21
+ try {
22
+ let targetUrl;
23
+ if (workbookId !== void 0) {
24
+ targetUrl = `${BOJ_BASE_URL}/workbook/view/${workbookId}`;
25
+ } else if (problemId !== void 0) {
26
+ targetUrl = `${BOJ_BASE_URL}/problem/${problemId}`;
27
+ } else {
28
+ throw new Error("\uBB38\uC81C \uBC88\uD638 \uB610\uB294 \uBB38\uC81C\uC9D1 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.");
29
+ }
30
+ setUrl(targetUrl);
31
+ await openBrowser(targetUrl);
32
+ setStatus("success");
33
+ setTimeout(() => {
34
+ onComplete?.();
35
+ }, 1500);
36
+ } catch (err) {
37
+ setStatus("error");
38
+ setError(err instanceof Error ? err.message : String(err));
39
+ setTimeout(() => {
40
+ onComplete?.();
41
+ }, 2e3);
42
+ }
43
+ }
44
+ void handleOpenBrowser();
45
+ }, [problemId, workbookId, onComplete]);
46
+ return {
47
+ status,
48
+ error,
49
+ url
50
+ };
51
+ }
52
+
53
+ export {
54
+ useOpenBrowser
55
+ };
@@ -1,8 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- getLanguageConfig
3
+ getLanguageConfig,
4
+ getProblemTimeLimitMs
4
5
  } from "./chunk-AHE4QHJD.js";
5
6
 
7
+ // src/hooks/use-run-solution.ts
8
+ import { useEffect, useState } from "react";
9
+
6
10
  // src/services/runner.ts
7
11
  import { readFile } from "fs/promises";
8
12
  import { join } from "path";
@@ -89,6 +93,52 @@ async function runSolution({
89
93
  }
90
94
  }
91
95
 
96
+ // src/hooks/use-run-solution.ts
97
+ function useRunSolution({
98
+ problemDir,
99
+ language,
100
+ inputFile,
101
+ onComplete
102
+ }) {
103
+ const [status, setStatus] = useState(
104
+ "loading"
105
+ );
106
+ const [result, setResult] = useState(null);
107
+ const [error, setError] = useState(null);
108
+ useEffect(() => {
109
+ async function run() {
110
+ const timeLimitMs = await getProblemTimeLimitMs(problemDir);
111
+ const effectiveTimeout = timeLimitMs ? timeLimitMs * 5 : 1e4;
112
+ try {
113
+ const runResult = await runSolution({
114
+ problemDir,
115
+ language,
116
+ inputPath: inputFile,
117
+ timeoutMs: effectiveTimeout
118
+ });
119
+ setResult(runResult);
120
+ setStatus("ready");
121
+ setTimeout(() => {
122
+ onComplete();
123
+ }, 100);
124
+ } catch (err) {
125
+ setError(err instanceof Error ? err.message : String(err));
126
+ setStatus("error");
127
+ setTimeout(() => {
128
+ onComplete();
129
+ }, 2e3);
130
+ }
131
+ }
132
+ void run();
133
+ }, [problemDir, language, inputFile, onComplete]);
134
+ return {
135
+ status,
136
+ result,
137
+ error
138
+ };
139
+ }
140
+
92
141
  export {
93
- runSolution
142
+ runSolution,
143
+ useRunSolution
94
144
  };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- openBrowser
4
- } from "./chunk-QGMWUOJ3.js";
3
+ useSubmit
4
+ } from "./chunk-MZUR7SER.js";
5
5
  import {
6
6
  Command,
7
7
  CommandBuilder,
@@ -18,102 +18,6 @@ import {
18
18
  // src/commands/submit.tsx
19
19
  import { Badge, StatusMessage, Alert, Spinner } from "@inkjs/ui";
20
20
  import { Text, Box } from "ink";
21
-
22
- // src/hooks/use-submit.ts
23
- import { readFile } from "fs/promises";
24
- import { useEffect, useState } from "react";
25
-
26
- // src/utils/clipboard.ts
27
- import { execa, execaCommand } from "execa";
28
- async function copyToClipboard(text) {
29
- try {
30
- if (process.platform === "win32") {
31
- await execaCommand("clip", {
32
- shell: true,
33
- input: text
34
- });
35
- } else if (process.platform === "darwin") {
36
- await execaCommand("pbcopy", {
37
- shell: false,
38
- input: text
39
- });
40
- } else {
41
- try {
42
- await execa("xclip", ["-selection", "clipboard"], {
43
- input: text
44
- });
45
- } catch {
46
- try {
47
- await execa("xsel", ["--clipboard", "--input"], {
48
- input: text
49
- });
50
- } catch {
51
- return false;
52
- }
53
- }
54
- }
55
- return true;
56
- } catch {
57
- return false;
58
- }
59
- }
60
-
61
- // src/hooks/use-submit.ts
62
- var BOJ_BASE_URL = "https://www.acmicpc.net";
63
- function useSubmit({
64
- problemId,
65
- language: _language,
66
- sourcePath,
67
- onComplete
68
- }) {
69
- const [status, setStatus] = useState(
70
- "loading"
71
- );
72
- const [message, setMessage] = useState("\uC81C\uCD9C \uC900\uBE44 \uC911...");
73
- const [error, setError] = useState(null);
74
- const [submitUrl, setSubmitUrl] = useState("");
75
- const [clipboardSuccess, setClipboardSuccess] = useState(false);
76
- const [clipboardError, setClipboardError] = useState(null);
77
- useEffect(() => {
78
- async function submit() {
79
- try {
80
- setMessage("\uC18C\uC2A4 \uCF54\uB4DC\uB97C \uC77D\uB294 \uC911...");
81
- const sourceCode = await readFile(sourcePath, "utf-8");
82
- setMessage("\uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBCF5\uC0AC\uD558\uB294 \uC911...");
83
- const clipboardResult = await copyToClipboard(sourceCode);
84
- setClipboardSuccess(clipboardResult);
85
- if (!clipboardResult) {
86
- setClipboardError("\uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
87
- }
88
- const url = `${BOJ_BASE_URL}/submit/${problemId}`;
89
- setSubmitUrl(url);
90
- setMessage("\uBE0C\uB77C\uC6B0\uC800\uB97C \uC5EC\uB294 \uC911...");
91
- await openBrowser(url);
92
- setStatus("success");
93
- setTimeout(() => {
94
- onComplete();
95
- }, 2e3);
96
- } catch (err) {
97
- setStatus("error");
98
- setError(err instanceof Error ? err.message : String(err));
99
- setTimeout(() => {
100
- onComplete();
101
- }, 2e3);
102
- }
103
- }
104
- void submit();
105
- }, [problemId, sourcePath, onComplete]);
106
- return {
107
- status,
108
- message,
109
- error,
110
- submitUrl,
111
- clipboardSuccess,
112
- clipboardError
113
- };
114
- }
115
-
116
- // src/commands/submit.tsx
117
21
  import { jsx, jsxs } from "react/jsx-runtime";
118
22
  var submitFlagsSchema = {
119
23
  language: {
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ useFetchProblem
4
+ } from "./chunk-ERJEYECY.js";
5
+ import {
6
+ Command,
7
+ CommandBuilder,
8
+ CommandDef,
9
+ __decorateClass,
10
+ defineFlags,
11
+ getSupportedLanguages,
12
+ getSupportedLanguagesString,
13
+ getTierColor,
14
+ getTierName,
15
+ logger,
16
+ resolveProblemContext
17
+ } from "./chunk-AHE4QHJD.js";
18
+
19
+ // src/commands/fetch.tsx
20
+ import { StatusMessage, Alert, Spinner } from "@inkjs/ui";
21
+ import { Box as Box2 } from "ink";
22
+
23
+ // src/components/problem-dashboard.tsx
24
+ import { Box, Text } from "ink";
25
+ import { jsx, jsxs } from "react/jsx-runtime";
26
+ function ProblemDashboard({ problem }) {
27
+ const tierName = getTierName(problem.level);
28
+ const tierColor = getTierColor(problem.level);
29
+ const borderColorString = typeof tierColor === "string" ? tierColor : "#ff7ca8";
30
+ const textColorString = borderColorString;
31
+ return /* @__PURE__ */ jsx(
32
+ Box,
33
+ {
34
+ flexDirection: "column",
35
+ borderStyle: "round",
36
+ borderColor: borderColorString,
37
+ paddingX: 1,
38
+ alignSelf: "flex-start",
39
+ children: /* @__PURE__ */ jsxs(Text, { bold: true, color: textColorString, children: [
40
+ tierName,
41
+ " ",
42
+ /* @__PURE__ */ jsxs(Text, { color: "white", children: [
43
+ "#",
44
+ problem.id,
45
+ ": ",
46
+ problem.title
47
+ ] })
48
+ ] })
49
+ }
50
+ );
51
+ }
52
+
53
+ // src/commands/fetch.tsx
54
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
55
+ var fetchFlagsSchema = {
56
+ language: {
57
+ type: "string",
58
+ shortFlag: "l",
59
+ description: `\uC5B8\uC5B4 \uC120\uD0DD (${getSupportedLanguagesString()})
60
+ \uAE30\uBCF8\uAC12: python`
61
+ }
62
+ };
63
+ function FetchView({
64
+ problemId,
65
+ language = "python",
66
+ onComplete
67
+ }) {
68
+ const { status, problem, error, message } = useFetchProblem({
69
+ problemId,
70
+ language,
71
+ onComplete
72
+ });
73
+ if (status === "loading") {
74
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
75
+ /* @__PURE__ */ jsx2(Spinner, { label: message }),
76
+ problem && /* @__PURE__ */ jsx2(ProblemDashboard, { problem })
77
+ ] });
78
+ }
79
+ if (status === "error") {
80
+ return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: /* @__PURE__ */ jsxs2(Alert, { variant: "error", children: [
81
+ "\uC624\uB958 \uBC1C\uC0DD: ",
82
+ error
83
+ ] }) });
84
+ }
85
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: "100%", children: [
86
+ problem && /* @__PURE__ */ jsx2(Box2, { alignSelf: "flex-start", children: /* @__PURE__ */ jsx2(ProblemDashboard, { problem }) }),
87
+ /* @__PURE__ */ jsx2(StatusMessage, { variant: "success", children: message })
88
+ ] });
89
+ }
90
+ var FetchCommand = class extends Command {
91
+ async execute(args, flags) {
92
+ const context = await resolveProblemContext(args, { requireId: true });
93
+ if (context.problemId === null) {
94
+ logger.error("\uBB38\uC81C \uBC88\uD638\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694.");
95
+ console.log(`\uB3C4\uC6C0\uB9D0: ps fetch --help`);
96
+ process.exit(1);
97
+ return;
98
+ }
99
+ const validLanguages = getSupportedLanguages();
100
+ const language = flags.language;
101
+ if (language && !validLanguages.includes(language)) {
102
+ console.error(
103
+ `\uC624\uB958: \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC5B8\uC5B4\uC785\uB2C8\uB2E4. (${getSupportedLanguagesString()})`
104
+ );
105
+ process.exit(1);
106
+ return;
107
+ }
108
+ await this.renderView(FetchView, {
109
+ problemId: context.problemId,
110
+ language: language || "python"
111
+ });
112
+ }
113
+ };
114
+ FetchCommand = __decorateClass([
115
+ CommandDef({
116
+ name: "fetch",
117
+ description: `\uBC31\uC900 \uBB38\uC81C\uB97C \uAC00\uC838\uC640\uC11C \uB85C\uCEEC\uC5D0 \uD30C\uC77C\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.
118
+ - Solved.ac API\uC640 BOJ \uD06C\uB864\uB9C1\uC744 \uD1B5\uD574 \uBB38\uC81C \uC815\uBCF4 \uC218\uC9D1
119
+ - \uBB38\uC81C \uC124\uBA85, \uC785\uCD9C\uB825 \uD615\uC2DD, \uC608\uC81C \uC785\uCD9C\uB825 \uD30C\uC77C \uC790\uB3D9 \uC0DD\uC131
120
+ - \uC120\uD0DD\uD55C \uC5B8\uC5B4\uC758 \uC194\uB8E8\uC158 \uD15C\uD50C\uB9BF \uD30C\uC77C \uC0DD\uC131
121
+ - README.md\uC5D0 \uBB38\uC81C \uC815\uBCF4, \uD1B5\uACC4, \uD0DC\uADF8(\uC124\uC815 \uC2DC) \uB4F1 \uD3EC\uD568
122
+ - \uAE30\uBCF8 \uC5B8\uC5B4, \uC5D0\uB514\uD130 \uC124\uC815 \uB4F1\uC740 ps config\uC5D0\uC11C \uC124\uC815 \uAC00\uB2A5\uD569\uB2C8\uB2E4.`,
123
+ flags: defineFlags(fetchFlagsSchema),
124
+ autoDetectProblemId: false,
125
+ requireProblemId: true,
126
+ examples: ["fetch 1000", "fetch 1000 --language python", "fetch 1000 -l cpp"]
127
+ })
128
+ ], FetchCommand);
129
+ var fetch_default = CommandBuilder.fromClass(FetchCommand);
130
+
131
+ export {
132
+ FetchView,
133
+ FetchCommand,
134
+ fetch_default
135
+ };