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