@glasstrace/sdk 0.9.0 → 0.10.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.
@@ -0,0 +1,77 @@
1
+ import {
2
+ AnonApiKeySchema,
3
+ createAnonApiKey
4
+ } from "./chunk-O3Y45VGV.js";
5
+
6
+ // src/anon-key.ts
7
+ import { readFile, writeFile, mkdir, chmod } from "fs/promises";
8
+ import { join } from "path";
9
+ var GLASSTRACE_DIR = ".glasstrace";
10
+ var ANON_KEY_FILE = "anon_key";
11
+ var ephemeralKeyCache = /* @__PURE__ */ new Map();
12
+ async function readAnonKey(projectRoot) {
13
+ const root = projectRoot ?? process.cwd();
14
+ const keyPath = join(root, GLASSTRACE_DIR, ANON_KEY_FILE);
15
+ try {
16
+ const content = await readFile(keyPath, "utf-8");
17
+ const result = AnonApiKeySchema.safeParse(content);
18
+ if (result.success) {
19
+ return result.data;
20
+ }
21
+ } catch {
22
+ }
23
+ const cached = ephemeralKeyCache.get(root);
24
+ if (cached !== void 0) {
25
+ return cached;
26
+ }
27
+ return null;
28
+ }
29
+ async function getOrCreateAnonKey(projectRoot) {
30
+ const root = projectRoot ?? process.cwd();
31
+ const dirPath = join(root, GLASSTRACE_DIR);
32
+ const keyPath = join(dirPath, ANON_KEY_FILE);
33
+ const existingKey = await readAnonKey(root);
34
+ if (existingKey !== null) {
35
+ return existingKey;
36
+ }
37
+ const cached = ephemeralKeyCache.get(root);
38
+ if (cached !== void 0) {
39
+ return cached;
40
+ }
41
+ const newKey = createAnonApiKey();
42
+ try {
43
+ await mkdir(dirPath, { recursive: true, mode: 448 });
44
+ await writeFile(keyPath, newKey, { flag: "wx", mode: 384 });
45
+ return newKey;
46
+ } catch (err) {
47
+ const code = err.code;
48
+ if (code === "EEXIST") {
49
+ for (let attempt = 0; attempt < 3; attempt++) {
50
+ const winnerKey = await readAnonKey(root);
51
+ if (winnerKey !== null) {
52
+ return winnerKey;
53
+ }
54
+ if (attempt < 2) {
55
+ await new Promise((resolve) => setTimeout(resolve, 50));
56
+ }
57
+ }
58
+ try {
59
+ await writeFile(keyPath, newKey, { mode: 384 });
60
+ await chmod(keyPath, 384);
61
+ return newKey;
62
+ } catch {
63
+ }
64
+ }
65
+ ephemeralKeyCache.set(root, newKey);
66
+ console.warn(
67
+ `[glasstrace] Failed to persist anonymous key to ${keyPath}: ${err instanceof Error ? err.message : String(err)}. Using ephemeral key.`
68
+ );
69
+ return newKey;
70
+ }
71
+ }
72
+
73
+ export {
74
+ readAnonKey,
75
+ getOrCreateAnonKey
76
+ };
77
+ //# sourceMappingURL=chunk-ZRNG36LU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/anon-key.ts"],"sourcesContent":["import { readFile, writeFile, mkdir, chmod } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { AnonApiKeySchema, createAnonApiKey } from \"@glasstrace/protocol\";\nimport type { AnonApiKey } from \"@glasstrace/protocol\";\n\nconst GLASSTRACE_DIR = \".glasstrace\";\nconst ANON_KEY_FILE = \"anon_key\";\n\n/**\n * In-memory cache for ephemeral keys when filesystem persistence fails.\n * Keyed by resolved project root to support multiple roots in tests.\n */\nconst ephemeralKeyCache = new Map<string, AnonApiKey>();\n\n/**\n * Reads an existing anonymous key from the filesystem.\n * Returns the key if valid, or null if:\n * - The file does not exist\n * - The file content is invalid\n * - An I/O error occurs\n */\nexport async function readAnonKey(projectRoot?: string): Promise<AnonApiKey | null> {\n const root = projectRoot ?? process.cwd();\n const keyPath = join(root, GLASSTRACE_DIR, ANON_KEY_FILE);\n\n try {\n const content = await readFile(keyPath, \"utf-8\");\n const result = AnonApiKeySchema.safeParse(content);\n if (result.success) {\n return result.data;\n }\n } catch {\n // Fall through to check ephemeral cache\n }\n\n // Check in-memory cache (used when filesystem persistence failed)\n const cached = ephemeralKeyCache.get(root);\n if (cached !== undefined) {\n return cached;\n }\n\n return null;\n}\n\n/**\n * Gets an existing anonymous key from the filesystem, or creates a new one.\n *\n * - If file exists and contains a valid key, returns it\n * - If file does not exist or content is invalid, generates a new key via createAnonApiKey()\n * - Writes the new key to `.glasstrace/anon_key`, creating the directory if needed\n * - On file write failure: logs a warning, caches an ephemeral in-memory key so\n * repeated calls in the same process return the same key\n */\nexport async function getOrCreateAnonKey(projectRoot?: string): Promise<AnonApiKey> {\n const root = projectRoot ?? process.cwd();\n const dirPath = join(root, GLASSTRACE_DIR);\n const keyPath = join(dirPath, ANON_KEY_FILE);\n\n // Try reading existing key from filesystem\n const existingKey = await readAnonKey(root);\n if (existingKey !== null) {\n return existingKey;\n }\n\n // Check in-memory cache (used when filesystem is unavailable)\n const cached = ephemeralKeyCache.get(root);\n if (cached !== undefined) {\n return cached;\n }\n\n // Generate a new key\n const newKey = createAnonApiKey();\n\n // Persist to filesystem using atomic create-or-fail (O_CREAT | O_EXCL)\n // to prevent TOCTOU races where concurrent cold starts both generate keys.\n try {\n await mkdir(dirPath, { recursive: true, mode: 0o700 });\n await writeFile(keyPath, newKey, { flag: \"wx\", mode: 0o600 });\n return newKey;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"EEXIST\") {\n // Another process won the race. Retry reading their key with\n // short delays — the winner's writeFile is atomic for small\n // payloads but the filesystem may not have flushed yet.\n for (let attempt = 0; attempt < 3; attempt++) {\n const winnerKey = await readAnonKey(root);\n if (winnerKey !== null) {\n return winnerKey;\n }\n // Short delay before next retry (50ms), skip after final attempt\n if (attempt < 2) {\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n }\n // All retries exhausted — overwrite as last resort.\n // Use explicit chmod after overwrite since writeFile mode only\n // applies on creation on some platforms.\n try {\n await writeFile(keyPath, newKey, { mode: 0o600 });\n await chmod(keyPath, 0o600);\n return newKey;\n } catch {\n // Overwrite failed — fall through to ephemeral cache\n }\n }\n\n // Non-EEXIST error (EACCES, ENOTDIR, etc.) — cache in memory so\n // repeated calls get the same ephemeral key within this process.\n ephemeralKeyCache.set(root, newKey);\n console.warn(\n `[glasstrace] Failed to persist anonymous key to ${keyPath}: ${err instanceof Error ? err.message : String(err)}. Using ephemeral key.`,\n );\n return newKey;\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,UAAU,WAAW,OAAO,aAAa;AAClD,SAAS,YAAY;AAIrB,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AAMtB,IAAM,oBAAoB,oBAAI,IAAwB;AAStD,eAAsB,YAAY,aAAkD;AAClF,QAAM,OAAO,eAAe,QAAQ,IAAI;AACxC,QAAM,UAAU,KAAK,MAAM,gBAAgB,aAAa;AAExD,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,SAAS,OAAO;AAC/C,UAAM,SAAS,iBAAiB,UAAU,OAAO;AACjD,QAAI,OAAO,SAAS;AAClB,aAAO,OAAO;AAAA,IAChB;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,QAAM,SAAS,kBAAkB,IAAI,IAAI;AACzC,MAAI,WAAW,QAAW;AACxB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAWA,eAAsB,mBAAmB,aAA2C;AAClF,QAAM,OAAO,eAAe,QAAQ,IAAI;AACxC,QAAM,UAAU,KAAK,MAAM,cAAc;AACzC,QAAM,UAAU,KAAK,SAAS,aAAa;AAG3C,QAAM,cAAc,MAAM,YAAY,IAAI;AAC1C,MAAI,gBAAgB,MAAM;AACxB,WAAO;AAAA,EACT;AAGA,QAAM,SAAS,kBAAkB,IAAI,IAAI;AACzC,MAAI,WAAW,QAAW;AACxB,WAAO;AAAA,EACT;AAGA,QAAM,SAAS,iBAAiB;AAIhC,MAAI;AACF,UAAM,MAAM,SAAS,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACrD,UAAM,UAAU,SAAS,QAAQ,EAAE,MAAM,MAAM,MAAM,IAAM,CAAC;AAC5D,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,OAAQ,IAA8B;AAC5C,QAAI,SAAS,UAAU;AAIrB,eAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,cAAM,YAAY,MAAM,YAAY,IAAI;AACxC,YAAI,cAAc,MAAM;AACtB,iBAAO;AAAA,QACT;AAEA,YAAI,UAAU,GAAG;AACf,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,QACxD;AAAA,MACF;AAIA,UAAI;AACF,cAAM,UAAU,SAAS,QAAQ,EAAE,MAAM,IAAM,CAAC;AAChD,cAAM,MAAM,SAAS,GAAK;AAC1B,eAAO;AAAA,MACT,QAAQ;AAAA,MAER;AAAA,IACF;AAIA,sBAAkB,IAAI,MAAM,MAAM;AAClC,YAAQ;AAAA,MACN,mDAAmD,OAAO,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACjH;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
package/dist/cli/init.cjs CHANGED
@@ -31,6 +31,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
+ // src/cli/constants.ts
35
+ function formatAgentName(name) {
36
+ const displayNames = {
37
+ claude: "Claude Code",
38
+ codex: "Codex",
39
+ gemini: "Gemini",
40
+ cursor: "Cursor",
41
+ windsurf: "Windsurf",
42
+ generic: "Generic"
43
+ };
44
+ return displayNames[name];
45
+ }
46
+ var MCP_ENDPOINT, NEXT_CONFIG_NAMES;
47
+ var init_constants = __esm({
48
+ "src/cli/constants.ts"() {
49
+ "use strict";
50
+ MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
51
+ NEXT_CONFIG_NAMES = ["next.config.ts", "next.config.js", "next.config.mjs"];
52
+ }
53
+ });
54
+
34
55
  // src/cli/scaffolder.ts
