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