@hyperfrontend/project-scope 0.1.0 → 0.2.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.
Files changed (177) hide show
  1. package/CHANGELOG.md +15 -3
  2. package/README.md +2 -0
  3. package/analyze.d.ts.map +1 -1
  4. package/cli/commands/analyze.d.ts +8 -0
  5. package/cli/commands/analyze.d.ts.map +1 -1
  6. package/cli/commands/config.d.ts +7 -0
  7. package/cli/commands/config.d.ts.map +1 -1
  8. package/cli/commands/deps.d.ts +6 -0
  9. package/cli/commands/deps.d.ts.map +1 -1
  10. package/cli/commands/tree.d.ts +12 -0
  11. package/cli/commands/tree.d.ts.map +1 -1
  12. package/cli/index.cjs.js +73 -206
  13. package/cli/index.cjs.js.map +1 -1
  14. package/cli/index.esm.js +73 -206
  15. package/cli/index.esm.js.map +1 -1
  16. package/cli/run.d.ts.map +1 -1
  17. package/core/cache.d.ts +1 -0
  18. package/core/cache.d.ts.map +1 -1
  19. package/core/encoding/convert.d.ts.map +1 -1
  20. package/core/encoding/detect.d.ts +5 -0
  21. package/core/encoding/detect.d.ts.map +1 -1
  22. package/core/encoding/index.cjs.js +2 -23
  23. package/core/encoding/index.cjs.js.map +1 -1
  24. package/core/encoding/index.esm.js +2 -23
  25. package/core/encoding/index.esm.js.map +1 -1
  26. package/core/errors/structured-errors.d.ts +2 -0
  27. package/core/errors/structured-errors.d.ts.map +1 -1
  28. package/core/fs/directory.d.ts +3 -0
  29. package/core/fs/directory.d.ts.map +1 -1
  30. package/core/fs/index.cjs.js +0 -14
  31. package/core/fs/index.cjs.js.map +1 -1
  32. package/core/fs/index.esm.js +0 -14
  33. package/core/fs/index.esm.js.map +1 -1
  34. package/core/fs/read.d.ts +11 -3
  35. package/core/fs/read.d.ts.map +1 -1
  36. package/core/fs/traversal.d.ts.map +1 -1
  37. package/core/index.cjs.js +11 -63
  38. package/core/index.cjs.js.map +1 -1
  39. package/core/index.esm.js +11 -63
  40. package/core/index.esm.js.map +1 -1
  41. package/core/logger.d.ts.map +1 -1
  42. package/core/path/index.cjs.js +5 -2
  43. package/core/path/index.cjs.js.map +1 -1
  44. package/core/path/index.esm.js +5 -2
  45. package/core/path/index.esm.js.map +1 -1
  46. package/core/path/normalize.d.ts.map +1 -1
  47. package/core/patterns/glob.d.ts +0 -4
  48. package/core/patterns/glob.d.ts.map +1 -1
  49. package/core/platform/detect.d.ts.map +1 -1
  50. package/core/platform/index.cjs.js +0 -10
  51. package/core/platform/index.cjs.js.map +1 -1
  52. package/core/platform/index.esm.js +0 -10
  53. package/core/platform/index.esm.js.map +1 -1
  54. package/core/platform/line-endings.d.ts.map +1 -1
  55. package/heuristics/dependencies/analyze.d.ts.map +1 -1
  56. package/heuristics/dependencies/index.cjs.js +0 -17
  57. package/heuristics/dependencies/index.cjs.js.map +1 -1
  58. package/heuristics/dependencies/index.esm.js +0 -17
  59. package/heuristics/dependencies/index.esm.js.map +1 -1
  60. package/heuristics/entry-points/discover.d.ts +34 -7
  61. package/heuristics/entry-points/discover.d.ts.map +1 -1
  62. package/heuristics/entry-points/index.cjs.js +6 -34
  63. package/heuristics/entry-points/index.cjs.js.map +1 -1
  64. package/heuristics/entry-points/index.esm.js +6 -34
  65. package/heuristics/entry-points/index.esm.js.map +1 -1
  66. package/heuristics/framework/index.cjs.js +1 -63
  67. package/heuristics/framework/index.cjs.js.map +1 -1
  68. package/heuristics/framework/index.esm.js +1 -63
  69. package/heuristics/framework/index.esm.js.map +1 -1
  70. package/heuristics/index.cjs.js +7 -88
  71. package/heuristics/index.cjs.js.map +1 -1
  72. package/heuristics/index.esm.js +7 -88
  73. package/heuristics/index.esm.js.map +1 -1
  74. package/heuristics/project-type/index.cjs.js +1 -63
  75. package/heuristics/project-type/index.cjs.js.map +1 -1
  76. package/heuristics/project-type/index.esm.js +1 -63
  77. package/heuristics/project-type/index.esm.js.map +1 -1
  78. package/index.cjs.js +86 -294
  79. package/index.cjs.js.map +1 -1
  80. package/index.esm.js +86 -294
  81. package/index.esm.js.map +1 -1
  82. package/nx/detect.d.ts.map +1 -1
  83. package/nx/devkit-loader.d.ts.map +1 -1
  84. package/nx/index.cjs.js +0 -29
  85. package/nx/index.cjs.js.map +1 -1
  86. package/nx/index.esm.js +0 -29
  87. package/nx/index.esm.js.map +1 -1
  88. package/nx/project-config.d.ts +2 -0
  89. package/nx/project-config.d.ts.map +1 -1
  90. package/package.json +9 -9
  91. package/project/config/index.cjs.js +4 -46
  92. package/project/config/index.cjs.js.map +1 -1
  93. package/project/config/index.esm.js +4 -46
  94. package/project/config/index.esm.js.map +1 -1
  95. package/project/config/patterns.d.ts.map +1 -1
  96. package/project/index.cjs.js +4 -47
  97. package/project/index.cjs.js.map +1 -1
  98. package/project/index.esm.js +4 -47
  99. package/project/index.esm.js.map +1 -1
  100. package/project/package/index.cjs.js +0 -11
  101. package/project/package/index.cjs.js.map +1 -1
  102. package/project/package/index.esm.js +0 -11
  103. package/project/package/index.esm.js.map +1 -1
  104. package/project/package/read.d.ts +1 -0
  105. package/project/package/read.d.ts.map +1 -1
  106. package/project/root/index.cjs.js +0 -11
  107. package/project/root/index.cjs.js.map +1 -1
  108. package/project/root/index.esm.js +0 -11
  109. package/project/root/index.esm.js.map +1 -1
  110. package/project/traversal/index.cjs.js +4 -28
  111. package/project/traversal/index.cjs.js.map +1 -1
  112. package/project/traversal/index.esm.js +4 -28
  113. package/project/traversal/index.esm.js.map +1 -1
  114. package/tech/backend/express.d.ts.map +1 -1
  115. package/tech/backend/fastify.d.ts.map +1 -1
  116. package/tech/backend/index.cjs.js +0 -17
  117. package/tech/backend/index.cjs.js.map +1 -1
  118. package/tech/backend/index.esm.js +0 -17
  119. package/tech/backend/index.esm.js.map +1 -1
  120. package/tech/backend/koa.d.ts.map +1 -1
  121. package/tech/backend/nestjs.d.ts.map +1 -1
  122. package/tech/build/index.cjs.js +0 -12
  123. package/tech/build/index.cjs.js.map +1 -1
  124. package/tech/build/index.esm.js +0 -12
  125. package/tech/build/index.esm.js.map +1 -1
  126. package/tech/frontend/index.cjs.js +0 -16
  127. package/tech/frontend/index.cjs.js.map +1 -1
  128. package/tech/frontend/index.esm.js +0 -16
  129. package/tech/frontend/index.esm.js.map +1 -1
  130. package/tech/frontend/qwik.d.ts.map +1 -1
  131. package/tech/frontend/remix.d.ts.map +1 -1
  132. package/tech/frontend/sveltekit.d.ts.map +1 -1
  133. package/tech/index.cjs.js +1 -63
  134. package/tech/index.cjs.js.map +1 -1
  135. package/tech/index.d.ts.map +1 -1
  136. package/tech/index.esm.js +1 -63
  137. package/tech/index.esm.js.map +1 -1
  138. package/tech/legacy/angularjs.d.ts.map +1 -1
  139. package/tech/legacy/backbone.d.ts.map +1 -1
  140. package/tech/legacy/ember.d.ts.map +1 -1
  141. package/tech/legacy/index.cjs.js +0 -26
  142. package/tech/legacy/index.cjs.js.map +1 -1
  143. package/tech/legacy/index.esm.js +0 -26
  144. package/tech/legacy/index.esm.js.map +1 -1
  145. package/tech/legacy/jquery.d.ts.map +1 -1
  146. package/tech/linting/biome.d.ts.map +1 -1
  147. package/tech/linting/index.cjs.js +0 -14
  148. package/tech/linting/index.cjs.js.map +1 -1
  149. package/tech/linting/index.esm.js +0 -14
  150. package/tech/linting/index.esm.js.map +1 -1
  151. package/tech/linting/prettier.d.ts.map +1 -1
  152. package/tech/monorepo/index.cjs.js +1 -13
  153. package/tech/monorepo/index.cjs.js.map +1 -1
  154. package/tech/monorepo/index.esm.js +1 -13
  155. package/tech/monorepo/index.esm.js.map +1 -1
  156. package/tech/monorepo/types.d.ts +1 -1
  157. package/tech/monorepo/types.d.ts.map +1 -1
  158. package/tech/shared-utils/detector-helpers.d.ts.map +1 -1
  159. package/tech/testing/index.cjs.js +0 -12
  160. package/tech/testing/index.cjs.js.map +1 -1
  161. package/tech/testing/index.esm.js +0 -12
  162. package/tech/testing/index.esm.js.map +1 -1
  163. package/tech/types/detectors.d.ts.map +1 -1
  164. package/tech/types/index.cjs.js +0 -27
  165. package/tech/types/index.cjs.js.map +1 -1
  166. package/tech/types/index.esm.js +0 -27
  167. package/tech/types/index.esm.js.map +1 -1
  168. package/vfs/commit.d.ts.map +1 -1
  169. package/vfs/diff.d.ts.map +1 -1
  170. package/vfs/factory.d.ts.map +1 -1
  171. package/vfs/fs-tree.d.ts.map +1 -1
  172. package/vfs/index.cjs.js +5 -46
  173. package/vfs/index.cjs.js.map +1 -1
  174. package/vfs/index.esm.js +5 -46
  175. package/vfs/index.esm.js.map +1 -1
  176. package/vfs/types.d.ts +1 -0
  177. package/vfs/types.d.ts.map +1 -1
