@bharatpanigrahi/onw-cli 1.1.0 → 1.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bharatpanigrahi/onw-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "A CLI tool for Claude AI",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -25,6 +25,7 @@
25
25
  "@clack/prompts": "^1.1.0",
26
26
  "@prisma/client": "^6.19.2",
27
27
  "ai": "^6.0.141",
28
+ "better-auth": "^1.5.6",
28
29
  "boxen": "^8.0.1",
29
30
  "chalk": "^5.6.2",
30
31
  "commandor": "^0.1.3",
@@ -1,4 +1,4 @@
1
- import { cancel, confirm, intro, isCancel, outro } from "@clack/prompts";
1
+ import { cancel, confirm, intro, isCancel, outro, text } from "@clack/prompts";
2
2
  import { logger } from "better-auth";
3
3
  import { createAuthClient } from "better-auth/client";
4
4
  import { deviceAuthorizationClient } from "better-auth/client/plugins";
@@ -12,21 +12,23 @@ import path from "path";
12
12
  import yoctoSpinner from "yocto-spinner";
13
13
  import * as z from "zod/v4";
14
14
  import { fetchUserFromAPI } from "../../../lib/api-client.js";
15
- import dotenv from "dotenv";
16
15
  import {
17
16
  clearStoredToken,
18
17
  getStoredToken,
19
18
  isTokenExpired,
20
19
  requireAuth,
21
20
  storeToken,
21
+ getStoredClientId,
22
+ storeClientId,
23
+ clearStoredClientId,
22
24
  } from "../../../lib/token.js";
23
25
 
24
- dotenv.config();
26
+ // dotenv.config();
25
27
 
26
- const URL = process.env.BASE_URL;
27
- const CLIENT_ID = process.env.GITHUB_CLIENT_ID;
28
+ const URL = "https://claude-code-topaz.vercel.app";
28
29
  export const CONFIG_DIR = path.join(os.homedir(), ".better-auth");
29
30
  export const TOKEN_FILE = path.join(CONFIG_DIR, "token.json");
31
+ export const CLIENT_ID_FILE = path.join(CONFIG_DIR, "client-id.txt");
30
32
 
