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