@hyperfrontend/project-scope 0.2.1 → 0.2.2
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 +7 -1
- package/README.md +3 -4
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.cjs.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.cjs.js +13 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.esm.js +8 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.cjs.js +10 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.esm.js +8 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.cjs.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.cjs.js +9 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.esm.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.cjs.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.esm.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.cjs.js +15 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.esm.js +9 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.cjs.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/logging/index.cjs.js +191 -0
- package/_dependencies/@hyperfrontend/logging/index.d.ts +151 -0
- package/_dependencies/@hyperfrontend/logging/index.esm.js +186 -0
- package/_shared/core/cache/index.cjs.js +135 -0
- package/_shared/core/cache/index.esm.js +128 -0
- package/_shared/core/errors/structured-errors/index.cjs.js +28 -0
- package/_shared/core/errors/structured-errors/index.esm.js +23 -0
- package/_shared/core/fs/stat/index.cjs.js +46 -0
- package/_shared/core/fs/stat/index.esm.js +40 -0
- package/_shared/core/path/join/index.cjs.js +13 -0
- package/_shared/core/path/join/index.esm.js +10 -0
- package/_shared/core/path/normalize/index.cjs.js +37 -0
- package/_shared/core/path/normalize/index.esm.js +31 -0
- package/_shared/core/path/resolve/index.cjs.js +47 -0
- package/_shared/core/path/resolve/index.esm.js +41 -0
- package/_shared/core/path/segments/index.cjs.js +38 -0
- package/_shared/core/path/segments/index.esm.js +31 -0
- package/_shared/core/patterns/glob/index.cjs.js +145 -0
- package/_shared/core/patterns/glob/index.esm.js +136 -0
- package/_shared/core/platform/detect/index.cjs.js +103 -0
- package/_shared/core/platform/detect/index.esm.js +95 -0
- package/_shared/core/platform/line-endings/index.cjs.js +52 -0
- package/_shared/core/platform/line-endings/index.esm.js +44 -0
- package/_shared/project/config/patterns/index.cjs.js +172 -0
- package/_shared/project/config/patterns/index.esm.js +169 -0
- package/_shared/tech/monorepo/pnpm-workspaces/index.cjs.js +33 -0
- package/_shared/tech/monorepo/pnpm-workspaces/index.esm.js +31 -0
- package/_shared/tech/shared-utils/detector-helpers/index.cjs.js +48 -0
- package/_shared/tech/shared-utils/detector-helpers/index.esm.js +43 -0
- package/_shared/vfs/types/index.cjs.js +14 -0
- package/_shared/vfs/types/index.esm.js +12 -0
- package/cli/index.cjs.js +1702 -1910
- package/cli/index.d.ts +273 -7
- package/cli/index.d.ts.map +1 -1
- package/cli/index.esm.js +1586 -1794
- package/core/encoding/index.cjs.js +86 -401
- package/core/encoding/index.d.ts +186 -3
- package/core/encoding/index.d.ts.map +1 -1
- package/core/encoding/index.esm.js +78 -392
- package/core/fs/index.cjs.js +231 -581
- package/core/fs/index.d.ts +479 -6
- package/core/fs/index.d.ts.map +1 -1
- package/core/fs/index.esm.js +221 -571
- package/core/index.cjs.js +518 -1748
- package/core/index.d.ts +486 -9
- package/core/index.d.ts.map +1 -1
- package/core/index.esm.js +501 -1728
- package/core/path/index.cjs.js +6 -234
- package/core/path/index.d.ts +306 -5
- package/core/path/index.d.ts.map +1 -1
- package/core/path/index.esm.js +4 -232
- package/core/platform/index.cjs.js +5 -216
- package/core/platform/index.d.ts +185 -3
- package/core/platform/index.d.ts.map +1 -1
- package/core/platform/index.esm.js +3 -212
- package/heuristics/dependencies/index.cjs.js +95 -492
- package/heuristics/dependencies/index.d.ts +99 -2
- package/heuristics/dependencies/index.d.ts.map +1 -1
- package/heuristics/dependencies/index.esm.js +69 -466
- package/heuristics/entry-points/index.cjs.js +91 -795
- package/heuristics/entry-points/index.d.ts +123 -2
- package/heuristics/entry-points/index.d.ts.map +1 -1
- package/heuristics/entry-points/index.esm.js +72 -776
- package/heuristics/framework/index.cjs.js +1481 -1410
- package/heuristics/framework/index.d.ts +104 -2
- package/heuristics/framework/index.d.ts.map +1 -1
- package/heuristics/framework/index.esm.js +1417 -1346
- package/heuristics/index.cjs.js +3206 -3301
- package/heuristics/index.d.ts +4 -5
- package/heuristics/index.d.ts.map +1 -1
- package/heuristics/index.esm.js +3231 -3326
- package/heuristics/project-type/index.cjs.js +1487 -1437
- package/heuristics/project-type/index.d.ts +64 -2
- package/heuristics/project-type/index.d.ts.map +1 -1
- package/heuristics/project-type/index.esm.js +1416 -1366
- package/index.cjs.js +3044 -3533
- package/index.d.ts +44 -10
- package/index.d.ts.map +1 -1
- package/index.esm.js +2900 -3377
- package/models/index.cjs.js +0 -1
- package/models/index.d.ts +20 -14
- package/models/index.d.ts.map +1 -1
- package/models/index.esm.js +0 -1
- package/nx/index.cjs.js +163 -577
- package/nx/index.d.ts +279 -4
- package/nx/index.d.ts.map +1 -1
- package/nx/index.esm.js +145 -554
- package/package.json +13 -12
- package/project/config/index.cjs.js +122 -1062
- package/project/config/index.d.ts +202 -4
- package/project/config/index.d.ts.map +1 -1
- package/project/config/index.esm.js +105 -1043
- package/project/index.cjs.js +323 -1100
- package/project/index.d.ts +4 -5
- package/project/index.d.ts.map +1 -1
- package/project/index.esm.js +302 -1076
- package/project/package/index.cjs.js +191 -472
- package/project/package/index.d.ts +280 -3
- package/project/package/index.d.ts.map +1 -1
- package/project/package/index.esm.js +178 -458
- package/project/root/index.cjs.js +107 -416
- package/project/root/index.d.ts +83 -2
- package/project/root/index.d.ts.map +1 -1
- package/project/root/index.esm.js +96 -405
- package/project/traversal/index.cjs.js +94 -621
- package/project/traversal/index.d.ts +165 -3
- package/project/traversal/index.d.ts.map +1 -1
- package/project/traversal/index.esm.js +80 -607
- package/tech/backend/index.cjs.js +221 -507
- package/tech/backend/index.d.ts +205 -8
- package/tech/backend/index.d.ts.map +1 -1
- package/tech/backend/index.esm.js +200 -486
- package/tech/build/index.cjs.js +348 -635
- package/tech/build/index.d.ts +276 -10
- package/tech/build/index.d.ts.map +1 -1
- package/tech/build/index.esm.js +326 -613
- package/tech/frontend/index.cjs.js +505 -684
- package/tech/frontend/index.d.ts +379 -15
- package/tech/frontend/index.d.ts.map +1 -1
- package/tech/frontend/index.esm.js +481 -660
- package/tech/index.cjs.js +1580 -1420
- package/tech/index.d.ts +55 -32
- package/tech/index.d.ts.map +1 -1
- package/tech/index.esm.js +1513 -1353
- package/tech/legacy/index.cjs.js +97 -448
- package/tech/legacy/index.d.ts +125 -7
- package/tech/legacy/index.d.ts.map +1 -1
- package/tech/legacy/index.esm.js +79 -430
- package/tech/linting/index.cjs.js +136 -522
- package/tech/linting/index.d.ts +129 -7
- package/tech/linting/index.d.ts.map +1 -1
- package/tech/linting/index.esm.js +116 -502
- package/tech/monorepo/index.cjs.js +244 -572
- package/tech/monorepo/index.d.ts +241 -10
- package/tech/monorepo/index.d.ts.map +1 -1
- package/tech/monorepo/index.esm.js +224 -552
- package/tech/testing/index.cjs.js +214 -570
- package/tech/testing/index.d.ts +176 -8
- package/tech/testing/index.d.ts.map +1 -1
- package/tech/testing/index.esm.js +196 -552
- package/tech/types/index.cjs.js +121 -505
- package/tech/types/index.d.ts +120 -2
- package/tech/types/index.d.ts.map +1 -1
- package/tech/types/index.esm.js +99 -483
- package/vfs/index.cjs.js +647 -1142
- package/vfs/index.d.ts +360 -6
- package/vfs/index.d.ts.map +1 -1
- package/vfs/index.esm.js +672 -1167
- package/ARCHITECTURE.md +0 -370
- package/analyze.d.ts +0 -33
- package/analyze.d.ts.map +0 -1
- package/cli/commands/analyze.d.ts +0 -28
- package/cli/commands/analyze.d.ts.map +0 -1
- package/cli/commands/config.d.ts +0 -27
- package/cli/commands/config.d.ts.map +0 -1
- package/cli/commands/deps.d.ts +0 -24
- package/cli/commands/deps.d.ts.map +0 -1
- package/cli/commands/tree.d.ts +0 -36
- package/cli/commands/tree.d.ts.map +0 -1
- package/cli/index.cjs.js.map +0 -1
- package/cli/index.esm.js.map +0 -1
- package/cli/run.d.ts +0 -25
- package/cli/run.d.ts.map +0 -1
- package/cli/types.d.ts +0 -55
- package/cli/types.d.ts.map +0 -1
- package/core/cache.d.ts +0 -158
- package/core/cache.d.ts.map +0 -1
- package/core/encoding/convert.d.ts +0 -32
- package/core/encoding/convert.d.ts.map +0 -1
- package/core/encoding/detect.d.ts +0 -91
- package/core/encoding/detect.d.ts.map +0 -1
- package/core/encoding/index.cjs.js.map +0 -1
- package/core/encoding/index.esm.js.map +0 -1
- package/core/errors/structured-errors.d.ts +0 -66
- package/core/errors/structured-errors.d.ts.map +0 -1
- package/core/fs/directory.d.ts +0 -91
- package/core/fs/directory.d.ts.map +0 -1
- package/core/fs/index.cjs.js.map +0 -1
- package/core/fs/index.esm.js.map +0 -1
- package/core/fs/read.d.ts +0 -94
- package/core/fs/read.d.ts.map +0 -1
- package/core/fs/stat.d.ts +0 -58
- package/core/fs/stat.d.ts.map +0 -1
- package/core/fs/traversal.d.ts +0 -26
- package/core/fs/traversal.d.ts.map +0 -1
- package/core/fs/write.d.ts +0 -75
- package/core/fs/write.d.ts.map +0 -1
- package/core/index.cjs.js.map +0 -1
- package/core/index.esm.js.map +0 -1
- package/core/logger.d.ts +0 -111
- package/core/logger.d.ts.map +0 -1
- package/core/path/index.cjs.js.map +0 -1
- package/core/path/index.esm.js.map +0 -1
- package/core/path/join.d.ts +0 -17
- package/core/path/join.d.ts.map +0 -1
- package/core/path/normalize.d.ts +0 -37
- package/core/path/normalize.d.ts.map +0 -1
- package/core/path/resolve.d.ts +0 -52
- package/core/path/resolve.d.ts.map +0 -1
- package/core/path/segments.d.ts +0 -59
- package/core/path/segments.d.ts.map +0 -1
- package/core/patterns/glob.d.ts +0 -42
- package/core/patterns/glob.d.ts.map +0 -1
- package/core/platform/detect.d.ts +0 -66
- package/core/platform/detect.d.ts.map +0 -1
- package/core/platform/index.cjs.js.map +0 -1
- package/core/platform/index.esm.js.map +0 -1
- package/core/platform/line-endings.d.ts +0 -48
- package/core/platform/line-endings.d.ts.map +0 -1
- package/heuristics/dependencies/analyze.d.ts +0 -77
- package/heuristics/dependencies/analyze.d.ts.map +0 -1
- package/heuristics/dependencies/index.cjs.js.map +0 -1
- package/heuristics/dependencies/index.esm.js.map +0 -1
- package/heuristics/entry-points/discover.d.ts +0 -113
- package/heuristics/entry-points/discover.d.ts.map +0 -1
- package/heuristics/entry-points/index.cjs.js.map +0 -1
- package/heuristics/entry-points/index.esm.js.map +0 -1
- package/heuristics/framework/identify.d.ts +0 -84
- package/heuristics/framework/identify.d.ts.map +0 -1
- package/heuristics/framework/index.cjs.js.map +0 -1
- package/heuristics/framework/index.esm.js.map +0 -1
- package/heuristics/index.cjs.js.map +0 -1
- package/heuristics/index.esm.js.map +0 -1
- package/heuristics/project-type/detect.d.ts +0 -61
- package/heuristics/project-type/detect.d.ts.map +0 -1
- package/heuristics/project-type/index.cjs.js.map +0 -1
- package/heuristics/project-type/index.esm.js.map +0 -1
- package/index.cjs.js.map +0 -1
- package/index.esm.js.map +0 -1
- package/models/index.cjs.js.map +0 -1
- package/models/index.esm.js.map +0 -1
- package/nx/detect.d.ts +0 -105
- package/nx/detect.d.ts.map +0 -1
- package/nx/devkit-loader.d.ts +0 -62
- package/nx/devkit-loader.d.ts.map +0 -1
- package/nx/index.cjs.js.map +0 -1
- package/nx/index.esm.js.map +0 -1
- package/nx/project-config.d.ts +0 -111
- package/nx/project-config.d.ts.map +0 -1
- package/project/config/detect.d.ts +0 -77
- package/project/config/detect.d.ts.map +0 -1
- package/project/config/index.cjs.js.map +0 -1
- package/project/config/index.esm.js.map +0 -1
- package/project/config/parse.d.ts +0 -53
- package/project/config/parse.d.ts.map +0 -1
- package/project/config/patterns.d.ts +0 -31
- package/project/config/patterns.d.ts.map +0 -1
- package/project/index.cjs.js.map +0 -1
- package/project/index.esm.js.map +0 -1
- package/project/package/dependencies.d.ts +0 -101
- package/project/package/dependencies.d.ts.map +0 -1
- package/project/package/index.cjs.js.map +0 -1
- package/project/package/index.esm.js.map +0 -1
- package/project/package/read.d.ts +0 -67
- package/project/package/read.d.ts.map +0 -1
- package/project/root/detect.d.ts +0 -65
- package/project/root/detect.d.ts.map +0 -1
- package/project/root/index.cjs.js.map +0 -1
- package/project/root/index.esm.js.map +0 -1
- package/project/traversal/index.cjs.js.map +0 -1
- package/project/traversal/index.esm.js.map +0 -1
- package/project/traversal/search.d.ts +0 -59
- package/project/traversal/search.d.ts.map +0 -1
- package/project/traversal/walk.d.ts +0 -63
- package/project/traversal/walk.d.ts.map +0 -1
- package/tech/backend/detect-all.d.ts +0 -13
- package/tech/backend/detect-all.d.ts.map +0 -1
- package/tech/backend/express.d.ts +0 -11
- package/tech/backend/express.d.ts.map +0 -1
- package/tech/backend/fastify.d.ts +0 -11
- package/tech/backend/fastify.d.ts.map +0 -1
- package/tech/backend/hono.d.ts +0 -11
- package/tech/backend/hono.d.ts.map +0 -1
- package/tech/backend/index.cjs.js.map +0 -1
- package/tech/backend/index.esm.js.map +0 -1
- package/tech/backend/koa.d.ts +0 -11
- package/tech/backend/koa.d.ts.map +0 -1
- package/tech/backend/nestjs.d.ts +0 -11
- package/tech/backend/nestjs.d.ts.map +0 -1
- package/tech/backend/types.d.ts +0 -31
- package/tech/backend/types.d.ts.map +0 -1
- package/tech/build/babel.d.ts +0 -13
- package/tech/build/babel.d.ts.map +0 -1
- package/tech/build/detect-all.d.ts +0 -13
- package/tech/build/detect-all.d.ts.map +0 -1
- package/tech/build/esbuild.d.ts +0 -11
- package/tech/build/esbuild.d.ts.map +0 -1
- package/tech/build/index.cjs.js.map +0 -1
- package/tech/build/index.esm.js.map +0 -1
- package/tech/build/parcel.d.ts +0 -13
- package/tech/build/parcel.d.ts.map +0 -1
- package/tech/build/rollup.d.ts +0 -13
- package/tech/build/rollup.d.ts.map +0 -1
- package/tech/build/swc.d.ts +0 -13
- package/tech/build/swc.d.ts.map +0 -1
- package/tech/build/types.d.ts +0 -31
- package/tech/build/types.d.ts.map +0 -1
- package/tech/build/vite.d.ts +0 -13
- package/tech/build/vite.d.ts.map +0 -1
- package/tech/build/webpack.d.ts +0 -13
- package/tech/build/webpack.d.ts.map +0 -1
- package/tech/frontend/angular.d.ts +0 -11
- package/tech/frontend/angular.d.ts.map +0 -1
- package/tech/frontend/astro.d.ts +0 -11
- package/tech/frontend/astro.d.ts.map +0 -1
- package/tech/frontend/detect-all.d.ts +0 -13
- package/tech/frontend/detect-all.d.ts.map +0 -1
- package/tech/frontend/gatsby.d.ts +0 -11
- package/tech/frontend/gatsby.d.ts.map +0 -1
- package/tech/frontend/index.cjs.js.map +0 -1
- package/tech/frontend/index.esm.js.map +0 -1
- package/tech/frontend/nextjs.d.ts +0 -11
- package/tech/frontend/nextjs.d.ts.map +0 -1
- package/tech/frontend/nuxt.d.ts +0 -11
- package/tech/frontend/nuxt.d.ts.map +0 -1
- package/tech/frontend/qwik.d.ts +0 -11
- package/tech/frontend/qwik.d.ts.map +0 -1
- package/tech/frontend/react.d.ts +0 -11
- package/tech/frontend/react.d.ts.map +0 -1
- package/tech/frontend/remix.d.ts +0 -11
- package/tech/frontend/remix.d.ts.map +0 -1
- package/tech/frontend/solid.d.ts +0 -11
- package/tech/frontend/solid.d.ts.map +0 -1
- package/tech/frontend/svelte.d.ts +0 -11
- package/tech/frontend/svelte.d.ts.map +0 -1
- package/tech/frontend/sveltekit.d.ts +0 -11
- package/tech/frontend/sveltekit.d.ts.map +0 -1
- package/tech/frontend/types.d.ts +0 -35
- package/tech/frontend/types.d.ts.map +0 -1
- package/tech/frontend/vue.d.ts +0 -11
- package/tech/frontend/vue.d.ts.map +0 -1
- package/tech/index.cjs.js.map +0 -1
- package/tech/index.esm.js.map +0 -1
- package/tech/legacy/angularjs.d.ts +0 -12
- package/tech/legacy/angularjs.d.ts.map +0 -1
- package/tech/legacy/backbone.d.ts +0 -11
- package/tech/legacy/backbone.d.ts.map +0 -1
- package/tech/legacy/detect-all.d.ts +0 -13
- package/tech/legacy/detect-all.d.ts.map +0 -1
- package/tech/legacy/ember.d.ts +0 -11
- package/tech/legacy/ember.d.ts.map +0 -1
- package/tech/legacy/index.cjs.js.map +0 -1
- package/tech/legacy/index.esm.js.map +0 -1
- package/tech/legacy/jquery.d.ts +0 -11
- package/tech/legacy/jquery.d.ts.map +0 -1
- package/tech/legacy/types.d.ts +0 -33
- package/tech/legacy/types.d.ts.map +0 -1
- package/tech/linting/biome.d.ts +0 -11
- package/tech/linting/biome.d.ts.map +0 -1
- package/tech/linting/detect-all.d.ts +0 -13
- package/tech/linting/detect-all.d.ts.map +0 -1
- package/tech/linting/eslint.d.ts +0 -13
- package/tech/linting/eslint.d.ts.map +0 -1
- package/tech/linting/index.cjs.js.map +0 -1
- package/tech/linting/index.esm.js.map +0 -1
- package/tech/linting/prettier.d.ts +0 -13
- package/tech/linting/prettier.d.ts.map +0 -1
- package/tech/linting/stylelint.d.ts +0 -13
- package/tech/linting/stylelint.d.ts.map +0 -1
- package/tech/linting/types.d.ts +0 -31
- package/tech/linting/types.d.ts.map +0 -1
- package/tech/monorepo/detect-all.d.ts +0 -13
- package/tech/monorepo/detect-all.d.ts.map +0 -1
- package/tech/monorepo/index.cjs.js.map +0 -1
- package/tech/monorepo/index.esm.js.map +0 -1
- package/tech/monorepo/lerna.d.ts +0 -11
- package/tech/monorepo/lerna.d.ts.map +0 -1
- package/tech/monorepo/npm-workspaces.d.ts +0 -11
- package/tech/monorepo/npm-workspaces.d.ts.map +0 -1
- package/tech/monorepo/nx.d.ts +0 -11
- package/tech/monorepo/nx.d.ts.map +0 -1
- package/tech/monorepo/pnpm-workspaces.d.ts +0 -9
- package/tech/monorepo/pnpm-workspaces.d.ts.map +0 -1
- package/tech/monorepo/rush.d.ts +0 -11
- package/tech/monorepo/rush.d.ts.map +0 -1
- package/tech/monorepo/turborepo.d.ts +0 -11
- package/tech/monorepo/turborepo.d.ts.map +0 -1
- package/tech/monorepo/types.d.ts +0 -39
- package/tech/monorepo/types.d.ts.map +0 -1
- package/tech/monorepo/yarn-workspaces.d.ts +0 -11
- package/tech/monorepo/yarn-workspaces.d.ts.map +0 -1
- package/tech/shared-utils/detector-helpers.d.ts +0 -52
- package/tech/shared-utils/detector-helpers.d.ts.map +0 -1
- package/tech/shared-utils/types.d.ts +0 -41
- package/tech/shared-utils/types.d.ts.map +0 -1
- package/tech/testing/cypress.d.ts +0 -13
- package/tech/testing/cypress.d.ts.map +0 -1
- package/tech/testing/detect-all.d.ts +0 -13
- package/tech/testing/detect-all.d.ts.map +0 -1
- package/tech/testing/index.cjs.js.map +0 -1
- package/tech/testing/index.esm.js.map +0 -1
- package/tech/testing/jest.d.ts +0 -13
- package/tech/testing/jest.d.ts.map +0 -1
- package/tech/testing/mocha.d.ts +0 -13
- package/tech/testing/mocha.d.ts.map +0 -1
- package/tech/testing/playwright.d.ts +0 -13
- package/tech/testing/playwright.d.ts.map +0 -1
- package/tech/testing/types.d.ts +0 -35
- package/tech/testing/types.d.ts.map +0 -1
- package/tech/testing/vitest.d.ts +0 -13
- package/tech/testing/vitest.d.ts.map +0 -1
- package/tech/types/detectors.d.ts +0 -67
- package/tech/types/detectors.d.ts.map +0 -1
- package/tech/types/index.cjs.js.map +0 -1
- package/tech/types/index.esm.js.map +0 -1
- package/vfs/commit.d.ts +0 -32
- package/vfs/commit.d.ts.map +0 -1
- package/vfs/diff.d.ts +0 -73
- package/vfs/diff.d.ts.map +0 -1
- package/vfs/factory.d.ts +0 -37
- package/vfs/factory.d.ts.map +0 -1
- package/vfs/fs-tree.d.ts +0 -13
- package/vfs/fs-tree.d.ts.map +0 -1
- package/vfs/index.cjs.js.map +0 -1
- package/vfs/index.esm.js.map +0 -1
- package/vfs/types.d.ts +0 -179
- package/vfs/types.d.ts.map +0 -1
package/cli/index.esm.js
CHANGED
|
@@ -1,445 +1,25 @@
|
|
|
1
|
+
import { join as join$1, resolve, parse, dirname, basename } from 'node:path';
|
|
1
2
|
import { parseArgs } from 'node:util';
|
|
2
|
-
import {
|
|
3
|
+
import { isArray } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.esm.js';
|
|
4
|
+
import { stringify, parse as parse$1 } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.esm.js';
|
|
5
|
+
import { freeze, entries, keys, defineProperties, values } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.esm.js';
|
|
6
|
+
import { dateNow, createDate } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.esm.js';
|
|
3
7
|
import { existsSync, readFileSync, statSync, lstatSync, readdirSync } from 'node:fs';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* (Safe copy) Outputs a warning message to the console.
|
|
20
|
-
*/
|
|
21
|
-
const warn = _console.warn.bind(_console);
|
|
22
|
-
/**
|
|
23
|
-
* (Safe copy) Outputs an error message to the console.
|
|
24
|
-
*/
|
|
25
|
-
const error = _console.error.bind(_console);
|
|
26
|
-
/**
|
|
27
|
-
* (Safe copy) Outputs an informational message to the console.
|
|
28
|
-
*/
|
|
29
|
-
const info = _console.info.bind(_console);
|
|
30
|
-
/**
|
|
31
|
-
* (Safe copy) Outputs a debug message to the console.
|
|
32
|
-
*/
|
|
33
|
-
const debug = _console.debug.bind(_console);
|
|
34
|
-
/**
|
|
35
|
-
* (Safe copy) Outputs a stack trace to the console.
|
|
36
|
-
*/
|
|
37
|
-
_console.trace.bind(_console);
|
|
38
|
-
/**
|
|
39
|
-
* (Safe copy) Displays an interactive listing of the properties of a specified object.
|
|
40
|
-
*/
|
|
41
|
-
_console.dir.bind(_console);
|
|
42
|
-
/**
|
|
43
|
-
* (Safe copy) Displays tabular data as a table.
|
|
44
|
-
*/
|
|
45
|
-
_console.table.bind(_console);
|
|
46
|
-
/**
|
|
47
|
-
* (Safe copy) Writes an error message to the console if the assertion is false.
|
|
48
|
-
*/
|
|
49
|
-
_console.assert.bind(_console);
|
|
50
|
-
/**
|
|
51
|
-
* (Safe copy) Clears the console.
|
|
52
|
-
*/
|
|
53
|
-
_console.clear.bind(_console);
|
|
54
|
-
/**
|
|
55
|
-
* (Safe copy) Logs the number of times that this particular call to count() has been called.
|
|
56
|
-
*/
|
|
57
|
-
_console.count.bind(_console);
|
|
58
|
-
/**
|
|
59
|
-
* (Safe copy) Resets the counter used with console.count().
|
|
60
|
-
*/
|
|
61
|
-
_console.countReset.bind(_console);
|
|
62
|
-
/**
|
|
63
|
-
* (Safe copy) Creates a new inline group in the console.
|
|
64
|
-
*/
|
|
65
|
-
_console.group.bind(_console);
|
|
66
|
-
/**
|
|
67
|
-
* (Safe copy) Creates a new inline group in the console that is initially collapsed.
|
|
68
|
-
*/
|
|
69
|
-
_console.groupCollapsed.bind(_console);
|
|
70
|
-
/**
|
|
71
|
-
* (Safe copy) Exits the current inline group.
|
|
72
|
-
*/
|
|
73
|
-
_console.groupEnd.bind(_console);
|
|
74
|
-
/**
|
|
75
|
-
* (Safe copy) Starts a timer with a name specified as an input parameter.
|
|
76
|
-
*/
|
|
77
|
-
_console.time.bind(_console);
|
|
78
|
-
/**
|
|
79
|
-
* (Safe copy) Stops a timer that was previously started.
|
|
80
|
-
*/
|
|
81
|
-
_console.timeEnd.bind(_console);
|
|
82
|
-
/**
|
|
83
|
-
* (Safe copy) Logs the current value of a timer that was previously started.
|
|
84
|
-
*/
|
|
85
|
-
_console.timeLog.bind(_console);
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Safe copies of Object built-in methods.
|
|
89
|
-
*
|
|
90
|
-
* These references are captured at module initialization time to protect against
|
|
91
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
92
|
-
*
|
|
93
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/object
|
|
94
|
-
*/
|
|
95
|
-
const _Object = globalThis.Object;
|
|
96
|
-
/**
|
|
97
|
-
* (Safe copy) Prevents modification of existing property attributes and values,
|
|
98
|
-
* and prevents the addition of new properties.
|
|
99
|
-
*/
|
|
100
|
-
const freeze = _Object.freeze;
|
|
101
|
-
/**
|
|
102
|
-
* (Safe copy) Returns the names of the enumerable string properties and methods of an object.
|
|
103
|
-
*/
|
|
104
|
-
const keys = _Object.keys;
|
|
105
|
-
/**
|
|
106
|
-
* (Safe copy) Returns an array of key/values of the enumerable own properties of an object.
|
|
107
|
-
*/
|
|
108
|
-
const entries = _Object.entries;
|
|
109
|
-
/**
|
|
110
|
-
* (Safe copy) Returns an array of values of the enumerable own properties of an object.
|
|
111
|
-
*/
|
|
112
|
-
const values = _Object.values;
|
|
113
|
-
/**
|
|
114
|
-
* (Safe copy) Adds one or more properties to an object, and/or modifies attributes of existing properties.
|
|
115
|
-
*/
|
|
116
|
-
const defineProperties = _Object.defineProperties;
|
|
117
|
-
|
|
118
|
-
const registeredClasses = [];
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Safe copies of Array built-in static methods.
|
|
122
|
-
*
|
|
123
|
-
* These references are captured at module initialization time to protect against
|
|
124
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
125
|
-
*
|
|
126
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
127
|
-
*/
|
|
128
|
-
const _Array = globalThis.Array;
|
|
129
|
-
/**
|
|
130
|
-
* (Safe copy) Determines whether the passed value is an Array.
|
|
131
|
-
*/
|
|
132
|
-
const isArray = _Array.isArray;
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Returns the data type of the target.
|
|
136
|
-
* Uses native `typeof` operator, however, makes distinction between `null`, `array`, and `object`.
|
|
137
|
-
* Also, when classes are registered via `registerClass`, it checks if objects are instance of any known registered class.
|
|
138
|
-
*
|
|
139
|
-
* @param target - The target to get the data type of.
|
|
140
|
-
* @returns The data type of the target.
|
|
141
|
-
*/
|
|
142
|
-
const getType = (target) => {
|
|
143
|
-
if (target === null)
|
|
144
|
-
return 'null';
|
|
145
|
-
const nativeDataType = typeof target;
|
|
146
|
-
if (nativeDataType === 'object') {
|
|
147
|
-
if (isArray(target))
|
|
148
|
-
return 'array';
|
|
149
|
-
for (const registeredClass of registeredClasses) {
|
|
150
|
-
if (target instanceof registeredClass)
|
|
151
|
-
return registeredClass.name;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return nativeDataType;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Safe copies of Error built-ins via factory functions.
|
|
159
|
-
*
|
|
160
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
161
|
-
* provides factory functions that use Reflect.construct internally.
|
|
162
|
-
*
|
|
163
|
-
* These references are captured at module initialization time to protect against
|
|
164
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
165
|
-
*
|
|
166
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
167
|
-
*/
|
|
168
|
-
const _Error = globalThis.Error;
|
|
169
|
-
const _Reflect$3 = globalThis.Reflect;
|
|
170
|
-
/**
|
|
171
|
-
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
172
|
-
* Use this instead of `new Error()`.
|
|
173
|
-
*
|
|
174
|
-
* @param message - Optional error message.
|
|
175
|
-
* @param options - Optional error options.
|
|
176
|
-
* @returns A new Error instance.
|
|
177
|
-
*/
|
|
178
|
-
const createError = (message, options) => _Reflect$3.construct(_Error, [message, options]);
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Safe copies of Map built-in via factory function.
|
|
182
|
-
*
|
|
183
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
184
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
185
|
-
*
|
|
186
|
-
* These references are captured at module initialization time to protect against
|
|
187
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
188
|
-
*
|
|
189
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/map
|
|
190
|
-
*/
|
|
191
|
-
const _Map = globalThis.Map;
|
|
192
|
-
const _Reflect$2 = globalThis.Reflect;
|
|
193
|
-
/**
|
|
194
|
-
* (Safe copy) Creates a new Map using the captured Map constructor.
|
|
195
|
-
* Use this instead of `new Map()`.
|
|
196
|
-
*
|
|
197
|
-
* @param iterable - Optional iterable of key-value pairs.
|
|
198
|
-
* @returns A new Map instance.
|
|
199
|
-
*/
|
|
200
|
-
const createMap = (iterable) => _Reflect$2.construct(_Map, iterable ? [iterable] : []);
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Safe copies of Date built-in via factory function and static methods.
|
|
204
|
-
*
|
|
205
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
206
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
207
|
-
*
|
|
208
|
-
* These references are captured at module initialization time to protect against
|
|
209
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
210
|
-
*
|
|
211
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/date
|
|
212
|
-
*/
|
|
213
|
-
const _Date = globalThis.Date;
|
|
214
|
-
const _Reflect$1 = globalThis.Reflect;
|
|
215
|
-
function createDate(...args) {
|
|
216
|
-
return _Reflect$1.construct(_Date, args);
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* (Safe copy) Returns the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC.
|
|
220
|
-
*/
|
|
221
|
-
const dateNow = _Date.now;
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Safe copies of Math built-in methods.
|
|
225
|
-
*
|
|
226
|
-
* These references are captured at module initialization time to protect against
|
|
227
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
228
|
-
*
|
|
229
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/math
|
|
230
|
-
*/
|
|
231
|
-
const _Math = globalThis.Math;
|
|
232
|
-
/**
|
|
233
|
-
* (Safe copy) Returns the value of a number rounded to the nearest integer.
|
|
234
|
-
*/
|
|
235
|
-
const round = _Math.round;
|
|
236
|
-
/**
|
|
237
|
-
* (Safe copy) Returns the smaller of zero or more numbers.
|
|
238
|
-
*/
|
|
239
|
-
const min = _Math.min;
|
|
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
|
-
|
|
263
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
264
|
-
/**
|
|
265
|
-
* Creates a wrapper function that only executes the wrapped function if the condition function returns true.
|
|
266
|
-
*
|
|
267
|
-
* @param func - The function to be conditionally executed.
|
|
268
|
-
* @param conditionFunc - A function that returns a boolean, determining if `func` should be executed.
|
|
269
|
-
* @returns A wrapped version of `func` that executes conditionally.
|
|
270
|
-
*/
|
|
271
|
-
function createConditionalExecutionFunction(func, conditionFunc) {
|
|
272
|
-
return function (...args) {
|
|
273
|
-
if (conditionFunc()) {
|
|
274
|
-
return func(...args);
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
280
|
-
/**
|
|
281
|
-
* Creates a wrapper function that silently ignores any errors thrown by the wrapped void function.
|
|
282
|
-
* This function is specifically for wrapping functions that do not return a value (void functions).
|
|
283
|
-
* Exceptions are swallowed without any logging or handling.
|
|
284
|
-
*
|
|
285
|
-
* @param func - The void function to be wrapped.
|
|
286
|
-
* @returns A wrapped version of the input function that ignores errors.
|
|
287
|
-
*/
|
|
288
|
-
function createErrorIgnoringFunction(func) {
|
|
289
|
-
return function (...args) {
|
|
290
|
-
try {
|
|
291
|
-
func(...args);
|
|
292
|
-
}
|
|
293
|
-
catch {
|
|
294
|
-
// Deliberately swallowing/ignoring the exception
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
300
|
-
/**
|
|
301
|
-
* A no-operation function (noop) that does nothing regardless of the arguments passed.
|
|
302
|
-
* It is designed to be as permissive as possible in its typing without using the `Function` keyword.
|
|
303
|
-
*
|
|
304
|
-
* @param args - Any arguments passed to the function (ignored)
|
|
305
|
-
*/
|
|
306
|
-
const noop = (...args) => {
|
|
307
|
-
// Intentionally does nothing
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
const logLevels = ['none', 'error', 'warn', 'log', 'info', 'debug'];
|
|
311
|
-
const priority = {
|
|
312
|
-
error: 4,
|
|
313
|
-
warn: 3,
|
|
314
|
-
log: 2,
|
|
315
|
-
info: 1,
|
|
316
|
-
debug: 0,
|
|
317
|
-
};
|
|
318
|
-
/**
|
|
319
|
-
* Validates whether a given string is a valid log level.
|
|
320
|
-
*
|
|
321
|
-
* @param level - The log level to validate
|
|
322
|
-
* @returns True if the level is valid, false otherwise
|
|
323
|
-
*/
|
|
324
|
-
function isValidLogLevel(level) {
|
|
325
|
-
return logLevels.includes(level);
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Creates a log level configuration manager for controlling logging behavior.
|
|
329
|
-
* Provides methods to get, set, and evaluate log levels based on priority.
|
|
330
|
-
*
|
|
331
|
-
* @param level - The initial log level (defaults to 'error')
|
|
332
|
-
* @returns A configuration object with log level management methods
|
|
333
|
-
* @throws {Error} When the provided level is not a valid log level
|
|
334
|
-
*/
|
|
335
|
-
function createLogLevelConfig(level = 'error') {
|
|
336
|
-
if (!isValidLogLevel(level)) {
|
|
337
|
-
throw createError('Cannot create log level configuration with a valid default log level');
|
|
338
|
-
}
|
|
339
|
-
const state = { level };
|
|
340
|
-
const getLogLevel = () => state.level;
|
|
341
|
-
const setLogLevel = (level) => {
|
|
342
|
-
if (!isValidLogLevel(level)) {
|
|
343
|
-
throw createError(`Cannot set value '${level}' level. Expected levels are ${logLevels}.`);
|
|
344
|
-
}
|
|
345
|
-
state.level = level;
|
|
346
|
-
};
|
|
347
|
-
const shouldLog = (level) => {
|
|
348
|
-
if (state.level === 'none' || level === 'none' || !isValidLogLevel(level)) {
|
|
349
|
-
return false;
|
|
350
|
-
}
|
|
351
|
-
return priority[level] >= priority[state.level];
|
|
352
|
-
};
|
|
353
|
-
return freeze({
|
|
354
|
-
getLogLevel,
|
|
355
|
-
setLogLevel,
|
|
356
|
-
shouldLog,
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Creates a logger instance with configurable log level filtering.
|
|
362
|
-
* Each log function is wrapped to respect the current log level setting.
|
|
363
|
-
*
|
|
364
|
-
* @param error - Function to handle error-level logs (required)
|
|
365
|
-
* @param warn - Function to handle warning-level logs (optional, defaults to noop)
|
|
366
|
-
* @param log - Function to handle standard logs (optional, defaults to noop)
|
|
367
|
-
* @param info - Function to handle info-level logs (optional, defaults to noop)
|
|
368
|
-
* @param debug - Function to handle debug-level logs (optional, defaults to noop)
|
|
369
|
-
* @returns A frozen logger object with log methods and level control
|
|
370
|
-
* @throws {ErrorLevelFn} When any provided log function is invalid
|
|
371
|
-
*/
|
|
372
|
-
function createLogger(error, warn = noop, log = noop, info = noop, debug = noop) {
|
|
373
|
-
if (notValidLogFn(error)) {
|
|
374
|
-
throw createError(notFnMsg('error'));
|
|
375
|
-
}
|
|
376
|
-
if (notValidLogFn(warn)) {
|
|
377
|
-
throw createError(notFnMsg('warn'));
|
|
378
|
-
}
|
|
379
|
-
if (notValidLogFn(log)) {
|
|
380
|
-
throw createError(notFnMsg('log'));
|
|
381
|
-
}
|
|
382
|
-
if (notValidLogFn(info)) {
|
|
383
|
-
throw createError(notFnMsg('info'));
|
|
384
|
-
}
|
|
385
|
-
if (notValidLogFn(debug)) {
|
|
386
|
-
throw createError(notFnMsg('debug'));
|
|
387
|
-
}
|
|
388
|
-
const { setLogLevel, getLogLevel, shouldLog } = createLogLevelConfig();
|
|
389
|
-
const wrapLogFn = (fn, level) => {
|
|
390
|
-
if (fn === noop)
|
|
391
|
-
return fn;
|
|
392
|
-
const condition = () => shouldLog(level);
|
|
393
|
-
return createConditionalExecutionFunction(createErrorIgnoringFunction(fn), condition);
|
|
394
|
-
};
|
|
395
|
-
return freeze({
|
|
396
|
-
error: wrapLogFn(error, 'error'),
|
|
397
|
-
warn: wrapLogFn(warn, 'warn'),
|
|
398
|
-
log: wrapLogFn(log, 'log'),
|
|
399
|
-
info: wrapLogFn(info, 'info'),
|
|
400
|
-
debug: wrapLogFn(debug, 'debug'),
|
|
401
|
-
setLogLevel,
|
|
402
|
-
getLogLevel,
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Validates whether a given value is a valid log function.
|
|
407
|
-
*
|
|
408
|
-
* @param fn - The value to validate
|
|
409
|
-
* @returns True if the value is not a function (invalid), false if it is valid
|
|
410
|
-
*/
|
|
411
|
-
function notValidLogFn(fn) {
|
|
412
|
-
return getType(fn) !== 'function' && fn !== noop;
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Generates an error message for invalid log function parameters.
|
|
416
|
-
*
|
|
417
|
-
* @param label - The name of the log function that failed validation
|
|
418
|
-
* @returns A formatted error message string
|
|
419
|
-
*/
|
|
420
|
-
function notFnMsg(label) {
|
|
421
|
-
return `Cannot create a logger when ${label} is not a function`;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
createLogger(error, warn, log, info, debug);
|
|
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;
|
|
8
|
+
import { error, warn, log, info, debug } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.esm.js';
|
|
9
|
+
import { createSet } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.esm.js';
|
|
10
|
+
import { createLogger } from '../_dependencies/@hyperfrontend/logging/index.esm.js';
|
|
11
|
+
import { createError } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js';
|
|
12
|
+
import { createMap } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.esm.js';
|
|
13
|
+
import { min, round } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.esm.js';
|
|
14
|
+
import { parseInt, parseFloat } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.esm.js';
|
|
15
|
+
import { getFileStat, isDirectory, exists } from '../_shared/core/fs/stat/index.esm.js';
|
|
16
|
+
import { join } from '../_shared/core/path/join/index.esm.js';
|
|
17
|
+
import { createConfigError } from '../_shared/core/errors/structured-errors/index.esm.js';
|
|
18
|
+
import { createCache } from '../_shared/core/cache/index.esm.js';
|
|
19
|
+
import { matchGlobPattern } from '../_shared/core/patterns/glob/index.esm.js';
|
|
20
|
+
import { collectAllDependencies, parseVersionString, locateConfigFile, filterScriptsByCommand } from '../_shared/tech/shared-utils/detector-helpers/index.esm.js';
|
|
21
|
+
import { pnpmWorkspacesDetector } from '../_shared/tech/monorepo/pnpm-workspaces/index.esm.js';
|
|
22
|
+
import { CONFIG_PATTERNS } from '../_shared/project/config/patterns/index.esm.js';
|
|
443
23
|
|
|
444
24
|
/**
|
|
445
25
|
* Global log level registry.
|
|
@@ -457,7 +37,7 @@ let globalLogLevel = null;
|
|
|
457
37
|
*
|
|
458
38
|
* @param level - The log level to set globally
|
|
459
39
|
*
|
|
460
|
-
* @example
|
|
40
|
+
* @example Enabling debug logging globally
|
|
461
41
|
* ```typescript
|
|
462
42
|
* import { setGlobalLogLevel } from '@hyperfrontend/project-scope/core'
|
|
463
43
|
*
|
|
@@ -504,6 +84,13 @@ function isSensitiveKey(key) {
|
|
|
504
84
|
*
|
|
505
85
|
* @param obj - Object to sanitize
|
|
506
86
|
* @returns New object with sensitive values redacted
|
|
87
|
+
*
|
|
88
|
+
* @example Sanitizing sensitive data
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const config = { apiKey: 'secret123', endpoint: 'https://api.example.com' }
|
|
91
|
+
* const safe = sanitize(config)
|
|
92
|
+
* // => { apiKey: '[REDACTED]', endpoint: 'https://api.example.com' }
|
|
93
|
+
* ```
|
|
507
94
|
*/
|
|
508
95
|
function sanitize(obj) {
|
|
509
96
|
if (obj === null || obj === undefined) {
|
|
@@ -554,7 +141,7 @@ function formatMessage(namespace, message, meta) {
|
|
|
554
141
|
* @param options - Logger configuration options
|
|
555
142
|
* @returns A configured scoped logger instance
|
|
556
143
|
*
|
|
557
|
-
* @example
|
|
144
|
+
* @example Creating a scoped logger
|
|
558
145
|
* ```typescript
|
|
559
146
|
* const logger = createScopedLogger('project-scope')
|
|
560
147
|
* logger.setLogLevel('debug')
|
|
@@ -591,7 +178,7 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
591
178
|
* Default logger instance for the project-scope library.
|
|
592
179
|
* Use this for general logging within the library.
|
|
593
180
|
*
|
|
594
|
-
* @example
|
|
181
|
+
* @example Using the default logger
|
|
595
182
|
* ```typescript
|
|
596
183
|
* import { logger } from '@hyperfrontend/project-scope/core'
|
|
597
184
|
*
|
|
@@ -609,6 +196,15 @@ const fsLogger = createScopedLogger('project-scope:fs');
|
|
|
609
196
|
* @param code - The category code for this type of filesystem failure
|
|
610
197
|
* @param context - Additional context including path, operation, and cause
|
|
611
198
|
* @returns A configured Error object with code and context properties
|
|
199
|
+
*
|
|
200
|
+
* @example Creating a file system error
|
|
201
|
+
* ```typescript
|
|
202
|
+
* throw createFileSystemError(
|
|
203
|
+
* 'Cannot read file',
|
|
204
|
+
* 'FS_READ_ERROR',
|
|
205
|
+
* { path: './missing.txt', operation: 'read' }
|
|
206
|
+
* )
|
|
207
|
+
* ```
|
|
612
208
|
*/
|
|
613
209
|
function createFileSystemError(message, code, context) {
|
|
614
210
|
const error = createError(message);
|
|
@@ -626,7 +222,7 @@ function createFileSystemError(message, code, context) {
|
|
|
626
222
|
* @returns File contents as string
|
|
627
223
|
* @throws {Error} If file doesn't exist or can't be read
|
|
628
224
|
*
|
|
629
|
-
* @example
|
|
225
|
+
* @example Reading file contents
|
|
630
226
|
* ```typescript
|
|
631
227
|
* import { readFileContent } from '@hyperfrontend/project-scope'
|
|
632
228
|
*
|
|
@@ -653,6 +249,14 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
653
249
|
* @param filePath - Path to file
|
|
654
250
|
* @param encoding - File encoding (default: utf-8)
|
|
655
251
|
* @returns File contents or null if file doesn't exist
|
|
252
|
+
*
|
|
253
|
+
* @example Reading file if it exists
|
|
254
|
+
* ```typescript
|
|
255
|
+
* const content = readFileIfExists('./optional-config.json')
|
|
256
|
+
* if (content) {
|
|
257
|
+
* // File existed, use content
|
|
258
|
+
* }
|
|
259
|
+
* ```
|
|
656
260
|
*/
|
|
657
261
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
658
262
|
if (!existsSync(filePath)) {
|
|
@@ -666,56 +270,6 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
666
270
|
}
|
|
667
271
|
}
|
|
668
272
|
|
|
669
|
-
createScopedLogger('project-scope:fs:write');
|
|
670
|
-
|
|
671
|
-
/**
|
|
672
|
-
* Get file stats with error handling.
|
|
673
|
-
*
|
|
674
|
-
* @param filePath - Path to file
|
|
675
|
-
* @param followSymlinks - Whether to follow symlinks (default: true)
|
|
676
|
-
* @returns File stats or null if path doesn't exist
|
|
677
|
-
*/
|
|
678
|
-
function getFileStat(filePath, followSymlinks = true) {
|
|
679
|
-
if (!existsSync(filePath)) {
|
|
680
|
-
return null;
|
|
681
|
-
}
|
|
682
|
-
try {
|
|
683
|
-
const stat = followSymlinks ? statSync(filePath) : lstatSync(filePath);
|
|
684
|
-
return {
|
|
685
|
-
isFile: stat.isFile(),
|
|
686
|
-
isDirectory: stat.isDirectory(),
|
|
687
|
-
isSymlink: stat.isSymbolicLink(),
|
|
688
|
-
size: stat.size,
|
|
689
|
-
created: stat.birthtime,
|
|
690
|
-
modified: stat.mtime,
|
|
691
|
-
accessed: stat.atime,
|
|
692
|
-
mode: stat.mode,
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
catch {
|
|
696
|
-
return null;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
/**
|
|
700
|
-
* Check if path is a directory.
|
|
701
|
-
*
|
|
702
|
-
* @param dirPath - Path to check
|
|
703
|
-
* @returns True if path is a directory
|
|
704
|
-
*/
|
|
705
|
-
function isDirectory(dirPath) {
|
|
706
|
-
const stats = getFileStat(dirPath);
|
|
707
|
-
return stats?.isDirectory ?? false;
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* Check if path exists.
|
|
711
|
-
*
|
|
712
|
-
* @param filePath - Path to check
|
|
713
|
-
* @returns True if path exists
|
|
714
|
-
*/
|
|
715
|
-
function exists(filePath) {
|
|
716
|
-
return existsSync(filePath);
|
|
717
|
-
}
|
|
718
|
-
|
|
719
273
|
const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
720
274
|
/**
|
|
721
275
|
* List immediate contents of a directory.
|
|
@@ -724,7 +278,7 @@ const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
|
724
278
|
* @returns Array of entries with metadata for each file/directory
|
|
725
279
|
* @throws {Error} If directory doesn't exist or isn't a directory
|
|
726
280
|
*
|
|
727
|
-
* @example
|
|
281
|
+
* @example Listing directory contents
|
|
728
282
|
* ```typescript
|
|
729
283
|
* import { readDirectory } from '@hyperfrontend/project-scope'
|
|
730
284
|
*
|
|
@@ -765,17 +319,6 @@ function readDirectory(dirPath) {
|
|
|
765
319
|
}
|
|
766
320
|
}
|
|
767
321
|
|
|
768
|
-
/**
|
|
769
|
-
* Join path segments.
|
|
770
|
-
* Uses platform-specific separators (e.g., / or \).
|
|
771
|
-
*
|
|
772
|
-
* @param paths - Path segments to join
|
|
773
|
-
* @returns Joined path
|
|
774
|
-
*/
|
|
775
|
-
function join(...paths) {
|
|
776
|
-
return join$1(...paths);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
322
|
const fsTraversalLogger = createScopedLogger('project-scope:fs:traversal');
|
|
780
323
|
/**
|
|
781
324
|
* Generic upward directory traversal.
|
|
@@ -784,11 +327,20 @@ const fsTraversalLogger = createScopedLogger('project-scope:fs:traversal');
|
|
|
784
327
|
* @param startPath - Starting directory
|
|
785
328
|
* @param predicate - Function to test each directory
|
|
786
329
|
* @returns First matching directory or null
|
|
330
|
+
*
|
|
331
|
+
* @example Finding directory containing README
|
|
332
|
+
* ```typescript
|
|
333
|
+
* // Find first directory containing a README
|
|
334
|
+
* const readmeDir = traverseUpward('./src/utils', (dir) =>
|
|
335
|
+
* existsSync(join(dir, 'README.md'))
|
|
336
|
+
* )
|
|
337
|
+
* // => '/project' or null
|
|
338
|
+
* ```
|
|
787
339
|
*/
|
|
788
340
|
function traverseUpward(startPath, predicate) {
|
|
789
341
|
fsTraversalLogger.debug('Starting upward traversal', { startPath });
|
|
790
342
|
let currentPath = resolve(startPath);
|
|
791
|
-
const rootPath = parse
|
|
343
|
+
const rootPath = parse(currentPath).root;
|
|
792
344
|
while (currentPath !== rootPath) {
|
|
793
345
|
if (predicate(currentPath)) {
|
|
794
346
|
fsTraversalLogger.debug('Upward traversal found match', { startPath, foundPath: currentPath });
|
|
@@ -809,6 +361,17 @@ function traverseUpward(startPath, predicate) {
|
|
|
809
361
|
* @param startPath - Starting directory
|
|
810
362
|
* @param markers - Array of marker file names to search for
|
|
811
363
|
* @returns First directory containing any marker, or null
|
|
364
|
+
*
|
|
365
|
+
* @example Finding project root by marker files
|
|
366
|
+
* ```typescript
|
|
367
|
+
* // Find project root by looking for common marker files
|
|
368
|
+
* const projectRoot = locateByMarkers('./src/components', [
|
|
369
|
+
* 'package.json',
|
|
370
|
+
* 'nx.json',
|
|
371
|
+
* 'tsconfig.base.json'
|
|
372
|
+
* ])
|
|
373
|
+
* // => '/workspace/my-project'
|
|
374
|
+
* ```
|
|
812
375
|
*/
|
|
813
376
|
function locateByMarkers(startPath, markers) {
|
|
814
377
|
fsTraversalLogger.debug('Locating by markers', { startPath, markers });
|
|
@@ -819,42 +382,7 @@ function locateByMarkers(startPath, markers) {
|
|
|
819
382
|
return result;
|
|
820
383
|
}
|
|
821
384
|
|
|
822
|
-
|
|
823
|
-
* Create a structured error with code and optional context.
|
|
824
|
-
*
|
|
825
|
-
* @param message - The human-readable error message
|
|
826
|
-
* @param code - The machine-readable error code for programmatic handling
|
|
827
|
-
* @param context - Additional contextual information about the error
|
|
828
|
-
* @returns Structured error instance with code and context properties
|
|
829
|
-
*
|
|
830
|
-
* @example
|
|
831
|
-
* ```typescript
|
|
832
|
-
* import { createStructuredError } from '@hyperfrontend/project-scope'
|
|
833
|
-
*
|
|
834
|
-
* throw createStructuredError(
|
|
835
|
-
* 'Configuration file not found',
|
|
836
|
-
* 'CONFIG_NOT_FOUND',
|
|
837
|
-
* { path: './config.json', searched: ['./config.json', './settings.json'] }
|
|
838
|
-
* )
|
|
839
|
-
* ```
|
|
840
|
-
*/
|
|
841
|
-
function createStructuredError(message, code, context) {
|
|
842
|
-
const error = createError(message);
|
|
843
|
-
error.code = code;
|
|
844
|
-
error.context = context ?? {};
|
|
845
|
-
return error;
|
|
846
|
-
}
|
|
847
|
-
/**
|
|
848
|
-
* Create a configuration-related error.
|
|
849
|
-
*
|
|
850
|
-
* @param message - The human-readable error message
|
|
851
|
-
* @param code - The machine-readable error code for programmatic handling
|
|
852
|
-
* @param context - Additional contextual information (e.g., file path, config key)
|
|
853
|
-
* @returns Structured error instance tagged with type 'config'
|
|
854
|
-
*/
|
|
855
|
-
function createConfigError(message, code, context) {
|
|
856
|
-
return createStructuredError(message, code, { ...context, type: 'config' });
|
|
857
|
-
}
|
|
385
|
+
createScopedLogger('project-scope:fs:write');
|
|
858
386
|
|
|
859
387
|
const packageLogger = createScopedLogger('project-scope:project:package');
|
|
860
388
|
/**
|
|
@@ -926,13 +454,21 @@ function validatePackageJson(data) {
|
|
|
926
454
|
* @param projectPath - Project directory path or path to package.json
|
|
927
455
|
* @returns Parsed package.json
|
|
928
456
|
* @throws {Error} Error if file doesn't exist or is invalid
|
|
457
|
+
*
|
|
458
|
+
* @example Reading package.json
|
|
459
|
+
* ```typescript
|
|
460
|
+
* import { readPackageJson } from '@hyperfrontend/project-scope'
|
|
461
|
+
*
|
|
462
|
+
* const pkg = readPackageJson('/path/to/project')
|
|
463
|
+
* console.log(pkg.name, pkg.version)
|
|
464
|
+
* ```
|
|
929
465
|
*/
|
|
930
466
|
function readPackageJson(projectPath) {
|
|
931
467
|
const packageJsonPath = projectPath.endsWith('package.json') ? projectPath : join$1(projectPath, 'package.json');
|
|
932
468
|
packageLogger.debug('Reading package.json', { path: packageJsonPath });
|
|
933
469
|
const content = readFileContent(packageJsonPath);
|
|
934
470
|
try {
|
|
935
|
-
const data = parse(content);
|
|
471
|
+
const data = parse$1(content);
|
|
936
472
|
const validated = validatePackageJson(data);
|
|
937
473
|
packageLogger.debug('Package.json read successfully', { path: packageJsonPath, name: validated.name });
|
|
938
474
|
return validated;
|
|
@@ -954,6 +490,16 @@ function readPackageJson(projectPath) {
|
|
|
954
490
|
*
|
|
955
491
|
* @param projectPath - Project directory path or path to package.json
|
|
956
492
|
* @returns Parsed package.json or null if not found
|
|
493
|
+
*
|
|
494
|
+
* @example Reading package.json if it exists
|
|
495
|
+
* ```typescript
|
|
496
|
+
* import { readPackageJsonIfExists } from '@hyperfrontend/project-scope'
|
|
497
|
+
*
|
|
498
|
+
* const pkg = readPackageJsonIfExists('/path/to/project')
|
|
499
|
+
* if (pkg) {
|
|
500
|
+
* console.log('Found:', pkg.name)
|
|
501
|
+
* }
|
|
502
|
+
* ```
|
|
957
503
|
*/
|
|
958
504
|
function readPackageJsonIfExists(projectPath) {
|
|
959
505
|
const packageJsonPath = projectPath.endsWith('package.json') ? projectPath : join$1(projectPath, 'package.json');
|
|
@@ -963,7 +509,7 @@ function readPackageJsonIfExists(projectPath) {
|
|
|
963
509
|
return null;
|
|
964
510
|
}
|
|
965
511
|
try {
|
|
966
|
-
const validated = validatePackageJson(parse(content));
|
|
512
|
+
const validated = validatePackageJson(parse$1(content));
|
|
967
513
|
packageLogger.debug('Package.json loaded', { path: packageJsonPath, name: validated.name });
|
|
968
514
|
return validated;
|
|
969
515
|
}
|
|
@@ -978,6 +524,15 @@ function readPackageJsonIfExists(projectPath) {
|
|
|
978
524
|
*
|
|
979
525
|
* @param packageJson - Parsed package.json
|
|
980
526
|
* @returns All dependencies categorized
|
|
527
|
+
*
|
|
528
|
+
* @example Extracting all dependencies
|
|
529
|
+
* ```typescript
|
|
530
|
+
* import { getDependencies } from '@hyperfrontend/project-scope'
|
|
531
|
+
*
|
|
532
|
+
* const deps = getDependencies(packageJson)
|
|
533
|
+
* console.log('Runtime:', Object.keys(deps.dependencies))
|
|
534
|
+
* console.log('Dev:', Object.keys(deps.devDependencies))
|
|
535
|
+
* ```
|
|
981
536
|
*/
|
|
982
537
|
function getDependencies(packageJson) {
|
|
983
538
|
return {
|
|
@@ -994,6 +549,16 @@ createScopedLogger('project-scope:heuristics:deps');
|
|
|
994
549
|
*
|
|
995
550
|
* @param projectPath - Project directory
|
|
996
551
|
* @returns Dependencies grouped by runtime, dev, peer, and optional
|
|
552
|
+
*
|
|
553
|
+
* @example Getting project dependencies
|
|
554
|
+
* ```typescript
|
|
555
|
+
* import { getProjectDependencies } from '@hyperfrontend/project-scope'
|
|
556
|
+
*
|
|
557
|
+
* const deps = getProjectDependencies('/path/to/project')
|
|
558
|
+
* console.log('Runtime:', deps.runtime) // ['express', 'lodash']
|
|
559
|
+
* console.log('Dev:', deps.development) // ['jest', 'typescript']
|
|
560
|
+
* console.log('Total:', deps.total) // 15
|
|
561
|
+
* ```
|
|
997
562
|
*/
|
|
998
563
|
function getProjectDependencies(projectPath) {
|
|
999
564
|
const packageJson = readPackageJsonIfExists(projectPath);
|
|
@@ -1020,326 +585,6 @@ function getProjectDependencies(projectPath) {
|
|
|
1020
585
|
};
|
|
1021
586
|
}
|
|
1022
587
|
|
|
1023
|
-
/**
|
|
1024
|
-
* Global registry of all caches for bulk operations.
|
|
1025
|
-
*/
|
|
1026
|
-
const cacheRegistry = createSet();
|
|
1027
|
-
/**
|
|
1028
|
-
* Create a cache with optional TTL and size limits.
|
|
1029
|
-
*
|
|
1030
|
-
* The cache provides a simple key-value store with:
|
|
1031
|
-
* - Optional TTL (time-to-live) for automatic expiration
|
|
1032
|
-
* - Optional maxSize for limiting cache size with FIFO eviction
|
|
1033
|
-
* - Lazy expiration (entries are checked on access)
|
|
1034
|
-
*
|
|
1035
|
-
* @param options - Cache configuration options
|
|
1036
|
-
* @returns Cache instance
|
|
1037
|
-
*
|
|
1038
|
-
* @example
|
|
1039
|
-
* ```typescript
|
|
1040
|
-
* // Basic cache
|
|
1041
|
-
* const cache = createCache<string, number>()
|
|
1042
|
-
* cache.set('answer', 42)
|
|
1043
|
-
* cache.get('answer') // 42
|
|
1044
|
-
*
|
|
1045
|
-
* // Cache with TTL (expires after 60 seconds)
|
|
1046
|
-
* const ttlCache = createCache<string, object>({ ttl: 60000 })
|
|
1047
|
-
*
|
|
1048
|
-
* // Cache with max size (evicts oldest when full)
|
|
1049
|
-
* const lruCache = createCache<string, object>({ maxSize: 100 })
|
|
1050
|
-
*
|
|
1051
|
-
* // Combined options
|
|
1052
|
-
* const configCache = createCache<string, object>({
|
|
1053
|
-
* ttl: 30000,
|
|
1054
|
-
* maxSize: 50
|
|
1055
|
-
* })
|
|
1056
|
-
* ```
|
|
1057
|
-
*/
|
|
1058
|
-
function createCache(options) {
|
|
1059
|
-
const { ttl, maxSize } = options ?? {};
|
|
1060
|
-
const store = createMap();
|
|
1061
|
-
const insertionOrder = [];
|
|
1062
|
-
/**
|
|
1063
|
-
* Check if an entry is expired.
|
|
1064
|
-
*
|
|
1065
|
-
* @param entry - Cache entry to check
|
|
1066
|
-
* @returns True if entry is expired
|
|
1067
|
-
*/
|
|
1068
|
-
function isExpired(entry) {
|
|
1069
|
-
if (ttl === undefined)
|
|
1070
|
-
return false;
|
|
1071
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
1072
|
-
return Date.now() - entry.timestamp > ttl;
|
|
1073
|
-
}
|
|
1074
|
-
/**
|
|
1075
|
-
* Evict oldest entries to make room for new ones.
|
|
1076
|
-
*/
|
|
1077
|
-
function evictIfNeeded() {
|
|
1078
|
-
if (maxSize === undefined)
|
|
1079
|
-
return;
|
|
1080
|
-
while (store.size >= maxSize && insertionOrder.length > 0) {
|
|
1081
|
-
const oldestKey = insertionOrder.shift();
|
|
1082
|
-
if (oldestKey !== undefined) {
|
|
1083
|
-
store.delete(oldestKey);
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
/**
|
|
1088
|
-
* Remove key from insertion order tracking.
|
|
1089
|
-
*
|
|
1090
|
-
* @param key - Key to remove from order tracking
|
|
1091
|
-
*/
|
|
1092
|
-
function removeFromOrder(key) {
|
|
1093
|
-
const index = insertionOrder.indexOf(key);
|
|
1094
|
-
if (index !== -1) {
|
|
1095
|
-
insertionOrder.splice(index, 1);
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
const cache = {
|
|
1099
|
-
get(key) {
|
|
1100
|
-
const entry = store.get(key);
|
|
1101
|
-
if (!entry)
|
|
1102
|
-
return undefined;
|
|
1103
|
-
if (isExpired(entry)) {
|
|
1104
|
-
store.delete(key);
|
|
1105
|
-
removeFromOrder(key);
|
|
1106
|
-
return undefined;
|
|
1107
|
-
}
|
|
1108
|
-
return entry.value;
|
|
1109
|
-
},
|
|
1110
|
-
set(key, value) {
|
|
1111
|
-
if (store.has(key)) {
|
|
1112
|
-
removeFromOrder(key);
|
|
1113
|
-
}
|
|
1114
|
-
else {
|
|
1115
|
-
evictIfNeeded();
|
|
1116
|
-
}
|
|
1117
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
1118
|
-
store.set(key, { value, timestamp: Date.now() });
|
|
1119
|
-
insertionOrder.push(key);
|
|
1120
|
-
},
|
|
1121
|
-
has(key) {
|
|
1122
|
-
const entry = store.get(key);
|
|
1123
|
-
if (!entry)
|
|
1124
|
-
return false;
|
|
1125
|
-
if (isExpired(entry)) {
|
|
1126
|
-
store.delete(key);
|
|
1127
|
-
removeFromOrder(key);
|
|
1128
|
-
return false;
|
|
1129
|
-
}
|
|
1130
|
-
return true;
|
|
1131
|
-
},
|
|
1132
|
-
delete(key) {
|
|
1133
|
-
removeFromOrder(key);
|
|
1134
|
-
return store.delete(key);
|
|
1135
|
-
},
|
|
1136
|
-
clear() {
|
|
1137
|
-
store.clear();
|
|
1138
|
-
insertionOrder.length = 0;
|
|
1139
|
-
},
|
|
1140
|
-
size() {
|
|
1141
|
-
return store.size;
|
|
1142
|
-
},
|
|
1143
|
-
keys() {
|
|
1144
|
-
return [...insertionOrder];
|
|
1145
|
-
},
|
|
1146
|
-
};
|
|
1147
|
-
cacheRegistry.add(cache);
|
|
1148
|
-
return freeze(cache);
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
/**
|
|
1152
|
-
* Match path against glob pattern using safe character iteration.
|
|
1153
|
-
* Avoids regex to prevent ReDoS attacks.
|
|
1154
|
-
*
|
|
1155
|
-
* Supported patterns:
|
|
1156
|
-
* - * matches any characters except /
|
|
1157
|
-
* - ** matches any characters including /
|
|
1158
|
-
* - ? matches exactly one character except /
|
|
1159
|
-
* - {a,b,c} matches any of the alternatives
|
|
1160
|
-
*
|
|
1161
|
-
* @param path - The filesystem path to test against the pattern
|
|
1162
|
-
* @param pattern - The glob pattern to match against
|
|
1163
|
-
* @returns True if path matches pattern
|
|
1164
|
-
*
|
|
1165
|
-
* @example
|
|
1166
|
-
* ```typescript
|
|
1167
|
-
* import { matchGlobPattern } from '@hyperfrontend/project-scope'
|
|
1168
|
-
*
|
|
1169
|
-
* matchGlobPattern('src/utils/helper.ts', '\*\*\/*.ts') // true
|
|
1170
|
-
* matchGlobPattern('test.spec.ts', '\*.spec.ts') // true
|
|
1171
|
-
* matchGlobPattern('config.json', '\*.{json,yaml}') // true
|
|
1172
|
-
* matchGlobPattern('src/index.ts', 'src/\*.ts') // true
|
|
1173
|
-
* ```
|
|
1174
|
-
*/
|
|
1175
|
-
function matchGlobPattern(path, pattern) {
|
|
1176
|
-
return matchSegments(path.split('/'), pattern.split('/'), 0, 0);
|
|
1177
|
-
}
|
|
1178
|
-
/**
|
|
1179
|
-
* Internal recursive function to match path segments against pattern segments.
|
|
1180
|
-
*
|
|
1181
|
-
* @param pathParts - Array of path segments split by '/'
|
|
1182
|
-
* @param patternParts - Array of pattern segments split by '/'
|
|
1183
|
-
* @param pathIdx - Current index in pathParts being examined
|
|
1184
|
-
* @param patternIdx - Current index in patternParts being examined
|
|
1185
|
-
* @returns True if remaining segments match
|
|
1186
|
-
*/
|
|
1187
|
-
function matchSegments(pathParts, patternParts, pathIdx, patternIdx) {
|
|
1188
|
-
if (pathIdx === pathParts.length && patternIdx === patternParts.length) {
|
|
1189
|
-
return true;
|
|
1190
|
-
}
|
|
1191
|
-
if (patternIdx >= patternParts.length) {
|
|
1192
|
-
return false;
|
|
1193
|
-
}
|
|
1194
|
-
const patternPart = patternParts[patternIdx];
|
|
1195
|
-
if (patternPart === '**') {
|
|
1196
|
-
for (let i = pathIdx; i <= pathParts.length; i++) {
|
|
1197
|
-
if (matchSegments(pathParts, patternParts, i, patternIdx + 1)) {
|
|
1198
|
-
return true;
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
return false;
|
|
1202
|
-
}
|
|
1203
|
-
if (pathIdx >= pathParts.length) {
|
|
1204
|
-
return false;
|
|
1205
|
-
}
|
|
1206
|
-
const pathPart = pathParts[pathIdx];
|
|
1207
|
-
if (matchSegment(pathPart, patternPart)) {
|
|
1208
|
-
return matchSegments(pathParts, patternParts, pathIdx + 1, patternIdx + 1);
|
|
1209
|
-
}
|
|
1210
|
-
return false;
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* Match a single path segment against a pattern segment.
|
|
1214
|
-
* Handles *, ?, and {a,b,c} patterns.
|
|
1215
|
-
*
|
|
1216
|
-
* @param text - The path segment text to match
|
|
1217
|
-
* @param pattern - The pattern segment to match against
|
|
1218
|
-
* @returns True if the text matches the pattern
|
|
1219
|
-
*/
|
|
1220
|
-
function matchSegment(text, pattern) {
|
|
1221
|
-
let textIdx = 0;
|
|
1222
|
-
let patternIdx = 0;
|
|
1223
|
-
while (patternIdx < pattern.length) {
|
|
1224
|
-
const char = pattern[patternIdx];
|
|
1225
|
-
if (char === '*') {
|
|
1226
|
-
patternIdx++;
|
|
1227
|
-
if (patternIdx === pattern.length) {
|
|
1228
|
-
return true;
|
|
1229
|
-
}
|
|
1230
|
-
for (let i = textIdx; i <= text.length; i++) {
|
|
1231
|
-
if (matchSegmentFrom(text, i, pattern, patternIdx)) {
|
|
1232
|
-
return true;
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
return false;
|
|
1236
|
-
}
|
|
1237
|
-
else if (char === '?') {
|
|
1238
|
-
if (textIdx >= text.length) {
|
|
1239
|
-
return false;
|
|
1240
|
-
}
|
|
1241
|
-
textIdx++;
|
|
1242
|
-
patternIdx++;
|
|
1243
|
-
}
|
|
1244
|
-
else if (char === '{') {
|
|
1245
|
-
const closeIdx = findClosingBrace(pattern, patternIdx);
|
|
1246
|
-
if (closeIdx === -1) {
|
|
1247
|
-
if (textIdx >= text.length || text[textIdx] !== char) {
|
|
1248
|
-
return false;
|
|
1249
|
-
}
|
|
1250
|
-
textIdx++;
|
|
1251
|
-
patternIdx++;
|
|
1252
|
-
}
|
|
1253
|
-
else {
|
|
1254
|
-
const alternatives = extractAlternatives(pattern.slice(patternIdx + 1, closeIdx));
|
|
1255
|
-
for (const alt of alternatives) {
|
|
1256
|
-
if (matchSegmentFrom(text, textIdx, text.slice(0, textIdx) + alt + pattern.slice(closeIdx + 1), textIdx)) {
|
|
1257
|
-
return true;
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
return false;
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
else {
|
|
1264
|
-
if (textIdx >= text.length || text[textIdx] !== char) {
|
|
1265
|
-
return false;
|
|
1266
|
-
}
|
|
1267
|
-
textIdx++;
|
|
1268
|
-
patternIdx++;
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
return textIdx === text.length;
|
|
1272
|
-
}
|
|
1273
|
-
/**
|
|
1274
|
-
* Helper to match from a specific position.
|
|
1275
|
-
*
|
|
1276
|
-
* @param text - The full text being matched
|
|
1277
|
-
* @param textIdx - The starting index in text to match from
|
|
1278
|
-
* @param pattern - The full pattern being matched
|
|
1279
|
-
* @param patternIdx - The starting index in pattern to match from
|
|
1280
|
-
* @returns True if the text matches the pattern from the given positions
|
|
1281
|
-
*/
|
|
1282
|
-
function matchSegmentFrom(text, textIdx, pattern, patternIdx) {
|
|
1283
|
-
const remainingText = text.slice(textIdx);
|
|
1284
|
-
const remainingPattern = pattern.slice(patternIdx);
|
|
1285
|
-
return matchSegment(remainingText, remainingPattern);
|
|
1286
|
-
}
|
|
1287
|
-
/**
|
|
1288
|
-
* Find closing brace for {a,b,c} pattern.
|
|
1289
|
-
*
|
|
1290
|
-
* @param pattern - The pattern string to search within
|
|
1291
|
-
* @param startIdx - The index of the opening brace
|
|
1292
|
-
* @returns The index of the matching closing brace, or -1 if not found
|
|
1293
|
-
*/
|
|
1294
|
-
function findClosingBrace(pattern, startIdx) {
|
|
1295
|
-
let depth = 0;
|
|
1296
|
-
for (let i = startIdx; i < pattern.length; i++) {
|
|
1297
|
-
if (pattern[i] === '{') {
|
|
1298
|
-
depth++;
|
|
1299
|
-
}
|
|
1300
|
-
else if (pattern[i] === '}') {
|
|
1301
|
-
depth--;
|
|
1302
|
-
if (depth === 0) {
|
|
1303
|
-
return i;
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
return -1;
|
|
1308
|
-
}
|
|
1309
|
-
/**
|
|
1310
|
-
* Extract alternatives from {a,b,c} pattern content.
|
|
1311
|
-
*
|
|
1312
|
-
* @param content - The content between braces (without the braces themselves)
|
|
1313
|
-
* @returns Array of alternative strings split by commas at depth 0
|
|
1314
|
-
*/
|
|
1315
|
-
function extractAlternatives(content) {
|
|
1316
|
-
const alternatives = [];
|
|
1317
|
-
let current = '';
|
|
1318
|
-
let depth = 0;
|
|
1319
|
-
for (let i = 0; i < content.length; i++) {
|
|
1320
|
-
const char = content[i];
|
|
1321
|
-
if (char === '{') {
|
|
1322
|
-
depth++;
|
|
1323
|
-
current += char;
|
|
1324
|
-
}
|
|
1325
|
-
else if (char === '}') {
|
|
1326
|
-
depth--;
|
|
1327
|
-
current += char;
|
|
1328
|
-
}
|
|
1329
|
-
else if (char === ',' && depth === 0) {
|
|
1330
|
-
alternatives.push(current);
|
|
1331
|
-
current = '';
|
|
1332
|
-
}
|
|
1333
|
-
else {
|
|
1334
|
-
current += char;
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
if (current) {
|
|
1338
|
-
alternatives.push(current);
|
|
1339
|
-
}
|
|
1340
|
-
return alternatives;
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
588
|
const walkLogger = createScopedLogger('project-scope:project:walk');
|
|
1344
589
|
/**
|
|
1345
590
|
* Reads .gitignore file from the given directory and extracts
|
|
@@ -1405,6 +650,18 @@ function matchPattern(path, pattern) {
|
|
|
1405
650
|
* @param startPath - Root directory to begin traversal
|
|
1406
651
|
* @param visitor - Callback function invoked for each file system entry
|
|
1407
652
|
* @param options - Configuration for traversal behavior
|
|
653
|
+
*
|
|
654
|
+
* @example Walking a directory tree
|
|
655
|
+
* ```typescript
|
|
656
|
+
* import { walkDirectory } from '@hyperfrontend/project-scope'
|
|
657
|
+
*
|
|
658
|
+
* const tsFiles: string[] = []
|
|
659
|
+
* walkDirectory('./src', (entry) => {
|
|
660
|
+
* if (entry.isFile && entry.name.endsWith('.ts')) {
|
|
661
|
+
* tsFiles.push(entry.relativePath)
|
|
662
|
+
* }
|
|
663
|
+
* }, { maxDepth: 5, respectGitignore: true })
|
|
664
|
+
* ```
|
|
1408
665
|
*/
|
|
1409
666
|
function walkDirectory(startPath, visitor, options) {
|
|
1410
667
|
walkLogger.debug('Starting directory walk', {
|
|
@@ -1501,7 +758,7 @@ function matchesPatterns(path, patterns) {
|
|
|
1501
758
|
* @param options - Configuration for search behavior
|
|
1502
759
|
* @returns List of relative file paths that match the patterns
|
|
1503
760
|
*
|
|
1504
|
-
* @example
|
|
761
|
+
* @example Finding files by pattern
|
|
1505
762
|
* ```typescript
|
|
1506
763
|
* import { findFiles } from '@hyperfrontend/project-scope'
|
|
1507
764
|
*
|
|
@@ -1615,7 +872,7 @@ function discoverFromExports(exports$1, entryPoints) {
|
|
|
1615
872
|
* @param options - Discovery options
|
|
1616
873
|
* @returns Array of discovered entry points sorted by confidence
|
|
1617
874
|
*
|
|
1618
|
-
* @example
|
|
875
|
+
* @example Discovering project entry points
|
|
1619
876
|
* ```typescript
|
|
1620
877
|
* import { discoverEntryPoints } from '@hyperfrontend/project-scope'
|
|
1621
878
|
*
|
|
@@ -1782,80 +1039,32 @@ function discoverEntryPoints(projectPath, options) {
|
|
|
1782
1039
|
return result;
|
|
1783
1040
|
}
|
|
1784
1041
|
|
|
1785
|
-
/**
|
|
1786
|
-
* Get combined dependencies from package.json.
|
|
1787
|
-
* Merges dependencies, devDependencies, peerDependencies, and optionalDependencies.
|
|
1788
|
-
*
|
|
1789
|
-
* @param packageJson - The package.json object to extract dependencies from
|
|
1790
|
-
* @returns Combined dependencies as a single record
|
|
1791
|
-
*/
|
|
1792
|
-
function collectAllDependencies(packageJson) {
|
|
1793
|
-
return {
|
|
1794
|
-
...packageJson?.dependencies,
|
|
1795
|
-
...packageJson?.devDependencies,
|
|
1796
|
-
...packageJson?.peerDependencies,
|
|
1797
|
-
...packageJson?.optionalDependencies,
|
|
1798
|
-
};
|
|
1799
|
-
}
|
|
1800
|
-
/**
|
|
1801
|
-
* Extract clean version from dependency version string.
|
|
1802
|
-
* Removes semver prefixes like ^, ~, >=, etc.
|
|
1803
|
-
* Uses character-by-character parsing to avoid ReDoS vulnerabilities.
|
|
1804
|
-
*
|
|
1805
|
-
* @param versionString - The version string with optional prefix characters
|
|
1806
|
-
* @returns The cleaned version string without prefix characters
|
|
1807
|
-
*/
|
|
1808
|
-
function parseVersionString(versionString) {
|
|
1809
|
-
if (versionString === undefined || versionString === null)
|
|
1810
|
-
return undefined;
|
|
1811
|
-
let start = 0;
|
|
1812
|
-
while (start < versionString.length) {
|
|
1813
|
-
const char = versionString[start];
|
|
1814
|
-
if (char !== '^' && char !== '~' && char !== '>' && char !== '=' && char !== '<') {
|
|
1815
|
-
break;
|
|
1816
|
-
}
|
|
1817
|
-
start++;
|
|
1818
|
-
}
|
|
1819
|
-
return versionString.slice(start);
|
|
1820
|
-
}
|
|
1821
|
-
/**
|
|
1822
|
-
* Find first matching config file in project.
|
|
1823
|
-
* Note: Name avoids similarity to fs.readFile/fs.readFileSync.
|
|
1824
|
-
*
|
|
1825
|
-
* @param projectPath - The project directory path
|
|
1826
|
-
* @param patterns - Array of config file patterns to search for
|
|
1827
|
-
* @returns The first matching config file path or undefined
|
|
1828
|
-
*/
|
|
1829
|
-
function locateConfigFile(projectPath, patterns) {
|
|
1830
|
-
for (const pattern of patterns) {
|
|
1831
|
-
const fullPath = join(projectPath, pattern);
|
|
1832
|
-
if (exists(fullPath)) {
|
|
1833
|
-
return pattern;
|
|
1834
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
return undefined;
|
|
1837
|
-
}
|
|
1838
|
-
/**
|
|
1839
|
-
* Find scripts containing a specific command.
|
|
1840
|
-
*
|
|
1841
|
-
* @param scripts - The scripts object from package.json
|
|
1842
|
-
* @param command - The command string to search for
|
|
1843
|
-
* @returns Array of script names that contain the command
|
|
1844
|
-
*/
|
|
1845
|
-
function filterScriptsByCommand(scripts, command) {
|
|
1846
|
-
if (!scripts)
|
|
1847
|
-
return [];
|
|
1848
|
-
return entries(scripts)
|
|
1849
|
-
.filter(([, script]) => script.includes(command))
|
|
1850
|
-
.map(([name]) => name);
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
1042
|
/**
|
|
1854
1043
|
* Detect Express in project.
|
|
1855
1044
|
*
|
|
1856
1045
|
* @param projectPath - Project directory path
|
|
1857
1046
|
* @param packageJson - Optional pre-loaded package.json
|
|
1858
1047
|
* @returns Detection result or null if not detected
|
|
1048
|
+
* @example Detecting Express framework
|
|
1049
|
+
* ```typescript
|
|
1050
|
+
* const pkg = {
|
|
1051
|
+
* dependencies: { express: '^4.18.2', cors: '^2.8.5' },
|
|
1052
|
+
* devDependencies: { '@types/express': '^4.17.17' },
|
|
1053
|
+
* }
|
|
1054
|
+
*
|
|
1055
|
+
* const result = expressDetector('/path/to/project', pkg)
|
|
1056
|
+
* // => {
|
|
1057
|
+
* // id: 'express',
|
|
1058
|
+
* // name: 'Express',
|
|
1059
|
+
* // version: '4.18.2',
|
|
1060
|
+
* // confidence: 100,
|
|
1061
|
+
* // detectedFrom: [
|
|
1062
|
+
* // { type: 'package.json', field: 'dependencies.express' },
|
|
1063
|
+
* // { type: 'package.json', field: 'dependencies.@types/express' },
|
|
1064
|
+
* // { type: 'package.json', field: 'dependencies (express middleware)' },
|
|
1065
|
+
* // ],
|
|
1066
|
+
* // }
|
|
1067
|
+
* ```
|
|
1859
1068
|
*/
|
|
1860
1069
|
function expressDetector(projectPath, packageJson) {
|
|
1861
1070
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1890,84 +1099,109 @@ function expressDetector(projectPath, packageJson) {
|
|
|
1890
1099
|
}
|
|
1891
1100
|
|
|
1892
1101
|
/**
|
|
1893
|
-
* Detect
|
|
1102
|
+
* Detect Fastify in project.
|
|
1894
1103
|
*
|
|
1895
1104
|
* @param projectPath - Project directory path
|
|
1896
1105
|
* @param packageJson - Optional pre-loaded package.json
|
|
1897
1106
|
* @returns Detection result or null if not detected
|
|
1107
|
+
* @example Detecting Fastify framework
|
|
1108
|
+
* ```typescript
|
|
1109
|
+
* const pkg = {
|
|
1110
|
+
* dependencies: { fastify: '^4.24.0', '@fastify/cors': '^8.4.0' },
|
|
1111
|
+
* }
|
|
1112
|
+
*
|
|
1113
|
+
* const result = fastifyDetector('/path/to/project', pkg)
|
|
1114
|
+
* // => {
|
|
1115
|
+
* // id: 'fastify',
|
|
1116
|
+
* // name: 'Fastify',
|
|
1117
|
+
* // version: '4.24.0',
|
|
1118
|
+
* // confidence: 95,
|
|
1119
|
+
* // detectedFrom: [
|
|
1120
|
+
* // { type: 'package.json', field: 'dependencies.fastify' },
|
|
1121
|
+
* // { type: 'package.json', field: 'dependencies (fastify plugins)' },
|
|
1122
|
+
* // ],
|
|
1123
|
+
* // }
|
|
1124
|
+
* ```
|
|
1898
1125
|
*/
|
|
1899
|
-
function
|
|
1126
|
+
function fastifyDetector(projectPath, packageJson) {
|
|
1900
1127
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1901
1128
|
const sources = [];
|
|
1902
1129
|
let confidence = 0;
|
|
1903
1130
|
let version;
|
|
1904
|
-
let configPath;
|
|
1905
1131
|
const deps = collectAllDependencies(pkg);
|
|
1906
|
-
if (deps['
|
|
1907
|
-
confidence +=
|
|
1908
|
-
version = parseVersionString(deps['
|
|
1909
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1910
|
-
}
|
|
1911
|
-
if (deps['@nestjs/common']) {
|
|
1912
|
-
confidence += 15;
|
|
1913
|
-
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
|
|
1132
|
+
if (deps['fastify']) {
|
|
1133
|
+
confidence += 80;
|
|
1134
|
+
version = parseVersionString(deps['fastify']);
|
|
1135
|
+
sources.push({ type: 'package.json', field: 'dependencies.fastify' });
|
|
1914
1136
|
}
|
|
1915
|
-
|
|
1137
|
+
const fastifyPlugins = keys(deps).filter((d) => d.startsWith('@fastify/') || d.startsWith('fastify-'));
|
|
1138
|
+
if (fastifyPlugins.length > 0) {
|
|
1916
1139
|
confidence += 15;
|
|
1917
|
-
|
|
1918
|
-
sources.push({ type: 'config-file', path: 'nest-cli.json' });
|
|
1140
|
+
sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
|
|
1919
1141
|
}
|
|
1920
|
-
|
|
1921
|
-
if (nestPackages.length > 2) {
|
|
1142
|
+
if (deps['@types/fastify']) {
|
|
1922
1143
|
confidence += 5;
|
|
1923
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1144
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
1924
1145
|
}
|
|
1925
1146
|
if (confidence === 0) {
|
|
1926
1147
|
return null;
|
|
1927
1148
|
}
|
|
1928
1149
|
return {
|
|
1929
|
-
id: '
|
|
1930
|
-
name: '
|
|
1150
|
+
id: 'fastify',
|
|
1151
|
+
name: 'Fastify',
|
|
1931
1152
|
version,
|
|
1932
|
-
configPath,
|
|
1933
1153
|
confidence: min(confidence, 100),
|
|
1934
1154
|
detectedFrom: sources,
|
|
1935
1155
|
};
|
|
1936
1156
|
}
|
|
1937
1157
|
|
|
1938
1158
|
/**
|
|
1939
|
-
* Detect
|
|
1159
|
+
* Detect Hono in project.
|
|
1940
1160
|
*
|
|
1941
1161
|
* @param projectPath - Project directory path
|
|
1942
1162
|
* @param packageJson - Optional pre-loaded package.json
|
|
1943
1163
|
* @returns Detection result or null if not detected
|
|
1164
|
+
* @example Detecting Hono framework
|
|
1165
|
+
* ```typescript
|
|
1166
|
+
* const pkg = {
|
|
1167
|
+
* dependencies: { hono: '^3.11.0', '@hono/node-server': '^1.3.0' },
|
|
1168
|
+
* }
|
|
1169
|
+
*
|
|
1170
|
+
* const result = honoDetector('/path/to/project', pkg)
|
|
1171
|
+
* // => {
|
|
1172
|
+
* // id: 'hono',
|
|
1173
|
+
* // name: 'Hono',
|
|
1174
|
+
* // version: '3.11.0',
|
|
1175
|
+
* // confidence: 100,
|
|
1176
|
+
* // detectedFrom: [
|
|
1177
|
+
* // { type: 'package.json', field: 'dependencies.hono' },
|
|
1178
|
+
* // { type: 'package.json', field: 'dependencies (@hono adapters)' },
|
|
1179
|
+
* // ],
|
|
1180
|
+
* // }
|
|
1181
|
+
* ```
|
|
1944
1182
|
*/
|
|
1945
|
-
function
|
|
1183
|
+
function honoDetector(projectPath, packageJson) {
|
|
1946
1184
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1947
1185
|
const sources = [];
|
|
1948
1186
|
let confidence = 0;
|
|
1949
1187
|
let version;
|
|
1950
1188
|
const deps = collectAllDependencies(pkg);
|
|
1951
|
-
if (deps['
|
|
1952
|
-
confidence +=
|
|
1953
|
-
version = parseVersionString(deps['
|
|
1954
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1189
|
+
if (deps['hono']) {
|
|
1190
|
+
confidence += 85;
|
|
1191
|
+
version = parseVersionString(deps['hono']);
|
|
1192
|
+
sources.push({ type: 'package.json', field: 'dependencies.hono' });
|
|
1955
1193
|
}
|
|
1956
|
-
const
|
|
1957
|
-
if (
|
|
1194
|
+
const honoAdapters = keys(deps).filter((d) => d.startsWith('@hono/'));
|
|
1195
|
+
if (honoAdapters.length > 0) {
|
|
1958
1196
|
confidence += 15;
|
|
1959
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1960
|
-
}
|
|
1961
|
-
if (deps['@types/fastify']) {
|
|
1962
|
-
confidence += 5;
|
|
1963
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
1197
|
+
sources.push({ type: 'package.json', field: 'dependencies (@hono adapters)' });
|
|
1964
1198
|
}
|
|
1965
1199
|
if (confidence === 0) {
|
|
1966
1200
|
return null;
|
|
1967
1201
|
}
|
|
1968
1202
|
return {
|
|
1969
|
-
id: '
|
|
1970
|
-
name: '
|
|
1203
|
+
id: 'hono',
|
|
1204
|
+
name: 'Hono',
|
|
1971
1205
|
version,
|
|
1972
1206
|
confidence: min(confidence, 100),
|
|
1973
1207
|
detectedFrom: sources,
|
|
@@ -1980,6 +1214,26 @@ function fastifyDetector(projectPath, packageJson) {
|
|
|
1980
1214
|
* @param projectPath - Project directory path
|
|
1981
1215
|
* @param packageJson - Optional pre-loaded package.json
|
|
1982
1216
|
* @returns Detection result or null if not detected
|
|
1217
|
+
* @example Detecting Koa framework
|
|
1218
|
+
* ```typescript
|
|
1219
|
+
* const pkg = {
|
|
1220
|
+
* dependencies: { koa: '^2.14.2', 'koa-router': '^12.0.0' },
|
|
1221
|
+
* devDependencies: { '@types/koa': '^2.13.9' },
|
|
1222
|
+
* }
|
|
1223
|
+
*
|
|
1224
|
+
* const result = koaDetector('/path/to/project', pkg)
|
|
1225
|
+
* // => {
|
|
1226
|
+
* // id: 'koa',
|
|
1227
|
+
* // name: 'Koa',
|
|
1228
|
+
* // version: '2.14.2',
|
|
1229
|
+
* // confidence: 100,
|
|
1230
|
+
* // detectedFrom: [
|
|
1231
|
+
* // { type: 'package.json', field: 'dependencies.koa' },
|
|
1232
|
+
* // { type: 'package.json', field: 'dependencies.@types/koa' },
|
|
1233
|
+
* // { type: 'package.json', field: 'dependencies (koa middleware)' },
|
|
1234
|
+
* // ],
|
|
1235
|
+
* // }
|
|
1236
|
+
* ```
|
|
1983
1237
|
*/
|
|
1984
1238
|
function koaDetector(projectPath, packageJson) {
|
|
1985
1239
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2014,35 +1268,72 @@ function koaDetector(projectPath, packageJson) {
|
|
|
2014
1268
|
}
|
|
2015
1269
|
|
|
2016
1270
|
/**
|
|
2017
|
-
* Detect
|
|
1271
|
+
* Detect NestJS in project.
|
|
2018
1272
|
*
|
|
2019
1273
|
* @param projectPath - Project directory path
|
|
2020
1274
|
* @param packageJson - Optional pre-loaded package.json
|
|
2021
1275
|
* @returns Detection result or null if not detected
|
|
1276
|
+
* @example Detecting NestJS framework
|
|
1277
|
+
* ```typescript
|
|
1278
|
+
* // Project with nest-cli.json and NestJS packages
|
|
1279
|
+
* const pkg = {
|
|
1280
|
+
* dependencies: {
|
|
1281
|
+
* '@nestjs/core': '^10.2.0',
|
|
1282
|
+
* '@nestjs/common': '^10.2.0',
|
|
1283
|
+
* '@nestjs/platform-express': '^10.2.0',
|
|
1284
|
+
* },
|
|
1285
|
+
* }
|
|
1286
|
+
*
|
|
1287
|
+
* const result = nestDetector('/path/to/nest-project', pkg)
|
|
1288
|
+
* // => {
|
|
1289
|
+
* // id: 'nestjs',
|
|
1290
|
+
* // name: 'NestJS',
|
|
1291
|
+
* // version: '10.2.0',
|
|
1292
|
+
* // configPath: 'nest-cli.json', // if present
|
|
1293
|
+
* // confidence: 100,
|
|
1294
|
+
* // detectedFrom: [
|
|
1295
|
+
* // { type: 'package.json', field: 'dependencies.@nestjs/core' },
|
|
1296
|
+
* // { type: 'package.json', field: 'dependencies.@nestjs/common' },
|
|
1297
|
+
* // { type: 'config-file', path: 'nest-cli.json' },
|
|
1298
|
+
* // { type: 'package.json', field: 'dependencies (@nestjs packages)' },
|
|
1299
|
+
* // ],
|
|
1300
|
+
* // }
|
|
1301
|
+
* ```
|
|
2022
1302
|
*/
|
|
2023
|
-
function
|
|
1303
|
+
function nestDetector(projectPath, packageJson) {
|
|
2024
1304
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2025
1305
|
const sources = [];
|
|
2026
1306
|
let confidence = 0;
|
|
2027
1307
|
let version;
|
|
1308
|
+
let configPath;
|
|
2028
1309
|
const deps = collectAllDependencies(pkg);
|
|
2029
|
-
if (deps['
|
|
2030
|
-
confidence +=
|
|
2031
|
-
version = parseVersionString(deps['
|
|
2032
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1310
|
+
if (deps['@nestjs/core']) {
|
|
1311
|
+
confidence += 70;
|
|
1312
|
+
version = parseVersionString(deps['@nestjs/core']);
|
|
1313
|
+
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
|
|
2033
1314
|
}
|
|
2034
|
-
|
|
2035
|
-
if (honoAdapters.length > 0) {
|
|
1315
|
+
if (deps['@nestjs/common']) {
|
|
2036
1316
|
confidence += 15;
|
|
2037
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1317
|
+
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
|
|
1318
|
+
}
|
|
1319
|
+
if (exists(join$1(projectPath, 'nest-cli.json'))) {
|
|
1320
|
+
confidence += 15;
|
|
1321
|
+
configPath = 'nest-cli.json';
|
|
1322
|
+
sources.push({ type: 'config-file', path: 'nest-cli.json' });
|
|
1323
|
+
}
|
|
1324
|
+
const nestPackages = keys(deps).filter((d) => d.startsWith('@nestjs/'));
|
|
1325
|
+
if (nestPackages.length > 2) {
|
|
1326
|
+
confidence += 5;
|
|
1327
|
+
sources.push({ type: 'package.json', field: 'dependencies (@nestjs packages)' });
|
|
2038
1328
|
}
|
|
2039
1329
|
if (confidence === 0) {
|
|
2040
1330
|
return null;
|
|
2041
1331
|
}
|
|
2042
1332
|
return {
|
|
2043
|
-
id: '
|
|
2044
|
-
name: '
|
|
1333
|
+
id: 'nestjs',
|
|
1334
|
+
name: 'NestJS',
|
|
2045
1335
|
version,
|
|
1336
|
+
configPath,
|
|
2046
1337
|
confidence: min(confidence, 100),
|
|
2047
1338
|
detectedFrom: sources,
|
|
2048
1339
|
};
|
|
@@ -2057,99 +1348,64 @@ const backendDetectors = [
|
|
|
2057
1348
|
{ id: 'hono', name: 'Hono', detect: honoDetector },
|
|
2058
1349
|
];
|
|
2059
1350
|
|
|
2060
|
-
/** Config patterns for
|
|
2061
|
-
const
|
|
2062
|
-
'webpack.config.js',
|
|
2063
|
-
'webpack.config.ts',
|
|
2064
|
-
'webpack.config.cjs',
|
|
2065
|
-
'webpack.config.mjs',
|
|
2066
|
-
'webpack.config.babel.js',
|
|
2067
|
-
];
|
|
1351
|
+
/** Config patterns for Babel */
|
|
1352
|
+
const BABEL_CONFIG_PATTERNS = ['babel.config.js', 'babel.config.cjs', 'babel.config.mjs', 'babel.config.json', '.babelrc', '.babelrc.json', '.babelrc.js'];
|
|
2068
1353
|
/**
|
|
2069
|
-
* Detect
|
|
1354
|
+
* Detect Babel in project.
|
|
2070
1355
|
*
|
|
2071
1356
|
* @param projectPath - Project directory path
|
|
2072
1357
|
* @param packageJson - Optional pre-loaded package.json
|
|
2073
1358
|
* @returns Detection result or null if not detected
|
|
1359
|
+
*
|
|
1360
|
+
* @example Detecting Babel compiler
|
|
1361
|
+
* ```typescript
|
|
1362
|
+
* const result = babelDetector('/path/to/project', {
|
|
1363
|
+
* name: 'my-app',
|
|
1364
|
+
* devDependencies: { '@babel/core': '^7.23.0', '@babel/preset-env': '^7.23.0' }
|
|
1365
|
+
* })
|
|
1366
|
+
* // => {
|
|
1367
|
+
* // id: 'babel',
|
|
1368
|
+
* // name: 'Babel',
|
|
1369
|
+
* // version: '7.23.0',
|
|
1370
|
+
* // confidence: 60,
|
|
1371
|
+
* // detectedFrom: [
|
|
1372
|
+
* // { type: 'package.json', field: 'dependencies.@babel/core' },
|
|
1373
|
+
* // { type: 'package.json', field: 'dependencies (@babel packages)' }
|
|
1374
|
+
* // ]
|
|
1375
|
+
* // }
|
|
1376
|
+
* ```
|
|
2074
1377
|
*/
|
|
2075
|
-
function
|
|
1378
|
+
function babelDetector(projectPath, packageJson) {
|
|
2076
1379
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2077
1380
|
const sources = [];
|
|
2078
1381
|
let confidence = 0;
|
|
2079
1382
|
let version;
|
|
2080
1383
|
const deps = collectAllDependencies(pkg);
|
|
2081
|
-
if (deps['
|
|
1384
|
+
if (deps['@babel/core']) {
|
|
2082
1385
|
confidence += 50;
|
|
2083
|
-
version = parseVersionString(deps['
|
|
2084
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1386
|
+
version = parseVersionString(deps['@babel/core']);
|
|
1387
|
+
sources.push({ type: 'package.json', field: 'dependencies.@babel/core' });
|
|
2085
1388
|
}
|
|
2086
|
-
const configPath = locateConfigFile(projectPath,
|
|
1389
|
+
const configPath = locateConfigFile(projectPath, BABEL_CONFIG_PATTERNS);
|
|
2087
1390
|
if (configPath) {
|
|
2088
1391
|
confidence += 40;
|
|
2089
1392
|
sources.push({ type: 'config-file', path: configPath });
|
|
2090
1393
|
}
|
|
2091
|
-
if (
|
|
2092
|
-
confidence +=
|
|
2093
|
-
sources.push({ type: 'package.json', field: '
|
|
2094
|
-
}
|
|
2095
|
-
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'webpack');
|
|
2096
|
-
for (const name of scriptMatches) {
|
|
2097
|
-
confidence = min(confidence + 5, 100);
|
|
2098
|
-
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
2099
|
-
}
|
|
2100
|
-
if (confidence === 0) {
|
|
2101
|
-
return null;
|
|
2102
|
-
}
|
|
2103
|
-
return {
|
|
2104
|
-
id: 'webpack',
|
|
2105
|
-
name: 'Webpack',
|
|
2106
|
-
version,
|
|
2107
|
-
configPath,
|
|
2108
|
-
confidence: min(confidence, 100),
|
|
2109
|
-
detectedFrom: sources,
|
|
2110
|
-
};
|
|
2111
|
-
}
|
|
2112
|
-
|
|
2113
|
-
/** Config patterns for Vite */
|
|
2114
|
-
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
2115
|
-
/**
|
|
2116
|
-
* Detect Vite in project.
|
|
2117
|
-
*
|
|
2118
|
-
* @param projectPath - Project directory path
|
|
2119
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2120
|
-
* @returns Detection result or null if not detected
|
|
2121
|
-
*/
|
|
2122
|
-
function viteDetector(projectPath, packageJson) {
|
|
2123
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2124
|
-
const sources = [];
|
|
2125
|
-
let confidence = 0;
|
|
2126
|
-
let version;
|
|
2127
|
-
const deps = collectAllDependencies(pkg);
|
|
2128
|
-
if (deps['vite']) {
|
|
2129
|
-
confidence += 60;
|
|
2130
|
-
version = parseVersionString(deps['vite']);
|
|
2131
|
-
sources.push({ type: 'package.json', field: 'dependencies.vite' });
|
|
2132
|
-
}
|
|
2133
|
-
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
2134
|
-
if (configPath) {
|
|
2135
|
-
confidence += 35;
|
|
2136
|
-
sources.push({ type: 'config-file', path: configPath });
|
|
2137
|
-
}
|
|
2138
|
-
if (deps['vitest']) {
|
|
2139
|
-
confidence += 10;
|
|
2140
|
-
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
1394
|
+
if (pkg && 'babel' in pkg) {
|
|
1395
|
+
confidence += 30;
|
|
1396
|
+
sources.push({ type: 'package.json', field: 'babel' });
|
|
2141
1397
|
}
|
|
2142
|
-
const
|
|
2143
|
-
if (
|
|
1398
|
+
const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
1399
|
+
if (babelPackages.length > 1) {
|
|
2144
1400
|
confidence += 10;
|
|
2145
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1401
|
+
sources.push({ type: 'package.json', field: 'dependencies (@babel packages)' });
|
|
2146
1402
|
}
|
|
2147
1403
|
if (confidence === 0) {
|
|
2148
1404
|
return null;
|
|
2149
1405
|
}
|
|
2150
1406
|
return {
|
|
2151
|
-
id: '
|
|
2152
|
-
name: '
|
|
1407
|
+
id: 'babel',
|
|
1408
|
+
name: 'Babel',
|
|
2153
1409
|
version,
|
|
2154
1410
|
configPath,
|
|
2155
1411
|
confidence: min(confidence, 100),
|
|
@@ -2157,78 +1413,116 @@ function viteDetector(projectPath, packageJson) {
|
|
|
2157
1413
|
};
|
|
2158
1414
|
}
|
|
2159
1415
|
|
|
2160
|
-
/** Config patterns for Rollup */
|
|
2161
|
-
const ROLLUP_CONFIG_PATTERNS = ['rollup.config.js', 'rollup.config.ts', 'rollup.config.mjs', 'rollup.config.cjs'];
|
|
2162
1416
|
/**
|
|
2163
|
-
* Detect
|
|
1417
|
+
* Detect esbuild in project.
|
|
2164
1418
|
*
|
|
2165
1419
|
* @param projectPath - Project directory path
|
|
2166
1420
|
* @param packageJson - Optional pre-loaded package.json
|
|
2167
1421
|
* @returns Detection result or null if not detected
|
|
1422
|
+
*
|
|
1423
|
+
* @example Detecting esbuild bundler
|
|
1424
|
+
* ```typescript
|
|
1425
|
+
* const result = esbuildDetector('/path/to/project', {
|
|
1426
|
+
* name: 'my-lib',
|
|
1427
|
+
* devDependencies: { 'esbuild': '^0.19.0' },
|
|
1428
|
+
* scripts: { 'build': 'esbuild src/index.ts --bundle --outfile=dist/index.js' }
|
|
1429
|
+
* })
|
|
1430
|
+
* // => {
|
|
1431
|
+
* // id: 'esbuild',
|
|
1432
|
+
* // name: 'esbuild',
|
|
1433
|
+
* // version: '0.19.0',
|
|
1434
|
+
* // confidence: 80,
|
|
1435
|
+
* // detectedFrom: [
|
|
1436
|
+
* // { type: 'package.json', field: 'dependencies.esbuild' },
|
|
1437
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
1438
|
+
* // ]
|
|
1439
|
+
* // }
|
|
1440
|
+
* ```
|
|
2168
1441
|
*/
|
|
2169
|
-
function
|
|
1442
|
+
function esbuildDetector(projectPath, packageJson) {
|
|
2170
1443
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2171
1444
|
const sources = [];
|
|
2172
1445
|
let confidence = 0;
|
|
2173
1446
|
let version;
|
|
2174
1447
|
const deps = collectAllDependencies(pkg);
|
|
2175
|
-
if (deps['
|
|
2176
|
-
confidence +=
|
|
2177
|
-
version = parseVersionString(deps['
|
|
2178
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2179
|
-
}
|
|
2180
|
-
const configPath = locateConfigFile(projectPath, ROLLUP_CONFIG_PATTERNS);
|
|
2181
|
-
if (configPath) {
|
|
2182
|
-
confidence += 40;
|
|
2183
|
-
sources.push({ type: 'config-file', path: configPath });
|
|
1448
|
+
if (deps['esbuild']) {
|
|
1449
|
+
confidence += 70;
|
|
1450
|
+
version = parseVersionString(deps['esbuild']);
|
|
1451
|
+
sources.push({ type: 'package.json', field: 'dependencies.esbuild' });
|
|
2184
1452
|
}
|
|
2185
|
-
const
|
|
2186
|
-
if (
|
|
2187
|
-
confidence +=
|
|
2188
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1453
|
+
const esbuildPlugins = keys(deps).filter((d) => d.includes('esbuild-plugin') || d.includes('esbuild-'));
|
|
1454
|
+
if (esbuildPlugins.length > 0) {
|
|
1455
|
+
confidence += 15;
|
|
1456
|
+
sources.push({ type: 'package.json', field: 'dependencies (esbuild plugins)' });
|
|
2189
1457
|
}
|
|
2190
|
-
const scriptMatches = filterScriptsByCommand(pkg?.scripts, '
|
|
1458
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'esbuild');
|
|
2191
1459
|
for (const name of scriptMatches) {
|
|
2192
|
-
confidence = min(confidence +
|
|
1460
|
+
confidence = min(confidence + 10, 100);
|
|
2193
1461
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
2194
1462
|
}
|
|
2195
1463
|
if (confidence === 0) {
|
|
2196
1464
|
return null;
|
|
2197
1465
|
}
|
|
2198
1466
|
return {
|
|
2199
|
-
id: '
|
|
2200
|
-
name: '
|
|
1467
|
+
id: 'esbuild',
|
|
1468
|
+
name: 'esbuild',
|
|
2201
1469
|
version,
|
|
2202
|
-
configPath,
|
|
2203
1470
|
confidence: min(confidence, 100),
|
|
2204
1471
|
detectedFrom: sources,
|
|
2205
1472
|
};
|
|
2206
1473
|
}
|
|
2207
1474
|
|
|
1475
|
+
/** Config patterns for Parcel */
|
|
1476
|
+
const PARCEL_CONFIG_PATTERNS = ['.parcelrc'];
|
|
2208
1477
|
/**
|
|
2209
|
-
* Detect
|
|
1478
|
+
* Detect Parcel in project.
|
|
2210
1479
|
*
|
|
2211
1480
|
* @param projectPath - Project directory path
|
|
2212
1481
|
* @param packageJson - Optional pre-loaded package.json
|
|
2213
1482
|
* @returns Detection result or null if not detected
|
|
1483
|
+
*
|
|
1484
|
+
* @example Detecting Parcel bundler
|
|
1485
|
+
* ```typescript
|
|
1486
|
+
* const result = parcelDetector('/path/to/project', {
|
|
1487
|
+
* name: 'my-app',
|
|
1488
|
+
* devDependencies: { 'parcel': '^2.10.0' },
|
|
1489
|
+
* scripts: { 'dev': 'parcel src/index.html', 'build': 'parcel build src/index.html' }
|
|
1490
|
+
* })
|
|
1491
|
+
* // => {
|
|
1492
|
+
* // id: 'parcel',
|
|
1493
|
+
* // name: 'Parcel',
|
|
1494
|
+
* // version: '2.10.0',
|
|
1495
|
+
* // confidence: 80,
|
|
1496
|
+
* // detectedFrom: [
|
|
1497
|
+
* // { type: 'package.json', field: 'dependencies.parcel' },
|
|
1498
|
+
* // { type: 'package.json', field: 'scripts.dev' },
|
|
1499
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
1500
|
+
* // ]
|
|
1501
|
+
* // }
|
|
1502
|
+
* ```
|
|
2214
1503
|
*/
|
|
2215
|
-
function
|
|
1504
|
+
function parcelDetector(projectPath, packageJson) {
|
|
2216
1505
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2217
1506
|
const sources = [];
|
|
2218
1507
|
let confidence = 0;
|
|
2219
1508
|
let version;
|
|
2220
1509
|
const deps = collectAllDependencies(pkg);
|
|
2221
|
-
if (deps['
|
|
2222
|
-
confidence +=
|
|
2223
|
-
version = parseVersionString(deps['
|
|
2224
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1510
|
+
if (deps['parcel']) {
|
|
1511
|
+
confidence += 60;
|
|
1512
|
+
version = parseVersionString(deps['parcel']);
|
|
1513
|
+
sources.push({ type: 'package.json', field: 'dependencies.parcel' });
|
|
2225
1514
|
}
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1515
|
+
if (deps['parcel-bundler']) {
|
|
1516
|
+
confidence += 60;
|
|
1517
|
+
version = parseVersionString(deps['parcel-bundler']);
|
|
1518
|
+
sources.push({ type: 'package.json', field: 'dependencies.parcel-bundler' });
|
|
2230
1519
|
}
|
|
2231
|
-
const
|
|
1520
|
+
const configPath = locateConfigFile(projectPath, PARCEL_CONFIG_PATTERNS);
|
|
1521
|
+
if (configPath) {
|
|
1522
|
+
confidence += 30;
|
|
1523
|
+
sources.push({ type: 'config-file', path: configPath });
|
|
1524
|
+
}
|
|
1525
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'parcel');
|
|
2232
1526
|
for (const name of scriptMatches) {
|
|
2233
1527
|
confidence = min(confidence + 10, 100);
|
|
2234
1528
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
@@ -2237,54 +1531,78 @@ function esbuildDetector(projectPath, packageJson) {
|
|
|
2237
1531
|
return null;
|
|
2238
1532
|
}
|
|
2239
1533
|
return {
|
|
2240
|
-
id: '
|
|
2241
|
-
name: '
|
|
1534
|
+
id: 'parcel',
|
|
1535
|
+
name: 'Parcel',
|
|
2242
1536
|
version,
|
|
1537
|
+
configPath,
|
|
2243
1538
|
confidence: min(confidence, 100),
|
|
2244
1539
|
detectedFrom: sources,
|
|
2245
1540
|
};
|
|
2246
1541
|
}
|
|
2247
1542
|
|
|
2248
|
-
/** Config patterns for
|
|
2249
|
-
const
|
|
1543
|
+
/** Config patterns for Rollup */
|
|
1544
|
+
const ROLLUP_CONFIG_PATTERNS = ['rollup.config.js', 'rollup.config.ts', 'rollup.config.mjs', 'rollup.config.cjs'];
|
|
2250
1545
|
/**
|
|
2251
|
-
* Detect
|
|
1546
|
+
* Detect Rollup in project.
|
|
2252
1547
|
*
|
|
2253
1548
|
* @param projectPath - Project directory path
|
|
2254
1549
|
* @param packageJson - Optional pre-loaded package.json
|
|
2255
1550
|
* @returns Detection result or null if not detected
|
|
1551
|
+
*
|
|
1552
|
+
* @example Detecting Rollup bundler
|
|
1553
|
+
* ```typescript
|
|
1554
|
+
* const result = rollupDetector('/path/to/project', {
|
|
1555
|
+
* name: 'my-lib',
|
|
1556
|
+
* devDependencies: {
|
|
1557
|
+
* 'rollup': '^4.0.0',
|
|
1558
|
+
* '@rollup/plugin-node-resolve': '^15.0.0',
|
|
1559
|
+
* '@rollup/plugin-commonjs': '^25.0.0'
|
|
1560
|
+
* }
|
|
1561
|
+
* })
|
|
1562
|
+
* // => {
|
|
1563
|
+
* // id: 'rollup',
|
|
1564
|
+
* // name: 'Rollup',
|
|
1565
|
+
* // version: '4.0.0',
|
|
1566
|
+
* // confidence: 65,
|
|
1567
|
+
* // detectedFrom: [
|
|
1568
|
+
* // { type: 'package.json', field: 'dependencies.rollup' },
|
|
1569
|
+
* // { type: 'package.json', field: 'dependencies (rollup plugins)' }
|
|
1570
|
+
* // ]
|
|
1571
|
+
* // }
|
|
1572
|
+
* ```
|
|
2256
1573
|
*/
|
|
2257
|
-
function
|
|
1574
|
+
function rollupDetector(projectPath, packageJson) {
|
|
2258
1575
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2259
1576
|
const sources = [];
|
|
2260
1577
|
let confidence = 0;
|
|
2261
1578
|
let version;
|
|
2262
1579
|
const deps = collectAllDependencies(pkg);
|
|
2263
|
-
if (deps['
|
|
2264
|
-
confidence +=
|
|
2265
|
-
version = parseVersionString(deps['
|
|
2266
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1580
|
+
if (deps['rollup']) {
|
|
1581
|
+
confidence += 55;
|
|
1582
|
+
version = parseVersionString(deps['rollup']);
|
|
1583
|
+
sources.push({ type: 'package.json', field: 'dependencies.rollup' });
|
|
2267
1584
|
}
|
|
2268
|
-
const configPath = locateConfigFile(projectPath,
|
|
1585
|
+
const configPath = locateConfigFile(projectPath, ROLLUP_CONFIG_PATTERNS);
|
|
2269
1586
|
if (configPath) {
|
|
2270
1587
|
confidence += 40;
|
|
2271
1588
|
sources.push({ type: 'config-file', path: configPath });
|
|
2272
1589
|
}
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
sources.push({ type: 'package.json', field: 'babel' });
|
|
2276
|
-
}
|
|
2277
|
-
const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
2278
|
-
if (babelPackages.length > 1) {
|
|
1590
|
+
const rollupPlugins = keys(deps).filter((d) => d.startsWith('@rollup/') || d.startsWith('rollup-plugin-'));
|
|
1591
|
+
if (rollupPlugins.length > 0) {
|
|
2279
1592
|
confidence += 10;
|
|
2280
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1593
|
+
sources.push({ type: 'package.json', field: 'dependencies (rollup plugins)' });
|
|
1594
|
+
}
|
|
1595
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'rollup');
|
|
1596
|
+
for (const name of scriptMatches) {
|
|
1597
|
+
confidence = min(confidence + 5, 100);
|
|
1598
|
+
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
2281
1599
|
}
|
|
2282
1600
|
if (confidence === 0) {
|
|
2283
1601
|
return null;
|
|
2284
1602
|
}
|
|
2285
1603
|
return {
|
|
2286
|
-
id: '
|
|
2287
|
-
name: '
|
|
1604
|
+
id: 'rollup',
|
|
1605
|
+
name: 'Rollup',
|
|
2288
1606
|
version,
|
|
2289
1607
|
configPath,
|
|
2290
1608
|
confidence: min(confidence, 100),
|
|
@@ -2300,6 +1618,24 @@ const SWC_CONFIG_PATTERNS = ['.swcrc', 'swc.config.js'];
|
|
|
2300
1618
|
* @param projectPath - Project directory path
|
|
2301
1619
|
* @param packageJson - Optional pre-loaded package.json
|
|
2302
1620
|
* @returns Detection result or null if not detected
|
|
1621
|
+
*
|
|
1622
|
+
* @example Detecting SWC compiler
|
|
1623
|
+
* ```typescript
|
|
1624
|
+
* const result = swcDetector('/path/to/project', {
|
|
1625
|
+
* name: 'my-app',
|
|
1626
|
+
* devDependencies: { '@swc/core': '^1.3.0', '@swc/cli': '^0.1.0' }
|
|
1627
|
+
* })
|
|
1628
|
+
* // => {
|
|
1629
|
+
* // id: 'swc',
|
|
1630
|
+
* // name: 'SWC',
|
|
1631
|
+
* // version: '1.3.0',
|
|
1632
|
+
* // confidence: 70,
|
|
1633
|
+
* // detectedFrom: [
|
|
1634
|
+
* // { type: 'package.json', field: 'dependencies.@swc/core' },
|
|
1635
|
+
* // { type: 'package.json', field: 'dependencies.@swc/cli' }
|
|
1636
|
+
* // ]
|
|
1637
|
+
* // }
|
|
1638
|
+
* ```
|
|
2303
1639
|
*/
|
|
2304
1640
|
function swcDetector(projectPath, packageJson) {
|
|
2305
1641
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2339,47 +1675,142 @@ function swcDetector(projectPath, packageJson) {
|
|
|
2339
1675
|
};
|
|
2340
1676
|
}
|
|
2341
1677
|
|
|
2342
|
-
/** Config patterns for
|
|
2343
|
-
const
|
|
1678
|
+
/** Config patterns for Vite */
|
|
1679
|
+
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
2344
1680
|
/**
|
|
2345
|
-
* Detect
|
|
1681
|
+
* Detect Vite in project.
|
|
2346
1682
|
*
|
|
2347
1683
|
* @param projectPath - Project directory path
|
|
2348
1684
|
* @param packageJson - Optional pre-loaded package.json
|
|
2349
1685
|
* @returns Detection result or null if not detected
|
|
1686
|
+
*
|
|
1687
|
+
* @example Detecting Vite build tool
|
|
1688
|
+
* ```typescript
|
|
1689
|
+
* const result = viteDetector('/path/to/project', {
|
|
1690
|
+
* name: 'my-app',
|
|
1691
|
+
* devDependencies: {
|
|
1692
|
+
* 'vite': '^5.0.0',
|
|
1693
|
+
* '@vitejs/plugin-react': '^4.0.0',
|
|
1694
|
+
* 'vitest': '^1.0.0'
|
|
1695
|
+
* }
|
|
1696
|
+
* })
|
|
1697
|
+
* // => {
|
|
1698
|
+
* // id: 'vite',
|
|
1699
|
+
* // name: 'Vite',
|
|
1700
|
+
* // version: '5.0.0',
|
|
1701
|
+
* // confidence: 80,
|
|
1702
|
+
* // detectedFrom: [
|
|
1703
|
+
* // { type: 'package.json', field: 'dependencies.vite' },
|
|
1704
|
+
* // { type: 'package.json', field: 'dependencies.vitest' },
|
|
1705
|
+
* // { type: 'package.json', field: 'dependencies (vite plugins)' }
|
|
1706
|
+
* // ]
|
|
1707
|
+
* // }
|
|
1708
|
+
* ```
|
|
2350
1709
|
*/
|
|
2351
|
-
function
|
|
1710
|
+
function viteDetector(projectPath, packageJson) {
|
|
2352
1711
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2353
1712
|
const sources = [];
|
|
2354
1713
|
let confidence = 0;
|
|
2355
1714
|
let version;
|
|
2356
1715
|
const deps = collectAllDependencies(pkg);
|
|
2357
|
-
if (deps['
|
|
2358
|
-
confidence += 60;
|
|
2359
|
-
version = parseVersionString(deps['parcel']);
|
|
2360
|
-
sources.push({ type: 'package.json', field: 'dependencies.parcel' });
|
|
2361
|
-
}
|
|
2362
|
-
if (deps['parcel-bundler']) {
|
|
1716
|
+
if (deps['vite']) {
|
|
2363
1717
|
confidence += 60;
|
|
2364
|
-
version = parseVersionString(deps['
|
|
2365
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1718
|
+
version = parseVersionString(deps['vite']);
|
|
1719
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite' });
|
|
2366
1720
|
}
|
|
2367
|
-
const configPath = locateConfigFile(projectPath,
|
|
1721
|
+
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
2368
1722
|
if (configPath) {
|
|
2369
|
-
confidence +=
|
|
1723
|
+
confidence += 35;
|
|
2370
1724
|
sources.push({ type: 'config-file', path: configPath });
|
|
2371
1725
|
}
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
1726
|
+
if (deps['vitest']) {
|
|
1727
|
+
confidence += 10;
|
|
1728
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
1729
|
+
}
|
|
1730
|
+
const vitePlugins = keys(deps).filter((d) => d.startsWith('vite-plugin-') || d.startsWith('@vitejs/'));
|
|
1731
|
+
if (vitePlugins.length > 0) {
|
|
1732
|
+
confidence += 10;
|
|
1733
|
+
sources.push({ type: 'package.json', field: 'dependencies (vite plugins)' });
|
|
1734
|
+
}
|
|
1735
|
+
if (confidence === 0) {
|
|
1736
|
+
return null;
|
|
1737
|
+
}
|
|
1738
|
+
return {
|
|
1739
|
+
id: 'vite',
|
|
1740
|
+
name: 'Vite',
|
|
1741
|
+
version,
|
|
1742
|
+
configPath,
|
|
1743
|
+
confidence: min(confidence, 100),
|
|
1744
|
+
detectedFrom: sources,
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
/** Config patterns for Webpack */
|
|
1749
|
+
const WEBPACK_CONFIG_PATTERNS = [
|
|
1750
|
+
'webpack.config.js',
|
|
1751
|
+
'webpack.config.ts',
|
|
1752
|
+
'webpack.config.cjs',
|
|
1753
|
+
'webpack.config.mjs',
|
|
1754
|
+
'webpack.config.babel.js',
|
|
1755
|
+
];
|
|
1756
|
+
/**
|
|
1757
|
+
* Detect Webpack in project.
|
|
1758
|
+
*
|
|
1759
|
+
* @param projectPath - Project directory path
|
|
1760
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
1761
|
+
* @returns Detection result or null if not detected
|
|
1762
|
+
*
|
|
1763
|
+
* @example Detecting Webpack bundler
|
|
1764
|
+
* ```typescript
|
|
1765
|
+
* const result = webpackDetector('/path/to/project', {
|
|
1766
|
+
* name: 'my-app',
|
|
1767
|
+
* devDependencies: { 'webpack': '^5.89.0', 'webpack-cli': '^5.1.0' },
|
|
1768
|
+
* scripts: { 'build': 'webpack --mode production' }
|
|
1769
|
+
* })
|
|
1770
|
+
* // => {
|
|
1771
|
+
* // id: 'webpack',
|
|
1772
|
+
* // name: 'Webpack',
|
|
1773
|
+
* // version: '5.89.0',
|
|
1774
|
+
* // confidence: 65,
|
|
1775
|
+
* // detectedFrom: [
|
|
1776
|
+
* // { type: 'package.json', field: 'dependencies.webpack' },
|
|
1777
|
+
* // { type: 'package.json', field: 'dependencies.webpack-cli' },
|
|
1778
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
1779
|
+
* // ]
|
|
1780
|
+
* // }
|
|
1781
|
+
* ```
|
|
1782
|
+
*/
|
|
1783
|
+
function webpackDetector(projectPath, packageJson) {
|
|
1784
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1785
|
+
const sources = [];
|
|
1786
|
+
let confidence = 0;
|
|
1787
|
+
let version;
|
|
1788
|
+
const deps = collectAllDependencies(pkg);
|
|
1789
|
+
if (deps['webpack']) {
|
|
1790
|
+
confidence += 50;
|
|
1791
|
+
version = parseVersionString(deps['webpack']);
|
|
1792
|
+
sources.push({ type: 'package.json', field: 'dependencies.webpack' });
|
|
1793
|
+
}
|
|
1794
|
+
const configPath = locateConfigFile(projectPath, WEBPACK_CONFIG_PATTERNS);
|
|
1795
|
+
if (configPath) {
|
|
1796
|
+
confidence += 40;
|
|
1797
|
+
sources.push({ type: 'config-file', path: configPath });
|
|
1798
|
+
}
|
|
1799
|
+
if (deps['webpack-cli']) {
|
|
1800
|
+
confidence += 10;
|
|
1801
|
+
sources.push({ type: 'package.json', field: 'dependencies.webpack-cli' });
|
|
1802
|
+
}
|
|
1803
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'webpack');
|
|
1804
|
+
for (const name of scriptMatches) {
|
|
1805
|
+
confidence = min(confidence + 5, 100);
|
|
2375
1806
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
2376
1807
|
}
|
|
2377
1808
|
if (confidence === 0) {
|
|
2378
1809
|
return null;
|
|
2379
1810
|
}
|
|
2380
1811
|
return {
|
|
2381
|
-
id: '
|
|
2382
|
-
name: '
|
|
1812
|
+
id: 'webpack',
|
|
1813
|
+
name: 'Webpack',
|
|
2383
1814
|
version,
|
|
2384
1815
|
configPath,
|
|
2385
1816
|
confidence: min(confidence, 100),
|
|
@@ -2399,81 +1830,187 @@ const buildToolDetectors = [
|
|
|
2399
1830
|
];
|
|
2400
1831
|
|
|
2401
1832
|
/**
|
|
2402
|
-
* Detect
|
|
1833
|
+
* Detect Angular in project.
|
|
2403
1834
|
*
|
|
2404
1835
|
* @param projectPath - Project directory path
|
|
2405
1836
|
* @param packageJson - Optional pre-loaded package.json
|
|
2406
1837
|
* @returns Detection result or null if not detected
|
|
1838
|
+
*
|
|
1839
|
+
* @example Detecting Angular framework
|
|
1840
|
+
* ```typescript
|
|
1841
|
+
* const result = angularDetector('/path/to/angular-app', {
|
|
1842
|
+
* dependencies: { '@angular/core': '^17.0.0', '@angular/cli': '^17.0.0' }
|
|
1843
|
+
* })
|
|
1844
|
+
* // => {
|
|
1845
|
+
* // id: 'angular',
|
|
1846
|
+
* // name: 'Angular',
|
|
1847
|
+
* // category: 'frontend',
|
|
1848
|
+
* // version: '17.0.0',
|
|
1849
|
+
* // confidence: 85,
|
|
1850
|
+
* // detectedFrom: [
|
|
1851
|
+
* // { type: 'package.json', field: 'dependencies.@angular/core' },
|
|
1852
|
+
* // { type: 'package.json', field: 'dependencies.@angular/cli' }
|
|
1853
|
+
* // ]
|
|
1854
|
+
* // }
|
|
1855
|
+
* ```
|
|
2407
1856
|
*/
|
|
2408
|
-
function
|
|
1857
|
+
function angularDetector(projectPath, packageJson) {
|
|
2409
1858
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2410
1859
|
const sources = [];
|
|
2411
1860
|
let confidence = 0;
|
|
2412
1861
|
let version;
|
|
2413
|
-
const metaFrameworks = [];
|
|
2414
1862
|
const deps = collectAllDependencies(pkg);
|
|
2415
|
-
if (deps['
|
|
2416
|
-
confidence +=
|
|
2417
|
-
version = parseVersionString(deps['
|
|
2418
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1863
|
+
if (deps['@angular/core']) {
|
|
1864
|
+
confidence += 70;
|
|
1865
|
+
version = parseVersionString(deps['@angular/core']);
|
|
1866
|
+
sources.push({ type: 'package.json', field: 'dependencies.@angular/core' });
|
|
2419
1867
|
}
|
|
2420
|
-
if (deps['
|
|
2421
|
-
confidence +=
|
|
2422
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1868
|
+
if (deps['@angular/cli']) {
|
|
1869
|
+
confidence += 15;
|
|
1870
|
+
sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
|
|
2423
1871
|
}
|
|
2424
|
-
if (
|
|
2425
|
-
confidence +=
|
|
2426
|
-
sources.push({ type: '
|
|
1872
|
+
if (exists(join$1(projectPath, 'angular.json'))) {
|
|
1873
|
+
confidence += 15;
|
|
1874
|
+
sources.push({ type: 'config-file', path: 'angular.json' });
|
|
2427
1875
|
}
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
1876
|
+
if (deps['angular'] && !deps['@angular/core']) {
|
|
1877
|
+
return {
|
|
1878
|
+
id: 'angularjs',
|
|
1879
|
+
name: 'AngularJS (Legacy)',
|
|
1880
|
+
category: 'frontend',
|
|
1881
|
+
version: parseVersionString(deps['angular']),
|
|
1882
|
+
confidence: 80,
|
|
1883
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
1884
|
+
};
|
|
2435
1885
|
}
|
|
2436
|
-
if (
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
1886
|
+
if (confidence === 0) {
|
|
1887
|
+
return null;
|
|
1888
|
+
}
|
|
1889
|
+
return {
|
|
1890
|
+
id: 'angular',
|
|
1891
|
+
name: 'Angular',
|
|
1892
|
+
category: 'frontend',
|
|
1893
|
+
version,
|
|
1894
|
+
confidence: min(confidence, 100),
|
|
1895
|
+
detectedFrom: sources,
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
/**
|
|
1900
|
+
* Detect Astro in project.
|
|
1901
|
+
*
|
|
1902
|
+
* @param projectPath - Project directory path
|
|
1903
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
1904
|
+
* @returns Detection result or null if not detected
|
|
1905
|
+
*
|
|
1906
|
+
* @example Detecting Astro framework
|
|
1907
|
+
* ```typescript
|
|
1908
|
+
* const result = astroDetector('/path/to/astro-project', {
|
|
1909
|
+
* dependencies: { 'astro': '^4.0.0' }
|
|
1910
|
+
* })
|
|
1911
|
+
* // => {
|
|
1912
|
+
* // id: 'astro',
|
|
1913
|
+
* // name: 'Astro',
|
|
1914
|
+
* // category: 'meta-framework',
|
|
1915
|
+
* // version: '4.0.0',
|
|
1916
|
+
* // confidence: 70,
|
|
1917
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.astro' }]
|
|
1918
|
+
* // }
|
|
1919
|
+
* ```
|
|
1920
|
+
*/
|
|
1921
|
+
function astroDetector(projectPath, packageJson) {
|
|
1922
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1923
|
+
const sources = [];
|
|
1924
|
+
let confidence = 0;
|
|
1925
|
+
let version;
|
|
1926
|
+
const deps = collectAllDependencies(pkg);
|
|
1927
|
+
if (deps['astro']) {
|
|
1928
|
+
confidence += 70;
|
|
1929
|
+
version = parseVersionString(deps['astro']);
|
|
1930
|
+
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
1931
|
+
}
|
|
1932
|
+
if (exists(join$1(projectPath, 'astro.config.mjs')) ||
|
|
1933
|
+
exists(join$1(projectPath, 'astro.config.ts')) ||
|
|
1934
|
+
exists(join$1(projectPath, 'astro.config.js'))) {
|
|
1935
|
+
confidence += 25;
|
|
1936
|
+
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
2445
1937
|
}
|
|
1938
|
+
if (exists(join$1(projectPath, 'src', 'pages'))) {
|
|
1939
|
+
confidence += 5;
|
|
1940
|
+
sources.push({ type: 'directory', path: 'src/pages/' });
|
|
1941
|
+
}
|
|
1942
|
+
if (confidence === 0) {
|
|
1943
|
+
return null;
|
|
1944
|
+
}
|
|
1945
|
+
return {
|
|
1946
|
+
id: 'astro',
|
|
1947
|
+
name: 'Astro',
|
|
1948
|
+
category: 'meta-framework',
|
|
1949
|
+
version,
|
|
1950
|
+
confidence: min(confidence, 100),
|
|
1951
|
+
detectedFrom: sources,
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
/**
|
|
1956
|
+
* Detect Gatsby in project.
|
|
1957
|
+
*
|
|
1958
|
+
* @param projectPath - Project directory path
|
|
1959
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
1960
|
+
* @returns Detection result or null if not detected
|
|
1961
|
+
*
|
|
1962
|
+
* @example Detecting Gatsby framework
|
|
1963
|
+
* ```typescript
|
|
1964
|
+
* const result = gatsbyDetector('/path/to/gatsby-blog', {
|
|
1965
|
+
* dependencies: {
|
|
1966
|
+
* 'gatsby': '^5.0.0',
|
|
1967
|
+
* 'gatsby-plugin-image': '^3.0.0',
|
|
1968
|
+
* 'gatsby-source-filesystem': '^5.0.0'
|
|
1969
|
+
* }
|
|
1970
|
+
* })
|
|
1971
|
+
* // => {
|
|
1972
|
+
* // id: 'gatsby',
|
|
1973
|
+
* // name: 'Gatsby',
|
|
1974
|
+
* // category: 'meta-framework',
|
|
1975
|
+
* // version: '5.0.0',
|
|
1976
|
+
* // confidence: 75,
|
|
1977
|
+
* // detectedFrom: [
|
|
1978
|
+
* // { type: 'package.json', field: 'dependencies.gatsby' },
|
|
1979
|
+
* // { type: 'package.json', field: 'dependencies (gatsby plugins)' }
|
|
1980
|
+
* // ]
|
|
1981
|
+
* // }
|
|
1982
|
+
* ```
|
|
1983
|
+
*/
|
|
1984
|
+
function gatsbyDetector(projectPath, packageJson) {
|
|
1985
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1986
|
+
const sources = [];
|
|
1987
|
+
let confidence = 0;
|
|
1988
|
+
let version;
|
|
1989
|
+
const deps = collectAllDependencies(pkg);
|
|
2446
1990
|
if (deps['gatsby']) {
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
category: 'meta-framework',
|
|
2451
|
-
version: parseVersionString(deps['gatsby']),
|
|
2452
|
-
confidence: 90,
|
|
2453
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
2454
|
-
});
|
|
1991
|
+
confidence += 70;
|
|
1992
|
+
version = parseVersionString(deps['gatsby']);
|
|
1993
|
+
sources.push({ type: 'package.json', field: 'dependencies.gatsby' });
|
|
2455
1994
|
}
|
|
2456
|
-
if (
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
});
|
|
1995
|
+
if (exists(join$1(projectPath, 'gatsby-config.js')) || exists(join$1(projectPath, 'gatsby-config.ts'))) {
|
|
1996
|
+
confidence += 25;
|
|
1997
|
+
sources.push({ type: 'config-file', path: 'gatsby-config.*' });
|
|
1998
|
+
}
|
|
1999
|
+
const gatsbyPlugins = keys(deps).filter((d) => d.startsWith('gatsby-plugin-') || d.startsWith('gatsby-source-'));
|
|
2000
|
+
if (gatsbyPlugins.length > 0) {
|
|
2001
|
+
confidence += 5;
|
|
2002
|
+
sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
|
|
2465
2003
|
}
|
|
2466
2004
|
if (confidence === 0) {
|
|
2467
2005
|
return null;
|
|
2468
2006
|
}
|
|
2469
2007
|
return {
|
|
2470
|
-
id: '
|
|
2471
|
-
name: '
|
|
2472
|
-
category: '
|
|
2008
|
+
id: 'gatsby',
|
|
2009
|
+
name: 'Gatsby',
|
|
2010
|
+
category: 'meta-framework',
|
|
2473
2011
|
version,
|
|
2474
2012
|
confidence: min(confidence, 100),
|
|
2475
2013
|
detectedFrom: sources,
|
|
2476
|
-
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
2477
2014
|
};
|
|
2478
2015
|
}
|
|
2479
2016
|
|
|
@@ -2483,6 +2020,21 @@ function reactDetector(projectPath, packageJson) {
|
|
|
2483
2020
|
* @param projectPath - Project directory path
|
|
2484
2021
|
* @param packageJson - Optional pre-loaded package.json
|
|
2485
2022
|
* @returns Detection result or null if not detected
|
|
2023
|
+
*
|
|
2024
|
+
* @example Detecting Next.js framework
|
|
2025
|
+
* ```typescript
|
|
2026
|
+
* const result = nextjsDetector('/path/to/nextjs-app', {
|
|
2027
|
+
* dependencies: { 'next': '^14.0.0', 'react': '^18.0.0' }
|
|
2028
|
+
* })
|
|
2029
|
+
* // => {
|
|
2030
|
+
* // id: 'nextjs',
|
|
2031
|
+
* // name: 'Next.js',
|
|
2032
|
+
* // category: 'meta-framework',
|
|
2033
|
+
* // version: '14.0.0',
|
|
2034
|
+
* // confidence: 70,
|
|
2035
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }]
|
|
2036
|
+
* // }
|
|
2037
|
+
* ```
|
|
2486
2038
|
*/
|
|
2487
2039
|
function nextjsDetector(projectPath, packageJson) {
|
|
2488
2040
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2522,37 +2074,52 @@ function nextjsDetector(projectPath, packageJson) {
|
|
|
2522
2074
|
}
|
|
2523
2075
|
|
|
2524
2076
|
/**
|
|
2525
|
-
* Detect
|
|
2077
|
+
* Detect Nuxt in project.
|
|
2526
2078
|
*
|
|
2527
2079
|
* @param projectPath - Project directory path
|
|
2528
2080
|
* @param packageJson - Optional pre-loaded package.json
|
|
2529
2081
|
* @returns Detection result or null if not detected
|
|
2082
|
+
*
|
|
2083
|
+
* @example Detecting Nuxt framework
|
|
2084
|
+
* ```typescript
|
|
2085
|
+
* const result = nuxtDetector('/path/to/nuxt-app', {
|
|
2086
|
+
* dependencies: { 'nuxt': '^3.0.0', 'vue': '^3.0.0' }
|
|
2087
|
+
* })
|
|
2088
|
+
* // => {
|
|
2089
|
+
* // id: 'nuxt',
|
|
2090
|
+
* // name: 'Nuxt',
|
|
2091
|
+
* // category: 'meta-framework',
|
|
2092
|
+
* // version: '3.0.0',
|
|
2093
|
+
* // confidence: 70,
|
|
2094
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }]
|
|
2095
|
+
* // }
|
|
2096
|
+
* ```
|
|
2530
2097
|
*/
|
|
2531
|
-
function
|
|
2098
|
+
function nuxtDetector(projectPath, packageJson) {
|
|
2532
2099
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2533
2100
|
const sources = [];
|
|
2534
2101
|
let confidence = 0;
|
|
2535
2102
|
let version;
|
|
2536
2103
|
const deps = collectAllDependencies(pkg);
|
|
2537
|
-
if (deps['
|
|
2104
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
2538
2105
|
confidence += 70;
|
|
2539
|
-
version = parseVersionString(deps['
|
|
2540
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
2106
|
+
version = parseVersionString(deps['nuxt'] ?? deps['nuxt3']);
|
|
2107
|
+
sources.push({ type: 'package.json', field: 'dependencies.nuxt' });
|
|
2541
2108
|
}
|
|
2542
|
-
if (
|
|
2543
|
-
confidence +=
|
|
2544
|
-
sources.push({ type: '
|
|
2109
|
+
if (exists(join$1(projectPath, 'nuxt.config.js')) || exists(join$1(projectPath, 'nuxt.config.ts'))) {
|
|
2110
|
+
confidence += 25;
|
|
2111
|
+
sources.push({ type: 'config-file', path: 'nuxt.config.*' });
|
|
2545
2112
|
}
|
|
2546
|
-
if (exists(join$1(projectPath, '
|
|
2547
|
-
confidence +=
|
|
2548
|
-
sources.push({ type: '
|
|
2113
|
+
if (exists(join$1(projectPath, 'pages'))) {
|
|
2114
|
+
confidence += 5;
|
|
2115
|
+
sources.push({ type: 'directory', path: 'pages/' });
|
|
2549
2116
|
}
|
|
2550
2117
|
if (confidence === 0) {
|
|
2551
2118
|
return null;
|
|
2552
2119
|
}
|
|
2553
2120
|
return {
|
|
2554
|
-
id: '
|
|
2555
|
-
name: '
|
|
2121
|
+
id: 'nuxt',
|
|
2122
|
+
name: 'Nuxt',
|
|
2556
2123
|
category: 'meta-framework',
|
|
2557
2124
|
version,
|
|
2558
2125
|
confidence: min(confidence, 100),
|
|
@@ -2561,39 +2128,59 @@ function remixDetector(projectPath, packageJson) {
|
|
|
2561
2128
|
}
|
|
2562
2129
|
|
|
2563
2130
|
/**
|
|
2564
|
-
* Detect
|
|
2131
|
+
* Detect Qwik in project.
|
|
2565
2132
|
*
|
|
2566
2133
|
* @param projectPath - Project directory path
|
|
2567
2134
|
* @param packageJson - Optional pre-loaded package.json
|
|
2568
2135
|
* @returns Detection result or null if not detected
|
|
2136
|
+
*
|
|
2137
|
+
* @example Detecting Qwik framework
|
|
2138
|
+
* ```typescript
|
|
2139
|
+
* const result = qwikDetector('/path/to/qwik-app', {
|
|
2140
|
+
* dependencies: {
|
|
2141
|
+
* '@builder.io/qwik': '^1.0.0',
|
|
2142
|
+
* '@builder.io/qwik-city': '^1.0.0'
|
|
2143
|
+
* }
|
|
2144
|
+
* })
|
|
2145
|
+
* // => {
|
|
2146
|
+
* // id: 'qwik',
|
|
2147
|
+
* // name: 'Qwik',
|
|
2148
|
+
* // category: 'frontend',
|
|
2149
|
+
* // version: '1.0.0',
|
|
2150
|
+
* // confidence: 90,
|
|
2151
|
+
* // detectedFrom: [
|
|
2152
|
+
* // { type: 'package.json', field: 'dependencies.@builder.io/qwik' },
|
|
2153
|
+
* // { type: 'package.json', field: 'dependencies.@builder.io/qwik-city' }
|
|
2154
|
+
* // ]
|
|
2155
|
+
* // }
|
|
2156
|
+
* ```
|
|
2569
2157
|
*/
|
|
2570
|
-
function
|
|
2158
|
+
function qwikDetector(projectPath, packageJson) {
|
|
2571
2159
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2572
2160
|
const sources = [];
|
|
2573
2161
|
let confidence = 0;
|
|
2574
2162
|
let version;
|
|
2575
2163
|
const deps = collectAllDependencies(pkg);
|
|
2576
|
-
if (deps['
|
|
2164
|
+
if (deps['@builder.io/qwik']) {
|
|
2577
2165
|
confidence += 70;
|
|
2578
|
-
version = parseVersionString(deps['
|
|
2579
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2166
|
+
version = parseVersionString(deps['@builder.io/qwik']);
|
|
2167
|
+
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
|
|
2580
2168
|
}
|
|
2581
|
-
if (
|
|
2582
|
-
confidence +=
|
|
2583
|
-
sources.push({ type: '
|
|
2169
|
+
if (deps['@builder.io/qwik-city']) {
|
|
2170
|
+
confidence += 20;
|
|
2171
|
+
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
|
|
2584
2172
|
}
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
|
|
2173
|
+
if (exists(join$1(projectPath, 'qwik.config.ts')) || exists(join$1(projectPath, 'qwik.config.js'))) {
|
|
2174
|
+
confidence += 10;
|
|
2175
|
+
sources.push({ type: 'config-file', path: 'qwik.config.*' });
|
|
2589
2176
|
}
|
|
2590
2177
|
if (confidence === 0) {
|
|
2591
2178
|
return null;
|
|
2592
2179
|
}
|
|
2593
2180
|
return {
|
|
2594
|
-
id: '
|
|
2595
|
-
name: '
|
|
2596
|
-
category: '
|
|
2181
|
+
id: 'qwik',
|
|
2182
|
+
name: 'Qwik',
|
|
2183
|
+
category: 'frontend',
|
|
2597
2184
|
version,
|
|
2598
2185
|
confidence: min(confidence, 100),
|
|
2599
2186
|
detectedFrom: sources,
|
|
@@ -2601,53 +2188,94 @@ function gatsbyDetector(projectPath, packageJson) {
|
|
|
2601
2188
|
}
|
|
2602
2189
|
|
|
2603
2190
|
/**
|
|
2604
|
-
* Detect
|
|
2191
|
+
* Detect React in project.
|
|
2605
2192
|
*
|
|
2606
2193
|
* @param projectPath - Project directory path
|
|
2607
2194
|
* @param packageJson - Optional pre-loaded package.json
|
|
2608
2195
|
* @returns Detection result or null if not detected
|
|
2196
|
+
*
|
|
2197
|
+
* @example Detecting React library
|
|
2198
|
+
* ```typescript
|
|
2199
|
+
* const result = reactDetector('/path/to/react-app', {
|
|
2200
|
+
* dependencies: { 'react': '^18.0.0', 'react-dom': '^18.0.0' }
|
|
2201
|
+
* })
|
|
2202
|
+
* // => {
|
|
2203
|
+
* // id: 'react',
|
|
2204
|
+
* // name: 'React',
|
|
2205
|
+
* // category: 'frontend',
|
|
2206
|
+
* // version: '18.0.0',
|
|
2207
|
+
* // confidence: 80,
|
|
2208
|
+
* // detectedFrom: [
|
|
2209
|
+
* // { type: 'package.json', field: 'dependencies.react' },
|
|
2210
|
+
* // { type: 'package.json', field: 'dependencies.react-dom' }
|
|
2211
|
+
* // ]
|
|
2212
|
+
* // }
|
|
2213
|
+
* ```
|
|
2609
2214
|
*/
|
|
2610
|
-
function
|
|
2215
|
+
function reactDetector(projectPath, packageJson) {
|
|
2611
2216
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2612
2217
|
const sources = [];
|
|
2613
2218
|
let confidence = 0;
|
|
2614
2219
|
let version;
|
|
2615
2220
|
const metaFrameworks = [];
|
|
2616
2221
|
const deps = collectAllDependencies(pkg);
|
|
2617
|
-
if (deps['
|
|
2618
|
-
confidence +=
|
|
2619
|
-
version = parseVersionString(deps['
|
|
2620
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2222
|
+
if (deps['react']) {
|
|
2223
|
+
confidence += 60;
|
|
2224
|
+
version = parseVersionString(deps['react']);
|
|
2225
|
+
sources.push({ type: 'package.json', field: 'dependencies.react' });
|
|
2621
2226
|
}
|
|
2622
|
-
if (deps['
|
|
2623
|
-
confidence +=
|
|
2624
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
2227
|
+
if (deps['react-dom']) {
|
|
2228
|
+
confidence += 20;
|
|
2229
|
+
sources.push({ type: 'package.json', field: 'dependencies.react-dom' });
|
|
2625
2230
|
}
|
|
2626
|
-
|
|
2627
|
-
|
|
2231
|
+
if (deps['react-native']) {
|
|
2232
|
+
confidence += 20;
|
|
2233
|
+
sources.push({ type: 'package.json', field: 'dependencies.react-native' });
|
|
2234
|
+
}
|
|
2235
|
+
const hasJsxFiles = exists(join$1(projectPath, 'src', 'App.tsx')) ||
|
|
2236
|
+
exists(join$1(projectPath, 'src', 'App.jsx')) ||
|
|
2237
|
+
exists(join$1(projectPath, 'src', 'index.tsx')) ||
|
|
2238
|
+
exists(join$1(projectPath, 'src', 'index.jsx'));
|
|
2239
|
+
if (hasJsxFiles) {
|
|
2628
2240
|
confidence += 10;
|
|
2629
|
-
sources.push({ type: 'directory', path: 'src/*.
|
|
2241
|
+
sources.push({ type: 'directory', path: 'src/*.tsx or src/*.jsx' });
|
|
2630
2242
|
}
|
|
2631
|
-
if (
|
|
2632
|
-
|
|
2633
|
-
|
|
2243
|
+
if (deps['next']) {
|
|
2244
|
+
metaFrameworks.push({
|
|
2245
|
+
id: 'nextjs',
|
|
2246
|
+
name: 'Next.js',
|
|
2247
|
+
category: 'meta-framework',
|
|
2248
|
+
version: parseVersionString(deps['next']),
|
|
2249
|
+
confidence: 90,
|
|
2250
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }],
|
|
2251
|
+
});
|
|
2634
2252
|
}
|
|
2635
|
-
if (deps['
|
|
2253
|
+
if (deps['gatsby']) {
|
|
2636
2254
|
metaFrameworks.push({
|
|
2637
|
-
id: '
|
|
2638
|
-
name: '
|
|
2255
|
+
id: 'gatsby',
|
|
2256
|
+
name: 'Gatsby',
|
|
2639
2257
|
category: 'meta-framework',
|
|
2640
|
-
version: parseVersionString(deps['
|
|
2258
|
+
version: parseVersionString(deps['gatsby']),
|
|
2641
2259
|
confidence: 90,
|
|
2642
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.
|
|
2260
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
if (deps['@remix-run/react'] || deps['remix']) {
|
|
2264
|
+
metaFrameworks.push({
|
|
2265
|
+
id: 'remix',
|
|
2266
|
+
name: 'Remix',
|
|
2267
|
+
category: 'meta-framework',
|
|
2268
|
+
version: parseVersionString(deps['@remix-run/react'] ?? deps['remix']),
|
|
2269
|
+
confidence: 90,
|
|
2270
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.@remix-run/react' }],
|
|
2643
2271
|
});
|
|
2644
2272
|
}
|
|
2645
2273
|
if (confidence === 0) {
|
|
2646
2274
|
return null;
|
|
2647
2275
|
}
|
|
2648
2276
|
return {
|
|
2649
|
-
id: '
|
|
2650
|
-
name: '
|
|
2277
|
+
id: 'react',
|
|
2278
|
+
name: 'React',
|
|
2651
2279
|
category: 'frontend',
|
|
2652
2280
|
version,
|
|
2653
2281
|
confidence: min(confidence, 100),
|
|
@@ -2657,37 +2285,58 @@ function vueDetector(projectPath, packageJson) {
|
|
|
2657
2285
|
}
|
|
2658
2286
|
|
|
2659
2287
|
/**
|
|
2660
|
-
* Detect
|
|
2288
|
+
* Detect Remix in project.
|
|
2661
2289
|
*
|
|
2662
2290
|
* @param projectPath - Project directory path
|
|
2663
2291
|
* @param packageJson - Optional pre-loaded package.json
|
|
2664
2292
|
* @returns Detection result or null if not detected
|
|
2293
|
+
*
|
|
2294
|
+
* @example Detecting Remix framework
|
|
2295
|
+
* ```typescript
|
|
2296
|
+
* const result = remixDetector('/path/to/remix-app', {
|
|
2297
|
+
* dependencies: {
|
|
2298
|
+
* '@remix-run/react': '^2.0.0',
|
|
2299
|
+
* '@remix-run/node': '^2.0.0'
|
|
2300
|
+
* }
|
|
2301
|
+
* })
|
|
2302
|
+
* // => {
|
|
2303
|
+
* // id: 'remix',
|
|
2304
|
+
* // name: 'Remix',
|
|
2305
|
+
* // category: 'meta-framework',
|
|
2306
|
+
* // version: '2.0.0',
|
|
2307
|
+
* // confidence: 90,
|
|
2308
|
+
* // detectedFrom: [
|
|
2309
|
+
* // { type: 'package.json', field: 'dependencies.@remix-run/react' },
|
|
2310
|
+
* // { type: 'package.json', field: 'dependencies.@remix-run/*' }
|
|
2311
|
+
* // ]
|
|
2312
|
+
* // }
|
|
2313
|
+
* ```
|
|
2665
2314
|
*/
|
|
2666
|
-
function
|
|
2315
|
+
function remixDetector(projectPath, packageJson) {
|
|
2667
2316
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2668
2317
|
const sources = [];
|
|
2669
2318
|
let confidence = 0;
|
|
2670
2319
|
let version;
|
|
2671
2320
|
const deps = collectAllDependencies(pkg);
|
|
2672
|
-
if (deps['
|
|
2321
|
+
if (deps['@remix-run/react']) {
|
|
2673
2322
|
confidence += 70;
|
|
2674
|
-
version = parseVersionString(deps['
|
|
2675
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
2323
|
+
version = parseVersionString(deps['@remix-run/react']);
|
|
2324
|
+
sources.push({ type: 'package.json', field: 'dependencies.@remix-run/react' });
|
|
2676
2325
|
}
|
|
2677
|
-
if (
|
|
2678
|
-
confidence +=
|
|
2679
|
-
sources.push({ type: '
|
|
2326
|
+
if (deps['@remix-run/node'] || deps['@remix-run/cloudflare'] || deps['@remix-run/deno']) {
|
|
2327
|
+
confidence += 20;
|
|
2328
|
+
sources.push({ type: 'package.json', field: 'dependencies.@remix-run/*' });
|
|
2680
2329
|
}
|
|
2681
|
-
if (exists(join$1(projectPath, '
|
|
2682
|
-
confidence +=
|
|
2683
|
-
sources.push({ type: '
|
|
2330
|
+
if (exists(join$1(projectPath, 'remix.config.js')) || exists(join$1(projectPath, 'remix.config.ts'))) {
|
|
2331
|
+
confidence += 10;
|
|
2332
|
+
sources.push({ type: 'config-file', path: 'remix.config.*' });
|
|
2684
2333
|
}
|
|
2685
2334
|
if (confidence === 0) {
|
|
2686
2335
|
return null;
|
|
2687
2336
|
}
|
|
2688
2337
|
return {
|
|
2689
|
-
id: '
|
|
2690
|
-
name: '
|
|
2338
|
+
id: 'remix',
|
|
2339
|
+
name: 'Remix',
|
|
2691
2340
|
category: 'meta-framework',
|
|
2692
2341
|
version,
|
|
2693
2342
|
confidence: min(confidence, 100),
|
|
@@ -2696,47 +2345,55 @@ function nuxtDetector(projectPath, packageJson) {
|
|
|
2696
2345
|
}
|
|
2697
2346
|
|
|
2698
2347
|
/**
|
|
2699
|
-
* Detect
|
|
2348
|
+
* Detect Solid in project.
|
|
2700
2349
|
*
|
|
2701
2350
|
* @param projectPath - Project directory path
|
|
2702
2351
|
* @param packageJson - Optional pre-loaded package.json
|
|
2703
2352
|
* @returns Detection result or null if not detected
|
|
2353
|
+
*
|
|
2354
|
+
* @example Detecting Solid.js framework
|
|
2355
|
+
* ```typescript
|
|
2356
|
+
* const result = solidDetector('/path/to/solid-app', {
|
|
2357
|
+
* dependencies: { 'solid-js': '^1.8.0', 'vite-plugin-solid': '^2.0.0' }
|
|
2358
|
+
* })
|
|
2359
|
+
* // => {
|
|
2360
|
+
* // id: 'solid',
|
|
2361
|
+
* // name: 'Solid',
|
|
2362
|
+
* // category: 'frontend',
|
|
2363
|
+
* // version: '1.8.0',
|
|
2364
|
+
* // confidence: 90,
|
|
2365
|
+
* // detectedFrom: [
|
|
2366
|
+
* // { type: 'package.json', field: 'dependencies.solid-js' },
|
|
2367
|
+
* // { type: 'package.json', field: 'dependencies.vite-plugin-solid' }
|
|
2368
|
+
* // ]
|
|
2369
|
+
* // }
|
|
2370
|
+
* ```
|
|
2704
2371
|
*/
|
|
2705
|
-
function
|
|
2372
|
+
function solidDetector(projectPath, packageJson) {
|
|
2706
2373
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2707
2374
|
const sources = [];
|
|
2708
2375
|
let confidence = 0;
|
|
2709
2376
|
let version;
|
|
2710
2377
|
const deps = collectAllDependencies(pkg);
|
|
2711
|
-
if (deps['
|
|
2378
|
+
if (deps['solid-js']) {
|
|
2712
2379
|
confidence += 70;
|
|
2713
|
-
version = parseVersionString(deps['
|
|
2714
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
2715
|
-
}
|
|
2716
|
-
if (deps['@angular/cli']) {
|
|
2717
|
-
confidence += 15;
|
|
2718
|
-
sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
|
|
2380
|
+
version = parseVersionString(deps['solid-js']);
|
|
2381
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
2719
2382
|
}
|
|
2720
|
-
if (
|
|
2721
|
-
confidence +=
|
|
2722
|
-
sources.push({ type: '
|
|
2383
|
+
if (deps['vite-plugin-solid']) {
|
|
2384
|
+
confidence += 20;
|
|
2385
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
2723
2386
|
}
|
|
2724
|
-
if (deps['
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
name: 'AngularJS (Legacy)',
|
|
2728
|
-
category: 'frontend',
|
|
2729
|
-
version: parseVersionString(deps['angular']),
|
|
2730
|
-
confidence: 80,
|
|
2731
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
2732
|
-
};
|
|
2387
|
+
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
2388
|
+
confidence += 10;
|
|
2389
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
2733
2390
|
}
|
|
2734
2391
|
if (confidence === 0) {
|
|
2735
2392
|
return null;
|
|
2736
2393
|
}
|
|
2737
2394
|
return {
|
|
2738
|
-
id: '
|
|
2739
|
-
name: '
|
|
2395
|
+
id: 'solid',
|
|
2396
|
+
name: 'Solid',
|
|
2740
2397
|
category: 'frontend',
|
|
2741
2398
|
version,
|
|
2742
2399
|
confidence: min(confidence, 100),
|
|
@@ -2750,6 +2407,21 @@ function angularDetector(projectPath, packageJson) {
|
|
|
2750
2407
|
* @param projectPath - Project directory path
|
|
2751
2408
|
* @param packageJson - Optional pre-loaded package.json
|
|
2752
2409
|
* @returns Detection result or null if not detected
|
|
2410
|
+
*
|
|
2411
|
+
* @example Detecting Svelte framework
|
|
2412
|
+
* ```typescript
|
|
2413
|
+
* const result = svelteDetector('/path/to/svelte-app', {
|
|
2414
|
+
* devDependencies: { 'svelte': '^4.0.0' }
|
|
2415
|
+
* })
|
|
2416
|
+
* // => {
|
|
2417
|
+
* // id: 'svelte',
|
|
2418
|
+
* // name: 'Svelte',
|
|
2419
|
+
* // category: 'frontend',
|
|
2420
|
+
* // version: '4.0.0',
|
|
2421
|
+
* // confidence: 70,
|
|
2422
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.svelte' }]
|
|
2423
|
+
* // }
|
|
2424
|
+
* ```
|
|
2753
2425
|
*/
|
|
2754
2426
|
function svelteDetector(projectPath, packageJson) {
|
|
2755
2427
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2802,6 +2474,21 @@ function svelteDetector(projectPath, packageJson) {
|
|
|
2802
2474
|
* @param projectPath - Project directory path
|
|
2803
2475
|
* @param packageJson - Optional pre-loaded package.json
|
|
2804
2476
|
* @returns Detection result or null if not detected
|
|
2477
|
+
*
|
|
2478
|
+
* @example Detecting SvelteKit framework
|
|
2479
|
+
* ```typescript
|
|
2480
|
+
* const result = sveltekitDetector('/path/to/sveltekit-app', {
|
|
2481
|
+
* devDependencies: { '@sveltejs/kit': '^2.0.0', 'svelte': '^4.0.0' }
|
|
2482
|
+
* })
|
|
2483
|
+
* // => {
|
|
2484
|
+
* // id: 'sveltekit',
|
|
2485
|
+
* // name: 'SvelteKit',
|
|
2486
|
+
* // category: 'meta-framework',
|
|
2487
|
+
* // version: '2.0.0',
|
|
2488
|
+
* // confidence: 70,
|
|
2489
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.@sveltejs/kit' }]
|
|
2490
|
+
* // }
|
|
2491
|
+
* ```
|
|
2805
2492
|
*/
|
|
2806
2493
|
function sveltekitDetector(projectPath, packageJson) {
|
|
2807
2494
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2836,121 +2523,76 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
2836
2523
|
}
|
|
2837
2524
|
|
|
2838
2525
|
/**
|
|
2839
|
-
* Detect
|
|
2526
|
+
* Detect Vue in project.
|
|
2840
2527
|
*
|
|
2841
2528
|
* @param projectPath - Project directory path
|
|
2842
2529
|
* @param packageJson - Optional pre-loaded package.json
|
|
2843
2530
|
* @returns Detection result or null if not detected
|
|
2844
|
-
*/
|
|
2845
|
-
function solidDetector(projectPath, packageJson) {
|
|
2846
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2847
|
-
const sources = [];
|
|
2848
|
-
let confidence = 0;
|
|
2849
|
-
let version;
|
|
2850
|
-
const deps = collectAllDependencies(pkg);
|
|
2851
|
-
if (deps['solid-js']) {
|
|
2852
|
-
confidence += 70;
|
|
2853
|
-
version = parseVersionString(deps['solid-js']);
|
|
2854
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
2855
|
-
}
|
|
2856
|
-
if (deps['vite-plugin-solid']) {
|
|
2857
|
-
confidence += 20;
|
|
2858
|
-
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
2859
|
-
}
|
|
2860
|
-
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
2861
|
-
confidence += 10;
|
|
2862
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
2863
|
-
}
|
|
2864
|
-
if (confidence === 0) {
|
|
2865
|
-
return null;
|
|
2866
|
-
}
|
|
2867
|
-
return {
|
|
2868
|
-
id: 'solid',
|
|
2869
|
-
name: 'Solid',
|
|
2870
|
-
category: 'frontend',
|
|
2871
|
-
version,
|
|
2872
|
-
confidence: min(confidence, 100),
|
|
2873
|
-
detectedFrom: sources,
|
|
2874
|
-
};
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
|
-
/**
|
|
2878
|
-
* Detect Qwik in project.
|
|
2879
2531
|
*
|
|
2880
|
-
* @
|
|
2881
|
-
*
|
|
2882
|
-
*
|
|
2532
|
+
* @example Detecting Vue.js framework
|
|
2533
|
+
* ```typescript
|
|
2534
|
+
* const result = vueDetector('/path/to/vue-app', {
|
|
2535
|
+
* dependencies: { 'vue': '^3.0.0', '@vue/cli-service': '^5.0.0' }
|
|
2536
|
+
* })
|
|
2537
|
+
* // => {
|
|
2538
|
+
* // id: 'vue',
|
|
2539
|
+
* // name: 'Vue',
|
|
2540
|
+
* // category: 'frontend',
|
|
2541
|
+
* // version: '3.0.0',
|
|
2542
|
+
* // confidence: 85,
|
|
2543
|
+
* // detectedFrom: [
|
|
2544
|
+
* // { type: 'package.json', field: 'dependencies.vue' },
|
|
2545
|
+
* // { type: 'package.json', field: 'dependencies.@vue/cli-service' }
|
|
2546
|
+
* // ]
|
|
2547
|
+
* // }
|
|
2548
|
+
* ```
|
|
2883
2549
|
*/
|
|
2884
|
-
function
|
|
2550
|
+
function vueDetector(projectPath, packageJson) {
|
|
2885
2551
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2886
2552
|
const sources = [];
|
|
2887
2553
|
let confidence = 0;
|
|
2888
2554
|
let version;
|
|
2555
|
+
const metaFrameworks = [];
|
|
2889
2556
|
const deps = collectAllDependencies(pkg);
|
|
2890
|
-
if (deps['
|
|
2557
|
+
if (deps['vue']) {
|
|
2891
2558
|
confidence += 70;
|
|
2892
|
-
version = parseVersionString(deps['
|
|
2893
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
2559
|
+
version = parseVersionString(deps['vue']);
|
|
2560
|
+
sources.push({ type: 'package.json', field: 'dependencies.vue' });
|
|
2894
2561
|
}
|
|
2895
|
-
if (deps['@
|
|
2896
|
-
confidence +=
|
|
2897
|
-
sources.push({ type: 'package.json', field: 'dependencies.@
|
|
2562
|
+
if (deps['@vue/cli-service']) {
|
|
2563
|
+
confidence += 15;
|
|
2564
|
+
sources.push({ type: 'package.json', field: 'dependencies.@vue/cli-service' });
|
|
2898
2565
|
}
|
|
2899
|
-
|
|
2566
|
+
const hasVueFiles = exists(join$1(projectPath, 'src', 'App.vue')) || exists(join$1(projectPath, 'src', 'main.vue'));
|
|
2567
|
+
if (hasVueFiles) {
|
|
2900
2568
|
confidence += 10;
|
|
2901
|
-
sources.push({ type: '
|
|
2902
|
-
}
|
|
2903
|
-
if (confidence === 0) {
|
|
2904
|
-
return null;
|
|
2905
|
-
}
|
|
2906
|
-
return {
|
|
2907
|
-
id: 'qwik',
|
|
2908
|
-
name: 'Qwik',
|
|
2909
|
-
category: 'frontend',
|
|
2910
|
-
version,
|
|
2911
|
-
confidence: min(confidence, 100),
|
|
2912
|
-
detectedFrom: sources,
|
|
2913
|
-
};
|
|
2914
|
-
}
|
|
2915
|
-
|
|
2916
|
-
/**
|
|
2917
|
-
* Detect Astro in project.
|
|
2918
|
-
*
|
|
2919
|
-
* @param projectPath - Project directory path
|
|
2920
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2921
|
-
* @returns Detection result or null if not detected
|
|
2922
|
-
*/
|
|
2923
|
-
function astroDetector(projectPath, packageJson) {
|
|
2924
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2925
|
-
const sources = [];
|
|
2926
|
-
let confidence = 0;
|
|
2927
|
-
let version;
|
|
2928
|
-
const deps = collectAllDependencies(pkg);
|
|
2929
|
-
if (deps['astro']) {
|
|
2930
|
-
confidence += 70;
|
|
2931
|
-
version = parseVersionString(deps['astro']);
|
|
2932
|
-
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
2933
|
-
}
|
|
2934
|
-
if (exists(join$1(projectPath, 'astro.config.mjs')) ||
|
|
2935
|
-
exists(join$1(projectPath, 'astro.config.ts')) ||
|
|
2936
|
-
exists(join$1(projectPath, 'astro.config.js'))) {
|
|
2937
|
-
confidence += 25;
|
|
2938
|
-
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
2569
|
+
sources.push({ type: 'directory', path: 'src/*.vue' });
|
|
2939
2570
|
}
|
|
2940
|
-
if (exists(join$1(projectPath, '
|
|
2571
|
+
if (exists(join$1(projectPath, 'vue.config.js'))) {
|
|
2941
2572
|
confidence += 5;
|
|
2942
|
-
sources.push({ type: '
|
|
2573
|
+
sources.push({ type: 'config-file', path: 'vue.config.js' });
|
|
2574
|
+
}
|
|
2575
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
2576
|
+
metaFrameworks.push({
|
|
2577
|
+
id: 'nuxt',
|
|
2578
|
+
name: 'Nuxt',
|
|
2579
|
+
category: 'meta-framework',
|
|
2580
|
+
version: parseVersionString(deps['nuxt'] ?? deps['nuxt3']),
|
|
2581
|
+
confidence: 90,
|
|
2582
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }],
|
|
2583
|
+
});
|
|
2943
2584
|
}
|
|
2944
2585
|
if (confidence === 0) {
|
|
2945
2586
|
return null;
|
|
2946
2587
|
}
|
|
2947
2588
|
return {
|
|
2948
|
-
id: '
|
|
2949
|
-
name: '
|
|
2950
|
-
category: '
|
|
2589
|
+
id: 'vue',
|
|
2590
|
+
name: 'Vue',
|
|
2591
|
+
category: 'frontend',
|
|
2951
2592
|
version,
|
|
2952
2593
|
confidence: min(confidence, 100),
|
|
2953
2594
|
detectedFrom: sources,
|
|
2595
|
+
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
2954
2596
|
};
|
|
2955
2597
|
}
|
|
2956
2598
|
|
|
@@ -2977,6 +2619,14 @@ const frameworkDetectors = [
|
|
|
2977
2619
|
* @param projectPath - Project directory path
|
|
2978
2620
|
* @param packageJson - Optional pre-loaded package.json
|
|
2979
2621
|
* @returns Detection result or null if not detected
|
|
2622
|
+
*
|
|
2623
|
+
* @example Detecting AngularJS framework
|
|
2624
|
+
* ```typescript
|
|
2625
|
+
* const result = angularJSDetector('/path/to/project', {
|
|
2626
|
+
* dependencies: { angular: '^1.8.0', 'angular-route': '^1.8.0' },
|
|
2627
|
+
* })
|
|
2628
|
+
* // => { id: 'angularjs', name: 'AngularJS', confidence: 85, version: '1.8.0', ... }
|
|
2629
|
+
* ```
|
|
2980
2630
|
*/
|
|
2981
2631
|
function angularJSDetector(projectPath, packageJson) {
|
|
2982
2632
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3020,6 +2670,14 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
3020
2670
|
* @param projectPath - Project directory path
|
|
3021
2671
|
* @param packageJson - Optional pre-loaded package.json
|
|
3022
2672
|
* @returns Detection result or null if not detected
|
|
2673
|
+
*
|
|
2674
|
+
* @example Detecting Backbone.js framework
|
|
2675
|
+
* ```typescript
|
|
2676
|
+
* const result = backboneDetector('/path/to/project', {
|
|
2677
|
+
* dependencies: { backbone: '^1.4.0', underscore: '^1.13.0' },
|
|
2678
|
+
* })
|
|
2679
|
+
* // => { id: 'backbone', name: 'Backbone.js', confidence: 85, version: '1.4.0', ... }
|
|
2680
|
+
* ```
|
|
3023
2681
|
*/
|
|
3024
2682
|
function backboneDetector(projectPath, packageJson) {
|
|
3025
2683
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3063,6 +2721,15 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
3063
2721
|
* @param projectPath - Project directory path
|
|
3064
2722
|
* @param packageJson - Optional pre-loaded package.json
|
|
3065
2723
|
* @returns Detection result or null if not detected
|
|
2724
|
+
*
|
|
2725
|
+
* @example Detecting Ember.js framework
|
|
2726
|
+
* ```typescript
|
|
2727
|
+
* const result = emberDetector('/path/to/project', {
|
|
2728
|
+
* dependencies: { 'ember-source': '^4.0.0' },
|
|
2729
|
+
* devDependencies: { 'ember-cli': '^4.0.0' },
|
|
2730
|
+
* })
|
|
2731
|
+
* // => { id: 'ember', name: 'Ember.js', confidence: 90, version: '4.0.0', ... }
|
|
2732
|
+
* ```
|
|
3066
2733
|
*/
|
|
3067
2734
|
function emberDetector(projectPath, packageJson) {
|
|
3068
2735
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3102,6 +2769,14 @@ function emberDetector(projectPath, packageJson) {
|
|
|
3102
2769
|
* @param projectPath - Project directory path
|
|
3103
2770
|
* @param packageJson - Optional pre-loaded package.json
|
|
3104
2771
|
* @returns Detection result or null if not detected
|
|
2772
|
+
*
|
|
2773
|
+
* @example Detecting jQuery library
|
|
2774
|
+
* ```typescript
|
|
2775
|
+
* const result = jqueryDetector('/path/to/project', {
|
|
2776
|
+
* dependencies: { jquery: '^3.6.0', 'jquery-ui': '^1.13.0' },
|
|
2777
|
+
* })
|
|
2778
|
+
* // => { id: 'jquery', name: 'jQuery', confidence: 90, version: '3.6.0', ... }
|
|
2779
|
+
* ```
|
|
3105
2780
|
*/
|
|
3106
2781
|
function jqueryDetector(projectPath, packageJson) {
|
|
3107
2782
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3143,6 +2818,56 @@ const legacyDetectors = [
|
|
|
3143
2818
|
{ id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
|
|
3144
2819
|
];
|
|
3145
2820
|
|
|
2821
|
+
/**
|
|
2822
|
+
* Detect Biome in project.
|
|
2823
|
+
*
|
|
2824
|
+
* @param projectPath - Project directory path
|
|
2825
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
2826
|
+
* @returns Detection result or null if not detected
|
|
2827
|
+
*
|
|
2828
|
+
* @example Detecting Biome linter
|
|
2829
|
+
* ```typescript
|
|
2830
|
+
* const result = biomeDetector('/path/to/project', {
|
|
2831
|
+
* devDependencies: { '@biomejs/biome': '^1.5.0' },
|
|
2832
|
+
* })
|
|
2833
|
+
* // => { id: 'biome', name: 'Biome', confidence: 70, version: '1.5.0', ... }
|
|
2834
|
+
* ```
|
|
2835
|
+
*/
|
|
2836
|
+
function biomeDetector(projectPath, packageJson) {
|
|
2837
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2838
|
+
const sources = [];
|
|
2839
|
+
let confidence = 0;
|
|
2840
|
+
let configPath;
|
|
2841
|
+
let version;
|
|
2842
|
+
const deps = collectAllDependencies(pkg);
|
|
2843
|
+
if (deps['@biomejs/biome']) {
|
|
2844
|
+
confidence += 70;
|
|
2845
|
+
version = parseVersionString(deps['@biomejs/biome']);
|
|
2846
|
+
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2847
|
+
}
|
|
2848
|
+
if (exists(join$1(projectPath, 'biome.json'))) {
|
|
2849
|
+
confidence += 30;
|
|
2850
|
+
configPath = 'biome.json';
|
|
2851
|
+
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2852
|
+
}
|
|
2853
|
+
if (!configPath && exists(join$1(projectPath, 'biome.jsonc'))) {
|
|
2854
|
+
confidence += 30;
|
|
2855
|
+
configPath = 'biome.jsonc';
|
|
2856
|
+
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
2857
|
+
}
|
|
2858
|
+
if (confidence === 0) {
|
|
2859
|
+
return null;
|
|
2860
|
+
}
|
|
2861
|
+
return {
|
|
2862
|
+
id: 'biome',
|
|
2863
|
+
name: 'Biome',
|
|
2864
|
+
version,
|
|
2865
|
+
configPath,
|
|
2866
|
+
confidence: min(confidence, 100),
|
|
2867
|
+
detectedFrom: sources,
|
|
2868
|
+
};
|
|
2869
|
+
}
|
|
2870
|
+
|
|
3146
2871
|
/** Config patterns for ESLint */
|
|
3147
2872
|
const ESLINT_CONFIG_PATTERNS = [
|
|
3148
2873
|
'eslint.config.js',
|
|
@@ -3162,6 +2887,15 @@ const ESLINT_CONFIG_PATTERNS = [
|
|
|
3162
2887
|
* @param projectPath - Project directory path
|
|
3163
2888
|
* @param packageJson - Optional pre-loaded package.json
|
|
3164
2889
|
* @returns Detection result or null if not detected
|
|
2890
|
+
*
|
|
2891
|
+
* @example Detecting ESLint linter
|
|
2892
|
+
* ```typescript
|
|
2893
|
+
* const result = eslintDetector('/path/to/project', {
|
|
2894
|
+
* devDependencies: { eslint: '^8.50.0', '@typescript-eslint/parser': '^6.0.0' },
|
|
2895
|
+
* scripts: { lint: 'eslint src/' },
|
|
2896
|
+
* })
|
|
2897
|
+
* // => { id: 'eslint', name: 'ESLint', confidence: 65, version: '8.50.0', ... }
|
|
2898
|
+
* ```
|
|
3165
2899
|
*/
|
|
3166
2900
|
function eslintDetector(projectPath, packageJson) {
|
|
3167
2901
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3225,6 +2959,15 @@ const PRETTIER_CONFIG_PATTERNS = [
|
|
|
3225
2959
|
* @param projectPath - Project directory path
|
|
3226
2960
|
* @param packageJson - Optional pre-loaded package.json
|
|
3227
2961
|
* @returns Detection result or null if not detected
|
|
2962
|
+
*
|
|
2963
|
+
* @example Detecting Prettier formatter
|
|
2964
|
+
* ```typescript
|
|
2965
|
+
* const result = prettierDetector('/path/to/project', {
|
|
2966
|
+
* devDependencies: { prettier: '^3.0.0' },
|
|
2967
|
+
* scripts: { format: 'prettier --write .' },
|
|
2968
|
+
* })
|
|
2969
|
+
* // => { id: 'prettier', name: 'Prettier', confidence: 55, version: '3.0.0', ... }
|
|
2970
|
+
* ```
|
|
3228
2971
|
*/
|
|
3229
2972
|
function prettierDetector(projectPath, packageJson) {
|
|
3230
2973
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3287,6 +3030,14 @@ const STYLELINT_CONFIG_PATTERNS = [
|
|
|
3287
3030
|
* @param projectPath - Project directory path
|
|
3288
3031
|
* @param packageJson - Optional pre-loaded package.json
|
|
3289
3032
|
* @returns Detection result or null if not detected
|
|
3033
|
+
*
|
|
3034
|
+
* @example Detecting Stylelint linter
|
|
3035
|
+
* ```typescript
|
|
3036
|
+
* const result = stylelintDetector('/path/to/project', {
|
|
3037
|
+
* devDependencies: { stylelint: '^15.0.0', 'stylelint-config-standard': '^30.0.0' },
|
|
3038
|
+
* })
|
|
3039
|
+
* // => { id: 'stylelint', name: 'Stylelint', confidence: 65, version: '15.0.0', ... }
|
|
3040
|
+
* ```
|
|
3290
3041
|
*/
|
|
3291
3042
|
function stylelintDetector(projectPath, packageJson) {
|
|
3292
3043
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3308,59 +3059,17 @@ function stylelintDetector(projectPath, packageJson) {
|
|
|
3308
3059
|
break;
|
|
3309
3060
|
}
|
|
3310
3061
|
}
|
|
3311
|
-
const stylelintPlugins = keys(deps).filter((d) => d.startsWith('stylelint-'));
|
|
3312
|
-
if (stylelintPlugins.length > 0) {
|
|
3313
|
-
confidence += 5;
|
|
3314
|
-
sources.push({ type: 'package.json', field: 'dependencies (stylelint plugins)' });
|
|
3315
|
-
}
|
|
3316
|
-
if (confidence === 0) {
|
|
3317
|
-
return null;
|
|
3318
|
-
}
|
|
3319
|
-
return {
|
|
3320
|
-
id: 'stylelint',
|
|
3321
|
-
name: 'Stylelint',
|
|
3322
|
-
version,
|
|
3323
|
-
configPath,
|
|
3324
|
-
confidence: min(confidence, 100),
|
|
3325
|
-
detectedFrom: sources,
|
|
3326
|
-
};
|
|
3327
|
-
}
|
|
3328
|
-
|
|
3329
|
-
/**
|
|
3330
|
-
* Detect Biome in project.
|
|
3331
|
-
*
|
|
3332
|
-
* @param projectPath - Project directory path
|
|
3333
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
3334
|
-
* @returns Detection result or null if not detected
|
|
3335
|
-
*/
|
|
3336
|
-
function biomeDetector(projectPath, packageJson) {
|
|
3337
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3338
|
-
const sources = [];
|
|
3339
|
-
let confidence = 0;
|
|
3340
|
-
let configPath;
|
|
3341
|
-
let version;
|
|
3342
|
-
const deps = collectAllDependencies(pkg);
|
|
3343
|
-
if (deps['@biomejs/biome']) {
|
|
3344
|
-
confidence += 70;
|
|
3345
|
-
version = parseVersionString(deps['@biomejs/biome']);
|
|
3346
|
-
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
3347
|
-
}
|
|
3348
|
-
if (exists(join$1(projectPath, 'biome.json'))) {
|
|
3349
|
-
confidence += 30;
|
|
3350
|
-
configPath = 'biome.json';
|
|
3351
|
-
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
3352
|
-
}
|
|
3353
|
-
if (!configPath && exists(join$1(projectPath, 'biome.jsonc'))) {
|
|
3354
|
-
confidence += 30;
|
|
3355
|
-
configPath = 'biome.jsonc';
|
|
3356
|
-
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
3062
|
+
const stylelintPlugins = keys(deps).filter((d) => d.startsWith('stylelint-'));
|
|
3063
|
+
if (stylelintPlugins.length > 0) {
|
|
3064
|
+
confidence += 5;
|
|
3065
|
+
sources.push({ type: 'package.json', field: 'dependencies (stylelint plugins)' });
|
|
3357
3066
|
}
|
|
3358
3067
|
if (confidence === 0) {
|
|
3359
3068
|
return null;
|
|
3360
3069
|
}
|
|
3361
3070
|
return {
|
|
3362
|
-
id: '
|
|
3363
|
-
name: '
|
|
3071
|
+
id: 'stylelint',
|
|
3072
|
+
name: 'Stylelint',
|
|
3364
3073
|
version,
|
|
3365
3074
|
configPath,
|
|
3366
3075
|
confidence: min(confidence, 100),
|
|
@@ -3377,140 +3086,179 @@ const lintingDetectors = [
|
|
|
3377
3086
|
];
|
|
3378
3087
|
|
|
3379
3088
|
/**
|
|
3380
|
-
* Detect
|
|
3089
|
+
* Detect Lerna in project.
|
|
3381
3090
|
*
|
|
3382
3091
|
* @param workspacePath - Workspace directory path
|
|
3383
3092
|
* @param packageJson - Optional pre-loaded package.json
|
|
3384
3093
|
* @returns Detection result or null if not detected
|
|
3094
|
+
*
|
|
3095
|
+
* @example Detecting Lerna monorepo
|
|
3096
|
+
* ```typescript
|
|
3097
|
+
* // Project with lerna.json config file
|
|
3098
|
+
* const result = lernaDetector('/path/to/lerna-project')
|
|
3099
|
+
* // => {
|
|
3100
|
+
* // id: 'lerna',
|
|
3101
|
+
* // name: 'Lerna',
|
|
3102
|
+
* // confidence: 80,
|
|
3103
|
+
* // configPath: 'lerna.json',
|
|
3104
|
+
* // detectedFrom: [{ type: 'config-file', path: 'lerna.json' }]
|
|
3105
|
+
* // }
|
|
3106
|
+
* ```
|
|
3385
3107
|
*/
|
|
3386
|
-
function
|
|
3108
|
+
function lernaDetector(workspacePath, packageJson) {
|
|
3387
3109
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
3388
3110
|
const sources = [];
|
|
3389
3111
|
let confidence = 0;
|
|
3390
3112
|
let version;
|
|
3391
|
-
let
|
|
3392
|
-
const
|
|
3393
|
-
if (exists(
|
|
3394
|
-
confidence +=
|
|
3395
|
-
|
|
3113
|
+
let configPath;
|
|
3114
|
+
const lernaJsonPath = join$1(workspacePath, 'lerna.json');
|
|
3115
|
+
if (exists(lernaJsonPath)) {
|
|
3116
|
+
confidence += 80;
|
|
3117
|
+
configPath = 'lerna.json';
|
|
3118
|
+
sources.push({ type: 'config-file', path: 'lerna.json' });
|
|
3396
3119
|
}
|
|
3397
3120
|
const deps = collectAllDependencies(pkg);
|
|
3398
|
-
if (deps['
|
|
3399
|
-
confidence +=
|
|
3400
|
-
version = parseVersionString(deps['
|
|
3401
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
3402
|
-
}
|
|
3403
|
-
const hasApps = exists(join$1(workspacePath, 'apps'));
|
|
3404
|
-
const hasLibs = exists(join$1(workspacePath, 'libs'));
|
|
3405
|
-
if (hasApps || hasLibs) {
|
|
3406
|
-
confidence += 10;
|
|
3407
|
-
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
3408
|
-
workspaceLayout = {
|
|
3409
|
-
appsDir: hasApps ? 'apps' : '',
|
|
3410
|
-
libsDir: hasLibs ? 'libs' : '',
|
|
3411
|
-
};
|
|
3121
|
+
if (deps['lerna']) {
|
|
3122
|
+
confidence += 15;
|
|
3123
|
+
version = parseVersionString(deps['lerna']);
|
|
3124
|
+
sources.push({ type: 'package.json', field: 'dependencies.lerna' });
|
|
3412
3125
|
}
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
sources.push({ type: 'package.json', field: '@nx/* packages' });
|
|
3126
|
+
if (exists(join$1(workspacePath, 'packages'))) {
|
|
3127
|
+
confidence += 5;
|
|
3128
|
+
sources.push({ type: 'directory', path: 'packages/' });
|
|
3417
3129
|
}
|
|
3418
3130
|
if (confidence === 0) {
|
|
3419
3131
|
return null;
|
|
3420
3132
|
}
|
|
3421
3133
|
return {
|
|
3422
|
-
id: '
|
|
3423
|
-
name: '
|
|
3134
|
+
id: 'lerna',
|
|
3135
|
+
name: 'Lerna',
|
|
3424
3136
|
version,
|
|
3425
|
-
configPath
|
|
3137
|
+
configPath,
|
|
3426
3138
|
confidence: min(confidence, 100),
|
|
3427
3139
|
detectedFrom: sources,
|
|
3428
|
-
workspaceLayout,
|
|
3429
3140
|
};
|
|
3430
3141
|
}
|
|
3431
3142
|
|
|
3432
3143
|
/**
|
|
3433
|
-
* Detect
|
|
3144
|
+
* Detect npm workspaces in project.
|
|
3434
3145
|
*
|
|
3435
3146
|
* @param workspacePath - Workspace directory path
|
|
3436
3147
|
* @param packageJson - Optional pre-loaded package.json
|
|
3437
3148
|
* @returns Detection result or null if not detected
|
|
3149
|
+
*
|
|
3150
|
+
* @example Detecting npm workspaces
|
|
3151
|
+
* ```typescript
|
|
3152
|
+
* // Project with workspaces in package.json and package-lock.json
|
|
3153
|
+
* const result = npmWorkspacesDetector('/path/to/npm-project')
|
|
3154
|
+
* // => {
|
|
3155
|
+
* // id: 'npm-workspaces',
|
|
3156
|
+
* // name: 'npm Workspaces',
|
|
3157
|
+
* // confidence: 90,
|
|
3158
|
+
* // configPath: 'package.json',
|
|
3159
|
+
* // detectedFrom: [
|
|
3160
|
+
* // { type: 'package.json', field: 'workspaces' },
|
|
3161
|
+
* // { type: 'lockfile', path: 'package-lock.json' }
|
|
3162
|
+
* // ]
|
|
3163
|
+
* // }
|
|
3164
|
+
* ```
|
|
3438
3165
|
*/
|
|
3439
|
-
function
|
|
3166
|
+
function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
3440
3167
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
3441
3168
|
const sources = [];
|
|
3442
3169
|
let confidence = 0;
|
|
3443
|
-
|
|
3444
|
-
let configPath;
|
|
3445
|
-
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
3446
|
-
if (exists(turboJsonPath)) {
|
|
3170
|
+
if (pkg?.workspaces) {
|
|
3447
3171
|
confidence += 80;
|
|
3448
|
-
|
|
3449
|
-
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
3172
|
+
sources.push({ type: 'package.json', field: 'workspaces' });
|
|
3450
3173
|
}
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
version = parseVersionString(deps['turbo']);
|
|
3455
|
-
sources.push({ type: 'package.json', field: 'dependencies.turbo' });
|
|
3174
|
+
if (exists(join$1(workspacePath, 'package-lock.json'))) {
|
|
3175
|
+
confidence += 10;
|
|
3176
|
+
sources.push({ type: 'lockfile', path: 'package-lock.json' });
|
|
3456
3177
|
}
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
confidence += 5;
|
|
3460
|
-
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
3178
|
+
if (exists(join$1(workspacePath, 'yarn.lock'))) {
|
|
3179
|
+
return null;
|
|
3461
3180
|
}
|
|
3462
3181
|
if (confidence === 0) {
|
|
3463
3182
|
return null;
|
|
3464
3183
|
}
|
|
3465
3184
|
return {
|
|
3466
|
-
id: '
|
|
3467
|
-
name: '
|
|
3468
|
-
|
|
3469
|
-
configPath,
|
|
3185
|
+
id: 'npm-workspaces',
|
|
3186
|
+
name: 'npm Workspaces',
|
|
3187
|
+
configPath: 'package.json',
|
|
3470
3188
|
confidence: min(confidence, 100),
|
|
3471
3189
|
detectedFrom: sources,
|
|
3472
3190
|
};
|
|
3473
3191
|
}
|
|
3474
3192
|
|
|
3475
3193
|
/**
|
|
3476
|
-
* Detect
|
|
3194
|
+
* Detect NX in project.
|
|
3477
3195
|
*
|
|
3478
3196
|
* @param workspacePath - Workspace directory path
|
|
3479
3197
|
* @param packageJson - Optional pre-loaded package.json
|
|
3480
3198
|
* @returns Detection result or null if not detected
|
|
3199
|
+
*
|
|
3200
|
+
* @example Detecting NX workspace
|
|
3201
|
+
* ```typescript
|
|
3202
|
+
* // Project with nx.json and apps/libs directories
|
|
3203
|
+
* const result = nxDetector('/path/to/nx-workspace')
|
|
3204
|
+
* // => {
|
|
3205
|
+
* // id: 'nx',
|
|
3206
|
+
* // name: 'NX',
|
|
3207
|
+
* // confidence: 100,
|
|
3208
|
+
* // configPath: 'nx.json',
|
|
3209
|
+
* // version: '17.0.0',
|
|
3210
|
+
* // workspaceLayout: { appsDir: 'apps', libsDir: 'libs' },
|
|
3211
|
+
* // detectedFrom: [
|
|
3212
|
+
* // { type: 'config-file', path: 'nx.json' },
|
|
3213
|
+
* // { type: 'package.json', field: 'dependencies.nx' },
|
|
3214
|
+
* // { type: 'directory', path: 'apps/ or libs/' }
|
|
3215
|
+
* // ]
|
|
3216
|
+
* // }
|
|
3217
|
+
* ```
|
|
3481
3218
|
*/
|
|
3482
|
-
function
|
|
3219
|
+
function nxDetector(workspacePath, packageJson) {
|
|
3483
3220
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
3484
3221
|
const sources = [];
|
|
3485
3222
|
let confidence = 0;
|
|
3486
3223
|
let version;
|
|
3487
|
-
let
|
|
3488
|
-
const
|
|
3489
|
-
if (exists(
|
|
3490
|
-
confidence +=
|
|
3491
|
-
|
|
3492
|
-
sources.push({ type: 'config-file', path: 'lerna.json' });
|
|
3224
|
+
let workspaceLayout;
|
|
3225
|
+
const nxJsonPath = join$1(workspacePath, 'nx.json');
|
|
3226
|
+
if (exists(nxJsonPath)) {
|
|
3227
|
+
confidence += 70;
|
|
3228
|
+
sources.push({ type: 'config-file', path: 'nx.json' });
|
|
3493
3229
|
}
|
|
3494
3230
|
const deps = collectAllDependencies(pkg);
|
|
3495
|
-
if (deps['
|
|
3496
|
-
confidence +=
|
|
3497
|
-
version = parseVersionString(deps['
|
|
3498
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
3231
|
+
if (deps['nx']) {
|
|
3232
|
+
confidence += 20;
|
|
3233
|
+
version = parseVersionString(deps['nx']);
|
|
3234
|
+
sources.push({ type: 'package.json', field: 'dependencies.nx' });
|
|
3499
3235
|
}
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3236
|
+
const hasApps = exists(join$1(workspacePath, 'apps'));
|
|
3237
|
+
const hasLibs = exists(join$1(workspacePath, 'libs'));
|
|
3238
|
+
if (hasApps || hasLibs) {
|
|
3239
|
+
confidence += 10;
|
|
3240
|
+
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
3241
|
+
workspaceLayout = {
|
|
3242
|
+
appsDir: hasApps ? 'apps' : '',
|
|
3243
|
+
libsDir: hasLibs ? 'libs' : '',
|
|
3244
|
+
};
|
|
3245
|
+
}
|
|
3246
|
+
const nxPackages = keys(deps).filter((d) => d.startsWith('@nx/') || d.startsWith('@nrwl/'));
|
|
3247
|
+
if (nxPackages.length > 0) {
|
|
3248
|
+
confidence += 10;
|
|
3249
|
+
sources.push({ type: 'package.json', field: '@nx/* packages' });
|
|
3503
3250
|
}
|
|
3504
3251
|
if (confidence === 0) {
|
|
3505
3252
|
return null;
|
|
3506
3253
|
}
|
|
3507
3254
|
return {
|
|
3508
|
-
id: '
|
|
3509
|
-
name: '
|
|
3255
|
+
id: 'nx',
|
|
3256
|
+
name: 'NX',
|
|
3510
3257
|
version,
|
|
3511
|
-
configPath,
|
|
3258
|
+
configPath: exists(nxJsonPath) ? 'nx.json' : undefined,
|
|
3512
3259
|
confidence: min(confidence, 100),
|
|
3513
3260
|
detectedFrom: sources,
|
|
3261
|
+
workspaceLayout,
|
|
3514
3262
|
};
|
|
3515
3263
|
}
|
|
3516
3264
|
|
|
@@ -3520,6 +3268,19 @@ function lernaDetector(workspacePath, packageJson) {
|
|
|
3520
3268
|
* @param workspacePath - Workspace directory path
|
|
3521
3269
|
* @param packageJson - Optional pre-loaded package.json
|
|
3522
3270
|
* @returns Detection result or null if not detected
|
|
3271
|
+
*
|
|
3272
|
+
* @example Detecting Rush monorepo
|
|
3273
|
+
* ```typescript
|
|
3274
|
+
* // Project with rush.json config file
|
|
3275
|
+
* const result = rushDetector('/path/to/rush-project')
|
|
3276
|
+
* // => {
|
|
3277
|
+
* // id: 'rush',
|
|
3278
|
+
* // name: 'Rush',
|
|
3279
|
+
* // confidence: 90,
|
|
3280
|
+
* // configPath: 'rush.json',
|
|
3281
|
+
* // detectedFrom: [{ type: 'config-file', path: 'rush.json' }]
|
|
3282
|
+
* // }
|
|
3283
|
+
* ```
|
|
3523
3284
|
*/
|
|
3524
3285
|
function rushDetector(workspacePath, packageJson) {
|
|
3525
3286
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -3557,66 +3318,60 @@ function rushDetector(workspacePath, packageJson) {
|
|
|
3557
3318
|
}
|
|
3558
3319
|
|
|
3559
3320
|
/**
|
|
3560
|
-
* Detect
|
|
3561
|
-
*
|
|
3562
|
-
* @param workspacePath - Workspace directory path
|
|
3563
|
-
* @returns Detection result or null if not detected
|
|
3564
|
-
*/
|
|
3565
|
-
function pnpmWorkspacesDetector(workspacePath) {
|
|
3566
|
-
const sources = [];
|
|
3567
|
-
let confidence = 0;
|
|
3568
|
-
let configPath;
|
|
3569
|
-
const pnpmWorkspacePath = join$1(workspacePath, 'pnpm-workspace.yaml');
|
|
3570
|
-
if (exists(pnpmWorkspacePath)) {
|
|
3571
|
-
confidence += 90;
|
|
3572
|
-
configPath = 'pnpm-workspace.yaml';
|
|
3573
|
-
sources.push({ type: 'config-file', path: 'pnpm-workspace.yaml' });
|
|
3574
|
-
}
|
|
3575
|
-
if (exists(join$1(workspacePath, 'pnpm-lock.yaml'))) {
|
|
3576
|
-
confidence += 10;
|
|
3577
|
-
sources.push({ type: 'lockfile', path: 'pnpm-lock.yaml' });
|
|
3578
|
-
}
|
|
3579
|
-
if (confidence === 0) {
|
|
3580
|
-
return null;
|
|
3581
|
-
}
|
|
3582
|
-
return {
|
|
3583
|
-
id: 'pnpm-workspaces',
|
|
3584
|
-
name: 'pnpm Workspaces',
|
|
3585
|
-
configPath,
|
|
3586
|
-
confidence: min(confidence, 100),
|
|
3587
|
-
detectedFrom: sources,
|
|
3588
|
-
};
|
|
3589
|
-
}
|
|
3590
|
-
|
|
3591
|
-
/**
|
|
3592
|
-
* Detect npm workspaces in project.
|
|
3321
|
+
* Detect Turborepo in project.
|
|
3593
3322
|
*
|
|
3594
3323
|
* @param workspacePath - Workspace directory path
|
|
3595
3324
|
* @param packageJson - Optional pre-loaded package.json
|
|
3596
3325
|
* @returns Detection result or null if not detected
|
|
3326
|
+
*
|
|
3327
|
+
* @example Detecting Turborepo monorepo
|
|
3328
|
+
* ```typescript
|
|
3329
|
+
* // Project with turbo.json and turbo dependency
|
|
3330
|
+
* const result = turborepoDetector('/path/to/turbo-project')
|
|
3331
|
+
* // => {
|
|
3332
|
+
* // id: 'turborepo',
|
|
3333
|
+
* // name: 'Turborepo',
|
|
3334
|
+
* // confidence: 95,
|
|
3335
|
+
* // configPath: 'turbo.json',
|
|
3336
|
+
* // version: '2.0.0',
|
|
3337
|
+
* // detectedFrom: [
|
|
3338
|
+
* // { type: 'config-file', path: 'turbo.json' },
|
|
3339
|
+
* // { type: 'package.json', field: 'dependencies.turbo' }
|
|
3340
|
+
* // ]
|
|
3341
|
+
* // }
|
|
3342
|
+
* ```
|
|
3597
3343
|
*/
|
|
3598
|
-
function
|
|
3344
|
+
function turborepoDetector(workspacePath, packageJson) {
|
|
3599
3345
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
3600
3346
|
const sources = [];
|
|
3601
3347
|
let confidence = 0;
|
|
3602
|
-
|
|
3348
|
+
let version;
|
|
3349
|
+
let configPath;
|
|
3350
|
+
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
3351
|
+
if (exists(turboJsonPath)) {
|
|
3603
3352
|
confidence += 80;
|
|
3604
|
-
|
|
3353
|
+
configPath = 'turbo.json';
|
|
3354
|
+
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
3605
3355
|
}
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3356
|
+
const deps = collectAllDependencies(pkg);
|
|
3357
|
+
if (deps['turbo']) {
|
|
3358
|
+
confidence += 15;
|
|
3359
|
+
version = parseVersionString(deps['turbo']);
|
|
3360
|
+
sources.push({ type: 'package.json', field: 'dependencies.turbo' });
|
|
3609
3361
|
}
|
|
3610
|
-
|
|
3611
|
-
|
|
3362
|
+
const scripts = pkg?.scripts ?? {};
|
|
3363
|
+
if (values(scripts).some((s) => s?.includes('turbo'))) {
|
|
3364
|
+
confidence += 5;
|
|
3365
|
+
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
3612
3366
|
}
|
|
3613
3367
|
if (confidence === 0) {
|
|
3614
3368
|
return null;
|
|
3615
3369
|
}
|
|
3616
3370
|
return {
|
|
3617
|
-
id: '
|
|
3618
|
-
name: '
|
|
3619
|
-
|
|
3371
|
+
id: 'turborepo',
|
|
3372
|
+
name: 'Turborepo',
|
|
3373
|
+
version,
|
|
3374
|
+
configPath,
|
|
3620
3375
|
confidence: min(confidence, 100),
|
|
3621
3376
|
detectedFrom: sources,
|
|
3622
3377
|
};
|
|
@@ -3628,6 +3383,23 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
|
3628
3383
|
* @param workspacePath - Workspace directory path
|
|
3629
3384
|
* @param packageJson - Optional pre-loaded package.json
|
|
3630
3385
|
* @returns Detection result or null if not detected
|
|
3386
|
+
*
|
|
3387
|
+
* @example Detecting yarn workspaces
|
|
3388
|
+
* ```typescript
|
|
3389
|
+
* // Project with workspaces in package.json and yarn.lock
|
|
3390
|
+
* const result = yarnWorkspacesDetector('/path/to/yarn-project')
|
|
3391
|
+
* // => {
|
|
3392
|
+
* // id: 'yarn-workspaces',
|
|
3393
|
+
* // name: 'Yarn Workspaces',
|
|
3394
|
+
* // confidence: 100,
|
|
3395
|
+
* // configPath: 'package.json',
|
|
3396
|
+
* // detectedFrom: [
|
|
3397
|
+
* // { type: 'package.json', field: 'workspaces' },
|
|
3398
|
+
* // { type: 'lockfile', path: 'yarn.lock' },
|
|
3399
|
+
* // { type: 'config-file', path: '.yarnrc.yml' }
|
|
3400
|
+
* // ]
|
|
3401
|
+
* // }
|
|
3402
|
+
* ```
|
|
3631
3403
|
*/
|
|
3632
3404
|
function yarnWorkspacesDetector(workspacePath, packageJson) {
|
|
3633
3405
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -3668,107 +3440,125 @@ const monorepoDetectors = [
|
|
|
3668
3440
|
{ id: 'yarn-workspaces', name: 'Yarn Workspaces', detect: yarnWorkspacesDetector },
|
|
3669
3441
|
];
|
|
3670
3442
|
|
|
3671
|
-
/** Config patterns for
|
|
3672
|
-
const
|
|
3443
|
+
/** Config patterns for Cypress */
|
|
3444
|
+
const CYPRESS_CONFIG_PATTERNS = ['cypress.config.js', 'cypress.config.ts', 'cypress.config.mjs', 'cypress.json'];
|
|
3673
3445
|
/**
|
|
3674
|
-
* Detect
|
|
3446
|
+
* Detect Cypress in project.
|
|
3675
3447
|
*
|
|
3676
3448
|
* @param projectPath - Project directory path
|
|
3677
3449
|
* @param packageJson - Optional pre-loaded package.json
|
|
3678
3450
|
* @returns Detection result or null if not detected
|
|
3451
|
+
*
|
|
3452
|
+
* @example Detecting Cypress testing framework
|
|
3453
|
+
* ```typescript
|
|
3454
|
+
* import { cypressDetector } from '@hyperfrontend/project-scope'
|
|
3455
|
+
*
|
|
3456
|
+
* const result = cypressDetector('./my-project')
|
|
3457
|
+
* if (result) {
|
|
3458
|
+
* console.log(`Cypress ${result.version} detected (${result.confidence}% confidence)`)
|
|
3459
|
+
* // => "Cypress 13.6.0 detected (95% confidence)"
|
|
3460
|
+
* }
|
|
3461
|
+
* ```
|
|
3679
3462
|
*/
|
|
3680
|
-
function
|
|
3463
|
+
function cypressDetector(projectPath, packageJson) {
|
|
3681
3464
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3682
3465
|
const sources = [];
|
|
3683
3466
|
let confidence = 0;
|
|
3684
3467
|
let version;
|
|
3685
3468
|
const deps = collectAllDependencies(pkg);
|
|
3686
|
-
if (deps['
|
|
3469
|
+
if (deps['cypress']) {
|
|
3687
3470
|
confidence += 60;
|
|
3688
|
-
version = parseVersionString(deps['
|
|
3689
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
3471
|
+
version = parseVersionString(deps['cypress']);
|
|
3472
|
+
sources.push({ type: 'package.json', field: 'dependencies.cypress' });
|
|
3690
3473
|
}
|
|
3691
|
-
const configPath = locateConfigFile(projectPath,
|
|
3474
|
+
const configPath = locateConfigFile(projectPath, CYPRESS_CONFIG_PATTERNS);
|
|
3692
3475
|
if (configPath) {
|
|
3693
3476
|
confidence += 30;
|
|
3694
3477
|
sources.push({ type: 'config-file', path: configPath });
|
|
3695
3478
|
}
|
|
3696
|
-
if (
|
|
3697
|
-
confidence += 20;
|
|
3698
|
-
sources.push({ type: 'package.json', field: 'jest' });
|
|
3699
|
-
}
|
|
3700
|
-
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
3701
|
-
if (testScript.includes('jest')) {
|
|
3479
|
+
if (exists(join$1(projectPath, 'cypress'))) {
|
|
3702
3480
|
confidence += 10;
|
|
3703
|
-
sources.push({ type: '
|
|
3704
|
-
}
|
|
3705
|
-
if (deps['@types/jest']) {
|
|
3706
|
-
confidence += 5;
|
|
3707
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
3481
|
+
sources.push({ type: 'directory', path: 'cypress/' });
|
|
3708
3482
|
}
|
|
3709
|
-
|
|
3483
|
+
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
3484
|
+
if (e2eScript.includes('cypress')) {
|
|
3710
3485
|
confidence += 5;
|
|
3711
|
-
sources.push({ type: 'package.json', field: '
|
|
3486
|
+
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
3712
3487
|
}
|
|
3713
3488
|
if (confidence === 0) {
|
|
3714
3489
|
return null;
|
|
3715
3490
|
}
|
|
3716
3491
|
return {
|
|
3717
|
-
id: '
|
|
3718
|
-
name: '
|
|
3719
|
-
type: '
|
|
3492
|
+
id: 'cypress',
|
|
3493
|
+
name: 'Cypress',
|
|
3494
|
+
type: 'e2e',
|
|
3720
3495
|
version,
|
|
3721
3496
|
configPath,
|
|
3722
3497
|
confidence: min(confidence, 100),
|
|
3723
3498
|
detectedFrom: sources,
|
|
3724
3499
|
};
|
|
3725
3500
|
}
|
|
3726
|
-
|
|
3727
|
-
/** Config patterns for
|
|
3728
|
-
const
|
|
3501
|
+
|
|
3502
|
+
/** Config patterns for Jest */
|
|
3503
|
+
const JEST_CONFIG_PATTERNS = ['jest.config.js', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json'];
|
|
3729
3504
|
/**
|
|
3730
|
-
* Detect
|
|
3505
|
+
* Detect Jest in project.
|
|
3731
3506
|
*
|
|
3732
3507
|
* @param projectPath - Project directory path
|
|
3733
3508
|
* @param packageJson - Optional pre-loaded package.json
|
|
3734
3509
|
* @returns Detection result or null if not detected
|
|
3510
|
+
*
|
|
3511
|
+
* @example Detecting Jest testing framework
|
|
3512
|
+
* ```typescript
|
|
3513
|
+
* import { jestDetector } from '@hyperfrontend/project-scope'
|
|
3514
|
+
*
|
|
3515
|
+
* const result = jestDetector('./my-project')
|
|
3516
|
+
* if (result) {
|
|
3517
|
+
* console.log(`Jest ${result.version} detected`)
|
|
3518
|
+
* console.log('Sources:', result.detectedFrom.map(s => s.type))
|
|
3519
|
+
* // => "Sources: ['package.json', 'config-file']"
|
|
3520
|
+
* }
|
|
3521
|
+
* ```
|
|
3735
3522
|
*/
|
|
3736
|
-
function
|
|
3523
|
+
function jestDetector(projectPath, packageJson) {
|
|
3737
3524
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3738
3525
|
const sources = [];
|
|
3739
3526
|
let confidence = 0;
|
|
3740
3527
|
let version;
|
|
3741
3528
|
const deps = collectAllDependencies(pkg);
|
|
3742
|
-
if (deps['
|
|
3743
|
-
confidence +=
|
|
3744
|
-
version = parseVersionString(deps['
|
|
3745
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
3529
|
+
if (deps['jest']) {
|
|
3530
|
+
confidence += 60;
|
|
3531
|
+
version = parseVersionString(deps['jest']);
|
|
3532
|
+
sources.push({ type: 'package.json', field: 'dependencies.jest' });
|
|
3746
3533
|
}
|
|
3747
|
-
const configPath = locateConfigFile(projectPath,
|
|
3534
|
+
const configPath = locateConfigFile(projectPath, JEST_CONFIG_PATTERNS);
|
|
3748
3535
|
if (configPath) {
|
|
3749
|
-
confidence +=
|
|
3536
|
+
confidence += 30;
|
|
3750
3537
|
sources.push({ type: 'config-file', path: configPath });
|
|
3751
3538
|
}
|
|
3752
|
-
if (
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
exists(join$1(projectPath, 'vite.config.mjs'));
|
|
3756
|
-
if (viteConfig && deps['vitest']) {
|
|
3757
|
-
confidence += 5;
|
|
3758
|
-
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
3759
|
-
}
|
|
3539
|
+
if (pkg && 'jest' in pkg) {
|
|
3540
|
+
confidence += 20;
|
|
3541
|
+
sources.push({ type: 'package.json', field: 'jest' });
|
|
3760
3542
|
}
|
|
3761
3543
|
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
3762
|
-
if (testScript.includes('
|
|
3544
|
+
if (testScript.includes('jest')) {
|
|
3763
3545
|
confidence += 10;
|
|
3764
3546
|
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
3765
3547
|
}
|
|
3548
|
+
if (deps['@types/jest']) {
|
|
3549
|
+
confidence += 5;
|
|
3550
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
3551
|
+
}
|
|
3552
|
+
if (deps['ts-jest']) {
|
|
3553
|
+
confidence += 5;
|
|
3554
|
+
sources.push({ type: 'package.json', field: 'dependencies.ts-jest' });
|
|
3555
|
+
}
|
|
3766
3556
|
if (confidence === 0) {
|
|
3767
3557
|
return null;
|
|
3768
3558
|
}
|
|
3769
3559
|
return {
|
|
3770
|
-
id: '
|
|
3771
|
-
name: '
|
|
3560
|
+
id: 'jest',
|
|
3561
|
+
name: 'Jest',
|
|
3772
3562
|
type: 'unit',
|
|
3773
3563
|
version,
|
|
3774
3564
|
configPath,
|
|
@@ -3785,6 +3575,17 @@ const MOCHA_CONFIG_PATTERNS = ['.mocharc.js', '.mocharc.json', '.mocharc.yaml',
|
|
|
3785
3575
|
* @param projectPath - Project directory path
|
|
3786
3576
|
* @param packageJson - Optional pre-loaded package.json
|
|
3787
3577
|
* @returns Detection result or null if not detected
|
|
3578
|
+
*
|
|
3579
|
+
* @example Detecting Mocha testing framework
|
|
3580
|
+
* ```typescript
|
|
3581
|
+
* import { mochaDetector } from '@hyperfrontend/project-scope'
|
|
3582
|
+
*
|
|
3583
|
+
* const result = mochaDetector('./my-project')
|
|
3584
|
+
* if (result) {
|
|
3585
|
+
* console.log(`Mocha ${result.version} detected (${result.confidence}%)`)
|
|
3586
|
+
* // => "Mocha 10.2.0 detected (95%)"
|
|
3587
|
+
* }
|
|
3588
|
+
* ```
|
|
3788
3589
|
*/
|
|
3789
3590
|
function mochaDetector(projectPath, packageJson) {
|
|
3790
3591
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3829,37 +3630,53 @@ function mochaDetector(projectPath, packageJson) {
|
|
|
3829
3630
|
};
|
|
3830
3631
|
}
|
|
3831
3632
|
|
|
3832
|
-
/** Config patterns for
|
|
3833
|
-
const
|
|
3633
|
+
/** Config patterns for Playwright */
|
|
3634
|
+
const PLAYWRIGHT_CONFIG_PATTERNS = ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs'];
|
|
3834
3635
|
/**
|
|
3835
|
-
* Detect
|
|
3636
|
+
* Detect Playwright in project.
|
|
3836
3637
|
*
|
|
3837
3638
|
* @param projectPath - Project directory path
|
|
3838
3639
|
* @param packageJson - Optional pre-loaded package.json
|
|
3839
3640
|
* @returns Detection result or null if not detected
|
|
3641
|
+
*
|
|
3642
|
+
* @example Detecting Playwright testing framework
|
|
3643
|
+
* ```typescript
|
|
3644
|
+
* import { playwrightDetector } from '@hyperfrontend/project-scope'
|
|
3645
|
+
*
|
|
3646
|
+
* const result = playwrightDetector('./my-project')
|
|
3647
|
+
* if (result) {
|
|
3648
|
+
* console.log(`Playwright ${result.version} (${result.type} tests)`)
|
|
3649
|
+
* // => "Playwright 1.42.0 (e2e tests)"
|
|
3650
|
+
* }
|
|
3651
|
+
* ```
|
|
3840
3652
|
*/
|
|
3841
|
-
function
|
|
3653
|
+
function playwrightDetector(projectPath, packageJson) {
|
|
3842
3654
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3843
3655
|
const sources = [];
|
|
3844
3656
|
let confidence = 0;
|
|
3845
3657
|
let version;
|
|
3846
3658
|
const deps = collectAllDependencies(pkg);
|
|
3847
|
-
if (deps['
|
|
3848
|
-
confidence +=
|
|
3849
|
-
version = parseVersionString(deps['
|
|
3850
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
3659
|
+
if (deps['@playwright/test']) {
|
|
3660
|
+
confidence += 70;
|
|
3661
|
+
version = parseVersionString(deps['@playwright/test']);
|
|
3662
|
+
sources.push({ type: 'package.json', field: 'dependencies.@playwright/test' });
|
|
3851
3663
|
}
|
|
3852
|
-
|
|
3664
|
+
if (deps['playwright']) {
|
|
3665
|
+
confidence += 50;
|
|
3666
|
+
version = version ?? parseVersionString(deps['playwright']);
|
|
3667
|
+
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
3668
|
+
}
|
|
3669
|
+
const configPath = locateConfigFile(projectPath, PLAYWRIGHT_CONFIG_PATTERNS);
|
|
3853
3670
|
if (configPath) {
|
|
3854
|
-
confidence +=
|
|
3671
|
+
confidence += 25;
|
|
3855
3672
|
sources.push({ type: 'config-file', path: configPath });
|
|
3856
3673
|
}
|
|
3857
|
-
if (exists(join$1(projectPath, '
|
|
3858
|
-
confidence +=
|
|
3859
|
-
sources.push({ type: 'directory', path: '
|
|
3674
|
+
if (exists(join$1(projectPath, 'e2e')) || exists(join$1(projectPath, 'tests'))) {
|
|
3675
|
+
confidence += 5;
|
|
3676
|
+
sources.push({ type: 'directory', path: 'e2e/ or tests/' });
|
|
3860
3677
|
}
|
|
3861
3678
|
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
3862
|
-
if (e2eScript.includes('
|
|
3679
|
+
if (e2eScript.includes('playwright')) {
|
|
3863
3680
|
confidence += 5;
|
|
3864
3681
|
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
3865
3682
|
}
|
|
@@ -3867,8 +3684,8 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3867
3684
|
return null;
|
|
3868
3685
|
}
|
|
3869
3686
|
return {
|
|
3870
|
-
id: '
|
|
3871
|
-
name: '
|
|
3687
|
+
id: 'playwright',
|
|
3688
|
+
name: 'Playwright',
|
|
3872
3689
|
type: 'e2e',
|
|
3873
3690
|
version,
|
|
3874
3691
|
configPath,
|
|
@@ -3877,52 +3694,64 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3877
3694
|
};
|
|
3878
3695
|
}
|
|
3879
3696
|
|
|
3880
|
-
/** Config patterns for
|
|
3881
|
-
const
|
|
3697
|
+
/** Config patterns for Vitest */
|
|
3698
|
+
const VITEST_CONFIG_PATTERNS = ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'];
|
|
3882
3699
|
/**
|
|
3883
|
-
* Detect
|
|
3700
|
+
* Detect Vitest in project.
|
|
3884
3701
|
*
|
|
3885
3702
|
* @param projectPath - Project directory path
|
|
3886
3703
|
* @param packageJson - Optional pre-loaded package.json
|
|
3887
3704
|
* @returns Detection result or null if not detected
|
|
3705
|
+
*
|
|
3706
|
+
* @example Detecting Vitest testing framework
|
|
3707
|
+
* ```typescript
|
|
3708
|
+
* import { vitestDetector } from '@hyperfrontend/project-scope'
|
|
3709
|
+
*
|
|
3710
|
+
* const result = vitestDetector('./my-project')
|
|
3711
|
+
* if (result) {
|
|
3712
|
+
* console.log(`Vitest ${result.version} detected`)
|
|
3713
|
+
* console.log('Config:', result.configPath)
|
|
3714
|
+
* // => "Config: vitest.config.ts"
|
|
3715
|
+
* }
|
|
3716
|
+
* ```
|
|
3888
3717
|
*/
|
|
3889
|
-
function
|
|
3718
|
+
function vitestDetector(projectPath, packageJson) {
|
|
3890
3719
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3891
3720
|
const sources = [];
|
|
3892
3721
|
let confidence = 0;
|
|
3893
3722
|
let version;
|
|
3894
3723
|
const deps = collectAllDependencies(pkg);
|
|
3895
|
-
if (deps['
|
|
3724
|
+
if (deps['vitest']) {
|
|
3896
3725
|
confidence += 70;
|
|
3897
|
-
version = parseVersionString(deps['
|
|
3898
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
3899
|
-
}
|
|
3900
|
-
if (deps['playwright']) {
|
|
3901
|
-
confidence += 50;
|
|
3902
|
-
version = version ?? parseVersionString(deps['playwright']);
|
|
3903
|
-
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
3726
|
+
version = parseVersionString(deps['vitest']);
|
|
3727
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
3904
3728
|
}
|
|
3905
|
-
const configPath = locateConfigFile(projectPath,
|
|
3729
|
+
const configPath = locateConfigFile(projectPath, VITEST_CONFIG_PATTERNS);
|
|
3906
3730
|
if (configPath) {
|
|
3907
3731
|
confidence += 25;
|
|
3908
3732
|
sources.push({ type: 'config-file', path: configPath });
|
|
3909
3733
|
}
|
|
3910
|
-
if (
|
|
3911
|
-
|
|
3912
|
-
|
|
3734
|
+
if (!configPath) {
|
|
3735
|
+
const viteConfig = exists(join$1(projectPath, 'vite.config.ts')) ||
|
|
3736
|
+
exists(join$1(projectPath, 'vite.config.js')) ||
|
|
3737
|
+
exists(join$1(projectPath, 'vite.config.mjs'));
|
|
3738
|
+
if (viteConfig && deps['vitest']) {
|
|
3739
|
+
confidence += 5;
|
|
3740
|
+
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
3741
|
+
}
|
|
3913
3742
|
}
|
|
3914
|
-
const
|
|
3915
|
-
if (
|
|
3916
|
-
confidence +=
|
|
3917
|
-
sources.push({ type: 'package.json', field: 'scripts.
|
|
3743
|
+
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
3744
|
+
if (testScript.includes('vitest')) {
|
|
3745
|
+
confidence += 10;
|
|
3746
|
+
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
3918
3747
|
}
|
|
3919
3748
|
if (confidence === 0) {
|
|
3920
3749
|
return null;
|
|
3921
3750
|
}
|
|
3922
3751
|
return {
|
|
3923
|
-
id: '
|
|
3924
|
-
name: '
|
|
3925
|
-
type: '
|
|
3752
|
+
id: 'vitest',
|
|
3753
|
+
name: 'Vitest',
|
|
3754
|
+
type: 'unit',
|
|
3926
3755
|
version,
|
|
3927
3756
|
configPath,
|
|
3928
3757
|
confidence: min(confidence, 100),
|
|
@@ -3952,7 +3781,7 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3952
3781
|
return undefined;
|
|
3953
3782
|
try {
|
|
3954
3783
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
3955
|
-
const parsed = parse(cleanContent);
|
|
3784
|
+
const parsed = parse$1(cleanContent);
|
|
3956
3785
|
return parsed?.compilerOptions?.strict === true;
|
|
3957
3786
|
}
|
|
3958
3787
|
catch {
|
|
@@ -3965,6 +3794,19 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3965
3794
|
* @param projectPath - Project directory path
|
|
3966
3795
|
* @param packageJson - Optional pre-loaded package.json
|
|
3967
3796
|
* @returns Detection result or null if not detected
|
|
3797
|
+
*
|
|
3798
|
+
* @example Detecting TypeScript
|
|
3799
|
+
* ```typescript
|
|
3800
|
+
* import { typescriptDetector } from '@hyperfrontend/project-scope'
|
|
3801
|
+
*
|
|
3802
|
+
* const result = typescriptDetector('./my-project')
|
|
3803
|
+
* if (result) {
|
|
3804
|
+
* console.log(`TypeScript ${result.version}`)
|
|
3805
|
+
* console.log(`Strict mode: ${result.strictMode ?? 'unknown'}`)
|
|
3806
|
+
* // => "TypeScript 5.3.0"
|
|
3807
|
+
* // => "Strict mode: true"
|
|
3808
|
+
* }
|
|
3809
|
+
* ```
|
|
3968
3810
|
*/
|
|
3969
3811
|
function typescriptDetector(projectPath, packageJson) {
|
|
3970
3812
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -4016,6 +3858,17 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
4016
3858
|
* @param projectPath - Project directory path
|
|
4017
3859
|
* @param packageJson - Optional pre-loaded package.json
|
|
4018
3860
|
* @returns Detection result or null if not detected
|
|
3861
|
+
*
|
|
3862
|
+
* @example Detecting Flow type system
|
|
3863
|
+
* ```typescript
|
|
3864
|
+
* import { flowDetector } from '@hyperfrontend/project-scope'
|
|
3865
|
+
*
|
|
3866
|
+
* const result = flowDetector('./my-project')
|
|
3867
|
+
* if (result) {
|
|
3868
|
+
* console.log(`Flow ${result.version} with config: ${result.configPath}`)
|
|
3869
|
+
* // => "Flow 0.232.0 with config: .flowconfig"
|
|
3870
|
+
* }
|
|
3871
|
+
* ```
|
|
4019
3872
|
*/
|
|
4020
3873
|
function flowDetector(projectPath, packageJson) {
|
|
4021
3874
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -4073,6 +3926,18 @@ function hasJsDocTypes(content) {
|
|
|
4073
3926
|
* @param projectPath - Project directory path
|
|
4074
3927
|
* @param packageJson - Optional pre-loaded package.json
|
|
4075
3928
|
* @returns Detection result or null if not detected
|
|
3929
|
+
*
|
|
3930
|
+
* @example Detecting JSDoc type annotations
|
|
3931
|
+
* ```typescript
|
|
3932
|
+
* import { jsdocDetector } from '@hyperfrontend/project-scope'
|
|
3933
|
+
*
|
|
3934
|
+
* const result = jsdocDetector('./my-project')
|
|
3935
|
+
* if (result) {
|
|
3936
|
+
* console.log('JSDoc types detected')
|
|
3937
|
+
* console.log('Sources:', result.detectedFrom.map(s => s.path ?? s.field))
|
|
3938
|
+
* // => "Sources: ['jsconfig.json', 'src/utils.js (JSDoc annotations)']"
|
|
3939
|
+
* }
|
|
3940
|
+
* ```
|
|
4076
3941
|
*/
|
|
4077
3942
|
function jsdocDetector(projectPath, packageJson) {
|
|
4078
3943
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -4089,7 +3954,7 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
4089
3954
|
if (content) {
|
|
4090
3955
|
try {
|
|
4091
3956
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
4092
|
-
const parsed = parse(cleanContent);
|
|
3957
|
+
const parsed = parse$1(cleanContent);
|
|
4093
3958
|
if (parsed?.compilerOptions?.checkJs === true || parsed?.compilerOptions?.allowJs === true) {
|
|
4094
3959
|
confidence += 30;
|
|
4095
3960
|
sources.push({ type: 'config-file', path: 'tsconfig.json (checkJs/allowJs)' });
|
|
@@ -4166,7 +4031,7 @@ function isDetectAllOptions(value) {
|
|
|
4166
4031
|
* @param packageJsonOrOptions - Optional pre-loaded package.json or options object
|
|
4167
4032
|
* @returns All detection results organized by category
|
|
4168
4033
|
*
|
|
4169
|
-
* @example
|
|
4034
|
+
* @example Running all tech detectors
|
|
4170
4035
|
* ```typescript
|
|
4171
4036
|
* import { detectAll } from '@hyperfrontend/project-scope'
|
|
4172
4037
|
*
|
|
@@ -4258,7 +4123,7 @@ const projectTypeLogger = createScopedLogger('project-scope:heuristics:project-t
|
|
|
4258
4123
|
* @param options - Detection options
|
|
4259
4124
|
* @returns Project type detection result with confidence score
|
|
4260
4125
|
*
|
|
4261
|
-
* @example
|
|
4126
|
+
* @example Detecting project type
|
|
4262
4127
|
* ```typescript
|
|
4263
4128
|
* import { detectProjectType } from '@hyperfrontend/project-scope'
|
|
4264
4129
|
*
|
|
@@ -4376,7 +4241,7 @@ function detectProjectType(projectPath, options) {
|
|
|
4376
4241
|
const projectJsonContent = readFileIfExists(projectJsonPath);
|
|
4377
4242
|
if (projectJsonContent) {
|
|
4378
4243
|
try {
|
|
4379
|
-
const projectJson = parse(projectJsonContent);
|
|
4244
|
+
const projectJson = parse$1(projectJsonContent);
|
|
4380
4245
|
if (projectJson.projectType) {
|
|
4381
4246
|
const nxType = projectJson.projectType === 'library' ? 'library' : 'application';
|
|
4382
4247
|
typeScores[nxType] += 50;
|
|
@@ -4436,6 +4301,15 @@ createScopedLogger('project-scope:root');
|
|
|
4436
4301
|
* @param startPath - Starting path
|
|
4437
4302
|
* @param markers - Files to search for
|
|
4438
4303
|
* @returns Root directory path or null
|
|
4304
|
+
*
|
|
4305
|
+
* @example Finding root by marker files
|
|
4306
|
+
* ```typescript
|
|
4307
|
+
* import { findRootDirectory } from '@hyperfrontend/project-scope'
|
|
4308
|
+
*
|
|
4309
|
+
* // Find monorepo root by looking for nx.json or lerna.json
|
|
4310
|
+
* const root = findRootDirectory('./libs/my-lib', ['nx.json', 'lerna.json'])
|
|
4311
|
+
* // => '/path/to/monorepo'
|
|
4312
|
+
* ```
|
|
4439
4313
|
*/
|
|
4440
4314
|
function findRootDirectory(startPath, markers) {
|
|
4441
4315
|
return locateByMarkers(startPath, markers);
|
|
@@ -4452,7 +4326,7 @@ const NX_CONFIG_FILES = ['nx.json', 'workspace.json'];
|
|
|
4452
4326
|
* @param path - Directory path to check
|
|
4453
4327
|
* @returns True if the directory contains nx.json or workspace.json
|
|
4454
4328
|
*
|
|
4455
|
-
* @example
|
|
4329
|
+
* @example Checking for NX workspace
|
|
4456
4330
|
* ```typescript
|
|
4457
4331
|
* import { isNxWorkspace } from '@hyperfrontend/project-scope'
|
|
4458
4332
|
*
|
|
@@ -4477,7 +4351,7 @@ function isNxWorkspace(path) {
|
|
|
4477
4351
|
* @param startPath - Starting path to search from
|
|
4478
4352
|
* @returns Workspace root path or null if not found
|
|
4479
4353
|
*
|
|
4480
|
-
* @example
|
|
4354
|
+
* @example Finding NX workspace root
|
|
4481
4355
|
* ```typescript
|
|
4482
4356
|
* import { findNxWorkspaceRoot } from '@hyperfrontend/project-scope'
|
|
4483
4357
|
*
|
|
@@ -4499,178 +4373,8 @@ function findNxWorkspaceRoot(startPath) {
|
|
|
4499
4373
|
return result;
|
|
4500
4374
|
}
|
|
4501
4375
|
|
|
4502
|
-
createScopedLogger('project-scope:nx:devkit');
|
|
4503
|
-
|
|
4504
4376
|
createScopedLogger('project-scope:nx:config');
|
|
4505
4377
|
|
|
4506
|
-
/**
|
|
4507
|
-
* Known configuration file patterns organized by type.
|
|
4508
|
-
*/
|
|
4509
|
-
const CONFIG_PATTERNS = {
|
|
4510
|
-
'package.json': {
|
|
4511
|
-
patterns: ['package.json'],
|
|
4512
|
-
format: 'json',
|
|
4513
|
-
description: 'NPM package manifest',
|
|
4514
|
-
},
|
|
4515
|
-
'package-lock.json': {
|
|
4516
|
-
patterns: ['package-lock.json'],
|
|
4517
|
-
format: 'json',
|
|
4518
|
-
description: 'NPM lockfile',
|
|
4519
|
-
},
|
|
4520
|
-
'pnpm-lock.yaml': {
|
|
4521
|
-
patterns: ['pnpm-lock.yaml'],
|
|
4522
|
-
format: 'yaml',
|
|
4523
|
-
description: 'PNPM lockfile',
|
|
4524
|
-
},
|
|
4525
|
-
'yarn.lock': {
|
|
4526
|
-
patterns: ['yarn.lock'],
|
|
4527
|
-
format: 'text',
|
|
4528
|
-
description: 'Yarn lockfile',
|
|
4529
|
-
},
|
|
4530
|
-
'.npmrc': {
|
|
4531
|
-
patterns: ['.npmrc'],
|
|
4532
|
-
format: 'ini',
|
|
4533
|
-
description: 'NPM configuration',
|
|
4534
|
-
sensitive: true,
|
|
4535
|
-
},
|
|
4536
|
-
tsconfig: {
|
|
4537
|
-
patterns: ['tsconfig.json', 'tsconfig.*.json'],
|
|
4538
|
-
format: 'jsonc',
|
|
4539
|
-
description: 'TypeScript configuration',
|
|
4540
|
-
canExtend: true,
|
|
4541
|
-
},
|
|
4542
|
-
nx: {
|
|
4543
|
-
patterns: ['nx.json'],
|
|
4544
|
-
format: 'json',
|
|
4545
|
-
description: 'NX workspace configuration',
|
|
4546
|
-
},
|
|
4547
|
-
'project.json': {
|
|
4548
|
-
patterns: ['project.json', '**/project.json'],
|
|
4549
|
-
format: 'json',
|
|
4550
|
-
description: 'NX project configuration',
|
|
4551
|
-
},
|
|
4552
|
-
'workspace.json': {
|
|
4553
|
-
patterns: ['workspace.json'],
|
|
4554
|
-
format: 'json',
|
|
4555
|
-
description: 'NX workspace projects (deprecated)',
|
|
4556
|
-
},
|
|
4557
|
-
turbo: {
|
|
4558
|
-
patterns: ['turbo.json'],
|
|
4559
|
-
format: 'jsonc',
|
|
4560
|
-
description: 'TurboRepo configuration',
|
|
4561
|
-
},
|
|
4562
|
-
lerna: {
|
|
4563
|
-
patterns: ['lerna.json'],
|
|
4564
|
-
format: 'json',
|
|
4565
|
-
description: 'Lerna configuration',
|
|
4566
|
-
},
|
|
4567
|
-
webpack: {
|
|
4568
|
-
patterns: ['webpack.config.js', 'webpack.config.ts', 'webpack.config.cjs', 'webpack.config.mjs'],
|
|
4569
|
-
format: 'js',
|
|
4570
|
-
description: 'Webpack configuration',
|
|
4571
|
-
},
|
|
4572
|
-
rollup: {
|
|
4573
|
-
patterns: ['rollup.config.js', 'rollup.config.ts', 'rollup.config.mjs'],
|
|
4574
|
-
format: 'js',
|
|
4575
|
-
description: 'Rollup configuration',
|
|
4576
|
-
},
|
|
4577
|
-
vite: {
|
|
4578
|
-
patterns: ['vite.config.js', 'vite.config.ts', 'vite.config.mjs'],
|
|
4579
|
-
format: 'js',
|
|
4580
|
-
description: 'Vite configuration',
|
|
4581
|
-
},
|
|
4582
|
-
esbuild: {
|
|
4583
|
-
patterns: ['esbuild.config.js', 'esbuild.config.ts', 'esbuild.config.mjs'],
|
|
4584
|
-
format: 'js',
|
|
4585
|
-
description: 'esbuild configuration',
|
|
4586
|
-
},
|
|
4587
|
-
babel: {
|
|
4588
|
-
patterns: ['babel.config.js', 'babel.config.json', '.babelrc', '.babelrc.js', '.babelrc.json'],
|
|
4589
|
-
format: 'json',
|
|
4590
|
-
description: 'Babel configuration',
|
|
4591
|
-
},
|
|
4592
|
-
swc: {
|
|
4593
|
-
patterns: ['.swcrc'],
|
|
4594
|
-
format: 'json',
|
|
4595
|
-
description: 'SWC configuration',
|
|
4596
|
-
},
|
|
4597
|
-
jest: {
|
|
4598
|
-
patterns: ['jest.config.js', 'jest.config.ts', 'jest.config.mjs'],
|
|
4599
|
-
description: 'Jest configuration',
|
|
4600
|
-
},
|
|
4601
|
-
vitest: {
|
|
4602
|
-
patterns: ['vitest.config.js', 'vitest.config.ts'],
|
|
4603
|
-
description: 'Vitest configuration',
|
|
4604
|
-
},
|
|
4605
|
-
cypress: {
|
|
4606
|
-
patterns: ['cypress.config.js', 'cypress.config.ts'],
|
|
4607
|
-
description: 'Cypress configuration',
|
|
4608
|
-
},
|
|
4609
|
-
playwright: {
|
|
4610
|
-
patterns: ['playwright.config.js', 'playwright.config.ts'],
|
|
4611
|
-
description: 'Playwright configuration',
|
|
4612
|
-
},
|
|
4613
|
-
next: {
|
|
4614
|
-
patterns: ['next.config.js', 'next.config.mjs', 'next.config.ts'],
|
|
4615
|
-
format: 'js',
|
|
4616
|
-
description: 'Next.js configuration',
|
|
4617
|
-
},
|
|
4618
|
-
angular: {
|
|
4619
|
-
patterns: ['angular.json'],
|
|
4620
|
-
format: 'json',
|
|
4621
|
-
description: 'Angular CLI configuration',
|
|
4622
|
-
},
|
|
4623
|
-
nuxt: {
|
|
4624
|
-
patterns: ['nuxt.config.js', 'nuxt.config.ts'],
|
|
4625
|
-
format: 'js',
|
|
4626
|
-
description: 'Nuxt.js configuration',
|
|
4627
|
-
},
|
|
4628
|
-
svelte: {
|
|
4629
|
-
patterns: ['svelte.config.js', 'svelte.config.ts'],
|
|
4630
|
-
format: 'js',
|
|
4631
|
-
description: 'SvelteKit configuration',
|
|
4632
|
-
},
|
|
4633
|
-
astro: {
|
|
4634
|
-
patterns: ['astro.config.js', 'astro.config.ts', 'astro.config.mjs'],
|
|
4635
|
-
format: 'js',
|
|
4636
|
-
description: 'Astro configuration',
|
|
4637
|
-
},
|
|
4638
|
-
eslint: {
|
|
4639
|
-
patterns: [
|
|
4640
|
-
'eslint.config.js',
|
|
4641
|
-
'eslint.config.cjs',
|
|
4642
|
-
'eslint.config.mjs',
|
|
4643
|
-
'.eslintrc',
|
|
4644
|
-
'.eslintrc.js',
|
|
4645
|
-
'.eslintrc.json',
|
|
4646
|
-
'.eslintrc.yml',
|
|
4647
|
-
],
|
|
4648
|
-
format: 'js',
|
|
4649
|
-
description: 'ESLint configuration',
|
|
4650
|
-
},
|
|
4651
|
-
prettier: {
|
|
4652
|
-
patterns: ['prettier.config.js', 'prettier.config.cjs', '.prettierrc', '.prettierrc.js', '.prettierrc.json', '.prettierrc.yml'],
|
|
4653
|
-
format: 'json',
|
|
4654
|
-
description: 'Prettier configuration',
|
|
4655
|
-
},
|
|
4656
|
-
env: {
|
|
4657
|
-
patterns: ['.env', '.env.*', '*.env'],
|
|
4658
|
-
format: 'dotenv',
|
|
4659
|
-
description: 'Environment variables',
|
|
4660
|
-
sensitive: true,
|
|
4661
|
-
},
|
|
4662
|
-
'.gitignore': {
|
|
4663
|
-
patterns: ['.gitignore'],
|
|
4664
|
-
format: 'text',
|
|
4665
|
-
description: 'Git ignore patterns',
|
|
4666
|
-
},
|
|
4667
|
-
'.gitattributes': {
|
|
4668
|
-
patterns: ['.gitattributes'],
|
|
4669
|
-
format: 'text',
|
|
4670
|
-
description: 'Git attributes',
|
|
4671
|
-
},
|
|
4672
|
-
};
|
|
4673
|
-
|
|
4674
4378
|
const configLogger = createScopedLogger('project-scope:config');
|
|
4675
4379
|
/**
|
|
4676
4380
|
* Cache for config detection results.
|
|
@@ -4688,7 +4392,7 @@ const configDetectionCache = createCache({ ttl: 30000, maxSize: 50 });
|
|
|
4688
4392
|
* @param options - Detection options
|
|
4689
4393
|
* @returns Array of detected configuration files
|
|
4690
4394
|
*
|
|
4691
|
-
* @example
|
|
4395
|
+
* @example Detecting configuration files
|
|
4692
4396
|
* ```typescript
|
|
4693
4397
|
* import { detectConfigs } from '@hyperfrontend/project-scope'
|
|
4694
4398
|
*
|
|
@@ -4765,25 +4469,6 @@ function detectConfigs(rootPath, types, options) {
|
|
|
4765
4469
|
return results;
|
|
4766
4470
|
}
|
|
4767
4471
|
|
|
4768
|
-
/**
|
|
4769
|
-
* Safe copies of Number built-in methods and constants.
|
|
4770
|
-
*
|
|
4771
|
-
* These references are captured at module initialization time to protect against
|
|
4772
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
4773
|
-
*
|
|
4774
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/number
|
|
4775
|
-
*/
|
|
4776
|
-
const _parseInt = globalThis.parseInt;
|
|
4777
|
-
const _parseFloat = globalThis.parseFloat;
|
|
4778
|
-
/**
|
|
4779
|
-
* (Safe copy) Parses a string and returns an integer.
|
|
4780
|
-
*/
|
|
4781
|
-
const parseInt = _parseInt;
|
|
4782
|
-
/**
|
|
4783
|
-
* (Safe copy) Parses a string and returns a floating point number.
|
|
4784
|
-
*/
|
|
4785
|
-
const parseFloat = _parseFloat;
|
|
4786
|
-
|
|
4787
4472
|
/**
|
|
4788
4473
|
* Detect config type from file name.
|
|
4789
4474
|
* Uses safe character-by-character matching to prevent ReDoS attacks.
|
|
@@ -4995,11 +4680,23 @@ function parseDotenv(content) {
|
|
|
4995
4680
|
* @param type - Category of configuration (e.g., typescript, eslint)
|
|
4996
4681
|
* @param format - Whether to strip comments (jsonc) or parse strictly (json)
|
|
4997
4682
|
* @returns Configuration object with parsed data and extends references
|
|
4683
|
+
*
|
|
4684
|
+
* @example Parsing JSON configuration
|
|
4685
|
+
* ```typescript
|
|
4686
|
+
* import { parseJsonConfig } from '@hyperfrontend/project-scope'
|
|
4687
|
+
*
|
|
4688
|
+
* const config = parseJsonConfig(
|
|
4689
|
+
* 'tsconfig.json',
|
|
4690
|
+
* '{ "extends": "./base.json", "compilerOptions": {} }',
|
|
4691
|
+
* 'typescript'
|
|
4692
|
+
* )
|
|
4693
|
+
* // => { type: 'typescript', path: 'tsconfig.json', data: {...}, extends: ['./base.json'] }
|
|
4694
|
+
* ```
|
|
4998
4695
|
*/
|
|
4999
4696
|
function parseJsonConfig(filePath, content, type, format = 'json') {
|
|
5000
4697
|
const cleanContent = format === 'jsonc' ? stripJsonComments(content) : content;
|
|
5001
4698
|
try {
|
|
5002
|
-
const data = parse(cleanContent);
|
|
4699
|
+
const data = parse$1(cleanContent);
|
|
5003
4700
|
let extendsPath;
|
|
5004
4701
|
if (typeof data['extends'] === 'string') {
|
|
5005
4702
|
extendsPath = [data['extends']];
|
|
@@ -5030,6 +4727,14 @@ function parseJsonConfig(filePath, content, type, format = 'json') {
|
|
|
5030
4727
|
* @param content - Raw file content to parse
|
|
5031
4728
|
* @param type - Category of configuration (e.g., github-actions, docker-compose)
|
|
5032
4729
|
* @returns Configuration object with parsed YAML data
|
|
4730
|
+
*
|
|
4731
|
+
* @example Parsing YAML configuration
|
|
4732
|
+
* ```typescript
|
|
4733
|
+
* import { parseYamlConfig } from '@hyperfrontend/project-scope'
|
|
4734
|
+
*
|
|
4735
|
+
* const config = parseYamlConfig('.github/workflows/ci.yml', yamlContent, 'github-actions')
|
|
4736
|
+
* // => { type: 'github-actions', path: '...', format: 'yaml', data: {...} }
|
|
4737
|
+
* ```
|
|
5033
4738
|
*/
|
|
5034
4739
|
function parseYamlConfig(filePath, content, type) {
|
|
5035
4740
|
const data = parseSimpleYaml(content);
|
|
@@ -5046,6 +4751,14 @@ function parseYamlConfig(filePath, content, type) {
|
|
|
5046
4751
|
* @param filePath - Path to config file
|
|
5047
4752
|
* @param type - Optional config type (auto-detected if not provided)
|
|
5048
4753
|
* @returns Parsed configuration
|
|
4754
|
+
*
|
|
4755
|
+
* @example Parsing a configuration file
|
|
4756
|
+
* ```typescript
|
|
4757
|
+
* import { parseConfig } from '@hyperfrontend/project-scope'
|
|
4758
|
+
*
|
|
4759
|
+
* const tsConfig = parseConfig('/project/tsconfig.json')
|
|
4760
|
+
* const eslintConfig = parseConfig('/project/.eslintrc.yml', 'eslint')
|
|
4761
|
+
* ```
|
|
5049
4762
|
*/
|
|
5050
4763
|
function parseConfig(filePath, type) {
|
|
5051
4764
|
const content = readFileContent(filePath);
|
|
@@ -5178,7 +4891,7 @@ function normalizeConfigFormat(format) {
|
|
|
5178
4891
|
* @param options - Analysis options
|
|
5179
4892
|
* @returns Complete analysis result
|
|
5180
4893
|
*
|
|
5181
|
-
* @example
|
|
4894
|
+
* @example Basic project analysis
|
|
5182
4895
|
* ```typescript
|
|
5183
4896
|
* const result = analyzeProject('./my-project')
|
|
5184
4897
|
* console.log(result.projectType) // 'application' | 'library' | ...
|
|
@@ -5511,6 +5224,26 @@ function parseAnalyzeArgs(args) {
|
|
|
5511
5224
|
*
|
|
5512
5225
|
* @param options - Configuration for the analyze operation
|
|
5513
5226
|
* @returns Command execution result with exit code and output
|
|
5227
|
+
*
|
|
5228
|
+
* @example Basic analysis of current directory
|
|
5229
|
+
* ```typescript
|
|
5230
|
+
* const result = analyzeCommand({ depth: 'basic' })
|
|
5231
|
+
* if (result.exitCode === 0) {
|
|
5232
|
+
* console.log(result.output)
|
|
5233
|
+
* // => "Project Type: Library\nWorkspace: NX Monorepo\n..."
|
|
5234
|
+
* }
|
|
5235
|
+
* ```
|
|
5236
|
+
*
|
|
5237
|
+
* @example JSON output with filters
|
|
5238
|
+
* ```typescript
|
|
5239
|
+
* const result = analyzeCommand({
|
|
5240
|
+
* path: './apps/frontend',
|
|
5241
|
+
* format: 'json',
|
|
5242
|
+
* depth: 'deep',
|
|
5243
|
+
* exclude: ['node_modules', 'dist'],
|
|
5244
|
+
* })
|
|
5245
|
+
* // => { exitCode: 0, output: '{"type":"application",...}' }
|
|
5246
|
+
* ```
|
|
5514
5247
|
*/
|
|
5515
5248
|
function analyzeCommand(options) {
|
|
5516
5249
|
const projectPath = options.path ? resolve(options.path) : process.cwd();
|
|
@@ -5790,6 +5523,26 @@ function parseConfigArgs(args) {
|
|
|
5790
5523
|
*
|
|
5791
5524
|
* @param options - Configuration command options
|
|
5792
5525
|
* @returns Command execution result with exit code and output
|
|
5526
|
+
*
|
|
5527
|
+
* @example Detect all configs in a project
|
|
5528
|
+
* ```typescript
|
|
5529
|
+
* const result = configCommand({ path: './my-project' })
|
|
5530
|
+
* if (result.exitCode === 0) {
|
|
5531
|
+
* console.log(result.output)
|
|
5532
|
+
* // => "TypeScript: tsconfig.json\nLinting: eslint.config.js\n..."
|
|
5533
|
+
* }
|
|
5534
|
+
* ```
|
|
5535
|
+
*
|
|
5536
|
+
* @example Filter by type with contents
|
|
5537
|
+
* ```typescript
|
|
5538
|
+
* const result = configCommand({
|
|
5539
|
+
* path: './my-project',
|
|
5540
|
+
* type: 'tsconfig',
|
|
5541
|
+
* showContents: true,
|
|
5542
|
+
* format: 'json',
|
|
5543
|
+
* })
|
|
5544
|
+
* // => { exitCode: 0, output: '[{"type":"tsconfig","path":"tsconfig.json",...}]' }
|
|
5545
|
+
* ```
|
|
5793
5546
|
*/
|
|
5794
5547
|
function configCommand(options) {
|
|
5795
5548
|
const projectPath = options.path ? resolve(options.path) : process.cwd();
|
|
@@ -5999,6 +5752,25 @@ function parseDepsArgs(args) {
|
|
|
5999
5752
|
*
|
|
6000
5753
|
* @param options - Parsed command options
|
|
6001
5754
|
* @returns Command execution result with exit code and output
|
|
5755
|
+
*
|
|
5756
|
+
* @example List all dependencies
|
|
5757
|
+
* ```typescript
|
|
5758
|
+
* const result = depsCommand({ path: './my-project' })
|
|
5759
|
+
* if (result.exitCode === 0) {
|
|
5760
|
+
* console.log(result.output)
|
|
5761
|
+
* // => "Dependencies\n============\nProduction (3):\n react ^18.2.0\n..."
|
|
5762
|
+
* }
|
|
5763
|
+
* ```
|
|
5764
|
+
*
|
|
5765
|
+
* @example Filter to dev dependencies as JSON
|
|
5766
|
+
* ```typescript
|
|
5767
|
+
* const result = depsCommand({
|
|
5768
|
+
* path: './my-project',
|
|
5769
|
+
* type: 'development',
|
|
5770
|
+
* format: 'json',
|
|
5771
|
+
* })
|
|
5772
|
+
* // => { exitCode: 0, output: '{"devDependencies":{"typescript":"^5.0.0",...}}' }
|
|
5773
|
+
* ```
|
|
6002
5774
|
*/
|
|
6003
5775
|
function depsCommand(options) {
|
|
6004
5776
|
const projectPath = options.path ? resolve(options.path) : process.cwd();
|
|
@@ -6275,6 +6047,27 @@ function parseTreeArgs(args) {
|
|
|
6275
6047
|
*
|
|
6276
6048
|
* @param options - Configuration for the tree operation
|
|
6277
6049
|
* @returns Command execution result with exit code and output
|
|
6050
|
+
*
|
|
6051
|
+
* @example Basic tree of current directory
|
|
6052
|
+
* ```typescript
|
|
6053
|
+
* const result = treeCommand({ depth: 2 })
|
|
6054
|
+
* if (result.exitCode === 0) {
|
|
6055
|
+
* console.log(result.output)
|
|
6056
|
+
* // => "src/\n├── index.ts\n├── lib/\n│ └── utils.ts\n..."
|
|
6057
|
+
* }
|
|
6058
|
+
* ```
|
|
6059
|
+
*
|
|
6060
|
+
* @example Directories only with metadata
|
|
6061
|
+
* ```typescript
|
|
6062
|
+
* const result = treeCommand({
|
|
6063
|
+
* path: './project',
|
|
6064
|
+
* dirsOnly: true,
|
|
6065
|
+
* showSize: true,
|
|
6066
|
+
* ignore: ['node_modules', '.git'],
|
|
6067
|
+
* format: 'json',
|
|
6068
|
+
* })
|
|
6069
|
+
* // => { exitCode: 0, output: '[{"name":"src","isDirectory":true,...}]' }
|
|
6070
|
+
* ```
|
|
6278
6071
|
*/
|
|
6279
6072
|
function treeCommand(options) {
|
|
6280
6073
|
const rootPath = options.path ? resolve(options.path) : process.cwd();
|
|
@@ -6432,7 +6225,7 @@ function parseGlobalOptions(args) {
|
|
|
6432
6225
|
* @param args - Command line arguments (typically process.argv.slice(2))
|
|
6433
6226
|
* @returns Command result with exit code and optional output/error
|
|
6434
6227
|
*
|
|
6435
|
-
* @example
|
|
6228
|
+
* @example Running analysis via CLI
|
|
6436
6229
|
* ```typescript
|
|
6437
6230
|
* import { run } from '@hyperfrontend/project-scope'
|
|
6438
6231
|
*
|
|
@@ -6493,4 +6286,3 @@ function run(args) {
|
|
|
6493
6286
|
}
|
|
6494
6287
|
|
|
6495
6288
|
export { analyzeCommand, analyzeCommandDef, configCommand, configCommandDef, depsCommand, depsCommandDef, run, treeCommand, treeCommandDef };
|
|
6496
|
-
//# sourceMappingURL=index.esm.js.map
|