@@ -11,7 +11,6 @@ var node_fs = require('node:fs');
11
11
  *
12
12
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/json
13
13
  */
14
- // Capture references at module initialization time
15
14
  const _JSON = globalThis.JSON;
16
15
  /**
17
16
  * (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
@@ -30,7 +29,6 @@ const stringify = _JSON.stringify;
30
29
  *
31
30
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/math
32
31
  */
33
- // Capture references at module initialization time
34
32
  const _Math = globalThis.Math;
35
33
  /**
36
34
  * (Safe copy) Returns the value of a number rounded to the nearest integer.
@@ -49,7 +47,6 @@ const min = _Math.min;
49
47
  *
50
48
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/object
51
49
  */
52
- // Capture references at module initialization time
53
50
  const _Object = globalThis.Object;
54
51
  /**
55
52
  * (Safe copy) Prevents modification of existing property attributes and values,
@@ -84,7 +81,6 @@ const defineProperties = _Object.defineProperties;
84
81
  *
85
82
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/error
86
83
  */
87
- // Capture references at module initialization time
88
84
  const _Error = globalThis.Error;
89
85
  const _Reflect$2 = globalThis.Reflect;
90
86
  /**
@@ -105,7 +101,6 @@ const createError = (message, options) => _Reflect$2.construct(_Error, [message,
105
101
  *
106
102
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/array
107
103
  */
