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