ctxindex 0.1.1 → 0.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.
Files changed (2) hide show
  1. package/dist/ctxindex.mjs +105 -35
  2. package/package.json +1 -1
package/dist/ctxindex.mjs CHANGED
@@ -39006,6 +39006,40 @@ async function launchOAuthBrowser(url2) {
39006
39006
  if (await processHandle.exited !== 0)
39007
39007
  throw new Error("browser launcher failed");
39008
39008
  }
39009
+ function callbackResult(value, redirectUri, state) {
39010
+ const pasted = value.trim();
39011
+ if (pasted.length === 0 || pasted.length > 16384)
39012
+ throw new CtxindexAuthError("missing_code", "OAuth authorization failed: missing_code");
39013
+ if (!/^https?:\/\//i.test(pasted)) {
39014
+ if (/\s/.test(pasted))
39015
+ throw new CtxindexAuthError("missing_code", "OAuth authorization failed: missing_code");
39016
+ return pasted;
39017
+ }
39018
+ let callback;
39019
+ try {
39020
+ callback = new URL(pasted);
39021
+ } catch {
39022
+ throw new CtxindexAuthError("oauth_failed", "OAuth authorization failed: invalid_callback");
39023
+ }
39024
+ const expected = new URL(redirectUri);
39025
+ if (callback.origin !== expected.origin || callback.pathname !== callbackPath || callback.username !== "" || callback.password !== "" || callback.hash !== "")
39026
+ throw new CtxindexAuthError("oauth_failed", "OAuth authorization failed: invalid_callback");
39027
+ if (callback.searchParams.getAll("state").length !== 1 || callback.searchParams.get("state") !== state)
39028
+ throw new CtxindexAuthError("state_mismatch", "OAuth authorization failed: state_mismatch");
39029
+ const providerError = callback.searchParams.get("error");
39030
+ if (providerError === "access_denied")
39031
+ throw new CtxindexAuthError("authorization_denied", "OAuth authorization failed: authorization_denied");
39032
+ if (providerError) {
39033
+ const safeError = /^[A-Za-z0-9._-]{1,64}$/.test(providerError) ? providerError : "unknown_error";
39034
+ const providerCode = callback.searchParams.get("error_description")?.match(/\b[A-Z]{2,12}\d{3,10}\b/)?.[0];
39035
+ const diagnostic = providerCode ? `${safeError} (${providerCode})` : safeError;
39036
+ throw new CtxindexAuthError("oauth_failed", `OAuth authorization failed: ${diagnostic}`);
39037
+ }
39038
+ const codes = callback.searchParams.getAll("code");
39039
+ if (codes.length !== 1 || !codes[0])
39040
+ throw new CtxindexAuthError("missing_code", "OAuth authorization failed: missing_code");
39041
+ return codes[0];
39042
+ }
39009
39043
  async function openOAuthLoopback(input) {
39010
39044
  const state = randomToken();
39011
39045
  const codeVerifier = randomToken();
@@ -39025,17 +39059,20 @@ async function openOAuthLoopback(input) {
39025
39059
  const authorizationUrl = authorization.toString();
39026
39060
  let timer;
39027
39061
  let settled = false;
39062
+ const manualInput = new AbortController;
39063
+ let finishCallback = () => {};
39028
39064
  const callback = new Promise((resolve, reject) => {
39029
- const finish = (error51, code) => {
39065
+ finishCallback = (error51, code) => {
39030
39066
  if (settled)
39031
39067
  return;
39032
39068
  settled = true;
39069
+ manualInput.abort();
39033
39070
  if (error51)
39034
39071
  reject(error51);
39035
39072
  else
39036
39073
  resolve(code ?? "");
39037
39074
  };
39038
- timer = setTimeout(() => finish(new CtxindexAuthError("loopback_timeout", "OAuth authorization failed: loopback_timeout (callback timed out)")), input.timeoutMs ?? defaultTimeoutMs);
39075
+ timer = setTimeout(() => finishCallback(new CtxindexAuthError("loopback_timeout", "OAuth authorization failed: loopback_timeout (callback timed out)")), input.timeoutMs ?? defaultTimeoutMs);
39039
39076
  server.on("request", (request, response) => {
39040
39077
  const url2 = new URL(request.url ?? "/", redirectUri);
39041
39078
  if (url2.pathname !== callbackPath) {
@@ -39043,38 +39080,16 @@ async function openOAuthLoopback(input) {
39043
39080
  response.end("not found");
39044
39081
  return;
39045
39082
  }
39046
- if (url2.searchParams.get("state") !== state) {
39047
- response.writeHead(400, { "content-type": "text/plain" });
39048
- response.end("state mismatch");
39049
- finish(new CtxindexAuthError("state_mismatch", "OAuth authorization failed: state_mismatch"));
39050
- return;
39051
- }
39052
- const providerError = url2.searchParams.get("error");
39053
- if (providerError === "access_denied") {
39054
- response.writeHead(400, { "content-type": "text/plain" });
39055
- response.end("authorization denied");
39056
- finish(new CtxindexAuthError("authorization_denied", "OAuth authorization failed: authorization_denied"));
39057
- return;
39058
- }
39059
- if (providerError) {
39060
- const safeError = /^[A-Za-z0-9._-]{1,64}$/.test(providerError) ? providerError : "unknown_error";
39061
- const providerCode = url2.searchParams.get("error_description")?.match(/\b[A-Z]{2,12}\d{3,10}\b/)?.[0];
39062
- const diagnostic = providerCode ? `${safeError} (${providerCode})` : safeError;
39083
+ try {
39084
+ const code = callbackResult(url2.toString(), redirectUri, state);
39085
+ response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
39086
+ response.end("<!doctype html><title>ctxindex authorization complete</title><p>You can close this window.</p>");
39087
+ finishCallback(null, code);
39088
+ } catch (error51) {
39063
39089
  response.writeHead(400, { "content-type": "text/plain" });
39064
- response.end(`authorization failed: ${diagnostic}`);
39065
- finish(new CtxindexAuthError("oauth_failed", `OAuth authorization failed: ${diagnostic}`));
39066
- return;
39090
+ response.end("authorization failed");
39091
+ finishCallback(error51 instanceof CtxindexAuthError ? error51 : new CtxindexAuthError("oauth_failed", "OAuth authorization failed: invalid_callback"));
39067
39092
  }
39068
- const code = url2.searchParams.get("code");
39069
- if (!code) {
39070
- response.writeHead(400, { "content-type": "text/plain" });
39071
- response.end("missing code");
39072
- finish(new CtxindexAuthError("missing_code", "OAuth authorization failed: missing_code"));
39073
- return;
39074
- }
39075
- response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
39076
- response.end("<!doctype html><title>ctxindex authorization complete</title><p>You can close this window.</p>");
39077
- finish(null, code);
39078
39093
  });
39079
39094
  });
39080
39095
  try {
@@ -39087,6 +39102,24 @@ async function openOAuthLoopback(input) {
39087
39102
  input.emitAuthorizationUrl?.(authorizationUrl);
39088
39103
  }
39089
39104
  }
39105
+ if (input.readAuthorizationResponse) {
39106
+ input.readAuthorizationResponse({
39107
+ authorizationUrl,
39108
+ redirectUri,
39109
+ signal: manualInput.signal
39110
+ }).then((value) => {
39111
+ if (value === undefined || settled)
39112
+ return;
39113
+ try {
39114
+ finishCallback(null, callbackResult(value, redirectUri, state));
39115
+ } catch (error51) {
39116
+ finishCallback(error51 instanceof CtxindexAuthError ? error51 : new CtxindexAuthError("oauth_failed", "OAuth authorization failed: invalid_callback"));
39117
+ }
39118
+ }).catch((error51) => {
39119
+ if (!manualInput.signal.aborted)
39120
+ finishCallback(error51 instanceof CtxindexAuthError ? error51 : new CtxindexAuthError("oauth_failed", "OAuth authorization failed: manual_input"));
39121
+ });
39122
+ }
39090
39123
  const code = await callback;
39091
39124
  return { code, codeVerifier, redirectUri, authorizationUrl };
39092
39125
  } finally {
@@ -39374,7 +39407,8 @@ async function authorizeProvider(input, deps) {
39374
39407
  ...Number.isFinite(timeoutSeconds) && timeoutSeconds >= 0 ? { timeoutMs: timeoutSeconds * 1000 } : {},
39375
39408
  noBrowser: readEnvironment("CTXINDEX_NO_BROWSER") === "1",
39376
39409
  ...deps.launchBrowser ? { launchBrowser: deps.launchBrowser } : {},
39377
- ...deps.emitAuthorizationUrl ? { emitAuthorizationUrl: deps.emitAuthorizationUrl } : {}
39410
+ ...deps.emitAuthorizationUrl ? { emitAuthorizationUrl: deps.emitAuthorizationUrl } : {},
39411
+ ...deps.readAuthorizationResponse ? { readAuthorizationResponse: deps.readAuthorizationResponse } : {}
39378
39412
  });
39379
39413
  token = await postOAuthToken({
39380
39414
  provider,
@@ -80861,6 +80895,41 @@ async function runWithExit(handler4) {
80861
80895
  }
80862
80896
  }
80863
80897
 
80898
+ // src/account/read-hidden-oauth-response.ts
80899
+ import { createInterface } from "readline";
80900
+ var prompt = "Paste the redirect URL or authorization code here: ";
80901
+ function readHiddenOAuthResponse(input) {
80902
+ const stdin = process.stdin;
80903
+ const stdout = process.stdout;
80904
+ return new Promise((resolve9) => {
80905
+ let finished = false;
80906
+ const wasRaw = stdin.isRaw;
80907
+ const interactive = stdin.isTTY && typeof stdin.setRawMode === "function";
80908
+ const lines = createInterface({ input: stdin, terminal: false });
80909
+ const finish = (value2) => {
80910
+ if (finished)
80911
+ return;
80912
+ finished = true;
80913
+ input.signal.removeEventListener("abort", onAbort);
80914
+ lines.close();
80915
+ if (interactive)
80916
+ stdin.setRawMode(Boolean(wasRaw));
80917
+ stdout.write(`
80918
+ `);
80919
+ resolve9(value2);
80920
+ };
80921
+ const onAbort = () => finish();
80922
+ input.signal.addEventListener("abort", onAbort, { once: true });
80923
+ if (input.signal.aborted)
80924
+ return finish();
80925
+ stdout.write(prompt);
80926
+ if (interactive)
80927
+ stdin.setRawMode(true);
80928
+ lines.once("line", (line) => finish(line));
80929
+ lines.once("close", () => finish());
80930
+ });
80931
+ }
80932
+
80864
80933
  // src/account/handle-account-command.ts
80865
80934
  var accountCommandRuntime = {
80866
80935
  assertInitialized,
@@ -80946,7 +81015,8 @@ async function handleAccountCommand(parsed, runtime = accountCommandRuntime) {
80946
81015
  }
80947
81016
  return app;
80948
81017
  },
80949
- emitAuthorizationUrl: (url2) => console.log(`Open this URL: ${url2}`)
81018
+ emitAuthorizationUrl: (url2) => console.log(`Open this URL: ${url2}`),
81019
+ readAuthorizationResponse: readHiddenOAuthResponse
80950
81020
  });
80951
81021
  console.log(formatAccountAdded(result));
80952
81022
  }
@@ -85459,7 +85529,7 @@ var daemonCommand = defineCtxCommand({
85459
85529
 
85460
85530
  // src/main.ts
85461
85531
  var LOG_LEVELS = ["trace", "debug", "info", "warn", "error", "fatal"];
85462
- var cliVersion = "0.1.1";
85532
+ var cliVersion = "0.1.2";
85463
85533
  function captureProcessExit() {
85464
85534
  const originalExit = process.exit;
85465
85535
  process.exit = (code) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctxindex",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Local personal-context gateway CLI for agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://ctxindex.com",