@exposify/cli 0.0.2 → 0.1.0

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @exposify/cli
2
2
 
3
- The framework-neutral engine behind `exposify-express` and `exposify-next`:
3
+ The framework-neutral engine behind `@exposify/express` and `@exposify/next`:
4
4
  the endpoint checklist, the startup-log question, config + clipboard + verify,
5
5
  tool descriptions (`describe`), and `inspect` snapshots. You don't use it
6
6
  directly: install an adapter (`@exposify/express`, `@exposify/nestjs`,
package/dist/index.d.ts CHANGED
@@ -132,6 +132,22 @@ interface ScanResult {
132
132
  fields: string[];
133
133
  others?: string[];
134
134
  };
135
+ /**
136
+ * Supabase Auth with `@supabase/ssr` (Next.js): which sign-ins Connect
137
+ * makes on Supabase directly, and where the app signs in (plan
138
+ * `2026-10-24-supabase-connect.md` Part 2).
139
+ */
140
+ supabase?: {
141
+ direct: Array<"password" | "email-code" | "social">;
142
+ /** The sign-in calls found, one line each; empty: none found. */
143
+ found: string[];
144
+ /** Server sign-ins the form can't run. */
145
+ unusable?: string[];
146
+ /** Routes that finish a sign-in; Connect's sign-ins skip them. */
147
+ callbacks?: string[];
148
+ /** `@supabase/auth-helpers-nextjs`: an older cookie format, not supported. */
149
+ authHelpers?: boolean;
150
+ };
135
151
  }
