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