@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.
- package/CHANGELOG.md +15 -3
- package/README.md +2 -0
- package/analyze.d.ts.map +1 -1
- package/cli/commands/analyze.d.ts +8 -0
- package/cli/commands/analyze.d.ts.map +1 -1
- package/cli/commands/config.d.ts +7 -0
- package/cli/commands/config.d.ts.map +1 -1
- package/cli/commands/deps.d.ts +6 -0
- package/cli/commands/deps.d.ts.map +1 -1
- package/cli/commands/tree.d.ts +12 -0
- package/cli/commands/tree.d.ts.map +1 -1
- package/cli/index.cjs.js +73 -206
- package/cli/index.cjs.js.map +1 -1
- package/cli/index.esm.js +73 -206
- package/cli/index.esm.js.map +1 -1
- package/cli/run.d.ts.map +1 -1
- package/core/cache.d.ts +1 -0
- package/core/cache.d.ts.map +1 -1
- package/core/encoding/convert.d.ts.map +1 -1
- package/core/encoding/detect.d.ts +5 -0
- package/core/encoding/detect.d.ts.map +1 -1
- package/core/encoding/index.cjs.js +2 -23
- package/core/encoding/index.cjs.js.map +1 -1
- package/core/encoding/index.esm.js +2 -23
- package/core/encoding/index.esm.js.map +1 -1
- package/core/errors/structured-errors.d.ts +2 -0
- package/core/errors/structured-errors.d.ts.map +1 -1
- package/core/fs/directory.d.ts +3 -0
- package/core/fs/directory.d.ts.map +1 -1
- package/core/fs/index.cjs.js +0 -14
- package/core/fs/index.cjs.js.map +1 -1
- package/core/fs/index.esm.js +0 -14
- package/core/fs/index.esm.js.map +1 -1
- package/core/fs/read.d.ts +11 -3
- package/core/fs/read.d.ts.map +1 -1
- package/core/fs/traversal.d.ts.map +1 -1
- package/core/index.cjs.js +11 -63
- package/core/index.cjs.js.map +1 -1
- package/core/index.esm.js +11 -63
- package/core/index.esm.js.map +1 -1
- package/core/logger.d.ts.map +1 -1
- package/core/path/index.cjs.js +5 -2
- package/core/path/index.cjs.js.map +1 -1
- package/core/path/index.esm.js +5 -2
- package/core/path/index.esm.js.map +1 -1
- package/core/path/normalize.d.ts.map +1 -1
- package/core/patterns/glob.d.ts +0 -4
- package/core/patterns/glob.d.ts.map +1 -1
- package/core/platform/detect.d.ts.map +1 -1
- package/core/platform/index.cjs.js +0 -10
- package/core/platform/index.cjs.js.map +1 -1
- package/core/platform/index.esm.js +0 -10
- package/core/platform/index.esm.js.map +1 -1
- package/core/platform/line-endings.d.ts.map +1 -1
- package/heuristics/dependencies/analyze.d.ts.map +1 -1
- package/heuristics/dependencies/index.cjs.js +0 -17
- package/heuristics/dependencies/index.cjs.js.map +1 -1
- package/heuristics/dependencies/index.esm.js +0 -17
- package/heuristics/dependencies/index.esm.js.map +1 -1
- package/heuristics/entry-points/discover.d.ts +34 -7
- package/heuristics/entry-points/discover.d.ts.map +1 -1
- package/heuristics/entry-points/index.cjs.js +6 -34
- package/heuristics/entry-points/index.cjs.js.map +1 -1
- package/heuristics/entry-points/index.esm.js +6 -34
- package/heuristics/entry-points/index.esm.js.map +1 -1
- package/heuristics/framework/index.cjs.js +1 -63
- package/heuristics/framework/index.cjs.js.map +1 -1
- package/heuristics/framework/index.esm.js +1 -63
- package/heuristics/framework/index.esm.js.map +1 -1
- package/heuristics/index.cjs.js +7 -88
- package/heuristics/index.cjs.js.map +1 -1
- package/heuristics/index.esm.js +7 -88
- package/heuristics/index.esm.js.map +1 -1
- package/heuristics/project-type/index.cjs.js +1 -63
- package/heuristics/project-type/index.cjs.js.map +1 -1
- package/heuristics/project-type/index.esm.js +1 -63
- package/heuristics/project-type/index.esm.js.map +1 -1
- package/index.cjs.js +86 -294
- package/index.cjs.js.map +1 -1
- package/index.esm.js +86 -294
- package/index.esm.js.map +1 -1
- package/nx/detect.d.ts.map +1 -1
- package/nx/devkit-loader.d.ts.map +1 -1
- package/nx/index.cjs.js +0 -29
- package/nx/index.cjs.js.map +1 -1
- package/nx/index.esm.js +0 -29
- package/nx/index.esm.js.map +1 -1
- package/nx/project-config.d.ts +2 -0
- package/nx/project-config.d.ts.map +1 -1
- package/package.json +9 -9
- package/project/config/index.cjs.js +4 -46
- package/project/config/index.cjs.js.map +1 -1
- package/project/config/index.esm.js +4 -46
- package/project/config/index.esm.js.map +1 -1
- package/project/config/patterns.d.ts.map +1 -1
- package/project/index.cjs.js +4 -47
- package/project/index.cjs.js.map +1 -1
- package/project/index.esm.js +4 -47
- package/project/index.esm.js.map +1 -1
- package/project/package/index.cjs.js +0 -11
- package/project/package/index.cjs.js.map +1 -1
- package/project/package/index.esm.js +0 -11
- package/project/package/index.esm.js.map +1 -1
- package/project/package/read.d.ts +1 -0
- package/project/package/read.d.ts.map +1 -1
- package/project/root/index.cjs.js +0 -11
- package/project/root/index.cjs.js.map +1 -1
- package/project/root/index.esm.js +0 -11
- package/project/root/index.esm.js.map +1 -1
- package/project/traversal/index.cjs.js +4 -28
- package/project/traversal/index.cjs.js.map +1 -1
- package/project/traversal/index.esm.js +4 -28
- package/project/traversal/index.esm.js.map +1 -1
- package/tech/backend/express.d.ts.map +1 -1
- package/tech/backend/fastify.d.ts.map +1 -1
- package/tech/backend/index.cjs.js +0 -17
- package/tech/backend/index.cjs.js.map +1 -1
- package/tech/backend/index.esm.js +0 -17
- package/tech/backend/index.esm.js.map +1 -1
- package/tech/backend/koa.d.ts.map +1 -1
- package/tech/backend/nestjs.d.ts.map +1 -1
- package/tech/build/index.cjs.js +0 -12
- package/tech/build/index.cjs.js.map +1 -1
- package/tech/build/index.esm.js +0 -12
- package/tech/build/index.esm.js.map +1 -1
- package/tech/frontend/index.cjs.js +0 -16
- package/tech/frontend/index.cjs.js.map +1 -1
- package/tech/frontend/index.esm.js +0 -16
- package/tech/frontend/index.esm.js.map +1 -1
- package/tech/frontend/qwik.d.ts.map +1 -1
- package/tech/frontend/remix.d.ts.map +1 -1
- package/tech/frontend/sveltekit.d.ts.map +1 -1
- package/tech/index.cjs.js +1 -63
- package/tech/index.cjs.js.map +1 -1
- package/tech/index.d.ts.map +1 -1
- package/tech/index.esm.js +1 -63
- package/tech/index.esm.js.map +1 -1
- package/tech/legacy/angularjs.d.ts.map +1 -1
- package/tech/legacy/backbone.d.ts.map +1 -1
- package/tech/legacy/ember.d.ts.map +1 -1
- package/tech/legacy/index.cjs.js +0 -26
- package/tech/legacy/index.cjs.js.map +1 -1
- package/tech/legacy/index.esm.js +0 -26
- package/tech/legacy/index.esm.js.map +1 -1
- package/tech/legacy/jquery.d.ts.map +1 -1
- package/tech/linting/biome.d.ts.map +1 -1
- package/tech/linting/index.cjs.js +0 -14
- package/tech/linting/index.cjs.js.map +1 -1
- package/tech/linting/index.esm.js +0 -14
- package/tech/linting/index.esm.js.map +1 -1
- package/tech/linting/prettier.d.ts.map +1 -1
- package/tech/monorepo/index.cjs.js +1 -13
- package/tech/monorepo/index.cjs.js.map +1 -1
- package/tech/monorepo/index.esm.js +1 -13
- package/tech/monorepo/index.esm.js.map +1 -1
- package/tech/monorepo/types.d.ts +1 -1
- package/tech/monorepo/types.d.ts.map +1 -1
- package/tech/shared-utils/detector-helpers.d.ts.map +1 -1
- package/tech/testing/index.cjs.js +0 -12
- package/tech/testing/index.cjs.js.map +1 -1
- package/tech/testing/index.esm.js +0 -12
- package/tech/testing/index.esm.js.map +1 -1
- package/tech/types/detectors.d.ts.map +1 -1
- package/tech/types/index.cjs.js +0 -27
- package/tech/types/index.cjs.js.map +1 -1
- package/tech/types/index.esm.js +0 -27
- package/tech/types/index.esm.js.map +1 -1
- package/vfs/commit.d.ts.map +1 -1
- package/vfs/diff.d.ts.map +1 -1
- package/vfs/factory.d.ts.map +1 -1
- package/vfs/fs-tree.d.ts.map +1 -1
- package/vfs/index.cjs.js +5 -46
- package/vfs/index.cjs.js.map +1 -1
- package/vfs/index.esm.js +5 -46
- package/vfs/index.esm.js.map +1 -1
- package/vfs/types.d.ts +1 -0
- package/vfs/types.d.ts.map +1 -1
package/cli/index.esm.js
CHANGED
|
@@ -10,7 +10,6 @@ import { existsSync, readFileSync, statSync, lstatSync, readdirSync } from 'node
|
|
|
10
10
|
*
|
|
11
11
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/console
|
|
12
12
|
*/
|
|
13
|
-
// Capture references at module initialization time
|
|
14
13
|
const _console = globalThis.console;
|
|
15
14
|
/**
|
|
16
15
|
* (Safe copy) Outputs a message to the console.
|
|
@@ -85,40 +84,6 @@ _console.timeEnd.bind(_console);
|
|
|
85
84
|
*/
|
|
86
85
|
_console.timeLog.bind(_console);
|
|
87
86
|
|
|
88
|
-
/**
|
|
89
|
-
* Safe copies of Array built-in static methods.
|
|
90
|
-
*
|
|
91
|
-
* These references are captured at module initialization time to protect against
|
|
92
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
93
|
-
*
|
|
94
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
95
|
-
*/
|
|
96
|
-
// Capture references at module initialization time
|
|
97
|
-
const _Array = globalThis.Array;
|
|
98
|
-
/**
|
|
99
|
-
* (Safe copy) Determines whether the passed value is an Array.
|
|
100
|
-
*/
|
|
101
|
-
const isArray = _Array.isArray;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Safe copies of JSON built-in methods.
|
|
105
|
-
*
|
|
106
|
-
* These references are captured at module initialization time to protect against
|
|
107
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
108
|
-
*
|
|
109
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/json
|
|
110
|
-
*/
|
|
111
|
-
// Capture references at module initialization time
|
|
112
|
-
const _JSON = globalThis.JSON;
|
|
113
|
-
/**
|
|
114
|
-
* (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
|
|
115
|
-
*/
|
|
116
|
-
const parse = _JSON.parse;
|
|
117
|
-
/**
|
|
118
|
-
* (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
|
119
|
-
*/
|
|
120
|
-
const stringify = _JSON.stringify;
|
|
121
|
-
|
|
122
87
|
/**
|
|
123
88
|
* Safe copies of Object built-in methods.
|
|
124
89
|
*
|
|
@@ -127,7 +92,6 @@ const stringify = _JSON.stringify;
|
|
|
127
92
|
*
|
|
128
93
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/object
|
|
129
94
|
*/
|
|
130
|
-
// Capture references at module initialization time
|
|
131
95
|
const _Object = globalThis.Object;
|
|
132
96
|
/**
|
|
133
97
|
* (Safe copy) Prevents modification of existing property attributes and values,
|
|
@@ -151,30 +115,21 @@ const values = _Object.values;
|
|
|
151
115
|
*/
|
|
152
116
|
const defineProperties = _Object.defineProperties;
|
|
153
117
|
|
|
118
|
+
const registeredClasses = [];
|
|
119
|
+
|
|
154
120
|
/**
|
|
155
|
-
* Safe copies of
|
|
156
|
-
*
|
|
157
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
158
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
121
|
+
* Safe copies of Array built-in static methods.
|
|
159
122
|
*
|
|
160
123
|
* These references are captured at module initialization time to protect against
|
|
161
124
|
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
162
125
|
*
|
|
163
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/
|
|
126
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
164
127
|
*/
|
|
165
|
-
|
|
166
|
-
const _Set = globalThis.Set;
|
|
167
|
-
const _Reflect$3 = globalThis.Reflect;
|
|
128
|
+
const _Array = globalThis.Array;
|
|
168
129
|
/**
|
|
169
|
-
* (Safe copy)
|
|
170
|
-
* Use this instead of `new Set()`.
|
|
171
|
-
*
|
|
172
|
-
* @param iterable - Optional iterable of values.
|
|
173
|
-
* @returns A new Set instance.
|
|
130
|
+
* (Safe copy) Determines whether the passed value is an Array.
|
|
174
131
|
*/
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const registeredClasses = [];
|
|
132
|
+
const isArray = _Array.isArray;
|
|
178
133
|
|
|
179
134
|
/**
|
|
180
135
|
* Returns the data type of the target.
|
|
@@ -210,9 +165,8 @@ const getType = (target) => {
|
|
|
210
165
|
*
|
|
211
166
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
212
167
|
*/
|
|
213
|
-
// Capture references at module initialization time
|
|
214
168
|
const _Error = globalThis.Error;
|
|
215
|
-
const _Reflect$
|
|
169
|
+
const _Reflect$3 = globalThis.Reflect;
|
|
216
170
|
/**
|
|
217
171
|
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
218
172
|
* Use this instead of `new Error()`.
|
|
@@ -221,7 +175,7 @@ const _Reflect$2 = globalThis.Reflect;
|
|
|
221
175
|
* @param options - Optional error options.
|
|
222
176
|
* @returns A new Error instance.
|
|
223
177
|
*/
|
|
224
|
-
const createError = (message, options) => _Reflect$
|
|
178
|
+
const createError = (message, options) => _Reflect$3.construct(_Error, [message, options]);
|
|
225
179
|
|
|
226
180
|
/**
|
|
227
181
|
* Safe copies of Map built-in via factory function.
|
|
@@ -234,9 +188,8 @@ const createError = (message, options) => _Reflect$2.construct(_Error, [message,
|
|
|
234
188
|
*
|
|
235
189
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/map
|
|
236
190
|
*/
|
|
237
|
-
// Capture references at module initialization time
|
|
238
191
|
const _Map = globalThis.Map;
|
|
239
|
-
const _Reflect$
|
|
192
|
+
const _Reflect$2 = globalThis.Reflect;
|
|
240
193
|
/**
|
|
241
194
|
* (Safe copy) Creates a new Map using the captured Map constructor.
|
|
242
195
|
* Use this instead of `new Map()`.
|
|
@@ -244,7 +197,7 @@ const _Reflect$1 = globalThis.Reflect;
|
|
|
244
197
|
* @param iterable - Optional iterable of key-value pairs.
|
|
245
198
|
* @returns A new Map instance.
|
|
246
199
|
*/
|
|
247
|
-
const createMap = (iterable) => _Reflect$
|
|
200
|
+
const createMap = (iterable) => _Reflect$2.construct(_Map, iterable ? [iterable] : []);
|
|
248
201
|
|
|
249
202
|
/**
|
|
250
203
|
* Safe copies of Date built-in via factory function and static methods.
|
|
@@ -257,11 +210,10 @@ const createMap = (iterable) => _Reflect$1.construct(_Map, iterable ? [iterable]
|
|
|
257
210
|
*
|
|
258
211
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/date
|
|
259
212
|
*/
|
|
260
|
-
// Capture references at module initialization time
|
|
261
213
|
const _Date = globalThis.Date;
|
|
262
|
-
const _Reflect = globalThis.Reflect;
|
|
214
|
+
const _Reflect$1 = globalThis.Reflect;
|
|
263
215
|
function createDate(...args) {
|
|
264
|
-
return _Reflect.construct(_Date, args);
|
|
216
|
+
return _Reflect$1.construct(_Date, args);
|
|
265
217
|
}
|
|
266
218
|
/**
|
|
267
219
|
* (Safe copy) Returns the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC.
|
|
@@ -276,7 +228,6 @@ const dateNow = _Date.now;
|
|
|
276
228
|
*
|
|
277
229
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/math
|
|
278
230
|
*/
|
|
279
|
-
// Capture references at module initialization time
|
|
280
231
|
const _Math = globalThis.Math;
|
|
281
232
|
/**
|
|
282
233
|
* (Safe copy) Returns the value of a number rounded to the nearest integer.
|
|
@@ -287,6 +238,28 @@ const round = _Math.round;
|
|
|
287
238
|
*/
|
|
288
239
|
const min = _Math.min;
|
|
289
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Safe copies of Set built-in via factory function.
|
|
243
|
+
*
|
|
244
|
+
* Since constructors cannot be safely captured via Object.assign, this module
|
|
245
|
+
* provides a factory function that uses Reflect.construct internally.
|
|
246
|
+
*
|
|
247
|
+
* These references are captured at module initialization time to protect against
|
|
248
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
249
|
+
*
|
|
250
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/set
|
|
251
|
+
*/
|
|
252
|
+
const _Set = globalThis.Set;
|
|
253
|
+
const _Reflect = globalThis.Reflect;
|
|
254
|
+
/**
|
|
255
|
+
* (Safe copy) Creates a new Set using the captured Set constructor.
|
|
256
|
+
* Use this instead of `new Set()`.
|
|
257
|
+
*
|
|
258
|
+
* @param iterable - Optional iterable of values.
|
|
259
|
+
* @returns A new Set instance.
|
|
260
|
+
*/
|
|
261
|
+
const createSet = (iterable) => _Reflect.construct(_Set, iterable ? [iterable] : []);
|
|
262
|
+
|
|
290
263
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
291
264
|
/**
|
|
292
265
|
* Creates a wrapper function that only executes the wrapped function if the condition function returns true.
|
|
@@ -450,6 +423,24 @@ function notFnMsg(label) {
|
|
|
450
423
|
|
|
451
424
|
createLogger(error, warn, log, info, debug);
|
|
452
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Safe copies of JSON built-in methods.
|
|
428
|
+
*
|
|
429
|
+
* These references are captured at module initialization time to protect against
|
|
430
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
431
|
+
*
|
|
432
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/json
|
|
433
|
+
*/
|
|
434
|
+
const _JSON = globalThis.JSON;
|
|
435
|
+
/**
|
|
436
|
+
* (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
|
|
437
|
+
*/
|
|
438
|
+
const parse = _JSON.parse;
|
|
439
|
+
/**
|
|
440
|
+
* (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
|
441
|
+
*/
|
|
442
|
+
const stringify = _JSON.stringify;
|
|
443
|
+
|
|
453
444
|
/**
|
|
454
445
|
* Global log level registry.
|
|
455
446
|
* Tracks all created scoped loggers to allow global log level changes.
|
|
@@ -578,14 +569,11 @@ function formatMessage(namespace, message, meta) {
|
|
|
578
569
|
*/
|
|
579
570
|
function createScopedLogger(namespace, options = {}) {
|
|
580
571
|
const { level = 'error', sanitizeSecrets = true } = options;
|
|
581
|
-
// Create wrapper functions that add namespace prefix and sanitization
|
|
582
572
|
const createLogFn = (baseFn) => (message, meta) => {
|
|
583
573
|
const processedMeta = sanitizeSecrets && meta ? sanitize(meta) : meta;
|
|
584
574
|
baseFn(formatMessage(namespace, message, processedMeta));
|
|
585
575
|
};
|
|
586
|
-
// Create base logger with wrapped functions
|
|
587
576
|
const baseLogger = createLogger(createLogFn(error), createLogFn(warn), createLogFn(log), createLogFn(info), createLogFn(debug));
|
|
588
|
-
// Set initial log level (use global override if set)
|
|
589
577
|
baseLogger.setLogLevel(globalLogLevel ?? level);
|
|
590
578
|
const scopedLogger = freeze({
|
|
591
579
|
error: (message, meta) => baseLogger.error(message, meta),
|
|
@@ -596,7 +584,6 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
596
584
|
setLogLevel: baseLogger.setLogLevel,
|
|
597
585
|
getLogLevel: baseLogger.getLogLevel,
|
|
598
586
|
});
|
|
599
|
-
// Register logger for global level management
|
|
600
587
|
loggerRegistry.add(scopedLogger);
|
|
601
588
|
return scopedLogger;
|
|
602
589
|
}
|
|
@@ -809,7 +796,6 @@ function traverseUpward(startPath, predicate) {
|
|
|
809
796
|
}
|
|
810
797
|
currentPath = dirname(currentPath);
|
|
811
798
|
}
|
|
812
|
-
// Check root directory
|
|
813
799
|
if (predicate(rootPath)) {
|
|
814
800
|
fsTraversalLogger.debug('Upward traversal found match at root', { startPath, foundPath: rootPath });
|
|
815
801
|
return rootPath;
|
|
@@ -1072,7 +1058,6 @@ const cacheRegistry = createSet();
|
|
|
1072
1058
|
function createCache(options) {
|
|
1073
1059
|
const { ttl, maxSize } = options ?? {};
|
|
1074
1060
|
const store = createMap();
|
|
1075
|
-
// Track insertion order for FIFO eviction
|
|
1076
1061
|
const insertionOrder = [];
|
|
1077
1062
|
/**
|
|
1078
1063
|
* Check if an entry is expired.
|
|
@@ -1123,12 +1108,10 @@ function createCache(options) {
|
|
|
1123
1108
|
return entry.value;
|
|
1124
1109
|
},
|
|
1125
1110
|
set(key, value) {
|
|
1126
|
-
// If key exists, remove from order first
|
|
1127
1111
|
if (store.has(key)) {
|
|
1128
1112
|
removeFromOrder(key);
|
|
1129
1113
|
}
|
|
1130
1114
|
else {
|
|
1131
|
-
// Evict if needed before adding new entry
|
|
1132
1115
|
evictIfNeeded();
|
|
1133
1116
|
}
|
|
1134
1117
|
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
@@ -1161,15 +1144,10 @@ function createCache(options) {
|
|
|
1161
1144
|
return [...insertionOrder];
|
|
1162
1145
|
},
|
|
1163
1146
|
};
|
|
1164
|
-
// Register cache for global operations
|
|
1165
1147
|
cacheRegistry.add(cache);
|
|
1166
1148
|
return freeze(cache);
|
|
1167
1149
|
}
|
|
1168
1150
|
|
|
1169
|
-
/**
|
|
1170
|
-
* Pattern matching utilities with ReDoS protection.
|
|
1171
|
-
* Uses character-by-character matching instead of regex where possible.
|
|
1172
|
-
*/
|
|
1173
1151
|
/**
|
|
1174
1152
|
* Match path against glob pattern using safe character iteration.
|
|
1175
1153
|
* Avoids regex to prevent ReDoS attacks.
|
|
@@ -1207,17 +1185,14 @@ function matchGlobPattern(path, pattern) {
|
|
|
1207
1185
|
* @returns True if remaining segments match
|
|
1208
1186
|
*/
|
|
1209
1187
|
function matchSegments(pathParts, patternParts, pathIdx, patternIdx) {
|
|
1210
|
-
// Base cases
|
|
1211
1188
|
if (pathIdx === pathParts.length && patternIdx === patternParts.length) {
|
|
1212
|
-
return true;
|
|
1189
|
+
return true;
|
|
1213
1190
|
}
|
|
1214
1191
|
if (patternIdx >= patternParts.length) {
|
|
1215
|
-
return false;
|
|
1192
|
+
return false;
|
|
1216
1193
|
}
|
|
1217
1194
|
const patternPart = patternParts[patternIdx];
|
|
1218
|
-
// Handle ** (globstar) - matches zero or more directories
|
|
1219
1195
|
if (patternPart === '**') {
|
|
1220
|
-
// Try matching rest of pattern against current position and all future positions
|
|
1221
1196
|
for (let i = pathIdx; i <= pathParts.length; i++) {
|
|
1222
1197
|
if (matchSegments(pathParts, patternParts, i, patternIdx + 1)) {
|
|
1223
1198
|
return true;
|
|
@@ -1226,10 +1201,9 @@ function matchSegments(pathParts, patternParts, pathIdx, patternIdx) {
|
|
|
1226
1201
|
return false;
|
|
1227
1202
|
}
|
|
1228
1203
|
if (pathIdx >= pathParts.length) {
|
|
1229
|
-
return false;
|
|
1204
|
+
return false;
|
|
1230
1205
|
}
|
|
1231
1206
|
const pathPart = pathParts[pathIdx];
|
|
1232
|
-
// Match current segment
|
|
1233
1207
|
if (matchSegment(pathPart, patternPart)) {
|
|
1234
1208
|
return matchSegments(pathParts, patternParts, pathIdx + 1, patternIdx + 1);
|
|
1235
1209
|
}
|
|
@@ -1249,12 +1223,10 @@ function matchSegment(text, pattern) {
|
|
|
1249
1223
|
while (patternIdx < pattern.length) {
|
|
1250
1224
|
const char = pattern[patternIdx];
|
|
1251
1225
|
if (char === '*') {
|
|
1252
|
-
// * matches zero or more characters
|
|
1253
1226
|
patternIdx++;
|
|
1254
1227
|
if (patternIdx === pattern.length) {
|
|
1255
|
-
return true;
|
|
1228
|
+
return true;
|
|
1256
1229
|
}
|
|
1257
|
-
// Try matching rest of pattern at each position in text
|
|
1258
1230
|
for (let i = textIdx; i <= text.length; i++) {
|
|
1259
1231
|
if (matchSegmentFrom(text, i, pattern, patternIdx)) {
|
|
1260
1232
|
return true;
|
|
@@ -1263,7 +1235,6 @@ function matchSegment(text, pattern) {
|
|
|
1263
1235
|
return false;
|
|
1264
1236
|
}
|
|
1265
1237
|
else if (char === '?') {
|
|
1266
|
-
// ? matches exactly one character
|
|
1267
1238
|
if (textIdx >= text.length) {
|
|
1268
1239
|
return false;
|
|
1269
1240
|
}
|
|
@@ -1271,10 +1242,8 @@ function matchSegment(text, pattern) {
|
|
|
1271
1242
|
patternIdx++;
|
|
1272
1243
|
}
|
|
1273
1244
|
else if (char === '{') {
|
|
1274
|
-
// {a,b,c} matches any alternative
|
|
1275
1245
|
const closeIdx = findClosingBrace(pattern, patternIdx);
|
|
1276
1246
|
if (closeIdx === -1) {
|
|
1277
|
-
// Unmatched brace, treat as literal
|
|
1278
1247
|
if (textIdx >= text.length || text[textIdx] !== char) {
|
|
1279
1248
|
return false;
|
|
1280
1249
|
}
|
|
@@ -1292,7 +1261,6 @@ function matchSegment(text, pattern) {
|
|
|
1292
1261
|
}
|
|
1293
1262
|
}
|
|
1294
1263
|
else {
|
|
1295
|
-
// Literal character
|
|
1296
1264
|
if (textIdx >= text.length || text[textIdx] !== char) {
|
|
1297
1265
|
return false;
|
|
1298
1266
|
}
|
|
@@ -1840,7 +1808,6 @@ function collectAllDependencies(packageJson) {
|
|
|
1840
1808
|
function parseVersionString(versionString) {
|
|
1841
1809
|
if (versionString === undefined || versionString === null)
|
|
1842
1810
|
return undefined;
|
|
1843
|
-
// Manual parsing instead of regex to avoid ReDoS
|
|
1844
1811
|
let start = 0;
|
|
1845
1812
|
while (start < versionString.length) {
|
|
1846
1813
|
const char = versionString[start];
|
|
@@ -1901,7 +1868,6 @@ function expressDetector(projectPath, packageJson) {
|
|
|
1901
1868
|
version = parseVersionString(deps['express']);
|
|
1902
1869
|
sources.push({ type: 'package.json', field: 'dependencies.express' });
|
|
1903
1870
|
}
|
|
1904
|
-
// @types/express (indicates usage)
|
|
1905
1871
|
if (deps['@types/express']) {
|
|
1906
1872
|
confidence += 10;
|
|
1907
1873
|
sources.push({ type: 'package.json', field: 'dependencies.@types/express' });
|
|
@@ -1937,13 +1903,11 @@ function nestDetector(projectPath, packageJson) {
|
|
|
1937
1903
|
let version;
|
|
1938
1904
|
let configPath;
|
|
1939
1905
|
const deps = collectAllDependencies(pkg);
|
|
1940
|
-
// @nestjs/core package
|
|
1941
1906
|
if (deps['@nestjs/core']) {
|
|
1942
1907
|
confidence += 70;
|
|
1943
1908
|
version = parseVersionString(deps['@nestjs/core']);
|
|
1944
1909
|
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
|
|
1945
1910
|
}
|
|
1946
|
-
// @nestjs/common
|
|
1947
1911
|
if (deps['@nestjs/common']) {
|
|
1948
1912
|
confidence += 15;
|
|
1949
1913
|
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
|
|
@@ -1994,7 +1958,6 @@ function fastifyDetector(projectPath, packageJson) {
|
|
|
1994
1958
|
confidence += 15;
|
|
1995
1959
|
sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
|
|
1996
1960
|
}
|
|
1997
|
-
// @types/fastify (older versions)
|
|
1998
1961
|
if (deps['@types/fastify']) {
|
|
1999
1962
|
confidence += 5;
|
|
2000
1963
|
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
@@ -2029,7 +1992,6 @@ function koaDetector(projectPath, packageJson) {
|
|
|
2029
1992
|
version = parseVersionString(deps['koa']);
|
|
2030
1993
|
sources.push({ type: 'package.json', field: 'dependencies.koa' });
|
|
2031
1994
|
}
|
|
2032
|
-
// @types/koa
|
|
2033
1995
|
if (deps['@types/koa']) {
|
|
2034
1996
|
confidence += 10;
|
|
2035
1997
|
sources.push({ type: 'package.json', field: 'dependencies.@types/koa' });
|
|
@@ -2572,7 +2534,6 @@ function remixDetector(projectPath, packageJson) {
|
|
|
2572
2534
|
let confidence = 0;
|
|
2573
2535
|
let version;
|
|
2574
2536
|
const deps = collectAllDependencies(pkg);
|
|
2575
|
-
// @remix-run packages
|
|
2576
2537
|
if (deps['@remix-run/react']) {
|
|
2577
2538
|
confidence += 70;
|
|
2578
2539
|
version = parseVersionString(deps['@remix-run/react']);
|
|
@@ -2848,7 +2809,6 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
2848
2809
|
let confidence = 0;
|
|
2849
2810
|
let version;
|
|
2850
2811
|
const deps = collectAllDependencies(pkg);
|
|
2851
|
-
// @sveltejs/kit package
|
|
2852
2812
|
if (deps['@sveltejs/kit']) {
|
|
2853
2813
|
confidence += 70;
|
|
2854
2814
|
version = parseVersionString(deps['@sveltejs/kit']);
|
|
@@ -2927,13 +2887,11 @@ function qwikDetector(projectPath, packageJson) {
|
|
|
2927
2887
|
let confidence = 0;
|
|
2928
2888
|
let version;
|
|
2929
2889
|
const deps = collectAllDependencies(pkg);
|
|
2930
|
-
// @builder.io/qwik package
|
|
2931
2890
|
if (deps['@builder.io/qwik']) {
|
|
2932
2891
|
confidence += 70;
|
|
2933
2892
|
version = parseVersionString(deps['@builder.io/qwik']);
|
|
2934
2893
|
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
|
|
2935
2894
|
}
|
|
2936
|
-
// @builder.io/qwik-city
|
|
2937
2895
|
if (deps['@builder.io/qwik-city']) {
|
|
2938
2896
|
confidence += 20;
|
|
2939
2897
|
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
|
|
@@ -3026,23 +2984,19 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
3026
2984
|
let confidence = 0;
|
|
3027
2985
|
let version;
|
|
3028
2986
|
const deps = collectAllDependencies(pkg);
|
|
3029
|
-
// AngularJS package (angular, not @angular/core)
|
|
3030
2987
|
if (deps['angular']) {
|
|
3031
2988
|
confidence += 70;
|
|
3032
2989
|
version = parseVersionString(deps['angular']);
|
|
3033
2990
|
sources.push({ type: 'package.json', field: 'dependencies.angular' });
|
|
3034
2991
|
}
|
|
3035
|
-
// AngularJS router
|
|
3036
2992
|
if (deps['angular-route']) {
|
|
3037
2993
|
confidence += 15;
|
|
3038
2994
|
sources.push({ type: 'package.json', field: 'dependencies.angular-route' });
|
|
3039
2995
|
}
|
|
3040
|
-
// AngularJS resource
|
|
3041
2996
|
if (deps['angular-resource']) {
|
|
3042
2997
|
confidence += 10;
|
|
3043
2998
|
sources.push({ type: 'package.json', field: 'dependencies.angular-resource' });
|
|
3044
2999
|
}
|
|
3045
|
-
// AngularJS animate
|
|
3046
3000
|
if (deps['angular-animate']) {
|
|
3047
3001
|
confidence += 5;
|
|
3048
3002
|
sources.push({ type: 'package.json', field: 'dependencies.angular-animate' });
|
|
@@ -3073,23 +3027,19 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
3073
3027
|
let confidence = 0;
|
|
3074
3028
|
let version;
|
|
3075
3029
|
const deps = collectAllDependencies(pkg);
|
|
3076
|
-
// Backbone package
|
|
3077
3030
|
if (deps['backbone']) {
|
|
3078
3031
|
confidence += 70;
|
|
3079
3032
|
version = parseVersionString(deps['backbone']);
|
|
3080
3033
|
sources.push({ type: 'package.json', field: 'dependencies.backbone' });
|
|
3081
|
-
// Underscore (commonly used with Backbone)
|
|
3082
3034
|
if (deps['underscore']) {
|
|
3083
3035
|
confidence += 15;
|
|
3084
3036
|
sources.push({ type: 'package.json', field: 'dependencies.underscore' });
|
|
3085
3037
|
}
|
|
3086
|
-
// Lodash can be used as underscore replacement
|
|
3087
3038
|
if (deps['lodash']) {
|
|
3088
3039
|
confidence += 5;
|
|
3089
3040
|
sources.push({ type: 'package.json', field: 'dependencies.lodash' });
|
|
3090
3041
|
}
|
|
3091
3042
|
}
|
|
3092
|
-
// Marionette (Backbone framework)
|
|
3093
3043
|
if (deps['backbone.marionette'] || deps['marionette']) {
|
|
3094
3044
|
confidence += 10;
|
|
3095
3045
|
sources.push({ type: 'package.json', field: 'dependencies.backbone.marionette' });
|
|
@@ -3120,18 +3070,15 @@ function emberDetector(projectPath, packageJson) {
|
|
|
3120
3070
|
let confidence = 0;
|
|
3121
3071
|
let version;
|
|
3122
3072
|
const deps = collectAllDependencies(pkg);
|
|
3123
|
-
// Ember source package
|
|
3124
3073
|
if (deps['ember-source']) {
|
|
3125
3074
|
confidence += 70;
|
|
3126
3075
|
version = parseVersionString(deps['ember-source']);
|
|
3127
3076
|
sources.push({ type: 'package.json', field: 'dependencies.ember-source' });
|
|
3128
3077
|
}
|
|
3129
|
-
// Ember CLI
|
|
3130
3078
|
if (deps['ember-cli']) {
|
|
3131
3079
|
confidence += 20;
|
|
3132
3080
|
sources.push({ type: 'package.json', field: 'devDependencies.ember-cli' });
|
|
3133
3081
|
}
|
|
3134
|
-
// Ember Data
|
|
3135
3082
|
if (deps['ember-data']) {
|
|
3136
3083
|
confidence += 10;
|
|
3137
3084
|
sources.push({ type: 'package.json', field: 'dependencies.ember-data' });
|
|
@@ -3162,18 +3109,15 @@ function jqueryDetector(projectPath, packageJson) {
|
|
|
3162
3109
|
let confidence = 0;
|
|
3163
3110
|
let version;
|
|
3164
3111
|
const deps = collectAllDependencies(pkg);
|
|
3165
|
-
// jQuery package
|
|
3166
3112
|
if (deps['jquery']) {
|
|
3167
3113
|
confidence += 80;
|
|
3168
3114
|
version = parseVersionString(deps['jquery']);
|
|
3169
3115
|
sources.push({ type: 'package.json', field: 'dependencies.jquery' });
|
|
3170
3116
|
}
|
|
3171
|
-
// jQuery UI
|
|
3172
3117
|
if (deps['jquery-ui']) {
|
|
3173
3118
|
confidence += 10;
|
|
3174
3119
|
sources.push({ type: 'package.json', field: 'dependencies.jquery-ui' });
|
|
3175
3120
|
}
|
|
3176
|
-
// jQuery plugins
|
|
3177
3121
|
if (deps['jquery-validation']) {
|
|
3178
3122
|
confidence += 5;
|
|
3179
3123
|
sources.push({ type: 'package.json', field: 'dependencies.jquery-validation' });
|
|
@@ -3302,7 +3246,6 @@ function prettierDetector(projectPath, packageJson) {
|
|
|
3302
3246
|
confidence += 30;
|
|
3303
3247
|
sources.push({ type: 'package.json', field: 'prettier' });
|
|
3304
3248
|
}
|
|
3305
|
-
// .prettierignore file
|
|
3306
3249
|
if (exists(join$1(projectPath, '.prettierignore'))) {
|
|
3307
3250
|
confidence += 10;
|
|
3308
3251
|
sources.push({ type: 'config-file', path: '.prettierignore' });
|
|
@@ -3397,7 +3340,6 @@ function biomeDetector(projectPath, packageJson) {
|
|
|
3397
3340
|
let configPath;
|
|
3398
3341
|
let version;
|
|
3399
3342
|
const deps = collectAllDependencies(pkg);
|
|
3400
|
-
// @biomejs/biome package
|
|
3401
3343
|
if (deps['@biomejs/biome']) {
|
|
3402
3344
|
confidence += 70;
|
|
3403
3345
|
version = parseVersionString(deps['@biomejs/biome']);
|
|
@@ -3666,7 +3608,7 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
|
3666
3608
|
sources.push({ type: 'lockfile', path: 'package-lock.json' });
|
|
3667
3609
|
}
|
|
3668
3610
|
if (exists(join$1(workspacePath, 'yarn.lock'))) {
|
|
3669
|
-
return null;
|
|
3611
|
+
return null;
|
|
3670
3612
|
}
|
|
3671
3613
|
if (confidence === 0) {
|
|
3672
3614
|
return null;
|
|
@@ -4009,7 +3951,6 @@ function checkTsConfigStrict(projectPath) {
|
|
|
4009
3951
|
if (!content)
|
|
4010
3952
|
return undefined;
|
|
4011
3953
|
try {
|
|
4012
|
-
// Simple JSON parsing - doesn't handle comments but good enough for strict check
|
|
4013
3954
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
4014
3955
|
const parsed = parse(cleanContent);
|
|
4015
3956
|
return parsed?.compilerOptions?.strict === true;
|
|
@@ -4032,19 +3973,16 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
4032
3973
|
let configPath;
|
|
4033
3974
|
let version;
|
|
4034
3975
|
const deps = collectAllDependencies(pkg);
|
|
4035
|
-
// TypeScript package
|
|
4036
3976
|
if (deps['typescript']) {
|
|
4037
3977
|
confidence += 50;
|
|
4038
3978
|
version = parseVersionString(deps['typescript']);
|
|
4039
3979
|
sources.push({ type: 'package.json', field: 'dependencies.typescript' });
|
|
4040
3980
|
}
|
|
4041
|
-
// tsconfig.json
|
|
4042
3981
|
if (exists(join$1(projectPath, 'tsconfig.json'))) {
|
|
4043
3982
|
confidence += 40;
|
|
4044
3983
|
configPath = 'tsconfig.json';
|
|
4045
3984
|
sources.push({ type: 'config-file', path: 'tsconfig.json' });
|
|
4046
3985
|
}
|
|
4047
|
-
// tsconfig.*.json variants
|
|
4048
3986
|
const tsconfigVariants = ['tsconfig.build.json', 'tsconfig.lib.json', 'tsconfig.spec.json', 'tsconfig.app.json'];
|
|
4049
3987
|
for (const variant of tsconfigVariants) {
|
|
4050
3988
|
if (exists(join$1(projectPath, variant))) {
|
|
@@ -4053,7 +3991,6 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
4053
3991
|
break;
|
|
4054
3992
|
}
|
|
4055
3993
|
}
|
|
4056
|
-
// @types packages
|
|
4057
3994
|
const typePackages = keys(deps).filter((d) => d.startsWith('@types/'));
|
|
4058
3995
|
if (typePackages.length > 0) {
|
|
4059
3996
|
confidence += 10;
|
|
@@ -4087,24 +4024,20 @@ function flowDetector(projectPath, packageJson) {
|
|
|
4087
4024
|
let configPath;
|
|
4088
4025
|
let version;
|
|
4089
4026
|
const deps = collectAllDependencies(pkg);
|
|
4090
|
-
// flow-bin package
|
|
4091
4027
|
if (deps['flow-bin']) {
|
|
4092
4028
|
confidence += 60;
|
|
4093
4029
|
version = parseVersionString(deps['flow-bin']);
|
|
4094
4030
|
sources.push({ type: 'package.json', field: 'dependencies.flow-bin' });
|
|
4095
4031
|
}
|
|
4096
|
-
// .flowconfig
|
|
4097
4032
|
if (exists(join$1(projectPath, '.flowconfig'))) {
|
|
4098
4033
|
confidence += 40;
|
|
4099
4034
|
configPath = '.flowconfig';
|
|
4100
4035
|
sources.push({ type: 'config-file', path: '.flowconfig' });
|
|
4101
4036
|
}
|
|
4102
|
-
// flow-typed directory
|
|
4103
4037
|
if (exists(join$1(projectPath, 'flow-typed'))) {
|
|
4104
4038
|
confidence += 10;
|
|
4105
4039
|
sources.push({ type: 'directory', path: 'flow-typed/' });
|
|
4106
4040
|
}
|
|
4107
|
-
// @babel/preset-flow
|
|
4108
4041
|
if (deps['@babel/preset-flow']) {
|
|
4109
4042
|
confidence += 10;
|
|
4110
4043
|
sources.push({ type: 'package.json', field: 'dependencies.@babel/preset-flow' });
|
|
@@ -4128,7 +4061,6 @@ function flowDetector(projectPath, packageJson) {
|
|
|
4128
4061
|
* @returns `true` if the content contains JSDoc type annotations.
|
|
4129
4062
|
*/
|
|
4130
4063
|
function hasJsDocTypes(content) {
|
|
4131
|
-
// Check for JSDoc type annotations
|
|
4132
4064
|
return (content.includes('@type {') ||
|
|
4133
4065
|
content.includes('@param {') ||
|
|
4134
4066
|
content.includes('@returns {') ||
|
|
@@ -4147,14 +4079,11 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
4147
4079
|
const sources = [];
|
|
4148
4080
|
let confidence = 0;
|
|
4149
4081
|
const deps = collectAllDependencies(pkg);
|
|
4150
|
-
// jsdoc package
|
|
4151
4082
|
if (deps['jsdoc']) {
|
|
4152
4083
|
confidence += 30;
|
|
4153
4084
|
sources.push({ type: 'package.json', field: 'dependencies.jsdoc' });
|
|
4154
4085
|
}
|
|
4155
|
-
// typescript with checkJs (JSDoc type checking)
|
|
4156
4086
|
if (deps['typescript']) {
|
|
4157
|
-
// Check if checkJs is enabled in tsconfig
|
|
4158
4087
|
const tsconfigPath = join$1(projectPath, 'tsconfig.json');
|
|
4159
4088
|
const content = readFileIfExists(tsconfigPath);
|
|
4160
4089
|
if (content) {
|
|
@@ -4171,12 +4100,10 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
4171
4100
|
}
|
|
4172
4101
|
}
|
|
4173
4102
|
}
|
|
4174
|
-
// Check for jsconfig.json (VS Code JS type checking)
|
|
4175
4103
|
if (exists(join$1(projectPath, 'jsconfig.json'))) {
|
|
4176
4104
|
confidence += 40;
|
|
4177
4105
|
sources.push({ type: 'config-file', path: 'jsconfig.json' });
|
|
4178
4106
|
}
|
|
4179
|
-
// Sample check for JSDoc annotations in source files
|
|
4180
4107
|
const srcDir = join$1(projectPath, 'src');
|
|
4181
4108
|
if (exists(srcDir)) {
|
|
4182
4109
|
try {
|
|
@@ -4227,8 +4154,6 @@ const detectAllCache = createCache({ ttl: 60000, maxSize: 50 });
|
|
|
4227
4154
|
function isDetectAllOptions(value) {
|
|
4228
4155
|
if (typeof value !== 'object' || value === null)
|
|
4229
4156
|
return false;
|
|
4230
|
-
// DetectAllOptions has skipCache or packageJson fields specifically
|
|
4231
|
-
// PackageJson never has skipCache field
|
|
4232
4157
|
return 'skipCache' in value || 'packageJson' in value;
|
|
4233
4158
|
}
|
|
4234
4159
|
/**
|
|
@@ -4260,9 +4185,7 @@ function isDetectAllOptions(value) {
|
|
|
4260
4185
|
* ```
|
|
4261
4186
|
*/
|
|
4262
4187
|
function detectAll(projectPath, packageJsonOrOptions) {
|
|
4263
|
-
// Handle backward-compatible arguments
|
|
4264
4188
|
const options = isDetectAllOptions(packageJsonOrOptions) ? packageJsonOrOptions : { packageJson: packageJsonOrOptions };
|
|
4265
|
-
// Check cache first (unless skipCache is true)
|
|
4266
4189
|
if (!options.skipCache) {
|
|
4267
4190
|
const cached = detectAllCache.get(projectPath);
|
|
4268
4191
|
if (cached) {
|
|
@@ -4313,7 +4236,6 @@ function detectAll(projectPath, packageJsonOrOptions) {
|
|
|
4313
4236
|
legacyFrameworks: result.legacyFrameworks.map((f) => f.id),
|
|
4314
4237
|
testingFrameworks: result.testingFrameworks.map((f) => f.id),
|
|
4315
4238
|
});
|
|
4316
|
-
// Cache the result
|
|
4317
4239
|
detectAllCache.set(projectPath, result);
|
|
4318
4240
|
return result;
|
|
4319
4241
|
}
|
|
@@ -4585,7 +4507,6 @@ createScopedLogger('project-scope:nx:config');
|
|
|
4585
4507
|
* Known configuration file patterns organized by type.
|
|
4586
4508
|
*/
|
|
4587
4509
|
const CONFIG_PATTERNS = {
|
|
4588
|
-
// Package Management
|
|
4589
4510
|
'package.json': {
|
|
4590
4511
|
patterns: ['package.json'],
|
|
4591
4512
|
format: 'json',
|
|
@@ -4612,14 +4533,12 @@ const CONFIG_PATTERNS = {
|
|
|
4612
4533
|
description: 'NPM configuration',
|
|
4613
4534
|
sensitive: true,
|
|
4614
4535
|
},
|
|
4615
|
-
// TypeScript
|
|
4616
4536
|
tsconfig: {
|
|
4617
4537
|
patterns: ['tsconfig.json', 'tsconfig.*.json'],
|
|
4618
4538
|
format: 'jsonc',
|
|
4619
4539
|
description: 'TypeScript configuration',
|
|
4620
4540
|
canExtend: true,
|
|
4621
4541
|
},
|
|
4622
|
-
// Monorepo
|
|
4623
4542
|
nx: {
|
|
4624
4543
|
patterns: ['nx.json'],
|
|
4625
4544
|
format: 'json',
|
|
@@ -4645,7 +4564,6 @@ const CONFIG_PATTERNS = {
|
|
|
4645
4564
|
format: 'json',
|
|
4646
4565
|
description: 'Lerna configuration',
|
|
4647
4566
|
},
|
|
4648
|
-
// Build Tools
|
|
4649
4567
|
webpack: {
|
|
4650
4568
|
patterns: ['webpack.config.js', 'webpack.config.ts', 'webpack.config.cjs', 'webpack.config.mjs'],
|
|
4651
4569
|
format: 'js',
|
|
@@ -4676,7 +4594,6 @@ const CONFIG_PATTERNS = {
|
|
|
4676
4594
|
format: 'json',
|
|
4677
4595
|
description: 'SWC configuration',
|
|
4678
4596
|
},
|
|
4679
|
-
// Testing
|
|
4680
4597
|
jest: {
|
|
4681
4598
|
patterns: ['jest.config.js', 'jest.config.ts', 'jest.config.mjs'],
|
|
4682
4599
|
description: 'Jest configuration',
|
|
@@ -4693,7 +4610,6 @@ const CONFIG_PATTERNS = {
|
|
|
4693
4610
|
patterns: ['playwright.config.js', 'playwright.config.ts'],
|
|
4694
4611
|
description: 'Playwright configuration',
|
|
4695
4612
|
},
|
|
4696
|
-
// Framework configs
|
|
4697
4613
|
next: {
|
|
4698
4614
|
patterns: ['next.config.js', 'next.config.mjs', 'next.config.ts'],
|
|
4699
4615
|
format: 'js',
|
|
@@ -4719,7 +4635,6 @@ const CONFIG_PATTERNS = {
|
|
|
4719
4635
|
format: 'js',
|
|
4720
4636
|
description: 'Astro configuration',
|
|
4721
4637
|
},
|
|
4722
|
-
// Linting & Formatting
|
|
4723
4638
|
eslint: {
|
|
4724
4639
|
patterns: [
|
|
4725
4640
|
'eslint.config.js',
|
|
@@ -4738,14 +4653,12 @@ const CONFIG_PATTERNS = {
|
|
|
4738
4653
|
format: 'json',
|
|
4739
4654
|
description: 'Prettier configuration',
|
|
4740
4655
|
},
|
|
4741
|
-
// Environment (sensitive)
|
|
4742
4656
|
env: {
|
|
4743
4657
|
patterns: ['.env', '.env.*', '*.env'],
|
|
4744
4658
|
format: 'dotenv',
|
|
4745
4659
|
description: 'Environment variables',
|
|
4746
4660
|
sensitive: true,
|
|
4747
4661
|
},
|
|
4748
|
-
// Git
|
|
4749
4662
|
'.gitignore': {
|
|
4750
4663
|
patterns: ['.gitignore'],
|
|
4751
4664
|
format: 'text',
|
|
@@ -4860,12 +4773,8 @@ function detectConfigs(rootPath, types, options) {
|
|
|
4860
4773
|
*
|
|
4861
4774
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/number
|
|
4862
4775
|
*/
|
|
4863
|
-
// Capture references at module initialization time
|
|
4864
4776
|
const _parseInt = globalThis.parseInt;
|
|
4865
4777
|
const _parseFloat = globalThis.parseFloat;
|
|
4866
|
-
// ============================================================================
|
|
4867
|
-
// Parsing
|
|
4868
|
-
// ============================================================================
|
|
4869
4778
|
/**
|
|
4870
4779
|
* (Safe copy) Parses a string and returns an integer.
|
|
4871
4780
|
*/
|
|
@@ -5193,11 +5102,9 @@ const analyzeLogger = createScopedLogger('project-scope:analyze');
|
|
|
5193
5102
|
* @returns Detected workspace type
|
|
5194
5103
|
*/
|
|
5195
5104
|
function detectWorkspaceType(projectPath) {
|
|
5196
|
-
// Check for NX
|
|
5197
5105
|
if (isNxWorkspace(projectPath) || findNxWorkspaceRoot(projectPath) !== null) {
|
|
5198
5106
|
return 'nx';
|
|
5199
5107
|
}
|
|
5200
|
-
// Check for common monorepo markers
|
|
5201
5108
|
if (exists(resolve(projectPath, 'turbo.json'))) {
|
|
5202
5109
|
return 'turborepo';
|
|
5203
5110
|
}
|
|
@@ -5207,7 +5114,6 @@ function detectWorkspaceType(projectPath) {
|
|
|
5207
5114
|
if (exists(resolve(projectPath, 'pnpm-workspace.yaml'))) {
|
|
5208
5115
|
return 'pnpm';
|
|
5209
5116
|
}
|
|
5210
|
-
// Check package.json for workspaces
|
|
5211
5117
|
const pkg = readPackageJsonIfExists(projectPath);
|
|
5212
5118
|
if (pkg?.workspaces) {
|
|
5213
5119
|
if (exists(resolve(projectPath, 'yarn.lock'))) {
|
|
@@ -5216,7 +5122,7 @@ function detectWorkspaceType(projectPath) {
|
|
|
5216
5122
|
if (exists(resolve(projectPath, 'package-lock.json'))) {
|
|
5217
5123
|
return 'npm';
|
|
5218
5124
|
}
|
|
5219
|
-
return 'npm';
|
|
5125
|
+
return 'npm';
|
|
5220
5126
|
}
|
|
5221
5127
|
return 'standalone';
|
|
5222
5128
|
}
|
|
@@ -5228,15 +5134,12 @@ function detectWorkspaceType(projectPath) {
|
|
|
5228
5134
|
* @returns True if the analysis should be performed
|
|
5229
5135
|
*/
|
|
5230
5136
|
function shouldInclude(type, options) {
|
|
5231
|
-
// If include list is specified, item must be in it
|
|
5232
5137
|
if (options?.include && options.include.length > 0) {
|
|
5233
5138
|
return options.include.includes(type);
|
|
5234
5139
|
}
|
|
5235
|
-
// If exclude list is specified, item must not be in it
|
|
5236
5140
|
if (options?.exclude && options.exclude.length > 0) {
|
|
5237
5141
|
return !options.exclude.includes(type);
|
|
5238
5142
|
}
|
|
5239
|
-
// Default: include everything
|
|
5240
5143
|
return true;
|
|
5241
5144
|
}
|
|
5242
5145
|
/**
|
|
@@ -5285,28 +5188,22 @@ function normalizeConfigFormat(format) {
|
|
|
5285
5188
|
function analyzeProject(projectPath, options) {
|
|
5286
5189
|
const startTime = dateNow();
|
|
5287
5190
|
const resolvedPath = resolve(projectPath);
|
|
5288
|
-
// Set log level based on verbose option
|
|
5289
5191
|
if (options?.verbose) {
|
|
5290
5192
|
analyzeLogger.setLogLevel('debug');
|
|
5291
5193
|
}
|
|
5292
5194
|
analyzeLogger.debug('Starting project analysis', { path: resolvedPath, options });
|
|
5293
|
-
// Read package.json once for reuse
|
|
5294
5195
|
const packageJson = readPackageJsonIfExists(resolvedPath);
|
|
5295
5196
|
analyzeLogger.debug('Package.json loaded', { found: !!packageJson, name: packageJson?.name });
|
|
5296
|
-
// Detect project and workspace types
|
|
5297
5197
|
const projectTypeDetection = detectProjectType(resolvedPath, {
|
|
5298
5198
|
skipTechDetection: options?.depth === 'basic',
|
|
5299
5199
|
});
|
|
5300
5200
|
const projectType = projectTypeDetection.type;
|
|
5301
5201
|
const workspaceType = detectWorkspaceType(resolvedPath);
|
|
5302
5202
|
analyzeLogger.debug('Project type detected', { projectType, workspaceType });
|
|
5303
|
-
// Get project name from package.json or directory name
|
|
5304
5203
|
const projectName = packageJson?.name ?? basename(resolvedPath);
|
|
5305
|
-
// Run all technology detectors
|
|
5306
5204
|
const detections = shouldInclude('frameworks', options) || shouldInclude('buildTools', options) || shouldInclude('testing', options)
|
|
5307
5205
|
? detectAll(resolvedPath, packageJson ?? undefined)
|
|
5308
5206
|
: null;
|
|
5309
|
-
// Convert framework detections to FrameworkInfo
|
|
5310
5207
|
const frameworks = shouldInclude('frameworks', options) && detections
|
|
5311
5208
|
? [
|
|
5312
5209
|
...detections.frontendFrameworks.map((d) => ({
|
|
@@ -5326,7 +5223,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5326
5223
|
})),
|
|
5327
5224
|
]
|
|
5328
5225
|
: [];
|
|
5329
|
-
// Convert build tool detections
|
|
5330
5226
|
const buildTools = shouldInclude('buildTools', options) && detections
|
|
5331
5227
|
? detections.buildTools.map((d) => ({
|
|
5332
5228
|
id: d.id,
|
|
@@ -5336,7 +5232,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5336
5232
|
confidence: d.confidence,
|
|
5337
5233
|
}))
|
|
5338
5234
|
: [];
|
|
5339
|
-
// Convert testing framework detections
|
|
5340
5235
|
const testingFrameworks = shouldInclude('testing', options) && detections
|
|
5341
5236
|
? detections.testingFrameworks.map((d) => ({
|
|
5342
5237
|
id: d.id,
|
|
@@ -5347,7 +5242,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5347
5242
|
confidence: d.confidence,
|
|
5348
5243
|
}))
|
|
5349
5244
|
: [];
|
|
5350
|
-
// Discover entry points
|
|
5351
5245
|
const entryPoints = shouldInclude('entryPoints', options)
|
|
5352
5246
|
? discoverEntryPoints(resolvedPath).map((e) => ({
|
|
5353
5247
|
path: e.path,
|
|
@@ -5355,7 +5249,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5355
5249
|
confidence: e.confidence,
|
|
5356
5250
|
}))
|
|
5357
5251
|
: [];
|
|
5358
|
-
// Detect configuration files
|
|
5359
5252
|
const configFiles = shouldInclude('configs', options)
|
|
5360
5253
|
? detectConfigs(resolvedPath).map((c) => ({
|
|
5361
5254
|
path: c.path,
|
|
@@ -5364,7 +5257,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5364
5257
|
tool: c.type,
|
|
5365
5258
|
}))
|
|
5366
5259
|
: [];
|
|
5367
|
-
// Get dependency summary
|
|
5368
5260
|
let dependencies;
|
|
5369
5261
|
if (shouldInclude('dependencies', options)) {
|
|
5370
5262
|
const deps = getProjectDependencies(resolvedPath);
|
|
@@ -5385,7 +5277,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5385
5277
|
total: 0,
|
|
5386
5278
|
};
|
|
5387
5279
|
}
|
|
5388
|
-
// Build metadata
|
|
5389
5280
|
const metadata = {
|
|
5390
5281
|
timestamp: createDate(),
|
|
5391
5282
|
durationMs: dateNow() - startTime,
|
|
@@ -5460,15 +5351,12 @@ function formatWorkspaceType(type) {
|
|
|
5460
5351
|
*/
|
|
5461
5352
|
function formatAnalysisText(result) {
|
|
5462
5353
|
const lines = [];
|
|
5463
|
-
// Header
|
|
5464
5354
|
lines.push(`Project Analysis: ${result.name}`);
|
|
5465
5355
|
lines.push('='.repeat(30));
|
|
5466
5356
|
lines.push('');
|
|
5467
|
-
// Basic info
|
|
5468
5357
|
lines.push(`Type: ${formatProjectType(result.projectType)}`);
|
|
5469
5358
|
lines.push(`Workspace: ${formatWorkspaceType(result.workspaceType)}`);
|
|
5470
5359
|
lines.push('');
|
|
5471
|
-
// Frameworks
|
|
5472
5360
|
if (result.frameworks.length > 0) {
|
|
5473
5361
|
lines.push('Frameworks:');
|
|
5474
5362
|
for (const framework of result.frameworks) {
|
|
@@ -5482,7 +5370,6 @@ function formatAnalysisText(result) {
|
|
|
5482
5370
|
}
|
|
5483
5371
|
lines.push('');
|
|
5484
5372
|
}
|
|
5485
|
-
// Build tools
|
|
5486
5373
|
if (result.buildTools.length > 0) {
|
|
5487
5374
|
lines.push('Build Tools:');
|
|
5488
5375
|
for (const tool of result.buildTools) {
|
|
@@ -5491,7 +5378,6 @@ function formatAnalysisText(result) {
|
|
|
5491
5378
|
}
|
|
5492
5379
|
lines.push('');
|
|
5493
5380
|
}
|
|
5494
|
-
// Testing
|
|
5495
5381
|
if (result.testingFrameworks.length > 0) {
|
|
5496
5382
|
lines.push('Testing:');
|
|
5497
5383
|
for (const framework of result.testingFrameworks) {
|
|
@@ -5500,7 +5386,6 @@ function formatAnalysisText(result) {
|
|
|
5500
5386
|
}
|
|
5501
5387
|
lines.push('');
|
|
5502
5388
|
}
|
|
5503
|
-
// Entry points
|
|
5504
5389
|
if (result.entryPoints.length > 0) {
|
|
5505
5390
|
lines.push('Entry Points:');
|
|
5506
5391
|
for (const entry of result.entryPoints.slice(0, 5)) {
|
|
@@ -5511,7 +5396,6 @@ function formatAnalysisText(result) {
|
|
|
5511
5396
|
}
|
|
5512
5397
|
lines.push('');
|
|
5513
5398
|
}
|
|
5514
|
-
// Configurations
|
|
5515
5399
|
if (result.configFiles.length > 0) {
|
|
5516
5400
|
lines.push('Configurations:');
|
|
5517
5401
|
for (const config of result.configFiles.slice(0, 8)) {
|
|
@@ -5522,7 +5406,6 @@ function formatAnalysisText(result) {
|
|
|
5522
5406
|
}
|
|
5523
5407
|
lines.push('');
|
|
5524
5408
|
}
|
|
5525
|
-
// Dependencies summary
|
|
5526
5409
|
lines.push('Dependencies:');
|
|
5527
5410
|
lines.push(` Production: ${result.dependencies.production}`);
|
|
5528
5411
|
lines.push(` Development: ${result.dependencies.development}`);
|
|
@@ -5609,7 +5492,7 @@ function parseAnalyzeArgs(args) {
|
|
|
5609
5492
|
exclude: { type: 'string', short: 'e' },
|
|
5610
5493
|
},
|
|
5611
5494
|
allowPositionals: true,
|
|
5612
|
-
strict: false,
|
|
5495
|
+
strict: false,
|
|
5613
5496
|
});
|
|
5614
5497
|
const format = values.format;
|
|
5615
5498
|
const depth = values.depth;
|
|
@@ -5668,7 +5551,6 @@ const analyzeCommandDef = {
|
|
|
5668
5551
|
description: 'Analyze project structure and tech stack',
|
|
5669
5552
|
execute(args, globalOptions) {
|
|
5670
5553
|
const options = parseAnalyzeArgs(args);
|
|
5671
|
-
// Global --json flag overrides format
|
|
5672
5554
|
if (globalOptions.json) {
|
|
5673
5555
|
options.format = 'json';
|
|
5674
5556
|
}
|
|
@@ -5975,12 +5857,10 @@ Examples:
|
|
|
5975
5857
|
function formatDependencyList(deps, maxItems = 20) {
|
|
5976
5858
|
const lines = [];
|
|
5977
5859
|
const depEntries = entries(deps);
|
|
5978
|
-
// Sort alphabetically
|
|
5979
5860
|
depEntries.sort((a, b) => a[0].localeCompare(b[0]));
|
|
5980
5861
|
const displayCount = min(depEntries.length, maxItems);
|
|
5981
5862
|
for (let i = 0; i < displayCount; i++) {
|
|
5982
5863
|
const [name, version] = depEntries[i];
|
|
5983
|
-
// Pad name to align versions
|
|
5984
5864
|
const paddedName = name.padEnd(30);
|
|
5985
5865
|
lines.push(` ${paddedName} ${version}`);
|
|
5986
5866
|
}
|
|
@@ -6223,13 +6103,10 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6223
6103
|
isDirectory: true,
|
|
6224
6104
|
children: [],
|
|
6225
6105
|
};
|
|
6226
|
-
// Create a map for quick lookup
|
|
6227
6106
|
const nodeMap = createMap();
|
|
6228
6107
|
nodeMap.set('.', root);
|
|
6229
|
-
// Sort entries by path for proper parent-child relationships
|
|
6230
6108
|
const sortedEntries = [...walkEntries].sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
6231
6109
|
for (const entry of sortedEntries) {
|
|
6232
|
-
// Skip based on filters
|
|
6233
6110
|
if (options.dirsOnly && !entry.isDirectory)
|
|
6234
6111
|
continue;
|
|
6235
6112
|
if (options.filesOnly && entry.isDirectory)
|
|
@@ -6240,7 +6117,6 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6240
6117
|
isDirectory: entry.isDirectory,
|
|
6241
6118
|
children: [],
|
|
6242
6119
|
};
|
|
6243
|
-
// Add size/modified if requested
|
|
6244
6120
|
if ((options.showSize || options.showModified) && entry.isFile) {
|
|
6245
6121
|
const stats = getFileStat(entry.path);
|
|
6246
6122
|
if (stats) {
|
|
@@ -6250,9 +6126,8 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6250
6126
|
node.modified = stats.modified;
|
|
6251
6127
|
}
|
|
6252
6128
|
}
|
|
6253
|
-
// Find parent
|
|
6254
6129
|
const parts = entry.relativePath.split('/');
|
|
6255
|
-
parts.pop();
|
|
6130
|
+
parts.pop();
|
|
6256
6131
|
const parentPath = parts.join('/') || '.';
|
|
6257
6132
|
const parent = nodeMap.get(parentPath);
|
|
6258
6133
|
if (parent) {
|
|
@@ -6273,11 +6148,9 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6273
6148
|
*/
|
|
6274
6149
|
function renderTreeText(node, options, prefix = '', isLast = true) {
|
|
6275
6150
|
const lines = [];
|
|
6276
|
-
// Current line
|
|
6277
6151
|
const connector = isLast ? '└── ' : '├── ';
|
|
6278
6152
|
const dirMark = node.isDirectory ? '/' : '';
|
|
6279
6153
|
let line = `${prefix}${connector}${node.name}${dirMark}`;
|
|
6280
|
-
// Add size/modified
|
|
6281
6154
|
const meta = [];
|
|
6282
6155
|
if (options.showSize && node.size !== undefined) {
|
|
6283
6156
|
meta.push(formatSize(node.size));
|
|
@@ -6289,10 +6162,8 @@ function renderTreeText(node, options, prefix = '', isLast = true) {
|
|
|
6289
6162
|
line += ` [${meta.join(' ')}]`;
|
|
6290
6163
|
}
|
|
6291
6164
|
lines.push(line);
|
|
6292
|
-
// Process children
|
|
6293
6165
|
const childPrefix = prefix + (isLast ? ' ' : '│ ');
|
|
6294
6166
|
const sortedChildren = [...node.children].sort((a, b) => {
|
|
6295
|
-
// Directories first, then alphabetically
|
|
6296
6167
|
if (a.isDirectory && !b.isDirectory)
|
|
6297
6168
|
return -1;
|
|
6298
6169
|
if (!a.isDirectory && b.isDirectory)
|
|
@@ -6316,9 +6187,7 @@ function renderTreeText(node, options, prefix = '', isLast = true) {
|
|
|
6316
6187
|
*/
|
|
6317
6188
|
function formatTreeText(rootPath, tree, options) {
|
|
6318
6189
|
const lines = [];
|
|
6319
|
-
// Root line
|
|
6320
6190
|
lines.push(basename(rootPath));
|
|
6321
|
-
// Count stats
|
|
6322
6191
|
let dirCount = 0;
|
|
6323
6192
|
let fileCount = 0;
|
|
6324
6193
|
/**
|
|
@@ -6337,7 +6206,6 @@ function formatTreeText(rootPath, tree, options) {
|
|
|
6337
6206
|
countNodes(child);
|
|
6338
6207
|
}
|
|
6339
6208
|
}
|
|
6340
|
-
// Render children of root
|
|
6341
6209
|
const sortedChildren = [...tree.children].sort((a, b) => {
|
|
6342
6210
|
if (a.isDirectory && !b.isDirectory)
|
|
6343
6211
|
return -1;
|
|
@@ -6351,7 +6219,6 @@ function formatTreeText(rootPath, tree, options) {
|
|
|
6351
6219
|
lines.push(...renderTreeText(child, options, '', isLast));
|
|
6352
6220
|
countNodes(child);
|
|
6353
6221
|
}
|
|
6354
|
-
// Summary
|
|
6355
6222
|
lines.push('');
|
|
6356
6223
|
const dirText = dirCount === 1 ? '1 directory' : `${dirCount} directories`;
|
|
6357
6224
|
const fileText = fileCount === 1 ? '1 file' : `${fileCount} files`;
|
|
@@ -6412,7 +6279,6 @@ function parseTreeArgs(args) {
|
|
|
6412
6279
|
function treeCommand(options) {
|
|
6413
6280
|
const rootPath = options.path ? resolve(options.path) : process.cwd();
|
|
6414
6281
|
try {
|
|
6415
|
-
// Collect entries via walk
|
|
6416
6282
|
const walkEntries = [];
|
|
6417
6283
|
walkDirectory(rootPath, (entry) => {
|
|
6418
6284
|
walkEntries.push(entry);
|
|
@@ -6422,9 +6288,7 @@ function treeCommand(options) {
|
|
|
6422
6288
|
ignorePatterns: options.ignore,
|
|
6423
6289
|
includeHidden: false,
|
|
6424
6290
|
});
|
|
6425
|
-
// Build tree structure
|
|
6426
6291
|
const tree = buildTree(rootPath, walkEntries, options);
|
|
6427
|
-
// Format output
|
|
6428
6292
|
let output;
|
|
6429
6293
|
if (options.format === 'json') {
|
|
6430
6294
|
output = formatTreeJson(tree);
|
|
@@ -6483,6 +6347,9 @@ Examples:
|
|
|
6483
6347
|
|
|
6484
6348
|
/** Logger for CLI operations */
|
|
6485
6349
|
const cliLogger = createScopedLogger('project-scope:cli');
|
|
6350
|
+
/** Output printer for user-facing CLI output (help, version, command results). */
|
|
6351
|
+
const output = createLogger(error, undefined, log);
|
|
6352
|
+
output.setLogLevel('log');
|
|
6486
6353
|
/** Library version */
|
|
6487
6354
|
const VERSION = '0.1.0';
|
|
6488
6355
|
/**
|
|
@@ -6498,7 +6365,7 @@ const commands = {
|
|
|
6498
6365
|
* Print general help information.
|
|
6499
6366
|
*/
|
|
6500
6367
|
function printHelp() {
|
|
6501
|
-
log(`
|
|
6368
|
+
output.log(`
|
|
6502
6369
|
project-scope <command> [options]
|
|
6503
6370
|
|
|
6504
6371
|
A tool for analyzing JavaScript/TypeScript project structure and tech stack.
|
|
@@ -6530,7 +6397,7 @@ Examples:
|
|
|
6530
6397
|
* Print CLI version.
|
|
6531
6398
|
*/
|
|
6532
6399
|
function printVersion() {
|
|
6533
|
-
log(`project-scope v${VERSION}`);
|
|
6400
|
+
output.log(`project-scope v${VERSION}`);
|
|
6534
6401
|
}
|
|
6535
6402
|
/**
|
|
6536
6403
|
* Parse global options from command line arguments.
|
|
@@ -6591,24 +6458,24 @@ function run(args) {
|
|
|
6591
6458
|
setGlobalLogLevel('debug');
|
|
6592
6459
|
}
|
|
6593
6460
|
cliLogger.debug('CLI invoked', { args, globalOptions });
|
|
6461
|
+
const commandName = args[0];
|
|
6594
6462
|
if (globalOptions.version) {
|
|
6595
6463
|
printVersion();
|
|
6596
6464
|
return { exitCode: 0 };
|
|
6597
6465
|
}
|
|
6598
|
-
if (globalOptions.help && (args.length === 1 || !commands[
|
|
6466
|
+
if (globalOptions.help && (args.length === 1 || !commands[commandName])) {
|
|
6599
6467
|
printHelp();
|
|
6600
6468
|
return { exitCode: 0 };
|
|
6601
6469
|
}
|
|
6602
|
-
const commandName = args[0];
|
|
6603
6470
|
const command = commands[commandName];
|
|
6604
6471
|
if (!command) {
|
|
6605
6472
|
cliLogger.warn('Unknown command requested', { commandName });
|
|
6606
|
-
error(`Unknown command: ${commandName}`);
|
|
6607
|
-
error('Run "project-scope --help" for usage information.');
|
|
6473
|
+
output.error(`Unknown command: ${commandName}`);
|
|
6474
|
+
output.error('Run "project-scope --help" for usage information.');
|
|
6608
6475
|
return { exitCode: 1, error: `Unknown command: ${commandName}` };
|
|
6609
6476
|
}
|
|
6610
6477
|
if (globalOptions.help) {
|
|
6611
|
-
log(command.getHelp());
|
|
6478
|
+
output.log(command.getHelp());
|
|
6612
6479
|
return { exitCode: 0 };
|
|
6613
6480
|
}
|
|
6614
6481
|
const commandArgs = args.slice(1);
|
|
@@ -6616,11 +6483,11 @@ function run(args) {
|
|
|
6616
6483
|
const result = command.execute(commandArgs, globalOptions);
|
|
6617
6484
|
cliLogger.debug('Command completed', { commandName, exitCode: result.exitCode });
|
|
6618
6485
|
if (result.output) {
|
|
6619
|
-
log(result.output);
|
|
6486
|
+
output.log(result.output);
|
|
6620
6487
|
}
|
|
6621
6488
|
if (result.error) {
|
|
6622
6489
|
cliLogger.error('Command error', { commandName, error: result.error });
|
|
6623
|
-
error(result.error);
|
|
6490
|
+
output.error(result.error);
|
|
6624
6491
|
}
|
|
6625
6492
|
return result;
|
|
6626
6493
|
}
|