@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.cjs.js
CHANGED
|
@@ -12,7 +12,6 @@ var node_fs = require('node:fs');
|
|
|
12
12
|
*
|
|
13
13
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/console
|
|
14
14
|
*/
|
|
15
|
-
// Capture references at module initialization time
|
|
16
15
|
const _console = globalThis.console;
|
|
17
16
|
/**
|
|
18
17
|
* (Safe copy) Outputs a message to the console.
|
|
@@ -87,40 +86,6 @@ _console.timeEnd.bind(_console);
|
|
|
87
86
|
*/
|
|
88
87
|
_console.timeLog.bind(_console);
|
|
89
88
|
|
|
90
|
-
/**
|
|
91
|
-
* Safe copies of Array built-in static methods.
|
|
92
|
-
*
|
|
93
|
-
* These references are captured at module initialization time to protect against
|
|
94
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
95
|
-
*
|
|
96
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
97
|
-
*/
|
|
98
|
-
// Capture references at module initialization time
|
|
99
|
-
const _Array = globalThis.Array;
|
|
100
|
-
/**
|
|
101
|
-
* (Safe copy) Determines whether the passed value is an Array.
|
|
102
|
-
*/
|
|
103
|
-
const isArray = _Array.isArray;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Safe copies of JSON built-in methods.
|
|
107
|
-
*
|
|
108
|
-
* These references are captured at module initialization time to protect against
|
|
109
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
110
|
-
*
|
|
111
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/json
|
|
112
|
-
*/
|
|
113
|
-
// Capture references at module initialization time
|
|
114
|
-
const _JSON = globalThis.JSON;
|
|
115
|
-
/**
|
|
116
|
-
* (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
|
|
117
|
-
*/
|
|
118
|
-
const parse = _JSON.parse;
|
|
119
|
-
/**
|
|
120
|
-
* (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
|
121
|
-
*/
|
|
122
|
-
const stringify = _JSON.stringify;
|
|
123
|
-
|
|
124
89
|
/**
|
|
125
90
|
* Safe copies of Object built-in methods.
|
|
126
91
|
*
|
|
@@ -129,7 +94,6 @@ const stringify = _JSON.stringify;
|
|
|
129
94
|
*
|
|
130
95
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/object
|
|
131
96
|
*/
|
|
132
|
-
// Capture references at module initialization time
|
|
133
97
|
const _Object = globalThis.Object;
|
|
134
98
|
/**
|
|
135
99
|
* (Safe copy) Prevents modification of existing property attributes and values,
|
|
@@ -153,30 +117,21 @@ const values = _Object.values;
|
|
|
153
117
|
*/
|
|
154
118
|
const defineProperties = _Object.defineProperties;
|
|
155
119
|
|
|
120
|
+
const registeredClasses = [];
|
|
121
|
+
|
|
156
122
|
/**
|
|
157
|
-
* Safe copies of
|
|
158
|
-
*
|
|
159
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
160
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
123
|
+
* Safe copies of Array built-in static methods.
|
|
161
124
|
*
|
|
162
125
|
* These references are captured at module initialization time to protect against
|
|
163
126
|
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
164
127
|
*
|
|
165
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/
|
|
128
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
166
129
|
*/
|
|
167
|
-
|
|
168
|
-
const _Set = globalThis.Set;
|
|
169
|
-
const _Reflect$3 = globalThis.Reflect;
|
|
130
|
+
const _Array = globalThis.Array;
|
|
170
131
|
/**
|
|
171
|
-
* (Safe copy)
|
|
172
|
-
* Use this instead of `new Set()`.
|
|
173
|
-
*
|
|
174
|
-
* @param iterable - Optional iterable of values.
|
|
175
|
-
* @returns A new Set instance.
|
|
132
|
+
* (Safe copy) Determines whether the passed value is an Array.
|
|
176
133
|
*/
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
const registeredClasses = [];
|
|
134
|
+
const isArray = _Array.isArray;
|
|
180
135
|
|
|
181
136
|
/**
|
|
182
137
|
* Returns the data type of the target.
|
|
@@ -212,9 +167,8 @@ const getType = (target) => {
|
|
|
212
167
|
*
|
|
213
168
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
214
169
|
*/
|
|
215
|
-
// Capture references at module initialization time
|
|
216
170
|
const _Error = globalThis.Error;
|
|
217
|
-
const _Reflect$
|
|
171
|
+
const _Reflect$3 = globalThis.Reflect;
|
|
218
172
|
/**
|
|
219
173
|
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
220
174
|
* Use this instead of `new Error()`.
|
|
@@ -223,7 +177,7 @@ const _Reflect$2 = globalThis.Reflect;
|
|
|
223
177
|
* @param options - Optional error options.
|
|
224
178
|
* @returns A new Error instance.
|
|
225
179
|
*/
|
|
226
|
-
const createError = (message, options) => _Reflect$
|
|
180
|
+
const createError = (message, options) => _Reflect$3.construct(_Error, [message, options]);
|
|
227
181
|
|
|
228
182
|
/**
|
|
229
183
|
* Safe copies of Map built-in via factory function.
|
|
@@ -236,9 +190,8 @@ const createError = (message, options) => _Reflect$2.construct(_Error, [message,
|
|
|
236
190
|
*
|
|
237
191
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/map
|
|
238
192
|
*/
|
|
239
|
-
// Capture references at module initialization time
|
|
240
193
|
const _Map = globalThis.Map;
|
|
241
|
-
const _Reflect$
|
|
194
|
+
const _Reflect$2 = globalThis.Reflect;
|
|
242
195
|
/**
|
|
243
196
|
* (Safe copy) Creates a new Map using the captured Map constructor.
|
|
244
197
|
* Use this instead of `new Map()`.
|
|
@@ -246,7 +199,7 @@ const _Reflect$1 = globalThis.Reflect;
|
|
|
246
199
|
* @param iterable - Optional iterable of key-value pairs.
|
|
247
200
|
* @returns A new Map instance.
|
|
248
201
|
*/
|
|
249
|
-
const createMap = (iterable) => _Reflect$
|
|
202
|
+
const createMap = (iterable) => _Reflect$2.construct(_Map, iterable ? [iterable] : []);
|
|
250
203
|
|
|
251
204
|
/**
|
|
252
205
|
* Safe copies of Date built-in via factory function and static methods.
|
|
@@ -259,11 +212,10 @@ const createMap = (iterable) => _Reflect$1.construct(_Map, iterable ? [iterable]
|
|
|
259
212
|
*
|
|
260
213
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/date
|
|
261
214
|
*/
|
|
262
|
-
// Capture references at module initialization time
|
|
263
215
|
const _Date = globalThis.Date;
|
|
264
|
-
const _Reflect = globalThis.Reflect;
|
|
216
|
+
const _Reflect$1 = globalThis.Reflect;
|
|
265
217
|
function createDate(...args) {
|
|
266
|
-
return _Reflect.construct(_Date, args);
|
|
218
|
+
return _Reflect$1.construct(_Date, args);
|
|
267
219
|
}
|
|
268
220
|
/**
|
|
269
221
|
* (Safe copy) Returns the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC.
|
|
@@ -278,7 +230,6 @@ const dateNow = _Date.now;
|
|
|
278
230
|
*
|
|
279
231
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/math
|
|
280
232
|
*/
|
|
281
|
-
// Capture references at module initialization time
|
|
282
233
|
const _Math = globalThis.Math;
|
|
283
234
|
/**
|
|
284
235
|
* (Safe copy) Returns the value of a number rounded to the nearest integer.
|
|
@@ -289,6 +240,28 @@ const round = _Math.round;
|
|
|
289
240
|
*/
|
|
290
241
|
const min = _Math.min;
|
|
291
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Safe copies of Set built-in via factory function.
|
|
245
|
+
*
|
|
246
|
+
* Since constructors cannot be safely captured via Object.assign, this module
|
|
247
|
+
* provides a factory function that uses Reflect.construct internally.
|
|
248
|
+
*
|
|
249
|
+
* These references are captured at module initialization time to protect against
|
|
250
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
251
|
+
*
|
|
252
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/set
|
|
253
|
+
*/
|
|
254
|
+
const _Set = globalThis.Set;
|
|
255
|
+
const _Reflect = globalThis.Reflect;
|
|
256
|
+
/**
|
|
257
|
+
* (Safe copy) Creates a new Set using the captured Set constructor.
|
|
258
|
+
* Use this instead of `new Set()`.
|
|
259
|
+
*
|
|
260
|
+
* @param iterable - Optional iterable of values.
|
|
261
|
+
* @returns A new Set instance.
|
|
262
|
+
*/
|
|
263
|
+
const createSet = (iterable) => _Reflect.construct(_Set, iterable ? [iterable] : []);
|
|
264
|
+
|
|
292
265
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
293
266
|
/**
|
|
294
267
|
* Creates a wrapper function that only executes the wrapped function if the condition function returns true.
|
|
@@ -452,6 +425,24 @@ function notFnMsg(label) {
|
|
|
452
425
|
|
|
453
426
|
createLogger(error, warn, log, info, debug);
|
|
454
427
|
|
|
428
|
+
/**
|
|
429
|
+
* Safe copies of JSON built-in methods.
|
|
430
|
+
*
|
|
431
|
+
* These references are captured at module initialization time to protect against
|
|
432
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
433
|
+
*
|
|
434
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/json
|
|
435
|
+
*/
|
|
436
|
+
const _JSON = globalThis.JSON;
|
|
437
|
+
/**
|
|
438
|
+
* (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
|
|
439
|
+
*/
|
|
440
|
+
const parse = _JSON.parse;
|
|
441
|
+
/**
|
|
442
|
+
* (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
|
443
|
+
*/
|
|
444
|
+
const stringify = _JSON.stringify;
|
|
445
|
+
|
|
455
446
|
/**
|
|
456
447
|
* Global log level registry.
|
|
457
448
|
* Tracks all created scoped loggers to allow global log level changes.
|
|
@@ -580,14 +571,11 @@ function formatMessage(namespace, message, meta) {
|
|
|
580
571
|
*/
|
|
581
572
|
function createScopedLogger(namespace, options = {}) {
|
|
582
573
|
const { level = 'error', sanitizeSecrets = true } = options;
|
|
583
|
-
// Create wrapper functions that add namespace prefix and sanitization
|
|
584
574
|
const createLogFn = (baseFn) => (message, meta) => {
|
|
585
575
|
const processedMeta = sanitizeSecrets && meta ? sanitize(meta) : meta;
|
|
586
576
|
baseFn(formatMessage(namespace, message, processedMeta));
|
|
587
577
|
};
|
|
588
|
-
// Create base logger with wrapped functions
|
|
589
578
|
const baseLogger = createLogger(createLogFn(error), createLogFn(warn), createLogFn(log), createLogFn(info), createLogFn(debug));
|
|
590
|
-
// Set initial log level (use global override if set)
|
|
591
579
|
baseLogger.setLogLevel(globalLogLevel ?? level);
|
|
592
580
|
const scopedLogger = freeze({
|
|
593
581
|
error: (message, meta) => baseLogger.error(message, meta),
|
|
@@ -598,7 +586,6 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
598
586
|
setLogLevel: baseLogger.setLogLevel,
|
|
599
587
|
getLogLevel: baseLogger.getLogLevel,
|
|
600
588
|
});
|
|
601
|
-
// Register logger for global level management
|
|
602
589
|
loggerRegistry.add(scopedLogger);
|
|
603
590
|
return scopedLogger;
|
|
604
591
|
}
|
|
@@ -811,7 +798,6 @@ function traverseUpward(startPath, predicate) {
|
|
|
811
798
|
}
|
|
812
799
|
currentPath = node_path.dirname(currentPath);
|
|
813
800
|
}
|
|
814
|
-
// Check root directory
|
|
815
801
|
if (predicate(rootPath)) {
|
|
816
802
|
fsTraversalLogger.debug('Upward traversal found match at root', { startPath, foundPath: rootPath });
|
|
817
803
|
return rootPath;
|
|
@@ -1074,7 +1060,6 @@ const cacheRegistry = createSet();
|
|
|
1074
1060
|
function createCache(options) {
|
|
1075
1061
|
const { ttl, maxSize } = options ?? {};
|
|
1076
1062
|
const store = createMap();
|
|
1077
|
-
// Track insertion order for FIFO eviction
|
|
1078
1063
|
const insertionOrder = [];
|
|
1079
1064
|
/**
|
|
1080
1065
|
* Check if an entry is expired.
|
|
@@ -1125,12 +1110,10 @@ function createCache(options) {
|
|
|
1125
1110
|
return entry.value;
|
|
1126
1111
|
},
|
|
1127
1112
|
set(key, value) {
|
|
1128
|
-
// If key exists, remove from order first
|
|
1129
1113
|
if (store.has(key)) {
|
|
1130
1114
|
removeFromOrder(key);
|
|
1131
1115
|
}
|
|
1132
1116
|
else {
|
|
1133
|
-
// Evict if needed before adding new entry
|
|
1134
1117
|
evictIfNeeded();
|
|
1135
1118
|
}
|
|
1136
1119
|
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
@@ -1163,15 +1146,10 @@ function createCache(options) {
|
|
|
1163
1146
|
return [...insertionOrder];
|
|
1164
1147
|
},
|
|
1165
1148
|
};
|
|
1166
|
-
// Register cache for global operations
|
|
1167
1149
|
cacheRegistry.add(cache);
|
|
1168
1150
|
return freeze(cache);
|
|
1169
1151
|
}
|
|
1170
1152
|
|
|
1171
|
-
/**
|
|
1172
|
-
* Pattern matching utilities with ReDoS protection.
|
|
1173
|
-
* Uses character-by-character matching instead of regex where possible.
|
|
1174
|
-
*/
|
|
1175
1153
|
/**
|
|
1176
1154
|
* Match path against glob pattern using safe character iteration.
|
|
1177
1155
|
* Avoids regex to prevent ReDoS attacks.
|
|
@@ -1209,17 +1187,14 @@ function matchGlobPattern(path, pattern) {
|
|
|
1209
1187
|
* @returns True if remaining segments match
|
|
1210
1188
|
*/
|
|
1211
1189
|
function matchSegments(pathParts, patternParts, pathIdx, patternIdx) {
|
|
1212
|
-
// Base cases
|
|
1213
1190
|
if (pathIdx === pathParts.length && patternIdx === patternParts.length) {
|
|
1214
|
-
return true;
|
|
1191
|
+
return true;
|
|
1215
1192
|
}
|
|
1216
1193
|
if (patternIdx >= patternParts.length) {
|
|
1217
|
-
return false;
|
|
1194
|
+
return false;
|
|
1218
1195
|
}
|
|
1219
1196
|
const patternPart = patternParts[patternIdx];
|
|
1220
|
-
// Handle ** (globstar) - matches zero or more directories
|
|
1221
1197
|
if (patternPart === '**') {
|
|
1222
|
-
// Try matching rest of pattern against current position and all future positions
|
|
1223
1198
|
for (let i = pathIdx; i <= pathParts.length; i++) {
|
|
1224
1199
|
if (matchSegments(pathParts, patternParts, i, patternIdx + 1)) {
|
|
1225
1200
|
return true;
|
|
@@ -1228,10 +1203,9 @@ function matchSegments(pathParts, patternParts, pathIdx, patternIdx) {
|
|
|
1228
1203
|
return false;
|
|
1229
1204
|
}
|
|
1230
1205
|
if (pathIdx >= pathParts.length) {
|
|
1231
|
-
return false;
|
|
1206
|
+
return false;
|
|
1232
1207
|
}
|
|
1233
1208
|
const pathPart = pathParts[pathIdx];
|
|
1234
|
-
// Match current segment
|
|
1235
1209
|
if (matchSegment(pathPart, patternPart)) {
|
|
1236
1210
|
return matchSegments(pathParts, patternParts, pathIdx + 1, patternIdx + 1);
|
|
1237
1211
|
}
|
|
@@ -1251,12 +1225,10 @@ function matchSegment(text, pattern) {
|
|
|
1251
1225
|
while (patternIdx < pattern.length) {
|
|
1252
1226
|
const char = pattern[patternIdx];
|
|
1253
1227
|
if (char === '*') {
|
|
1254
|
-
// * matches zero or more characters
|
|
1255
1228
|
patternIdx++;
|
|
1256
1229
|
if (patternIdx === pattern.length) {
|
|
1257
|
-
return true;
|
|
1230
|
+
return true;
|
|
1258
1231
|
}
|
|
1259
|
-
// Try matching rest of pattern at each position in text
|
|
1260
1232
|
for (let i = textIdx; i <= text.length; i++) {
|
|
1261
1233
|
if (matchSegmentFrom(text, i, pattern, patternIdx)) {
|
|
1262
1234
|
return true;
|
|
@@ -1265,7 +1237,6 @@ function matchSegment(text, pattern) {
|
|
|
1265
1237
|
return false;
|
|
1266
1238
|
}
|
|
1267
1239
|
else if (char === '?') {
|
|
1268
|
-
// ? matches exactly one character
|
|
1269
1240
|
if (textIdx >= text.length) {
|
|
1270
1241
|
return false;
|
|
1271
1242
|
}
|
|
@@ -1273,10 +1244,8 @@ function matchSegment(text, pattern) {
|
|
|
1273
1244
|
patternIdx++;
|
|
1274
1245
|
}
|
|
1275
1246
|
else if (char === '{') {
|
|
1276
|
-
// {a,b,c} matches any alternative
|
|
1277
1247
|
const closeIdx = findClosingBrace(pattern, patternIdx);
|
|
1278
1248
|
if (closeIdx === -1) {
|
|
1279
|
-
// Unmatched brace, treat as literal
|
|
1280
1249
|
if (textIdx >= text.length || text[textIdx] !== char) {
|
|
1281
1250
|
return false;
|
|
1282
1251
|
}
|
|
@@ -1294,7 +1263,6 @@ function matchSegment(text, pattern) {
|
|
|
1294
1263
|
}
|
|
1295
1264
|
}
|
|
1296
1265
|
else {
|
|
1297
|
-
// Literal character
|
|
1298
1266
|
if (textIdx >= text.length || text[textIdx] !== char) {
|
|
1299
1267
|
return false;
|
|
1300
1268
|
}
|
|
@@ -1842,7 +1810,6 @@ function collectAllDependencies(packageJson) {
|
|
|
1842
1810
|
function parseVersionString(versionString) {
|
|
1843
1811
|
if (versionString === undefined || versionString === null)
|
|
1844
1812
|
return undefined;
|
|
1845
|
-
// Manual parsing instead of regex to avoid ReDoS
|
|
1846
1813
|
let start = 0;
|
|
1847
1814
|
while (start < versionString.length) {
|
|
1848
1815
|
const char = versionString[start];
|
|
@@ -1903,7 +1870,6 @@ function expressDetector(projectPath, packageJson) {
|
|
|
1903
1870
|
version = parseVersionString(deps['express']);
|
|
1904
1871
|
sources.push({ type: 'package.json', field: 'dependencies.express' });
|
|
1905
1872
|
}
|
|
1906
|
-
// @types/express (indicates usage)
|
|
1907
1873
|
if (deps['@types/express']) {
|
|
1908
1874
|
confidence += 10;
|
|
1909
1875
|
sources.push({ type: 'package.json', field: 'dependencies.@types/express' });
|
|
@@ -1939,13 +1905,11 @@ function nestDetector(projectPath, packageJson) {
|
|
|
1939
1905
|
let version;
|
|
1940
1906
|
let configPath;
|
|
1941
1907
|
const deps = collectAllDependencies(pkg);
|
|
1942
|
-
// @nestjs/core package
|
|
1943
1908
|
if (deps['@nestjs/core']) {
|
|
1944
1909
|
confidence += 70;
|
|
1945
1910
|
version = parseVersionString(deps['@nestjs/core']);
|
|
1946
1911
|
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
|
|
1947
1912
|
}
|
|
1948
|
-
// @nestjs/common
|
|
1949
1913
|
if (deps['@nestjs/common']) {
|
|
1950
1914
|
confidence += 15;
|
|
1951
1915
|
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
|
|
@@ -1996,7 +1960,6 @@ function fastifyDetector(projectPath, packageJson) {
|
|
|
1996
1960
|
confidence += 15;
|
|
1997
1961
|
sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
|
|
1998
1962
|
}
|
|
1999
|
-
// @types/fastify (older versions)
|
|
2000
1963
|
if (deps['@types/fastify']) {
|
|
2001
1964
|
confidence += 5;
|
|
2002
1965
|
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
@@ -2031,7 +1994,6 @@ function koaDetector(projectPath, packageJson) {
|
|
|
2031
1994
|
version = parseVersionString(deps['koa']);
|
|
2032
1995
|
sources.push({ type: 'package.json', field: 'dependencies.koa' });
|
|
2033
1996
|
}
|
|
2034
|
-
// @types/koa
|
|
2035
1997
|
if (deps['@types/koa']) {
|
|
2036
1998
|
confidence += 10;
|
|
2037
1999
|
sources.push({ type: 'package.json', field: 'dependencies.@types/koa' });
|
|
@@ -2574,7 +2536,6 @@ function remixDetector(projectPath, packageJson) {
|
|
|
2574
2536
|
let confidence = 0;
|
|
2575
2537
|
let version;
|
|
2576
2538
|
const deps = collectAllDependencies(pkg);
|
|
2577
|
-
// @remix-run packages
|
|
2578
2539
|
if (deps['@remix-run/react']) {
|
|
2579
2540
|
confidence += 70;
|
|
2580
2541
|
version = parseVersionString(deps['@remix-run/react']);
|
|
@@ -2850,7 +2811,6 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
2850
2811
|
let confidence = 0;
|
|
2851
2812
|
let version;
|
|
2852
2813
|
const deps = collectAllDependencies(pkg);
|
|
2853
|
-
// @sveltejs/kit package
|
|
2854
2814
|
if (deps['@sveltejs/kit']) {
|
|
2855
2815
|
confidence += 70;
|
|
2856
2816
|
version = parseVersionString(deps['@sveltejs/kit']);
|
|
@@ -2929,13 +2889,11 @@ function qwikDetector(projectPath, packageJson) {
|
|
|
2929
2889
|
let confidence = 0;
|
|
2930
2890
|
let version;
|
|
2931
2891
|
const deps = collectAllDependencies(pkg);
|
|
2932
|
-
// @builder.io/qwik package
|
|
2933
2892
|
if (deps['@builder.io/qwik']) {
|
|
2934
2893
|
confidence += 70;
|
|
2935
2894
|
version = parseVersionString(deps['@builder.io/qwik']);
|
|
2936
2895
|
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
|
|
2937
2896
|
}
|
|
2938
|
-
// @builder.io/qwik-city
|
|
2939
2897
|
if (deps['@builder.io/qwik-city']) {
|
|
2940
2898
|
confidence += 20;
|
|
2941
2899
|
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
|
|
@@ -3028,23 +2986,19 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
3028
2986
|
let confidence = 0;
|
|
3029
2987
|
let version;
|
|
3030
2988
|
const deps = collectAllDependencies(pkg);
|
|
3031
|
-
// AngularJS package (angular, not @angular/core)
|
|
3032
2989
|
if (deps['angular']) {
|
|
3033
2990
|
confidence += 70;
|
|
3034
2991
|
version = parseVersionString(deps['angular']);
|
|
3035
2992
|
sources.push({ type: 'package.json', field: 'dependencies.angular' });
|
|
3036
2993
|
}
|
|
3037
|
-
// AngularJS router
|
|
3038
2994
|
if (deps['angular-route']) {
|
|
3039
2995
|
confidence += 15;
|
|
3040
2996
|
sources.push({ type: 'package.json', field: 'dependencies.angular-route' });
|
|
3041
2997
|
}
|
|
3042
|
-
// AngularJS resource
|
|
3043
2998
|
if (deps['angular-resource']) {
|
|
3044
2999
|
confidence += 10;
|
|
3045
3000
|
sources.push({ type: 'package.json', field: 'dependencies.angular-resource' });
|
|
3046
3001
|
}
|
|
3047
|
-
// AngularJS animate
|
|
3048
3002
|
if (deps['angular-animate']) {
|
|
3049
3003
|
confidence += 5;
|
|
3050
3004
|
sources.push({ type: 'package.json', field: 'dependencies.angular-animate' });
|
|
@@ -3075,23 +3029,19 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
3075
3029
|
let confidence = 0;
|
|
3076
3030
|
let version;
|
|
3077
3031
|
const deps = collectAllDependencies(pkg);
|
|
3078
|
-
// Backbone package
|
|
3079
3032
|
if (deps['backbone']) {
|
|
3080
3033
|
confidence += 70;
|
|
3081
3034
|
version = parseVersionString(deps['backbone']);
|
|
3082
3035
|
sources.push({ type: 'package.json', field: 'dependencies.backbone' });
|
|
3083
|
-
// Underscore (commonly used with Backbone)
|
|
3084
3036
|
if (deps['underscore']) {
|
|
3085
3037
|
confidence += 15;
|
|
3086
3038
|
sources.push({ type: 'package.json', field: 'dependencies.underscore' });
|
|
3087
3039
|
}
|
|
3088
|
-
// Lodash can be used as underscore replacement
|
|
3089
3040
|
if (deps['lodash']) {
|
|
3090
3041
|
confidence += 5;
|
|
3091
3042
|
sources.push({ type: 'package.json', field: 'dependencies.lodash' });
|
|
3092
3043
|
}
|
|
3093
3044
|
}
|
|
3094
|
-
// Marionette (Backbone framework)
|
|
3095
3045
|
if (deps['backbone.marionette'] || deps['marionette']) {
|
|
3096
3046
|
confidence += 10;
|
|
3097
3047
|
sources.push({ type: 'package.json', field: 'dependencies.backbone.marionette' });
|
|
@@ -3122,18 +3072,15 @@ function emberDetector(projectPath, packageJson) {
|
|
|
3122
3072
|
let confidence = 0;
|
|
3123
3073
|
let version;
|
|
3124
3074
|
const deps = collectAllDependencies(pkg);
|
|
3125
|
-
// Ember source package
|
|
3126
3075
|
if (deps['ember-source']) {
|
|
3127
3076
|
confidence += 70;
|
|
3128
3077
|
version = parseVersionString(deps['ember-source']);
|
|
3129
3078
|
sources.push({ type: 'package.json', field: 'dependencies.ember-source' });
|
|
3130
3079
|
}
|
|
3131
|
-
// Ember CLI
|
|
3132
3080
|
if (deps['ember-cli']) {
|
|
3133
3081
|
confidence += 20;
|
|
3134
3082
|
sources.push({ type: 'package.json', field: 'devDependencies.ember-cli' });
|
|
3135
3083
|
}
|
|
3136
|
-
// Ember Data
|
|
3137
3084
|
if (deps['ember-data']) {
|
|
3138
3085
|
confidence += 10;
|
|
3139
3086
|
sources.push({ type: 'package.json', field: 'dependencies.ember-data' });
|
|
@@ -3164,18 +3111,15 @@ function jqueryDetector(projectPath, packageJson) {
|
|
|
3164
3111
|
let confidence = 0;
|
|
3165
3112
|
let version;
|
|
3166
3113
|
const deps = collectAllDependencies(pkg);
|
|
3167
|
-
// jQuery package
|
|
3168
3114
|
if (deps['jquery']) {
|
|
3169
3115
|
confidence += 80;
|
|
3170
3116
|
version = parseVersionString(deps['jquery']);
|
|
3171
3117
|
sources.push({ type: 'package.json', field: 'dependencies.jquery' });
|
|
3172
3118
|
}
|
|
3173
|
-
// jQuery UI
|
|
3174
3119
|
if (deps['jquery-ui']) {
|
|
3175
3120
|
confidence += 10;
|
|
3176
3121
|
sources.push({ type: 'package.json', field: 'dependencies.jquery-ui' });
|
|
3177
3122
|
}
|
|
3178
|
-
// jQuery plugins
|
|
3179
3123
|
if (deps['jquery-validation']) {
|
|
3180
3124
|
confidence += 5;
|
|
3181
3125
|
sources.push({ type: 'package.json', field: 'dependencies.jquery-validation' });
|
|
@@ -3304,7 +3248,6 @@ function prettierDetector(projectPath, packageJson) {
|
|
|
3304
3248
|
confidence += 30;
|
|
3305
3249
|
sources.push({ type: 'package.json', field: 'prettier' });
|
|
3306
3250
|
}
|
|
3307
|
-
// .prettierignore file
|
|
3308
3251
|
if (exists(node_path.join(projectPath, '.prettierignore'))) {
|
|
3309
3252
|
confidence += 10;
|
|
3310
3253
|
sources.push({ type: 'config-file', path: '.prettierignore' });
|
|
@@ -3399,7 +3342,6 @@ function biomeDetector(projectPath, packageJson) {
|
|
|
3399
3342
|
let configPath;
|
|
3400
3343
|
let version;
|
|
3401
3344
|
const deps = collectAllDependencies(pkg);
|
|
3402
|
-
// @biomejs/biome package
|
|
3403
3345
|
if (deps['@biomejs/biome']) {
|
|
3404
3346
|
confidence += 70;
|
|
3405
3347
|
version = parseVersionString(deps['@biomejs/biome']);
|
|
@@ -3668,7 +3610,7 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
|
3668
3610
|
sources.push({ type: 'lockfile', path: 'package-lock.json' });
|
|
3669
3611
|
}
|
|
3670
3612
|
if (exists(node_path.join(workspacePath, 'yarn.lock'))) {
|
|
3671
|
-
return null;
|
|
3613
|
+
return null;
|
|
3672
3614
|
}
|
|
3673
3615
|
if (confidence === 0) {
|
|
3674
3616
|
return null;
|
|
@@ -4011,7 +3953,6 @@ function checkTsConfigStrict(projectPath) {
|
|
|
4011
3953
|
if (!content)
|
|
4012
3954
|
return undefined;
|
|
4013
3955
|
try {
|
|
4014
|
-
// Simple JSON parsing - doesn't handle comments but good enough for strict check
|
|
4015
3956
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
4016
3957
|
const parsed = parse(cleanContent);
|
|
4017
3958
|
return parsed?.compilerOptions?.strict === true;
|
|
@@ -4034,19 +3975,16 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
4034
3975
|
let configPath;
|
|
4035
3976
|
let version;
|
|
4036
3977
|
const deps = collectAllDependencies(pkg);
|
|
4037
|
-
// TypeScript package
|
|
4038
3978
|
if (deps['typescript']) {
|
|
4039
3979
|
confidence += 50;
|
|
4040
3980
|
version = parseVersionString(deps['typescript']);
|
|
4041
3981
|
sources.push({ type: 'package.json', field: 'dependencies.typescript' });
|
|
4042
3982
|
}
|
|
4043
|
-
// tsconfig.json
|
|
4044
3983
|
if (exists(node_path.join(projectPath, 'tsconfig.json'))) {
|
|
4045
3984
|
confidence += 40;
|
|
4046
3985
|
configPath = 'tsconfig.json';
|
|
4047
3986
|
sources.push({ type: 'config-file', path: 'tsconfig.json' });
|
|
4048
3987
|
}
|
|
4049
|
-
// tsconfig.*.json variants
|
|
4050
3988
|
const tsconfigVariants = ['tsconfig.build.json', 'tsconfig.lib.json', 'tsconfig.spec.json', 'tsconfig.app.json'];
|
|
4051
3989
|
for (const variant of tsconfigVariants) {
|
|
4052
3990
|
if (exists(node_path.join(projectPath, variant))) {
|
|
@@ -4055,7 +3993,6 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
4055
3993
|
break;
|
|
4056
3994
|
}
|
|
4057
3995
|
}
|
|
4058
|
-
// @types packages
|
|
4059
3996
|
const typePackages = keys(deps).filter((d) => d.startsWith('@types/'));
|
|
4060
3997
|
if (typePackages.length > 0) {
|
|
4061
3998
|
confidence += 10;
|
|
@@ -4089,24 +4026,20 @@ function flowDetector(projectPath, packageJson) {
|
|
|
4089
4026
|
let configPath;
|
|
4090
4027
|
let version;
|
|
4091
4028
|
const deps = collectAllDependencies(pkg);
|
|
4092
|
-
// flow-bin package
|
|
4093
4029
|
if (deps['flow-bin']) {
|
|
4094
4030
|
confidence += 60;
|
|
4095
4031
|
version = parseVersionString(deps['flow-bin']);
|
|
4096
4032
|
sources.push({ type: 'package.json', field: 'dependencies.flow-bin' });
|
|
4097
4033
|
}
|
|
4098
|
-
// .flowconfig
|
|
4099
4034
|
if (exists(node_path.join(projectPath, '.flowconfig'))) {
|
|
4100
4035
|
confidence += 40;
|
|
4101
4036
|
configPath = '.flowconfig';
|
|
4102
4037
|
sources.push({ type: 'config-file', path: '.flowconfig' });
|
|
4103
4038
|
}
|
|
4104
|
-
// flow-typed directory
|
|
4105
4039
|
if (exists(node_path.join(projectPath, 'flow-typed'))) {
|
|
4106
4040
|
confidence += 10;
|
|
4107
4041
|
sources.push({ type: 'directory', path: 'flow-typed/' });
|
|
4108
4042
|
}
|
|
4109
|
-
// @babel/preset-flow
|
|
4110
4043
|
if (deps['@babel/preset-flow']) {
|
|
4111
4044
|
confidence += 10;
|
|
4112
4045
|
sources.push({ type: 'package.json', field: 'dependencies.@babel/preset-flow' });
|
|
@@ -4130,7 +4063,6 @@ function flowDetector(projectPath, packageJson) {
|
|
|
4130
4063
|
* @returns `true` if the content contains JSDoc type annotations.
|
|
4131
4064
|
*/
|
|
4132
4065
|
function hasJsDocTypes(content) {
|
|
4133
|
-
// Check for JSDoc type annotations
|
|
4134
4066
|
return (content.includes('@type {') ||
|
|
4135
4067
|
content.includes('@param {') ||
|
|
4136
4068
|
content.includes('@returns {') ||
|
|
@@ -4149,14 +4081,11 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
4149
4081
|
const sources = [];
|
|
4150
4082
|
let confidence = 0;
|
|
4151
4083
|
const deps = collectAllDependencies(pkg);
|
|
4152
|
-
// jsdoc package
|
|
4153
4084
|
if (deps['jsdoc']) {
|
|
4154
4085
|
confidence += 30;
|
|
4155
4086
|
sources.push({ type: 'package.json', field: 'dependencies.jsdoc' });
|
|
4156
4087
|
}
|
|
4157
|
-
// typescript with checkJs (JSDoc type checking)
|
|
4158
4088
|
if (deps['typescript']) {
|
|
4159
|
-
// Check if checkJs is enabled in tsconfig
|
|
4160
4089
|
const tsconfigPath = node_path.join(projectPath, 'tsconfig.json');
|
|
4161
4090
|
const content = readFileIfExists(tsconfigPath);
|
|
4162
4091
|
if (content) {
|
|
@@ -4173,12 +4102,10 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
4173
4102
|
}
|
|
4174
4103
|
}
|
|
4175
4104
|
}
|
|
4176
|
-
// Check for jsconfig.json (VS Code JS type checking)
|
|
4177
4105
|
if (exists(node_path.join(projectPath, 'jsconfig.json'))) {
|
|
4178
4106
|
confidence += 40;
|
|
4179
4107
|
sources.push({ type: 'config-file', path: 'jsconfig.json' });
|
|
4180
4108
|
}
|
|
4181
|
-
// Sample check for JSDoc annotations in source files
|
|
4182
4109
|
const srcDir = node_path.join(projectPath, 'src');
|
|
4183
4110
|
if (exists(srcDir)) {
|
|
4184
4111
|
try {
|
|
@@ -4229,8 +4156,6 @@ const detectAllCache = createCache({ ttl: 60000, maxSize: 50 });
|
|
|
4229
4156
|
function isDetectAllOptions(value) {
|
|
4230
4157
|
if (typeof value !== 'object' || value === null)
|
|
4231
4158
|
return false;
|
|
4232
|
-
// DetectAllOptions has skipCache or packageJson fields specifically
|
|
4233
|
-
// PackageJson never has skipCache field
|
|
4234
4159
|
return 'skipCache' in value || 'packageJson' in value;
|
|
4235
4160
|
}
|
|
4236
4161
|
/**
|
|
@@ -4262,9 +4187,7 @@ function isDetectAllOptions(value) {
|
|
|
4262
4187
|
* ```
|
|
4263
4188
|
*/
|
|
4264
4189
|
function detectAll(projectPath, packageJsonOrOptions) {
|
|
4265
|
-
// Handle backward-compatible arguments
|
|
4266
4190
|
const options = isDetectAllOptions(packageJsonOrOptions) ? packageJsonOrOptions : { packageJson: packageJsonOrOptions };
|
|
4267
|
-
// Check cache first (unless skipCache is true)
|
|
4268
4191
|
if (!options.skipCache) {
|
|
4269
4192
|
const cached = detectAllCache.get(projectPath);
|
|
4270
4193
|
if (cached) {
|
|
@@ -4315,7 +4238,6 @@ function detectAll(projectPath, packageJsonOrOptions) {
|
|
|
4315
4238
|
legacyFrameworks: result.legacyFrameworks.map((f) => f.id),
|
|
4316
4239
|
testingFrameworks: result.testingFrameworks.map((f) => f.id),
|
|
4317
4240
|
});
|
|
4318
|
-
// Cache the result
|
|
4319
4241
|
detectAllCache.set(projectPath, result);
|
|
4320
4242
|
return result;
|
|
4321
4243
|
}
|
|
@@ -4587,7 +4509,6 @@ createScopedLogger('project-scope:nx:config');
|
|
|
4587
4509
|
* Known configuration file patterns organized by type.
|
|
4588
4510
|
*/
|
|
4589
4511
|
const CONFIG_PATTERNS = {
|
|
4590
|
-
// Package Management
|
|
4591
4512
|
'package.json': {
|
|
4592
4513
|
patterns: ['package.json'],
|
|
4593
4514
|
format: 'json',
|
|
@@ -4614,14 +4535,12 @@ const CONFIG_PATTERNS = {
|
|
|
4614
4535
|
description: 'NPM configuration',
|
|
4615
4536
|
sensitive: true,
|
|
4616
4537
|
},
|
|
4617
|
-
// TypeScript
|
|
4618
4538
|
tsconfig: {
|
|
4619
4539
|
patterns: ['tsconfig.json', 'tsconfig.*.json'],
|
|
4620
4540
|
format: 'jsonc',
|
|
4621
4541
|
description: 'TypeScript configuration',
|
|
4622
4542
|
canExtend: true,
|
|
4623
4543
|
},
|
|
4624
|
-
// Monorepo
|
|
4625
4544
|
nx: {
|
|
4626
4545
|
patterns: ['nx.json'],
|
|
4627
4546
|
format: 'json',
|
|
@@ -4647,7 +4566,6 @@ const CONFIG_PATTERNS = {
|
|
|
4647
4566
|
format: 'json',
|
|
4648
4567
|
description: 'Lerna configuration',
|
|
4649
4568
|
},
|
|
4650
|
-
// Build Tools
|
|
4651
4569
|
webpack: {
|
|
4652
4570
|
patterns: ['webpack.config.js', 'webpack.config.ts', 'webpack.config.cjs', 'webpack.config.mjs'],
|
|
4653
4571
|
format: 'js',
|
|
@@ -4678,7 +4596,6 @@ const CONFIG_PATTERNS = {
|
|
|
4678
4596
|
format: 'json',
|
|
4679
4597
|
description: 'SWC configuration',
|
|
4680
4598
|
},
|
|
4681
|
-
// Testing
|
|
4682
4599
|
jest: {
|
|
4683
4600
|
patterns: ['jest.config.js', 'jest.config.ts', 'jest.config.mjs'],
|
|
4684
4601
|
description: 'Jest configuration',
|
|
@@ -4695,7 +4612,6 @@ const CONFIG_PATTERNS = {
|
|
|
4695
4612
|
patterns: ['playwright.config.js', 'playwright.config.ts'],
|
|
4696
4613
|
description: 'Playwright configuration',
|
|
4697
4614
|
},
|
|
4698
|
-
// Framework configs
|
|
4699
4615
|
next: {
|
|
4700
4616
|
patterns: ['next.config.js', 'next.config.mjs', 'next.config.ts'],
|
|
4701
4617
|
format: 'js',
|
|
@@ -4721,7 +4637,6 @@ const CONFIG_PATTERNS = {
|
|
|
4721
4637
|
format: 'js',
|
|
4722
4638
|
description: 'Astro configuration',
|
|
4723
4639
|
},
|
|
4724
|
-
// Linting & Formatting
|
|
4725
4640
|
eslint: {
|
|
4726
4641
|
patterns: [
|
|
4727
4642
|
'eslint.config.js',
|
|
@@ -4740,14 +4655,12 @@ const CONFIG_PATTERNS = {
|
|
|
4740
4655
|
format: 'json',
|
|
4741
4656
|
description: 'Prettier configuration',
|
|
4742
4657
|
},
|
|
4743
|
-
// Environment (sensitive)
|
|
4744
4658
|
env: {
|
|
4745
4659
|
patterns: ['.env', '.env.*', '*.env'],
|
|
4746
4660
|
format: 'dotenv',
|
|
4747
4661
|
description: 'Environment variables',
|
|
4748
4662
|
sensitive: true,
|
|
4749
4663
|
},
|
|
4750
|
-
// Git
|
|
4751
4664
|
'.gitignore': {
|
|
4752
4665
|
patterns: ['.gitignore'],
|
|
4753
4666
|
format: 'text',
|
|
@@ -4862,12 +4775,8 @@ function detectConfigs(rootPath, types, options) {
|
|
|
4862
4775
|
*
|
|
4863
4776
|
* @module @hyperfrontend/immutable-api-utils/built-in-copy/number
|
|
4864
4777
|
*/
|
|
4865
|
-
// Capture references at module initialization time
|
|
4866
4778
|
const _parseInt = globalThis.parseInt;
|
|
4867
4779
|
const _parseFloat = globalThis.parseFloat;
|
|
4868
|
-
// ============================================================================
|
|
4869
|
-
// Parsing
|
|
4870
|
-
// ============================================================================
|
|
4871
4780
|
/**
|
|
4872
4781
|
* (Safe copy) Parses a string and returns an integer.
|
|
4873
4782
|
*/
|
|
@@ -5195,11 +5104,9 @@ const analyzeLogger = createScopedLogger('project-scope:analyze');
|
|
|
5195
5104
|
* @returns Detected workspace type
|
|
5196
5105
|
*/
|
|
5197
5106
|
function detectWorkspaceType(projectPath) {
|
|
5198
|
-
// Check for NX
|
|
5199
5107
|
if (isNxWorkspace(projectPath) || findNxWorkspaceRoot(projectPath) !== null) {
|
|
5200
5108
|
return 'nx';
|
|
5201
5109
|
}
|
|
5202
|
-
// Check for common monorepo markers
|
|
5203
5110
|
if (exists(node_path.resolve(projectPath, 'turbo.json'))) {
|
|
5204
5111
|
return 'turborepo';
|
|
5205
5112
|
}
|
|
@@ -5209,7 +5116,6 @@ function detectWorkspaceType(projectPath) {
|
|
|
5209
5116
|
if (exists(node_path.resolve(projectPath, 'pnpm-workspace.yaml'))) {
|
|
5210
5117
|
return 'pnpm';
|
|
5211
5118
|
}
|
|
5212
|
-
// Check package.json for workspaces
|
|
5213
5119
|
const pkg = readPackageJsonIfExists(projectPath);
|
|
5214
5120
|
if (pkg?.workspaces) {
|
|
5215
5121
|
if (exists(node_path.resolve(projectPath, 'yarn.lock'))) {
|
|
@@ -5218,7 +5124,7 @@ function detectWorkspaceType(projectPath) {
|
|
|
5218
5124
|
if (exists(node_path.resolve(projectPath, 'package-lock.json'))) {
|
|
5219
5125
|
return 'npm';
|
|
5220
5126
|
}
|
|
5221
|
-
return 'npm';
|
|
5127
|
+
return 'npm';
|
|
5222
5128
|
}
|
|
5223
5129
|
return 'standalone';
|
|
5224
5130
|
}
|
|
@@ -5230,15 +5136,12 @@ function detectWorkspaceType(projectPath) {
|
|
|
5230
5136
|
* @returns True if the analysis should be performed
|
|
5231
5137
|
*/
|
|
5232
5138
|
function shouldInclude(type, options) {
|
|
5233
|
-
// If include list is specified, item must be in it
|
|
5234
5139
|
if (options?.include && options.include.length > 0) {
|
|
5235
5140
|
return options.include.includes(type);
|
|
5236
5141
|
}
|
|
5237
|
-
// If exclude list is specified, item must not be in it
|
|
5238
5142
|
if (options?.exclude && options.exclude.length > 0) {
|
|
5239
5143
|
return !options.exclude.includes(type);
|
|
5240
5144
|
}
|
|
5241
|
-
// Default: include everything
|
|
5242
5145
|
return true;
|
|
5243
5146
|
}
|
|
5244
5147
|
/**
|
|
@@ -5287,28 +5190,22 @@ function normalizeConfigFormat(format) {
|
|
|
5287
5190
|
function analyzeProject(projectPath, options) {
|
|
5288
5191
|
const startTime = dateNow();
|
|
5289
5192
|
const resolvedPath = node_path.resolve(projectPath);
|
|
5290
|
-
// Set log level based on verbose option
|
|
5291
5193
|
if (options?.verbose) {
|
|
5292
5194
|
analyzeLogger.setLogLevel('debug');
|
|
5293
5195
|
}
|
|
5294
5196
|
analyzeLogger.debug('Starting project analysis', { path: resolvedPath, options });
|
|
5295
|
-
// Read package.json once for reuse
|
|
5296
5197
|
const packageJson = readPackageJsonIfExists(resolvedPath);
|
|
5297
5198
|
analyzeLogger.debug('Package.json loaded', { found: !!packageJson, name: packageJson?.name });
|
|
5298
|
-
// Detect project and workspace types
|
|
5299
5199
|
const projectTypeDetection = detectProjectType(resolvedPath, {
|
|
5300
5200
|
skipTechDetection: options?.depth === 'basic',
|
|
5301
5201
|
});
|
|
5302
5202
|
const projectType = projectTypeDetection.type;
|
|
5303
5203
|
const workspaceType = detectWorkspaceType(resolvedPath);
|
|
5304
5204
|
analyzeLogger.debug('Project type detected', { projectType, workspaceType });
|
|
5305
|
-
// Get project name from package.json or directory name
|
|
5306
5205
|
const projectName = packageJson?.name ?? node_path.basename(resolvedPath);
|
|
5307
|
-
// Run all technology detectors
|
|
5308
5206
|
const detections = shouldInclude('frameworks', options) || shouldInclude('buildTools', options) || shouldInclude('testing', options)
|
|
5309
5207
|
? detectAll(resolvedPath, packageJson ?? undefined)
|
|
5310
5208
|
: null;
|
|
5311
|
-
// Convert framework detections to FrameworkInfo
|
|
5312
5209
|
const frameworks = shouldInclude('frameworks', options) && detections
|
|
5313
5210
|
? [
|
|
5314
5211
|
...detections.frontendFrameworks.map((d) => ({
|
|
@@ -5328,7 +5225,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5328
5225
|
})),
|
|
5329
5226
|
]
|
|
5330
5227
|
: [];
|
|
5331
|
-
// Convert build tool detections
|
|
5332
5228
|
const buildTools = shouldInclude('buildTools', options) && detections
|
|
5333
5229
|
? detections.buildTools.map((d) => ({
|
|
5334
5230
|
id: d.id,
|
|
@@ -5338,7 +5234,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5338
5234
|
confidence: d.confidence,
|
|
5339
5235
|
}))
|
|
5340
5236
|
: [];
|
|
5341
|
-
// Convert testing framework detections
|
|
5342
5237
|
const testingFrameworks = shouldInclude('testing', options) && detections
|
|
5343
5238
|
? detections.testingFrameworks.map((d) => ({
|
|
5344
5239
|
id: d.id,
|
|
@@ -5349,7 +5244,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5349
5244
|
confidence: d.confidence,
|
|
5350
5245
|
}))
|
|
5351
5246
|
: [];
|
|
5352
|
-
// Discover entry points
|
|
5353
5247
|
const entryPoints = shouldInclude('entryPoints', options)
|
|
5354
5248
|
? discoverEntryPoints(resolvedPath).map((e) => ({
|
|
5355
5249
|
path: e.path,
|
|
@@ -5357,7 +5251,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5357
5251
|
confidence: e.confidence,
|
|
5358
5252
|
}))
|
|
5359
5253
|
: [];
|
|
5360
|
-
// Detect configuration files
|
|
5361
5254
|
const configFiles = shouldInclude('configs', options)
|
|
5362
5255
|
? detectConfigs(resolvedPath).map((c) => ({
|
|
5363
5256
|
path: c.path,
|
|
@@ -5366,7 +5259,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5366
5259
|
tool: c.type,
|
|
5367
5260
|
}))
|
|
5368
5261
|
: [];
|
|
5369
|
-
// Get dependency summary
|
|
5370
5262
|
let dependencies;
|
|
5371
5263
|
if (shouldInclude('dependencies', options)) {
|
|
5372
5264
|
const deps = getProjectDependencies(resolvedPath);
|
|
@@ -5387,7 +5279,6 @@ function analyzeProject(projectPath, options) {
|
|
|
5387
5279
|
total: 0,
|
|
5388
5280
|
};
|
|
5389
5281
|
}
|
|
5390
|
-
// Build metadata
|
|
5391
5282
|
const metadata = {
|
|
5392
5283
|
timestamp: createDate(),
|
|
5393
5284
|
durationMs: dateNow() - startTime,
|
|
@@ -5462,15 +5353,12 @@ function formatWorkspaceType(type) {
|
|
|
5462
5353
|
*/
|
|
5463
5354
|
function formatAnalysisText(result) {
|
|
5464
5355
|
const lines = [];
|
|
5465
|
-
// Header
|
|
5466
5356
|
lines.push(`Project Analysis: ${result.name}`);
|
|
5467
5357
|
lines.push('='.repeat(30));
|
|
5468
5358
|
lines.push('');
|
|
5469
|
-
// Basic info
|
|
5470
5359
|
lines.push(`Type: ${formatProjectType(result.projectType)}`);
|
|
5471
5360
|
lines.push(`Workspace: ${formatWorkspaceType(result.workspaceType)}`);
|
|
5472
5361
|
lines.push('');
|
|
5473
|
-
// Frameworks
|
|
5474
5362
|
if (result.frameworks.length > 0) {
|
|
5475
5363
|
lines.push('Frameworks:');
|
|
5476
5364
|
for (const framework of result.frameworks) {
|
|
@@ -5484,7 +5372,6 @@ function formatAnalysisText(result) {
|
|
|
5484
5372
|
}
|
|
5485
5373
|
lines.push('');
|
|
5486
5374
|
}
|
|
5487
|
-
// Build tools
|
|
5488
5375
|
if (result.buildTools.length > 0) {
|
|
5489
5376
|
lines.push('Build Tools:');
|
|
5490
5377
|
for (const tool of result.buildTools) {
|
|
@@ -5493,7 +5380,6 @@ function formatAnalysisText(result) {
|
|
|
5493
5380
|
}
|
|
5494
5381
|
lines.push('');
|
|
5495
5382
|
}
|
|
5496
|
-
// Testing
|
|
5497
5383
|
if (result.testingFrameworks.length > 0) {
|
|
5498
5384
|
lines.push('Testing:');
|
|
5499
5385
|
for (const framework of result.testingFrameworks) {
|
|
@@ -5502,7 +5388,6 @@ function formatAnalysisText(result) {
|
|
|
5502
5388
|
}
|
|
5503
5389
|
lines.push('');
|
|
5504
5390
|
}
|
|
5505
|
-
// Entry points
|
|
5506
5391
|
if (result.entryPoints.length > 0) {
|
|
5507
5392
|
lines.push('Entry Points:');
|
|
5508
5393
|
for (const entry of result.entryPoints.slice(0, 5)) {
|
|
@@ -5513,7 +5398,6 @@ function formatAnalysisText(result) {
|
|
|
5513
5398
|
}
|
|
5514
5399
|
lines.push('');
|
|
5515
5400
|
}
|
|
5516
|
-
// Configurations
|
|
5517
5401
|
if (result.configFiles.length > 0) {
|
|
5518
5402
|
lines.push('Configurations:');
|
|
5519
5403
|
for (const config of result.configFiles.slice(0, 8)) {
|
|
@@ -5524,7 +5408,6 @@ function formatAnalysisText(result) {
|
|
|
5524
5408
|
}
|
|
5525
5409
|
lines.push('');
|
|
5526
5410
|
}
|
|
5527
|
-
// Dependencies summary
|
|
5528
5411
|
lines.push('Dependencies:');
|
|
5529
5412
|
lines.push(` Production: ${result.dependencies.production}`);
|
|
5530
5413
|
lines.push(` Development: ${result.dependencies.development}`);
|
|
@@ -5611,7 +5494,7 @@ function parseAnalyzeArgs(args) {
|
|
|
5611
5494
|
exclude: { type: 'string', short: 'e' },
|
|
5612
5495
|
},
|
|
5613
5496
|
allowPositionals: true,
|
|
5614
|
-
strict: false,
|
|
5497
|
+
strict: false,
|
|
5615
5498
|
});
|
|
5616
5499
|
const format = values.format;
|
|
5617
5500
|
const depth = values.depth;
|
|
@@ -5670,7 +5553,6 @@ const analyzeCommandDef = {
|
|
|
5670
5553
|
description: 'Analyze project structure and tech stack',
|
|
5671
5554
|
execute(args, globalOptions) {
|
|
5672
5555
|
const options = parseAnalyzeArgs(args);
|
|
5673
|
-
// Global --json flag overrides format
|
|
5674
5556
|
if (globalOptions.json) {
|
|
5675
5557
|
options.format = 'json';
|
|
5676
5558
|
}
|
|
@@ -5977,12 +5859,10 @@ Examples:
|
|
|
5977
5859
|
function formatDependencyList(deps, maxItems = 20) {
|
|
5978
5860
|
const lines = [];
|
|
5979
5861
|
const depEntries = entries(deps);
|
|
5980
|
-
// Sort alphabetically
|
|
5981
5862
|
depEntries.sort((a, b) => a[0].localeCompare(b[0]));
|
|
5982
5863
|
const displayCount = min(depEntries.length, maxItems);
|
|
5983
5864
|
for (let i = 0; i < displayCount; i++) {
|
|
5984
5865
|
const [name, version] = depEntries[i];
|
|
5985
|
-
// Pad name to align versions
|
|
5986
5866
|
const paddedName = name.padEnd(30);
|
|
5987
5867
|
lines.push(` ${paddedName} ${version}`);
|
|
5988
5868
|
}
|
|
@@ -6225,13 +6105,10 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6225
6105
|
isDirectory: true,
|
|
6226
6106
|
children: [],
|
|
6227
6107
|
};
|
|
6228
|
-
// Create a map for quick lookup
|
|
6229
6108
|
const nodeMap = createMap();
|
|
6230
6109
|
nodeMap.set('.', root);
|
|
6231
|
-
// Sort entries by path for proper parent-child relationships
|
|
6232
6110
|
const sortedEntries = [...walkEntries].sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
6233
6111
|
for (const entry of sortedEntries) {
|
|
6234
|
-
// Skip based on filters
|
|
6235
6112
|
if (options.dirsOnly && !entry.isDirectory)
|
|
6236
6113
|
continue;
|
|
6237
6114
|
if (options.filesOnly && entry.isDirectory)
|
|
@@ -6242,7 +6119,6 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6242
6119
|
isDirectory: entry.isDirectory,
|
|
6243
6120
|
children: [],
|
|
6244
6121
|
};
|
|
6245
|
-
// Add size/modified if requested
|
|
6246
6122
|
if ((options.showSize || options.showModified) && entry.isFile) {
|
|
6247
6123
|
const stats = getFileStat(entry.path);
|
|
6248
6124
|
if (stats) {
|
|
@@ -6252,9 +6128,8 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6252
6128
|
node.modified = stats.modified;
|
|
6253
6129
|
}
|
|
6254
6130
|
}
|
|
6255
|
-
// Find parent
|
|
6256
6131
|
const parts = entry.relativePath.split('/');
|
|
6257
|
-
parts.pop();
|
|
6132
|
+
parts.pop();
|
|
6258
6133
|
const parentPath = parts.join('/') || '.';
|
|
6259
6134
|
const parent = nodeMap.get(parentPath);
|
|
6260
6135
|
if (parent) {
|
|
@@ -6275,11 +6150,9 @@ function buildTree(rootPath, walkEntries, options) {
|
|
|
6275
6150
|
*/
|
|
6276
6151
|
function renderTreeText(node, options, prefix = '', isLast = true) {
|
|
6277
6152
|
const lines = [];
|
|
6278
|
-
// Current line
|
|
6279
6153
|
const connector = isLast ? '└── ' : '├── ';
|
|
6280
6154
|
const dirMark = node.isDirectory ? '/' : '';
|
|
6281
6155
|
let line = `${prefix}${connector}${node.name}${dirMark}`;
|
|
6282
|
-
// Add size/modified
|
|
6283
6156
|
const meta = [];
|
|
6284
6157
|
if (options.showSize && node.size !== undefined) {
|
|
6285
6158
|
meta.push(formatSize(node.size));
|
|
@@ -6291,10 +6164,8 @@ function renderTreeText(node, options, prefix = '', isLast = true) {
|
|
|
6291
6164
|
line += ` [${meta.join(' ')}]`;
|
|
6292
6165
|
}
|
|
6293
6166
|
lines.push(line);
|
|
6294
|
-
// Process children
|
|
6295
6167
|
const childPrefix = prefix + (isLast ? ' ' : '│ ');
|
|
6296
6168
|
const sortedChildren = [...node.children].sort((a, b) => {
|
|
6297
|
-
// Directories first, then alphabetically
|
|
6298
6169
|
if (a.isDirectory && !b.isDirectory)
|
|
6299
6170
|
return -1;
|
|
6300
6171
|
if (!a.isDirectory && b.isDirectory)
|
|
@@ -6318,9 +6189,7 @@ function renderTreeText(node, options, prefix = '', isLast = true) {
|
|
|
6318
6189
|
*/
|
|
6319
6190
|
function formatTreeText(rootPath, tree, options) {
|
|
6320
6191
|
const lines = [];
|
|
6321
|
-
// Root line
|
|
6322
6192
|
lines.push(node_path.basename(rootPath));
|
|
6323
|
-
// Count stats
|
|
6324
6193
|
let dirCount = 0;
|
|
6325
6194
|
let fileCount = 0;
|
|
6326
6195
|
/**
|
|
@@ -6339,7 +6208,6 @@ function formatTreeText(rootPath, tree, options) {
|
|
|
6339
6208
|
countNodes(child);
|
|
6340
6209
|
}
|
|
6341
6210
|
}
|
|
6342
|
-
// Render children of root
|
|
6343
6211
|
const sortedChildren = [...tree.children].sort((a, b) => {
|
|
6344
6212
|
if (a.isDirectory && !b.isDirectory)
|
|
6345
6213
|
return -1;
|
|
@@ -6353,7 +6221,6 @@ function formatTreeText(rootPath, tree, options) {
|
|
|
6353
6221
|
lines.push(...renderTreeText(child, options, '', isLast));
|
|
6354
6222
|
countNodes(child);
|
|
6355
6223
|
}
|
|
6356
|
-
// Summary
|
|
6357
6224
|
lines.push('');
|
|
6358
6225
|
const dirText = dirCount === 1 ? '1 directory' : `${dirCount} directories`;
|
|
6359
6226
|
const fileText = fileCount === 1 ? '1 file' : `${fileCount} files`;
|
|
@@ -6414,7 +6281,6 @@ function parseTreeArgs(args) {
|
|
|
6414
6281
|
function treeCommand(options) {
|
|
6415
6282
|
const rootPath = options.path ? node_path.resolve(options.path) : process.cwd();
|
|
6416
6283
|
try {
|
|
6417
|
-
// Collect entries via walk
|
|
6418
6284
|
const walkEntries = [];
|
|
6419
6285
|
walkDirectory(rootPath, (entry) => {
|
|
6420
6286
|
walkEntries.push(entry);
|
|
@@ -6424,9 +6290,7 @@ function treeCommand(options) {
|
|
|
6424
6290
|
ignorePatterns: options.ignore,
|
|
6425
6291
|
includeHidden: false,
|
|
6426
6292
|
});
|
|
6427
|
-
// Build tree structure
|
|
6428
6293
|
const tree = buildTree(rootPath, walkEntries, options);
|
|
6429
|
-
// Format output
|
|
6430
6294
|
let output;
|
|
6431
6295
|
if (options.format === 'json') {
|
|
6432
6296
|
output = formatTreeJson(tree);
|
|
@@ -6485,6 +6349,9 @@ Examples:
|
|
|
6485
6349
|
|
|
6486
6350
|
/** Logger for CLI operations */
|
|
6487
6351
|
const cliLogger = createScopedLogger('project-scope:cli');
|
|
6352
|
+
/** Output printer for user-facing CLI output (help, version, command results). */
|
|
6353
|
+
const output = createLogger(error, undefined, log);
|
|
6354
|
+
output.setLogLevel('log');
|
|
6488
6355
|
/** Library version */
|
|
6489
6356
|
const VERSION = '0.1.0';
|
|
6490
6357
|
/**
|
|
@@ -6500,7 +6367,7 @@ const commands = {
|
|
|
6500
6367
|
* Print general help information.
|
|
6501
6368
|
*/
|
|
6502
6369
|
function printHelp() {
|
|
6503
|
-
log(`
|
|
6370
|
+
output.log(`
|
|
6504
6371
|
project-scope <command> [options]
|
|
6505
6372
|
|
|
6506
6373
|
A tool for analyzing JavaScript/TypeScript project structure and tech stack.
|
|
@@ -6532,7 +6399,7 @@ Examples:
|
|
|
6532
6399
|
* Print CLI version.
|
|
6533
6400
|
*/
|
|
6534
6401
|
function printVersion() {
|
|
6535
|
-
log(`project-scope v${VERSION}`);
|
|
6402
|
+
output.log(`project-scope v${VERSION}`);
|
|
6536
6403
|
}
|
|
6537
6404
|
/**
|
|
6538
6405
|
* Parse global options from command line arguments.
|
|
@@ -6593,24 +6460,24 @@ function run(args) {
|
|
|
6593
6460
|
setGlobalLogLevel('debug');
|
|
6594
6461
|
}
|
|
6595
6462
|
cliLogger.debug('CLI invoked', { args, globalOptions });
|
|
6463
|
+
const commandName = args[0];
|
|
6596
6464
|
if (globalOptions.version) {
|
|
6597
6465
|
printVersion();
|
|
6598
6466
|
return { exitCode: 0 };
|
|
6599
6467
|
}
|
|
6600
|
-
if (globalOptions.help && (args.length === 1 || !commands[
|
|
6468
|
+
if (globalOptions.help && (args.length === 1 || !commands[commandName])) {
|
|
6601
6469
|
printHelp();
|
|
6602
6470
|
return { exitCode: 0 };
|
|
6603
6471
|
}
|
|
6604
|
-
const commandName = args[0];
|
|
6605
6472
|
const command = commands[commandName];
|
|
6606
6473
|
if (!command) {
|
|
6607
6474
|
cliLogger.warn('Unknown command requested', { commandName });
|
|
6608
|
-
error(`Unknown command: ${commandName}`);
|
|
6609
|
-
error('Run "project-scope --help" for usage information.');
|
|
6475
|
+
output.error(`Unknown command: ${commandName}`);
|
|
6476
|
+
output.error('Run "project-scope --help" for usage information.');
|
|
6610
6477
|
return { exitCode: 1, error: `Unknown command: ${commandName}` };
|
|
6611
6478
|
}
|
|
6612
6479
|
if (globalOptions.help) {
|
|
6613
|
-
log(command.getHelp());
|
|
6480
|
+
output.log(command.getHelp());
|
|
6614
6481
|
return { exitCode: 0 };
|
|
6615
6482
|
}
|
|
6616
6483
|
const commandArgs = args.slice(1);
|
|
@@ -6618,11 +6485,11 @@ function run(args) {
|
|
|
6618
6485
|
const result = command.execute(commandArgs, globalOptions);
|
|
6619
6486
|
cliLogger.debug('Command completed', { commandName, exitCode: result.exitCode });
|
|
6620
6487
|
if (result.output) {
|
|
6621
|
-
log(result.output);
|
|
6488
|
+
output.log(result.output);
|
|
6622
6489
|
}
|
|
6623
6490
|
if (result.error) {
|
|
6624
6491
|
cliLogger.error('Command error', { commandName, error: result.error });
|
|
6625
|
-
error(result.error);
|
|
6492
|
+
output.error(result.error);
|
|
6626
6493
|
}
|
|
6627
6494
|
return result;
|
|
6628
6495
|
}
|