35
56
  function identityFingerprint(token) {
36
57
  return `sha256:${(0, import_node_crypto.createHash)("sha256").update(token).digest("hex")}`;
@@ -72,7 +93,7 @@ ${indent}registerGlasstrace();
72
93
  } else {
73
94
  const existingImports = specifiers.trimEnd();
74
95
  const separator = existingImports.endsWith(",") ? " " : ", ";
75
- const updatedImport = `import {${existingImports}${separator}registerGlasstrace} from "@glasstrace/sdk"`;
96
+ const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
76
97
  modified = content.replace(importMatch[0], updatedImport);
77
98
  const newMatch = registerFnRegex.exec(modified);
78
99
  if (newMatch) {
@@ -275,14 +296,14 @@ async function scaffoldMcpMarker(projectRoot, anonKey) {
275
296
  fs.chmodSync(markerPath, 384);
276
297
  return true;
277
298
  }
278
- var import_node_crypto, fs, path, NEXT_CONFIG_NAMES;
299
+ var import_node_crypto, fs, path;
279
300
  var init_scaffolder = __esm({
280
301
  "src/cli/scaffolder.ts"() {
281
302
  "use strict";
282
303
  import_node_crypto = require("crypto");
283
304
  fs = __toESM(require("fs"), 1);
284
305
  path = __toESM(require("path"), 1);
285
- NEXT_CONFIG_NAMES = ["next.config.ts", "next.config.js", "next.config.mjs"];
306
+ init_constants();
286
307
  }
287
308
  });
288
309
 
@@ -14859,9 +14880,14 @@ async function getOrCreateAnonKey(projectRoot) {
14859
14880
  } catch (err) {
14860
14881
  const code = err.code;
14861
14882
  if (code === "EEXIST") {
14862
- const winnerKey = await readAnonKey(root);
14863
- if (winnerKey !== null) {
14864
- return winnerKey;
14883
+ for (let attempt = 0; attempt < 3; attempt++) {
14884
+ const winnerKey = await readAnonKey(root);
14885
+ if (winnerKey !== null) {
14886
+ return winnerKey;
14887
+ }
14888
+ if (attempt < 2) {
14889
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
14890
+ }
14865
14891
  }
14866
14892
  try {
14867
14893
  await (0, import_promises.writeFile)(keyPath, newKey, { mode: 384 });
@@ -15075,7 +15101,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
15075
15101
  2
15076
15102
  );
15077
15103
  case "codex": {
15078
- const safeEndpoint = endpoint.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
15104
+ const safeEndpoint = endpoint.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
15079
15105
  return [
15080
15106
  "[mcp_servers.glasstrace]",
15081
15107
  `url = "${safeEndpoint}"`,
@@ -15143,6 +15169,10 @@ function generateMcpConfig(agent, endpoint, anonKey) {
15143
15169
  null,
15144
15170
  2
15145
15171
  );
15172
+ default: {
15173
+ const _exhaustive = agent.name;
15174
+ throw new Error(`Unknown agent: ${_exhaustive}`);
15175
+ }
15146
15176
  }
15147
15177
  }
15148
15178
  function htmlMarkers() {
@@ -15200,6 +15230,10 @@ ${content}${m.end}
15200
15230
  case "windsurf":
15201
15231
  case "generic":
15202
15232
  return "";
15233
+ default: {
15234
+ const _exhaustive = agent.name;
15235
+ throw new Error(`Unknown agent: ${_exhaustive}`);
15236
+ }
15203
15237
  }
15204
15238
  }
15205
15239
  var init_configs = __esm({
@@ -15391,26 +15425,6 @@ var init_inject = __esm({
15391
15425
  }
15392
15426
  });
15393
15427
 
15394
- // src/cli/constants.ts
15395
- function formatAgentName(name) {
15396
- const displayNames = {
15397
- claude: "Claude Code",
15398
- codex: "Codex",
15399
- gemini: "Gemini",
15400
- cursor: "Cursor",
15401
- windsurf: "Windsurf",
15402
- generic: "Generic"
15403
- };
15404
- return displayNames[name];
15405
- }
15406
- var MCP_ENDPOINT;
15407
- var init_constants = __esm({
15408
- "src/cli/constants.ts"() {
15409
- "use strict";
15410
- MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
15411
- }
15412
- });
15413
-
15414
15428
  // src/cli/mcp-add.ts
15415
15429
  var mcp_add_exports = {};
15416
15430
  __export(mcp_add_exports, {
@@ -15644,6 +15658,7 @@ var init_mcp_add = __esm({
15644
15658
  // src/cli/uninit.ts
15645
15659
  var uninit_exports = {};
15646
15660
  __export(uninit_exports, {
15661
+ findMatchingDelimiter: () => findMatchingDelimiter,
15647
15662
  findMatchingParen: () => findMatchingParen,
15648
15663
  isInitCreatedInstrumentation: () => isInitCreatedInstrumentation,
15649
15664
  processJsonMcpConfig: () => processJsonMcpConfig,
@@ -15652,23 +15667,64 @@ __export(uninit_exports, {
15652
15667
  removeMarkerSection: () => removeMarkerSection,
15653
15668
  removeRegisterGlasstrace: () => removeRegisterGlasstrace,
15654
15669
  runUninit: () => runUninit,
15670
+ skipString: () => skipString,
15655
15671
  unwrapCJSExport: () => unwrapCJSExport,
15656
15672
  unwrapExport: () => unwrapExport
15657
15673
  });
15658
- function findMatchingParen(text, openPos) {
15674
+ function skipString(text, start, quote) {
15675
+ let i = start + 1;
15676
+ while (i < text.length) {
15677
+ if (text[i] === "\\") {
15678
+ i += 2;
15679
+ continue;
15680
+ }
15681
+ if (text[i] === quote) {
15682
+ return i + 1;
15683
+ }
15684
+ i++;
15685
+ }
15686
+ return text.length;
15687
+ }
15688
+ function findMatchingDelimiter(text, openPos, openChar, closeChar) {
15659
15689
  let depth = 0;
15660
- for (let i = openPos; i < text.length; i++) {
15661
- if (text[i] === "(") {
15690
+ let i = openPos;
15691
+ while (i < text.length) {
15692
+ const ch = text[i];
15693
+ if (ch === '"' || ch === "'" || ch === "`") {
15694
+ i = skipString(text, i, ch);
15695
+ continue;
15696
+ }
15697
+ if (ch === "/" && text[i + 1] === "/") {
15698
+ const newline = text.indexOf("\n", i);
15699
+ if (newline === -1) {
15700
+ return -1;
15701
+ }
15702
+ i = newline + 1;
15703
+ continue;
15704
+ }
15705
+ if (ch === "/" && text[i + 1] === "*") {
15706
+ const end = text.indexOf("*/", i + 2);
15707
+ if (end === -1) {
15708
+ return -1;
15709
+ }
15710
+ i = end + 2;
15711
+ continue;
15712
+ }
15713
+ if (ch === openChar) {
15662
15714
  depth++;
15663
- } else if (text[i] === ")") {
15715
+ } else if (ch === closeChar) {
15664
15716
  depth--;
15665
15717
  if (depth === 0) {
15666
15718
  return i;
15667
15719
  }
15668
15720
  }
15721
+ i++;
15669
15722
  }
15670
15723
  return -1;
15671
15724
  }
15725
+ function findMatchingParen(text, openPos) {
15726
+ return findMatchingDelimiter(text, openPos, "(", ")");
15727
+ }
15672
15728
  function unwrapExport(content) {
15673
15729
  const pattern = /export\s+default\s+withGlasstraceConfig\s*\(/;
15674
15730
  const match = pattern.exec(content);
@@ -15799,18 +15855,7 @@ function isInitCreatedInstrumentation(content) {
15799
15855
  return topLevelBefore.length === 0 && topLevelAfter.length === 0;
15800
15856
  }
15801
15857
  function findMatchingBrace(text, openPos) {
15802
- let depth = 0;
15803
- for (let i = openPos; i < text.length; i++) {
15804
- if (text[i] === "{") {
15805
- depth++;
15806
- } else if (text[i] === "}") {
15807
- depth--;
15808
- if (depth === 0) {
15809
- return i;
15810
- }
15811
- }
15812
- }
15813
- return -1;
15858
+ return findMatchingDelimiter(text, openPos, "{", "}");
15814
15859
  }
15815
15860
  function removeRegisterGlasstrace(content) {
15816
15861
  let result = content;
@@ -15933,7 +15978,7 @@ async function runUninit(options) {
15933
15978
  const prefix = dryRun ? "[dry run] " : "";
15934
15979
  try {
15935
15980
  let configHandled = false;
15936
- for (const name of NEXT_CONFIG_NAMES3) {
15981
+ for (const name of NEXT_CONFIG_NAMES) {
15937
15982
  const configPath = path5.join(projectRoot, name);
15938
15983
  if (!fs5.existsSync(configPath)) {
15939
15984
  continue;
@@ -16120,16 +16165,22 @@ async function runUninit(options) {
16120
16165
  if (fs5.existsSync(windsurfConfigPath)) {
16121
16166
  const content = fs5.readFileSync(windsurfConfigPath, "utf-8");
16122
16167
  const windsurfResult = processJsonMcpConfig(content);
16168
+ const home = os.homedir();
16169
+ const displayPath = windsurfConfigPath.startsWith(home) ? "~" + windsurfConfigPath.slice(home.length) : windsurfConfigPath;
16123
16170
  if (windsurfResult.action === "deleted") {
16124
16171
  if (!dryRun) {
16125
16172
  fs5.unlinkSync(windsurfConfigPath);
16126
16173
  }
16127
- summary.push(`${prefix}Deleted Windsurf MCP config`);
16174
+ summary.push(
16175
+ `${prefix}Deleted global Windsurf config (${displayPath})`
16176
+ );
16128
16177
  } else if (windsurfResult.action === "removed-key" && windsurfResult.content !== void 0) {
16129
16178
  if (!dryRun) {
16130
16179
  fs5.writeFileSync(windsurfConfigPath, windsurfResult.content, "utf-8");
16131
16180
  }
16132
- summary.push(`${prefix}Removed glasstrace from Windsurf MCP config`);
16181
+ summary.push(
16182
+ `${prefix}Removed glasstrace from global Windsurf config (${displayPath})`
16183
+ );
16133
16184
  }
16134
16185
  }
16135
16186
  }
@@ -16170,14 +16221,14 @@ async function runUninit(options) {
16170
16221
  }
16171
16222
  return { exitCode: errors.length > 0 ? 1 : 0, summary, warnings, errors };
16172
16223
  }
16173
- var fs5, os, path5, NEXT_CONFIG_NAMES3, MCP_CONFIG_FILES, AGENT_INFO_FILES;
16224
+ var fs5, os, path5, MCP_CONFIG_FILES, AGENT_INFO_FILES;
16174
16225
  var init_uninit = __esm({
16175
16226
  "src/cli/uninit.ts"() {
16176
16227
  "use strict";
16177
16228
  fs5 = __toESM(require("fs"), 1);
16178
16229
  os = __toESM(require("os"), 1);
16179
16230
  path5 = __toESM(require("path"), 1);
16180
- NEXT_CONFIG_NAMES3 = ["next.config.ts", "next.config.js", "next.config.mjs"];
16231
+ init_constants();
16181
16232
  MCP_CONFIG_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json"];
16182
16233
  AGENT_INFO_FILES = [
16183
16234
  "CLAUDE.md",
@@ -16378,7 +16429,7 @@ init_constants();
16378
16429
  // src/cli/monorepo.ts
16379
16430
  var fs3 = __toESM(require("fs"), 1);
16380
16431
  var path3 = __toESM(require("path"), 1);
16381
- var NEXT_CONFIG_NAMES2 = ["next.config.ts", "next.config.js", "next.config.mjs"];
16432
+ init_constants();
16382
16433
  function resolveProjectRoot(cwd) {
16383
16434
  if (hasNextConfig(cwd)) {
16384
16435
  return { projectRoot: cwd, isMonorepo: false };
@@ -16414,7 +16465,7 @@ Run init from the specific app directory you want to instrument.`
16414
16465
  );
16415
16466
  }
16416
16467
  function hasNextConfig(dir) {
16417
- return NEXT_CONFIG_NAMES2.some(
16468
+ return NEXT_CONFIG_NAMES.some(
16418
16469
  (name) => fs3.existsSync(path3.join(dir, name))
16419
16470
  );
16420
16471
  }