136
152
  interface ScanFailure {
137
153
  ok: false;
@@ -278,7 +294,7 @@ interface ConfigStepInput<R extends ScanResult = ScanResult> {
278
294
  readLine: (site: CallSite) => string | undefined;
279
295
  }
280
296
  interface CliAdapter<R extends ScanResult = ScanResult> {
281
- /** The command name, e.g. "exposify-express". */
297
+ /** The command as users type it in hints, e.g. "npx @exposify/next". */
282
298
  bin: string;
283
299
  /** An example for "pass it explicitly", e.g. "src/server.ts". */
284
300
  entryExample: string;
package/dist/index.js CHANGED
@@ -1561,7 +1561,38 @@ function inspect(result, cwd) {
1561
1561
  if (result.actions && result.actions.length > 0) inspectActions(result, cwd);
1562
1562
  inspectLogin(result);
1563
1563
  }
1564
+ function supabaseSignIn(s, login) {
1565
+ if (s.authHelpers) return { row: "none: @supabase/auth-helpers-nextjs isn't supported", why: ["It keeps the session in an older cookie format. Move to @supabase/ssr, Supabase's replacement for it."] };
1566
+ const passwordDirect = s.direct.includes("password");
1567
+ const why = [];
1568
+ let row;
1569
+ if (s.found.length === 0) {
1570
+ row = "your Supabase Auth, directly";
1571
+ why.push("Couldn't find where your users sign in, so AI assistants sign in to Supabase directly: a password on /mcp/login, social and email codes on Exposify's page.");
1572
+ } else if (!passwordDirect && login) {
1573
+ row = `your app's own login for passwords (${login.what}); your Supabase Auth, directly, for social and email codes`;
1574
+ why.push('Your password sign-in runs on your server, which may hold your own checks, so the form runs it. Switch to "Sign in with Supabase" on the dashboard to skip it.');
1575
+ } else if (!passwordDirect) {
1576
+ row = "your Supabase Auth, directly, for social and email codes; no password sign-in";
1577
+ why.push(`Your app signs in on the server where the form can't run it: ${(s.unusable ?? []).join("; ")}.`);
1578
+ why.push('Switch on "Sign in with Supabase" on the dashboard to have passwords go to Supabase directly (it skips what that code checks).');
1579
+ } else {
1580
+ row = "your Supabase Auth, directly";
1581
+ why.push(`Your sign-in runs in the browser (${s.found[0]}), so there's no server check to skip.`);
1582
+ }
1583
+ if (s.callbacks?.length) why.push(`Connect's sign-ins don't go through ${s.callbacks.join(", ")}; anything those check is skipped.`);
1584
+ return { row, why };
1585
+ }
1564
1586
  function inspectLogin(result) {
1587
+ if (result.supabase) {
1588
+ const { row, why } = supabaseSignIn(result.supabase, result.login);
1589
+ console.log(`
1590
+ Sign-in for AI assistants: ${row}.`);
1591
+ for (const line of why) console.log(dim(` ${line}`));
1592
+ if (result.supabase.found.length > 1) for (const f of result.supabase.found) console.log(dim(` found ${f}`));
1593
+ if (result.supabase.direct.length && !result.supabase.authHelpers) console.log(dim(" Check it on a running app: npx @exposify/next test-sign-in"));
1594
+ return;
1595
+ }
1565
1596
  if (!result.login) return;
1566
1597
  console.log(`
1567
1598
  Sign-in for AI assistants: your app's own login, ${result.login.what} (${result.login.fields.join(", ")}).`);
@@ -1748,7 +1779,7 @@ ${bold("Step 2/5")} \xB7 Print "[agentready] MCP ready \u2026" when your server
1748
1779
  console.log(`
1749
1780
  ${green("\u2713 Already set up")}: your aiReady() config already matches. Nothing to change.`);
1750
1781
  if (tty && !args.quick) {
1751
- await signInStep(args, root, cwd, "Step 4/5", result.login);
1782
+ await signInStep(args, root, cwd, "Step 4/5", result.login, result.supabase);
1752
1783
  const code2 = await describeStep(args, toolRows(result.routes, result.actions), root, cwd, "Step 5/5");
1753
1784
  if (code2 !== 0) return code2;
1754
1785
  }
@@ -1834,7 +1865,7 @@ ${bold("Step 3/5")} \xB7 Your aiReady() config${copyNote}
1834
1865
  }
1835
1866
  const finalRoutes = verified ?? toolRows(routesAsSelected(registered, selected), actionRows.map((a) => ({ ...a, exposed: a.marker ? a.exposed : pickedActions.has(a.configKey) })));
1836
1867
  if (tty && !args.quick) {
1837
- await signInStep(args, root, cwd, "Step 4/5", result.login);
1868
+ await signInStep(args, root, cwd, "Step 4/5", result.login, result.supabase);
1838
1869
  const code2 = await describeStep(args, finalRoutes, root, cwd, "Step 5/5");
1839
1870
  if (code2 !== 0) return code2;
1840
1871
  const proposed = await proposeStep(args, verifiedActions, root, cwd);
@@ -1879,7 +1910,7 @@ ${bold("Optional")} \xB7 Save the tools agents get to ${shown}?`);
1879
1910
  }
1880
1911
  if (save) writeSnapshot(routes, file, cwd);
1881
1912
  }
1882
- async function signInStep(args, root, cwd, title, login) {
1913
+ async function signInStep(args, root, cwd, title, login, supabase) {
1883
1914
  if (!args.signIn) return;
1884
1915
  const stacks = detectAuthStacks(root);
1885
1916
  const oauth = stacks.find((s) => s.path === "oauth");
@@ -1892,13 +1923,17 @@ ${bold(title)} \xB7 How your users sign in`);
1892
1923
  console.log(dim(" The README's OAuth section lists the settings to turn on in the provider's dashboard."));
1893
1924
  return;
1894
1925
  }
1895
- const own = login ? `your app's own login, ${login.what} (${login.fields.join(", ")})` : null;
1896
- if (own) console.log(` Found ${own}. AI assistants sign in with it on a form your app serves at /mcp/login, so there's nothing to set up for it.`);
1926
+ const sb = supabase && !supabase.authHelpers ? supabaseSignIn(supabase, login) : null;
1927
+ const own = sb ? sb.row : login ? `your app's own login, ${login.what} (${login.fields.join(", ")})` : null;
1928
+ if (sb) {
1929
+ console.log(` AI assistants sign in with ${sb.row}. Nothing to set up for it.`);
1930
+ for (const line of sb.why) console.log(dim(` ${line}`));
1931
+ } else if (own) console.log(` Found ${own}. AI assistants sign in with it on a form your app serves at /mcp/login, so there's nothing to set up for it.`);
1897
1932
  const signedOut = "agents use your app signed out, and your own checks decide what they can do";
1898
1933
  const have = existingKey(root, process.env);
1899
1934
  if (have) {
1900
1935
  console.log(
1901
- green(` \u2713 ${KEY_ENV} is set (${have.from}):`) + (own ? " agents sign in with your app's login, through Exposify's broker." : ` until you add a sign-in method in the dashboard, ${signedOut}.`)
1936
+ green(` \u2713 ${KEY_ENV} is set (${have.from}):`) + (sb ? ` agents sign in with ${sb.row}, through Exposify's broker.` : own ? " agents sign in with your app's login, through Exposify's broker." : ` until you add a sign-in method in the dashboard, ${signedOut}.`)
1902
1937
  );
1903
1938
  return;
1904
1939
  }
@@ -1931,7 +1966,7 @@ ${bold(title)} \xB7 How your users sign in`);
1931
1966
  process.env[KEY_ENV] = outcome.key;
1932
1967
  console.log(green(` \u2713 ${written.created ? "Created" : "Updated"} ${relative(cwd, written.path) || written.path} with ${KEY_ENV}`) + ` (project "${outcome.projectName}").`);
1933
1968
  if (!written.ignored) console.log(yellow(` ! Add .env to .gitignore: it now holds a secret.`));
1934
- if (own) console.log(` Your app tells Exposify about its login when it starts with ${KEY_ENV}: nothing to add in the dashboard.`);
1969
+ if (own) console.log(` Your app tells Exposify about its ${sb ? "Supabase Auth" : "login"} when it starts with ${KEY_ENV}: nothing to add in the dashboard.`);
1935
1970
  else {
1936
1971
  console.log(` No login form was found, so ${signedOut}.`);
1937
1972
  console.log(` To have agents act as a signed-in user, add a sign-in method in the dashboard (presets for GitHub, Google, Supabase, \u2026).`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exposify/cli",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@babel/parser": "^8.0.0",
25
- "@exposify/core": "0.3.14"
25
+ "@exposify/core": "0.4.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.0.0",
@@ -33,7 +33,7 @@
33
33
  "publishConfig": {
34
34
  "access": "public"
35
35
  },
36
- "description": "The framework-neutral engine behind exposify-express and exposify-next: guided setup, inspect and describe for Exposify adapters.",
36
+ "description": "The framework-neutral engine behind @exposify/express and @exposify/next: guided setup, inspect and describe for Exposify adapters.",
37
37
  "author": "Exposify",
38
38
  "keywords": [
39
39
  "mcp",