@spfn/cli 0.0.7 → 0.0.8

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.
package/lib/index.js CHANGED
@@ -13,7 +13,7 @@ program
13
13
  .command("login")
14
14
  .description("Authenticate via browser login")
15
15
  .action(() => {
16
- login();
16
+ (async () => { await login(); })();
17
17
  });
18
18
 
19
19
  program.parse();
package/lib/login.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import http from "http";
2
2
  import open from "open";
3
- import fs from "fs";
4
- import os from "os";
5
- import path from "path";
6
3
  import { execSync } from "child_process";
7
4
 
8
- const PORT = 5678;
5
+ const isDev = process.env.NODE_ENV === "development" || process.env.SF_ENV === "local";
6
+ const GIT_HOST = isDev ? "gitea:13000" : "git.superfunctions.ai";
7
+ const GIT_PROTOCOL = isDev ? "http" : "https";
9
8
 
10
9
  /**
11
10
  * Git credential helper를 이용해 특정 레포에 대한 인증 정보를 저장합니다.
@@ -16,10 +15,14 @@ const PORT = 5678;
16
15
  function installGitCredentials(
17
16
  username,
18
17
  token,
19
- repoPath
18
+ {
19
+ protocol = "https",
20
+ host,
21
+ path // optional
22
+ }
20
23
  )
21
24
  {
22
- // credential helper 설정
25
+ // credential helper 설정 (글로벌, 1회면 충분)
23
26
  if (process.platform === "win32")
24
27
  {
25
28
  execSync("git config --global credential.helper manager-core");
@@ -31,73 +34,30 @@ function installGitCredentials(
31
34
 
32
35
  // git credential approve 입력 생성
33
36
  const cred = [
34
- "protocol=https",
35
- "host=git.superfunctions.ai",
36
- `path=${repoPath}`,
37
+ `protocol=${protocol}`,
38
+ `host=${host}`,
39
+ path ? `path=${path}` : null,
37
40
  `username=${username}`,
38
41
  `password=${token}`,
39
42
  ""
40
- ].join("\n");
43
+ ].filter(Boolean).join("\n");
41
44
 
42
45
  execSync("git credential approve", {
43
46
  input: cred,
44
47
  stdio: ["pipe", "ignore", "inherit"]
45
48
  });
46
49
 
47
- console.log(`✔️ Stored credentials for git.superfunctions.ai/${repoPath}`);
48
- }
49
-
50
- /**
51
- * 시스템 전역에 SF_USERNAME, SF_ACCESS_TOKEN 환경변수를 등록합니다.
52
- * - Windows: setx 명령 사용
53
- * - macOS/Linux: 쉘 RC 파일(~/.zshrc or ~/.bash_profile)에 export 라인 추가
54
- */
55
- function persistEnvVars(username, token) {
56
- try {
57
- if (process.platform === "win32") {
58
- // Windows 환경변수 등록(기존 값이 있으면 덮어쓰기)
59
- execSync(`setx SF_USERNAME "${username}"`);
60
- execSync(`setx SF_ACCESS_TOKEN "${token}"`);
61
- console.log("✔️ Windows 환경변수에 SF_USERNAME, SF_ACCESS_TOKEN 등록/갱신 완료");
62
- } else {
63
- // macOS/Linux: 사용자 쉘 RC 파일 선택
64
- const shell = process.env.SHELL || "";
65
- const rcFile = shell.includes("zsh") ? ".zshrc" : ".bash_profile";
66
- const rcPath = path.join(os.homedir(), rcFile);
67
-
68
- // RC 파일 내용을 읽어서 기존 export 라인 제거
69
- const existing = fs.existsSync(rcPath)
70
- ? fs.readFileSync(rcPath, "utf8").split(/\r?\n/)
71
- : [];
72
-
73
- const filtered = existing.filter(
74
- (line) =>
75
- !/^export\s+SF_USERNAME=/.test(line) &&
76
- !/^export\s+SF_ACCESS_TOKEN=/.test(line) &&
77
- !/^# Superfunctions CLI 로그인/.test(line)
78
- );
79
-
80
- // 새 export 라인 추가
81
- const exportBlock = [
82
- "",
83
- "# Superfunctions CLI 로그인",
84
- `export SF_USERNAME="${username}"`,
85
- `export SF_ACCESS_TOKEN="${token}"`,
86
- ""
87
- ];
88
-
89
- const updated = filtered.concat(exportBlock);
90
- fs.writeFileSync(rcPath, updated.join(os.EOL), { encoding: "utf8" });
91
-
92
- console.log(`✔️ ${rcFile}에 SF_USERNAME, SF_ACCESS_TOKEN export 추가/갱신 완료`);
93
- console.log(` 적용하려면: source ~/${rcFile} 또는 터미널 재시작`);
94
- }
95
- } catch (e) {
96
- console.error("❌ 전역 환경변수 등록/갱신 실패:", e);
50
+ if (path)
51
+ {
52
+ console.log(`✔️ Stored credentials for ${protocol}://${host}/${path}`);
53
+ }
54
+ else
55
+ {
56
+ console.log(`✔️ Stored credentials for ${protocol}://${host}`);
97
57
  }
98
58
  }
99
59
 
100
- export function login()
60
+ export async function login()
101
61
  {
102
62
  try
103
63
  {
@@ -122,24 +82,22 @@ export function login()
122
82
  {
123
83
  try
124
84
  {
125
- const { username, token, projectSlug } = JSON.parse(body);
85
+ const { username, token } = JSON.parse(body);
126
86
  if (!username || !token)
127
87
  {
128
88
  res.writeHead(400).end("Missing username or token");
129
89
  return;
130
90
  }
131
91
 
132
- persistEnvVars(username, token);
133
-
134
92
  // npm registry 설정 (생략)
135
93
  try
136
94
  {
137
95
  execSync(
138
- `npm config set @sf:registry https://git.superfunctions.ai/api/packages/sf/npm/`,
96
+ `npm config set @sf:registry ${GIT_PROTOCOL}://${GIT_HOST}/api/packages/spfn/npm/`,
139
97
  { stdio: "inherit", env: process.env }
140
98
  );
141
99
  execSync(
142
- `npm config set //git.superfunctions.ai/api/packages/sf/npm/:_authToken \"${token}\"`,
100
+ `npm config set //${GIT_HOST}/api/packages/spfn/npm/:_authToken \"${token}\"`,
143
101
  { stdio: "inherit", env: process.env }
144
102
  );
145
103
  console.log("✔️ npm registry and authToken set via npm config");
@@ -150,22 +108,14 @@ export function login()
150
108
  }
151
109
 
152
110
  // 2개 레포에 대해 각각 자격증명 저장
153
- installGitCredentials(username, token, `${projectSlug}/${projectSlug}-server`);
154
- installGitCredentials(username, token, `${projectSlug}/${projectSlug}-app`);
111
+ installGitCredentials(username, token, {
112
+ protocol: GIT_PROTOCOL,
113
+ host: GIT_HOST
114
+ });
155
115
 
156
116
  res.writeHead(200, { "Content-Type": "text/plain" });
157
117
  res.end("✅ Login successful! You can now close this window.");
158
118
 
159
- console.log();
160
- console.log("💡 Tips:");
161
- console.log(
162
- ` git clone https://git.superfunctions.ai/${projectSlug}/${projectSlug}-server`
163
- );
164
- console.log(
165
- ` git clone https://git.superfunctions.ai/${projectSlug}/${projectSlug}-app`
166
- );
167
- console.log();
168
-
169
119
  server.close();
170
120
  }
171
121
  catch (err)
@@ -182,14 +132,36 @@ export function login()
182
132
  }
183
133
  });
184
134
 
185
- server.listen(PORT, () =>
135
+ const port = await getAvailablePort();
136
+
137
+ // 로그인 UI 주소도 분기
138
+ const isDev = process.env.NODE_ENV === "development" || process.env.SF_ENV === "local";
139
+ const LOGIN_UI_URL = isDev
140
+ ? `http://localhost:3000/cli-login?port=${port}`
141
+ : `https://console.superfunctions.ai/cli-login?port=${port}`;
142
+
143
+ server.listen(port, () =>
186
144
  {
187
145
  console.log("🌐 Opening browser for login...");
188
- open(`https://console.superfunctions.ai/cli-login?port=${PORT}`);
146
+ open(LOGIN_UI_URL);
189
147
  });
190
148
  }
191
149
  catch (err)
192
150
  {
193
151
  console.error(err);
194
152
  }
195
- }
153
+ }
154
+
155
+ function getAvailablePort(defaultPort = 5678) {
156
+ return new Promise((resolve) => {
157
+ const srv = http.createServer();
158
+ srv.listen(defaultPort, () => {
159
+ srv.close(() => resolve(defaultPort));
160
+ });
161
+ srv.on("error", () => {
162
+ // 사용 중이면 10000~20000 사이 랜덤 포트
163
+ const randomPort = Math.floor(Math.random() * 10000) + 10000;
164
+ resolve(randomPort);
165
+ });
166
+ });
167
+ }
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@spfn/cli",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Superfunction CLI",
5
+ "scripts": {
6
+ "start": "node lib/index.js",
7
+ "start:dev": "NODE_ENV=development node lib/index.js",
8
+ "start:prod": "NODE_ENV=production node lib/index.js"
9
+ },
5
10
  "keywords": [
6
11
  "cli",
7
12
  "superfunction",
@@ -12,7 +17,7 @@
12
17
  "homepage": "https://console.superfunctions.ai",
13
18
  "repository": {
14
19
  "type": "git",
15
- "url": "https://git.superfunctions.ai/sf/sf-cli.git"
20
+ "url": "https://git.superfunctions.ai/spfn/sf-cli.git"
16
21
  },
17
22
  "license": "MIT",
18
23
  "author": "Superfunction Ray <rayim@superfunctions.ai>",
@@ -27,9 +32,6 @@
27
32
  "files": [
28
33
  "lib/**/*"
29
34
  ],
30
- "scripts": {
31
- "start": "node lib/index.js"
32
- },
33
35
  "dependencies": {
34
36
  "commander": "^13.1.0",
35
37
  "open": "^10.1.1"