@agentlink.sh/cli 0.12.0 → 0.12.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.
@@ -181,7 +181,7 @@ async function ensureAccessToken(nonInteractive, projectDir) {
181
181
  }
182
182
  if (creds.oauth.refresh_token) {
183
183
  try {
184
- const { refreshOAuthToken } = await import("./oauth-VTSNCG7U.js");
184
+ const { refreshOAuthToken } = await import("./oauth-BGBLVE52.js");
185
185
  const tokens = await refreshOAuthToken(creds.oauth.refresh_token);
186
186
  const updated = {
187
187
  ...creds,
@@ -230,7 +230,7 @@ async function ensureAccessToken(nonInteractive, projectDir) {
230
230
  ]
231
231
  });
232
232
  if (method === "oauth") {
233
- const { oauthLogin } = await import("./oauth-VTSNCG7U.js");
233
+ const { oauthLogin } = await import("./oauth-BGBLVE52.js");
234
234
  const tokens = await oauthLogin();
235
235
  process.env.SUPABASE_ACCESS_TOKEN = tokens.access_token;
236
236
  saveCredentials({
@@ -22,7 +22,7 @@ import {
22
22
  updateAuthConfig,
23
23
  updatePostgrestConfig,
24
24
  waitForProjectReady
25
- } from "./chunk-4EUOAXWZ.js";
25
+ } from "./chunk-3TPH54EQ.js";
26
26
  import "./chunk-G3HVUCWY.js";
27
27
  export {
28
28
  createProject,
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  updatePostgrestConfig,
28
28
  validateProjectName,
29
29
  waitForProjectReady
30
- } from "./chunk-4EUOAXWZ.js";
30
+ } from "./chunk-3TPH54EQ.js";
31
31
  import {
32
32
  SKILLS_VERSION,
33
33
  SUPPORTED_SUPABASE_CLI,
@@ -2500,7 +2500,7 @@ async function connectExistingProject() {
2500
2500
  };
2501
2501
  }
2502
2502
  async function createNewProject(envName, opts) {
2503
- const { listOrganizations: listOrganizations2, listRegions: listRegions2 } = await import("./cloud-QNZQNIS5.js");
2503
+ const { listOrganizations: listOrganizations2, listRegions: listRegions2 } = await import("./cloud-G7CIHVYT.js");
2504
2504
  const orgs = await listOrganizations2();
2505
2505
  if (orgs.length === 0) {
2506
2506
  throw new Error("No Supabase organizations found. Create one at https://supabase.com/dashboard.");
@@ -5075,7 +5075,7 @@ ${red("Error:")} No organizations found. Create one at ${link("https://supabase.
5075
5075
  const match = regions.find((r) => r.id === detected);
5076
5076
  region = match?.id ?? "us-east-1";
5077
5077
  const label2 = match?.name ?? "US East (N. Virginia)";
5078
- console.log(`${blue("\u2714")} ${bold("Region")} ${amber(label2)}`);
5078
+ console.log(`${blue("\u2714")} ${bold("Closest region")} ${amber(label2)}`);
5079
5079
  }
5080
5080
  const label = "dev";
5081
5081
  cloudConfig = { orgId, region, label };
@@ -5217,8 +5217,8 @@ program.command("info [name]").description("Show documentation about AgentLink c
5217
5217
  });
5218
5218
  program.command("login").description("Authenticate with Supabase via OAuth (opens browser)").action(async () => {
5219
5219
  try {
5220
- const { oauthLogin } = await import("./oauth-VTSNCG7U.js");
5221
- const { saveCredentials: saveCredentials2, loadCredentials: loadCredentials2, credentialsPath: credentialsPath2 } = await import("./cloud-QNZQNIS5.js");
5220
+ const { oauthLogin } = await import("./oauth-BGBLVE52.js");
5221
+ const { saveCredentials: saveCredentials2, loadCredentials: loadCredentials2, credentialsPath: credentialsPath2 } = await import("./cloud-G7CIHVYT.js");
5222
5222
  console.log();
5223
5223
  const tokens = await oauthLogin();
5224
5224
  saveCredentials2({
@@ -98,63 +98,71 @@ function openBrowser(url) {
98
98
  console.log(` ${dim(url)}`);
99
99
  }
100
100
  }
101
- function waitForCallback(port, state, timeoutMs) {
102
- let server;
103
- let timer;
104
- const promise = new Promise((resolve) => {
105
- timer = setTimeout(() => {
106
- server?.close();
107
- resolve(null);
108
- }, timeoutMs);
109
- server = createServer((req, res) => {
110
- const url = new URL(req.url, `http://localhost:${port}`);
111
- if (url.pathname !== "/callback") {
112
- res.writeHead(404);
113
- res.end();
114
- return;
115
- }
116
- const error = url.searchParams.get("error");
117
- if (error) {
118
- const desc = url.searchParams.get("error_description") ?? error;
119
- res.writeHead(400, { "Content-Type": "text/html" });
120
- res.end(ERROR_HTML(desc));
121
- clearTimeout(timer);
122
- server.close();
123
- console.log(` ${amber("\u25B2")} OAuth error: ${desc}`);
124
- resolve(null);
125
- return;
126
- }
127
- const returnedState = url.searchParams.get("state");
128
- if (returnedState !== state) {
129
- res.writeHead(400, { "Content-Type": "text/html" });
130
- res.end(ERROR_HTML("State mismatch \u2014 possible CSRF attack."));
131
- clearTimeout(timer);
132
- server.close();
133
- resolve(null);
134
- return;
135
- }
136
- const authCode = url.searchParams.get("code");
137
- if (!authCode) {
138
- res.writeHead(400, { "Content-Type": "text/html" });
139
- res.end(ERROR_HTML("No authorization code received."));
140
- clearTimeout(timer);
141
- server.close();
142
- resolve(null);
143
- return;
144
- }
145
- res.writeHead(200, { "Content-Type": "text/html" });
146
- res.end(SUCCESS_HTML);
147
- clearTimeout(timer);
148
- server.close();
149
- resolve(authCode);
150
- });
151
- server.listen(port, "127.0.0.1");
101
+ function createCallbackServer(port, state) {
102
+ let codeResolve = null;
103
+ let receivedCode = null;
104
+ let done = false;
105
+ const server = createServer((req, res) => {
106
+ const url = new URL(req.url, `http://localhost:${port}`);
107
+ if (url.pathname !== "/callback") {
108
+ res.writeHead(404);
109
+ res.end();
110
+ return;
111
+ }
112
+ const error = url.searchParams.get("error");
113
+ if (error) {
114
+ const desc = url.searchParams.get("error_description") ?? error;
115
+ res.writeHead(400, { "Content-Type": "text/html" });
116
+ res.end(ERROR_HTML(desc));
117
+ console.log(` ${amber("\u25B2")} OAuth error: ${desc}`);
118
+ done = true;
119
+ codeResolve?.(null);
120
+ return;
121
+ }
122
+ const returnedState = url.searchParams.get("state");
123
+ if (returnedState !== state) {
124
+ res.writeHead(400, { "Content-Type": "text/html" });
125
+ res.end(ERROR_HTML("State mismatch \u2014 possible CSRF attack."));
126
+ done = true;
127
+ codeResolve?.(null);
128
+ return;
129
+ }
130
+ const authCode = url.searchParams.get("code");
131
+ if (!authCode) {
132
+ res.writeHead(400, { "Content-Type": "text/html" });
133
+ res.end(ERROR_HTML("No authorization code received."));
134
+ done = true;
135
+ codeResolve?.(null);
136
+ return;
137
+ }
138
+ res.writeHead(200, { "Content-Type": "text/html" });
139
+ res.end(SUCCESS_HTML);
140
+ receivedCode = authCode;
141
+ done = true;
142
+ codeResolve?.(authCode);
152
143
  });
144
+ server.listen(port, "127.0.0.1");
153
145
  return {
154
- promise,
155
- cleanup: () => {
156
- clearTimeout(timer);
157
- server?.close();
146
+ /** Wait up to `ms` for the callback. Returns code or null on timeout. Server stays alive. */
147
+ waitForCode(ms) {
148
+ if (receivedCode) return Promise.resolve(receivedCode);
149
+ if (done) return Promise.resolve(null);
150
+ return new Promise((resolve) => {
151
+ codeResolve = resolve;
152
+ const timer = setTimeout(() => {
153
+ codeResolve = null;
154
+ resolve(null);
155
+ }, ms);
156
+ const origResolve = resolve;
157
+ codeResolve = (code) => {
158
+ clearTimeout(timer);
159
+ codeResolve = null;
160
+ origResolve(code);
161
+ };
162
+ });
163
+ },
164
+ close() {
165
+ server.close();
158
166
  }
159
167
  };
160
168
  }
@@ -176,33 +184,40 @@ async function oauthLogin() {
176
184
  openBrowser(authorizeUrl.toString());
177
185
  console.log(` ${dim("Waiting for authorization...")}`);
178
186
  console.log();
179
- let code = null;
180
- const first = waitForCallback(port, state, CHECK_IN_MS);
181
- code = await first.promise;
182
- if (code) {
183
- return exchangeCode(code, redirectUri, codeVerifier);
184
- }
185
- while (true) {
186
- const action = await select({
187
- message: "No response yet. What would you like to do?",
188
- theme,
189
- choices: [
190
- { name: "Keep waiting (30s more)", value: "wait" },
191
- { name: "Retry (open browser again)", value: "retry" },
192
- { name: "Cancel", value: "cancel" }
193
- ]
194
- });
195
- if (action === "cancel") {
196
- throw new Error("OAuth login cancelled.");
197
- }
198
- if (action === "retry") {
199
- break;
200
- }
201
- const next = waitForCallback(port, state, CHECK_IN_MS);
202
- code = await next.promise;
187
+ const callback = createCallbackServer(port, state);
188
+ try {
189
+ let code = await callback.waitForCode(CHECK_IN_MS);
203
190
  if (code) {
191
+ callback.close();
204
192
  return exchangeCode(code, redirectUri, codeVerifier);
205
193
  }
194
+ while (true) {
195
+ const action = await select({
196
+ message: "No response yet. What would you like to do?",
197
+ theme,
198
+ choices: [
199
+ { name: "Keep waiting", value: "wait" },
200
+ { name: "Retry (open browser again)", value: "retry" },
201
+ { name: "Cancel", value: "cancel" }
202
+ ]
203
+ });
204
+ if (action === "cancel") {
205
+ callback.close();
206
+ throw new Error("OAuth login cancelled.");
207
+ }
208
+ if (action === "retry") {
209
+ callback.close();
210
+ break;
211
+ }
212
+ code = await callback.waitForCode(CHECK_IN_MS);
213
+ if (code) {
214
+ callback.close();
215
+ return exchangeCode(code, redirectUri, codeVerifier);
216
+ }
217
+ }
218
+ } catch (err) {
219
+ callback.close();
220
+ throw err;
206
221
  }
207
222
  }
208
223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentlink.sh/cli",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "CLI for scaffolding Supabase apps with AI agents",
5
5
  "bin": {
6
6
  "agentlink": "dist/index.js"