@exposify/next 0.0.3 → 0.0.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.
package/dist/config.cjs CHANGED
@@ -24,14 +24,14 @@ __export(config_exports, {
24
24
  withExposify: () => withExposify
25
25
  });
26
26
  module.exports = __toCommonJS(config_exports);
27
- var import_node_fs7 = require("fs");
28
- var import_node_path7 = require("path");
27
+ var import_node_fs8 = require("fs");
28
+ var import_node_path8 = require("path");
29
29
  var import_core3 = require("@exposify/core");
30
30
 
31
31
  // src/codegen.ts
32
32
  var import_node_crypto = require("crypto");
33
- var import_node_fs6 = require("fs");
34
- var import_node_path6 = require("path");
33
+ var import_node_fs7 = require("fs");
34
+ var import_node_path7 = require("path");
35
35
  var import_core2 = require("@exposify/core");
36
36
  var import_tinyglobby = require("tinyglobby");
37
37
 
@@ -360,8 +360,8 @@ function readsOf(fn, formNames, st, depth) {
360
360
  st.readsAll = true;
361
361
  const decl = [...parents].reverse().find((p) => !["TSAsExpression", "TSSatisfiesExpression", "ParenthesizedExpression"].includes(p.type));
362
362
  if (decl?.type === "VariableDeclarator" && decl.id.type === "ObjectPattern") {
363
- for (const prop of decl.id.properties) {
364
- const key = prop.type === "ObjectProperty" ? keyName(prop.key) : void 0;
363
+ for (const prop2 of decl.id.properties) {
364
+ const key = prop2.type === "ObjectProperty" ? keyName(prop2.key) : void 0;
365
365
  if (key) addField(st, key, {}, false);
366
366
  }
367
367
  }
@@ -403,19 +403,19 @@ function analyzeFields(fn, roles, ctx) {
403
403
  if (literal?.type === "TSTypeLiteral") {
404
404
  for (const m of literal.members) if (m.type === "TSPropertySignature" && keyName(m.key)) members.set(keyName(m.key), m);
405
405
  }
406
- for (const prop of id.properties) {
407
- const key = prop.type === "ObjectProperty" ? keyName(prop.key) : void 0;
406
+ for (const prop2 of id.properties) {
407
+ const key = prop2.type === "ObjectProperty" ? keyName(prop2.key) : void 0;
408
408
  if (!key) {
409
- st.unresolved.push(`line ${lineOf(prop)}: a rest element in parameter ${role.name}`);
409
+ st.unresolved.push(`line ${lineOf(prop2)}: a rest element in parameter ${role.name}`);
410
410
  continue;
411
411
  }
412
412
  const member = members.get(key);
413
413
  const hint = annotated(member?.typeAnnotation?.typeAnnotation);
414
414
  if (!hint) {
415
- st.unresolved.push(`line ${lineOf(prop)}: ${key} has no type it can read (string, number, boolean or a union of strings)`);
415
+ st.unresolved.push(`line ${lineOf(prop2)}: ${key} has no type it can read (string, number, boolean or a union of strings)`);
416
416
  continue;
417
417
  }
418
- st.fields.set(key, { name: key, type: hint.type, ...hint.enum ? { enum: hint.enum } : {}, ...member?.optional || prop.value.type === "AssignmentPattern" ? {} : { required: true } });
418
+ st.fields.set(key, { name: key, type: hint.type, ...hint.enum ? { enum: hint.enum } : {}, ...member?.optional || prop2.value.type === "AssignmentPattern" ? {} : { required: true } });
419
419
  }
420
420
  });
421
421
  return { fields: [...st.fields.values()], readsAll: st.readsAll, unresolved: st.unresolved };
@@ -493,20 +493,20 @@ function renderedAttributes(el, fn, use, mod) {
493
493
  for (const p of pattern.properties) {
494
494
  if (p.type === "RestElement" && p.argument.type === "Identifier") restName = p.argument.name;
495
495
  if (p.type !== "ObjectProperty") continue;
496
- const prop = keyName(p.key);
496
+ const prop2 = keyName(p.key);
497
497
  const value = p.value.type === "AssignmentPattern" ? p.value.left : p.value;
498
- if (!prop || value.type !== "Identifier") continue;
498
+ if (!prop2 || value.type !== "Identifier") continue;
499
499
  const fallback = p.value.type === "AssignmentPattern" ? attrValue({ type: "JSXAttribute", value: { type: "JSXExpressionContainer", expression: p.value.right } }, [], mod.scope) : void 0;
500
- locals.set(value.name, { prop, ...fallback ? { fallback } : {} });
500
+ locals.set(value.name, { prop: prop2, ...fallback ? { fallback } : {} });
501
501
  }
502
502
  }
503
- const named2 = new Set([...locals.values()].map((l) => l.prop));
503
+ const named = new Set([...locals.values()].map((l) => l.prop));
504
504
  const out = /* @__PURE__ */ new Map();
505
505
  for (const a of el.openingElement.attributes) {
506
506
  if (a.type === "JSXSpreadAttribute") {
507
507
  const arg = unwrapTs(a.argument);
508
508
  if (arg?.type === "Identifier" && (arg.name === restName || arg.name === propsName)) {
509
- for (const [k, v] of use) if (arg.name === propsName || !named2.has(k)) out.set(k, v);
509
+ for (const [k, v] of use) if (arg.name === propsName || !named.has(k)) out.set(k, v);
510
510
  }
511
511
  continue;
512
512
  }
@@ -514,14 +514,14 @@ function renderedAttributes(el, fn, use, mod) {
514
514
  if (!key) continue;
515
515
  const expr = a.value?.type === "JSXExpressionContainer" ? unwrapTs(a.value.expression) : void 0;
516
516
  if (expr?.type === "Identifier" && locals.has(expr.name)) {
517
- const { prop, fallback } = locals.get(expr.name);
518
- const v = use.has(prop) ? use.get(prop) : fallback;
517
+ const { prop: prop2, fallback } = locals.get(expr.name);
518
+ const v = use.has(prop2) ? use.get(prop2) : fallback;
519
519
  if (v !== void 0) out.set(key, v);
520
520
  continue;
521
521
  }
522
522
  if (expr?.type === "MemberExpression" && unwrapTs(expr.object)?.type === "Identifier" && unwrapTs(expr.object).name === propsName) {
523
- const prop = keyName(expr.property);
524
- if (prop && use.has(prop)) out.set(key, use.get(prop));
523
+ const prop2 = keyName(expr.property);
524
+ if (prop2 && use.has(prop2)) out.set(key, use.get(prop2));
525
525
  continue;
526
526
  }
527
527
  out.set(key, attrValue(a, [], mod.scope));
@@ -918,7 +918,7 @@ function actionHosts(pages, graph, actionExports) {
918
918
  var import_node_fs2 = require("fs");
919
919
  var import_node_path2 = require("path");
920
920
  var import_core = require("@exposify/core");
921
- var SESSION_CODE = /cookies\(\)\s*\.set|\.cookies\.set\(|cookieStore\.set|set-cookie|setCookie|\bjwt\.sign\(|new\s+SignJWT|\bsign\(|createSession|session\.(save|create)|\.login\(/i;
921
+ var SESSION_CODE = /cookies\(\)\)?\s*\.set|\.cookies\.set\(|cookieStore\.set|set-cookie|setCookie|\bjwt\.sign\(|new\s+SignJWT|\bsign\(|createSession|session\.(save|create)|\.login\(/i;
922
922
  function routeBodyFields(source) {
923
923
  const names = /* @__PURE__ */ new Set();
924
924
  let body = null;
@@ -939,16 +939,27 @@ function routeBodyFields(source) {
939
939
  }
940
940
  return names.size && body ? { fields: [...names], body } : null;
941
941
  }
942
- function actionCandidate(a) {
943
- if (import_core.NOT_A_LOGIN.test(a.key) || import_core.NOT_A_LOGIN.test(a.action.name)) return null;
942
+ var LOGIN_RULE = { not: import_core.NOT_A_LOGIN, name: import_core.LOGIN_NAME, mustBeNamed: false, fields: (n) => (0, import_core.loginFields)(n), session: true };
943
+ var VERIFY_RULE = { not: import_core.NOT_A_VERIFY, name: import_core.VERIFY_NAME, mustBeNamed: true, fields: (n, named) => (0, import_core.verifyFields)(n, named), session: true };
944
+ var START_RULE = { not: import_core.NOT_A_LOGIN, name: new RegExp(`${import_core.LOGIN_NAME.source}|${import_core.START_NAME.source}`, "i"), mustBeNamed: true, fields: (n) => (0, import_core.startFields)(n), session: false };
945
+ var knownKey = (l) => l.kind === "action" ? `${l.file}#${l.export}` : l.file;
946
+ function actionCandidate(a, rule, known) {
947
+ if (rule.not.test(a.key) || rule.not.test(a.action.name)) return null;
944
948
  if (!a.action.params.some((p) => p.role === "formData" || p.role === "object")) return null;
945
- const fields = (0, import_core.loginFields)(a.action.fields.map((f) => f.name));
949
+ const isNamed = rule.name.test(a.action.name);
950
+ if (rule.mustBeNamed && !isNamed) return null;
951
+ const fields = rule.fields(
952
+ a.action.fields.map((f) => f.name),
953
+ isNamed
954
+ );
946
955
  if (!fields) return null;
947
- if (!a.action.setsCookies && !import_core.LOGIN_NAME.test(a.action.name)) return null;
956
+ if (rule.session && !a.action.setsCookies && !import_core.LOGIN_NAME.test(a.action.name) && !(rule === LOGIN_RULE && known.has(`${a.file}#${a.action.name}`))) return null;
948
957
  return { kind: "action", key: a.key, export: a.action.name, file: a.file, fields, ...a.host ? { host: a.host } : {} };
949
958
  }
950
- function routeCandidate(root, r) {
951
- if (r.router !== "app" || !r.module.methods.includes("POST") || r.params.length > 0 || import_core.NOT_A_LOGIN.test(r.path)) return null;
959
+ function routeCandidate(root, r, rule, known) {
960
+ if (r.router !== "app" || !r.module.methods.includes("POST") || r.params.length > 0 || rule.not.test(r.path)) return null;
961
+ const isNamed = rule.name.test(r.path);
962
+ if (rule.mustBeNamed && !isNamed) return null;
952
963
  let source;
953
964
  try {
954
965
  source = (0, import_node_fs2.readFileSync)((0, import_node_path2.join)(root, r.file), "utf8");
@@ -956,26 +967,41 @@ function routeCandidate(root, r) {
956
967
  return null;
957
968
  }
958
969
  const read2 = routeBodyFields(source);
959
- const fields = read2 ? (0, import_core.loginFields)(read2.fields) : null;
970
+ const fields = read2 ? rule.fields(read2.fields, isNamed) : null;
960
971
  if (!read2 || !fields) return null;
961
- if (!import_core.LOGIN_NAME.test(r.path) && !SESSION_CODE.test(source)) return null;
972
+ if (rule.session && !import_core.LOGIN_NAME.test(r.path) && !SESSION_CODE.test(source) && !(rule === LOGIN_RULE && known.has(r.file))) return null;
962
973
  return { kind: "route", path: r.path, file: r.file, fields, body: read2.body };
963
974
  }
964
- var named = (l) => import_core.LOGIN_NAME.test(l.kind === "action" ? l.export : l.path);
965
- function findLogin(d) {
966
- const candidates = [];
975
+ var nameOf = (l) => l.kind === "action" ? l.export : l.path;
976
+ function candidates(d, rule, known) {
977
+ const out = [];
967
978
  for (const a of d.actions) {
968
- const c = actionCandidate(a);
969
- if (c) candidates.push(c);
979
+ const c = actionCandidate(a, rule, known);
980
+ if (c) out.push(c);
970
981
  }
971
982
  for (const r of d.routes) {
972
- const c = routeCandidate(d.root, r);
973
- if (c) candidates.push(c);
983
+ const c = routeCandidate(d.root, r, rule, known);
984
+ if (c) out.push(c);
985
+ }
986
+ const score = (l) => (rule === LOGIN_RULE && known.has(knownKey(l)) ? 0 : 8) + (rule.name.test(nameOf(l)) ? 0 : 4) + (l.kind === "action" && l.host ? 0 : 2) + l.fields.length / 100;
987
+ return out.sort((a, b) => score(a) - score(b));
988
+ }
989
+ function findLogin(d, known = /* @__PURE__ */ new Set()) {
990
+ const verifies = candidates(d, VERIFY_RULE, known);
991
+ const logins = candidates(d, LOGIN_RULE, known);
992
+ if (logins.length > 0) {
993
+ const [first2, ...others2] = logins;
994
+ return { login: { ...first2, ...verifies[0] ? { verify: verifies[0] } : {} }, others: others2 };
995
+ }
996
+ const pairs = [];
997
+ for (const start of candidates(d, START_RULE, known)) {
998
+ const who = new Set(start.fields.filter((f) => f.kind === "identity").map((f) => f.name));
999
+ const verify = verifies.find((v) => v.fields.some((f) => who.has(f.name))) ?? verifies.find((v) => !v.fields.some((f) => f.kind === "identity"));
1000
+ if (verify) pairs.push({ ...start, passwordless: true, verify });
974
1001
  }
975
- if (candidates.length === 0) return null;
976
- const score = (l) => (named(l) ? 0 : 4) + (l.kind === "action" && l.host ? 0 : 2) + l.fields.length / 100;
977
- candidates.sort((a, b) => score(a) - score(b));
978
- return { login: candidates[0], others: candidates.slice(1) };
1002
+ if (pairs.length === 0) return null;
1003
+ const [first, ...others] = pairs;
1004
+ return { login: first, others };
979
1005
  }
980
1006
 
981
1007
  // src/guards.ts
@@ -1157,9 +1183,9 @@ function pageSearchParams(program) {
1157
1183
  if (!FUNCTION_TYPES.has(fn.type)) return;
1158
1184
  const param = fn.params?.[0];
1159
1185
  if (param?.type === "ObjectPattern") {
1160
- for (const prop of param.properties) {
1161
- if (prop.type !== "ObjectProperty" || keyName(prop.key) !== "searchParams") continue;
1162
- const value = prop.value.type === "AssignmentPattern" ? prop.value.left : prop.value;
1186
+ for (const prop2 of param.properties) {
1187
+ if (prop2.type !== "ObjectProperty" || keyName(prop2.key) !== "searchParams") continue;
1188
+ const value = prop2.value.type === "AssignmentPattern" ? prop2.value.left : prop2.value;
1163
1189
  if (value.type === "Identifier") sources.add(value.name);
1164
1190
  for (const k of patternKeys(value)) names.add(k);
1165
1191
  }
@@ -1226,10 +1252,10 @@ function staticMetadata(program) {
1226
1252
  const init = unwrapTs(d.init);
1227
1253
  if (d.id?.type !== "Identifier" || d.id.name !== "metadata" || init?.type !== "ObjectExpression") continue;
1228
1254
  const out = {};
1229
- for (const prop of init.properties) {
1230
- if (prop.type !== "ObjectProperty") continue;
1231
- const key = keyName(prop.key);
1232
- const value = unwrapTs(prop.value);
1255
+ for (const prop2 of init.properties) {
1256
+ if (prop2.type !== "ObjectProperty") continue;
1257
+ const key = keyName(prop2.key);
1258
+ const value = unwrapTs(prop2.value);
1233
1259
  if (key === "description") {
1234
1260
  const s = stringValue(value);
1235
1261
  if (s) out.description = s;
@@ -1332,15 +1358,15 @@ function readTsconfig(root) {
1332
1358
  }
1333
1359
  }
1334
1360
  function asFile(path) {
1335
- const candidates = [path, ...EXTENSIONS.map((e) => path + e), ...EXTENSIONS.map((e) => (0, import_node_path5.join)(path, `index${e}`))];
1336
- if (/\.[mc]?jsx?$/.test(path)) candidates.push(...EXTENSIONS.map((e) => path.replace(/\.[mc]?jsx?$/, e)));
1337
- return candidates.find((c) => (0, import_node_fs5.existsSync)(c) && (0, import_node_fs5.statSync)(c).isFile());
1361
+ const candidates2 = [path, ...EXTENSIONS.map((e) => path + e), ...EXTENSIONS.map((e) => (0, import_node_path5.join)(path, `index${e}`))];
1362
+ if (/\.[mc]?jsx?$/.test(path)) candidates2.push(...EXTENSIONS.map((e) => path.replace(/\.[mc]?jsx?$/, e)));
1363
+ return candidates2.find((c) => (0, import_node_fs5.existsSync)(c) && (0, import_node_fs5.statSync)(c).isFile());
1338
1364
  }
1339
1365
  function moduleLoader(root) {
1340
1366
  const { baseUrl, paths } = readTsconfig(root);
1341
1367
  const base = (0, import_node_path5.join)(root, baseUrl ?? ".");
1342
1368
  const cache = /* @__PURE__ */ new Map();
1343
- const candidates = (specifier2, fromFile) => {
1369
+ const candidates2 = (specifier2, fromFile) => {
1344
1370
  if (specifier2.startsWith(".")) return [(0, import_node_path5.resolve)(root, (0, import_node_path5.dirname)(fromFile), specifier2)];
1345
1371
  for (const [pattern, targets] of Object.entries(paths ?? {})) {
1346
1372
  const star = pattern.indexOf("*");
@@ -1357,7 +1383,7 @@ function moduleLoader(root) {
1357
1383
  const key = `${fromFile}\0${specifier2}`;
1358
1384
  if (cache.has(key)) return cache.get(key);
1359
1385
  let found;
1360
- for (const candidate of candidates(specifier2, fromFile)) {
1386
+ for (const candidate of candidates2(specifier2, fromFile)) {
1361
1387
  const path = asFile(candidate);
1362
1388
  const rel = path && (0, import_node_path5.relative)(root, path);
1363
1389
  if (!path || !rel || rel.startsWith("..") || rel.split(import_node_path5.sep).includes("node_modules")) continue;
@@ -1389,11 +1415,11 @@ function writtenInput(n) {
1389
1415
  n = unwrapTs(n);
1390
1416
  if (n?.type !== "ObjectExpression") return "opaque";
1391
1417
  const out = {};
1392
- for (const prop of n.properties) {
1393
- const key = prop.type === "ObjectProperty" ? keyName(prop.key) : void 0;
1418
+ for (const prop2 of n.properties) {
1419
+ const key = prop2.type === "ObjectProperty" ? keyName(prop2.key) : void 0;
1394
1420
  if (!key) continue;
1395
1421
  let values;
1396
- walk(prop.value, (c) => {
1422
+ walk(prop2.value, (c) => {
1397
1423
  if (values || c.type !== "CallExpression" || keyName(c.callee?.property) !== "enum") return;
1398
1424
  const list = unwrapTs(c.arguments[0]);
1399
1425
  const items = list?.type === "ArrayExpression" ? list.elements.map((e) => stringValue(e)) : [];
@@ -1413,13 +1439,13 @@ function markerOf(init, imports) {
1413
1439
  const meta = call.arguments[1];
1414
1440
  const marker = { kind: "described" };
1415
1441
  if (meta?.type === "ObjectExpression") {
1416
- for (const prop of meta.properties) {
1417
- if (prop.type !== "ObjectProperty") continue;
1418
- const key = keyName(prop.key);
1419
- const value = stringValue(prop.value);
1442
+ for (const prop2 of meta.properties) {
1443
+ if (prop2.type !== "ObjectProperty") continue;
1444
+ const key = keyName(prop2.key);
1445
+ const value = stringValue(prop2.value);
1420
1446
  if (key === "name" && value) marker.name = value;
1421
1447
  if (key === "description" && value) marker.description = value;
1422
- if (key === "input") marker.input = writtenInput(prop.value);
1448
+ if (key === "input") marker.input = writtenInput(prop2.value);
1423
1449
  }
1424
1450
  }
1425
1451
  return { marker, handler };
@@ -1690,18 +1716,241 @@ function findInlineActions(source, file) {
1690
1716
  const program = parseModule(source, file);
1691
1717
  if (!program) return [];
1692
1718
  const out = [];
1693
- const named2 = /* @__PURE__ */ new Map();
1719
+ const named = /* @__PURE__ */ new Map();
1694
1720
  walk(program, (n) => {
1695
- if (n.type === "VariableDeclarator" && n.id.type === "Identifier" && n.init) named2.set(unwrapTs(n.init), n.id.name);
1721
+ if (n.type === "VariableDeclarator" && n.id.type === "Identifier" && n.init) named.set(unwrapTs(n.init), n.id.name);
1696
1722
  if (!FUNCTION_TYPES.has(n.type) || n.body?.type !== "BlockStatement") return;
1697
1723
  if (!n.body.directives.some((d) => d.value?.value === "use server")) return;
1698
1724
  if (isActionModule(program) && program.body.some((s) => s === n || s.declaration === n || s.declaration?.declarations?.some((d) => unwrapTs(d.init) === n))) return;
1699
- const name = n.id?.name ?? named2.get(n);
1725
+ const name = n.id?.name ?? named.get(n);
1700
1726
  out.push({ ...name ? { name } : {}, line: n.loc?.start.line ?? 1 });
1701
1727
  });
1702
1728
  return out;
1703
1729
  }
1704
1730
 
1731
+ // src/supabase.ts
1732
+ var import_node_fs6 = require("fs");
1733
+ var import_node_path6 = require("path");
1734
+ var AUTH_CALLS = {
1735
+ signInWithPassword: "password",
1736
+ signInWithOtp: "email-code",
1737
+ verifyOtp: "email-code",
1738
+ signInWithOAuth: "social",
1739
+ signInWithIdToken: "other",
1740
+ signInWithSSO: "other",
1741
+ signInAnonymously: "other",
1742
+ signInWithWeb3: "other"
1743
+ };
1744
+ var MFA_CALLS = /* @__PURE__ */ new Set(["challenge", "verify", "challengeAndVerify"]);
1745
+ var APP_SERVER_FILE = /^(page|layout|template|route|default|loading|not-found|forbidden|unauthorized|error|global-error)\.[^.]+$/;
1746
+ var MIDDLEWARE_FILE = /^(src\/)?(middleware|proxy|instrumentation)\.[^./]+$/;
1747
+ var directive2 = (program) => program.directives?.[0]?.value?.value;
1748
+ var baseName = (f) => f.slice(f.lastIndexOf("/") + 1);
1749
+ function isAuthObject(n) {
1750
+ n = unwrapTs(n);
1751
+ if (n?.type === "Identifier") return n.name === "auth";
1752
+ return (n?.type === "MemberExpression" || n?.type === "OptionalMemberExpression") && keyName(n.property) === "auth" && !n.computed;
1753
+ }
1754
+ var propertyOf = (n) => n.computed ? stringValue(n.property) : keyName(n.property);
1755
+ function prop(obj, name) {
1756
+ obj = unwrapTs(obj);
1757
+ if (obj?.type !== "ObjectExpression") return void 0;
1758
+ return obj.properties.find((p) => p.type === "ObjectProperty" && keyName(p.key) === name)?.value;
1759
+ }
1760
+ function findSupabase(root, files, graph, dependencies, dirs) {
1761
+ const ssr = dependencies.includes("@supabase/ssr");
1762
+ if (!ssr) return dependencies.includes("@supabase/auth-helpers-nextjs") ? { authHelpers: true, signIns: [], callbacks: [] } : null;
1763
+ const facts = /* @__PURE__ */ new Map();
1764
+ const factsOf = (file) => {
1765
+ if (facts.has(file)) return facts.get(file);
1766
+ let found = null;
1767
+ try {
1768
+ const source = (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(root, file), "utf8");
1769
+ const program = parseModule(source, file);
1770
+ if (program) {
1771
+ const d = directive2(program);
1772
+ found = {
1773
+ program,
1774
+ ...d ? { directive: d } : {},
1775
+ serverClient: /\bcreateServerClient\s*\(|from\s+["']next\/headers["']/.test(source),
1776
+ browserClient: /\bcreateBrowserClient\s*\(/.test(source)
1777
+ };
1778
+ }
1779
+ } catch {
1780
+ found = null;
1781
+ }
1782
+ facts.set(file, found);
1783
+ return found;
1784
+ };
1785
+ const isPagesPage = (f) => Boolean(dirs.pagesDir && f.startsWith(`${dirs.pagesDir}/`) && !f.startsWith(`${dirs.pagesDir}/api/`));
1786
+ const isPagesApi = (f) => Boolean(dirs.pagesDir && f.startsWith(`${dirs.pagesDir}/api/`));
1787
+ const isAppRoute = (f) => Boolean(dirs.appDir && f.startsWith(`${dirs.appDir}/`) && /^route\./.test(baseName(f)));
1788
+ const candidates2 = files.filter((f) => {
1789
+ try {
1790
+ return /\b(signIn\w*|verifyOtp|exchangeCodeForSession|mfa|auth-ui-react|storageKey|cookieOptions)\b/.test((0, import_node_fs6.readFileSync)((0, import_node_path6.join)(root, f), "utf8"));
1791
+ } catch {
1792
+ return false;
1793
+ }
1794
+ });
1795
+ const clientRoots = [];
1796
+ const serverRoots = [];
1797
+ for (const f of files) {
1798
+ if (isPagesPage(f)) {
1799
+ clientRoots.push(f);
1800
+ continue;
1801
+ }
1802
+ const isEntry = isPagesApi(f) || MIDDLEWARE_FILE.test(f) || Boolean(dirs.appDir && f.startsWith(`${dirs.appDir}/`) && APP_SERVER_FILE.test(baseName(f)));
1803
+ let text2;
1804
+ try {
1805
+ text2 = (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(root, f), "utf8");
1806
+ } catch {
1807
+ continue;
1808
+ }
1809
+ const head = /^\s*(?:\/\/[^\n]*\n|\/\*[\s\S]*?\*\/\s*)*\s*["']use (client|server)["']/.exec(text2)?.[1];
1810
+ if (head === "client") clientRoots.push(f);
1811
+ else if (head === "server" || isEntry) serverRoots.push(f);
1812
+ }
1813
+ const browserSet = graph.reachable(clientRoots);
1814
+ const serverSet = /* @__PURE__ */ new Set();
1815
+ const queue = [...serverRoots];
1816
+ while (queue.length > 0 && serverSet.size < 2e3) {
1817
+ const f = queue.shift();
1818
+ if (serverSet.has(f)) continue;
1819
+ if (!serverRoots.includes(f) && factsOf(f)?.directive === "use client") continue;
1820
+ serverSet.add(f);
1821
+ for (const e of graph.edges(f)) if (!serverSet.has(e.file)) queue.push(e.file);
1822
+ }
1823
+ const sideOf = (file, inServerFn) => {
1824
+ const f = factsOf(file);
1825
+ if (inServerFn || f?.directive === "use server") return { side: "server", why: "a Server Action" };
1826
+ if (isAppRoute(file) || isPagesApi(file)) return { side: "server", why: "a route handler" };
1827
+ if (f?.directive === "use client") return { side: "browser", why: '"use client"' };
1828
+ if (isPagesPage(file)) return { side: "browser", why: "a Pages Router page" };
1829
+ let server = f?.serverClient ?? false;
1830
+ let browser = f?.browserClient ?? false;
1831
+ let helper;
1832
+ if (!server && !browser) {
1833
+ for (const e of graph.edges(file)) {
1834
+ const g = factsOf(e.file);
1835
+ if (g?.serverClient && !g.browserClient) {
1836
+ server = true;
1837
+ helper = e.file;
1838
+ }
1839
+ if (g?.browserClient && !g.serverClient) {
1840
+ browser = true;
1841
+ helper = e.file;
1842
+ }
1843
+ }
1844
+ }
1845
+ if (server !== browser) return { side: server ? "server" : "browser", why: `uses the ${server ? "server" : "browser"} client${helper ? ` from ${helper}` : ""}` };
1846
+ const inBrowser = browserSet.has(file);
1847
+ const inServer = serverSet.has(file);
1848
+ if (inBrowser && !inServer) return { side: "browser", why: "imported by browser code" };
1849
+ if (inServer && !inBrowser) return { side: "server", why: "imported by server code" };
1850
+ return { side: "unknown", why: inBrowser ? "imported by both browser and server code" : "not imported by a page or route we could follow" };
1851
+ };
1852
+ const out = { signIns: [], callbacks: [] };
1853
+ for (const file of candidates2) {
1854
+ const f = factsOf(file);
1855
+ if (!f) continue;
1856
+ const top = f.program;
1857
+ const topName = (n) => {
1858
+ const d = n.type === "ExportNamedDeclaration" ? n.declaration : n.type === "ExportDefaultDeclaration" ? n.declaration : n;
1859
+ if (n.type === "ExportDefaultDeclaration") return "default";
1860
+ if (d?.type === "FunctionDeclaration") return d.id?.name;
1861
+ if (d?.type === "VariableDeclaration") return keyName(d.declarations?.[0]?.id);
1862
+ return void 0;
1863
+ };
1864
+ let authUi;
1865
+ walk(top, (n, parents) => {
1866
+ if (n.type === "ImportDeclaration" && n.source?.value === "@supabase/auth-ui-react") {
1867
+ authUi = n.specifiers.find((s) => s.type === "ImportSpecifier" && keyName(s.imported) === "Auth")?.local?.name;
1868
+ }
1869
+ if (n.type === "ObjectProperty" && !out.cookieName) {
1870
+ const key = keyName(n.key);
1871
+ const value = stringValue(unwrapTs(n.value));
1872
+ const parentProp = parents.at(-2);
1873
+ if (key === "storageKey" && value) out.cookieName = value;
1874
+ if (key === "name" && value && parentProp?.type === "ObjectProperty" && keyName(parentProp.key) === "cookieOptions") out.cookieName = value;
1875
+ }
1876
+ const push = (call, method2, extra = {}) => {
1877
+ const inServerFn = parents.some((p) => FUNCTION_TYPES.has(p.type) && p.body?.directives?.some((d) => d.value?.value === "use server"));
1878
+ const { side, why } = sideOf(file, inServerFn);
1879
+ const holder = parents.find((p) => top.body.includes(p));
1880
+ const name2 = holder ? topName(holder) : void 0;
1881
+ out.signIns.push({
1882
+ method: method2,
1883
+ call,
1884
+ ...extra,
1885
+ file,
1886
+ line: n.loc?.start.line ?? 1,
1887
+ side,
1888
+ why,
1889
+ ...side === "server" && name2 && (isActionModule(top) || inServerFn) ? { action: `${file}#${name2}` } : {},
1890
+ ...side === "server" && (isAppRoute(file) || isPagesApi(file)) ? { route: file } : {}
1891
+ });
1892
+ };
1893
+ if (n.type === "JSXOpeningElement" && authUi && n.name?.type === "JSXIdentifier" && n.name.name === authUi) {
1894
+ push("<Auth />", "password");
1895
+ return;
1896
+ }
1897
+ if (n.type !== "CallExpression" && n.type !== "OptionalCallExpression") return;
1898
+ const callee = unwrapTs(n.callee);
1899
+ if (callee?.type !== "MemberExpression" && callee?.type !== "OptionalMemberExpression") return;
1900
+ const name = propertyOf(callee);
1901
+ if (!name) return;
1902
+ const object = unwrapTs(callee.object);
1903
+ if (MFA_CALLS.has(name) && (object?.type === "MemberExpression" || object?.type === "OptionalMemberExpression") && propertyOf(object) === "mfa" && isAuthObject(object.object)) {
1904
+ push(`mfa.${name}`, "totp");
1905
+ return;
1906
+ }
1907
+ if (!isAuthObject(object)) return;
1908
+ const arg = n.arguments?.[0];
1909
+ if (name === "exchangeCodeForSession" || name === "verifyOtp" && prop(arg, "token_hash")) {
1910
+ if (!out.callbacks.includes(file)) out.callbacks.push(file);
1911
+ return;
1912
+ }
1913
+ const method = Object.hasOwn(AUTH_CALLS, name) ? AUTH_CALLS[name] : void 0;
1914
+ if (!method) return;
1915
+ const provider = name === "signInWithOAuth" ? stringValue(unwrapTs(prop(arg, "provider"))) : void 0;
1916
+ push(name, method, provider ? { provider } : {});
1917
+ });
1918
+ }
1919
+ return out;
1920
+ }
1921
+ function signInLabel(s) {
1922
+ const side = s.side === "unknown" ? "side unclear, counted as server" : s.side;
1923
+ return `${s.call}${s.provider ? ` (${s.provider})` : ""} in ${s.file}:${s.line} (${side}: ${s.why})`;
1924
+ }
1925
+ function supabaseChoice(found, login, loginPages2 = []) {
1926
+ const onServer = (method) => found.signIns.filter((s) => s.method === method && s.side !== "browser");
1927
+ const direct = [];
1928
+ const unusable = [];
1929
+ for (const method of ["password", "email-code"]) {
1930
+ const server = onServer(method);
1931
+ if (server.length === 0) direct.push(method);
1932
+ else if (!login) unusable.push(...server.map(signInLabel));
1933
+ }
1934
+ direct.push("social");
1935
+ return {
1936
+ ...found.cookieName ? { cookieName: found.cookieName } : {},
1937
+ direct,
1938
+ found: found.signIns.map(signInLabel),
1939
+ ...unusable.length ? { unusable } : {},
1940
+ ...found.callbacks.length ? { callbacks: found.callbacks } : {},
1941
+ ...loginPages2.length ? { loginPages: loginPages2 } : {}
1942
+ };
1943
+ }
1944
+ function knownLogins(found) {
1945
+ const out = /* @__PURE__ */ new Set();
1946
+ for (const s of found?.signIns ?? []) {
1947
+ if (s.method !== "password" || s.side === "browser") continue;
1948
+ if (s.action) out.add(s.action);
1949
+ if (s.route) out.add(s.route);
1950
+ }
1951
+ return out;
1952
+ }
1953
+
1705
1954
  // src/codegen.ts
1706
1955
  var DEFAULT_DOCS = ["README.md", "docs/**/*.md"];
1707
1956
  var actionRoute = (mcpPath, key) => `POST ${(mcpPath ?? "/mcp").replace(/\/$/, "")}/actions/${key}`;
@@ -1709,16 +1958,16 @@ function actionSignature(route, source) {
1709
1958
  const [method, path] = route.split(" ");
1710
1959
  return (0, import_node_crypto.createHash)("sha256").update(JSON.stringify([method, path, [], source ?? ""])).digest("hex").slice(0, 16);
1711
1960
  }
1712
- var posix = (p) => p.split(import_node_path6.sep).join("/");
1961
+ var posix = (p) => p.split(import_node_path7.sep).join("/");
1713
1962
  function firstDir(root, names) {
1714
- return names.find((n) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(root, n)));
1963
+ return names.find((n) => (0, import_node_fs7.existsSync)((0, import_node_path7.join)(root, n)));
1715
1964
  }
1716
1965
  function filesUnder(root, dir) {
1717
1966
  const out = [];
1718
1967
  const visit = (rel) => {
1719
1968
  let entries;
1720
1969
  try {
1721
- entries = (0, import_node_fs6.readdirSync)((0, import_node_path6.join)(root, rel), { withFileTypes: true });
1970
+ entries = (0, import_node_fs7.readdirSync)((0, import_node_path7.join)(root, rel), { withFileTypes: true });
1722
1971
  } catch {
1723
1972
  return;
1724
1973
  }
@@ -1745,7 +1994,7 @@ function discover(root, opts = {}) {
1745
1994
  const dirSegs = file.slice(appDir.length + 1).split("/").slice(0, -1);
1746
1995
  const route = appRoute(dirSegs);
1747
1996
  if (!route) continue;
1748
- const source = (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(root, file), "utf8");
1997
+ const source = (0, import_node_fs7.readFileSync)((0, import_node_path7.join)(root, file), "utf8");
1749
1998
  const module2 = analyzeRouteModule(source, file);
1750
1999
  if (module2.mcpRoute) {
1751
2000
  out.mcpRoute ??= { file, source };
@@ -1761,7 +2010,7 @@ function discover(root, opts = {}) {
1761
2010
  const segs = file.slice(pagesDir.length + 1).replace(extPattern, "").split("/");
1762
2011
  const route = pagesApiRoute(segs);
1763
2012
  if (!route) continue;
1764
- const source = (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(root, file), "utf8");
2013
+ const source = (0, import_node_fs7.readFileSync)((0, import_node_path7.join)(root, file), "utf8");
1765
2014
  const src = defaultExportSource(source, file);
1766
2015
  out.routes.push({ router: "pages", file, ...route, detected: detectPagesMethods(source, file), ...src ? { source: src } : {} });
1767
2016
  }
@@ -1773,14 +2022,22 @@ function discover(root, opts = {}) {
1773
2022
  const catchAll = route ? /^(.*)\/:[A-Za-z0-9_]+\*\??$/.exec(route.path) : null;
1774
2023
  if (catchAll) out.mcpPath = catchAll[1] || "/";
1775
2024
  }
1776
- discoverActions(root, out, exts);
1777
- const found = findLogin(out);
2025
+ const { files, graph, pages } = discoverActions(root, out, exts);
2026
+ const supabase = findSupabase(root, files, graph, (0, import_core2.dependencyNames)(readJson((0, import_node_path7.join)(root, "package.json"))), out);
2027
+ const found = findLogin(out, knownLogins(supabase));
1778
2028
  if (found) {
1779
2029
  out.login = found.login;
1780
2030
  out.loginOthers = found.others;
1781
2031
  }
2032
+ if (supabase && !supabase.authHelpers) out.supabase = { found: supabase, choice: supabaseChoice(supabase, out.login, loginPages(supabase, pages, graph)) };
2033
+ else if (supabase) out.supabase = { found: supabase, choice: { direct: [], found: [] } };
1782
2034
  return out;
1783
2035
  }
2036
+ function loginPages(found, pages, graph) {
2037
+ const files = new Set(found.signIns.filter((s) => s.method === "password" || s.method === "email-code").map((s) => s.file));
2038
+ if (files.size === 0) return [];
2039
+ return pages.filter((p) => p.params.length === 0 && [...graph.reachable(p.roots)].some((f) => files.has(f))).map((p) => p.path);
2040
+ }
1784
2041
  var SOURCE_GLOB = "**/*.{ts,tsx,js,jsx,mjs,cjs}";
1785
2042
  var NOT_SOURCE = ["**/node_modules/**", ".next/**", "out/**", "build/**", "dist/**", "coverage/**", "**/*.d.ts"];
1786
2043
  function snakeCase(name) {
@@ -1794,7 +2051,7 @@ function discoverActions(root, out, exts) {
1794
2051
  for (const file of files) {
1795
2052
  let source;
1796
2053
  try {
1797
- source = (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(root, file), "utf8");
2054
+ source = (0, import_node_fs7.readFileSync)((0, import_node_path7.join)(root, file), "utf8");
1798
2055
  } catch {
1799
2056
  continue;
1800
2057
  }
@@ -1851,24 +2108,25 @@ function discoverActions(root, out, exts) {
1851
2108
  const found2 = guards.action(a.file, a.action.name);
1852
2109
  if (found2.length > 0) a.guards = found2;
1853
2110
  }
2111
+ return { files, graph, pages };
1854
2112
  }
1855
2113
  function readJson(path) {
1856
2114
  try {
1857
- return JSON.parse((0, import_node_fs6.readFileSync)(path, "utf8"));
2115
+ return JSON.parse((0, import_node_fs7.readFileSync)(path, "utf8"));
1858
2116
  } catch {
1859
2117
  return void 0;
1860
2118
  }
1861
2119
  }
1862
2120
  function readProposedInputs(root) {
1863
- const path = (0, import_node_path6.join)(root, import_core2.DESCRIPTIONS_FILE);
1864
- if (!(0, import_node_fs6.existsSync)(path)) return {};
1865
- const parsed = (0, import_core2.parseDescriptions)((0, import_node_fs6.readFileSync)(path, "utf8"));
2121
+ const path = (0, import_node_path7.join)(root, import_core2.DESCRIPTIONS_FILE);
2122
+ if (!(0, import_node_fs7.existsSync)(path)) return {};
2123
+ const parsed = (0, import_core2.parseDescriptions)((0, import_node_fs7.readFileSync)(path, "utf8"));
1866
2124
  return typeof parsed === "string" ? {} : parsed.inputs ?? {};
1867
2125
  }
1868
2126
  function readDescriptions(root, warn) {
1869
- const path = (0, import_node_path6.join)(root, import_core2.DESCRIPTIONS_FILE);
1870
- if (!(0, import_node_fs6.existsSync)(path)) return {};
1871
- const parsed = (0, import_core2.parseDescriptions)((0, import_node_fs6.readFileSync)(path, "utf8"));
2127
+ const path = (0, import_node_path7.join)(root, import_core2.DESCRIPTIONS_FILE);
2128
+ if (!(0, import_node_fs7.existsSync)(path)) return {};
2129
+ const parsed = (0, import_core2.parseDescriptions)((0, import_node_fs7.readFileSync)(path, "utf8"));
1872
2130
  if (typeof parsed === "string") {
1873
2131
  warn(`ignoring ${import_core2.DESCRIPTIONS_FILE}: ${parsed}`);
1874
2132
  return {};
@@ -1880,22 +2138,28 @@ function readDocs(root, globs) {
1880
2138
  const docs = [];
1881
2139
  for (const path of paths) {
1882
2140
  try {
1883
- docs.push({ path, content: (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(root, path), "utf8") });
2141
+ docs.push({ path, content: (0, import_node_fs7.readFileSync)((0, import_node_path7.join)(root, path), "utf8") });
1884
2142
  } catch {
1885
2143
  }
1886
2144
  }
1887
2145
  return docs;
1888
2146
  }
1889
2147
  function defaultOutFile(root) {
1890
- return (0, import_node_fs6.existsSync)((0, import_node_path6.join)(root, "tsconfig.json")) ? "exposify.generated.ts" : "exposify.generated.js";
2148
+ return (0, import_node_fs7.existsSync)((0, import_node_path7.join)(root, "tsconfig.json")) ? "exposify.generated.ts" : "exposify.generated.js";
1891
2149
  }
1892
2150
  function specifier(outFile, file) {
1893
- const rel = posix((0, import_node_path6.relative)((0, import_node_path6.dirname)(outFile), file)).replace(/\.[^./]+$/, "");
2151
+ const rel = posix((0, import_node_path7.relative)((0, import_node_path7.dirname)(outFile), file)).replace(/\.[^./]+$/, "");
1894
2152
  return rel.startsWith(".") ? rel : `./${rel}`;
1895
2153
  }
1896
2154
  function manifestLogin(l) {
1897
- return l.kind === "action" ? { kind: "action", key: l.key, fields: l.fields, ...l.host ? { host: l.host } : {}, where: `${l.export} in ${l.file}` } : { kind: "route", path: l.path, fields: l.fields, body: l.body, where: `POST ${l.path} in ${l.file}` };
2155
+ const verify = l.verify ? manifestStep(l.verify) : void 0;
2156
+ const where = l.verify ? `${whereOf(l)}, then a code: ${whereOf(l.verify)}` : whereOf(l);
2157
+ return { ...manifestStep(l), where, ...l.passwordless ? { passwordless: true } : {}, ...verify ? { verify } : {} };
1898
2158
  }
2159
+ function manifestStep(l) {
2160
+ return l.kind === "action" ? { kind: "action", key: l.key, fields: l.fields, ...l.host ? { host: l.host } : {} } : { kind: "route", path: l.path, fields: l.fields, body: l.body };
2161
+ }
2162
+ var whereOf = (l) => l.kind === "action" ? `${l.export} in ${l.file}` : `POST ${l.path} in ${l.file}`;
1899
2163
  function renderManifest(d, opts) {
1900
2164
  const ts = opts.outFile.endsWith(".ts");
1901
2165
  const j = (v) => JSON.stringify(v);
@@ -1939,13 +2203,14 @@ function renderManifest(d, opts) {
1939
2203
  ` info: ${j(opts.info)},`,
1940
2204
  ...opts.basePath ? [` basePath: ${j(opts.basePath)},`] : [],
1941
2205
  ...opts.trailingSlash ? [" trailingSlash: true,"] : [],
1942
- ...d.mcpPath && (actions.length > 0 || d.login) ? [` mcpPath: ${j(d.mcpPath)},`] : [],
2206
+ ...d.mcpPath && (actions.length > 0 || d.login || d.supabase) ? [` mcpPath: ${j(d.mcpPath)},`] : [],
1943
2207
  " routes: [",
1944
2208
  ...routes,
1945
2209
  " ],",
1946
2210
  ...actions.length > 0 ? [" actions: [", ...actions, " ],"] : [],
1947
2211
  ...pages.length > 0 ? [" pages: [", ...pages, " ],"] : [],
1948
2212
  ...d.login ? [` login: ${j(manifestLogin(d.login))},`] : [],
2213
+ ...d.supabase && !d.supabase.found.authHelpers ? [` supabase: ${j(d.supabase.choice)},`] : [],
1949
2214
  ...opts.authStacks?.length ? [` authStacks: ${j(opts.authStacks)},`] : [],
1950
2215
  ` docs: ${j(opts.docs)},`,
1951
2216
  ...Object.keys(opts.descriptions).length > 0 ? [` descriptions: ${JSON.stringify(opts.descriptions, null, 2).replace(/\n/g, "\n ")},`] : [],
@@ -1957,7 +2222,7 @@ function renderManifest(d, opts) {
1957
2222
  function generate(root, opts = {}, warn = (m) => console.warn(`[exposify] ${m}`)) {
1958
2223
  const outFile = opts.out ?? defaultOutFile(root);
1959
2224
  const discovery = discover(root, opts);
1960
- const pkg = readJson((0, import_node_path6.join)(root, "package.json"));
2225
+ const pkg = readJson((0, import_node_path7.join)(root, "package.json"));
1961
2226
  const info = { name: typeof pkg?.name === "string" ? pkg.name : "next-app", version: typeof pkg?.version === "string" ? pkg.version : "0.0.0" };
1962
2227
  const content = renderManifest(discovery, {
1963
2228
  outFile,
@@ -1968,6 +2233,12 @@ function generate(root, opts = {}, warn = (m) => console.warn(`[exposify] ${m}`)
1968
2233
  ...opts.trailingSlash ? { trailingSlash: true } : {},
1969
2234
  authStacks: (0, import_core2.authStacksOf)((0, import_core2.dependencyNames)(pkg)).map((s) => s.pkg)
1970
2235
  });
2236
+ if (discovery.supabase?.found.authHelpers) {
2237
+ warn("@supabase/auth-helpers-nextjs keeps its session in an older cookie format AI assistants can't sign in with; move to @supabase/ssr (Supabase's replacement for it) to use Connect");
2238
+ }
2239
+ for (const s of discovery.supabase?.choice.unusable ?? []) {
2240
+ warn(`your app signs users in to Supabase on the server (${s}), but not in a Server Action or route the sign-in form can run, so AI assistants can't sign in with a password; switch on "Sign in with Supabase" on the dashboard to have them sign in to Supabase directly`);
2241
+ }
1971
2242
  for (const a of discovery.actions.filter((x) => x.proposed?.status === "stale")) {
1972
2243
  warn(`the input accepted for the ${a.action.name} server action (${a.file}) is out of date, since the action changed: it's not used until \`@exposify/next describe\` reviews it again`);
1973
2244
  }
@@ -1976,14 +2247,14 @@ function generate(root, opts = {}, warn = (m) => console.warn(`[exposify] ${m}`)
1976
2247
  discovery.mcpRoute ? `found ${discovery.actions.length} Server Action(s), but the MCP route (${discovery.mcpRoute.file}) isn't a catch-all route, which they're served under: move it to app/mcp/[[...transport]]/route.ts` : `found ${discovery.actions.length} Server Action(s), but no MCP route to serve them under: create app/mcp/[[...transport]]/route.ts (npx @exposify/next setup)`
1977
2248
  );
1978
2249
  }
1979
- const file = (0, import_node_path6.join)(root, outFile);
2250
+ const file = (0, import_node_path7.join)(root, outFile);
1980
2251
  let current;
1981
2252
  try {
1982
- current = (0, import_node_fs6.readFileSync)(file, "utf8");
2253
+ current = (0, import_node_fs7.readFileSync)(file, "utf8");
1983
2254
  } catch {
1984
2255
  current = void 0;
1985
2256
  }
1986
- if (current !== content) (0, import_node_fs6.writeFileSync)(file, content);
2257
+ if (current !== content) (0, import_node_fs7.writeFileSync)(file, content);
1987
2258
  return { file, changed: current !== content, discovery };
1988
2259
  }
1989
2260
 
@@ -2026,14 +2297,14 @@ function watchRoutes(root, run) {
2026
2297
  timer = setTimeout(run, 150);
2027
2298
  };
2028
2299
  for (const dir of ["app", "pages", "src", "lib", "actions", "server"]) {
2029
- if (!(0, import_node_fs7.existsSync)((0, import_node_path7.join)(root, dir))) continue;
2300
+ if (!(0, import_node_fs8.existsSync)((0, import_node_path8.join)(root, dir))) continue;
2030
2301
  try {
2031
- (0, import_node_fs7.watch)((0, import_node_path7.join)(root, dir), { recursive: true }, schedule).unref();
2302
+ (0, import_node_fs8.watch)((0, import_node_path8.join)(root, dir), { recursive: true }, schedule).unref();
2032
2303
  } catch {
2033
2304
  }
2034
2305
  }
2035
2306
  try {
2036
- (0, import_node_fs7.watch)(root, (_event, name) => {
2307
+ (0, import_node_fs8.watch)(root, (_event, name) => {
2037
2308
  if (name === import_core3.DESCRIPTIONS_FILE) schedule();
2038
2309
  }).unref();
2039
2310
  } catch {