@hyperfrontend/project-scope 0.2.1 → 0.2.3
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 +14 -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/guard/index.cjs.js +7 -0
- package/_shared/core/fs/guard/index.esm.js +5 -0
- package/_shared/core/fs/stat/index.cjs.js +47 -0
- package/_shared/core/fs/stat/index.esm.js +41 -0
- package/_shared/core/path/confine/index.cjs.js +22 -0
- package/_shared/core/path/confine/index.esm.js +19 -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 +1706 -1910
- package/cli/index.d.ts +273 -7
- package/cli/index.d.ts.map +1 -1
- package/cli/index.esm.js +1593 -1797
- 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 +243 -583
- package/core/fs/index.d.ts +479 -6
- package/core/fs/index.d.ts.map +1 -1
- package/core/fs/index.esm.js +233 -573
- package/core/index.cjs.js +526 -1746
- package/core/index.d.ts +486 -9
- package/core/index.d.ts.map +1 -1
- package/core/index.esm.js +515 -1732
- package/core/path/index.cjs.js +8 -234
- package/core/path/index.d.ts +327 -5
- package/core/path/index.d.ts.map +1 -1
- package/core/path/index.esm.js +8 -235
- 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 +105 -493
- package/heuristics/dependencies/index.d.ts +99 -2
- package/heuristics/dependencies/index.d.ts.map +1 -1
- package/heuristics/dependencies/index.esm.js +81 -469
- package/heuristics/entry-points/index.cjs.js +93 -796
- 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 +74 -777
- package/heuristics/framework/index.cjs.js +1483 -1411
- package/heuristics/framework/index.d.ts +104 -2
- package/heuristics/framework/index.d.ts.map +1 -1
- package/heuristics/framework/index.esm.js +1419 -1347
- package/heuristics/index.cjs.js +3220 -3306
- package/heuristics/index.d.ts +4 -5
- package/heuristics/index.d.ts.map +1 -1
- package/heuristics/index.esm.js +3244 -3330
- package/heuristics/project-type/index.cjs.js +1489 -1438
- 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 +1419 -1368
- package/index.cjs.js +3058 -3532
- package/index.d.ts +44 -10
- package/index.d.ts.map +1 -1
- package/index.esm.js +2914 -3376
- 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 +166 -579
- package/nx/index.d.ts +279 -4
- package/nx/index.d.ts.map +1 -1
- package/nx/index.esm.js +148 -556
- package/package.json +13 -12
- package/project/config/index.cjs.js +127 -1063
- package/project/config/index.d.ts +202 -4
- package/project/config/index.d.ts.map +1 -1
- package/project/config/index.esm.js +110 -1044
- package/project/index.cjs.js +328 -1101
- package/project/index.d.ts +4 -5
- package/project/index.d.ts.map +1 -1
- package/project/index.esm.js +307 -1077
- package/project/package/index.cjs.js +196 -473
- package/project/package/index.d.ts +280 -3
- package/project/package/index.d.ts.map +1 -1
- package/project/package/index.esm.js +183 -459
- package/project/root/index.cjs.js +109 -417
- package/project/root/index.d.ts +83 -2
- package/project/root/index.d.ts.map +1 -1
- package/project/root/index.esm.js +98 -406
- package/project/traversal/index.cjs.js +96 -622
- package/project/traversal/index.d.ts +165 -3
- package/project/traversal/index.d.ts.map +1 -1
- package/project/traversal/index.esm.js +82 -608
- package/tech/backend/index.cjs.js +223 -508
- package/tech/backend/index.d.ts +205 -8
- package/tech/backend/index.d.ts.map +1 -1
- package/tech/backend/index.esm.js +202 -487
- package/tech/build/index.cjs.js +350 -636
- package/tech/build/index.d.ts +276 -10
- package/tech/build/index.d.ts.map +1 -1
- package/tech/build/index.esm.js +328 -614
- package/tech/frontend/index.cjs.js +507 -685
- package/tech/frontend/index.d.ts +379 -15
- package/tech/frontend/index.d.ts.map +1 -1
- package/tech/frontend/index.esm.js +483 -661
- package/tech/index.cjs.js +1581 -1420
- package/tech/index.d.ts +55 -32
- package/tech/index.d.ts.map +1 -1
- package/tech/index.esm.js +1515 -1354
- package/tech/legacy/index.cjs.js +99 -449
- package/tech/legacy/index.d.ts +125 -7
- package/tech/legacy/index.d.ts.map +1 -1
- package/tech/legacy/index.esm.js +81 -431
- package/tech/linting/index.cjs.js +138 -523
- package/tech/linting/index.d.ts +129 -7
- package/tech/linting/index.d.ts.map +1 -1
- package/tech/linting/index.esm.js +118 -503
- package/tech/monorepo/index.cjs.js +246 -573
- package/tech/monorepo/index.d.ts +241 -10
- package/tech/monorepo/index.d.ts.map +1 -1
- package/tech/monorepo/index.esm.js +226 -553
- package/tech/testing/index.cjs.js +216 -571
- package/tech/testing/index.d.ts +176 -8
- package/tech/testing/index.d.ts.map +1 -1
- package/tech/testing/index.esm.js +198 -553
- package/tech/types/index.cjs.js +123 -506
- package/tech/types/index.d.ts +120 -2
- package/tech/types/index.d.ts.map +1 -1
- package/tech/types/index.esm.js +101 -484
- 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/tech/index.cjs.js
CHANGED
|
@@ -1,555 +1,28 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
* (Safe copy) Creates a new Map using the captured Map constructor.
|
|
21
|
-
* Use this instead of `new Map()`.
|
|
22
|
-
*
|
|
23
|
-
* @param iterable - Optional iterable of key-value pairs.
|
|
24
|
-
* @returns A new Map instance.
|
|
25
|
-
*/
|
|
26
|
-
const createMap = (iterable) => _Reflect$2.construct(_Map, iterable ? [iterable] : []);
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Safe copies of Object built-in methods.
|
|
30
|
-
*
|
|
31
|
-
* These references are captured at module initialization time to protect against
|
|
32
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
33
|
-
*
|
|
34
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/object
|
|
35
|
-
*/
|
|
36
|
-
const _Object = globalThis.Object;
|
|
37
|
-
/**
|
|
38
|
-
* (Safe copy) Prevents modification of existing property attributes and values,
|
|
39
|
-
* and prevents the addition of new properties.
|
|
40
|
-
*/
|
|
41
|
-
const freeze = _Object.freeze;
|
|
42
|
-
/**
|
|
43
|
-
* (Safe copy) Returns the names of the enumerable string properties and methods of an object.
|
|
44
|
-
*/
|
|
45
|
-
const keys = _Object.keys;
|
|
46
|
-
/**
|
|
47
|
-
* (Safe copy) Returns an array of key/values of the enumerable own properties of an object.
|
|
48
|
-
*/
|
|
49
|
-
const entries = _Object.entries;
|
|
50
|
-
/**
|
|
51
|
-
* (Safe copy) Returns an array of values of the enumerable own properties of an object.
|
|
52
|
-
*/
|
|
53
|
-
const values = _Object.values;
|
|
54
|
-
/**
|
|
55
|
-
* (Safe copy) Adds one or more properties to an object, and/or modifies attributes of existing properties.
|
|
56
|
-
*/
|
|
57
|
-
const defineProperties = _Object.defineProperties;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Safe copies of Set built-in via factory function.
|
|
61
|
-
*
|
|
62
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
63
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
64
|
-
*
|
|
65
|
-
* These references are captured at module initialization time to protect against
|
|
66
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
67
|
-
*
|
|
68
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/set
|
|
69
|
-
*/
|
|
70
|
-
const _Set = globalThis.Set;
|
|
71
|
-
const _Reflect$1 = globalThis.Reflect;
|
|
72
|
-
/**
|
|
73
|
-
* (Safe copy) Creates a new Set using the captured Set constructor.
|
|
74
|
-
* Use this instead of `new Set()`.
|
|
75
|
-
*
|
|
76
|
-
* @param iterable - Optional iterable of values.
|
|
77
|
-
* @returns A new Set instance.
|
|
78
|
-
*/
|
|
79
|
-
const createSet = (iterable) => _Reflect$1.construct(_Set, iterable ? [iterable] : []);
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Global registry of all caches for bulk operations.
|
|
83
|
-
*/
|
|
84
|
-
const cacheRegistry = createSet();
|
|
85
|
-
/**
|
|
86
|
-
* Create a cache with optional TTL and size limits.
|
|
87
|
-
*
|
|
88
|
-
* The cache provides a simple key-value store with:
|
|
89
|
-
* - Optional TTL (time-to-live) for automatic expiration
|
|
90
|
-
* - Optional maxSize for limiting cache size with FIFO eviction
|
|
91
|
-
* - Lazy expiration (entries are checked on access)
|
|
92
|
-
*
|
|
93
|
-
* @param options - Cache configuration options
|
|
94
|
-
* @returns Cache instance
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* ```typescript
|
|
98
|
-
* // Basic cache
|
|
99
|
-
* const cache = createCache<string, number>()
|
|
100
|
-
* cache.set('answer', 42)
|
|
101
|
-
* cache.get('answer') // 42
|
|
102
|
-
*
|
|
103
|
-
* // Cache with TTL (expires after 60 seconds)
|
|
104
|
-
* const ttlCache = createCache<string, object>({ ttl: 60000 })
|
|
105
|
-
*
|
|
106
|
-
* // Cache with max size (evicts oldest when full)
|
|
107
|
-
* const lruCache = createCache<string, object>({ maxSize: 100 })
|
|
108
|
-
*
|
|
109
|
-
* // Combined options
|
|
110
|
-
* const configCache = createCache<string, object>({
|
|
111
|
-
* ttl: 30000,
|
|
112
|
-
* maxSize: 50
|
|
113
|
-
* })
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
function createCache(options) {
|
|
117
|
-
const { ttl, maxSize } = options ?? {};
|
|
118
|
-
const store = createMap();
|
|
119
|
-
const insertionOrder = [];
|
|
120
|
-
/**
|
|
121
|
-
* Check if an entry is expired.
|
|
122
|
-
*
|
|
123
|
-
* @param entry - Cache entry to check
|
|
124
|
-
* @returns True if entry is expired
|
|
125
|
-
*/
|
|
126
|
-
function isExpired(entry) {
|
|
127
|
-
if (ttl === undefined)
|
|
128
|
-
return false;
|
|
129
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
130
|
-
return Date.now() - entry.timestamp > ttl;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Evict oldest entries to make room for new ones.
|
|
134
|
-
*/
|
|
135
|
-
function evictIfNeeded() {
|
|
136
|
-
if (maxSize === undefined)
|
|
137
|
-
return;
|
|
138
|
-
while (store.size >= maxSize && insertionOrder.length > 0) {
|
|
139
|
-
const oldestKey = insertionOrder.shift();
|
|
140
|
-
if (oldestKey !== undefined) {
|
|
141
|
-
store.delete(oldestKey);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Remove key from insertion order tracking.
|
|
147
|
-
*
|
|
148
|
-
* @param key - Key to remove from order tracking
|
|
149
|
-
*/
|
|
150
|
-
function removeFromOrder(key) {
|
|
151
|
-
const index = insertionOrder.indexOf(key);
|
|
152
|
-
if (index !== -1) {
|
|
153
|
-
insertionOrder.splice(index, 1);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const cache = {
|
|
157
|
-
get(key) {
|
|
158
|
-
const entry = store.get(key);
|
|
159
|
-
if (!entry)
|
|
160
|
-
return undefined;
|
|
161
|
-
if (isExpired(entry)) {
|
|
162
|
-
store.delete(key);
|
|
163
|
-
removeFromOrder(key);
|
|
164
|
-
return undefined;
|
|
165
|
-
}
|
|
166
|
-
return entry.value;
|
|
167
|
-
},
|
|
168
|
-
set(key, value) {
|
|
169
|
-
if (store.has(key)) {
|
|
170
|
-
removeFromOrder(key);
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
evictIfNeeded();
|
|
174
|
-
}
|
|
175
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
176
|
-
store.set(key, { value, timestamp: Date.now() });
|
|
177
|
-
insertionOrder.push(key);
|
|
178
|
-
},
|
|
179
|
-
has(key) {
|
|
180
|
-
const entry = store.get(key);
|
|
181
|
-
if (!entry)
|
|
182
|
-
return false;
|
|
183
|
-
if (isExpired(entry)) {
|
|
184
|
-
store.delete(key);
|
|
185
|
-
removeFromOrder(key);
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
return true;
|
|
189
|
-
},
|
|
190
|
-
delete(key) {
|
|
191
|
-
removeFromOrder(key);
|
|
192
|
-
return store.delete(key);
|
|
193
|
-
},
|
|
194
|
-
clear() {
|
|
195
|
-
store.clear();
|
|
196
|
-
insertionOrder.length = 0;
|
|
197
|
-
},
|
|
198
|
-
size() {
|
|
199
|
-
return store.size;
|
|
200
|
-
},
|
|
201
|
-
keys() {
|
|
202
|
-
return [...insertionOrder];
|
|
203
|
-
},
|
|
204
|
-
};
|
|
205
|
-
cacheRegistry.add(cache);
|
|
206
|
-
return freeze(cache);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Safe copies of Array built-in static methods.
|
|
211
|
-
*
|
|
212
|
-
* These references are captured at module initialization time to protect against
|
|
213
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
214
|
-
*
|
|
215
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
216
|
-
*/
|
|
217
|
-
const _Array = globalThis.Array;
|
|
218
|
-
/**
|
|
219
|
-
* (Safe copy) Determines whether the passed value is an Array.
|
|
220
|
-
*/
|
|
221
|
-
const isArray = _Array.isArray;
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Safe copies of Console 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/console
|
|
230
|
-
*/
|
|
231
|
-
const _console = globalThis.console;
|
|
232
|
-
/**
|
|
233
|
-
* (Safe copy) Outputs a message to the console.
|
|
234
|
-
*/
|
|
235
|
-
const log = _console.log.bind(_console);
|
|
236
|
-
/**
|
|
237
|
-
* (Safe copy) Outputs a warning message to the console.
|
|
238
|
-
*/
|
|
239
|
-
const warn = _console.warn.bind(_console);
|
|
240
|
-
/**
|
|
241
|
-
* (Safe copy) Outputs an error message to the console.
|
|
242
|
-
*/
|
|
243
|
-
const error = _console.error.bind(_console);
|
|
244
|
-
/**
|
|
245
|
-
* (Safe copy) Outputs an informational message to the console.
|
|
246
|
-
*/
|
|
247
|
-
const info = _console.info.bind(_console);
|
|
248
|
-
/**
|
|
249
|
-
* (Safe copy) Outputs a debug message to the console.
|
|
250
|
-
*/
|
|
251
|
-
const debug = _console.debug.bind(_console);
|
|
252
|
-
/**
|
|
253
|
-
* (Safe copy) Outputs a stack trace to the console.
|
|
254
|
-
*/
|
|
255
|
-
_console.trace.bind(_console);
|
|
256
|
-
/**
|
|
257
|
-
* (Safe copy) Displays an interactive listing of the properties of a specified object.
|
|
258
|
-
*/
|
|
259
|
-
_console.dir.bind(_console);
|
|
260
|
-
/**
|
|
261
|
-
* (Safe copy) Displays tabular data as a table.
|
|
262
|
-
*/
|
|
263
|
-
_console.table.bind(_console);
|
|
264
|
-
/**
|
|
265
|
-
* (Safe copy) Writes an error message to the console if the assertion is false.
|
|
266
|
-
*/
|
|
267
|
-
_console.assert.bind(_console);
|
|
268
|
-
/**
|
|
269
|
-
* (Safe copy) Clears the console.
|
|
270
|
-
*/
|
|
271
|
-
_console.clear.bind(_console);
|
|
272
|
-
/**
|
|
273
|
-
* (Safe copy) Logs the number of times that this particular call to count() has been called.
|
|
274
|
-
*/
|
|
275
|
-
_console.count.bind(_console);
|
|
276
|
-
/**
|
|
277
|
-
* (Safe copy) Resets the counter used with console.count().
|
|
278
|
-
*/
|
|
279
|
-
_console.countReset.bind(_console);
|
|
280
|
-
/**
|
|
281
|
-
* (Safe copy) Creates a new inline group in the console.
|
|
282
|
-
*/
|
|
283
|
-
_console.group.bind(_console);
|
|
284
|
-
/**
|
|
285
|
-
* (Safe copy) Creates a new inline group in the console that is initially collapsed.
|
|
286
|
-
*/
|
|
287
|
-
_console.groupCollapsed.bind(_console);
|
|
288
|
-
/**
|
|
289
|
-
* (Safe copy) Exits the current inline group.
|
|
290
|
-
*/
|
|
291
|
-
_console.groupEnd.bind(_console);
|
|
292
|
-
/**
|
|
293
|
-
* (Safe copy) Starts a timer with a name specified as an input parameter.
|
|
294
|
-
*/
|
|
295
|
-
_console.time.bind(_console);
|
|
296
|
-
/**
|
|
297
|
-
* (Safe copy) Stops a timer that was previously started.
|
|
298
|
-
*/
|
|
299
|
-
_console.timeEnd.bind(_console);
|
|
300
|
-
/**
|
|
301
|
-
* (Safe copy) Logs the current value of a timer that was previously started.
|
|
302
|
-
*/
|
|
303
|
-
_console.timeLog.bind(_console);
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Safe copies of JSON built-in methods.
|
|
307
|
-
*
|
|
308
|
-
* These references are captured at module initialization time to protect against
|
|
309
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
310
|
-
*
|
|
311
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/json
|
|
312
|
-
*/
|
|
313
|
-
const _JSON = globalThis.JSON;
|
|
314
|
-
/**
|
|
315
|
-
* (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
|
|
316
|
-
*/
|
|
317
|
-
const parse = _JSON.parse;
|
|
318
|
-
/**
|
|
319
|
-
* (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
|
320
|
-
*/
|
|
321
|
-
const stringify = _JSON.stringify;
|
|
322
|
-
|
|
323
|
-
const registeredClasses = [];
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Returns the data type of the target.
|
|
327
|
-
* Uses native `typeof` operator, however, makes distinction between `null`, `array`, and `object`.
|
|
328
|
-
* Also, when classes are registered via `registerClass`, it checks if objects are instance of any known registered class.
|
|
329
|
-
*
|
|
330
|
-
* @param target - The target to get the data type of.
|
|
331
|
-
* @returns The data type of the target.
|
|
332
|
-
*/
|
|
333
|
-
const getType = (target) => {
|
|
334
|
-
if (target === null)
|
|
335
|
-
return 'null';
|
|
336
|
-
const nativeDataType = typeof target;
|
|
337
|
-
if (nativeDataType === 'object') {
|
|
338
|
-
if (isArray(target))
|
|
339
|
-
return 'array';
|
|
340
|
-
for (const registeredClass of registeredClasses) {
|
|
341
|
-
if (target instanceof registeredClass)
|
|
342
|
-
return registeredClass.name;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
return nativeDataType;
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Safe copies of Error built-ins via factory functions.
|
|
350
|
-
*
|
|
351
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
352
|
-
* provides factory functions that use Reflect.construct internally.
|
|
353
|
-
*
|
|
354
|
-
* These references are captured at module initialization time to protect against
|
|
355
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
356
|
-
*
|
|
357
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
358
|
-
*/
|
|
359
|
-
const _Error = globalThis.Error;
|
|
360
|
-
const _Reflect = globalThis.Reflect;
|
|
361
|
-
/**
|
|
362
|
-
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
363
|
-
* Use this instead of `new Error()`.
|
|
364
|
-
*
|
|
365
|
-
* @param message - Optional error message.
|
|
366
|
-
* @param options - Optional error options.
|
|
367
|
-
* @returns A new Error instance.
|
|
368
|
-
*/
|
|
369
|
-
const createError = (message, options) => _Reflect.construct(_Error, [message, options]);
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Safe copies of Math built-in methods.
|
|
373
|
-
*
|
|
374
|
-
* These references are captured at module initialization time to protect against
|
|
375
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
376
|
-
*
|
|
377
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/math
|
|
378
|
-
*/
|
|
379
|
-
const _Math = globalThis.Math;
|
|
380
|
-
/**
|
|
381
|
-
* (Safe copy) Returns the smaller of zero or more numbers.
|
|
382
|
-
*/
|
|
383
|
-
const min = _Math.min;
|
|
384
|
-
|
|
385
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
386
|
-
/**
|
|
387
|
-
* Creates a wrapper function that only executes the wrapped function if the condition function returns true.
|
|
388
|
-
*
|
|
389
|
-
* @param func - The function to be conditionally executed.
|
|
390
|
-
* @param conditionFunc - A function that returns a boolean, determining if `func` should be executed.
|
|
391
|
-
* @returns A wrapped version of `func` that executes conditionally.
|
|
392
|
-
*/
|
|
393
|
-
function createConditionalExecutionFunction(func, conditionFunc) {
|
|
394
|
-
return function (...args) {
|
|
395
|
-
if (conditionFunc()) {
|
|
396
|
-
return func(...args);
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
402
|
-
/**
|
|
403
|
-
* Creates a wrapper function that silently ignores any errors thrown by the wrapped void function.
|
|
404
|
-
* This function is specifically for wrapping functions that do not return a value (void functions).
|
|
405
|
-
* Exceptions are swallowed without any logging or handling.
|
|
406
|
-
*
|
|
407
|
-
* @param func - The void function to be wrapped.
|
|
408
|
-
* @returns A wrapped version of the input function that ignores errors.
|
|
409
|
-
*/
|
|
410
|
-
function createErrorIgnoringFunction(func) {
|
|
411
|
-
return function (...args) {
|
|
412
|
-
try {
|
|
413
|
-
func(...args);
|
|
414
|
-
}
|
|
415
|
-
catch {
|
|
416
|
-
// Deliberately swallowing/ignoring the exception
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
422
|
-
/**
|
|
423
|
-
* A no-operation function (noop) that does nothing regardless of the arguments passed.
|
|
424
|
-
* It is designed to be as permissive as possible in its typing without using the `Function` keyword.
|
|
425
|
-
*
|
|
426
|
-
* @param args - Any arguments passed to the function (ignored)
|
|
427
|
-
*/
|
|
428
|
-
const noop = (...args) => {
|
|
429
|
-
// Intentionally does nothing
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
const logLevels = ['none', 'error', 'warn', 'log', 'info', 'debug'];
|
|
433
|
-
const priority = {
|
|
434
|
-
error: 4,
|
|
435
|
-
warn: 3,
|
|
436
|
-
log: 2,
|
|
437
|
-
info: 1,
|
|
438
|
-
debug: 0,
|
|
439
|
-
};
|
|
440
|
-
/**
|
|
441
|
-
* Validates whether a given string is a valid log level.
|
|
442
|
-
*
|
|
443
|
-
* @param level - The log level to validate
|
|
444
|
-
* @returns True if the level is valid, false otherwise
|
|
445
|
-
*/
|
|
446
|
-
function isValidLogLevel(level) {
|
|
447
|
-
return logLevels.includes(level);
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Creates a log level configuration manager for controlling logging behavior.
|
|
451
|
-
* Provides methods to get, set, and evaluate log levels based on priority.
|
|
452
|
-
*
|
|
453
|
-
* @param level - The initial log level (defaults to 'error')
|
|
454
|
-
* @returns A configuration object with log level management methods
|
|
455
|
-
* @throws {Error} When the provided level is not a valid log level
|
|
456
|
-
*/
|
|
457
|
-
function createLogLevelConfig(level = 'error') {
|
|
458
|
-
if (!isValidLogLevel(level)) {
|
|
459
|
-
throw createError('Cannot create log level configuration with a valid default log level');
|
|
460
|
-
}
|
|
461
|
-
const state = { level };
|
|
462
|
-
const getLogLevel = () => state.level;
|
|
463
|
-
const setLogLevel = (level) => {
|
|
464
|
-
if (!isValidLogLevel(level)) {
|
|
465
|
-
throw createError(`Cannot set value '${level}' level. Expected levels are ${logLevels}.`);
|
|
466
|
-
}
|
|
467
|
-
state.level = level;
|
|
468
|
-
};
|
|
469
|
-
const shouldLog = (level) => {
|
|
470
|
-
if (state.level === 'none' || level === 'none' || !isValidLogLevel(level)) {
|
|
471
|
-
return false;
|
|
472
|
-
}
|
|
473
|
-
return priority[level] >= priority[state.level];
|
|
474
|
-
};
|
|
475
|
-
return freeze({
|
|
476
|
-
getLogLevel,
|
|
477
|
-
setLogLevel,
|
|
478
|
-
shouldLog,
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Creates a logger instance with configurable log level filtering.
|
|
484
|
-
* Each log function is wrapped to respect the current log level setting.
|
|
485
|
-
*
|
|
486
|
-
* @param error - Function to handle error-level logs (required)
|
|
487
|
-
* @param warn - Function to handle warning-level logs (optional, defaults to noop)
|
|
488
|
-
* @param log - Function to handle standard logs (optional, defaults to noop)
|
|
489
|
-
* @param info - Function to handle info-level logs (optional, defaults to noop)
|
|
490
|
-
* @param debug - Function to handle debug-level logs (optional, defaults to noop)
|
|
491
|
-
* @returns A frozen logger object with log methods and level control
|
|
492
|
-
* @throws {ErrorLevelFn} When any provided log function is invalid
|
|
493
|
-
*/
|
|
494
|
-
function createLogger(error, warn = noop, log = noop, info = noop, debug = noop) {
|
|
495
|
-
if (notValidLogFn(error)) {
|
|
496
|
-
throw createError(notFnMsg('error'));
|
|
497
|
-
}
|
|
498
|
-
if (notValidLogFn(warn)) {
|
|
499
|
-
throw createError(notFnMsg('warn'));
|
|
500
|
-
}
|
|
501
|
-
if (notValidLogFn(log)) {
|
|
502
|
-
throw createError(notFnMsg('log'));
|
|
503
|
-
}
|
|
504
|
-
if (notValidLogFn(info)) {
|
|
505
|
-
throw createError(notFnMsg('info'));
|
|
506
|
-
}
|
|
507
|
-
if (notValidLogFn(debug)) {
|
|
508
|
-
throw createError(notFnMsg('debug'));
|
|
509
|
-
}
|
|
510
|
-
const { setLogLevel, getLogLevel, shouldLog } = createLogLevelConfig();
|
|
511
|
-
const wrapLogFn = (fn, level) => {
|
|
512
|
-
if (fn === noop)
|
|
513
|
-
return fn;
|
|
514
|
-
const condition = () => shouldLog(level);
|
|
515
|
-
return createConditionalExecutionFunction(createErrorIgnoringFunction(fn), condition);
|
|
516
|
-
};
|
|
517
|
-
return freeze({
|
|
518
|
-
error: wrapLogFn(error, 'error'),
|
|
519
|
-
warn: wrapLogFn(warn, 'warn'),
|
|
520
|
-
log: wrapLogFn(log, 'log'),
|
|
521
|
-
info: wrapLogFn(info, 'info'),
|
|
522
|
-
debug: wrapLogFn(debug, 'debug'),
|
|
523
|
-
setLogLevel,
|
|
524
|
-
getLogLevel,
|
|
525
|
-
});
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* Validates whether a given value is a valid log function.
|
|
529
|
-
*
|
|
530
|
-
* @param fn - The value to validate
|
|
531
|
-
* @returns True if the value is not a function (invalid), false if it is valid
|
|
532
|
-
*/
|
|
533
|
-
function notValidLogFn(fn) {
|
|
534
|
-
return getType(fn) !== 'function' && fn !== noop;
|
|
535
|
-
}
|
|
536
|
-
/**
|
|
537
|
-
* Generates an error message for invalid log function parameters.
|
|
538
|
-
*
|
|
539
|
-
* @param label - The name of the log function that failed validation
|
|
540
|
-
* @returns A formatted error message string
|
|
541
|
-
*/
|
|
542
|
-
function notFnMsg(label) {
|
|
543
|
-
return `Cannot create a logger when ${label} is not a function`;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
createLogger(error, warn, log, info, debug);
|
|
3
|
+
const index_cjs_js$1 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.cjs.js');
|
|
4
|
+
const index_cjs_js$2 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.cjs.js');
|
|
5
|
+
const index_cjs_js = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.cjs.js');
|
|
6
|
+
const index_cjs_js$5 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.cjs.js');
|
|
7
|
+
const index_cjs_js$4 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.cjs.js');
|
|
8
|
+
const index_cjs_js$6 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js');
|
|
9
|
+
const index_cjs_js$3 = require('../_dependencies/@hyperfrontend/logging/index.cjs.js');
|
|
10
|
+
const node_path = require('node:path');
|
|
11
|
+
const index_cjs_js$7 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
|
|
12
|
+
const node_fs = require('node:fs');
|
|
13
|
+
const index_cjs_js$8 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.cjs.js');
|
|
14
|
+
const { isSafePath } = require('../_shared/core/fs/guard/index.cjs.js');
|
|
15
|
+
const { isDirectory, exists } = require('../_shared/core/fs/stat/index.cjs.js');
|
|
16
|
+
const { join } = require('../_shared/core/path/join/index.cjs.js');
|
|
17
|
+
const { createCache } = require('../_shared/core/cache/index.cjs.js');
|
|
18
|
+
const { collectAllDependencies, parseVersionString, locateConfigFile, filterScriptsByCommand } = require('../_shared/tech/shared-utils/detector-helpers/index.cjs.js');
|
|
19
|
+
const { pnpmWorkspacesDetector } = require('../_shared/tech/monorepo/pnpm-workspaces/index.cjs.js');
|
|
547
20
|
|
|
548
21
|
/**
|
|
549
22
|
* Global log level registry.
|
|
550
23
|
* Tracks all created scoped loggers to allow global log level changes.
|
|
551
24
|
*/
|
|
552
|
-
const loggerRegistry = createSet();
|
|
25
|
+
const loggerRegistry = index_cjs_js.createSet();
|
|
553
26
|
/** Redacted placeholder for sensitive values */
|
|
554
27
|
const REDACTED = '[REDACTED]';
|
|
555
28
|
/**
|
|
@@ -583,17 +56,24 @@ function isSensitiveKey(key) {
|
|
|
583
56
|
*
|
|
584
57
|
* @param obj - Object to sanitize
|
|
585
58
|
* @returns New object with sensitive values redacted
|
|
59
|
+
*
|
|
60
|
+
* @example Sanitizing sensitive data
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const config = { apiKey: 'secret123', endpoint: 'https://api.example.com' }
|
|
63
|
+
* const safe = sanitize(config)
|
|
64
|
+
* // => { apiKey: '[REDACTED]', endpoint: 'https://api.example.com' }
|
|
65
|
+
* ```
|
|
586
66
|
*/
|
|
587
67
|
function sanitize(obj) {
|
|
588
68
|
if (obj === null || obj === undefined) {
|
|
589
69
|
return obj;
|
|
590
70
|
}
|
|
591
|
-
if (isArray(obj)) {
|
|
71
|
+
if (index_cjs_js$5.isArray(obj)) {
|
|
592
72
|
return obj.map((item) => sanitize(item));
|
|
593
73
|
}
|
|
594
74
|
if (typeof obj === 'object') {
|
|
595
75
|
const result = {};
|
|
596
|
-
for (const [key, value] of entries(obj)) {
|
|
76
|
+
for (const [key, value] of index_cjs_js$2.entries(obj)) {
|
|
597
77
|
if (isSensitiveKey(key)) {
|
|
598
78
|
result[key] = REDACTED;
|
|
599
79
|
}
|
|
@@ -618,9 +98,9 @@ function sanitize(obj) {
|
|
|
618
98
|
*/
|
|
619
99
|
function formatMessage(namespace, message, meta) {
|
|
620
100
|
const prefix = `[${namespace}]`;
|
|
621
|
-
if (meta && keys(meta).length > 0) {
|
|
101
|
+
if (meta && index_cjs_js$2.keys(meta).length > 0) {
|
|
622
102
|
const sanitizedMeta = sanitize(meta);
|
|
623
|
-
return `${prefix} ${message} ${stringify(sanitizedMeta)}`;
|
|
103
|
+
return `${prefix} ${message} ${index_cjs_js$6.stringify(sanitizedMeta)}`;
|
|
624
104
|
}
|
|
625
105
|
return `${prefix} ${message}`;
|
|
626
106
|
}
|
|
@@ -633,7 +113,7 @@ function formatMessage(namespace, message, meta) {
|
|
|
633
113
|
* @param options - Logger configuration options
|
|
634
114
|
* @returns A configured scoped logger instance
|
|
635
115
|
*
|
|
636
|
-
* @example
|
|
116
|
+
* @example Creating a scoped logger
|
|
637
117
|
* ```typescript
|
|
638
118
|
* const logger = createScopedLogger('project-scope')
|
|
639
119
|
* logger.setLogLevel('debug')
|
|
@@ -652,9 +132,9 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
652
132
|
const processedMeta = sanitizeSecrets && meta ? sanitize(meta) : meta;
|
|
653
133
|
baseFn(formatMessage(namespace, message, processedMeta));
|
|
654
134
|
};
|
|
655
|
-
const baseLogger = createLogger(createLogFn(error), createLogFn(warn), createLogFn(log), createLogFn(info), createLogFn(debug));
|
|
135
|
+
const baseLogger = index_cjs_js$3.createLogger(createLogFn(index_cjs_js$4.error), createLogFn(index_cjs_js$4.warn), createLogFn(index_cjs_js$4.log), createLogFn(index_cjs_js$4.info), createLogFn(index_cjs_js$4.debug));
|
|
656
136
|
baseLogger.setLogLevel(level);
|
|
657
|
-
const scopedLogger = freeze({
|
|
137
|
+
const scopedLogger = index_cjs_js$2.freeze({
|
|
658
138
|
error: (message, meta) => baseLogger.error(message, meta),
|
|
659
139
|
warn: (message, meta) => baseLogger.warn(message, meta),
|
|
660
140
|
log: (message, meta) => baseLogger.log(message, meta),
|
|
@@ -670,7 +150,7 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
670
150
|
* Default logger instance for the project-scope library.
|
|
671
151
|
* Use this for general logging within the library.
|
|
672
152
|
*
|
|
673
|
-
* @example
|
|
153
|
+
* @example Using the default logger
|
|
674
154
|
* ```typescript
|
|
675
155
|
* import { logger } from '@hyperfrontend/project-scope/core'
|
|
676
156
|
*
|
|
@@ -688,10 +168,19 @@ createScopedLogger('project-scope:fs');
|
|
|
688
168
|
* @param code - The category code for this type of filesystem failure
|
|
689
169
|
* @param context - Additional context including path, operation, and cause
|
|
690
170
|
* @returns A configured Error object with code and context properties
|
|
171
|
+
*
|
|
172
|
+
* @example Creating a file system error
|
|
173
|
+
* ```typescript
|
|
174
|
+
* throw createFileSystemError(
|
|
175
|
+
* 'Cannot read file',
|
|
176
|
+
* 'FS_READ_ERROR',
|
|
177
|
+
* { path: './missing.txt', operation: 'read' }
|
|
178
|
+
* )
|
|
179
|
+
* ```
|
|
691
180
|
*/
|
|
692
181
|
function createFileSystemError(message, code, context) {
|
|
693
|
-
const error = createError(message);
|
|
694
|
-
defineProperties(error, {
|
|
182
|
+
const error = index_cjs_js$7.createError(message);
|
|
183
|
+
index_cjs_js$2.defineProperties(error, {
|
|
695
184
|
code: { value: code, enumerable: true },
|
|
696
185
|
context: { value: context, enumerable: true },
|
|
697
186
|
});
|
|
@@ -703,9 +192,17 @@ function createFileSystemError(message, code, context) {
|
|
|
703
192
|
* @param filePath - Path to file
|
|
704
193
|
* @param encoding - File encoding (default: utf-8)
|
|
705
194
|
* @returns File contents or null if file doesn't exist
|
|
195
|
+
*
|
|
196
|
+
* @example Reading file if it exists
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const content = readFileIfExists('./optional-config.json')
|
|
199
|
+
* if (content) {
|
|
200
|
+
* // File existed, use content
|
|
201
|
+
* }
|
|
202
|
+
* ```
|
|
706
203
|
*/
|
|
707
204
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
708
|
-
if (!node_fs.existsSync(filePath)) {
|
|
205
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
709
206
|
return null;
|
|
710
207
|
}
|
|
711
208
|
try {
|
|
@@ -716,56 +213,6 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
716
213
|
}
|
|
717
214
|
}
|
|
718
215
|
|
|
719
|
-
createScopedLogger('project-scope:fs:write');
|
|
720
|
-
|
|
721
|
-
/**
|
|
722
|
-
* Get file stats with error handling.
|
|
723
|
-
*
|
|
724
|
-
* @param filePath - Path to file
|
|
725
|
-
* @param followSymlinks - Whether to follow symlinks (default: true)
|
|
726
|
-
* @returns File stats or null if path doesn't exist
|
|
727
|
-
*/
|
|
728
|
-
function getFileStat(filePath, followSymlinks = true) {
|
|
729
|
-
if (!node_fs.existsSync(filePath)) {
|
|
730
|
-
return null;
|
|
731
|
-
}
|
|
732
|
-
try {
|
|
733
|
-
const stat = followSymlinks ? node_fs.statSync(filePath) : node_fs.lstatSync(filePath);
|
|
734
|
-
return {
|
|
735
|
-
isFile: stat.isFile(),
|
|
736
|
-
isDirectory: stat.isDirectory(),
|
|
737
|
-
isSymlink: stat.isSymbolicLink(),
|
|
738
|
-
size: stat.size,
|
|
739
|
-
created: stat.birthtime,
|
|
740
|
-
modified: stat.mtime,
|
|
741
|
-
accessed: stat.atime,
|
|
742
|
-
mode: stat.mode,
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
catch {
|
|
746
|
-
return null;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* Check if path is a directory.
|
|
751
|
-
*
|
|
752
|
-
* @param dirPath - Path to check
|
|
753
|
-
* @returns True if path is a directory
|
|
754
|
-
*/
|
|
755
|
-
function isDirectory(dirPath) {
|
|
756
|
-
const stats = getFileStat(dirPath);
|
|
757
|
-
return stats?.isDirectory ?? false;
|
|
758
|
-
}
|
|
759
|
-
/**
|
|
760
|
-
* Check if path exists.
|
|
761
|
-
*
|
|
762
|
-
* @param filePath - Path to check
|
|
763
|
-
* @returns True if path exists
|
|
764
|
-
*/
|
|
765
|
-
function exists(filePath) {
|
|
766
|
-
return node_fs.existsSync(filePath);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
216
|
const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
770
217
|
/**
|
|
771
218
|
* List immediate contents of a directory.
|
|
@@ -774,7 +221,7 @@ const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
|
774
221
|
* @returns Array of entries with metadata for each file/directory
|
|
775
222
|
* @throws {Error} If directory doesn't exist or isn't a directory
|
|
776
223
|
*
|
|
777
|
-
* @example
|
|
224
|
+
* @example Listing directory contents
|
|
778
225
|
* ```typescript
|
|
779
226
|
* import { readDirectory } from '@hyperfrontend/project-scope'
|
|
780
227
|
*
|
|
@@ -815,19 +262,10 @@ function readDirectory(dirPath) {
|
|
|
815
262
|
}
|
|
816
263
|
}
|
|
817
264
|
|
|
818
|
-
/**
|
|
819
|
-
* Join path segments.
|
|
820
|
-
* Uses platform-specific separators (e.g., / or \).
|
|
821
|
-
*
|
|
822
|
-
* @param paths - Path segments to join
|
|
823
|
-
* @returns Joined path
|
|
824
|
-
*/
|
|
825
|
-
function join(...paths) {
|
|
826
|
-
return node_path.join(...paths);
|
|
827
|
-
}
|
|
828
|
-
|
|
829
265
|
createScopedLogger('project-scope:fs:traversal');
|
|
830
266
|
|
|
267
|
+
createScopedLogger('project-scope:fs:write');
|
|
268
|
+
|
|
831
269
|
const packageLogger = createScopedLogger('project-scope:project:package');
|
|
832
270
|
/**
|
|
833
271
|
* Verifies that a value is an object with only string values,
|
|
@@ -839,7 +277,7 @@ const packageLogger = createScopedLogger('project-scope:project:package');
|
|
|
839
277
|
function isStringRecord(value) {
|
|
840
278
|
if (typeof value !== 'object' || value === null)
|
|
841
279
|
return false;
|
|
842
|
-
return values(value).every((v) => typeof v === 'string');
|
|
280
|
+
return index_cjs_js$2.values(value).every((v) => typeof v === 'string');
|
|
843
281
|
}
|
|
844
282
|
/**
|
|
845
283
|
* Extracts and normalizes the workspaces field from package.json,
|
|
@@ -849,12 +287,12 @@ function isStringRecord(value) {
|
|
|
849
287
|
* @returns Normalized workspace patterns or undefined if invalid
|
|
850
288
|
*/
|
|
851
289
|
function parseWorkspaces(value) {
|
|
852
|
-
if (isArray(value) && value.every((v) => typeof v === 'string')) {
|
|
290
|
+
if (index_cjs_js$5.isArray(value) && value.every((v) => typeof v === 'string')) {
|
|
853
291
|
return value;
|
|
854
292
|
}
|
|
855
293
|
if (typeof value === 'object' && value !== null) {
|
|
856
294
|
const obj = value;
|
|
857
|
-
if (isArray(obj['packages'])) {
|
|
295
|
+
if (index_cjs_js$5.isArray(obj['packages'])) {
|
|
858
296
|
return { packages: obj['packages'] };
|
|
859
297
|
}
|
|
860
298
|
}
|
|
@@ -868,7 +306,7 @@ function parseWorkspaces(value) {
|
|
|
868
306
|
*/
|
|
869
307
|
function validatePackageJson(data) {
|
|
870
308
|
if (typeof data !== 'object' || data === null) {
|
|
871
|
-
throw createError('package.json must be an object');
|
|
309
|
+
throw index_cjs_js$7.createError('package.json must be an object');
|
|
872
310
|
}
|
|
873
311
|
const pkg = data;
|
|
874
312
|
return {
|
|
@@ -897,6 +335,16 @@ function validatePackageJson(data) {
|
|
|
897
335
|
*
|
|
898
336
|
* @param projectPath - Project directory path or path to package.json
|
|
899
337
|
* @returns Parsed package.json or null if not found
|
|
338
|
+
*
|
|
339
|
+
* @example Reading package.json if it exists
|
|
340
|
+
* ```typescript
|
|
341
|
+
* import { readPackageJsonIfExists } from '@hyperfrontend/project-scope'
|
|
342
|
+
*
|
|
343
|
+
* const pkg = readPackageJsonIfExists('/path/to/project')
|
|
344
|
+
* if (pkg) {
|
|
345
|
+
* console.log('Found:', pkg.name)
|
|
346
|
+
* }
|
|
347
|
+
* ```
|
|
900
348
|
*/
|
|
901
349
|
function readPackageJsonIfExists(projectPath) {
|
|
902
350
|
const packageJsonPath = projectPath.endsWith('package.json') ? projectPath : node_path.join(projectPath, 'package.json');
|
|
@@ -906,7 +354,7 @@ function readPackageJsonIfExists(projectPath) {
|
|
|
906
354
|
return null;
|
|
907
355
|
}
|
|
908
356
|
try {
|
|
909
|
-
const validated = validatePackageJson(parse(content));
|
|
357
|
+
const validated = validatePackageJson(index_cjs_js$6.parse(content));
|
|
910
358
|
packageLogger.debug('Package.json loaded', { path: packageJsonPath, name: validated.name });
|
|
911
359
|
return validated;
|
|
912
360
|
}
|
|
@@ -917,79 +365,31 @@ function readPackageJsonIfExists(projectPath) {
|
|
|
917
365
|
}
|
|
918
366
|
|
|
919
367
|
/**
|
|
920
|
-
*
|
|
921
|
-
* Merges dependencies, devDependencies, peerDependencies, and optionalDependencies.
|
|
368
|
+
* Detect Express in project.
|
|
922
369
|
*
|
|
923
|
-
* @param
|
|
924
|
-
* @
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Extract clean version from dependency version string.
|
|
936
|
-
* Removes semver prefixes like ^, ~, >=, etc.
|
|
937
|
-
* Uses character-by-character parsing to avoid ReDoS vulnerabilities.
|
|
370
|
+
* @param projectPath - Project directory path
|
|
371
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
372
|
+
* @returns Detection result or null if not detected
|
|
373
|
+
* @example Detecting Express framework
|
|
374
|
+
* ```typescript
|
|
375
|
+
* const pkg = {
|
|
376
|
+
* dependencies: { express: '^4.18.2', cors: '^2.8.5' },
|
|
377
|
+
* devDependencies: { '@types/express': '^4.17.17' },
|
|
378
|
+
* }
|
|
938
379
|
*
|
|
939
|
-
*
|
|
940
|
-
*
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
}
|
|
953
|
-
return versionString.slice(start);
|
|
954
|
-
}
|
|
955
|
-
/**
|
|
956
|
-
* Find first matching config file in project.
|
|
957
|
-
* Note: Name avoids similarity to fs.readFile/fs.readFileSync.
|
|
958
|
-
*
|
|
959
|
-
* @param projectPath - The project directory path
|
|
960
|
-
* @param patterns - Array of config file patterns to search for
|
|
961
|
-
* @returns The first matching config file path or undefined
|
|
962
|
-
*/
|
|
963
|
-
function locateConfigFile(projectPath, patterns) {
|
|
964
|
-
for (const pattern of patterns) {
|
|
965
|
-
const fullPath = join(projectPath, pattern);
|
|
966
|
-
if (exists(fullPath)) {
|
|
967
|
-
return pattern;
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
return undefined;
|
|
971
|
-
}
|
|
972
|
-
/**
|
|
973
|
-
* Find scripts containing a specific command.
|
|
974
|
-
*
|
|
975
|
-
* @param scripts - The scripts object from package.json
|
|
976
|
-
* @param command - The command string to search for
|
|
977
|
-
* @returns Array of script names that contain the command
|
|
978
|
-
*/
|
|
979
|
-
function filterScriptsByCommand(scripts, command) {
|
|
980
|
-
if (!scripts)
|
|
981
|
-
return [];
|
|
982
|
-
return entries(scripts)
|
|
983
|
-
.filter(([, script]) => script.includes(command))
|
|
984
|
-
.map(([name]) => name);
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
/**
|
|
988
|
-
* Detect Express in project.
|
|
989
|
-
*
|
|
990
|
-
* @param projectPath - Project directory path
|
|
991
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
992
|
-
* @returns Detection result or null if not detected
|
|
380
|
+
* const result = expressDetector('/path/to/project', pkg)
|
|
381
|
+
* // => {
|
|
382
|
+
* // id: 'express',
|
|
383
|
+
* // name: 'Express',
|
|
384
|
+
* // version: '4.18.2',
|
|
385
|
+
* // confidence: 100,
|
|
386
|
+
* // detectedFrom: [
|
|
387
|
+
* // { type: 'package.json', field: 'dependencies.express' },
|
|
388
|
+
* // { type: 'package.json', field: 'dependencies.@types/express' },
|
|
389
|
+
* // { type: 'package.json', field: 'dependencies (express middleware)' },
|
|
390
|
+
* // ],
|
|
391
|
+
* // }
|
|
392
|
+
* ```
|
|
993
393
|
*/
|
|
994
394
|
function expressDetector(projectPath, packageJson) {
|
|
995
395
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1006,7 +406,7 @@ function expressDetector(projectPath, packageJson) {
|
|
|
1006
406
|
confidence += 10;
|
|
1007
407
|
sources.push({ type: 'package.json', field: 'dependencies.@types/express' });
|
|
1008
408
|
}
|
|
1009
|
-
const expressMiddleware = keys(deps).filter((d) => d.includes('express-') || d === 'body-parser' || d === 'cors' || d === 'helmet' || d === 'morgan');
|
|
409
|
+
const expressMiddleware = index_cjs_js$2.keys(deps).filter((d) => d.includes('express-') || d === 'body-parser' || d === 'cors' || d === 'helmet' || d === 'morgan');
|
|
1010
410
|
if (expressMiddleware.length > 0) {
|
|
1011
411
|
confidence += 10;
|
|
1012
412
|
sources.push({ type: 'package.json', field: 'dependencies (express middleware)' });
|
|
@@ -1018,92 +418,117 @@ function expressDetector(projectPath, packageJson) {
|
|
|
1018
418
|
id: 'express',
|
|
1019
419
|
name: 'Express',
|
|
1020
420
|
version,
|
|
1021
|
-
confidence: min(confidence, 100),
|
|
421
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1022
422
|
detectedFrom: sources,
|
|
1023
423
|
};
|
|
1024
424
|
}
|
|
1025
425
|
|
|
1026
426
|
/**
|
|
1027
|
-
* Detect
|
|
427
|
+
* Detect Fastify in project.
|
|
1028
428
|
*
|
|
1029
429
|
* @param projectPath - Project directory path
|
|
1030
430
|
* @param packageJson - Optional pre-loaded package.json
|
|
1031
431
|
* @returns Detection result or null if not detected
|
|
432
|
+
* @example Detecting Fastify framework
|
|
433
|
+
* ```typescript
|
|
434
|
+
* const pkg = {
|
|
435
|
+
* dependencies: { fastify: '^4.24.0', '@fastify/cors': '^8.4.0' },
|
|
436
|
+
* }
|
|
437
|
+
*
|
|
438
|
+
* const result = fastifyDetector('/path/to/project', pkg)
|
|
439
|
+
* // => {
|
|
440
|
+
* // id: 'fastify',
|
|
441
|
+
* // name: 'Fastify',
|
|
442
|
+
* // version: '4.24.0',
|
|
443
|
+
* // confidence: 95,
|
|
444
|
+
* // detectedFrom: [
|
|
445
|
+
* // { type: 'package.json', field: 'dependencies.fastify' },
|
|
446
|
+
* // { type: 'package.json', field: 'dependencies (fastify plugins)' },
|
|
447
|
+
* // ],
|
|
448
|
+
* // }
|
|
449
|
+
* ```
|
|
1032
450
|
*/
|
|
1033
|
-
function
|
|
451
|
+
function fastifyDetector(projectPath, packageJson) {
|
|
1034
452
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1035
453
|
const sources = [];
|
|
1036
454
|
let confidence = 0;
|
|
1037
455
|
let version;
|
|
1038
|
-
let configPath;
|
|
1039
456
|
const deps = collectAllDependencies(pkg);
|
|
1040
|
-
if (deps['
|
|
1041
|
-
confidence +=
|
|
1042
|
-
version = parseVersionString(deps['
|
|
1043
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1044
|
-
}
|
|
1045
|
-
if (deps['@nestjs/common']) {
|
|
1046
|
-
confidence += 15;
|
|
1047
|
-
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
|
|
457
|
+
if (deps['fastify']) {
|
|
458
|
+
confidence += 80;
|
|
459
|
+
version = parseVersionString(deps['fastify']);
|
|
460
|
+
sources.push({ type: 'package.json', field: 'dependencies.fastify' });
|
|
1048
461
|
}
|
|
1049
|
-
|
|
462
|
+
const fastifyPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@fastify/') || d.startsWith('fastify-'));
|
|
463
|
+
if (fastifyPlugins.length > 0) {
|
|
1050
464
|
confidence += 15;
|
|
1051
|
-
|
|
1052
|
-
sources.push({ type: 'config-file', path: 'nest-cli.json' });
|
|
465
|
+
sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
|
|
1053
466
|
}
|
|
1054
|
-
|
|
1055
|
-
if (nestPackages.length > 2) {
|
|
467
|
+
if (deps['@types/fastify']) {
|
|
1056
468
|
confidence += 5;
|
|
1057
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
469
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
1058
470
|
}
|
|
1059
471
|
if (confidence === 0) {
|
|
1060
472
|
return null;
|
|
1061
473
|
}
|
|
1062
474
|
return {
|
|
1063
|
-
id: '
|
|
1064
|
-
name: '
|
|
475
|
+
id: 'fastify',
|
|
476
|
+
name: 'Fastify',
|
|
1065
477
|
version,
|
|
1066
|
-
|
|
1067
|
-
confidence: min(confidence, 100),
|
|
478
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1068
479
|
detectedFrom: sources,
|
|
1069
480
|
};
|
|
1070
481
|
}
|
|
1071
482
|
|
|
1072
483
|
/**
|
|
1073
|
-
* Detect
|
|
484
|
+
* Detect Hono in project.
|
|
1074
485
|
*
|
|
1075
486
|
* @param projectPath - Project directory path
|
|
1076
487
|
* @param packageJson - Optional pre-loaded package.json
|
|
1077
488
|
* @returns Detection result or null if not detected
|
|
489
|
+
* @example Detecting Hono framework
|
|
490
|
+
* ```typescript
|
|
491
|
+
* const pkg = {
|
|
492
|
+
* dependencies: { hono: '^3.11.0', '@hono/node-server': '^1.3.0' },
|
|
493
|
+
* }
|
|
494
|
+
*
|
|
495
|
+
* const result = honoDetector('/path/to/project', pkg)
|
|
496
|
+
* // => {
|
|
497
|
+
* // id: 'hono',
|
|
498
|
+
* // name: 'Hono',
|
|
499
|
+
* // version: '3.11.0',
|
|
500
|
+
* // confidence: 100,
|
|
501
|
+
* // detectedFrom: [
|
|
502
|
+
* // { type: 'package.json', field: 'dependencies.hono' },
|
|
503
|
+
* // { type: 'package.json', field: 'dependencies (@hono adapters)' },
|
|
504
|
+
* // ],
|
|
505
|
+
* // }
|
|
506
|
+
* ```
|
|
1078
507
|
*/
|
|
1079
|
-
function
|
|
508
|
+
function honoDetector(projectPath, packageJson) {
|
|
1080
509
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1081
510
|
const sources = [];
|
|
1082
511
|
let confidence = 0;
|
|
1083
512
|
let version;
|
|
1084
513
|
const deps = collectAllDependencies(pkg);
|
|
1085
|
-
if (deps['
|
|
1086
|
-
confidence +=
|
|
1087
|
-
version = parseVersionString(deps['
|
|
1088
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
514
|
+
if (deps['hono']) {
|
|
515
|
+
confidence += 85;
|
|
516
|
+
version = parseVersionString(deps['hono']);
|
|
517
|
+
sources.push({ type: 'package.json', field: 'dependencies.hono' });
|
|
1089
518
|
}
|
|
1090
|
-
const
|
|
1091
|
-
if (
|
|
519
|
+
const honoAdapters = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@hono/'));
|
|
520
|
+
if (honoAdapters.length > 0) {
|
|
1092
521
|
confidence += 15;
|
|
1093
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1094
|
-
}
|
|
1095
|
-
if (deps['@types/fastify']) {
|
|
1096
|
-
confidence += 5;
|
|
1097
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
522
|
+
sources.push({ type: 'package.json', field: 'dependencies (@hono adapters)' });
|
|
1098
523
|
}
|
|
1099
524
|
if (confidence === 0) {
|
|
1100
525
|
return null;
|
|
1101
526
|
}
|
|
1102
527
|
return {
|
|
1103
|
-
id: '
|
|
1104
|
-
name: '
|
|
528
|
+
id: 'hono',
|
|
529
|
+
name: 'Hono',
|
|
1105
530
|
version,
|
|
1106
|
-
confidence: min(confidence, 100),
|
|
531
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1107
532
|
detectedFrom: sources,
|
|
1108
533
|
};
|
|
1109
534
|
}
|
|
@@ -1114,6 +539,26 @@ function fastifyDetector(projectPath, packageJson) {
|
|
|
1114
539
|
* @param projectPath - Project directory path
|
|
1115
540
|
* @param packageJson - Optional pre-loaded package.json
|
|
1116
541
|
* @returns Detection result or null if not detected
|
|
542
|
+
* @example Detecting Koa framework
|
|
543
|
+
* ```typescript
|
|
544
|
+
* const pkg = {
|
|
545
|
+
* dependencies: { koa: '^2.14.2', 'koa-router': '^12.0.0' },
|
|
546
|
+
* devDependencies: { '@types/koa': '^2.13.9' },
|
|
547
|
+
* }
|
|
548
|
+
*
|
|
549
|
+
* const result = koaDetector('/path/to/project', pkg)
|
|
550
|
+
* // => {
|
|
551
|
+
* // id: 'koa',
|
|
552
|
+
* // name: 'Koa',
|
|
553
|
+
* // version: '2.14.2',
|
|
554
|
+
* // confidence: 100,
|
|
555
|
+
* // detectedFrom: [
|
|
556
|
+
* // { type: 'package.json', field: 'dependencies.koa' },
|
|
557
|
+
* // { type: 'package.json', field: 'dependencies.@types/koa' },
|
|
558
|
+
* // { type: 'package.json', field: 'dependencies (koa middleware)' },
|
|
559
|
+
* // ],
|
|
560
|
+
* // }
|
|
561
|
+
* ```
|
|
1117
562
|
*/
|
|
1118
563
|
function koaDetector(projectPath, packageJson) {
|
|
1119
564
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1130,7 +575,7 @@ function koaDetector(projectPath, packageJson) {
|
|
|
1130
575
|
confidence += 10;
|
|
1131
576
|
sources.push({ type: 'package.json', field: 'dependencies.@types/koa' });
|
|
1132
577
|
}
|
|
1133
|
-
const koaMiddleware = keys(deps).filter((d) => d.startsWith('koa-') || d.startsWith('@koa/'));
|
|
578
|
+
const koaMiddleware = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('koa-') || d.startsWith('@koa/'));
|
|
1134
579
|
if (koaMiddleware.length > 0) {
|
|
1135
580
|
confidence += 10;
|
|
1136
581
|
sources.push({ type: 'package.json', field: 'dependencies (koa middleware)' });
|
|
@@ -1142,42 +587,79 @@ function koaDetector(projectPath, packageJson) {
|
|
|
1142
587
|
id: 'koa',
|
|
1143
588
|
name: 'Koa',
|
|
1144
589
|
version,
|
|
1145
|
-
confidence: min(confidence, 100),
|
|
590
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1146
591
|
detectedFrom: sources,
|
|
1147
592
|
};
|
|
1148
593
|
}
|
|
1149
594
|
|
|
1150
595
|
/**
|
|
1151
|
-
* Detect
|
|
596
|
+
* Detect NestJS in project.
|
|
1152
597
|
*
|
|
1153
598
|
* @param projectPath - Project directory path
|
|
1154
599
|
* @param packageJson - Optional pre-loaded package.json
|
|
1155
600
|
* @returns Detection result or null if not detected
|
|
601
|
+
* @example Detecting NestJS framework
|
|
602
|
+
* ```typescript
|
|
603
|
+
* // Project with nest-cli.json and NestJS packages
|
|
604
|
+
* const pkg = {
|
|
605
|
+
* dependencies: {
|
|
606
|
+
* '@nestjs/core': '^10.2.0',
|
|
607
|
+
* '@nestjs/common': '^10.2.0',
|
|
608
|
+
* '@nestjs/platform-express': '^10.2.0',
|
|
609
|
+
* },
|
|
610
|
+
* }
|
|
611
|
+
*
|
|
612
|
+
* const result = nestDetector('/path/to/nest-project', pkg)
|
|
613
|
+
* // => {
|
|
614
|
+
* // id: 'nestjs',
|
|
615
|
+
* // name: 'NestJS',
|
|
616
|
+
* // version: '10.2.0',
|
|
617
|
+
* // configPath: 'nest-cli.json', // if present
|
|
618
|
+
* // confidence: 100,
|
|
619
|
+
* // detectedFrom: [
|
|
620
|
+
* // { type: 'package.json', field: 'dependencies.@nestjs/core' },
|
|
621
|
+
* // { type: 'package.json', field: 'dependencies.@nestjs/common' },
|
|
622
|
+
* // { type: 'config-file', path: 'nest-cli.json' },
|
|
623
|
+
* // { type: 'package.json', field: 'dependencies (@nestjs packages)' },
|
|
624
|
+
* // ],
|
|
625
|
+
* // }
|
|
626
|
+
* ```
|
|
1156
627
|
*/
|
|
1157
|
-
function
|
|
628
|
+
function nestDetector(projectPath, packageJson) {
|
|
1158
629
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1159
630
|
const sources = [];
|
|
1160
631
|
let confidence = 0;
|
|
1161
632
|
let version;
|
|
633
|
+
let configPath;
|
|
1162
634
|
const deps = collectAllDependencies(pkg);
|
|
1163
|
-
if (deps['
|
|
1164
|
-
confidence +=
|
|
1165
|
-
version = parseVersionString(deps['
|
|
1166
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
635
|
+
if (deps['@nestjs/core']) {
|
|
636
|
+
confidence += 70;
|
|
637
|
+
version = parseVersionString(deps['@nestjs/core']);
|
|
638
|
+
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
|
|
1167
639
|
}
|
|
1168
|
-
|
|
1169
|
-
if (honoAdapters.length > 0) {
|
|
640
|
+
if (deps['@nestjs/common']) {
|
|
1170
641
|
confidence += 15;
|
|
1171
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
642
|
+
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
|
|
643
|
+
}
|
|
644
|
+
if (exists(node_path.join(projectPath, 'nest-cli.json'))) {
|
|
645
|
+
confidence += 15;
|
|
646
|
+
configPath = 'nest-cli.json';
|
|
647
|
+
sources.push({ type: 'config-file', path: 'nest-cli.json' });
|
|
648
|
+
}
|
|
649
|
+
const nestPackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@nestjs/'));
|
|
650
|
+
if (nestPackages.length > 2) {
|
|
651
|
+
confidence += 5;
|
|
652
|
+
sources.push({ type: 'package.json', field: 'dependencies (@nestjs packages)' });
|
|
1172
653
|
}
|
|
1173
654
|
if (confidence === 0) {
|
|
1174
655
|
return null;
|
|
1175
656
|
}
|
|
1176
657
|
return {
|
|
1177
|
-
id: '
|
|
1178
|
-
name: '
|
|
658
|
+
id: 'nestjs',
|
|
659
|
+
name: 'NestJS',
|
|
1179
660
|
version,
|
|
1180
|
-
|
|
661
|
+
configPath,
|
|
662
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1181
663
|
detectedFrom: sources,
|
|
1182
664
|
};
|
|
1183
665
|
}
|
|
@@ -1196,6 +678,19 @@ const backendDetectors = [
|
|
|
1196
678
|
* @param projectPath - Project directory path
|
|
1197
679
|
* @param packageJson - Optional pre-loaded package.json
|
|
1198
680
|
* @returns Array of detected frameworks, sorted by confidence
|
|
681
|
+
* @example Detecting multiple backend frameworks
|
|
682
|
+
* ```typescript
|
|
683
|
+
* const pkg = {
|
|
684
|
+
* dependencies: { '@nestjs/core': '^10.0.0', '@nestjs/common': '^10.0.0' },
|
|
685
|
+
* devDependencies: { express: '^4.18.0' },
|
|
686
|
+
* }
|
|
687
|
+
*
|
|
688
|
+
* const results = detectBackendFrameworks('/path/to/project', pkg)
|
|
689
|
+
* // => [
|
|
690
|
+
* // { id: 'nestjs', name: 'NestJS', confidence: 85, ... },
|
|
691
|
+
* // { id: 'express', name: 'Express', confidence: 80, ... },
|
|
692
|
+
* // ]
|
|
693
|
+
* ```
|
|
1199
694
|
*/
|
|
1200
695
|
function detectBackendFrameworks(projectPath, packageJson) {
|
|
1201
696
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1209,102 +704,194 @@ function detectBackendFrameworks(projectPath, packageJson) {
|
|
|
1209
704
|
return results.sort((a, b) => b.confidence - a.confidence);
|
|
1210
705
|
}
|
|
1211
706
|
|
|
1212
|
-
/** Config patterns for
|
|
1213
|
-
const
|
|
1214
|
-
'webpack.config.js',
|
|
1215
|
-
'webpack.config.ts',
|
|
1216
|
-
'webpack.config.cjs',
|
|
1217
|
-
'webpack.config.mjs',
|
|
1218
|
-
'webpack.config.babel.js',
|
|
1219
|
-
];
|
|
707
|
+
/** Config patterns for Babel */
|
|
708
|
+
const BABEL_CONFIG_PATTERNS = ['babel.config.js', 'babel.config.cjs', 'babel.config.mjs', 'babel.config.json', '.babelrc', '.babelrc.json', '.babelrc.js'];
|
|
1220
709
|
/**
|
|
1221
|
-
* Detect
|
|
710
|
+
* Detect Babel in project.
|
|
1222
711
|
*
|
|
1223
712
|
* @param projectPath - Project directory path
|
|
1224
713
|
* @param packageJson - Optional pre-loaded package.json
|
|
1225
714
|
* @returns Detection result or null if not detected
|
|
715
|
+
*
|
|
716
|
+
* @example Detecting Babel compiler
|
|
717
|
+
* ```typescript
|
|
718
|
+
* const result = babelDetector('/path/to/project', {
|
|
719
|
+
* name: 'my-app',
|
|
720
|
+
* devDependencies: { '@babel/core': '^7.23.0', '@babel/preset-env': '^7.23.0' }
|
|
721
|
+
* })
|
|
722
|
+
* // => {
|
|
723
|
+
* // id: 'babel',
|
|
724
|
+
* // name: 'Babel',
|
|
725
|
+
* // version: '7.23.0',
|
|
726
|
+
* // confidence: 60,
|
|
727
|
+
* // detectedFrom: [
|
|
728
|
+
* // { type: 'package.json', field: 'dependencies.@babel/core' },
|
|
729
|
+
* // { type: 'package.json', field: 'dependencies (@babel packages)' }
|
|
730
|
+
* // ]
|
|
731
|
+
* // }
|
|
732
|
+
* ```
|
|
1226
733
|
*/
|
|
1227
|
-
function
|
|
734
|
+
function babelDetector(projectPath, packageJson) {
|
|
1228
735
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1229
736
|
const sources = [];
|
|
1230
737
|
let confidence = 0;
|
|
1231
738
|
let version;
|
|
1232
739
|
const deps = collectAllDependencies(pkg);
|
|
1233
|
-
if (deps['
|
|
740
|
+
if (deps['@babel/core']) {
|
|
1234
741
|
confidence += 50;
|
|
1235
|
-
version = parseVersionString(deps['
|
|
1236
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
742
|
+
version = parseVersionString(deps['@babel/core']);
|
|
743
|
+
sources.push({ type: 'package.json', field: 'dependencies.@babel/core' });
|
|
1237
744
|
}
|
|
1238
|
-
const configPath = locateConfigFile(projectPath,
|
|
745
|
+
const configPath = locateConfigFile(projectPath, BABEL_CONFIG_PATTERNS);
|
|
1239
746
|
if (configPath) {
|
|
1240
747
|
confidence += 40;
|
|
1241
748
|
sources.push({ type: 'config-file', path: configPath });
|
|
1242
749
|
}
|
|
1243
|
-
if (
|
|
750
|
+
if (pkg && 'babel' in pkg) {
|
|
751
|
+
confidence += 30;
|
|
752
|
+
sources.push({ type: 'package.json', field: 'babel' });
|
|
753
|
+
}
|
|
754
|
+
const babelPackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
755
|
+
if (babelPackages.length > 1) {
|
|
1244
756
|
confidence += 10;
|
|
1245
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
757
|
+
sources.push({ type: 'package.json', field: 'dependencies (@babel packages)' });
|
|
1246
758
|
}
|
|
1247
|
-
|
|
759
|
+
if (confidence === 0) {
|
|
760
|
+
return null;
|
|
761
|
+
}
|
|
762
|
+
return {
|
|
763
|
+
id: 'babel',
|
|
764
|
+
name: 'Babel',
|
|
765
|
+
version,
|
|
766
|
+
configPath,
|
|
767
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
768
|
+
detectedFrom: sources,
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Detect esbuild in project.
|
|
774
|
+
*
|
|
775
|
+
* @param projectPath - Project directory path
|
|
776
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
777
|
+
* @returns Detection result or null if not detected
|
|
778
|
+
*
|
|
779
|
+
* @example Detecting esbuild bundler
|
|
780
|
+
* ```typescript
|
|
781
|
+
* const result = esbuildDetector('/path/to/project', {
|
|
782
|
+
* name: 'my-lib',
|
|
783
|
+
* devDependencies: { 'esbuild': '^0.19.0' },
|
|
784
|
+
* scripts: { 'build': 'esbuild src/index.ts --bundle --outfile=dist/index.js' }
|
|
785
|
+
* })
|
|
786
|
+
* // => {
|
|
787
|
+
* // id: 'esbuild',
|
|
788
|
+
* // name: 'esbuild',
|
|
789
|
+
* // version: '0.19.0',
|
|
790
|
+
* // confidence: 80,
|
|
791
|
+
* // detectedFrom: [
|
|
792
|
+
* // { type: 'package.json', field: 'dependencies.esbuild' },
|
|
793
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
794
|
+
* // ]
|
|
795
|
+
* // }
|
|
796
|
+
* ```
|
|
797
|
+
*/
|
|
798
|
+
function esbuildDetector(projectPath, packageJson) {
|
|
799
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
800
|
+
const sources = [];
|
|
801
|
+
let confidence = 0;
|
|
802
|
+
let version;
|
|
803
|
+
const deps = collectAllDependencies(pkg);
|
|
804
|
+
if (deps['esbuild']) {
|
|
805
|
+
confidence += 70;
|
|
806
|
+
version = parseVersionString(deps['esbuild']);
|
|
807
|
+
sources.push({ type: 'package.json', field: 'dependencies.esbuild' });
|
|
808
|
+
}
|
|
809
|
+
const esbuildPlugins = index_cjs_js$2.keys(deps).filter((d) => d.includes('esbuild-plugin') || d.includes('esbuild-'));
|
|
810
|
+
if (esbuildPlugins.length > 0) {
|
|
811
|
+
confidence += 15;
|
|
812
|
+
sources.push({ type: 'package.json', field: 'dependencies (esbuild plugins)' });
|
|
813
|
+
}
|
|
814
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'esbuild');
|
|
1248
815
|
for (const name of scriptMatches) {
|
|
1249
|
-
confidence = min(confidence +
|
|
816
|
+
confidence = index_cjs_js$8.min(confidence + 10, 100);
|
|
1250
817
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1251
818
|
}
|
|
1252
819
|
if (confidence === 0) {
|
|
1253
820
|
return null;
|
|
1254
821
|
}
|
|
1255
822
|
return {
|
|
1256
|
-
id: '
|
|
1257
|
-
name: '
|
|
823
|
+
id: 'esbuild',
|
|
824
|
+
name: 'esbuild',
|
|
1258
825
|
version,
|
|
1259
|
-
|
|
1260
|
-
confidence: min(confidence, 100),
|
|
826
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1261
827
|
detectedFrom: sources,
|
|
1262
828
|
};
|
|
1263
829
|
}
|
|
1264
830
|
|
|
1265
|
-
/** Config patterns for
|
|
1266
|
-
const
|
|
831
|
+
/** Config patterns for Parcel */
|
|
832
|
+
const PARCEL_CONFIG_PATTERNS = ['.parcelrc'];
|
|
1267
833
|
/**
|
|
1268
|
-
* Detect
|
|
834
|
+
* Detect Parcel in project.
|
|
1269
835
|
*
|
|
1270
836
|
* @param projectPath - Project directory path
|
|
1271
837
|
* @param packageJson - Optional pre-loaded package.json
|
|
1272
838
|
* @returns Detection result or null if not detected
|
|
839
|
+
*
|
|
840
|
+
* @example Detecting Parcel bundler
|
|
841
|
+
* ```typescript
|
|
842
|
+
* const result = parcelDetector('/path/to/project', {
|
|
843
|
+
* name: 'my-app',
|
|
844
|
+
* devDependencies: { 'parcel': '^2.10.0' },
|
|
845
|
+
* scripts: { 'dev': 'parcel src/index.html', 'build': 'parcel build src/index.html' }
|
|
846
|
+
* })
|
|
847
|
+
* // => {
|
|
848
|
+
* // id: 'parcel',
|
|
849
|
+
* // name: 'Parcel',
|
|
850
|
+
* // version: '2.10.0',
|
|
851
|
+
* // confidence: 80,
|
|
852
|
+
* // detectedFrom: [
|
|
853
|
+
* // { type: 'package.json', field: 'dependencies.parcel' },
|
|
854
|
+
* // { type: 'package.json', field: 'scripts.dev' },
|
|
855
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
856
|
+
* // ]
|
|
857
|
+
* // }
|
|
858
|
+
* ```
|
|
1273
859
|
*/
|
|
1274
|
-
function
|
|
860
|
+
function parcelDetector(projectPath, packageJson) {
|
|
1275
861
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1276
862
|
const sources = [];
|
|
1277
863
|
let confidence = 0;
|
|
1278
864
|
let version;
|
|
1279
865
|
const deps = collectAllDependencies(pkg);
|
|
1280
|
-
if (deps['
|
|
866
|
+
if (deps['parcel']) {
|
|
1281
867
|
confidence += 60;
|
|
1282
|
-
version = parseVersionString(deps['
|
|
1283
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
868
|
+
version = parseVersionString(deps['parcel']);
|
|
869
|
+
sources.push({ type: 'package.json', field: 'dependencies.parcel' });
|
|
1284
870
|
}
|
|
1285
|
-
|
|
871
|
+
if (deps['parcel-bundler']) {
|
|
872
|
+
confidence += 60;
|
|
873
|
+
version = parseVersionString(deps['parcel-bundler']);
|
|
874
|
+
sources.push({ type: 'package.json', field: 'dependencies.parcel-bundler' });
|
|
875
|
+
}
|
|
876
|
+
const configPath = locateConfigFile(projectPath, PARCEL_CONFIG_PATTERNS);
|
|
1286
877
|
if (configPath) {
|
|
1287
|
-
confidence +=
|
|
878
|
+
confidence += 30;
|
|
1288
879
|
sources.push({ type: 'config-file', path: configPath });
|
|
1289
880
|
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
const vitePlugins = keys(deps).filter((d) => d.startsWith('vite-plugin-') || d.startsWith('@vitejs/'));
|
|
1295
|
-
if (vitePlugins.length > 0) {
|
|
1296
|
-
confidence += 10;
|
|
1297
|
-
sources.push({ type: 'package.json', field: 'dependencies (vite plugins)' });
|
|
881
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'parcel');
|
|
882
|
+
for (const name of scriptMatches) {
|
|
883
|
+
confidence = index_cjs_js$8.min(confidence + 10, 100);
|
|
884
|
+
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1298
885
|
}
|
|
1299
886
|
if (confidence === 0) {
|
|
1300
887
|
return null;
|
|
1301
888
|
}
|
|
1302
889
|
return {
|
|
1303
|
-
id: '
|
|
1304
|
-
name: '
|
|
890
|
+
id: 'parcel',
|
|
891
|
+
name: 'Parcel',
|
|
1305
892
|
version,
|
|
1306
893
|
configPath,
|
|
1307
|
-
confidence: min(confidence, 100),
|
|
894
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1308
895
|
detectedFrom: sources,
|
|
1309
896
|
};
|
|
1310
897
|
}
|
|
@@ -1317,6 +904,28 @@ const ROLLUP_CONFIG_PATTERNS = ['rollup.config.js', 'rollup.config.ts', 'rollup.
|
|
|
1317
904
|
* @param projectPath - Project directory path
|
|
1318
905
|
* @param packageJson - Optional pre-loaded package.json
|
|
1319
906
|
* @returns Detection result or null if not detected
|
|
907
|
+
*
|
|
908
|
+
* @example Detecting Rollup bundler
|
|
909
|
+
* ```typescript
|
|
910
|
+
* const result = rollupDetector('/path/to/project', {
|
|
911
|
+
* name: 'my-lib',
|
|
912
|
+
* devDependencies: {
|
|
913
|
+
* 'rollup': '^4.0.0',
|
|
914
|
+
* '@rollup/plugin-node-resolve': '^15.0.0',
|
|
915
|
+
* '@rollup/plugin-commonjs': '^25.0.0'
|
|
916
|
+
* }
|
|
917
|
+
* })
|
|
918
|
+
* // => {
|
|
919
|
+
* // id: 'rollup',
|
|
920
|
+
* // name: 'Rollup',
|
|
921
|
+
* // version: '4.0.0',
|
|
922
|
+
* // confidence: 65,
|
|
923
|
+
* // detectedFrom: [
|
|
924
|
+
* // { type: 'package.json', field: 'dependencies.rollup' },
|
|
925
|
+
* // { type: 'package.json', field: 'dependencies (rollup plugins)' }
|
|
926
|
+
* // ]
|
|
927
|
+
* // }
|
|
928
|
+
* ```
|
|
1320
929
|
*/
|
|
1321
930
|
function rollupDetector(projectPath, packageJson) {
|
|
1322
931
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1334,14 +943,14 @@ function rollupDetector(projectPath, packageJson) {
|
|
|
1334
943
|
confidence += 40;
|
|
1335
944
|
sources.push({ type: 'config-file', path: configPath });
|
|
1336
945
|
}
|
|
1337
|
-
const rollupPlugins = keys(deps).filter((d) => d.startsWith('@rollup/') || d.startsWith('rollup-plugin-'));
|
|
946
|
+
const rollupPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@rollup/') || d.startsWith('rollup-plugin-'));
|
|
1338
947
|
if (rollupPlugins.length > 0) {
|
|
1339
948
|
confidence += 10;
|
|
1340
949
|
sources.push({ type: 'package.json', field: 'dependencies (rollup plugins)' });
|
|
1341
950
|
}
|
|
1342
951
|
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'rollup');
|
|
1343
952
|
for (const name of scriptMatches) {
|
|
1344
|
-
confidence = min(confidence + 5, 100);
|
|
953
|
+
confidence = index_cjs_js$8.min(confidence + 5, 100);
|
|
1345
954
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1346
955
|
}
|
|
1347
956
|
if (confidence === 0) {
|
|
@@ -1352,189 +961,215 @@ function rollupDetector(projectPath, packageJson) {
|
|
|
1352
961
|
name: 'Rollup',
|
|
1353
962
|
version,
|
|
1354
963
|
configPath,
|
|
1355
|
-
confidence: min(confidence, 100),
|
|
964
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1356
965
|
detectedFrom: sources,
|
|
1357
966
|
};
|
|
1358
967
|
}
|
|
1359
968
|
|
|
969
|
+
/** Config patterns for SWC */
|
|
970
|
+
const SWC_CONFIG_PATTERNS = ['.swcrc', 'swc.config.js'];
|
|
1360
971
|
/**
|
|
1361
|
-
* Detect
|
|
972
|
+
* Detect SWC in project.
|
|
1362
973
|
*
|
|
1363
974
|
* @param projectPath - Project directory path
|
|
1364
975
|
* @param packageJson - Optional pre-loaded package.json
|
|
1365
976
|
* @returns Detection result or null if not detected
|
|
1366
|
-
*/
|
|
1367
|
-
function esbuildDetector(projectPath, packageJson) {
|
|
1368
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1369
|
-
const sources = [];
|
|
1370
|
-
let confidence = 0;
|
|
1371
|
-
let version;
|
|
1372
|
-
const deps = collectAllDependencies(pkg);
|
|
1373
|
-
if (deps['esbuild']) {
|
|
1374
|
-
confidence += 70;
|
|
1375
|
-
version = parseVersionString(deps['esbuild']);
|
|
1376
|
-
sources.push({ type: 'package.json', field: 'dependencies.esbuild' });
|
|
1377
|
-
}
|
|
1378
|
-
const esbuildPlugins = keys(deps).filter((d) => d.includes('esbuild-plugin') || d.includes('esbuild-'));
|
|
1379
|
-
if (esbuildPlugins.length > 0) {
|
|
1380
|
-
confidence += 15;
|
|
1381
|
-
sources.push({ type: 'package.json', field: 'dependencies (esbuild plugins)' });
|
|
1382
|
-
}
|
|
1383
|
-
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'esbuild');
|
|
1384
|
-
for (const name of scriptMatches) {
|
|
1385
|
-
confidence = min(confidence + 10, 100);
|
|
1386
|
-
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1387
|
-
}
|
|
1388
|
-
if (confidence === 0) {
|
|
1389
|
-
return null;
|
|
1390
|
-
}
|
|
1391
|
-
return {
|
|
1392
|
-
id: 'esbuild',
|
|
1393
|
-
name: 'esbuild',
|
|
1394
|
-
version,
|
|
1395
|
-
confidence: min(confidence, 100),
|
|
1396
|
-
detectedFrom: sources,
|
|
1397
|
-
};
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
/** Config patterns for Babel */
|
|
1401
|
-
const BABEL_CONFIG_PATTERNS = ['babel.config.js', 'babel.config.cjs', 'babel.config.mjs', 'babel.config.json', '.babelrc', '.babelrc.json', '.babelrc.js'];
|
|
1402
|
-
/**
|
|
1403
|
-
* Detect Babel in project.
|
|
1404
977
|
*
|
|
1405
|
-
* @
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
978
|
+
* @example Detecting SWC compiler
|
|
979
|
+
* ```typescript
|
|
980
|
+
* const result = swcDetector('/path/to/project', {
|
|
981
|
+
* name: 'my-app',
|
|
982
|
+
* devDependencies: { '@swc/core': '^1.3.0', '@swc/cli': '^0.1.0' }
|
|
983
|
+
* })
|
|
984
|
+
* // => {
|
|
985
|
+
* // id: 'swc',
|
|
986
|
+
* // name: 'SWC',
|
|
987
|
+
* // version: '1.3.0',
|
|
988
|
+
* // confidence: 70,
|
|
989
|
+
* // detectedFrom: [
|
|
990
|
+
* // { type: 'package.json', field: 'dependencies.@swc/core' },
|
|
991
|
+
* // { type: 'package.json', field: 'dependencies.@swc/cli' }
|
|
992
|
+
* // ]
|
|
993
|
+
* // }
|
|
994
|
+
* ```
|
|
1408
995
|
*/
|
|
1409
|
-
function
|
|
996
|
+
function swcDetector(projectPath, packageJson) {
|
|
1410
997
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1411
998
|
const sources = [];
|
|
1412
999
|
let confidence = 0;
|
|
1413
1000
|
let version;
|
|
1414
1001
|
const deps = collectAllDependencies(pkg);
|
|
1415
|
-
if (deps['@
|
|
1416
|
-
confidence +=
|
|
1417
|
-
version = parseVersionString(deps['@
|
|
1418
|
-
sources.push({ type: 'package.json', field: 'dependencies.@
|
|
1002
|
+
if (deps['@swc/core']) {
|
|
1003
|
+
confidence += 60;
|
|
1004
|
+
version = parseVersionString(deps['@swc/core']);
|
|
1005
|
+
sources.push({ type: 'package.json', field: 'dependencies.@swc/core' });
|
|
1419
1006
|
}
|
|
1420
|
-
const configPath = locateConfigFile(projectPath,
|
|
1007
|
+
const configPath = locateConfigFile(projectPath, SWC_CONFIG_PATTERNS);
|
|
1421
1008
|
if (configPath) {
|
|
1422
|
-
confidence +=
|
|
1009
|
+
confidence += 35;
|
|
1423
1010
|
sources.push({ type: 'config-file', path: configPath });
|
|
1424
1011
|
}
|
|
1425
|
-
if (
|
|
1426
|
-
confidence += 30;
|
|
1427
|
-
sources.push({ type: 'package.json', field: 'babel' });
|
|
1428
|
-
}
|
|
1429
|
-
const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
1430
|
-
if (babelPackages.length > 1) {
|
|
1012
|
+
if (deps['@swc/cli']) {
|
|
1431
1013
|
confidence += 10;
|
|
1432
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1014
|
+
sources.push({ type: 'package.json', field: 'dependencies.@swc/cli' });
|
|
1015
|
+
}
|
|
1016
|
+
const swcPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@swc/') || d.includes('swc-plugin'));
|
|
1017
|
+
if (swcPlugins.length > 1) {
|
|
1018
|
+
confidence += 5;
|
|
1019
|
+
sources.push({ type: 'package.json', field: 'dependencies (@swc packages)' });
|
|
1433
1020
|
}
|
|
1434
1021
|
if (confidence === 0) {
|
|
1435
1022
|
return null;
|
|
1436
1023
|
}
|
|
1437
1024
|
return {
|
|
1438
|
-
id: '
|
|
1439
|
-
name: '
|
|
1025
|
+
id: 'swc',
|
|
1026
|
+
name: 'SWC',
|
|
1440
1027
|
version,
|
|
1441
1028
|
configPath,
|
|
1442
|
-
confidence: min(confidence, 100),
|
|
1029
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1443
1030
|
detectedFrom: sources,
|
|
1444
1031
|
};
|
|
1445
1032
|
}
|
|
1446
1033
|
|
|
1447
|
-
/** Config patterns for
|
|
1448
|
-
const
|
|
1034
|
+
/** Config patterns for Vite */
|
|
1035
|
+
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
1449
1036
|
/**
|
|
1450
|
-
* Detect
|
|
1037
|
+
* Detect Vite in project.
|
|
1451
1038
|
*
|
|
1452
1039
|
* @param projectPath - Project directory path
|
|
1453
1040
|
* @param packageJson - Optional pre-loaded package.json
|
|
1454
1041
|
* @returns Detection result or null if not detected
|
|
1042
|
+
*
|
|
1043
|
+
* @example Detecting Vite build tool
|
|
1044
|
+
* ```typescript
|
|
1045
|
+
* const result = viteDetector('/path/to/project', {
|
|
1046
|
+
* name: 'my-app',
|
|
1047
|
+
* devDependencies: {
|
|
1048
|
+
* 'vite': '^5.0.0',
|
|
1049
|
+
* '@vitejs/plugin-react': '^4.0.0',
|
|
1050
|
+
* 'vitest': '^1.0.0'
|
|
1051
|
+
* }
|
|
1052
|
+
* })
|
|
1053
|
+
* // => {
|
|
1054
|
+
* // id: 'vite',
|
|
1055
|
+
* // name: 'Vite',
|
|
1056
|
+
* // version: '5.0.0',
|
|
1057
|
+
* // confidence: 80,
|
|
1058
|
+
* // detectedFrom: [
|
|
1059
|
+
* // { type: 'package.json', field: 'dependencies.vite' },
|
|
1060
|
+
* // { type: 'package.json', field: 'dependencies.vitest' },
|
|
1061
|
+
* // { type: 'package.json', field: 'dependencies (vite plugins)' }
|
|
1062
|
+
* // ]
|
|
1063
|
+
* // }
|
|
1064
|
+
* ```
|
|
1455
1065
|
*/
|
|
1456
|
-
function
|
|
1066
|
+
function viteDetector(projectPath, packageJson) {
|
|
1457
1067
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1458
1068
|
const sources = [];
|
|
1459
1069
|
let confidence = 0;
|
|
1460
1070
|
let version;
|
|
1461
1071
|
const deps = collectAllDependencies(pkg);
|
|
1462
|
-
if (deps['
|
|
1072
|
+
if (deps['vite']) {
|
|
1463
1073
|
confidence += 60;
|
|
1464
|
-
version = parseVersionString(deps['
|
|
1465
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1074
|
+
version = parseVersionString(deps['vite']);
|
|
1075
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite' });
|
|
1466
1076
|
}
|
|
1467
|
-
const configPath = locateConfigFile(projectPath,
|
|
1077
|
+
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
1468
1078
|
if (configPath) {
|
|
1469
1079
|
confidence += 35;
|
|
1470
1080
|
sources.push({ type: 'config-file', path: configPath });
|
|
1471
1081
|
}
|
|
1472
|
-
if (deps['
|
|
1082
|
+
if (deps['vitest']) {
|
|
1473
1083
|
confidence += 10;
|
|
1474
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1084
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
1475
1085
|
}
|
|
1476
|
-
const
|
|
1477
|
-
if (
|
|
1478
|
-
confidence +=
|
|
1479
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1086
|
+
const vitePlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('vite-plugin-') || d.startsWith('@vitejs/'));
|
|
1087
|
+
if (vitePlugins.length > 0) {
|
|
1088
|
+
confidence += 10;
|
|
1089
|
+
sources.push({ type: 'package.json', field: 'dependencies (vite plugins)' });
|
|
1480
1090
|
}
|
|
1481
1091
|
if (confidence === 0) {
|
|
1482
1092
|
return null;
|
|
1483
1093
|
}
|
|
1484
1094
|
return {
|
|
1485
|
-
id: '
|
|
1486
|
-
name: '
|
|
1095
|
+
id: 'vite',
|
|
1096
|
+
name: 'Vite',
|
|
1487
1097
|
version,
|
|
1488
1098
|
configPath,
|
|
1489
|
-
confidence: min(confidence, 100),
|
|
1099
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1490
1100
|
detectedFrom: sources,
|
|
1491
1101
|
};
|
|
1492
1102
|
}
|
|
1493
1103
|
|
|
1494
|
-
/** Config patterns for
|
|
1495
|
-
const
|
|
1104
|
+
/** Config patterns for Webpack */
|
|
1105
|
+
const WEBPACK_CONFIG_PATTERNS = [
|
|
1106
|
+
'webpack.config.js',
|
|
1107
|
+
'webpack.config.ts',
|
|
1108
|
+
'webpack.config.cjs',
|
|
1109
|
+
'webpack.config.mjs',
|
|
1110
|
+
'webpack.config.babel.js',
|
|
1111
|
+
];
|
|
1496
1112
|
/**
|
|
1497
|
-
* Detect
|
|
1113
|
+
* Detect Webpack in project.
|
|
1498
1114
|
*
|
|
1499
1115
|
* @param projectPath - Project directory path
|
|
1500
1116
|
* @param packageJson - Optional pre-loaded package.json
|
|
1501
1117
|
* @returns Detection result or null if not detected
|
|
1118
|
+
*
|
|
1119
|
+
* @example Detecting Webpack bundler
|
|
1120
|
+
* ```typescript
|
|
1121
|
+
* const result = webpackDetector('/path/to/project', {
|
|
1122
|
+
* name: 'my-app',
|
|
1123
|
+
* devDependencies: { 'webpack': '^5.89.0', 'webpack-cli': '^5.1.0' },
|
|
1124
|
+
* scripts: { 'build': 'webpack --mode production' }
|
|
1125
|
+
* })
|
|
1126
|
+
* // => {
|
|
1127
|
+
* // id: 'webpack',
|
|
1128
|
+
* // name: 'Webpack',
|
|
1129
|
+
* // version: '5.89.0',
|
|
1130
|
+
* // confidence: 65,
|
|
1131
|
+
* // detectedFrom: [
|
|
1132
|
+
* // { type: 'package.json', field: 'dependencies.webpack' },
|
|
1133
|
+
* // { type: 'package.json', field: 'dependencies.webpack-cli' },
|
|
1134
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
1135
|
+
* // ]
|
|
1136
|
+
* // }
|
|
1137
|
+
* ```
|
|
1502
1138
|
*/
|
|
1503
|
-
function
|
|
1139
|
+
function webpackDetector(projectPath, packageJson) {
|
|
1504
1140
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1505
1141
|
const sources = [];
|
|
1506
1142
|
let confidence = 0;
|
|
1507
1143
|
let version;
|
|
1508
1144
|
const deps = collectAllDependencies(pkg);
|
|
1509
|
-
if (deps['
|
|
1510
|
-
confidence +=
|
|
1511
|
-
version = parseVersionString(deps['
|
|
1512
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1513
|
-
}
|
|
1514
|
-
if (deps['parcel-bundler']) {
|
|
1515
|
-
confidence += 60;
|
|
1516
|
-
version = parseVersionString(deps['parcel-bundler']);
|
|
1517
|
-
sources.push({ type: 'package.json', field: 'dependencies.parcel-bundler' });
|
|
1145
|
+
if (deps['webpack']) {
|
|
1146
|
+
confidence += 50;
|
|
1147
|
+
version = parseVersionString(deps['webpack']);
|
|
1148
|
+
sources.push({ type: 'package.json', field: 'dependencies.webpack' });
|
|
1518
1149
|
}
|
|
1519
|
-
const configPath = locateConfigFile(projectPath,
|
|
1150
|
+
const configPath = locateConfigFile(projectPath, WEBPACK_CONFIG_PATTERNS);
|
|
1520
1151
|
if (configPath) {
|
|
1521
|
-
confidence +=
|
|
1152
|
+
confidence += 40;
|
|
1522
1153
|
sources.push({ type: 'config-file', path: configPath });
|
|
1523
1154
|
}
|
|
1524
|
-
|
|
1155
|
+
if (deps['webpack-cli']) {
|
|
1156
|
+
confidence += 10;
|
|
1157
|
+
sources.push({ type: 'package.json', field: 'dependencies.webpack-cli' });
|
|
1158
|
+
}
|
|
1159
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'webpack');
|
|
1525
1160
|
for (const name of scriptMatches) {
|
|
1526
|
-
confidence = min(confidence +
|
|
1161
|
+
confidence = index_cjs_js$8.min(confidence + 5, 100);
|
|
1527
1162
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1528
1163
|
}
|
|
1529
1164
|
if (confidence === 0) {
|
|
1530
1165
|
return null;
|
|
1531
1166
|
}
|
|
1532
1167
|
return {
|
|
1533
|
-
id: '
|
|
1534
|
-
name: '
|
|
1168
|
+
id: 'webpack',
|
|
1169
|
+
name: 'Webpack',
|
|
1535
1170
|
version,
|
|
1536
1171
|
configPath,
|
|
1537
|
-
confidence: min(confidence, 100),
|
|
1172
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1538
1173
|
detectedFrom: sources,
|
|
1539
1174
|
};
|
|
1540
1175
|
}
|
|
@@ -1555,6 +1190,22 @@ const buildToolDetectors = [
|
|
|
1555
1190
|
* @param projectPath - Project directory path
|
|
1556
1191
|
* @param packageJson - Optional pre-loaded package.json
|
|
1557
1192
|
* @returns Array of detected build tools, sorted by confidence
|
|
1193
|
+
*
|
|
1194
|
+
* @example Detecting multiple build tools
|
|
1195
|
+
* ```typescript
|
|
1196
|
+
* const tools = detectBuildTools('/path/to/project', {
|
|
1197
|
+
* name: 'my-app',
|
|
1198
|
+
* devDependencies: {
|
|
1199
|
+
* 'vite': '^5.0.0',
|
|
1200
|
+
* '@vitejs/plugin-react': '^4.0.0',
|
|
1201
|
+
* '@babel/core': '^7.23.0'
|
|
1202
|
+
* }
|
|
1203
|
+
* })
|
|
1204
|
+
* // => [
|
|
1205
|
+
* // { id: 'vite', name: 'Vite', version: '5.0.0', confidence: 70, ... },
|
|
1206
|
+
* // { id: 'babel', name: 'Babel', version: '7.23.0', confidence: 50, ... }
|
|
1207
|
+
* // ]
|
|
1208
|
+
* ```
|
|
1558
1209
|
*/
|
|
1559
1210
|
function detectBuildTools(projectPath, packageJson) {
|
|
1560
1211
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1569,81 +1220,187 @@ function detectBuildTools(projectPath, packageJson) {
|
|
|
1569
1220
|
}
|
|
1570
1221
|
|
|
1571
1222
|
/**
|
|
1572
|
-
* Detect
|
|
1223
|
+
* Detect Angular in project.
|
|
1573
1224
|
*
|
|
1574
1225
|
* @param projectPath - Project directory path
|
|
1575
1226
|
* @param packageJson - Optional pre-loaded package.json
|
|
1576
1227
|
* @returns Detection result or null if not detected
|
|
1228
|
+
*
|
|
1229
|
+
* @example Detecting Angular framework
|
|
1230
|
+
* ```typescript
|
|
1231
|
+
* const result = angularDetector('/path/to/angular-app', {
|
|
1232
|
+
* dependencies: { '@angular/core': '^17.0.0', '@angular/cli': '^17.0.0' }
|
|
1233
|
+
* })
|
|
1234
|
+
* // => {
|
|
1235
|
+
* // id: 'angular',
|
|
1236
|
+
* // name: 'Angular',
|
|
1237
|
+
* // category: 'frontend',
|
|
1238
|
+
* // version: '17.0.0',
|
|
1239
|
+
* // confidence: 85,
|
|
1240
|
+
* // detectedFrom: [
|
|
1241
|
+
* // { type: 'package.json', field: 'dependencies.@angular/core' },
|
|
1242
|
+
* // { type: 'package.json', field: 'dependencies.@angular/cli' }
|
|
1243
|
+
* // ]
|
|
1244
|
+
* // }
|
|
1245
|
+
* ```
|
|
1577
1246
|
*/
|
|
1578
|
-
function
|
|
1247
|
+
function angularDetector(projectPath, packageJson) {
|
|
1579
1248
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1580
1249
|
const sources = [];
|
|
1581
1250
|
let confidence = 0;
|
|
1582
1251
|
let version;
|
|
1583
|
-
const metaFrameworks = [];
|
|
1584
1252
|
const deps = collectAllDependencies(pkg);
|
|
1585
|
-
if (deps['
|
|
1586
|
-
confidence +=
|
|
1587
|
-
version = parseVersionString(deps['
|
|
1588
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1253
|
+
if (deps['@angular/core']) {
|
|
1254
|
+
confidence += 70;
|
|
1255
|
+
version = parseVersionString(deps['@angular/core']);
|
|
1256
|
+
sources.push({ type: 'package.json', field: 'dependencies.@angular/core' });
|
|
1589
1257
|
}
|
|
1590
|
-
if (deps['
|
|
1591
|
-
confidence +=
|
|
1592
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1258
|
+
if (deps['@angular/cli']) {
|
|
1259
|
+
confidence += 15;
|
|
1260
|
+
sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
|
|
1593
1261
|
}
|
|
1594
|
-
if (
|
|
1595
|
-
confidence +=
|
|
1596
|
-
sources.push({ type: '
|
|
1262
|
+
if (exists(node_path.join(projectPath, 'angular.json'))) {
|
|
1263
|
+
confidence += 15;
|
|
1264
|
+
sources.push({ type: 'config-file', path: 'angular.json' });
|
|
1597
1265
|
}
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1266
|
+
if (deps['angular'] && !deps['@angular/core']) {
|
|
1267
|
+
return {
|
|
1268
|
+
id: 'angularjs',
|
|
1269
|
+
name: 'AngularJS (Legacy)',
|
|
1270
|
+
category: 'frontend',
|
|
1271
|
+
version: parseVersionString(deps['angular']),
|
|
1272
|
+
confidence: 80,
|
|
1273
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
1274
|
+
};
|
|
1605
1275
|
}
|
|
1606
|
-
if (
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1276
|
+
if (confidence === 0) {
|
|
1277
|
+
return null;
|
|
1278
|
+
}
|
|
1279
|
+
return {
|
|
1280
|
+
id: 'angular',
|
|
1281
|
+
name: 'Angular',
|
|
1282
|
+
category: 'frontend',
|
|
1283
|
+
version,
|
|
1284
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1285
|
+
detectedFrom: sources,
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
/**
|
|
1290
|
+
* Detect Astro in project.
|
|
1291
|
+
*
|
|
1292
|
+
* @param projectPath - Project directory path
|
|
1293
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
1294
|
+
* @returns Detection result or null if not detected
|
|
1295
|
+
*
|
|
1296
|
+
* @example Detecting Astro framework
|
|
1297
|
+
* ```typescript
|
|
1298
|
+
* const result = astroDetector('/path/to/astro-project', {
|
|
1299
|
+
* dependencies: { 'astro': '^4.0.0' }
|
|
1300
|
+
* })
|
|
1301
|
+
* // => {
|
|
1302
|
+
* // id: 'astro',
|
|
1303
|
+
* // name: 'Astro',
|
|
1304
|
+
* // category: 'meta-framework',
|
|
1305
|
+
* // version: '4.0.0',
|
|
1306
|
+
* // confidence: 70,
|
|
1307
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.astro' }]
|
|
1308
|
+
* // }
|
|
1309
|
+
* ```
|
|
1310
|
+
*/
|
|
1311
|
+
function astroDetector(projectPath, packageJson) {
|
|
1312
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1313
|
+
const sources = [];
|
|
1314
|
+
let confidence = 0;
|
|
1315
|
+
let version;
|
|
1316
|
+
const deps = collectAllDependencies(pkg);
|
|
1317
|
+
if (deps['astro']) {
|
|
1318
|
+
confidence += 70;
|
|
1319
|
+
version = parseVersionString(deps['astro']);
|
|
1320
|
+
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
1615
1321
|
}
|
|
1322
|
+
if (exists(node_path.join(projectPath, 'astro.config.mjs')) ||
|
|
1323
|
+
exists(node_path.join(projectPath, 'astro.config.ts')) ||
|
|
1324
|
+
exists(node_path.join(projectPath, 'astro.config.js'))) {
|
|
1325
|
+
confidence += 25;
|
|
1326
|
+
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
1327
|
+
}
|
|
1328
|
+
if (exists(node_path.join(projectPath, 'src', 'pages'))) {
|
|
1329
|
+
confidence += 5;
|
|
1330
|
+
sources.push({ type: 'directory', path: 'src/pages/' });
|
|
1331
|
+
}
|
|
1332
|
+
if (confidence === 0) {
|
|
1333
|
+
return null;
|
|
1334
|
+
}
|
|
1335
|
+
return {
|
|
1336
|
+
id: 'astro',
|
|
1337
|
+
name: 'Astro',
|
|
1338
|
+
category: 'meta-framework',
|
|
1339
|
+
version,
|
|
1340
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1341
|
+
detectedFrom: sources,
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
/**
|
|
1346
|
+
* Detect Gatsby in project.
|
|
1347
|
+
*
|
|
1348
|
+
* @param projectPath - Project directory path
|
|
1349
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
1350
|
+
* @returns Detection result or null if not detected
|
|
1351
|
+
*
|
|
1352
|
+
* @example Detecting Gatsby framework
|
|
1353
|
+
* ```typescript
|
|
1354
|
+
* const result = gatsbyDetector('/path/to/gatsby-blog', {
|
|
1355
|
+
* dependencies: {
|
|
1356
|
+
* 'gatsby': '^5.0.0',
|
|
1357
|
+
* 'gatsby-plugin-image': '^3.0.0',
|
|
1358
|
+
* 'gatsby-source-filesystem': '^5.0.0'
|
|
1359
|
+
* }
|
|
1360
|
+
* })
|
|
1361
|
+
* // => {
|
|
1362
|
+
* // id: 'gatsby',
|
|
1363
|
+
* // name: 'Gatsby',
|
|
1364
|
+
* // category: 'meta-framework',
|
|
1365
|
+
* // version: '5.0.0',
|
|
1366
|
+
* // confidence: 75,
|
|
1367
|
+
* // detectedFrom: [
|
|
1368
|
+
* // { type: 'package.json', field: 'dependencies.gatsby' },
|
|
1369
|
+
* // { type: 'package.json', field: 'dependencies (gatsby plugins)' }
|
|
1370
|
+
* // ]
|
|
1371
|
+
* // }
|
|
1372
|
+
* ```
|
|
1373
|
+
*/
|
|
1374
|
+
function gatsbyDetector(projectPath, packageJson) {
|
|
1375
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1376
|
+
const sources = [];
|
|
1377
|
+
let confidence = 0;
|
|
1378
|
+
let version;
|
|
1379
|
+
const deps = collectAllDependencies(pkg);
|
|
1616
1380
|
if (deps['gatsby']) {
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
category: 'meta-framework',
|
|
1621
|
-
version: parseVersionString(deps['gatsby']),
|
|
1622
|
-
confidence: 90,
|
|
1623
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
1624
|
-
});
|
|
1381
|
+
confidence += 70;
|
|
1382
|
+
version = parseVersionString(deps['gatsby']);
|
|
1383
|
+
sources.push({ type: 'package.json', field: 'dependencies.gatsby' });
|
|
1625
1384
|
}
|
|
1626
|
-
if (
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
});
|
|
1385
|
+
if (exists(node_path.join(projectPath, 'gatsby-config.js')) || exists(node_path.join(projectPath, 'gatsby-config.ts'))) {
|
|
1386
|
+
confidence += 25;
|
|
1387
|
+
sources.push({ type: 'config-file', path: 'gatsby-config.*' });
|
|
1388
|
+
}
|
|
1389
|
+
const gatsbyPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('gatsby-plugin-') || d.startsWith('gatsby-source-'));
|
|
1390
|
+
if (gatsbyPlugins.length > 0) {
|
|
1391
|
+
confidence += 5;
|
|
1392
|
+
sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
|
|
1635
1393
|
}
|
|
1636
1394
|
if (confidence === 0) {
|
|
1637
1395
|
return null;
|
|
1638
1396
|
}
|
|
1639
1397
|
return {
|
|
1640
|
-
id: '
|
|
1641
|
-
name: '
|
|
1642
|
-
category: '
|
|
1398
|
+
id: 'gatsby',
|
|
1399
|
+
name: 'Gatsby',
|
|
1400
|
+
category: 'meta-framework',
|
|
1643
1401
|
version,
|
|
1644
|
-
confidence: min(confidence, 100),
|
|
1402
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1645
1403
|
detectedFrom: sources,
|
|
1646
|
-
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
1647
1404
|
};
|
|
1648
1405
|
}
|
|
1649
1406
|
|
|
@@ -1653,6 +1410,21 @@ function reactDetector(projectPath, packageJson) {
|
|
|
1653
1410
|
* @param projectPath - Project directory path
|
|
1654
1411
|
* @param packageJson - Optional pre-loaded package.json
|
|
1655
1412
|
* @returns Detection result or null if not detected
|
|
1413
|
+
*
|
|
1414
|
+
* @example Detecting Next.js framework
|
|
1415
|
+
* ```typescript
|
|
1416
|
+
* const result = nextjsDetector('/path/to/nextjs-app', {
|
|
1417
|
+
* dependencies: { 'next': '^14.0.0', 'react': '^18.0.0' }
|
|
1418
|
+
* })
|
|
1419
|
+
* // => {
|
|
1420
|
+
* // id: 'nextjs',
|
|
1421
|
+
* // name: 'Next.js',
|
|
1422
|
+
* // category: 'meta-framework',
|
|
1423
|
+
* // version: '14.0.0',
|
|
1424
|
+
* // confidence: 70,
|
|
1425
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }]
|
|
1426
|
+
* // }
|
|
1427
|
+
* ```
|
|
1656
1428
|
*/
|
|
1657
1429
|
function nextjsDetector(projectPath, packageJson) {
|
|
1658
1430
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1686,230 +1458,335 @@ function nextjsDetector(projectPath, packageJson) {
|
|
|
1686
1458
|
name: 'Next.js',
|
|
1687
1459
|
category: 'meta-framework',
|
|
1688
1460
|
version,
|
|
1689
|
-
confidence: min(confidence, 100),
|
|
1461
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1690
1462
|
detectedFrom: sources,
|
|
1691
1463
|
};
|
|
1692
1464
|
}
|
|
1693
1465
|
|
|
1694
1466
|
/**
|
|
1695
|
-
* Detect
|
|
1467
|
+
* Detect Nuxt in project.
|
|
1696
1468
|
*
|
|
1697
1469
|
* @param projectPath - Project directory path
|
|
1698
1470
|
* @param packageJson - Optional pre-loaded package.json
|
|
1699
1471
|
* @returns Detection result or null if not detected
|
|
1472
|
+
*
|
|
1473
|
+
* @example Detecting Nuxt framework
|
|
1474
|
+
* ```typescript
|
|
1475
|
+
* const result = nuxtDetector('/path/to/nuxt-app', {
|
|
1476
|
+
* dependencies: { 'nuxt': '^3.0.0', 'vue': '^3.0.0' }
|
|
1477
|
+
* })
|
|
1478
|
+
* // => {
|
|
1479
|
+
* // id: 'nuxt',
|
|
1480
|
+
* // name: 'Nuxt',
|
|
1481
|
+
* // category: 'meta-framework',
|
|
1482
|
+
* // version: '3.0.0',
|
|
1483
|
+
* // confidence: 70,
|
|
1484
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }]
|
|
1485
|
+
* // }
|
|
1486
|
+
* ```
|
|
1700
1487
|
*/
|
|
1701
|
-
function
|
|
1488
|
+
function nuxtDetector(projectPath, packageJson) {
|
|
1702
1489
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1703
1490
|
const sources = [];
|
|
1704
1491
|
let confidence = 0;
|
|
1705
1492
|
let version;
|
|
1706
1493
|
const deps = collectAllDependencies(pkg);
|
|
1707
|
-
if (deps['
|
|
1494
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
1708
1495
|
confidence += 70;
|
|
1709
|
-
version = parseVersionString(deps['
|
|
1710
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1496
|
+
version = parseVersionString(deps['nuxt'] ?? deps['nuxt3']);
|
|
1497
|
+
sources.push({ type: 'package.json', field: 'dependencies.nuxt' });
|
|
1711
1498
|
}
|
|
1712
|
-
if (
|
|
1713
|
-
confidence +=
|
|
1714
|
-
sources.push({ type: '
|
|
1499
|
+
if (exists(node_path.join(projectPath, 'nuxt.config.js')) || exists(node_path.join(projectPath, 'nuxt.config.ts'))) {
|
|
1500
|
+
confidence += 25;
|
|
1501
|
+
sources.push({ type: 'config-file', path: 'nuxt.config.*' });
|
|
1715
1502
|
}
|
|
1716
|
-
if (exists(node_path.join(projectPath, '
|
|
1717
|
-
confidence +=
|
|
1718
|
-
sources.push({ type: '
|
|
1503
|
+
if (exists(node_path.join(projectPath, 'pages'))) {
|
|
1504
|
+
confidence += 5;
|
|
1505
|
+
sources.push({ type: 'directory', path: 'pages/' });
|
|
1719
1506
|
}
|
|
1720
1507
|
if (confidence === 0) {
|
|
1721
1508
|
return null;
|
|
1722
1509
|
}
|
|
1723
1510
|
return {
|
|
1724
|
-
id: '
|
|
1725
|
-
name: '
|
|
1511
|
+
id: 'nuxt',
|
|
1512
|
+
name: 'Nuxt',
|
|
1726
1513
|
category: 'meta-framework',
|
|
1727
1514
|
version,
|
|
1728
|
-
confidence: min(confidence, 100),
|
|
1515
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1729
1516
|
detectedFrom: sources,
|
|
1730
1517
|
};
|
|
1731
1518
|
}
|
|
1732
1519
|
|
|
1733
1520
|
/**
|
|
1734
|
-
* Detect
|
|
1521
|
+
* Detect Qwik in project.
|
|
1735
1522
|
*
|
|
1736
1523
|
* @param projectPath - Project directory path
|
|
1737
1524
|
* @param packageJson - Optional pre-loaded package.json
|
|
1738
1525
|
* @returns Detection result or null if not detected
|
|
1526
|
+
*
|
|
1527
|
+
* @example Detecting Qwik framework
|
|
1528
|
+
* ```typescript
|
|
1529
|
+
* const result = qwikDetector('/path/to/qwik-app', {
|
|
1530
|
+
* dependencies: {
|
|
1531
|
+
* '@builder.io/qwik': '^1.0.0',
|
|
1532
|
+
* '@builder.io/qwik-city': '^1.0.0'
|
|
1533
|
+
* }
|
|
1534
|
+
* })
|
|
1535
|
+
* // => {
|
|
1536
|
+
* // id: 'qwik',
|
|
1537
|
+
* // name: 'Qwik',
|
|
1538
|
+
* // category: 'frontend',
|
|
1539
|
+
* // version: '1.0.0',
|
|
1540
|
+
* // confidence: 90,
|
|
1541
|
+
* // detectedFrom: [
|
|
1542
|
+
* // { type: 'package.json', field: 'dependencies.@builder.io/qwik' },
|
|
1543
|
+
* // { type: 'package.json', field: 'dependencies.@builder.io/qwik-city' }
|
|
1544
|
+
* // ]
|
|
1545
|
+
* // }
|
|
1546
|
+
* ```
|
|
1739
1547
|
*/
|
|
1740
|
-
function
|
|
1548
|
+
function qwikDetector(projectPath, packageJson) {
|
|
1741
1549
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1742
1550
|
const sources = [];
|
|
1743
1551
|
let confidence = 0;
|
|
1744
1552
|
let version;
|
|
1745
1553
|
const deps = collectAllDependencies(pkg);
|
|
1746
|
-
if (deps['
|
|
1554
|
+
if (deps['@builder.io/qwik']) {
|
|
1747
1555
|
confidence += 70;
|
|
1748
|
-
version = parseVersionString(deps['
|
|
1749
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1556
|
+
version = parseVersionString(deps['@builder.io/qwik']);
|
|
1557
|
+
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
|
|
1750
1558
|
}
|
|
1751
|
-
if (
|
|
1752
|
-
confidence +=
|
|
1753
|
-
sources.push({ type: '
|
|
1559
|
+
if (deps['@builder.io/qwik-city']) {
|
|
1560
|
+
confidence += 20;
|
|
1561
|
+
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
|
|
1754
1562
|
}
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
|
|
1563
|
+
if (exists(node_path.join(projectPath, 'qwik.config.ts')) || exists(node_path.join(projectPath, 'qwik.config.js'))) {
|
|
1564
|
+
confidence += 10;
|
|
1565
|
+
sources.push({ type: 'config-file', path: 'qwik.config.*' });
|
|
1759
1566
|
}
|
|
1760
1567
|
if (confidence === 0) {
|
|
1761
1568
|
return null;
|
|
1762
1569
|
}
|
|
1763
1570
|
return {
|
|
1764
|
-
id: '
|
|
1765
|
-
name: '
|
|
1766
|
-
category: '
|
|
1571
|
+
id: 'qwik',
|
|
1572
|
+
name: 'Qwik',
|
|
1573
|
+
category: 'frontend',
|
|
1767
1574
|
version,
|
|
1768
|
-
confidence: min(confidence, 100),
|
|
1575
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1769
1576
|
detectedFrom: sources,
|
|
1770
1577
|
};
|
|
1771
1578
|
}
|
|
1772
1579
|
|
|
1773
1580
|
/**
|
|
1774
|
-
* Detect
|
|
1581
|
+
* Detect React in project.
|
|
1775
1582
|
*
|
|
1776
1583
|
* @param projectPath - Project directory path
|
|
1777
1584
|
* @param packageJson - Optional pre-loaded package.json
|
|
1778
1585
|
* @returns Detection result or null if not detected
|
|
1586
|
+
*
|
|
1587
|
+
* @example Detecting React library
|
|
1588
|
+
* ```typescript
|
|
1589
|
+
* const result = reactDetector('/path/to/react-app', {
|
|
1590
|
+
* dependencies: { 'react': '^18.0.0', 'react-dom': '^18.0.0' }
|
|
1591
|
+
* })
|
|
1592
|
+
* // => {
|
|
1593
|
+
* // id: 'react',
|
|
1594
|
+
* // name: 'React',
|
|
1595
|
+
* // category: 'frontend',
|
|
1596
|
+
* // version: '18.0.0',
|
|
1597
|
+
* // confidence: 80,
|
|
1598
|
+
* // detectedFrom: [
|
|
1599
|
+
* // { type: 'package.json', field: 'dependencies.react' },
|
|
1600
|
+
* // { type: 'package.json', field: 'dependencies.react-dom' }
|
|
1601
|
+
* // ]
|
|
1602
|
+
* // }
|
|
1603
|
+
* ```
|
|
1779
1604
|
*/
|
|
1780
|
-
function
|
|
1605
|
+
function reactDetector(projectPath, packageJson) {
|
|
1781
1606
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1782
1607
|
const sources = [];
|
|
1783
1608
|
let confidence = 0;
|
|
1784
1609
|
let version;
|
|
1785
1610
|
const metaFrameworks = [];
|
|
1786
1611
|
const deps = collectAllDependencies(pkg);
|
|
1787
|
-
if (deps['
|
|
1788
|
-
confidence +=
|
|
1789
|
-
version = parseVersionString(deps['
|
|
1790
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1612
|
+
if (deps['react']) {
|
|
1613
|
+
confidence += 60;
|
|
1614
|
+
version = parseVersionString(deps['react']);
|
|
1615
|
+
sources.push({ type: 'package.json', field: 'dependencies.react' });
|
|
1791
1616
|
}
|
|
1792
|
-
if (deps['
|
|
1793
|
-
confidence +=
|
|
1794
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1617
|
+
if (deps['react-dom']) {
|
|
1618
|
+
confidence += 20;
|
|
1619
|
+
sources.push({ type: 'package.json', field: 'dependencies.react-dom' });
|
|
1795
1620
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
1621
|
+
if (deps['react-native']) {
|
|
1622
|
+
confidence += 20;
|
|
1623
|
+
sources.push({ type: 'package.json', field: 'dependencies.react-native' });
|
|
1624
|
+
}
|
|
1625
|
+
const hasJsxFiles = exists(node_path.join(projectPath, 'src', 'App.tsx')) ||
|
|
1626
|
+
exists(node_path.join(projectPath, 'src', 'App.jsx')) ||
|
|
1627
|
+
exists(node_path.join(projectPath, 'src', 'index.tsx')) ||
|
|
1628
|
+
exists(node_path.join(projectPath, 'src', 'index.jsx'));
|
|
1629
|
+
if (hasJsxFiles) {
|
|
1798
1630
|
confidence += 10;
|
|
1799
|
-
sources.push({ type: 'directory', path: 'src/*.
|
|
1631
|
+
sources.push({ type: 'directory', path: 'src/*.tsx or src/*.jsx' });
|
|
1800
1632
|
}
|
|
1801
|
-
if (
|
|
1802
|
-
|
|
1803
|
-
|
|
1633
|
+
if (deps['next']) {
|
|
1634
|
+
metaFrameworks.push({
|
|
1635
|
+
id: 'nextjs',
|
|
1636
|
+
name: 'Next.js',
|
|
1637
|
+
category: 'meta-framework',
|
|
1638
|
+
version: parseVersionString(deps['next']),
|
|
1639
|
+
confidence: 90,
|
|
1640
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }],
|
|
1641
|
+
});
|
|
1804
1642
|
}
|
|
1805
|
-
if (deps['
|
|
1643
|
+
if (deps['gatsby']) {
|
|
1806
1644
|
metaFrameworks.push({
|
|
1807
|
-
id: '
|
|
1808
|
-
name: '
|
|
1645
|
+
id: 'gatsby',
|
|
1646
|
+
name: 'Gatsby',
|
|
1809
1647
|
category: 'meta-framework',
|
|
1810
|
-
version: parseVersionString(deps['
|
|
1648
|
+
version: parseVersionString(deps['gatsby']),
|
|
1811
1649
|
confidence: 90,
|
|
1812
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.
|
|
1650
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
if (deps['@remix-run/react'] || deps['remix']) {
|
|
1654
|
+
metaFrameworks.push({
|
|
1655
|
+
id: 'remix',
|
|
1656
|
+
name: 'Remix',
|
|
1657
|
+
category: 'meta-framework',
|
|
1658
|
+
version: parseVersionString(deps['@remix-run/react'] ?? deps['remix']),
|
|
1659
|
+
confidence: 90,
|
|
1660
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.@remix-run/react' }],
|
|
1813
1661
|
});
|
|
1814
1662
|
}
|
|
1815
1663
|
if (confidence === 0) {
|
|
1816
1664
|
return null;
|
|
1817
1665
|
}
|
|
1818
1666
|
return {
|
|
1819
|
-
id: '
|
|
1820
|
-
name: '
|
|
1667
|
+
id: 'react',
|
|
1668
|
+
name: 'React',
|
|
1821
1669
|
category: 'frontend',
|
|
1822
1670
|
version,
|
|
1823
|
-
confidence: min(confidence, 100),
|
|
1671
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1824
1672
|
detectedFrom: sources,
|
|
1825
1673
|
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
1826
1674
|
};
|
|
1827
1675
|
}
|
|
1828
1676
|
|
|
1829
1677
|
/**
|
|
1830
|
-
* Detect
|
|
1678
|
+
* Detect Remix in project.
|
|
1831
1679
|
*
|
|
1832
1680
|
* @param projectPath - Project directory path
|
|
1833
1681
|
* @param packageJson - Optional pre-loaded package.json
|
|
1834
1682
|
* @returns Detection result or null if not detected
|
|
1683
|
+
*
|
|
1684
|
+
* @example Detecting Remix framework
|
|
1685
|
+
* ```typescript
|
|
1686
|
+
* const result = remixDetector('/path/to/remix-app', {
|
|
1687
|
+
* dependencies: {
|
|
1688
|
+
* '@remix-run/react': '^2.0.0',
|
|
1689
|
+
* '@remix-run/node': '^2.0.0'
|
|
1690
|
+
* }
|
|
1691
|
+
* })
|
|
1692
|
+
* // => {
|
|
1693
|
+
* // id: 'remix',
|
|
1694
|
+
* // name: 'Remix',
|
|
1695
|
+
* // category: 'meta-framework',
|
|
1696
|
+
* // version: '2.0.0',
|
|
1697
|
+
* // confidence: 90,
|
|
1698
|
+
* // detectedFrom: [
|
|
1699
|
+
* // { type: 'package.json', field: 'dependencies.@remix-run/react' },
|
|
1700
|
+
* // { type: 'package.json', field: 'dependencies.@remix-run/*' }
|
|
1701
|
+
* // ]
|
|
1702
|
+
* // }
|
|
1703
|
+
* ```
|
|
1835
1704
|
*/
|
|
1836
|
-
function
|
|
1705
|
+
function remixDetector(projectPath, packageJson) {
|
|
1837
1706
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1838
1707
|
const sources = [];
|
|
1839
1708
|
let confidence = 0;
|
|
1840
1709
|
let version;
|
|
1841
1710
|
const deps = collectAllDependencies(pkg);
|
|
1842
|
-
if (deps['
|
|
1711
|
+
if (deps['@remix-run/react']) {
|
|
1843
1712
|
confidence += 70;
|
|
1844
|
-
version = parseVersionString(deps['
|
|
1845
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1713
|
+
version = parseVersionString(deps['@remix-run/react']);
|
|
1714
|
+
sources.push({ type: 'package.json', field: 'dependencies.@remix-run/react' });
|
|
1846
1715
|
}
|
|
1847
|
-
if (
|
|
1848
|
-
confidence +=
|
|
1849
|
-
sources.push({ type: '
|
|
1716
|
+
if (deps['@remix-run/node'] || deps['@remix-run/cloudflare'] || deps['@remix-run/deno']) {
|
|
1717
|
+
confidence += 20;
|
|
1718
|
+
sources.push({ type: 'package.json', field: 'dependencies.@remix-run/*' });
|
|
1850
1719
|
}
|
|
1851
|
-
if (exists(node_path.join(projectPath, '
|
|
1852
|
-
confidence +=
|
|
1853
|
-
sources.push({ type: '
|
|
1720
|
+
if (exists(node_path.join(projectPath, 'remix.config.js')) || exists(node_path.join(projectPath, 'remix.config.ts'))) {
|
|
1721
|
+
confidence += 10;
|
|
1722
|
+
sources.push({ type: 'config-file', path: 'remix.config.*' });
|
|
1854
1723
|
}
|
|
1855
1724
|
if (confidence === 0) {
|
|
1856
1725
|
return null;
|
|
1857
1726
|
}
|
|
1858
1727
|
return {
|
|
1859
|
-
id: '
|
|
1860
|
-
name: '
|
|
1728
|
+
id: 'remix',
|
|
1729
|
+
name: 'Remix',
|
|
1861
1730
|
category: 'meta-framework',
|
|
1862
1731
|
version,
|
|
1863
|
-
confidence: min(confidence, 100),
|
|
1732
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1864
1733
|
detectedFrom: sources,
|
|
1865
1734
|
};
|
|
1866
1735
|
}
|
|
1867
1736
|
|
|
1868
1737
|
/**
|
|
1869
|
-
* Detect
|
|
1738
|
+
* Detect Solid in project.
|
|
1870
1739
|
*
|
|
1871
1740
|
* @param projectPath - Project directory path
|
|
1872
1741
|
* @param packageJson - Optional pre-loaded package.json
|
|
1873
1742
|
* @returns Detection result or null if not detected
|
|
1743
|
+
*
|
|
1744
|
+
* @example Detecting Solid.js framework
|
|
1745
|
+
* ```typescript
|
|
1746
|
+
* const result = solidDetector('/path/to/solid-app', {
|
|
1747
|
+
* dependencies: { 'solid-js': '^1.8.0', 'vite-plugin-solid': '^2.0.0' }
|
|
1748
|
+
* })
|
|
1749
|
+
* // => {
|
|
1750
|
+
* // id: 'solid',
|
|
1751
|
+
* // name: 'Solid',
|
|
1752
|
+
* // category: 'frontend',
|
|
1753
|
+
* // version: '1.8.0',
|
|
1754
|
+
* // confidence: 90,
|
|
1755
|
+
* // detectedFrom: [
|
|
1756
|
+
* // { type: 'package.json', field: 'dependencies.solid-js' },
|
|
1757
|
+
* // { type: 'package.json', field: 'dependencies.vite-plugin-solid' }
|
|
1758
|
+
* // ]
|
|
1759
|
+
* // }
|
|
1760
|
+
* ```
|
|
1874
1761
|
*/
|
|
1875
|
-
function
|
|
1762
|
+
function solidDetector(projectPath, packageJson) {
|
|
1876
1763
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1877
1764
|
const sources = [];
|
|
1878
1765
|
let confidence = 0;
|
|
1879
1766
|
let version;
|
|
1880
1767
|
const deps = collectAllDependencies(pkg);
|
|
1881
|
-
if (deps['
|
|
1768
|
+
if (deps['solid-js']) {
|
|
1882
1769
|
confidence += 70;
|
|
1883
|
-
version = parseVersionString(deps['
|
|
1884
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1885
|
-
}
|
|
1886
|
-
if (deps['@angular/cli']) {
|
|
1887
|
-
confidence += 15;
|
|
1888
|
-
sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
|
|
1770
|
+
version = parseVersionString(deps['solid-js']);
|
|
1771
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
1889
1772
|
}
|
|
1890
|
-
if (
|
|
1891
|
-
confidence +=
|
|
1892
|
-
sources.push({ type: '
|
|
1773
|
+
if (deps['vite-plugin-solid']) {
|
|
1774
|
+
confidence += 20;
|
|
1775
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
1893
1776
|
}
|
|
1894
|
-
if (deps['
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
name: 'AngularJS (Legacy)',
|
|
1898
|
-
category: 'frontend',
|
|
1899
|
-
version: parseVersionString(deps['angular']),
|
|
1900
|
-
confidence: 80,
|
|
1901
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
1902
|
-
};
|
|
1777
|
+
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
1778
|
+
confidence += 10;
|
|
1779
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
1903
1780
|
}
|
|
1904
1781
|
if (confidence === 0) {
|
|
1905
1782
|
return null;
|
|
1906
1783
|
}
|
|
1907
1784
|
return {
|
|
1908
|
-
id: '
|
|
1909
|
-
name: '
|
|
1785
|
+
id: 'solid',
|
|
1786
|
+
name: 'Solid',
|
|
1910
1787
|
category: 'frontend',
|
|
1911
1788
|
version,
|
|
1912
|
-
confidence: min(confidence, 100),
|
|
1789
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1913
1790
|
detectedFrom: sources,
|
|
1914
1791
|
};
|
|
1915
1792
|
}
|
|
@@ -1920,6 +1797,21 @@ function angularDetector(projectPath, packageJson) {
|
|
|
1920
1797
|
* @param projectPath - Project directory path
|
|
1921
1798
|
* @param packageJson - Optional pre-loaded package.json
|
|
1922
1799
|
* @returns Detection result or null if not detected
|
|
1800
|
+
*
|
|
1801
|
+
* @example Detecting Svelte framework
|
|
1802
|
+
* ```typescript
|
|
1803
|
+
* const result = svelteDetector('/path/to/svelte-app', {
|
|
1804
|
+
* devDependencies: { 'svelte': '^4.0.0' }
|
|
1805
|
+
* })
|
|
1806
|
+
* // => {
|
|
1807
|
+
* // id: 'svelte',
|
|
1808
|
+
* // name: 'Svelte',
|
|
1809
|
+
* // category: 'frontend',
|
|
1810
|
+
* // version: '4.0.0',
|
|
1811
|
+
* // confidence: 70,
|
|
1812
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.svelte' }]
|
|
1813
|
+
* // }
|
|
1814
|
+
* ```
|
|
1923
1815
|
*/
|
|
1924
1816
|
function svelteDetector(projectPath, packageJson) {
|
|
1925
1817
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1960,7 +1852,7 @@ function svelteDetector(projectPath, packageJson) {
|
|
|
1960
1852
|
name: 'Svelte',
|
|
1961
1853
|
category: 'frontend',
|
|
1962
1854
|
version,
|
|
1963
|
-
confidence: min(confidence, 100),
|
|
1855
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
1964
1856
|
detectedFrom: sources,
|
|
1965
1857
|
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
1966
1858
|
};
|
|
@@ -1972,6 +1864,21 @@ function svelteDetector(projectPath, packageJson) {
|
|
|
1972
1864
|
* @param projectPath - Project directory path
|
|
1973
1865
|
* @param packageJson - Optional pre-loaded package.json
|
|
1974
1866
|
* @returns Detection result or null if not detected
|
|
1867
|
+
*
|
|
1868
|
+
* @example Detecting SvelteKit framework
|
|
1869
|
+
* ```typescript
|
|
1870
|
+
* const result = sveltekitDetector('/path/to/sveltekit-app', {
|
|
1871
|
+
* devDependencies: { '@sveltejs/kit': '^2.0.0', 'svelte': '^4.0.0' }
|
|
1872
|
+
* })
|
|
1873
|
+
* // => {
|
|
1874
|
+
* // id: 'sveltekit',
|
|
1875
|
+
* // name: 'SvelteKit',
|
|
1876
|
+
* // category: 'meta-framework',
|
|
1877
|
+
* // version: '2.0.0',
|
|
1878
|
+
* // confidence: 70,
|
|
1879
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.@sveltejs/kit' }]
|
|
1880
|
+
* // }
|
|
1881
|
+
* ```
|
|
1975
1882
|
*/
|
|
1976
1883
|
function sveltekitDetector(projectPath, packageJson) {
|
|
1977
1884
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2000,127 +1907,82 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
2000
1907
|
name: 'SvelteKit',
|
|
2001
1908
|
category: 'meta-framework',
|
|
2002
1909
|
version,
|
|
2003
|
-
confidence: min(confidence, 100),
|
|
1910
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2004
1911
|
detectedFrom: sources,
|
|
2005
1912
|
};
|
|
2006
1913
|
}
|
|
2007
1914
|
|
|
2008
1915
|
/**
|
|
2009
|
-
* Detect
|
|
1916
|
+
* Detect Vue in project.
|
|
2010
1917
|
*
|
|
2011
1918
|
* @param projectPath - Project directory path
|
|
2012
1919
|
* @param packageJson - Optional pre-loaded package.json
|
|
2013
1920
|
* @returns Detection result or null if not detected
|
|
2014
|
-
*/
|
|
2015
|
-
function solidDetector(projectPath, packageJson) {
|
|
2016
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2017
|
-
const sources = [];
|
|
2018
|
-
let confidence = 0;
|
|
2019
|
-
let version;
|
|
2020
|
-
const deps = collectAllDependencies(pkg);
|
|
2021
|
-
if (deps['solid-js']) {
|
|
2022
|
-
confidence += 70;
|
|
2023
|
-
version = parseVersionString(deps['solid-js']);
|
|
2024
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
2025
|
-
}
|
|
2026
|
-
if (deps['vite-plugin-solid']) {
|
|
2027
|
-
confidence += 20;
|
|
2028
|
-
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
2029
|
-
}
|
|
2030
|
-
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
2031
|
-
confidence += 10;
|
|
2032
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
2033
|
-
}
|
|
2034
|
-
if (confidence === 0) {
|
|
2035
|
-
return null;
|
|
2036
|
-
}
|
|
2037
|
-
return {
|
|
2038
|
-
id: 'solid',
|
|
2039
|
-
name: 'Solid',
|
|
2040
|
-
category: 'frontend',
|
|
2041
|
-
version,
|
|
2042
|
-
confidence: min(confidence, 100),
|
|
2043
|
-
detectedFrom: sources,
|
|
2044
|
-
};
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
/**
|
|
2048
|
-
* Detect Qwik in project.
|
|
2049
1921
|
*
|
|
2050
|
-
* @
|
|
2051
|
-
*
|
|
2052
|
-
*
|
|
1922
|
+
* @example Detecting Vue.js framework
|
|
1923
|
+
* ```typescript
|
|
1924
|
+
* const result = vueDetector('/path/to/vue-app', {
|
|
1925
|
+
* dependencies: { 'vue': '^3.0.0', '@vue/cli-service': '^5.0.0' }
|
|
1926
|
+
* })
|
|
1927
|
+
* // => {
|
|
1928
|
+
* // id: 'vue',
|
|
1929
|
+
* // name: 'Vue',
|
|
1930
|
+
* // category: 'frontend',
|
|
1931
|
+
* // version: '3.0.0',
|
|
1932
|
+
* // confidence: 85,
|
|
1933
|
+
* // detectedFrom: [
|
|
1934
|
+
* // { type: 'package.json', field: 'dependencies.vue' },
|
|
1935
|
+
* // { type: 'package.json', field: 'dependencies.@vue/cli-service' }
|
|
1936
|
+
* // ]
|
|
1937
|
+
* // }
|
|
1938
|
+
* ```
|
|
2053
1939
|
*/
|
|
2054
|
-
function
|
|
1940
|
+
function vueDetector(projectPath, packageJson) {
|
|
2055
1941
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2056
1942
|
const sources = [];
|
|
2057
1943
|
let confidence = 0;
|
|
2058
1944
|
let version;
|
|
1945
|
+
const metaFrameworks = [];
|
|
2059
1946
|
const deps = collectAllDependencies(pkg);
|
|
2060
|
-
if (deps['
|
|
1947
|
+
if (deps['vue']) {
|
|
2061
1948
|
confidence += 70;
|
|
2062
|
-
version = parseVersionString(deps['
|
|
2063
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1949
|
+
version = parseVersionString(deps['vue']);
|
|
1950
|
+
sources.push({ type: 'package.json', field: 'dependencies.vue' });
|
|
2064
1951
|
}
|
|
2065
|
-
if (deps['@
|
|
2066
|
-
confidence +=
|
|
2067
|
-
sources.push({ type: 'package.json', field: 'dependencies.@
|
|
1952
|
+
if (deps['@vue/cli-service']) {
|
|
1953
|
+
confidence += 15;
|
|
1954
|
+
sources.push({ type: 'package.json', field: 'dependencies.@vue/cli-service' });
|
|
2068
1955
|
}
|
|
2069
|
-
|
|
1956
|
+
const hasVueFiles = exists(node_path.join(projectPath, 'src', 'App.vue')) || exists(node_path.join(projectPath, 'src', 'main.vue'));
|
|
1957
|
+
if (hasVueFiles) {
|
|
2070
1958
|
confidence += 10;
|
|
2071
|
-
sources.push({ type: '
|
|
2072
|
-
}
|
|
2073
|
-
if (confidence === 0) {
|
|
2074
|
-
return null;
|
|
2075
|
-
}
|
|
2076
|
-
return {
|
|
2077
|
-
id: 'qwik',
|
|
2078
|
-
name: 'Qwik',
|
|
2079
|
-
category: 'frontend',
|
|
2080
|
-
version,
|
|
2081
|
-
confidence: min(confidence, 100),
|
|
2082
|
-
detectedFrom: sources,
|
|
2083
|
-
};
|
|
2084
|
-
}
|
|
2085
|
-
|
|
2086
|
-
/**
|
|
2087
|
-
* Detect Astro in project.
|
|
2088
|
-
*
|
|
2089
|
-
* @param projectPath - Project directory path
|
|
2090
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2091
|
-
* @returns Detection result or null if not detected
|
|
2092
|
-
*/
|
|
2093
|
-
function astroDetector(projectPath, packageJson) {
|
|
2094
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2095
|
-
const sources = [];
|
|
2096
|
-
let confidence = 0;
|
|
2097
|
-
let version;
|
|
2098
|
-
const deps = collectAllDependencies(pkg);
|
|
2099
|
-
if (deps['astro']) {
|
|
2100
|
-
confidence += 70;
|
|
2101
|
-
version = parseVersionString(deps['astro']);
|
|
2102
|
-
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
2103
|
-
}
|
|
2104
|
-
if (exists(node_path.join(projectPath, 'astro.config.mjs')) ||
|
|
2105
|
-
exists(node_path.join(projectPath, 'astro.config.ts')) ||
|
|
2106
|
-
exists(node_path.join(projectPath, 'astro.config.js'))) {
|
|
2107
|
-
confidence += 25;
|
|
2108
|
-
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
1959
|
+
sources.push({ type: 'directory', path: 'src/*.vue' });
|
|
2109
1960
|
}
|
|
2110
|
-
if (exists(node_path.join(projectPath, '
|
|
1961
|
+
if (exists(node_path.join(projectPath, 'vue.config.js'))) {
|
|
2111
1962
|
confidence += 5;
|
|
2112
|
-
sources.push({ type: '
|
|
1963
|
+
sources.push({ type: 'config-file', path: 'vue.config.js' });
|
|
1964
|
+
}
|
|
1965
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
1966
|
+
metaFrameworks.push({
|
|
1967
|
+
id: 'nuxt',
|
|
1968
|
+
name: 'Nuxt',
|
|
1969
|
+
category: 'meta-framework',
|
|
1970
|
+
version: parseVersionString(deps['nuxt'] ?? deps['nuxt3']),
|
|
1971
|
+
confidence: 90,
|
|
1972
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }],
|
|
1973
|
+
});
|
|
2113
1974
|
}
|
|
2114
1975
|
if (confidence === 0) {
|
|
2115
1976
|
return null;
|
|
2116
1977
|
}
|
|
2117
1978
|
return {
|
|
2118
|
-
id: '
|
|
2119
|
-
name: '
|
|
2120
|
-
category: '
|
|
1979
|
+
id: 'vue',
|
|
1980
|
+
name: 'Vue',
|
|
1981
|
+
category: 'frontend',
|
|
2121
1982
|
version,
|
|
2122
|
-
confidence: min(confidence, 100),
|
|
1983
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2123
1984
|
detectedFrom: sources,
|
|
1985
|
+
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
2124
1986
|
};
|
|
2125
1987
|
}
|
|
2126
1988
|
|
|
@@ -2145,6 +2007,17 @@ const frameworkDetectors = [
|
|
|
2145
2007
|
* @param projectPath - Project directory path
|
|
2146
2008
|
* @param packageJson - Optional pre-loaded package.json
|
|
2147
2009
|
* @returns Array of detected frameworks, sorted by confidence
|
|
2010
|
+
*
|
|
2011
|
+
* @example Detecting multiple frontend frameworks
|
|
2012
|
+
* ```typescript
|
|
2013
|
+
* const frameworks = detectFrontendFrameworks('/path/to/nextjs-app', {
|
|
2014
|
+
* dependencies: { 'react': '^18.0.0', 'next': '^14.0.0' }
|
|
2015
|
+
* })
|
|
2016
|
+
* // => [
|
|
2017
|
+
* // { id: 'nextjs', name: 'Next.js', category: 'meta-framework', confidence: 70, ... },
|
|
2018
|
+
* // { id: 'react', name: 'React', category: 'frontend', confidence: 60, ... }
|
|
2019
|
+
* // ]
|
|
2020
|
+
* ```
|
|
2148
2021
|
*/
|
|
2149
2022
|
function detectFrontendFrameworks(projectPath, packageJson) {
|
|
2150
2023
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2165,6 +2038,14 @@ function detectFrontendFrameworks(projectPath, packageJson) {
|
|
|
2165
2038
|
* @param projectPath - Project directory path
|
|
2166
2039
|
* @param packageJson - Optional pre-loaded package.json
|
|
2167
2040
|
* @returns Detection result or null if not detected
|
|
2041
|
+
*
|
|
2042
|
+
* @example Detecting AngularJS framework
|
|
2043
|
+
* ```typescript
|
|
2044
|
+
* const result = angularJSDetector('/path/to/project', {
|
|
2045
|
+
* dependencies: { angular: '^1.8.0', 'angular-route': '^1.8.0' },
|
|
2046
|
+
* })
|
|
2047
|
+
* // => { id: 'angularjs', name: 'AngularJS', confidence: 85, version: '1.8.0', ... }
|
|
2048
|
+
* ```
|
|
2168
2049
|
*/
|
|
2169
2050
|
function angularJSDetector(projectPath, packageJson) {
|
|
2170
2051
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2197,7 +2078,7 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
2197
2078
|
name: 'AngularJS',
|
|
2198
2079
|
category: 'legacy-frontend',
|
|
2199
2080
|
version,
|
|
2200
|
-
confidence: min(confidence, 100),
|
|
2081
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2201
2082
|
detectedFrom: sources,
|
|
2202
2083
|
};
|
|
2203
2084
|
}
|
|
@@ -2208,6 +2089,14 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
2208
2089
|
* @param projectPath - Project directory path
|
|
2209
2090
|
* @param packageJson - Optional pre-loaded package.json
|
|
2210
2091
|
* @returns Detection result or null if not detected
|
|
2092
|
+
*
|
|
2093
|
+
* @example Detecting Backbone.js framework
|
|
2094
|
+
* ```typescript
|
|
2095
|
+
* const result = backboneDetector('/path/to/project', {
|
|
2096
|
+
* dependencies: { backbone: '^1.4.0', underscore: '^1.13.0' },
|
|
2097
|
+
* })
|
|
2098
|
+
* // => { id: 'backbone', name: 'Backbone.js', confidence: 85, version: '1.4.0', ... }
|
|
2099
|
+
* ```
|
|
2211
2100
|
*/
|
|
2212
2101
|
function backboneDetector(projectPath, packageJson) {
|
|
2213
2102
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2240,7 +2129,7 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
2240
2129
|
name: 'Backbone.js',
|
|
2241
2130
|
category: 'legacy-frontend',
|
|
2242
2131
|
version,
|
|
2243
|
-
confidence: min(confidence, 100),
|
|
2132
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2244
2133
|
detectedFrom: sources,
|
|
2245
2134
|
};
|
|
2246
2135
|
}
|
|
@@ -2251,6 +2140,15 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
2251
2140
|
* @param projectPath - Project directory path
|
|
2252
2141
|
* @param packageJson - Optional pre-loaded package.json
|
|
2253
2142
|
* @returns Detection result or null if not detected
|
|
2143
|
+
*
|
|
2144
|
+
* @example Detecting Ember.js framework
|
|
2145
|
+
* ```typescript
|
|
2146
|
+
* const result = emberDetector('/path/to/project', {
|
|
2147
|
+
* dependencies: { 'ember-source': '^4.0.0' },
|
|
2148
|
+
* devDependencies: { 'ember-cli': '^4.0.0' },
|
|
2149
|
+
* })
|
|
2150
|
+
* // => { id: 'ember', name: 'Ember.js', confidence: 90, version: '4.0.0', ... }
|
|
2151
|
+
* ```
|
|
2254
2152
|
*/
|
|
2255
2153
|
function emberDetector(projectPath, packageJson) {
|
|
2256
2154
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2279,7 +2177,7 @@ function emberDetector(projectPath, packageJson) {
|
|
|
2279
2177
|
name: 'Ember.js',
|
|
2280
2178
|
category: 'legacy-frontend',
|
|
2281
2179
|
version,
|
|
2282
|
-
confidence: min(confidence, 100),
|
|
2180
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2283
2181
|
detectedFrom: sources,
|
|
2284
2182
|
};
|
|
2285
2183
|
}
|
|
@@ -2290,6 +2188,14 @@ function emberDetector(projectPath, packageJson) {
|
|
|
2290
2188
|
* @param projectPath - Project directory path
|
|
2291
2189
|
* @param packageJson - Optional pre-loaded package.json
|
|
2292
2190
|
* @returns Detection result or null if not detected
|
|
2191
|
+
*
|
|
2192
|
+
* @example Detecting jQuery library
|
|
2193
|
+
* ```typescript
|
|
2194
|
+
* const result = jqueryDetector('/path/to/project', {
|
|
2195
|
+
* dependencies: { jquery: '^3.6.0', 'jquery-ui': '^1.13.0' },
|
|
2196
|
+
* })
|
|
2197
|
+
* // => { id: 'jquery', name: 'jQuery', confidence: 90, version: '3.6.0', ... }
|
|
2198
|
+
* ```
|
|
2293
2199
|
*/
|
|
2294
2200
|
function jqueryDetector(projectPath, packageJson) {
|
|
2295
2201
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2314,41 +2220,99 @@ function jqueryDetector(projectPath, packageJson) {
|
|
|
2314
2220
|
return null;
|
|
2315
2221
|
}
|
|
2316
2222
|
return {
|
|
2317
|
-
id: 'jquery',
|
|
2318
|
-
name: 'jQuery',
|
|
2319
|
-
category: 'legacy-frontend',
|
|
2223
|
+
id: 'jquery',
|
|
2224
|
+
name: 'jQuery',
|
|
2225
|
+
category: 'legacy-frontend',
|
|
2226
|
+
version,
|
|
2227
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2228
|
+
detectedFrom: sources,
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
/** All legacy framework detectors */
|
|
2233
|
+
const legacyDetectors = [
|
|
2234
|
+
{ id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
|
|
2235
|
+
{ id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
|
|
2236
|
+
{ id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
|
|
2237
|
+
{ id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
|
|
2238
|
+
];
|
|
2239
|
+
/**
|
|
2240
|
+
* Detect all legacy frameworks in project.
|
|
2241
|
+
*
|
|
2242
|
+
* @param projectPath - Project directory path
|
|
2243
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
2244
|
+
* @returns Array of detected legacy frameworks, sorted by confidence
|
|
2245
|
+
*
|
|
2246
|
+
* @example Detecting legacy frameworks
|
|
2247
|
+
* ```typescript
|
|
2248
|
+
* const results = detectLegacyFrameworks('/path/to/project', {
|
|
2249
|
+
* dependencies: { jquery: '^3.6.0', backbone: '^1.4.0' },
|
|
2250
|
+
* })
|
|
2251
|
+
* // => [{ id: 'jquery', confidence: 80 }, { id: 'backbone', confidence: 70 }]
|
|
2252
|
+
* ```
|
|
2253
|
+
*/
|
|
2254
|
+
function detectLegacyFrameworks(projectPath, packageJson) {
|
|
2255
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2256
|
+
const results = [];
|
|
2257
|
+
for (const detector of legacyDetectors) {
|
|
2258
|
+
const detection = detector.detect(projectPath, pkg ?? undefined);
|
|
2259
|
+
if (detection) {
|
|
2260
|
+
results.push(detection);
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
return results.sort((a, b) => b.confidence - a.confidence);
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
/**
|
|
2267
|
+
* Detect Biome in project.
|
|
2268
|
+
*
|
|
2269
|
+
* @param projectPath - Project directory path
|
|
2270
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
2271
|
+
* @returns Detection result or null if not detected
|
|
2272
|
+
*
|
|
2273
|
+
* @example Detecting Biome linter
|
|
2274
|
+
* ```typescript
|
|
2275
|
+
* const result = biomeDetector('/path/to/project', {
|
|
2276
|
+
* devDependencies: { '@biomejs/biome': '^1.5.0' },
|
|
2277
|
+
* })
|
|
2278
|
+
* // => { id: 'biome', name: 'Biome', confidence: 70, version: '1.5.0', ... }
|
|
2279
|
+
* ```
|
|
2280
|
+
*/
|
|
2281
|
+
function biomeDetector(projectPath, packageJson) {
|
|
2282
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2283
|
+
const sources = [];
|
|
2284
|
+
let confidence = 0;
|
|
2285
|
+
let configPath;
|
|
2286
|
+
let version;
|
|
2287
|
+
const deps = collectAllDependencies(pkg);
|
|
2288
|
+
if (deps['@biomejs/biome']) {
|
|
2289
|
+
confidence += 70;
|
|
2290
|
+
version = parseVersionString(deps['@biomejs/biome']);
|
|
2291
|
+
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2292
|
+
}
|
|
2293
|
+
if (exists(node_path.join(projectPath, 'biome.json'))) {
|
|
2294
|
+
confidence += 30;
|
|
2295
|
+
configPath = 'biome.json';
|
|
2296
|
+
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2297
|
+
}
|
|
2298
|
+
if (!configPath && exists(node_path.join(projectPath, 'biome.jsonc'))) {
|
|
2299
|
+
confidence += 30;
|
|
2300
|
+
configPath = 'biome.jsonc';
|
|
2301
|
+
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
2302
|
+
}
|
|
2303
|
+
if (confidence === 0) {
|
|
2304
|
+
return null;
|
|
2305
|
+
}
|
|
2306
|
+
return {
|
|
2307
|
+
id: 'biome',
|
|
2308
|
+
name: 'Biome',
|
|
2320
2309
|
version,
|
|
2321
|
-
|
|
2310
|
+
configPath,
|
|
2311
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2322
2312
|
detectedFrom: sources,
|
|
2323
2313
|
};
|
|
2324
2314
|
}
|
|
2325
2315
|
|
|
2326
|
-
/** All legacy framework detectors */
|
|
2327
|
-
const legacyDetectors = [
|
|
2328
|
-
{ id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
|
|
2329
|
-
{ id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
|
|
2330
|
-
{ id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
|
|
2331
|
-
{ id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
|
|
2332
|
-
];
|
|
2333
|
-
/**
|
|
2334
|
-
* Detect all legacy frameworks in project.
|
|
2335
|
-
*
|
|
2336
|
-
* @param projectPath - Project directory path
|
|
2337
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2338
|
-
* @returns Array of detected legacy frameworks, sorted by confidence
|
|
2339
|
-
*/
|
|
2340
|
-
function detectLegacyFrameworks(projectPath, packageJson) {
|
|
2341
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2342
|
-
const results = [];
|
|
2343
|
-
for (const detector of legacyDetectors) {
|
|
2344
|
-
const detection = detector.detect(projectPath, pkg ?? undefined);
|
|
2345
|
-
if (detection) {
|
|
2346
|
-
results.push(detection);
|
|
2347
|
-
}
|
|
2348
|
-
}
|
|
2349
|
-
return results.sort((a, b) => b.confidence - a.confidence);
|
|
2350
|
-
}
|
|
2351
|
-
|
|
2352
2316
|
/** Config patterns for ESLint */
|
|
2353
2317
|
const ESLINT_CONFIG_PATTERNS = [
|
|
2354
2318
|
'eslint.config.js',
|
|
@@ -2368,6 +2332,15 @@ const ESLINT_CONFIG_PATTERNS = [
|
|
|
2368
2332
|
* @param projectPath - Project directory path
|
|
2369
2333
|
* @param packageJson - Optional pre-loaded package.json
|
|
2370
2334
|
* @returns Detection result or null if not detected
|
|
2335
|
+
*
|
|
2336
|
+
* @example Detecting ESLint linter
|
|
2337
|
+
* ```typescript
|
|
2338
|
+
* const result = eslintDetector('/path/to/project', {
|
|
2339
|
+
* devDependencies: { eslint: '^8.50.0', '@typescript-eslint/parser': '^6.0.0' },
|
|
2340
|
+
* scripts: { lint: 'eslint src/' },
|
|
2341
|
+
* })
|
|
2342
|
+
* // => { id: 'eslint', name: 'ESLint', confidence: 65, version: '8.50.0', ... }
|
|
2343
|
+
* ```
|
|
2371
2344
|
*/
|
|
2372
2345
|
function eslintDetector(projectPath, packageJson) {
|
|
2373
2346
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2389,7 +2362,7 @@ function eslintDetector(projectPath, packageJson) {
|
|
|
2389
2362
|
confidence += 30;
|
|
2390
2363
|
sources.push({ type: 'package.json', field: 'eslintConfig' });
|
|
2391
2364
|
}
|
|
2392
|
-
const eslintPlugins = keys(deps).filter((d) => d.startsWith('eslint-plugin-') || d.startsWith('@typescript-eslint/') || d.startsWith('eslint-config-'));
|
|
2365
|
+
const eslintPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('eslint-plugin-') || d.startsWith('@typescript-eslint/') || d.startsWith('eslint-config-'));
|
|
2393
2366
|
if (eslintPlugins.length > 0) {
|
|
2394
2367
|
confidence += 10;
|
|
2395
2368
|
sources.push({ type: 'package.json', field: 'dependencies (eslint plugins)' });
|
|
@@ -2407,7 +2380,7 @@ function eslintDetector(projectPath, packageJson) {
|
|
|
2407
2380
|
name: 'ESLint',
|
|
2408
2381
|
version,
|
|
2409
2382
|
configPath,
|
|
2410
|
-
confidence: min(confidence, 100),
|
|
2383
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2411
2384
|
detectedFrom: sources,
|
|
2412
2385
|
};
|
|
2413
2386
|
}
|
|
@@ -2431,6 +2404,15 @@ const PRETTIER_CONFIG_PATTERNS = [
|
|
|
2431
2404
|
* @param projectPath - Project directory path
|
|
2432
2405
|
* @param packageJson - Optional pre-loaded package.json
|
|
2433
2406
|
* @returns Detection result or null if not detected
|
|
2407
|
+
*
|
|
2408
|
+
* @example Detecting Prettier formatter
|
|
2409
|
+
* ```typescript
|
|
2410
|
+
* const result = prettierDetector('/path/to/project', {
|
|
2411
|
+
* devDependencies: { prettier: '^3.0.0' },
|
|
2412
|
+
* scripts: { format: 'prettier --write .' },
|
|
2413
|
+
* })
|
|
2414
|
+
* // => { id: 'prettier', name: 'Prettier', confidence: 55, version: '3.0.0', ... }
|
|
2415
|
+
* ```
|
|
2434
2416
|
*/
|
|
2435
2417
|
function prettierDetector(projectPath, packageJson) {
|
|
2436
2418
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2456,7 +2438,7 @@ function prettierDetector(projectPath, packageJson) {
|
|
|
2456
2438
|
confidence += 10;
|
|
2457
2439
|
sources.push({ type: 'config-file', path: '.prettierignore' });
|
|
2458
2440
|
}
|
|
2459
|
-
const prettierPlugins = keys(deps).filter((d) => d.startsWith('prettier-plugin-'));
|
|
2441
|
+
const prettierPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('prettier-plugin-'));
|
|
2460
2442
|
if (prettierPlugins.length > 0) {
|
|
2461
2443
|
confidence += 5;
|
|
2462
2444
|
sources.push({ type: 'package.json', field: 'dependencies (prettier plugins)' });
|
|
@@ -2474,7 +2456,7 @@ function prettierDetector(projectPath, packageJson) {
|
|
|
2474
2456
|
name: 'Prettier',
|
|
2475
2457
|
version,
|
|
2476
2458
|
configPath,
|
|
2477
|
-
confidence: min(confidence, 100),
|
|
2459
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2478
2460
|
detectedFrom: sources,
|
|
2479
2461
|
};
|
|
2480
2462
|
}
|
|
@@ -2493,6 +2475,14 @@ const STYLELINT_CONFIG_PATTERNS = [
|
|
|
2493
2475
|
* @param projectPath - Project directory path
|
|
2494
2476
|
* @param packageJson - Optional pre-loaded package.json
|
|
2495
2477
|
* @returns Detection result or null if not detected
|
|
2478
|
+
*
|
|
2479
|
+
* @example Detecting Stylelint linter
|
|
2480
|
+
* ```typescript
|
|
2481
|
+
* const result = stylelintDetector('/path/to/project', {
|
|
2482
|
+
* devDependencies: { stylelint: '^15.0.0', 'stylelint-config-standard': '^30.0.0' },
|
|
2483
|
+
* })
|
|
2484
|
+
* // => { id: 'stylelint', name: 'Stylelint', confidence: 65, version: '15.0.0', ... }
|
|
2485
|
+
* ```
|
|
2496
2486
|
*/
|
|
2497
2487
|
function stylelintDetector(projectPath, packageJson) {
|
|
2498
2488
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2514,7 +2504,7 @@ function stylelintDetector(projectPath, packageJson) {
|
|
|
2514
2504
|
break;
|
|
2515
2505
|
}
|
|
2516
2506
|
}
|
|
2517
|
-
const stylelintPlugins = keys(deps).filter((d) => d.startsWith('stylelint-'));
|
|
2507
|
+
const stylelintPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('stylelint-'));
|
|
2518
2508
|
if (stylelintPlugins.length > 0) {
|
|
2519
2509
|
confidence += 5;
|
|
2520
2510
|
sources.push({ type: 'package.json', field: 'dependencies (stylelint plugins)' });
|
|
@@ -2527,49 +2517,7 @@ function stylelintDetector(projectPath, packageJson) {
|
|
|
2527
2517
|
name: 'Stylelint',
|
|
2528
2518
|
version,
|
|
2529
2519
|
configPath,
|
|
2530
|
-
confidence: min(confidence, 100),
|
|
2531
|
-
detectedFrom: sources,
|
|
2532
|
-
};
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
|
-
/**
|
|
2536
|
-
* Detect Biome in project.
|
|
2537
|
-
*
|
|
2538
|
-
* @param projectPath - Project directory path
|
|
2539
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2540
|
-
* @returns Detection result or null if not detected
|
|
2541
|
-
*/
|
|
2542
|
-
function biomeDetector(projectPath, packageJson) {
|
|
2543
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2544
|
-
const sources = [];
|
|
2545
|
-
let confidence = 0;
|
|
2546
|
-
let configPath;
|
|
2547
|
-
let version;
|
|
2548
|
-
const deps = collectAllDependencies(pkg);
|
|
2549
|
-
if (deps['@biomejs/biome']) {
|
|
2550
|
-
confidence += 70;
|
|
2551
|
-
version = parseVersionString(deps['@biomejs/biome']);
|
|
2552
|
-
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2553
|
-
}
|
|
2554
|
-
if (exists(node_path.join(projectPath, 'biome.json'))) {
|
|
2555
|
-
confidence += 30;
|
|
2556
|
-
configPath = 'biome.json';
|
|
2557
|
-
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2558
|
-
}
|
|
2559
|
-
if (!configPath && exists(node_path.join(projectPath, 'biome.jsonc'))) {
|
|
2560
|
-
confidence += 30;
|
|
2561
|
-
configPath = 'biome.jsonc';
|
|
2562
|
-
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
2563
|
-
}
|
|
2564
|
-
if (confidence === 0) {
|
|
2565
|
-
return null;
|
|
2566
|
-
}
|
|
2567
|
-
return {
|
|
2568
|
-
id: 'biome',
|
|
2569
|
-
name: 'Biome',
|
|
2570
|
-
version,
|
|
2571
|
-
configPath,
|
|
2572
|
-
confidence: min(confidence, 100),
|
|
2520
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2573
2521
|
detectedFrom: sources,
|
|
2574
2522
|
};
|
|
2575
2523
|
}
|
|
@@ -2587,6 +2535,14 @@ const lintingDetectors = [
|
|
|
2587
2535
|
* @param projectPath - Project directory path
|
|
2588
2536
|
* @param packageJson - Optional pre-loaded package.json
|
|
2589
2537
|
* @returns Array of detected linting tools, sorted by confidence
|
|
2538
|
+
*
|
|
2539
|
+
* @example Detecting multiple linting tools
|
|
2540
|
+
* ```typescript
|
|
2541
|
+
* const results = detectLintingTools('/path/to/project', {
|
|
2542
|
+
* devDependencies: { eslint: '^8.0.0', prettier: '^3.0.0' },
|
|
2543
|
+
* })
|
|
2544
|
+
* // => [{ id: 'eslint', confidence: 50 }, { id: 'prettier', confidence: 50 }]
|
|
2545
|
+
* ```
|
|
2590
2546
|
*/
|
|
2591
2547
|
function detectLintingTools(projectPath, packageJson) {
|
|
2592
2548
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2601,140 +2557,179 @@ function detectLintingTools(projectPath, packageJson) {
|
|
|
2601
2557
|
}
|
|
2602
2558
|
|
|
2603
2559
|
/**
|
|
2604
|
-
* Detect
|
|
2560
|
+
* Detect Lerna in project.
|
|
2605
2561
|
*
|
|
2606
2562
|
* @param workspacePath - Workspace directory path
|
|
2607
2563
|
* @param packageJson - Optional pre-loaded package.json
|
|
2608
2564
|
* @returns Detection result or null if not detected
|
|
2565
|
+
*
|
|
2566
|
+
* @example Detecting Lerna monorepo
|
|
2567
|
+
* ```typescript
|
|
2568
|
+
* // Project with lerna.json config file
|
|
2569
|
+
* const result = lernaDetector('/path/to/lerna-project')
|
|
2570
|
+
* // => {
|
|
2571
|
+
* // id: 'lerna',
|
|
2572
|
+
* // name: 'Lerna',
|
|
2573
|
+
* // confidence: 80,
|
|
2574
|
+
* // configPath: 'lerna.json',
|
|
2575
|
+
* // detectedFrom: [{ type: 'config-file', path: 'lerna.json' }]
|
|
2576
|
+
* // }
|
|
2577
|
+
* ```
|
|
2609
2578
|
*/
|
|
2610
|
-
function
|
|
2579
|
+
function lernaDetector(workspacePath, packageJson) {
|
|
2611
2580
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2612
2581
|
const sources = [];
|
|
2613
2582
|
let confidence = 0;
|
|
2614
2583
|
let version;
|
|
2615
|
-
let
|
|
2616
|
-
const
|
|
2617
|
-
if (exists(
|
|
2618
|
-
confidence +=
|
|
2619
|
-
|
|
2584
|
+
let configPath;
|
|
2585
|
+
const lernaJsonPath = node_path.join(workspacePath, 'lerna.json');
|
|
2586
|
+
if (exists(lernaJsonPath)) {
|
|
2587
|
+
confidence += 80;
|
|
2588
|
+
configPath = 'lerna.json';
|
|
2589
|
+
sources.push({ type: 'config-file', path: 'lerna.json' });
|
|
2620
2590
|
}
|
|
2621
2591
|
const deps = collectAllDependencies(pkg);
|
|
2622
|
-
if (deps['
|
|
2623
|
-
confidence +=
|
|
2624
|
-
version = parseVersionString(deps['
|
|
2625
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2626
|
-
}
|
|
2627
|
-
const hasApps = exists(node_path.join(workspacePath, 'apps'));
|
|
2628
|
-
const hasLibs = exists(node_path.join(workspacePath, 'libs'));
|
|
2629
|
-
if (hasApps || hasLibs) {
|
|
2630
|
-
confidence += 10;
|
|
2631
|
-
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
2632
|
-
workspaceLayout = {
|
|
2633
|
-
appsDir: hasApps ? 'apps' : '',
|
|
2634
|
-
libsDir: hasLibs ? 'libs' : '',
|
|
2635
|
-
};
|
|
2592
|
+
if (deps['lerna']) {
|
|
2593
|
+
confidence += 15;
|
|
2594
|
+
version = parseVersionString(deps['lerna']);
|
|
2595
|
+
sources.push({ type: 'package.json', field: 'dependencies.lerna' });
|
|
2636
2596
|
}
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
sources.push({ type: 'package.json', field: '@nx/* packages' });
|
|
2597
|
+
if (exists(node_path.join(workspacePath, 'packages'))) {
|
|
2598
|
+
confidence += 5;
|
|
2599
|
+
sources.push({ type: 'directory', path: 'packages/' });
|
|
2641
2600
|
}
|
|
2642
2601
|
if (confidence === 0) {
|
|
2643
2602
|
return null;
|
|
2644
2603
|
}
|
|
2645
2604
|
return {
|
|
2646
|
-
id: '
|
|
2647
|
-
name: '
|
|
2605
|
+
id: 'lerna',
|
|
2606
|
+
name: 'Lerna',
|
|
2648
2607
|
version,
|
|
2649
|
-
configPath
|
|
2650
|
-
confidence: min(confidence, 100),
|
|
2608
|
+
configPath,
|
|
2609
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2651
2610
|
detectedFrom: sources,
|
|
2652
|
-
workspaceLayout,
|
|
2653
2611
|
};
|
|
2654
2612
|
}
|
|
2655
2613
|
|
|
2656
2614
|
/**
|
|
2657
|
-
* Detect
|
|
2615
|
+
* Detect npm workspaces in project.
|
|
2658
2616
|
*
|
|
2659
2617
|
* @param workspacePath - Workspace directory path
|
|
2660
2618
|
* @param packageJson - Optional pre-loaded package.json
|
|
2661
2619
|
* @returns Detection result or null if not detected
|
|
2620
|
+
*
|
|
2621
|
+
* @example Detecting npm workspaces
|
|
2622
|
+
* ```typescript
|
|
2623
|
+
* // Project with workspaces in package.json and package-lock.json
|
|
2624
|
+
* const result = npmWorkspacesDetector('/path/to/npm-project')
|
|
2625
|
+
* // => {
|
|
2626
|
+
* // id: 'npm-workspaces',
|
|
2627
|
+
* // name: 'npm Workspaces',
|
|
2628
|
+
* // confidence: 90,
|
|
2629
|
+
* // configPath: 'package.json',
|
|
2630
|
+
* // detectedFrom: [
|
|
2631
|
+
* // { type: 'package.json', field: 'workspaces' },
|
|
2632
|
+
* // { type: 'lockfile', path: 'package-lock.json' }
|
|
2633
|
+
* // ]
|
|
2634
|
+
* // }
|
|
2635
|
+
* ```
|
|
2662
2636
|
*/
|
|
2663
|
-
function
|
|
2637
|
+
function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
2664
2638
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2665
2639
|
const sources = [];
|
|
2666
2640
|
let confidence = 0;
|
|
2667
|
-
|
|
2668
|
-
let configPath;
|
|
2669
|
-
const turboJsonPath = node_path.join(workspacePath, 'turbo.json');
|
|
2670
|
-
if (exists(turboJsonPath)) {
|
|
2641
|
+
if (pkg?.workspaces) {
|
|
2671
2642
|
confidence += 80;
|
|
2672
|
-
|
|
2673
|
-
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2643
|
+
sources.push({ type: 'package.json', field: 'workspaces' });
|
|
2674
2644
|
}
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
version = parseVersionString(deps['turbo']);
|
|
2679
|
-
sources.push({ type: 'package.json', field: 'dependencies.turbo' });
|
|
2645
|
+
if (exists(node_path.join(workspacePath, 'package-lock.json'))) {
|
|
2646
|
+
confidence += 10;
|
|
2647
|
+
sources.push({ type: 'lockfile', path: 'package-lock.json' });
|
|
2680
2648
|
}
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
confidence += 5;
|
|
2684
|
-
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
2649
|
+
if (exists(node_path.join(workspacePath, 'yarn.lock'))) {
|
|
2650
|
+
return null;
|
|
2685
2651
|
}
|
|
2686
2652
|
if (confidence === 0) {
|
|
2687
2653
|
return null;
|
|
2688
2654
|
}
|
|
2689
2655
|
return {
|
|
2690
|
-
id: '
|
|
2691
|
-
name: '
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
confidence: min(confidence, 100),
|
|
2656
|
+
id: 'npm-workspaces',
|
|
2657
|
+
name: 'npm Workspaces',
|
|
2658
|
+
configPath: 'package.json',
|
|
2659
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2695
2660
|
detectedFrom: sources,
|
|
2696
2661
|
};
|
|
2697
2662
|
}
|
|
2698
2663
|
|
|
2699
2664
|
/**
|
|
2700
|
-
* Detect
|
|
2665
|
+
* Detect NX in project.
|
|
2701
2666
|
*
|
|
2702
2667
|
* @param workspacePath - Workspace directory path
|
|
2703
2668
|
* @param packageJson - Optional pre-loaded package.json
|
|
2704
2669
|
* @returns Detection result or null if not detected
|
|
2670
|
+
*
|
|
2671
|
+
* @example Detecting NX workspace
|
|
2672
|
+
* ```typescript
|
|
2673
|
+
* // Project with nx.json and apps/libs directories
|
|
2674
|
+
* const result = nxDetector('/path/to/nx-workspace')
|
|
2675
|
+
* // => {
|
|
2676
|
+
* // id: 'nx',
|
|
2677
|
+
* // name: 'NX',
|
|
2678
|
+
* // confidence: 100,
|
|
2679
|
+
* // configPath: 'nx.json',
|
|
2680
|
+
* // version: '17.0.0',
|
|
2681
|
+
* // workspaceLayout: { appsDir: 'apps', libsDir: 'libs' },
|
|
2682
|
+
* // detectedFrom: [
|
|
2683
|
+
* // { type: 'config-file', path: 'nx.json' },
|
|
2684
|
+
* // { type: 'package.json', field: 'dependencies.nx' },
|
|
2685
|
+
* // { type: 'directory', path: 'apps/ or libs/' }
|
|
2686
|
+
* // ]
|
|
2687
|
+
* // }
|
|
2688
|
+
* ```
|
|
2705
2689
|
*/
|
|
2706
|
-
function
|
|
2690
|
+
function nxDetector(workspacePath, packageJson) {
|
|
2707
2691
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2708
2692
|
const sources = [];
|
|
2709
2693
|
let confidence = 0;
|
|
2710
2694
|
let version;
|
|
2711
|
-
let
|
|
2712
|
-
const
|
|
2713
|
-
if (exists(
|
|
2714
|
-
confidence +=
|
|
2715
|
-
|
|
2716
|
-
sources.push({ type: 'config-file', path: 'lerna.json' });
|
|
2695
|
+
let workspaceLayout;
|
|
2696
|
+
const nxJsonPath = node_path.join(workspacePath, 'nx.json');
|
|
2697
|
+
if (exists(nxJsonPath)) {
|
|
2698
|
+
confidence += 70;
|
|
2699
|
+
sources.push({ type: 'config-file', path: 'nx.json' });
|
|
2717
2700
|
}
|
|
2718
2701
|
const deps = collectAllDependencies(pkg);
|
|
2719
|
-
if (deps['
|
|
2720
|
-
confidence +=
|
|
2721
|
-
version = parseVersionString(deps['
|
|
2722
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2702
|
+
if (deps['nx']) {
|
|
2703
|
+
confidence += 20;
|
|
2704
|
+
version = parseVersionString(deps['nx']);
|
|
2705
|
+
sources.push({ type: 'package.json', field: 'dependencies.nx' });
|
|
2723
2706
|
}
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2707
|
+
const hasApps = exists(node_path.join(workspacePath, 'apps'));
|
|
2708
|
+
const hasLibs = exists(node_path.join(workspacePath, 'libs'));
|
|
2709
|
+
if (hasApps || hasLibs) {
|
|
2710
|
+
confidence += 10;
|
|
2711
|
+
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
2712
|
+
workspaceLayout = {
|
|
2713
|
+
appsDir: hasApps ? 'apps' : '',
|
|
2714
|
+
libsDir: hasLibs ? 'libs' : '',
|
|
2715
|
+
};
|
|
2716
|
+
}
|
|
2717
|
+
const nxPackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@nx/') || d.startsWith('@nrwl/'));
|
|
2718
|
+
if (nxPackages.length > 0) {
|
|
2719
|
+
confidence += 10;
|
|
2720
|
+
sources.push({ type: 'package.json', field: '@nx/* packages' });
|
|
2727
2721
|
}
|
|
2728
2722
|
if (confidence === 0) {
|
|
2729
2723
|
return null;
|
|
2730
2724
|
}
|
|
2731
2725
|
return {
|
|
2732
|
-
id: '
|
|
2733
|
-
name: '
|
|
2726
|
+
id: 'nx',
|
|
2727
|
+
name: 'NX',
|
|
2734
2728
|
version,
|
|
2735
|
-
configPath,
|
|
2736
|
-
confidence: min(confidence, 100),
|
|
2729
|
+
configPath: exists(nxJsonPath) ? 'nx.json' : undefined,
|
|
2730
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2737
2731
|
detectedFrom: sources,
|
|
2732
|
+
workspaceLayout,
|
|
2738
2733
|
};
|
|
2739
2734
|
}
|
|
2740
2735
|
|
|
@@ -2744,6 +2739,19 @@ function lernaDetector(workspacePath, packageJson) {
|
|
|
2744
2739
|
* @param workspacePath - Workspace directory path
|
|
2745
2740
|
* @param packageJson - Optional pre-loaded package.json
|
|
2746
2741
|
* @returns Detection result or null if not detected
|
|
2742
|
+
*
|
|
2743
|
+
* @example Detecting Rush monorepo
|
|
2744
|
+
* ```typescript
|
|
2745
|
+
* // Project with rush.json config file
|
|
2746
|
+
* const result = rushDetector('/path/to/rush-project')
|
|
2747
|
+
* // => {
|
|
2748
|
+
* // id: 'rush',
|
|
2749
|
+
* // name: 'Rush',
|
|
2750
|
+
* // confidence: 90,
|
|
2751
|
+
* // configPath: 'rush.json',
|
|
2752
|
+
* // detectedFrom: [{ type: 'config-file', path: 'rush.json' }]
|
|
2753
|
+
* // }
|
|
2754
|
+
* ```
|
|
2747
2755
|
*/
|
|
2748
2756
|
function rushDetector(workspacePath, packageJson) {
|
|
2749
2757
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2775,73 +2783,67 @@ function rushDetector(workspacePath, packageJson) {
|
|
|
2775
2783
|
name: 'Rush',
|
|
2776
2784
|
version,
|
|
2777
2785
|
configPath,
|
|
2778
|
-
confidence: min(confidence, 100),
|
|
2779
|
-
detectedFrom: sources,
|
|
2780
|
-
};
|
|
2781
|
-
}
|
|
2782
|
-
|
|
2783
|
-
/**
|
|
2784
|
-
* Detect pnpm workspaces in project.
|
|
2785
|
-
*
|
|
2786
|
-
* @param workspacePath - Workspace directory path
|
|
2787
|
-
* @returns Detection result or null if not detected
|
|
2788
|
-
*/
|
|
2789
|
-
function pnpmWorkspacesDetector(workspacePath) {
|
|
2790
|
-
const sources = [];
|
|
2791
|
-
let confidence = 0;
|
|
2792
|
-
let configPath;
|
|
2793
|
-
const pnpmWorkspacePath = node_path.join(workspacePath, 'pnpm-workspace.yaml');
|
|
2794
|
-
if (exists(pnpmWorkspacePath)) {
|
|
2795
|
-
confidence += 90;
|
|
2796
|
-
configPath = 'pnpm-workspace.yaml';
|
|
2797
|
-
sources.push({ type: 'config-file', path: 'pnpm-workspace.yaml' });
|
|
2798
|
-
}
|
|
2799
|
-
if (exists(node_path.join(workspacePath, 'pnpm-lock.yaml'))) {
|
|
2800
|
-
confidence += 10;
|
|
2801
|
-
sources.push({ type: 'lockfile', path: 'pnpm-lock.yaml' });
|
|
2802
|
-
}
|
|
2803
|
-
if (confidence === 0) {
|
|
2804
|
-
return null;
|
|
2805
|
-
}
|
|
2806
|
-
return {
|
|
2807
|
-
id: 'pnpm-workspaces',
|
|
2808
|
-
name: 'pnpm Workspaces',
|
|
2809
|
-
configPath,
|
|
2810
|
-
confidence: min(confidence, 100),
|
|
2786
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2811
2787
|
detectedFrom: sources,
|
|
2812
2788
|
};
|
|
2813
2789
|
}
|
|
2814
2790
|
|
|
2815
2791
|
/**
|
|
2816
|
-
* Detect
|
|
2792
|
+
* Detect Turborepo in project.
|
|
2817
2793
|
*
|
|
2818
2794
|
* @param workspacePath - Workspace directory path
|
|
2819
2795
|
* @param packageJson - Optional pre-loaded package.json
|
|
2820
2796
|
* @returns Detection result or null if not detected
|
|
2797
|
+
*
|
|
2798
|
+
* @example Detecting Turborepo monorepo
|
|
2799
|
+
* ```typescript
|
|
2800
|
+
* // Project with turbo.json and turbo dependency
|
|
2801
|
+
* const result = turborepoDetector('/path/to/turbo-project')
|
|
2802
|
+
* // => {
|
|
2803
|
+
* // id: 'turborepo',
|
|
2804
|
+
* // name: 'Turborepo',
|
|
2805
|
+
* // confidence: 95,
|
|
2806
|
+
* // configPath: 'turbo.json',
|
|
2807
|
+
* // version: '2.0.0',
|
|
2808
|
+
* // detectedFrom: [
|
|
2809
|
+
* // { type: 'config-file', path: 'turbo.json' },
|
|
2810
|
+
* // { type: 'package.json', field: 'dependencies.turbo' }
|
|
2811
|
+
* // ]
|
|
2812
|
+
* // }
|
|
2813
|
+
* ```
|
|
2821
2814
|
*/
|
|
2822
|
-
function
|
|
2815
|
+
function turborepoDetector(workspacePath, packageJson) {
|
|
2823
2816
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2824
2817
|
const sources = [];
|
|
2825
2818
|
let confidence = 0;
|
|
2826
|
-
|
|
2819
|
+
let version;
|
|
2820
|
+
let configPath;
|
|
2821
|
+
const turboJsonPath = node_path.join(workspacePath, 'turbo.json');
|
|
2822
|
+
if (exists(turboJsonPath)) {
|
|
2827
2823
|
confidence += 80;
|
|
2828
|
-
|
|
2824
|
+
configPath = 'turbo.json';
|
|
2825
|
+
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2829
2826
|
}
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2827
|
+
const deps = collectAllDependencies(pkg);
|
|
2828
|
+
if (deps['turbo']) {
|
|
2829
|
+
confidence += 15;
|
|
2830
|
+
version = parseVersionString(deps['turbo']);
|
|
2831
|
+
sources.push({ type: 'package.json', field: 'dependencies.turbo' });
|
|
2833
2832
|
}
|
|
2834
|
-
|
|
2835
|
-
|
|
2833
|
+
const scripts = pkg?.scripts ?? {};
|
|
2834
|
+
if (index_cjs_js$2.values(scripts).some((s) => s?.includes('turbo'))) {
|
|
2835
|
+
confidence += 5;
|
|
2836
|
+
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
2836
2837
|
}
|
|
2837
2838
|
if (confidence === 0) {
|
|
2838
2839
|
return null;
|
|
2839
2840
|
}
|
|
2840
2841
|
return {
|
|
2841
|
-
id: '
|
|
2842
|
-
name: '
|
|
2843
|
-
|
|
2844
|
-
|
|
2842
|
+
id: 'turborepo',
|
|
2843
|
+
name: 'Turborepo',
|
|
2844
|
+
version,
|
|
2845
|
+
configPath,
|
|
2846
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2845
2847
|
detectedFrom: sources,
|
|
2846
2848
|
};
|
|
2847
2849
|
}
|
|
@@ -2852,6 +2854,23 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
|
2852
2854
|
* @param workspacePath - Workspace directory path
|
|
2853
2855
|
* @param packageJson - Optional pre-loaded package.json
|
|
2854
2856
|
* @returns Detection result or null if not detected
|
|
2857
|
+
*
|
|
2858
|
+
* @example Detecting yarn workspaces
|
|
2859
|
+
* ```typescript
|
|
2860
|
+
* // Project with workspaces in package.json and yarn.lock
|
|
2861
|
+
* const result = yarnWorkspacesDetector('/path/to/yarn-project')
|
|
2862
|
+
* // => {
|
|
2863
|
+
* // id: 'yarn-workspaces',
|
|
2864
|
+
* // name: 'Yarn Workspaces',
|
|
2865
|
+
* // confidence: 100,
|
|
2866
|
+
* // configPath: 'package.json',
|
|
2867
|
+
* // detectedFrom: [
|
|
2868
|
+
* // { type: 'package.json', field: 'workspaces' },
|
|
2869
|
+
* // { type: 'lockfile', path: 'yarn.lock' },
|
|
2870
|
+
* // { type: 'config-file', path: '.yarnrc.yml' }
|
|
2871
|
+
* // ]
|
|
2872
|
+
* // }
|
|
2873
|
+
* ```
|
|
2855
2874
|
*/
|
|
2856
2875
|
function yarnWorkspacesDetector(workspacePath, packageJson) {
|
|
2857
2876
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2876,7 +2895,7 @@ function yarnWorkspacesDetector(workspacePath, packageJson) {
|
|
|
2876
2895
|
id: 'yarn-workspaces',
|
|
2877
2896
|
name: 'Yarn Workspaces',
|
|
2878
2897
|
configPath: 'package.json',
|
|
2879
|
-
confidence: min(confidence, 100),
|
|
2898
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2880
2899
|
detectedFrom: sources,
|
|
2881
2900
|
};
|
|
2882
2901
|
}
|
|
@@ -2897,6 +2916,15 @@ const monorepoDetectors = [
|
|
|
2897
2916
|
* @param workspacePath - Workspace directory path
|
|
2898
2917
|
* @param packageJson - Optional pre-loaded package.json
|
|
2899
2918
|
* @returns Array of detected monorepo tools, sorted by confidence
|
|
2919
|
+
*
|
|
2920
|
+
* @example Detecting monorepo tools
|
|
2921
|
+
* ```typescript
|
|
2922
|
+
* const detections = detectMonorepoTools('/path/to/project')
|
|
2923
|
+
* // => [
|
|
2924
|
+
* // { id: 'nx', name: 'NX', confidence: 90, configPath: 'nx.json', detectedFrom: [...] },
|
|
2925
|
+
* // { id: 'npm-workspaces', name: 'npm Workspaces', confidence: 80, ... }
|
|
2926
|
+
* // ]
|
|
2927
|
+
* ```
|
|
2900
2928
|
*/
|
|
2901
2929
|
function detectMonorepoTools(workspacePath, packageJson) {
|
|
2902
2930
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2910,111 +2938,129 @@ function detectMonorepoTools(workspacePath, packageJson) {
|
|
|
2910
2938
|
return results.sort((a, b) => b.confidence - a.confidence);
|
|
2911
2939
|
}
|
|
2912
2940
|
|
|
2913
|
-
/** Config patterns for
|
|
2914
|
-
const
|
|
2941
|
+
/** Config patterns for Cypress */
|
|
2942
|
+
const CYPRESS_CONFIG_PATTERNS = ['cypress.config.js', 'cypress.config.ts', 'cypress.config.mjs', 'cypress.json'];
|
|
2915
2943
|
/**
|
|
2916
|
-
* Detect
|
|
2944
|
+
* Detect Cypress in project.
|
|
2917
2945
|
*
|
|
2918
2946
|
* @param projectPath - Project directory path
|
|
2919
2947
|
* @param packageJson - Optional pre-loaded package.json
|
|
2920
2948
|
* @returns Detection result or null if not detected
|
|
2949
|
+
*
|
|
2950
|
+
* @example Detecting Cypress testing framework
|
|
2951
|
+
* ```typescript
|
|
2952
|
+
* import { cypressDetector } from '@hyperfrontend/project-scope'
|
|
2953
|
+
*
|
|
2954
|
+
* const result = cypressDetector('./my-project')
|
|
2955
|
+
* if (result) {
|
|
2956
|
+
* console.log(`Cypress ${result.version} detected (${result.confidence}% confidence)`)
|
|
2957
|
+
* // => "Cypress 13.6.0 detected (95% confidence)"
|
|
2958
|
+
* }
|
|
2959
|
+
* ```
|
|
2921
2960
|
*/
|
|
2922
|
-
function
|
|
2961
|
+
function cypressDetector(projectPath, packageJson) {
|
|
2923
2962
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2924
2963
|
const sources = [];
|
|
2925
2964
|
let confidence = 0;
|
|
2926
2965
|
let version;
|
|
2927
2966
|
const deps = collectAllDependencies(pkg);
|
|
2928
|
-
if (deps['
|
|
2967
|
+
if (deps['cypress']) {
|
|
2929
2968
|
confidence += 60;
|
|
2930
|
-
version = parseVersionString(deps['
|
|
2931
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2969
|
+
version = parseVersionString(deps['cypress']);
|
|
2970
|
+
sources.push({ type: 'package.json', field: 'dependencies.cypress' });
|
|
2932
2971
|
}
|
|
2933
|
-
const configPath = locateConfigFile(projectPath,
|
|
2972
|
+
const configPath = locateConfigFile(projectPath, CYPRESS_CONFIG_PATTERNS);
|
|
2934
2973
|
if (configPath) {
|
|
2935
2974
|
confidence += 30;
|
|
2936
2975
|
sources.push({ type: 'config-file', path: configPath });
|
|
2937
2976
|
}
|
|
2938
|
-
if (
|
|
2939
|
-
confidence += 20;
|
|
2940
|
-
sources.push({ type: 'package.json', field: 'jest' });
|
|
2941
|
-
}
|
|
2942
|
-
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
2943
|
-
if (testScript.includes('jest')) {
|
|
2977
|
+
if (exists(node_path.join(projectPath, 'cypress'))) {
|
|
2944
2978
|
confidence += 10;
|
|
2945
|
-
sources.push({ type: '
|
|
2946
|
-
}
|
|
2947
|
-
if (deps['@types/jest']) {
|
|
2948
|
-
confidence += 5;
|
|
2949
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
2979
|
+
sources.push({ type: 'directory', path: 'cypress/' });
|
|
2950
2980
|
}
|
|
2951
|
-
|
|
2981
|
+
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
2982
|
+
if (e2eScript.includes('cypress')) {
|
|
2952
2983
|
confidence += 5;
|
|
2953
|
-
sources.push({ type: 'package.json', field: '
|
|
2984
|
+
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
2954
2985
|
}
|
|
2955
2986
|
if (confidence === 0) {
|
|
2956
2987
|
return null;
|
|
2957
2988
|
}
|
|
2958
2989
|
return {
|
|
2959
|
-
id: '
|
|
2960
|
-
name: '
|
|
2961
|
-
type: '
|
|
2990
|
+
id: 'cypress',
|
|
2991
|
+
name: 'Cypress',
|
|
2992
|
+
type: 'e2e',
|
|
2962
2993
|
version,
|
|
2963
2994
|
configPath,
|
|
2964
|
-
confidence: min(confidence, 100),
|
|
2995
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
2965
2996
|
detectedFrom: sources,
|
|
2966
2997
|
};
|
|
2967
2998
|
}
|
|
2968
2999
|
|
|
2969
|
-
/** Config patterns for
|
|
2970
|
-
const
|
|
3000
|
+
/** Config patterns for Jest */
|
|
3001
|
+
const JEST_CONFIG_PATTERNS = ['jest.config.js', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json'];
|
|
2971
3002
|
/**
|
|
2972
|
-
* Detect
|
|
3003
|
+
* Detect Jest in project.
|
|
2973
3004
|
*
|
|
2974
3005
|
* @param projectPath - Project directory path
|
|
2975
3006
|
* @param packageJson - Optional pre-loaded package.json
|
|
2976
3007
|
* @returns Detection result or null if not detected
|
|
3008
|
+
*
|
|
3009
|
+
* @example Detecting Jest testing framework
|
|
3010
|
+
* ```typescript
|
|
3011
|
+
* import { jestDetector } from '@hyperfrontend/project-scope'
|
|
3012
|
+
*
|
|
3013
|
+
* const result = jestDetector('./my-project')
|
|
3014
|
+
* if (result) {
|
|
3015
|
+
* console.log(`Jest ${result.version} detected`)
|
|
3016
|
+
* console.log('Sources:', result.detectedFrom.map(s => s.type))
|
|
3017
|
+
* // => "Sources: ['package.json', 'config-file']"
|
|
3018
|
+
* }
|
|
3019
|
+
* ```
|
|
2977
3020
|
*/
|
|
2978
|
-
function
|
|
3021
|
+
function jestDetector(projectPath, packageJson) {
|
|
2979
3022
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2980
3023
|
const sources = [];
|
|
2981
3024
|
let confidence = 0;
|
|
2982
3025
|
let version;
|
|
2983
3026
|
const deps = collectAllDependencies(pkg);
|
|
2984
|
-
if (deps['
|
|
2985
|
-
confidence +=
|
|
2986
|
-
version = parseVersionString(deps['
|
|
2987
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
3027
|
+
if (deps['jest']) {
|
|
3028
|
+
confidence += 60;
|
|
3029
|
+
version = parseVersionString(deps['jest']);
|
|
3030
|
+
sources.push({ type: 'package.json', field: 'dependencies.jest' });
|
|
2988
3031
|
}
|
|
2989
|
-
const configPath = locateConfigFile(projectPath,
|
|
3032
|
+
const configPath = locateConfigFile(projectPath, JEST_CONFIG_PATTERNS);
|
|
2990
3033
|
if (configPath) {
|
|
2991
|
-
confidence +=
|
|
3034
|
+
confidence += 30;
|
|
2992
3035
|
sources.push({ type: 'config-file', path: configPath });
|
|
2993
3036
|
}
|
|
2994
|
-
if (
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
exists(node_path.join(projectPath, 'vite.config.mjs'));
|
|
2998
|
-
if (viteConfig && deps['vitest']) {
|
|
2999
|
-
confidence += 5;
|
|
3000
|
-
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
3001
|
-
}
|
|
3037
|
+
if (pkg && 'jest' in pkg) {
|
|
3038
|
+
confidence += 20;
|
|
3039
|
+
sources.push({ type: 'package.json', field: 'jest' });
|
|
3002
3040
|
}
|
|
3003
3041
|
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
3004
|
-
if (testScript.includes('
|
|
3042
|
+
if (testScript.includes('jest')) {
|
|
3005
3043
|
confidence += 10;
|
|
3006
3044
|
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
3007
3045
|
}
|
|
3046
|
+
if (deps['@types/jest']) {
|
|
3047
|
+
confidence += 5;
|
|
3048
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
3049
|
+
}
|
|
3050
|
+
if (deps['ts-jest']) {
|
|
3051
|
+
confidence += 5;
|
|
3052
|
+
sources.push({ type: 'package.json', field: 'dependencies.ts-jest' });
|
|
3053
|
+
}
|
|
3008
3054
|
if (confidence === 0) {
|
|
3009
3055
|
return null;
|
|
3010
3056
|
}
|
|
3011
3057
|
return {
|
|
3012
|
-
id: '
|
|
3013
|
-
name: '
|
|
3058
|
+
id: 'jest',
|
|
3059
|
+
name: 'Jest',
|
|
3014
3060
|
type: 'unit',
|
|
3015
3061
|
version,
|
|
3016
3062
|
configPath,
|
|
3017
|
-
confidence: min(confidence, 100),
|
|
3063
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
3018
3064
|
detectedFrom: sources,
|
|
3019
3065
|
};
|
|
3020
3066
|
}
|
|
@@ -3027,6 +3073,17 @@ const MOCHA_CONFIG_PATTERNS = ['.mocharc.js', '.mocharc.json', '.mocharc.yaml',
|
|
|
3027
3073
|
* @param projectPath - Project directory path
|
|
3028
3074
|
* @param packageJson - Optional pre-loaded package.json
|
|
3029
3075
|
* @returns Detection result or null if not detected
|
|
3076
|
+
*
|
|
3077
|
+
* @example Detecting Mocha testing framework
|
|
3078
|
+
* ```typescript
|
|
3079
|
+
* import { mochaDetector } from '@hyperfrontend/project-scope'
|
|
3080
|
+
*
|
|
3081
|
+
* const result = mochaDetector('./my-project')
|
|
3082
|
+
* if (result) {
|
|
3083
|
+
* console.log(`Mocha ${result.version} detected (${result.confidence}%)`)
|
|
3084
|
+
* // => "Mocha 10.2.0 detected (95%)"
|
|
3085
|
+
* }
|
|
3086
|
+
* ```
|
|
3030
3087
|
*/
|
|
3031
3088
|
function mochaDetector(projectPath, packageJson) {
|
|
3032
3089
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3066,42 +3123,58 @@ function mochaDetector(projectPath, packageJson) {
|
|
|
3066
3123
|
type: 'unit',
|
|
3067
3124
|
version,
|
|
3068
3125
|
configPath,
|
|
3069
|
-
confidence: min(confidence, 100),
|
|
3126
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
3070
3127
|
detectedFrom: sources,
|
|
3071
3128
|
};
|
|
3072
3129
|
}
|
|
3073
3130
|
|
|
3074
|
-
/** Config patterns for
|
|
3075
|
-
const
|
|
3131
|
+
/** Config patterns for Playwright */
|
|
3132
|
+
const PLAYWRIGHT_CONFIG_PATTERNS = ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs'];
|
|
3076
3133
|
/**
|
|
3077
|
-
* Detect
|
|
3134
|
+
* Detect Playwright in project.
|
|
3078
3135
|
*
|
|
3079
3136
|
* @param projectPath - Project directory path
|
|
3080
3137
|
* @param packageJson - Optional pre-loaded package.json
|
|
3081
3138
|
* @returns Detection result or null if not detected
|
|
3139
|
+
*
|
|
3140
|
+
* @example Detecting Playwright testing framework
|
|
3141
|
+
* ```typescript
|
|
3142
|
+
* import { playwrightDetector } from '@hyperfrontend/project-scope'
|
|
3143
|
+
*
|
|
3144
|
+
* const result = playwrightDetector('./my-project')
|
|
3145
|
+
* if (result) {
|
|
3146
|
+
* console.log(`Playwright ${result.version} (${result.type} tests)`)
|
|
3147
|
+
* // => "Playwright 1.42.0 (e2e tests)"
|
|
3148
|
+
* }
|
|
3149
|
+
* ```
|
|
3082
3150
|
*/
|
|
3083
|
-
function
|
|
3151
|
+
function playwrightDetector(projectPath, packageJson) {
|
|
3084
3152
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3085
3153
|
const sources = [];
|
|
3086
3154
|
let confidence = 0;
|
|
3087
3155
|
let version;
|
|
3088
3156
|
const deps = collectAllDependencies(pkg);
|
|
3089
|
-
if (deps['
|
|
3090
|
-
confidence +=
|
|
3091
|
-
version = parseVersionString(deps['
|
|
3092
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
3157
|
+
if (deps['@playwright/test']) {
|
|
3158
|
+
confidence += 70;
|
|
3159
|
+
version = parseVersionString(deps['@playwright/test']);
|
|
3160
|
+
sources.push({ type: 'package.json', field: 'dependencies.@playwright/test' });
|
|
3093
3161
|
}
|
|
3094
|
-
|
|
3162
|
+
if (deps['playwright']) {
|
|
3163
|
+
confidence += 50;
|
|
3164
|
+
version = version ?? parseVersionString(deps['playwright']);
|
|
3165
|
+
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
3166
|
+
}
|
|
3167
|
+
const configPath = locateConfigFile(projectPath, PLAYWRIGHT_CONFIG_PATTERNS);
|
|
3095
3168
|
if (configPath) {
|
|
3096
|
-
confidence +=
|
|
3169
|
+
confidence += 25;
|
|
3097
3170
|
sources.push({ type: 'config-file', path: configPath });
|
|
3098
3171
|
}
|
|
3099
|
-
if (exists(node_path.join(projectPath, '
|
|
3100
|
-
confidence +=
|
|
3101
|
-
sources.push({ type: 'directory', path: '
|
|
3172
|
+
if (exists(node_path.join(projectPath, 'e2e')) || exists(node_path.join(projectPath, 'tests'))) {
|
|
3173
|
+
confidence += 5;
|
|
3174
|
+
sources.push({ type: 'directory', path: 'e2e/ or tests/' });
|
|
3102
3175
|
}
|
|
3103
3176
|
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
3104
|
-
if (e2eScript.includes('
|
|
3177
|
+
if (e2eScript.includes('playwright')) {
|
|
3105
3178
|
confidence += 5;
|
|
3106
3179
|
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
3107
3180
|
}
|
|
@@ -3109,65 +3182,77 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3109
3182
|
return null;
|
|
3110
3183
|
}
|
|
3111
3184
|
return {
|
|
3112
|
-
id: '
|
|
3113
|
-
name: '
|
|
3185
|
+
id: 'playwright',
|
|
3186
|
+
name: 'Playwright',
|
|
3114
3187
|
type: 'e2e',
|
|
3115
3188
|
version,
|
|
3116
3189
|
configPath,
|
|
3117
|
-
confidence: min(confidence, 100),
|
|
3190
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
3118
3191
|
detectedFrom: sources,
|
|
3119
3192
|
};
|
|
3120
3193
|
}
|
|
3121
3194
|
|
|
3122
|
-
/** Config patterns for
|
|
3123
|
-
const
|
|
3195
|
+
/** Config patterns for Vitest */
|
|
3196
|
+
const VITEST_CONFIG_PATTERNS = ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'];
|
|
3124
3197
|
/**
|
|
3125
|
-
* Detect
|
|
3198
|
+
* Detect Vitest in project.
|
|
3126
3199
|
*
|
|
3127
3200
|
* @param projectPath - Project directory path
|
|
3128
3201
|
* @param packageJson - Optional pre-loaded package.json
|
|
3129
3202
|
* @returns Detection result or null if not detected
|
|
3203
|
+
*
|
|
3204
|
+
* @example Detecting Vitest testing framework
|
|
3205
|
+
* ```typescript
|
|
3206
|
+
* import { vitestDetector } from '@hyperfrontend/project-scope'
|
|
3207
|
+
*
|
|
3208
|
+
* const result = vitestDetector('./my-project')
|
|
3209
|
+
* if (result) {
|
|
3210
|
+
* console.log(`Vitest ${result.version} detected`)
|
|
3211
|
+
* console.log('Config:', result.configPath)
|
|
3212
|
+
* // => "Config: vitest.config.ts"
|
|
3213
|
+
* }
|
|
3214
|
+
* ```
|
|
3130
3215
|
*/
|
|
3131
|
-
function
|
|
3216
|
+
function vitestDetector(projectPath, packageJson) {
|
|
3132
3217
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3133
3218
|
const sources = [];
|
|
3134
3219
|
let confidence = 0;
|
|
3135
3220
|
let version;
|
|
3136
3221
|
const deps = collectAllDependencies(pkg);
|
|
3137
|
-
if (deps['
|
|
3222
|
+
if (deps['vitest']) {
|
|
3138
3223
|
confidence += 70;
|
|
3139
|
-
version = parseVersionString(deps['
|
|
3140
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
3141
|
-
}
|
|
3142
|
-
if (deps['playwright']) {
|
|
3143
|
-
confidence += 50;
|
|
3144
|
-
version = version ?? parseVersionString(deps['playwright']);
|
|
3145
|
-
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
3224
|
+
version = parseVersionString(deps['vitest']);
|
|
3225
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
3146
3226
|
}
|
|
3147
|
-
const configPath = locateConfigFile(projectPath,
|
|
3227
|
+
const configPath = locateConfigFile(projectPath, VITEST_CONFIG_PATTERNS);
|
|
3148
3228
|
if (configPath) {
|
|
3149
3229
|
confidence += 25;
|
|
3150
3230
|
sources.push({ type: 'config-file', path: configPath });
|
|
3151
3231
|
}
|
|
3152
|
-
if (
|
|
3153
|
-
|
|
3154
|
-
|
|
3232
|
+
if (!configPath) {
|
|
3233
|
+
const viteConfig = exists(node_path.join(projectPath, 'vite.config.ts')) ||
|
|
3234
|
+
exists(node_path.join(projectPath, 'vite.config.js')) ||
|
|
3235
|
+
exists(node_path.join(projectPath, 'vite.config.mjs'));
|
|
3236
|
+
if (viteConfig && deps['vitest']) {
|
|
3237
|
+
confidence += 5;
|
|
3238
|
+
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
3239
|
+
}
|
|
3155
3240
|
}
|
|
3156
|
-
const
|
|
3157
|
-
if (
|
|
3158
|
-
confidence +=
|
|
3159
|
-
sources.push({ type: 'package.json', field: 'scripts.
|
|
3241
|
+
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
3242
|
+
if (testScript.includes('vitest')) {
|
|
3243
|
+
confidence += 10;
|
|
3244
|
+
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
3160
3245
|
}
|
|
3161
3246
|
if (confidence === 0) {
|
|
3162
3247
|
return null;
|
|
3163
3248
|
}
|
|
3164
3249
|
return {
|
|
3165
|
-
id: '
|
|
3166
|
-
name: '
|
|
3167
|
-
type: '
|
|
3250
|
+
id: 'vitest',
|
|
3251
|
+
name: 'Vitest',
|
|
3252
|
+
type: 'unit',
|
|
3168
3253
|
version,
|
|
3169
3254
|
configPath,
|
|
3170
|
-
confidence: min(confidence, 100),
|
|
3255
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
3171
3256
|
detectedFrom: sources,
|
|
3172
3257
|
};
|
|
3173
3258
|
}
|
|
@@ -3186,6 +3271,21 @@ const testingDetectors = [
|
|
|
3186
3271
|
* @param projectPath - Project directory path
|
|
3187
3272
|
* @param packageJson - Optional pre-loaded package.json
|
|
3188
3273
|
* @returns Array of detected testing frameworks, sorted by confidence
|
|
3274
|
+
*
|
|
3275
|
+
* @example Detecting multiple testing frameworks
|
|
3276
|
+
* ```typescript
|
|
3277
|
+
* import { detectTestingFrameworks } from '@hyperfrontend/project-scope'
|
|
3278
|
+
*
|
|
3279
|
+
* const frameworks = detectTestingFrameworks('./my-project')
|
|
3280
|
+
* // => [
|
|
3281
|
+
* // { id: 'jest', name: 'Jest', type: 'unit', confidence: 95, ... },
|
|
3282
|
+
* // { id: 'cypress', name: 'Cypress', type: 'e2e', confidence: 85, ... }
|
|
3283
|
+
* // ]
|
|
3284
|
+
*
|
|
3285
|
+
* // Results are sorted by confidence (highest first)
|
|
3286
|
+
* const primary = frameworks[0]?.name ?? 'None'
|
|
3287
|
+
* console.log(`Primary testing framework: ${primary}`)
|
|
3288
|
+
* ```
|
|
3189
3289
|
*/
|
|
3190
3290
|
function detectTestingFrameworks(projectPath, packageJson) {
|
|
3191
3291
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3212,7 +3312,7 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3212
3312
|
return undefined;
|
|
3213
3313
|
try {
|
|
3214
3314
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
3215
|
-
const parsed = parse(cleanContent);
|
|
3315
|
+
const parsed = index_cjs_js$6.parse(cleanContent);
|
|
3216
3316
|
return parsed?.compilerOptions?.strict === true;
|
|
3217
3317
|
}
|
|
3218
3318
|
catch {
|
|
@@ -3225,6 +3325,19 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3225
3325
|
* @param projectPath - Project directory path
|
|
3226
3326
|
* @param packageJson - Optional pre-loaded package.json
|
|
3227
3327
|
* @returns Detection result or null if not detected
|
|
3328
|
+
*
|
|
3329
|
+
* @example Detecting TypeScript
|
|
3330
|
+
* ```typescript
|
|
3331
|
+
* import { typescriptDetector } from '@hyperfrontend/project-scope'
|
|
3332
|
+
*
|
|
3333
|
+
* const result = typescriptDetector('./my-project')
|
|
3334
|
+
* if (result) {
|
|
3335
|
+
* console.log(`TypeScript ${result.version}`)
|
|
3336
|
+
* console.log(`Strict mode: ${result.strictMode ?? 'unknown'}`)
|
|
3337
|
+
* // => "TypeScript 5.3.0"
|
|
3338
|
+
* // => "Strict mode: true"
|
|
3339
|
+
* }
|
|
3340
|
+
* ```
|
|
3228
3341
|
*/
|
|
3229
3342
|
function typescriptDetector(projectPath, packageJson) {
|
|
3230
3343
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3251,7 +3364,7 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3251
3364
|
break;
|
|
3252
3365
|
}
|
|
3253
3366
|
}
|
|
3254
|
-
const typePackages = keys(deps).filter((d) => d.startsWith('@types/'));
|
|
3367
|
+
const typePackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@types/'));
|
|
3255
3368
|
if (typePackages.length > 0) {
|
|
3256
3369
|
confidence += 10;
|
|
3257
3370
|
sources.push({ type: 'package.json', field: '@types/* packages' });
|
|
@@ -3266,7 +3379,7 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3266
3379
|
version,
|
|
3267
3380
|
configPath,
|
|
3268
3381
|
strictMode,
|
|
3269
|
-
confidence: min(confidence, 100),
|
|
3382
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
3270
3383
|
detectedFrom: sources,
|
|
3271
3384
|
};
|
|
3272
3385
|
}
|
|
@@ -3276,6 +3389,17 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3276
3389
|
* @param projectPath - Project directory path
|
|
3277
3390
|
* @param packageJson - Optional pre-loaded package.json
|
|
3278
3391
|
* @returns Detection result or null if not detected
|
|
3392
|
+
*
|
|
3393
|
+
* @example Detecting Flow type system
|
|
3394
|
+
* ```typescript
|
|
3395
|
+
* import { flowDetector } from '@hyperfrontend/project-scope'
|
|
3396
|
+
*
|
|
3397
|
+
* const result = flowDetector('./my-project')
|
|
3398
|
+
* if (result) {
|
|
3399
|
+
* console.log(`Flow ${result.version} with config: ${result.configPath}`)
|
|
3400
|
+
* // => "Flow 0.232.0 with config: .flowconfig"
|
|
3401
|
+
* }
|
|
3402
|
+
* ```
|
|
3279
3403
|
*/
|
|
3280
3404
|
function flowDetector(projectPath, packageJson) {
|
|
3281
3405
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3310,7 +3434,7 @@ function flowDetector(projectPath, packageJson) {
|
|
|
3310
3434
|
name: 'Flow',
|
|
3311
3435
|
version,
|
|
3312
3436
|
configPath,
|
|
3313
|
-
confidence: min(confidence, 100),
|
|
3437
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
3314
3438
|
detectedFrom: sources,
|
|
3315
3439
|
};
|
|
3316
3440
|
}
|
|
@@ -3333,6 +3457,18 @@ function hasJsDocTypes(content) {
|
|
|
3333
3457
|
* @param projectPath - Project directory path
|
|
3334
3458
|
* @param packageJson - Optional pre-loaded package.json
|
|
3335
3459
|
* @returns Detection result or null if not detected
|
|
3460
|
+
*
|
|
3461
|
+
* @example Detecting JSDoc type annotations
|
|
3462
|
+
* ```typescript
|
|
3463
|
+
* import { jsdocDetector } from '@hyperfrontend/project-scope'
|
|
3464
|
+
*
|
|
3465
|
+
* const result = jsdocDetector('./my-project')
|
|
3466
|
+
* if (result) {
|
|
3467
|
+
* console.log('JSDoc types detected')
|
|
3468
|
+
* console.log('Sources:', result.detectedFrom.map(s => s.path ?? s.field))
|
|
3469
|
+
* // => "Sources: ['jsconfig.json', 'src/utils.js (JSDoc annotations)']"
|
|
3470
|
+
* }
|
|
3471
|
+
* ```
|
|
3336
3472
|
*/
|
|
3337
3473
|
function jsdocDetector(projectPath, packageJson) {
|
|
3338
3474
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3349,7 +3485,7 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
3349
3485
|
if (content) {
|
|
3350
3486
|
try {
|
|
3351
3487
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
3352
|
-
const parsed = parse(cleanContent);
|
|
3488
|
+
const parsed = index_cjs_js$6.parse(cleanContent);
|
|
3353
3489
|
if (parsed?.compilerOptions?.checkJs === true || parsed?.compilerOptions?.allowJs === true) {
|
|
3354
3490
|
confidence += 30;
|
|
3355
3491
|
sources.push({ type: 'config-file', path: 'tsconfig.json (checkJs/allowJs)' });
|
|
@@ -3388,7 +3524,7 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
3388
3524
|
return {
|
|
3389
3525
|
id: 'jsdoc',
|
|
3390
3526
|
name: 'JSDoc',
|
|
3391
|
-
confidence: min(confidence, 100),
|
|
3527
|
+
confidence: index_cjs_js$8.min(confidence, 100),
|
|
3392
3528
|
detectedFrom: sources,
|
|
3393
3529
|
};
|
|
3394
3530
|
}
|
|
@@ -3404,6 +3540,20 @@ const typeSystemDetectors = [
|
|
|
3404
3540
|
* @param projectPath - Project directory path
|
|
3405
3541
|
* @param packageJson - Optional pre-loaded package.json
|
|
3406
3542
|
* @returns Array of detected type systems, sorted by confidence
|
|
3543
|
+
*
|
|
3544
|
+
* @example Detecting all type systems
|
|
3545
|
+
* ```typescript
|
|
3546
|
+
* import { detectTypeSystems } from '@hyperfrontend/project-scope'
|
|
3547
|
+
*
|
|
3548
|
+
* const typeSystems = detectTypeSystems('./my-project')
|
|
3549
|
+
* // => [
|
|
3550
|
+
* // { id: 'typescript', name: 'TypeScript', version: '5.3.0', strictMode: true, confidence: 95, ... },
|
|
3551
|
+
* // { id: 'jsdoc', name: 'JSDoc', confidence: 40, ... }
|
|
3552
|
+
* // ]
|
|
3553
|
+
*
|
|
3554
|
+
* const primary = typeSystems[0]?.name ?? 'None'
|
|
3555
|
+
* console.log(`Primary type system: ${primary}`)
|
|
3556
|
+
* ```
|
|
3407
3557
|
*/
|
|
3408
3558
|
function detectTypeSystems(projectPath, packageJson) {
|
|
3409
3559
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3457,7 +3607,7 @@ function isDetectAllOptions(value) {
|
|
|
3457
3607
|
* @param packageJsonOrOptions - Optional pre-loaded package.json or options object
|
|
3458
3608
|
* @returns All detection results organized by category
|
|
3459
3609
|
*
|
|
3460
|
-
* @example
|
|
3610
|
+
* @example Running all tech detectors
|
|
3461
3611
|
* ```typescript
|
|
3462
3612
|
* import { detectAll } from '@hyperfrontend/project-scope'
|
|
3463
3613
|
*
|
|
@@ -3534,6 +3684,18 @@ function detectAll(projectPath, packageJsonOrOptions) {
|
|
|
3534
3684
|
* Clear the tech detection cache.
|
|
3535
3685
|
*
|
|
3536
3686
|
* Useful for testing or when the project files have changed.
|
|
3687
|
+
*
|
|
3688
|
+
* @example Clearing the tech detection cache
|
|
3689
|
+
* ```typescript
|
|
3690
|
+
* import { detectAll, clearTechDetectionCache } from '@hyperfrontend/project-scope'
|
|
3691
|
+
*
|
|
3692
|
+
* // Initial detection (cached)
|
|
3693
|
+
* const first = detectAll('./my-project')
|
|
3694
|
+
*
|
|
3695
|
+
* // After modifying package.json, clear cache to re-detect
|
|
3696
|
+
* clearTechDetectionCache()
|
|
3697
|
+
* const fresh = detectAll('./my-project')
|
|
3698
|
+
* ```
|
|
3537
3699
|
*/
|
|
3538
3700
|
function clearTechDetectionCache() {
|
|
3539
3701
|
detectAllCache.clear();
|
|
@@ -3619,4 +3781,3 @@ exports.vitestDetector = vitestDetector;
|
|
|
3619
3781
|
exports.vueDetector = vueDetector;
|
|
3620
3782
|
exports.webpackDetector = webpackDetector;
|
|
3621
3783
|
exports.yarnWorkspacesDetector = yarnWorkspacesDetector;
|
|
3622
|
-
//# sourceMappingURL=index.cjs.js.map
|