31
33
  export async function loginAction(opts) {
32
34
  const options = z.object({
@@ -35,9 +37,50 @@ export async function loginAction(opts) {
35
37
  });
36
38
 
37
39
  const serverUrl = options.serverUrl || URL;
38
- const clientId = options.clientId || CLIENT_ID;
40
+ let clientId = options.clientId;
39
41
 
40
- intro(chalk.bold("šŸ” Auth CLI Login"));
42
+ // If not provided as an option, try to get from stored local config
43
+ if (!clientId) {
44
+ clientId = await getStoredClientId();
45
+ }
46
+
47
+ // If still no client ID, prompt the user to enter it
48
+ if (!clientId) {
49
+ intro(chalk.bold("šŸ” Auth CLI Login"));
50
+ console.log(
51
+ chalk.cyan(
52
+ "\nšŸ“‹ GitHub Client ID not found. Please enter it to proceed.\n",
53
+ ),
54
+ );
55
+
56
+ clientId = await text({
57
+ message: "Enter your GitHub Client ID:",
58
+ placeholder: "e.g., Ov23liXXXXXXXXXXXXX",
59
+ validate: (value) => {
60
+ if (!value || value.trim().length === 0) {
61
+ return "Client ID cannot be empty";
62
+ }
63
+ return undefined;
64
+ },
65
+ });
66
+
67
+ if (isCancel(clientId)) {
68
+ cancel("Login cancelled.");
69
+ process.exit(0);
70
+ }
71
+
72
+ // Store the client ID for future use
73
+ const stored = await storeClientId(clientId);
74
+ if (stored) {
75
+ console.log(
76
+ chalk.green(
77
+ `āœ“ Client ID saved locally at: ${chalk.gray(CLIENT_ID_FILE)}`,
78
+ ),
79
+ );
80
+ }
81
+ } else {
82
+ intro(chalk.bold("šŸ” Auth CLI Login"));
83
+ }
41
84
 
42
85
  // TODO: CHANGE THIS WITH TOKEN MANAGEMENT UTILS
43
86
  const existingToken = await getStoredToken();
@@ -230,9 +273,9 @@ export async function logoutAction() {
230
273
  process.exit(0);
231
274
  }
232
275
 
233
- const cleared = await clearStoredToken();
276
+ const clearedToken = await clearStoredToken();
234
277
 
235
- if (cleared) {
278
+ if (clearedToken) {
236
279
  outro(chalk.green("Successfully logged out!"));
237
280
  } else {
238
281
  console.log(
@@ -262,6 +305,44 @@ export async function whoamiAction(opts) {
262
305
  }
263
306
  }
264
307
 
308
+ export async function updateClientIdAction() {
309
+ intro(chalk.bold("šŸ”„ Update GitHub Client ID"));
310
+
311
+ const currentClientId = await getStoredClientId();
312
+
313
+ if (currentClientId) {
314
+ console.log(
315
+ chalk.gray(
316
+ `\nCurrent Client ID: ${currentClientId.slice(0, 10)}...${currentClientId.slice(-5)}\n`,
317
+ ),
318
+ );
319
+ }
320
+
321
+ const newClientId = await text({
322
+ message: "Enter your new GitHub Client ID:",
323
+ placeholder: "e.g., Ov23liXXXXXXXXXXXXX",
324
+ validate: (value) => {
325
+ if (!value || value.trim().length === 0) {
326
+ return "Client ID cannot be empty";
327
+ }
328
+ return undefined;
329
+ },
330
+ });
331
+
332
+ if (isCancel(newClientId)) {
333
+ cancel("Update cancelled.");
334
+ process.exit(0);
335
+ }
336
+
337
+ const stored = await storeClientId(newClientId);
338
+ if (stored) {
339
+ outro(chalk.green(`āœ“ GitHub Client ID updated and saved locally!\n`));
340
+ } else {
341
+ console.log(chalk.red("Failed to update Client ID."));
342
+ process.exit(1);
343
+ }
344
+ }
345
+
265
346
  export const login = new Command("login")
266
347
  .description("Login to your account")
267
348
  .option("--server-url <url>", "URL of the authentication server")
@@ -276,3 +357,7 @@ export const whoami = new Command("whoami")
276
357
  .description("Display information about the current user")
277
358
  .option("--server-url <url>", "URL of the authentication server")
278
359
  .action(whoamiAction);
360
+
361
+ export const updateClientId = new Command("update-client-id")
362
+ .description("Update your GitHub Client ID")
363
+ .action(updateClientIdAction);
package/src/cli/main.js CHANGED
@@ -1,10 +1,10 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  // import dotenv from "dotenv";
4
4
  import chalk from "chalk";
5
5
  import figlet from "figlet";
6
6
  import { Command } from "commander";
7
- import { login, logout, whoami } from "./commands/auth/login.js";
7
+ import { login, logout, whoami, updateClientId } from "./commands/auth/login.js";
8
8
  import { wakeUp } from "./commands/ai/wakeUp.js";
9
9
 
10
10
  // dotenv.config();
@@ -30,6 +30,7 @@ async function main() {
30
30
  .addCommand(login)
31
31
  .addCommand(logout)
32
32
  .addCommand(whoami)
33
+ .addCommand(updateClientId)
33
34
  .addCommand(wakeUp);
34
35
 
35
36
  program.action(() => {
package/src/lib/token.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import chalk from "chalk";
2
2
  import fs from "node:fs/promises";
3
- import { CONFIG_DIR, TOKEN_FILE } from "../cli/commands/auth/login.js";
3
+ import {
4
+ CONFIG_DIR,
5
+ TOKEN_FILE,
6
+ CLIENT_ID_FILE,
7
+ } from "../cli/commands/auth/login.js";
4
8
 
5
9
  export async function getStoredToken() {
6
10
  try {
@@ -83,3 +87,50 @@ export async function requireAuth() {
83
87
 
84
88
  return token;
85
89
  }
90
+
91
+ /**
92
+ * Get stored GitHub Client ID from local machine
93
+ * @returns {Promise<string|null>} The stored client ID or null if not found
94
+ */
95
+ export async function getStoredClientId() {
96
+ try {
97
+ const data = await fs.readFile(CLIENT_ID_FILE, "utf-8");
98
+ return data.trim();
99
+ } catch (error) {
100
+ // File doesn't exist or can't be read
101
+ return null;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Store GitHub Client ID locally
107
+ * @param {string} clientId - The GitHub client ID to store
108
+ * @returns {Promise<boolean>} True if stored successfully
109
+ */
110
+ export async function storeClientId(clientId) {
111
+ try {
112
+ // Ensure the config directory exists
113
+ await fs.mkdir(CONFIG_DIR, { recursive: true });
114
+
115
+ // Store client ID as plain text
116
+ await fs.writeFile(CLIENT_ID_FILE, clientId, "utf-8");
117
+ return true;
118
+ } catch (error) {
119
+ console.error(chalk.red("Failed to store client ID: "), error?.message);
120
+ return false;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Clear stored GitHub Client ID
126
+ * @returns {Promise<boolean>} True if cleared successfully
127
+ */
128
+ export async function clearStoredClientId() {
129
+ try {
130
+ await fs.unlink(CLIENT_ID_FILE);
131
+ return true;
132
+ } catch (error) {
133
+ // File doesn't exist or can't be deleted
134
+ return false;
135
+ }
136
+ }