@overscore/cli 0.11.2 → 0.11.4

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.
Files changed (2) hide show
  1. package/dist/index.js +71 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ async function loadEnv() {
74
74
  process.exit(0);
75
75
  }
76
76
  async function apiRequest(method, urlPath, body, command) {
77
- const { apiUrl, apiKey } = await loadEnv();
77
+ const { apiUrl, apiKey, projectSlug } = await loadEnv();
78
78
  const baseUrl = apiUrl.replace(/\/api$/, "");
79
79
  const url = `${baseUrl}${urlPath}`;
80
80
  const headers = {
@@ -92,6 +92,23 @@ async function apiRequest(method, urlPath, body, command) {
92
92
  body: body !== undefined ? JSON.stringify(body) : undefined,
93
93
  });
94
94
  const data = await res.json();
95
+ if (res.status === 401 && projectSlug) {
96
+ console.log("\n API key expired. Refreshing...\n");
97
+ const newKey = await refreshApiKey(projectSlug);
98
+ if (newKey) {
99
+ const retryRes = await fetch(url, {
100
+ method,
101
+ headers: { ...headers, Authorization: `Bearer ${newKey}` },
102
+ body: body !== undefined ? JSON.stringify(body) : undefined,
103
+ });
104
+ const retryData = await retryRes.json();
105
+ if (!retryRes.ok) {
106
+ console.error(`\n Error: ${retryData.error || `HTTP ${retryRes.status}`}\n`);
107
+ process.exit(1);
108
+ }
109
+ return retryData;
110
+ }
111
+ }
95
112
  if (!res.ok) {
96
113
  console.error(`\n Error: ${data.error || `HTTP ${res.status}`}\n`);
97
114
  process.exit(1);
@@ -116,6 +133,58 @@ function prompt(message) {
116
133
  });
117
134
  });
118
135
  }
136
+ async function refreshApiKey(projectSlug) {
137
+ const configDir = path.join(process.env.HOME || "", ".overscore");
138
+ const configPath = path.join(configDir, "config");
139
+ let cfg = fs.existsSync(configPath)
140
+ ? parseEnv(fs.readFileSync(configPath, "utf-8"))
141
+ : {};
142
+ let deviceToken = cfg.OVERSCORE_DEVICE_TOKEN;
143
+ if (!deviceToken) {
144
+ console.log("\n No session found. Launching browser login...\n");
145
+ await authLogin();
146
+ cfg = parseEnv(fs.readFileSync(configPath, "utf-8"));
147
+ deviceToken = cfg.OVERSCORE_DEVICE_TOKEN;
148
+ if (!deviceToken)
149
+ return null;
150
+ }
151
+ for (let attempt = 0; attempt < 2; attempt++) {
152
+ const keyRes = await fetch(`${HUB_URL}/api/projects/${projectSlug}/api-keys`, {
153
+ method: "POST",
154
+ headers: { Authorization: `Bearer ${deviceToken}`, "Content-Type": "application/json" },
155
+ body: JSON.stringify({ name: `cli-${Date.now()}` }),
156
+ });
157
+ if (keyRes.ok) {
158
+ const data = (await keyRes.json());
159
+ const newKey = data.raw_key;
160
+ if (!newKey)
161
+ return null;
162
+ // Update local .env if present
163
+ const envPath = path.resolve(process.cwd(), ".env");
164
+ if (fs.existsSync(envPath)) {
165
+ const envContent = fs.readFileSync(envPath, "utf-8");
166
+ fs.writeFileSync(envPath, envContent.replace(/^VITE_OVERSCORE_API_KEY=.*/m, `VITE_OVERSCORE_API_KEY=${newKey}`));
167
+ }
168
+ // Update global config
169
+ cfg.OVERSCORE_API_KEY = newKey;
170
+ fs.mkdirSync(configDir, { recursive: true });
171
+ fs.writeFileSync(configPath, Object.entries(cfg).map(([k, v]) => `${k}=${v}`).join("\n") + "\n", { mode: 0o600 });
172
+ console.log(" API key refreshed.\n");
173
+ return newKey;
174
+ }
175
+ if ((keyRes.status === 401 || keyRes.status === 403) && attempt === 0) {
176
+ console.log("\n Session expired. Launching browser login...\n");
177
+ await authLogin();
178
+ cfg = parseEnv(fs.readFileSync(configPath, "utf-8"));
179
+ deviceToken = cfg.OVERSCORE_DEVICE_TOKEN;
180
+ if (!deviceToken)
181
+ return null;
182
+ continue;
183
+ }
184
+ return null;
185
+ }
186
+ return null;
187
+ }
119
188
  const SOURCE_EXCLUDE = new Set([
120
189
  "node_modules",
121
190
  "dist",
@@ -2001,7 +2070,7 @@ async function authLogin() {
2001
2070
  resolveCallback({ token, project });
2002
2071
  });
2003
2072
  server.listen(chosenPort, "127.0.0.1");
2004
- const loginUrl = `${HUB_URL}/login?next=${encodeURIComponent(`/api/cli/auth/finalize?port=${chosenPort}&state=${state}`)}&mode=signin`;
2073
+ const loginUrl = `${HUB_URL}/login?next=${encodeURIComponent(`/api/cli/auth/finalize?port=${chosenPort}&state=${state}`)}&mode=signin&switch=1`;
2005
2074
  console.log(`\n Opening browser to authenticate...`);
2006
2075
  console.log(`\n If your browser doesn't open automatically, visit:\n ${loginUrl}\n`);
2007
2076
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overscore/cli",
3
- "version": "0.11.2",
3
+ "version": "0.11.4",
4
4
  "description": "CLI for deploying Overscore dashboards and publishing analyses",
5
5
  "bin": {
6
6
  "overscore": "dist/index.js"