108
- // Capture references at module initialization time
109
104
  const _Array = globalThis.Array;
110
105
  /**
111
106
  * (Safe copy) Determines whether the passed value is an Array.
@@ -120,7 +115,6 @@ const isArray = _Array.isArray;
120
115
  *
121
116
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/console
122
117
  */
123
- // Capture references at module initialization time
124
118
  const _console = globalThis.console;
125
119
  /**
126
120
  * (Safe copy) Outputs a message to the console.
@@ -206,7 +200,6 @@ _console.timeLog.bind(_console);
206
200
  *
207
201
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/set
208
202
  */
209
- // Capture references at module initialization time
210
203
  const _Set = globalThis.Set;
211
204
  const _Reflect$1 = globalThis.Reflect;
212
205
  /**
@@ -254,7 +247,6 @@ const getType = (target) => {
254
247
  *
255
248
  * @module @hyperfrontend/immutable-api-utils/built-in-copy/map
256
249
  */
257
- // Capture references at module initialization time
258
250
  const _Map = globalThis.Map;
259
251
  const _Reflect = globalThis.Reflect;
260
252
  /**
@@ -532,14 +524,11 @@ function formatMessage(namespace, message, meta) {
532
524
  */
533
525
  function createScopedLogger(namespace, options = {}) {
534
526
  const { level = 'error', sanitizeSecrets = true } = options;
535
- // Create wrapper functions that add namespace prefix and sanitization
536
527
  const createLogFn = (baseFn) => (message, meta) => {
537
528
  const processedMeta = sanitizeSecrets && meta ? sanitize(meta) : meta;
538
529
  baseFn(formatMessage(namespace, message, processedMeta));
539
530
  };
540
- // Create base logger with wrapped functions
541
531
  const baseLogger = createLogger(createLogFn(error), createLogFn(warn), createLogFn(log), createLogFn(info), createLogFn(debug));
542
- // Set initial log level (use global override if set)
543
532
  baseLogger.setLogLevel(level);
544
533
  const scopedLogger = freeze({
545
534
  error: (message, meta) => baseLogger.error(message, meta),
@@ -550,7 +539,6 @@ function createScopedLogger(namespace, options = {}) {
550
539
  setLogLevel: baseLogger.setLogLevel,
551
540
  getLogLevel: baseLogger.getLogLevel,
552
541
  });
553
- // Register logger for global level management
554
542
  loggerRegistry.add(scopedLogger);
555
543
  return scopedLogger;
556
544
  }
@@ -881,7 +869,6 @@ const cacheRegistry = createSet();
881
869
  function createCache(options) {
882
870
  const { ttl, maxSize } = options ?? {};
883
871
  const store = createMap();
884
- // Track insertion order for FIFO eviction
885
872
  const insertionOrder = [];
886
873
  /**
887
874
  * Check if an entry is expired.
@@ -932,12 +919,10 @@ function createCache(options) {
932
919
  return entry.value;
933
920
  },
934
921
  set(key, value) {
935
- // If key exists, remove from order first
936
922
  if (store.has(key)) {
937
923
  removeFromOrder(key);
938
924
  }
939
925
  else {
940
- // Evict if needed before adding new entry
941
926
  evictIfNeeded();
942
927
  }
943
928
  // eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
@@ -970,7 +955,6 @@ function createCache(options) {
970
955
  return [...insertionOrder];
971
956
  },
972
957
  };
973
- // Register cache for global operations
974
958
  cacheRegistry.add(cache);
975
959
  return freeze(cache);
976
960
  }
@@ -1001,7 +985,6 @@ function collectAllDependencies(packageJson) {
1001
985
  function parseVersionString(versionString) {
1002
986
  if (versionString === undefined || versionString === null)
1003
987
  return undefined;
1004
- // Manual parsing instead of regex to avoid ReDoS
1005
988
  let start = 0;
1006
989
  while (start < versionString.length) {
1007
990
  const char = versionString[start];
@@ -1062,7 +1045,6 @@ function expressDetector(projectPath, packageJson) {
1062
1045
  version = parseVersionString(deps['express']);
1063
1046
  sources.push({ type: 'package.json', field: 'dependencies.express' });
1064
1047
  }
1065
- // @types/express (indicates usage)
1066
1048
  if (deps['@types/express']) {
1067
1049
  confidence += 10;
1068
1050
  sources.push({ type: 'package.json', field: 'dependencies.@types/express' });
@@ -1098,13 +1080,11 @@ function nestDetector(projectPath, packageJson) {
1098
1080
  let version;
1099
1081
  let configPath;
1100
1082
  const deps = collectAllDependencies(pkg);
1101
- // @nestjs/core package
1102
1083
  if (deps['@nestjs/core']) {
1103
1084
  confidence += 70;
1104
1085
  version = parseVersionString(deps['@nestjs/core']);
1105
1086
  sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
1106
1087
  }
1107
- // @nestjs/common
1108
1088
  if (deps['@nestjs/common']) {
1109
1089
  confidence += 15;
1110
1090
  sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
@@ -1155,7 +1135,6 @@ function fastifyDetector(projectPath, packageJson) {
1155
1135
  confidence += 15;
1156
1136
  sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
1157
1137
  }
1158
- // @types/fastify (older versions)
1159
1138
  if (deps['@types/fastify']) {
1160
1139
  confidence += 5;
1161
1140
  sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
@@ -1190,7 +1169,6 @@ function koaDetector(projectPath, packageJson) {
1190
1169
  version = parseVersionString(deps['koa']);
1191
1170
  sources.push({ type: 'package.json', field: 'dependencies.koa' });
1192
1171
  }
1193
- // @types/koa
1194
1172
  if (deps['@types/koa']) {
1195
1173
  confidence += 10;
1196
1174
  sources.push({ type: 'package.json', field: 'dependencies.@types/koa' });
@@ -1733,7 +1711,6 @@ function remixDetector(projectPath, packageJson) {
1733
1711
  let confidence = 0;
1734
1712
  let version;
1735
1713
  const deps = collectAllDependencies(pkg);
1736
- // @remix-run packages
1737
1714
  if (deps['@remix-run/react']) {
1738
1715
  confidence += 70;
1739
1716
  version = parseVersionString(deps['@remix-run/react']);
@@ -2009,7 +1986,6 @@ function sveltekitDetector(projectPath, packageJson) {
2009
1986
  let confidence = 0;
2010
1987
  let version;
2011
1988
  const deps = collectAllDependencies(pkg);
2012
- // @sveltejs/kit package
2013
1989
  if (deps['@sveltejs/kit']) {
2014
1990
  confidence += 70;
2015
1991
  version = parseVersionString(deps['@sveltejs/kit']);
@@ -2088,13 +2064,11 @@ function qwikDetector(projectPath, packageJson) {
2088
2064
  let confidence = 0;
2089
2065
  let version;
2090
2066
  const deps = collectAllDependencies(pkg);
2091
- // @builder.io/qwik package
2092
2067
  if (deps['@builder.io/qwik']) {
2093
2068
  confidence += 70;
2094
2069
  version = parseVersionString(deps['@builder.io/qwik']);
2095
2070
  sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
2096
2071
  }
2097
- // @builder.io/qwik-city
2098
2072
  if (deps['@builder.io/qwik-city']) {
2099
2073
  confidence += 20;
2100
2074
  sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
@@ -2187,23 +2161,19 @@ function angularJSDetector(projectPath, packageJson) {
2187
2161
  let confidence = 0;
2188
2162
  let version;
2189
2163
  const deps = collectAllDependencies(pkg);
2190
- // AngularJS package (angular, not @angular/core)
2191
2164
  if (deps['angular']) {
2192
2165
  confidence += 70;
2193
2166
  version = parseVersionString(deps['angular']);
2194
2167
  sources.push({ type: 'package.json', field: 'dependencies.angular' });
2195
2168
  }
2196
- // AngularJS router
2197
2169
  if (deps['angular-route']) {
2198
2170
  confidence += 15;
2199
2171
  sources.push({ type: 'package.json', field: 'dependencies.angular-route' });
2200
2172
  }
2201
- // AngularJS resource
2202
2173
  if (deps['angular-resource']) {
2203
2174
  confidence += 10;
2204
2175
  sources.push({ type: 'package.json', field: 'dependencies.angular-resource' });
2205
2176
  }
2206
- // AngularJS animate
2207
2177
  if (deps['angular-animate']) {
2208
2178
  confidence += 5;
2209
2179
  sources.push({ type: 'package.json', field: 'dependencies.angular-animate' });
@@ -2234,23 +2204,19 @@ function backboneDetector(projectPath, packageJson) {
2234
2204
  let confidence = 0;
2235
2205
  let version;
2236
2206
  const deps = collectAllDependencies(pkg);
2237
- // Backbone package
2238
2207
  if (deps['backbone']) {
2239
2208
  confidence += 70;
2240
2209
  version = parseVersionString(deps['backbone']);
2241
2210
  sources.push({ type: 'package.json', field: 'dependencies.backbone' });
2242
- // Underscore (commonly used with Backbone)
2243
2211
  if (deps['underscore']) {
2244
2212
  confidence += 15;
2245
2213
  sources.push({ type: 'package.json', field: 'dependencies.underscore' });
2246
2214
  }
2247
- // Lodash can be used as underscore replacement
2248
2215
  if (deps['lodash']) {
2249
2216
  confidence += 5;
2250
2217
  sources.push({ type: 'package.json', field: 'dependencies.lodash' });
2251
2218
  }
2252
2219
  }
2253
- // Marionette (Backbone framework)
2254
2220
  if (deps['backbone.marionette'] || deps['marionette']) {
2255
2221
  confidence += 10;
2256
2222
  sources.push({ type: 'package.json', field: 'dependencies.backbone.marionette' });
@@ -2281,18 +2247,15 @@ function emberDetector(projectPath, packageJson) {
2281
2247
  let confidence = 0;
2282
2248
  let version;
2283
2249
  const deps = collectAllDependencies(pkg);
2284
- // Ember source package
2285
2250
  if (deps['ember-source']) {
2286
2251
  confidence += 70;
2287
2252
  version = parseVersionString(deps['ember-source']);
2288
2253
  sources.push({ type: 'package.json', field: 'dependencies.ember-source' });
2289
2254
  }
2290
- // Ember CLI
2291
2255
  if (deps['ember-cli']) {
2292
2256
  confidence += 20;
2293
2257
  sources.push({ type: 'package.json', field: 'devDependencies.ember-cli' });
2294
2258
  }
2295
- // Ember Data
2296
2259
  if (deps['ember-data']) {
2297
2260
  confidence += 10;
2298
2261
  sources.push({ type: 'package.json', field: 'dependencies.ember-data' });
@@ -2323,18 +2286,15 @@ function jqueryDetector(projectPath, packageJson) {
2323
2286
  let confidence = 0;
2324
2287
  let version;
2325
2288
  const deps = collectAllDependencies(pkg);
2326
- // jQuery package
2327
2289
  if (deps['jquery']) {
2328
2290
  confidence += 80;
2329
2291
  version = parseVersionString(deps['jquery']);
2330
2292
  sources.push({ type: 'package.json', field: 'dependencies.jquery' });
2331
2293
  }
2332
- // jQuery UI
2333
2294
  if (deps['jquery-ui']) {
2334
2295
  confidence += 10;
2335
2296
  sources.push({ type: 'package.json', field: 'dependencies.jquery-ui' });
2336
2297
  }
2337
- // jQuery plugins
2338
2298
  if (deps['jquery-validation']) {
2339
2299
  confidence += 5;
2340
2300
  sources.push({ type: 'package.json', field: 'dependencies.jquery-validation' });
@@ -2463,7 +2423,6 @@ function prettierDetector(projectPath, packageJson) {
2463
2423
  confidence += 30;
2464
2424
  sources.push({ type: 'package.json', field: 'prettier' });
2465
2425
  }
2466
- // .prettierignore file
2467
2426
  if (exists(node_path.join(projectPath, '.prettierignore'))) {
2468
2427
  confidence += 10;
2469
2428
  sources.push({ type: 'config-file', path: '.prettierignore' });
@@ -2558,7 +2517,6 @@ function biomeDetector(projectPath, packageJson) {
2558
2517
  let configPath;
2559
2518
  let version;
2560
2519
  const deps = collectAllDependencies(pkg);
2561
- // @biomejs/biome package
2562
2520
  if (deps['@biomejs/biome']) {
2563
2521
  confidence += 70;
2564
2522
  version = parseVersionString(deps['@biomejs/biome']);
@@ -2827,7 +2785,7 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
2827
2785
  sources.push({ type: 'lockfile', path: 'package-lock.json' });
2828
2786
  }
2829
2787
  if (exists(node_path.join(workspacePath, 'yarn.lock'))) {
2830
- return null; // Let yarn workspace detector handle this
2788
+ return null;
2831
2789
  }
2832
2790
  if (confidence === 0) {
2833
2791
  return null;
@@ -3170,7 +3128,6 @@ function checkTsConfigStrict(projectPath) {
3170
3128
  if (!content)
3171
3129
  return undefined;
3172
3130
  try {
3173
- // Simple JSON parsing - doesn't handle comments but good enough for strict check
3174
3131
  const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
3175
3132
  const parsed = parse(cleanContent);
3176
3133
  return parsed?.compilerOptions?.strict === true;
@@ -3193,19 +3150,16 @@ function typescriptDetector(projectPath, packageJson) {
3193
3150
  let configPath;
3194
3151
  let version;
3195
3152
  const deps = collectAllDependencies(pkg);
3196
- // TypeScript package
3197
3153
  if (deps['typescript']) {
3198
3154
  confidence += 50;
3199
3155
  version = parseVersionString(deps['typescript']);
3200
3156
  sources.push({ type: 'package.json', field: 'dependencies.typescript' });
3201
3157
  }
3202
- // tsconfig.json
3203
3158
  if (exists(node_path.join(projectPath, 'tsconfig.json'))) {
3204
3159
  confidence += 40;
3205
3160
  configPath = 'tsconfig.json';
3206
3161
  sources.push({ type: 'config-file', path: 'tsconfig.json' });
3207
3162
  }
3208
- // tsconfig.*.json variants
3209
3163
  const tsconfigVariants = ['tsconfig.build.json', 'tsconfig.lib.json', 'tsconfig.spec.json', 'tsconfig.app.json'];
3210
3164
  for (const variant of tsconfigVariants) {
3211
3165
  if (exists(node_path.join(projectPath, variant))) {
@@ -3214,7 +3168,6 @@ function typescriptDetector(projectPath, packageJson) {
3214
3168
  break;
3215
3169
  }
3216
3170
  }
3217
- // @types packages
3218
3171
  const typePackages = keys(deps).filter((d) => d.startsWith('@types/'));
3219
3172
  if (typePackages.length > 0) {
3220
3173
  confidence += 10;
@@ -3248,24 +3201,20 @@ function flowDetector(projectPath, packageJson) {
3248
3201
  let configPath;
3249
3202
  let version;
3250
3203
  const deps = collectAllDependencies(pkg);
3251
- // flow-bin package
3252
3204
  if (deps['flow-bin']) {
3253
3205
  confidence += 60;
3254
3206
  version = parseVersionString(deps['flow-bin']);
3255
3207
  sources.push({ type: 'package.json', field: 'dependencies.flow-bin' });
3256
3208
  }
3257
- // .flowconfig
3258
3209
  if (exists(node_path.join(projectPath, '.flowconfig'))) {
3259
3210
  confidence += 40;
3260
3211
  configPath = '.flowconfig';
3261
3212
  sources.push({ type: 'config-file', path: '.flowconfig' });
3262
3213
  }
3263
- // flow-typed directory
3264
3214
  if (exists(node_path.join(projectPath, 'flow-typed'))) {
3265
3215
  confidence += 10;
3266
3216
  sources.push({ type: 'directory', path: 'flow-typed/' });
3267
3217
  }
3268
- // @babel/preset-flow
3269
3218
  if (deps['@babel/preset-flow']) {
3270
3219
  confidence += 10;
3271
3220
  sources.push({ type: 'package.json', field: 'dependencies.@babel/preset-flow' });
@@ -3289,7 +3238,6 @@ function flowDetector(projectPath, packageJson) {
3289
3238
  * @returns `true` if the content contains JSDoc type annotations.
3290
3239
  */
3291
3240
  function hasJsDocTypes(content) {
3292
- // Check for JSDoc type annotations
3293
3241
  return (content.includes('@type {') ||
3294
3242
  content.includes('@param {') ||
3295
3243
  content.includes('@returns {') ||
@@ -3308,14 +3256,11 @@ function jsdocDetector(projectPath, packageJson) {
3308
3256
  const sources = [];
3309
3257
  let confidence = 0;
3310
3258
  const deps = collectAllDependencies(pkg);
3311
- // jsdoc package
3312
3259
  if (deps['jsdoc']) {
3313
3260
  confidence += 30;
3314
3261
  sources.push({ type: 'package.json', field: 'dependencies.jsdoc' });
3315
3262
  }
3316
- // typescript with checkJs (JSDoc type checking)
3317
3263
  if (deps['typescript']) {
3318
- // Check if checkJs is enabled in tsconfig
3319
3264
  const tsconfigPath = node_path.join(projectPath, 'tsconfig.json');
3320
3265
  const content = readFileIfExists(tsconfigPath);
3321
3266
  if (content) {
@@ -3332,12 +3277,10 @@ function jsdocDetector(projectPath, packageJson) {
3332
3277
  }
3333
3278
  }
3334
3279
  }
3335
- // Check for jsconfig.json (VS Code JS type checking)
3336
3280
  if (exists(node_path.join(projectPath, 'jsconfig.json'))) {
3337
3281
  confidence += 40;
3338
3282
  sources.push({ type: 'config-file', path: 'jsconfig.json' });
3339
3283
  }
3340
- // Sample check for JSDoc annotations in source files
3341
3284
  const srcDir = node_path.join(projectPath, 'src');
3342
3285
  if (exists(srcDir)) {
3343
3286
  try {
@@ -3388,8 +3331,6 @@ const detectAllCache = createCache({ ttl: 60000, maxSize: 50 });
3388
3331
  function isDetectAllOptions(value) {
3389
3332
  if (typeof value !== 'object' || value === null)
3390
3333
  return false;
3391
- // DetectAllOptions has skipCache or packageJson fields specifically
3392
- // PackageJson never has skipCache field
3393
3334
  return 'skipCache' in value || 'packageJson' in value;
3394
3335
  }
3395
3336
  /**
@@ -3421,9 +3362,7 @@ function isDetectAllOptions(value) {
3421
3362
  * ```
3422
3363
  */
3423
3364
  function detectAll(projectPath, packageJsonOrOptions) {
3424
- // Handle backward-compatible arguments
3425
3365
  const options = isDetectAllOptions(packageJsonOrOptions) ? packageJsonOrOptions : { packageJson: packageJsonOrOptions };
3426
- // Check cache first (unless skipCache is true)
3427
3366
  if (!options.skipCache) {
3428
3367
  const cached = detectAllCache.get(projectPath);
3429
3368
  if (cached) {
@@ -3474,7 +3413,6 @@ function detectAll(projectPath, packageJsonOrOptions) {
3474
3413
  legacyFrameworks: result.legacyFrameworks.map((f) => f.id),
3475
3414
  testingFrameworks: result.testingFrameworks.map((f) => f.id),
3476
3415
  });
3477
- // Cache the result
3478
3416
  detectAllCache.set(projectPath, result);
3479
3417
  return result;
3480
3418
  }
@@ -3844,10 +3782,6 @@ function usesFramework(projectPath, frameworkId, minConfidence = 50) {
3844
3782
  return allFrameworks.some((f) => f.id === frameworkId && f.confidence >= minConfidence);
3845
3783
  }
3846
3784
 
3847
- /**
3848
- * Pattern matching utilities with ReDoS protection.
3849
- * Uses character-by-character matching instead of regex where possible.
3850
- */
3851
3785
  /**
3852
3786
  * Match path against glob pattern using safe character iteration.
3853
3787
  * Avoids regex to prevent ReDoS attacks.
@@ -3885,17 +3819,14 @@ function matchGlobPattern(path, pattern) {
3885
3819
  * @returns True if remaining segments match
3886
3820
  */
3887
3821
  function matchSegments(pathParts, patternParts, pathIdx, patternIdx) {
3888
- // Base cases
3889
3822
  if (pathIdx === pathParts.length && patternIdx === patternParts.length) {
3890
- return true; // Both exhausted = match
3823
+ return true;
3891
3824
  }
3892
3825
  if (patternIdx >= patternParts.length) {
3893
- return false; // Pattern exhausted but path remains
3826
+ return false;
3894
3827
  }
3895
3828
  const patternPart = patternParts[patternIdx];
3896
- // Handle ** (globstar) - matches zero or more directories
3897
3829
  if (patternPart === '**') {
3898
- // Try matching rest of pattern against current position and all future positions
3899
3830
  for (let i = pathIdx; i <= pathParts.length; i++) {
3900
3831
  if (matchSegments(pathParts, patternParts, i, patternIdx + 1)) {
3901
3832
  return true;
@@ -3904,10 +3835,9 @@ function matchSegments(pathParts, patternParts, pathIdx, patternIdx) {
3904
3835
  return false;
3905
3836
  }
3906
3837
  if (pathIdx >= pathParts.length) {
3907
- return false; // Path exhausted but pattern remains (and it's not **)
3838
+ return false;
3908
3839
  }
3909
3840
  const pathPart = pathParts[pathIdx];
3910
- // Match current segment
3911
3841
  if (matchSegment(pathPart, patternPart)) {
3912
3842
  return matchSegments(pathParts, patternParts, pathIdx + 1, patternIdx + 1);
3913
3843
  }
@@ -3927,12 +3857,10 @@ function matchSegment(text, pattern) {
3927
3857
  while (patternIdx < pattern.length) {
3928
3858
  const char = pattern[patternIdx];
3929
3859
  if (char === '*') {
3930
- // * matches zero or more characters
3931
3860
  patternIdx++;
3932
3861
  if (patternIdx === pattern.length) {
3933
- return true; // * at end matches rest of string
3862
+ return true;
3934
3863
  }
3935
- // Try matching rest of pattern at each position in text
3936
3864
  for (let i = textIdx; i <= text.length; i++) {
3937
3865
  if (matchSegmentFrom(text, i, pattern, patternIdx)) {
3938
3866
  return true;
@@ -3941,7 +3869,6 @@ function matchSegment(text, pattern) {
3941
3869
  return false;
3942
3870
  }
3943
3871
  else if (char === '?') {
3944
- // ? matches exactly one character
3945
3872
  if (textIdx >= text.length) {
3946
3873
  return false;
3947
3874
  }
@@ -3949,10 +3876,8 @@ function matchSegment(text, pattern) {
3949
3876
  patternIdx++;
3950
3877
  }
3951
3878
  else if (char === '{') {
3952
- // {a,b,c} matches any alternative
3953
3879
  const closeIdx = findClosingBrace(pattern, patternIdx);
3954
3880
  if (closeIdx === -1) {
3955
- // Unmatched brace, treat as literal
3956
3881
  if (textIdx >= text.length || text[textIdx] !== char) {
3957
3882
  return false;
3958
3883
  }
@@ -3970,7 +3895,6 @@ function matchSegment(text, pattern) {
3970
3895
  }
3971
3896
  }
3972
3897
  else {
3973
- // Literal character
3974
3898
  if (textIdx >= text.length || text[textIdx] !== char) {
3975
3899
  return false;
3976
3900
  }
@@ -4256,7 +4180,8 @@ const entryPointLogger = createScopedLogger('project-scope:heuristics:entry-poin
4256
4180
  */
4257
4181
  const entryPointCache = createCache({ ttl: 60000, maxSize: 50 });
4258
4182
  /**
4259
- * Common entry point patterns.
4183
+ * Common entry point patterns by project type.
4184
+ * Used for convention-based entry point discovery.
4260
4185
  */
4261
4186
  const ENTRY_POINT_PATTERNS = {
4262
4187
  /** Library entry patterns */
@@ -4522,29 +4447,23 @@ const depsLogger = createScopedLogger('project-scope:heuristics:deps');
4522
4447
  */
4523
4448
  function extractImports(content) {
4524
4449
  const imports = [];
4525
- // ES import with 'from': import X from 'path' or import { X } from 'path'
4526
- // Use non-greedy match and avoid nested quantifiers by matching "from" keyword directly
4527
4450
  const esImportFromRegex = /import\s+.+?\s+from\s+['"]([^'"]+)['"]/g;
4528
4451
  let match;
4529
4452
  while ((match = esImportFromRegex.exec(content)) !== null) {
4530
4453
  imports.push(match[1]);
4531
4454
  }
4532
- // Side-effect import: import 'path'
4533
4455
  const sideEffectImportRegex = /import\s+['"]([^'"]+)['"]/g;
4534
4456
  while ((match = sideEffectImportRegex.exec(content)) !== null) {
4535
4457
  imports.push(match[1]);
4536
4458
  }
4537
- // Dynamic import: import('path')
4538
4459
  const dynamicImportRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
4539
4460
  while ((match = dynamicImportRegex.exec(content)) !== null) {
4540
4461
  imports.push(match[1]);
4541
4462
  }
4542
- // require: require('path')
4543
4463
  const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
4544
4464
  while ((match = requireRegex.exec(content)) !== null) {
4545
4465
  imports.push(match[1]);
4546
4466
  }
4547
- // Re-export: export * from 'path' or export { X } from 'path'
4548
4467
  const exportFromRegex = /export\s+.+?\s+from\s+['"]([^'"]+)['"]/g;
4549
4468
  while ((match = exportFromRegex.exec(content)) !== null) {
4550
4469
  imports.push(match[1]);