@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
|
@@ -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
|
};
|
|
@@ -1211,52 +670,64 @@ const backendDetectors = [
|
|
|
1211
670
|
{ id: 'hono', name: 'Hono', detect: honoDetector },
|
|
1212
671
|
];
|
|
1213
672
|
|
|
1214
|
-
/** Config patterns for
|
|
1215
|
-
const
|
|
1216
|
-
'webpack.config.js',
|
|
1217
|
-
'webpack.config.ts',
|
|
1218
|
-
'webpack.config.cjs',
|
|
1219
|
-
'webpack.config.mjs',
|
|
1220
|
-
'webpack.config.babel.js',
|
|
1221
|
-
];
|
|
673
|
+
/** Config patterns for Babel */
|
|
674
|
+
const BABEL_CONFIG_PATTERNS = ['babel.config.js', 'babel.config.cjs', 'babel.config.mjs', 'babel.config.json', '.babelrc', '.babelrc.json', '.babelrc.js'];
|
|
1222
675
|
/**
|
|
1223
|
-
* Detect
|
|
676
|
+
* Detect Babel in project.
|
|
1224
677
|
*
|
|
1225
678
|
* @param projectPath - Project directory path
|
|
1226
679
|
* @param packageJson - Optional pre-loaded package.json
|
|
1227
680
|
* @returns Detection result or null if not detected
|
|
681
|
+
*
|
|
682
|
+
* @example Detecting Babel compiler
|
|
683
|
+
* ```typescript
|
|
684
|
+
* const result = babelDetector('/path/to/project', {
|
|
685
|
+
* name: 'my-app',
|
|
686
|
+
* devDependencies: { '@babel/core': '^7.23.0', '@babel/preset-env': '^7.23.0' }
|
|
687
|
+
* })
|
|
688
|
+
* // => {
|
|
689
|
+
* // id: 'babel',
|
|
690
|
+
* // name: 'Babel',
|
|
691
|
+
* // version: '7.23.0',
|
|
692
|
+
* // confidence: 60,
|
|
693
|
+
* // detectedFrom: [
|
|
694
|
+
* // { type: 'package.json', field: 'dependencies.@babel/core' },
|
|
695
|
+
* // { type: 'package.json', field: 'dependencies (@babel packages)' }
|
|
696
|
+
* // ]
|
|
697
|
+
* // }
|
|
698
|
+
* ```
|
|
1228
699
|
*/
|
|
1229
|
-
function
|
|
700
|
+
function babelDetector(projectPath, packageJson) {
|
|
1230
701
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1231
702
|
const sources = [];
|
|
1232
703
|
let confidence = 0;
|
|
1233
704
|
let version;
|
|
1234
705
|
const deps = collectAllDependencies(pkg);
|
|
1235
|
-
if (deps['
|
|
706
|
+
if (deps['@babel/core']) {
|
|
1236
707
|
confidence += 50;
|
|
1237
|
-
version = parseVersionString(deps['
|
|
1238
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
708
|
+
version = parseVersionString(deps['@babel/core']);
|
|
709
|
+
sources.push({ type: 'package.json', field: 'dependencies.@babel/core' });
|
|
1239
710
|
}
|
|
1240
|
-
const configPath = locateConfigFile(projectPath,
|
|
711
|
+
const configPath = locateConfigFile(projectPath, BABEL_CONFIG_PATTERNS);
|
|
1241
712
|
if (configPath) {
|
|
1242
713
|
confidence += 40;
|
|
1243
714
|
sources.push({ type: 'config-file', path: configPath });
|
|
1244
715
|
}
|
|
1245
|
-
if (
|
|
1246
|
-
confidence +=
|
|
1247
|
-
sources.push({ type: 'package.json', field: '
|
|
716
|
+
if (pkg && 'babel' in pkg) {
|
|
717
|
+
confidence += 30;
|
|
718
|
+
sources.push({ type: 'package.json', field: 'babel' });
|
|
1248
719
|
}
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1251
|
-
confidence
|
|
1252
|
-
sources.push({ type: 'package.json', field:
|
|
720
|
+
const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
721
|
+
if (babelPackages.length > 1) {
|
|
722
|
+
confidence += 10;
|
|
723
|
+
sources.push({ type: 'package.json', field: 'dependencies (@babel packages)' });
|
|
1253
724
|
}
|
|
1254
725
|
if (confidence === 0) {
|
|
1255
726
|
return null;
|
|
1256
727
|
}
|
|
1257
728
|
return {
|
|
1258
|
-
id: '
|
|
1259
|
-
name: '
|
|
729
|
+
id: 'babel',
|
|
730
|
+
name: 'Babel',
|
|
1260
731
|
version,
|
|
1261
732
|
configPath,
|
|
1262
733
|
confidence: min(confidence, 100),
|
|
@@ -1264,94 +735,126 @@ function webpackDetector(projectPath, packageJson) {
|
|
|
1264
735
|
};
|
|
1265
736
|
}
|
|
1266
737
|
|
|
1267
|
-
/** Config patterns for Vite */
|
|
1268
|
-
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
1269
738
|
/**
|
|
1270
|
-
* Detect
|
|
739
|
+
* Detect esbuild in project.
|
|
1271
740
|
*
|
|
1272
741
|
* @param projectPath - Project directory path
|
|
1273
742
|
* @param packageJson - Optional pre-loaded package.json
|
|
1274
743
|
* @returns Detection result or null if not detected
|
|
744
|
+
*
|
|
745
|
+
* @example Detecting esbuild bundler
|
|
746
|
+
* ```typescript
|
|
747
|
+
* const result = esbuildDetector('/path/to/project', {
|
|
748
|
+
* name: 'my-lib',
|
|
749
|
+
* devDependencies: { 'esbuild': '^0.19.0' },
|
|
750
|
+
* scripts: { 'build': 'esbuild src/index.ts --bundle --outfile=dist/index.js' }
|
|
751
|
+
* })
|
|
752
|
+
* // => {
|
|
753
|
+
* // id: 'esbuild',
|
|
754
|
+
* // name: 'esbuild',
|
|
755
|
+
* // version: '0.19.0',
|
|
756
|
+
* // confidence: 80,
|
|
757
|
+
* // detectedFrom: [
|
|
758
|
+
* // { type: 'package.json', field: 'dependencies.esbuild' },
|
|
759
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
760
|
+
* // ]
|
|
761
|
+
* // }
|
|
762
|
+
* ```
|
|
1275
763
|
*/
|
|
1276
|
-
function
|
|
764
|
+
function esbuildDetector(projectPath, packageJson) {
|
|
1277
765
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1278
766
|
const sources = [];
|
|
1279
767
|
let confidence = 0;
|
|
1280
768
|
let version;
|
|
1281
769
|
const deps = collectAllDependencies(pkg);
|
|
1282
|
-
if (deps['
|
|
1283
|
-
confidence +=
|
|
1284
|
-
version = parseVersionString(deps['
|
|
1285
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1286
|
-
}
|
|
1287
|
-
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
1288
|
-
if (configPath) {
|
|
1289
|
-
confidence += 35;
|
|
1290
|
-
sources.push({ type: 'config-file', path: configPath });
|
|
770
|
+
if (deps['esbuild']) {
|
|
771
|
+
confidence += 70;
|
|
772
|
+
version = parseVersionString(deps['esbuild']);
|
|
773
|
+
sources.push({ type: 'package.json', field: 'dependencies.esbuild' });
|
|
1291
774
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
775
|
+
const esbuildPlugins = keys(deps).filter((d) => d.includes('esbuild-plugin') || d.includes('esbuild-'));
|
|
776
|
+
if (esbuildPlugins.length > 0) {
|
|
777
|
+
confidence += 15;
|
|
778
|
+
sources.push({ type: 'package.json', field: 'dependencies (esbuild plugins)' });
|
|
1295
779
|
}
|
|
1296
|
-
const
|
|
1297
|
-
|
|
1298
|
-
confidence
|
|
1299
|
-
sources.push({ type: 'package.json', field:
|
|
780
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'esbuild');
|
|
781
|
+
for (const name of scriptMatches) {
|
|
782
|
+
confidence = min(confidence + 10, 100);
|
|
783
|
+
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1300
784
|
}
|
|
1301
785
|
if (confidence === 0) {
|
|
1302
786
|
return null;
|
|
1303
787
|
}
|
|
1304
788
|
return {
|
|
1305
|
-
id: '
|
|
1306
|
-
name: '
|
|
789
|
+
id: 'esbuild',
|
|
790
|
+
name: 'esbuild',
|
|
1307
791
|
version,
|
|
1308
|
-
configPath,
|
|
1309
792
|
confidence: min(confidence, 100),
|
|
1310
793
|
detectedFrom: sources,
|
|
1311
794
|
};
|
|
1312
795
|
}
|
|
1313
796
|
|
|
1314
|
-
/** Config patterns for
|
|
1315
|
-
const
|
|
797
|
+
/** Config patterns for Parcel */
|
|
798
|
+
const PARCEL_CONFIG_PATTERNS = ['.parcelrc'];
|
|
1316
799
|
/**
|
|
1317
|
-
* Detect
|
|
800
|
+
* Detect Parcel in project.
|
|
1318
801
|
*
|
|
1319
802
|
* @param projectPath - Project directory path
|
|
1320
803
|
* @param packageJson - Optional pre-loaded package.json
|
|
1321
804
|
* @returns Detection result or null if not detected
|
|
805
|
+
*
|
|
806
|
+
* @example Detecting Parcel bundler
|
|
807
|
+
* ```typescript
|
|
808
|
+
* const result = parcelDetector('/path/to/project', {
|
|
809
|
+
* name: 'my-app',
|
|
810
|
+
* devDependencies: { 'parcel': '^2.10.0' },
|
|
811
|
+
* scripts: { 'dev': 'parcel src/index.html', 'build': 'parcel build src/index.html' }
|
|
812
|
+
* })
|
|
813
|
+
* // => {
|
|
814
|
+
* // id: 'parcel',
|
|
815
|
+
* // name: 'Parcel',
|
|
816
|
+
* // version: '2.10.0',
|
|
817
|
+
* // confidence: 80,
|
|
818
|
+
* // detectedFrom: [
|
|
819
|
+
* // { type: 'package.json', field: 'dependencies.parcel' },
|
|
820
|
+
* // { type: 'package.json', field: 'scripts.dev' },
|
|
821
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
822
|
+
* // ]
|
|
823
|
+
* // }
|
|
824
|
+
* ```
|
|
1322
825
|
*/
|
|
1323
|
-
function
|
|
826
|
+
function parcelDetector(projectPath, packageJson) {
|
|
1324
827
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1325
828
|
const sources = [];
|
|
1326
829
|
let confidence = 0;
|
|
1327
830
|
let version;
|
|
1328
831
|
const deps = collectAllDependencies(pkg);
|
|
1329
|
-
if (deps['
|
|
1330
|
-
confidence +=
|
|
1331
|
-
version = parseVersionString(deps['
|
|
1332
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
832
|
+
if (deps['parcel']) {
|
|
833
|
+
confidence += 60;
|
|
834
|
+
version = parseVersionString(deps['parcel']);
|
|
835
|
+
sources.push({ type: 'package.json', field: 'dependencies.parcel' });
|
|
1333
836
|
}
|
|
1334
|
-
|
|
837
|
+
if (deps['parcel-bundler']) {
|
|
838
|
+
confidence += 60;
|
|
839
|
+
version = parseVersionString(deps['parcel-bundler']);
|
|
840
|
+
sources.push({ type: 'package.json', field: 'dependencies.parcel-bundler' });
|
|
841
|
+
}
|
|
842
|
+
const configPath = locateConfigFile(projectPath, PARCEL_CONFIG_PATTERNS);
|
|
1335
843
|
if (configPath) {
|
|
1336
|
-
confidence +=
|
|
844
|
+
confidence += 30;
|
|
1337
845
|
sources.push({ type: 'config-file', path: configPath });
|
|
1338
846
|
}
|
|
1339
|
-
const
|
|
1340
|
-
if (rollupPlugins.length > 0) {
|
|
1341
|
-
confidence += 10;
|
|
1342
|
-
sources.push({ type: 'package.json', field: 'dependencies (rollup plugins)' });
|
|
1343
|
-
}
|
|
1344
|
-
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'rollup');
|
|
847
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'parcel');
|
|
1345
848
|
for (const name of scriptMatches) {
|
|
1346
|
-
confidence = min(confidence +
|
|
849
|
+
confidence = min(confidence + 10, 100);
|
|
1347
850
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1348
851
|
}
|
|
1349
852
|
if (confidence === 0) {
|
|
1350
853
|
return null;
|
|
1351
854
|
}
|
|
1352
855
|
return {
|
|
1353
|
-
id: '
|
|
1354
|
-
name: '
|
|
856
|
+
id: 'parcel',
|
|
857
|
+
name: 'Parcel',
|
|
1355
858
|
version,
|
|
1356
859
|
configPath,
|
|
1357
860
|
confidence: min(confidence, 100),
|
|
@@ -1359,86 +862,134 @@ function rollupDetector(projectPath, packageJson) {
|
|
|
1359
862
|
};
|
|
1360
863
|
}
|
|
1361
864
|
|
|
865
|
+
/** Config patterns for Rollup */
|
|
866
|
+
const ROLLUP_CONFIG_PATTERNS = ['rollup.config.js', 'rollup.config.ts', 'rollup.config.mjs', 'rollup.config.cjs'];
|
|
1362
867
|
/**
|
|
1363
|
-
* Detect
|
|
868
|
+
* Detect Rollup in project.
|
|
1364
869
|
*
|
|
1365
870
|
* @param projectPath - Project directory path
|
|
1366
871
|
* @param packageJson - Optional pre-loaded package.json
|
|
1367
872
|
* @returns Detection result or null if not detected
|
|
873
|
+
*
|
|
874
|
+
* @example Detecting Rollup bundler
|
|
875
|
+
* ```typescript
|
|
876
|
+
* const result = rollupDetector('/path/to/project', {
|
|
877
|
+
* name: 'my-lib',
|
|
878
|
+
* devDependencies: {
|
|
879
|
+
* 'rollup': '^4.0.0',
|
|
880
|
+
* '@rollup/plugin-node-resolve': '^15.0.0',
|
|
881
|
+
* '@rollup/plugin-commonjs': '^25.0.0'
|
|
882
|
+
* }
|
|
883
|
+
* })
|
|
884
|
+
* // => {
|
|
885
|
+
* // id: 'rollup',
|
|
886
|
+
* // name: 'Rollup',
|
|
887
|
+
* // version: '4.0.0',
|
|
888
|
+
* // confidence: 65,
|
|
889
|
+
* // detectedFrom: [
|
|
890
|
+
* // { type: 'package.json', field: 'dependencies.rollup' },
|
|
891
|
+
* // { type: 'package.json', field: 'dependencies (rollup plugins)' }
|
|
892
|
+
* // ]
|
|
893
|
+
* // }
|
|
894
|
+
* ```
|
|
1368
895
|
*/
|
|
1369
|
-
function
|
|
896
|
+
function rollupDetector(projectPath, packageJson) {
|
|
1370
897
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1371
898
|
const sources = [];
|
|
1372
899
|
let confidence = 0;
|
|
1373
900
|
let version;
|
|
1374
901
|
const deps = collectAllDependencies(pkg);
|
|
1375
|
-
if (deps['
|
|
1376
|
-
confidence +=
|
|
1377
|
-
version = parseVersionString(deps['
|
|
1378
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
902
|
+
if (deps['rollup']) {
|
|
903
|
+
confidence += 55;
|
|
904
|
+
version = parseVersionString(deps['rollup']);
|
|
905
|
+
sources.push({ type: 'package.json', field: 'dependencies.rollup' });
|
|
1379
906
|
}
|
|
1380
|
-
const
|
|
1381
|
-
if (
|
|
1382
|
-
confidence +=
|
|
1383
|
-
sources.push({ type: '
|
|
907
|
+
const configPath = locateConfigFile(projectPath, ROLLUP_CONFIG_PATTERNS);
|
|
908
|
+
if (configPath) {
|
|
909
|
+
confidence += 40;
|
|
910
|
+
sources.push({ type: 'config-file', path: configPath });
|
|
1384
911
|
}
|
|
1385
|
-
const
|
|
912
|
+
const rollupPlugins = keys(deps).filter((d) => d.startsWith('@rollup/') || d.startsWith('rollup-plugin-'));
|
|
913
|
+
if (rollupPlugins.length > 0) {
|
|
914
|
+
confidence += 10;
|
|
915
|
+
sources.push({ type: 'package.json', field: 'dependencies (rollup plugins)' });
|
|
916
|
+
}
|
|
917
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'rollup');
|
|
1386
918
|
for (const name of scriptMatches) {
|
|
1387
|
-
confidence = min(confidence +
|
|
919
|
+
confidence = min(confidence + 5, 100);
|
|
1388
920
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1389
921
|
}
|
|
1390
922
|
if (confidence === 0) {
|
|
1391
923
|
return null;
|
|
1392
924
|
}
|
|
1393
925
|
return {
|
|
1394
|
-
id: '
|
|
1395
|
-
name: '
|
|
926
|
+
id: 'rollup',
|
|
927
|
+
name: 'Rollup',
|
|
1396
928
|
version,
|
|
929
|
+
configPath,
|
|
1397
930
|
confidence: min(confidence, 100),
|
|
1398
931
|
detectedFrom: sources,
|
|
1399
932
|
};
|
|
1400
933
|
}
|
|
1401
934
|
|
|
1402
|
-
/** Config patterns for
|
|
1403
|
-
const
|
|
935
|
+
/** Config patterns for SWC */
|
|
936
|
+
const SWC_CONFIG_PATTERNS = ['.swcrc', 'swc.config.js'];
|
|
1404
937
|
/**
|
|
1405
|
-
* Detect
|
|
938
|
+
* Detect SWC in project.
|
|
1406
939
|
*
|
|
1407
940
|
* @param projectPath - Project directory path
|
|
1408
941
|
* @param packageJson - Optional pre-loaded package.json
|
|
1409
942
|
* @returns Detection result or null if not detected
|
|
943
|
+
*
|
|
944
|
+
* @example Detecting SWC compiler
|
|
945
|
+
* ```typescript
|
|
946
|
+
* const result = swcDetector('/path/to/project', {
|
|
947
|
+
* name: 'my-app',
|
|
948
|
+
* devDependencies: { '@swc/core': '^1.3.0', '@swc/cli': '^0.1.0' }
|
|
949
|
+
* })
|
|
950
|
+
* // => {
|
|
951
|
+
* // id: 'swc',
|
|
952
|
+
* // name: 'SWC',
|
|
953
|
+
* // version: '1.3.0',
|
|
954
|
+
* // confidence: 70,
|
|
955
|
+
* // detectedFrom: [
|
|
956
|
+
* // { type: 'package.json', field: 'dependencies.@swc/core' },
|
|
957
|
+
* // { type: 'package.json', field: 'dependencies.@swc/cli' }
|
|
958
|
+
* // ]
|
|
959
|
+
* // }
|
|
960
|
+
* ```
|
|
1410
961
|
*/
|
|
1411
|
-
function
|
|
962
|
+
function swcDetector(projectPath, packageJson) {
|
|
1412
963
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1413
964
|
const sources = [];
|
|
1414
965
|
let confidence = 0;
|
|
1415
966
|
let version;
|
|
1416
967
|
const deps = collectAllDependencies(pkg);
|
|
1417
|
-
if (deps['@
|
|
1418
|
-
confidence +=
|
|
1419
|
-
version = parseVersionString(deps['@
|
|
1420
|
-
sources.push({ type: 'package.json', field: 'dependencies.@
|
|
968
|
+
if (deps['@swc/core']) {
|
|
969
|
+
confidence += 60;
|
|
970
|
+
version = parseVersionString(deps['@swc/core']);
|
|
971
|
+
sources.push({ type: 'package.json', field: 'dependencies.@swc/core' });
|
|
1421
972
|
}
|
|
1422
|
-
const configPath = locateConfigFile(projectPath,
|
|
973
|
+
const configPath = locateConfigFile(projectPath, SWC_CONFIG_PATTERNS);
|
|
1423
974
|
if (configPath) {
|
|
1424
|
-
confidence +=
|
|
975
|
+
confidence += 35;
|
|
1425
976
|
sources.push({ type: 'config-file', path: configPath });
|
|
1426
977
|
}
|
|
1427
|
-
if (
|
|
1428
|
-
confidence += 30;
|
|
1429
|
-
sources.push({ type: 'package.json', field: 'babel' });
|
|
1430
|
-
}
|
|
1431
|
-
const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
1432
|
-
if (babelPackages.length > 1) {
|
|
978
|
+
if (deps['@swc/cli']) {
|
|
1433
979
|
confidence += 10;
|
|
1434
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
980
|
+
sources.push({ type: 'package.json', field: 'dependencies.@swc/cli' });
|
|
981
|
+
}
|
|
982
|
+
const swcPlugins = keys(deps).filter((d) => d.startsWith('@swc/') || d.includes('swc-plugin'));
|
|
983
|
+
if (swcPlugins.length > 1) {
|
|
984
|
+
confidence += 5;
|
|
985
|
+
sources.push({ type: 'package.json', field: 'dependencies (@swc packages)' });
|
|
1435
986
|
}
|
|
1436
987
|
if (confidence === 0) {
|
|
1437
988
|
return null;
|
|
1438
989
|
}
|
|
1439
990
|
return {
|
|
1440
|
-
id: '
|
|
1441
|
-
name: '
|
|
991
|
+
id: 'swc',
|
|
992
|
+
name: 'SWC',
|
|
1442
993
|
version,
|
|
1443
994
|
configPath,
|
|
1444
995
|
confidence: min(confidence, 100),
|
|
@@ -1446,46 +997,69 @@ function babelDetector(projectPath, packageJson) {
|
|
|
1446
997
|
};
|
|
1447
998
|
}
|
|
1448
999
|
|
|
1449
|
-
/** Config patterns for
|
|
1450
|
-
const
|
|
1000
|
+
/** Config patterns for Vite */
|
|
1001
|
+
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
1451
1002
|
/**
|
|
1452
|
-
* Detect
|
|
1003
|
+
* Detect Vite in project.
|
|
1453
1004
|
*
|
|
1454
1005
|
* @param projectPath - Project directory path
|
|
1455
1006
|
* @param packageJson - Optional pre-loaded package.json
|
|
1456
1007
|
* @returns Detection result or null if not detected
|
|
1008
|
+
*
|
|
1009
|
+
* @example Detecting Vite build tool
|
|
1010
|
+
* ```typescript
|
|
1011
|
+
* const result = viteDetector('/path/to/project', {
|
|
1012
|
+
* name: 'my-app',
|
|
1013
|
+
* devDependencies: {
|
|
1014
|
+
* 'vite': '^5.0.0',
|
|
1015
|
+
* '@vitejs/plugin-react': '^4.0.0',
|
|
1016
|
+
* 'vitest': '^1.0.0'
|
|
1017
|
+
* }
|
|
1018
|
+
* })
|
|
1019
|
+
* // => {
|
|
1020
|
+
* // id: 'vite',
|
|
1021
|
+
* // name: 'Vite',
|
|
1022
|
+
* // version: '5.0.0',
|
|
1023
|
+
* // confidence: 80,
|
|
1024
|
+
* // detectedFrom: [
|
|
1025
|
+
* // { type: 'package.json', field: 'dependencies.vite' },
|
|
1026
|
+
* // { type: 'package.json', field: 'dependencies.vitest' },
|
|
1027
|
+
* // { type: 'package.json', field: 'dependencies (vite plugins)' }
|
|
1028
|
+
* // ]
|
|
1029
|
+
* // }
|
|
1030
|
+
* ```
|
|
1457
1031
|
*/
|
|
1458
|
-
function
|
|
1032
|
+
function viteDetector(projectPath, packageJson) {
|
|
1459
1033
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1460
1034
|
const sources = [];
|
|
1461
1035
|
let confidence = 0;
|
|
1462
1036
|
let version;
|
|
1463
1037
|
const deps = collectAllDependencies(pkg);
|
|
1464
|
-
if (deps['
|
|
1038
|
+
if (deps['vite']) {
|
|
1465
1039
|
confidence += 60;
|
|
1466
|
-
version = parseVersionString(deps['
|
|
1467
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1040
|
+
version = parseVersionString(deps['vite']);
|
|
1041
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite' });
|
|
1468
1042
|
}
|
|
1469
|
-
const configPath = locateConfigFile(projectPath,
|
|
1043
|
+
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
1470
1044
|
if (configPath) {
|
|
1471
1045
|
confidence += 35;
|
|
1472
1046
|
sources.push({ type: 'config-file', path: configPath });
|
|
1473
1047
|
}
|
|
1474
|
-
if (deps['
|
|
1048
|
+
if (deps['vitest']) {
|
|
1475
1049
|
confidence += 10;
|
|
1476
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1050
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
1477
1051
|
}
|
|
1478
|
-
const
|
|
1479
|
-
if (
|
|
1480
|
-
confidence +=
|
|
1481
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1052
|
+
const vitePlugins = keys(deps).filter((d) => d.startsWith('vite-plugin-') || d.startsWith('@vitejs/'));
|
|
1053
|
+
if (vitePlugins.length > 0) {
|
|
1054
|
+
confidence += 10;
|
|
1055
|
+
sources.push({ type: 'package.json', field: 'dependencies (vite plugins)' });
|
|
1482
1056
|
}
|
|
1483
1057
|
if (confidence === 0) {
|
|
1484
1058
|
return null;
|
|
1485
1059
|
}
|
|
1486
1060
|
return {
|
|
1487
|
-
id: '
|
|
1488
|
-
name: '
|
|
1061
|
+
id: 'vite',
|
|
1062
|
+
name: 'Vite',
|
|
1489
1063
|
version,
|
|
1490
1064
|
configPath,
|
|
1491
1065
|
confidence: min(confidence, 100),
|
|
@@ -1493,47 +1067,72 @@ function swcDetector(projectPath, packageJson) {
|
|
|
1493
1067
|
};
|
|
1494
1068
|
}
|
|
1495
1069
|
|
|
1496
|
-
/** Config patterns for
|
|
1497
|
-
const
|
|
1070
|
+
/** Config patterns for Webpack */
|
|
1071
|
+
const WEBPACK_CONFIG_PATTERNS = [
|
|
1072
|
+
'webpack.config.js',
|
|
1073
|
+
'webpack.config.ts',
|
|
1074
|
+
'webpack.config.cjs',
|
|
1075
|
+
'webpack.config.mjs',
|
|
1076
|
+
'webpack.config.babel.js',
|
|
1077
|
+
];
|
|
1498
1078
|
/**
|
|
1499
|
-
* Detect
|
|
1079
|
+
* Detect Webpack in project.
|
|
1500
1080
|
*
|
|
1501
1081
|
* @param projectPath - Project directory path
|
|
1502
1082
|
* @param packageJson - Optional pre-loaded package.json
|
|
1503
1083
|
* @returns Detection result or null if not detected
|
|
1084
|
+
*
|
|
1085
|
+
* @example Detecting Webpack bundler
|
|
1086
|
+
* ```typescript
|
|
1087
|
+
* const result = webpackDetector('/path/to/project', {
|
|
1088
|
+
* name: 'my-app',
|
|
1089
|
+
* devDependencies: { 'webpack': '^5.89.0', 'webpack-cli': '^5.1.0' },
|
|
1090
|
+
* scripts: { 'build': 'webpack --mode production' }
|
|
1091
|
+
* })
|
|
1092
|
+
* // => {
|
|
1093
|
+
* // id: 'webpack',
|
|
1094
|
+
* // name: 'Webpack',
|
|
1095
|
+
* // version: '5.89.0',
|
|
1096
|
+
* // confidence: 65,
|
|
1097
|
+
* // detectedFrom: [
|
|
1098
|
+
* // { type: 'package.json', field: 'dependencies.webpack' },
|
|
1099
|
+
* // { type: 'package.json', field: 'dependencies.webpack-cli' },
|
|
1100
|
+
* // { type: 'package.json', field: 'scripts.build' }
|
|
1101
|
+
* // ]
|
|
1102
|
+
* // }
|
|
1103
|
+
* ```
|
|
1504
1104
|
*/
|
|
1505
|
-
function
|
|
1105
|
+
function webpackDetector(projectPath, packageJson) {
|
|
1506
1106
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1507
1107
|
const sources = [];
|
|
1508
1108
|
let confidence = 0;
|
|
1509
1109
|
let version;
|
|
1510
1110
|
const deps = collectAllDependencies(pkg);
|
|
1511
|
-
if (deps['
|
|
1512
|
-
confidence +=
|
|
1513
|
-
version = parseVersionString(deps['
|
|
1514
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1515
|
-
}
|
|
1516
|
-
if (deps['parcel-bundler']) {
|
|
1517
|
-
confidence += 60;
|
|
1518
|
-
version = parseVersionString(deps['parcel-bundler']);
|
|
1519
|
-
sources.push({ type: 'package.json', field: 'dependencies.parcel-bundler' });
|
|
1111
|
+
if (deps['webpack']) {
|
|
1112
|
+
confidence += 50;
|
|
1113
|
+
version = parseVersionString(deps['webpack']);
|
|
1114
|
+
sources.push({ type: 'package.json', field: 'dependencies.webpack' });
|
|
1520
1115
|
}
|
|
1521
|
-
const configPath = locateConfigFile(projectPath,
|
|
1116
|
+
const configPath = locateConfigFile(projectPath, WEBPACK_CONFIG_PATTERNS);
|
|
1522
1117
|
if (configPath) {
|
|
1523
|
-
confidence +=
|
|
1118
|
+
confidence += 40;
|
|
1524
1119
|
sources.push({ type: 'config-file', path: configPath });
|
|
1525
1120
|
}
|
|
1526
|
-
|
|
1121
|
+
if (deps['webpack-cli']) {
|
|
1122
|
+
confidence += 10;
|
|
1123
|
+
sources.push({ type: 'package.json', field: 'dependencies.webpack-cli' });
|
|
1124
|
+
}
|
|
1125
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'webpack');
|
|
1527
1126
|
for (const name of scriptMatches) {
|
|
1528
|
-
confidence = min(confidence +
|
|
1127
|
+
confidence = min(confidence + 5, 100);
|
|
1529
1128
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1530
1129
|
}
|
|
1531
1130
|
if (confidence === 0) {
|
|
1532
1131
|
return null;
|
|
1533
1132
|
}
|
|
1534
1133
|
return {
|
|
1535
|
-
id: '
|
|
1536
|
-
name: '
|
|
1134
|
+
id: 'webpack',
|
|
1135
|
+
name: 'Webpack',
|
|
1537
1136
|
version,
|
|
1538
1137
|
configPath,
|
|
1539
1138
|
confidence: min(confidence, 100),
|
|
@@ -1553,81 +1152,187 @@ const buildToolDetectors = [
|
|
|
1553
1152
|
];
|
|
1554
1153
|
|
|
1555
1154
|
/**
|
|
1556
|
-
* Detect
|
|
1155
|
+
* Detect Angular in project.
|
|
1557
1156
|
*
|
|
1558
1157
|
* @param projectPath - Project directory path
|
|
1559
1158
|
* @param packageJson - Optional pre-loaded package.json
|
|
1560
1159
|
* @returns Detection result or null if not detected
|
|
1160
|
+
*
|
|
1161
|
+
* @example Detecting Angular framework
|
|
1162
|
+
* ```typescript
|
|
1163
|
+
* const result = angularDetector('/path/to/angular-app', {
|
|
1164
|
+
* dependencies: { '@angular/core': '^17.0.0', '@angular/cli': '^17.0.0' }
|
|
1165
|
+
* })
|
|
1166
|
+
* // => {
|
|
1167
|
+
* // id: 'angular',
|
|
1168
|
+
* // name: 'Angular',
|
|
1169
|
+
* // category: 'frontend',
|
|
1170
|
+
* // version: '17.0.0',
|
|
1171
|
+
* // confidence: 85,
|
|
1172
|
+
* // detectedFrom: [
|
|
1173
|
+
* // { type: 'package.json', field: 'dependencies.@angular/core' },
|
|
1174
|
+
* // { type: 'package.json', field: 'dependencies.@angular/cli' }
|
|
1175
|
+
* // ]
|
|
1176
|
+
* // }
|
|
1177
|
+
* ```
|
|
1561
1178
|
*/
|
|
1562
|
-
function
|
|
1179
|
+
function angularDetector(projectPath, packageJson) {
|
|
1563
1180
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1564
1181
|
const sources = [];
|
|
1565
1182
|
let confidence = 0;
|
|
1566
1183
|
let version;
|
|
1567
|
-
const metaFrameworks = [];
|
|
1568
1184
|
const deps = collectAllDependencies(pkg);
|
|
1569
|
-
if (deps['
|
|
1570
|
-
confidence +=
|
|
1571
|
-
version = parseVersionString(deps['
|
|
1572
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1185
|
+
if (deps['@angular/core']) {
|
|
1186
|
+
confidence += 70;
|
|
1187
|
+
version = parseVersionString(deps['@angular/core']);
|
|
1188
|
+
sources.push({ type: 'package.json', field: 'dependencies.@angular/core' });
|
|
1573
1189
|
}
|
|
1574
|
-
if (deps['
|
|
1575
|
-
confidence +=
|
|
1576
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1190
|
+
if (deps['@angular/cli']) {
|
|
1191
|
+
confidence += 15;
|
|
1192
|
+
sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
|
|
1577
1193
|
}
|
|
1578
|
-
if (
|
|
1579
|
-
confidence +=
|
|
1580
|
-
sources.push({ type: '
|
|
1194
|
+
if (exists(join$1(projectPath, 'angular.json'))) {
|
|
1195
|
+
confidence += 15;
|
|
1196
|
+
sources.push({ type: 'config-file', path: 'angular.json' });
|
|
1581
1197
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1198
|
+
if (deps['angular'] && !deps['@angular/core']) {
|
|
1199
|
+
return {
|
|
1200
|
+
id: 'angularjs',
|
|
1201
|
+
name: 'AngularJS (Legacy)',
|
|
1202
|
+
category: 'frontend',
|
|
1203
|
+
version: parseVersionString(deps['angular']),
|
|
1204
|
+
confidence: 80,
|
|
1205
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
1206
|
+
};
|
|
1589
1207
|
}
|
|
1590
|
-
if (
|
|
1591
|
-
|
|
1592
|
-
id: 'nextjs',
|
|
1593
|
-
name: 'Next.js',
|
|
1594
|
-
category: 'meta-framework',
|
|
1595
|
-
version: parseVersionString(deps['next']),
|
|
1596
|
-
confidence: 90,
|
|
1597
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }],
|
|
1598
|
-
});
|
|
1208
|
+
if (confidence === 0) {
|
|
1209
|
+
return null;
|
|
1599
1210
|
}
|
|
1211
|
+
return {
|
|
1212
|
+
id: 'angular',
|
|
1213
|
+
name: 'Angular',
|
|
1214
|
+
category: 'frontend',
|
|
1215
|
+
version,
|
|
1216
|
+
confidence: min(confidence, 100),
|
|
1217
|
+
detectedFrom: sources,
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* Detect Astro in project.
|
|
1223
|
+
*
|
|
1224
|
+
* @param projectPath - Project directory path
|
|
1225
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
1226
|
+
* @returns Detection result or null if not detected
|
|
1227
|
+
*
|
|
1228
|
+
* @example Detecting Astro framework
|
|
1229
|
+
* ```typescript
|
|
1230
|
+
* const result = astroDetector('/path/to/astro-project', {
|
|
1231
|
+
* dependencies: { 'astro': '^4.0.0' }
|
|
1232
|
+
* })
|
|
1233
|
+
* // => {
|
|
1234
|
+
* // id: 'astro',
|
|
1235
|
+
* // name: 'Astro',
|
|
1236
|
+
* // category: 'meta-framework',
|
|
1237
|
+
* // version: '4.0.0',
|
|
1238
|
+
* // confidence: 70,
|
|
1239
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.astro' }]
|
|
1240
|
+
* // }
|
|
1241
|
+
* ```
|
|
1242
|
+
*/
|
|
1243
|
+
function astroDetector(projectPath, packageJson) {
|
|
1244
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1245
|
+
const sources = [];
|
|
1246
|
+
let confidence = 0;
|
|
1247
|
+
let version;
|
|
1248
|
+
const deps = collectAllDependencies(pkg);
|
|
1249
|
+
if (deps['astro']) {
|
|
1250
|
+
confidence += 70;
|
|
1251
|
+
version = parseVersionString(deps['astro']);
|
|
1252
|
+
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
1253
|
+
}
|
|
1254
|
+
if (exists(join$1(projectPath, 'astro.config.mjs')) ||
|
|
1255
|
+
exists(join$1(projectPath, 'astro.config.ts')) ||
|
|
1256
|
+
exists(join$1(projectPath, 'astro.config.js'))) {
|
|
1257
|
+
confidence += 25;
|
|
1258
|
+
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
1259
|
+
}
|
|
1260
|
+
if (exists(join$1(projectPath, 'src', 'pages'))) {
|
|
1261
|
+
confidence += 5;
|
|
1262
|
+
sources.push({ type: 'directory', path: 'src/pages/' });
|
|
1263
|
+
}
|
|
1264
|
+
if (confidence === 0) {
|
|
1265
|
+
return null;
|
|
1266
|
+
}
|
|
1267
|
+
return {
|
|
1268
|
+
id: 'astro',
|
|
1269
|
+
name: 'Astro',
|
|
1270
|
+
category: 'meta-framework',
|
|
1271
|
+
version,
|
|
1272
|
+
confidence: min(confidence, 100),
|
|
1273
|
+
detectedFrom: sources,
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
/**
|
|
1278
|
+
* Detect Gatsby in project.
|
|
1279
|
+
*
|
|
1280
|
+
* @param projectPath - Project directory path
|
|
1281
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
1282
|
+
* @returns Detection result or null if not detected
|
|
1283
|
+
*
|
|
1284
|
+
* @example Detecting Gatsby framework
|
|
1285
|
+
* ```typescript
|
|
1286
|
+
* const result = gatsbyDetector('/path/to/gatsby-blog', {
|
|
1287
|
+
* dependencies: {
|
|
1288
|
+
* 'gatsby': '^5.0.0',
|
|
1289
|
+
* 'gatsby-plugin-image': '^3.0.0',
|
|
1290
|
+
* 'gatsby-source-filesystem': '^5.0.0'
|
|
1291
|
+
* }
|
|
1292
|
+
* })
|
|
1293
|
+
* // => {
|
|
1294
|
+
* // id: 'gatsby',
|
|
1295
|
+
* // name: 'Gatsby',
|
|
1296
|
+
* // category: 'meta-framework',
|
|
1297
|
+
* // version: '5.0.0',
|
|
1298
|
+
* // confidence: 75,
|
|
1299
|
+
* // detectedFrom: [
|
|
1300
|
+
* // { type: 'package.json', field: 'dependencies.gatsby' },
|
|
1301
|
+
* // { type: 'package.json', field: 'dependencies (gatsby plugins)' }
|
|
1302
|
+
* // ]
|
|
1303
|
+
* // }
|
|
1304
|
+
* ```
|
|
1305
|
+
*/
|
|
1306
|
+
function gatsbyDetector(projectPath, packageJson) {
|
|
1307
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1308
|
+
const sources = [];
|
|
1309
|
+
let confidence = 0;
|
|
1310
|
+
let version;
|
|
1311
|
+
const deps = collectAllDependencies(pkg);
|
|
1600
1312
|
if (deps['gatsby']) {
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
category: 'meta-framework',
|
|
1605
|
-
version: parseVersionString(deps['gatsby']),
|
|
1606
|
-
confidence: 90,
|
|
1607
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
1608
|
-
});
|
|
1313
|
+
confidence += 70;
|
|
1314
|
+
version = parseVersionString(deps['gatsby']);
|
|
1315
|
+
sources.push({ type: 'package.json', field: 'dependencies.gatsby' });
|
|
1609
1316
|
}
|
|
1610
|
-
if (
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
});
|
|
1317
|
+
if (exists(join$1(projectPath, 'gatsby-config.js')) || exists(join$1(projectPath, 'gatsby-config.ts'))) {
|
|
1318
|
+
confidence += 25;
|
|
1319
|
+
sources.push({ type: 'config-file', path: 'gatsby-config.*' });
|
|
1320
|
+
}
|
|
1321
|
+
const gatsbyPlugins = keys(deps).filter((d) => d.startsWith('gatsby-plugin-') || d.startsWith('gatsby-source-'));
|
|
1322
|
+
if (gatsbyPlugins.length > 0) {
|
|
1323
|
+
confidence += 5;
|
|
1324
|
+
sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
|
|
1619
1325
|
}
|
|
1620
1326
|
if (confidence === 0) {
|
|
1621
1327
|
return null;
|
|
1622
1328
|
}
|
|
1623
1329
|
return {
|
|
1624
|
-
id: '
|
|
1625
|
-
name: '
|
|
1626
|
-
category: '
|
|
1330
|
+
id: 'gatsby',
|
|
1331
|
+
name: 'Gatsby',
|
|
1332
|
+
category: 'meta-framework',
|
|
1627
1333
|
version,
|
|
1628
1334
|
confidence: min(confidence, 100),
|
|
1629
1335
|
detectedFrom: sources,
|
|
1630
|
-
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
1631
1336
|
};
|
|
1632
1337
|
}
|
|
1633
1338
|
|
|
@@ -1637,6 +1342,21 @@ function reactDetector(projectPath, packageJson) {
|
|
|
1637
1342
|
* @param projectPath - Project directory path
|
|
1638
1343
|
* @param packageJson - Optional pre-loaded package.json
|
|
1639
1344
|
* @returns Detection result or null if not detected
|
|
1345
|
+
*
|
|
1346
|
+
* @example Detecting Next.js framework
|
|
1347
|
+
* ```typescript
|
|
1348
|
+
* const result = nextjsDetector('/path/to/nextjs-app', {
|
|
1349
|
+
* dependencies: { 'next': '^14.0.0', 'react': '^18.0.0' }
|
|
1350
|
+
* })
|
|
1351
|
+
* // => {
|
|
1352
|
+
* // id: 'nextjs',
|
|
1353
|
+
* // name: 'Next.js',
|
|
1354
|
+
* // category: 'meta-framework',
|
|
1355
|
+
* // version: '14.0.0',
|
|
1356
|
+
* // confidence: 70,
|
|
1357
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }]
|
|
1358
|
+
* // }
|
|
1359
|
+
* ```
|
|
1640
1360
|
*/
|
|
1641
1361
|
function nextjsDetector(projectPath, packageJson) {
|
|
1642
1362
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1676,38 +1396,52 @@ function nextjsDetector(projectPath, packageJson) {
|
|
|
1676
1396
|
}
|
|
1677
1397
|
|
|
1678
1398
|
/**
|
|
1679
|
-
* Detect
|
|
1399
|
+
* Detect Nuxt in project.
|
|
1680
1400
|
*
|
|
1681
1401
|
* @param projectPath - Project directory path
|
|
1682
1402
|
* @param packageJson - Optional pre-loaded package.json
|
|
1683
1403
|
* @returns Detection result or null if not detected
|
|
1404
|
+
*
|
|
1405
|
+
* @example Detecting Nuxt framework
|
|
1406
|
+
* ```typescript
|
|
1407
|
+
* const result = nuxtDetector('/path/to/nuxt-app', {
|
|
1408
|
+
* dependencies: { 'nuxt': '^3.0.0', 'vue': '^3.0.0' }
|
|
1409
|
+
* })
|
|
1410
|
+
* // => {
|
|
1411
|
+
* // id: 'nuxt',
|
|
1412
|
+
* // name: 'Nuxt',
|
|
1413
|
+
* // category: 'meta-framework',
|
|
1414
|
+
* // version: '3.0.0',
|
|
1415
|
+
* // confidence: 70,
|
|
1416
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }]
|
|
1417
|
+
* // }
|
|
1418
|
+
* ```
|
|
1684
1419
|
*/
|
|
1685
|
-
function
|
|
1420
|
+
function nuxtDetector(projectPath, packageJson) {
|
|
1686
1421
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1687
1422
|
const sources = [];
|
|
1688
1423
|
let confidence = 0;
|
|
1689
1424
|
let version;
|
|
1690
1425
|
const deps = collectAllDependencies(pkg);
|
|
1691
|
-
|
|
1692
|
-
if (deps['@remix-run/react']) {
|
|
1426
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
1693
1427
|
confidence += 70;
|
|
1694
|
-
version = parseVersionString(deps['
|
|
1695
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1428
|
+
version = parseVersionString(deps['nuxt'] ?? deps['nuxt3']);
|
|
1429
|
+
sources.push({ type: 'package.json', field: 'dependencies.nuxt' });
|
|
1696
1430
|
}
|
|
1697
|
-
if (
|
|
1698
|
-
confidence +=
|
|
1699
|
-
sources.push({ type: '
|
|
1431
|
+
if (exists(join$1(projectPath, 'nuxt.config.js')) || exists(join$1(projectPath, 'nuxt.config.ts'))) {
|
|
1432
|
+
confidence += 25;
|
|
1433
|
+
sources.push({ type: 'config-file', path: 'nuxt.config.*' });
|
|
1700
1434
|
}
|
|
1701
|
-
if (exists(join$1(projectPath, '
|
|
1702
|
-
confidence +=
|
|
1703
|
-
sources.push({ type: '
|
|
1435
|
+
if (exists(join$1(projectPath, 'pages'))) {
|
|
1436
|
+
confidence += 5;
|
|
1437
|
+
sources.push({ type: 'directory', path: 'pages/' });
|
|
1704
1438
|
}
|
|
1705
1439
|
if (confidence === 0) {
|
|
1706
1440
|
return null;
|
|
1707
1441
|
}
|
|
1708
1442
|
return {
|
|
1709
|
-
id: '
|
|
1710
|
-
name: '
|
|
1443
|
+
id: 'nuxt',
|
|
1444
|
+
name: 'Nuxt',
|
|
1711
1445
|
category: 'meta-framework',
|
|
1712
1446
|
version,
|
|
1713
1447
|
confidence: min(confidence, 100),
|
|
@@ -1716,39 +1450,59 @@ function remixDetector(projectPath, packageJson) {
|
|
|
1716
1450
|
}
|
|
1717
1451
|
|
|
1718
1452
|
/**
|
|
1719
|
-
* Detect
|
|
1453
|
+
* Detect Qwik in project.
|
|
1720
1454
|
*
|
|
1721
1455
|
* @param projectPath - Project directory path
|
|
1722
1456
|
* @param packageJson - Optional pre-loaded package.json
|
|
1723
1457
|
* @returns Detection result or null if not detected
|
|
1458
|
+
*
|
|
1459
|
+
* @example Detecting Qwik framework
|
|
1460
|
+
* ```typescript
|
|
1461
|
+
* const result = qwikDetector('/path/to/qwik-app', {
|
|
1462
|
+
* dependencies: {
|
|
1463
|
+
* '@builder.io/qwik': '^1.0.0',
|
|
1464
|
+
* '@builder.io/qwik-city': '^1.0.0'
|
|
1465
|
+
* }
|
|
1466
|
+
* })
|
|
1467
|
+
* // => {
|
|
1468
|
+
* // id: 'qwik',
|
|
1469
|
+
* // name: 'Qwik',
|
|
1470
|
+
* // category: 'frontend',
|
|
1471
|
+
* // version: '1.0.0',
|
|
1472
|
+
* // confidence: 90,
|
|
1473
|
+
* // detectedFrom: [
|
|
1474
|
+
* // { type: 'package.json', field: 'dependencies.@builder.io/qwik' },
|
|
1475
|
+
* // { type: 'package.json', field: 'dependencies.@builder.io/qwik-city' }
|
|
1476
|
+
* // ]
|
|
1477
|
+
* // }
|
|
1478
|
+
* ```
|
|
1724
1479
|
*/
|
|
1725
|
-
function
|
|
1480
|
+
function qwikDetector(projectPath, packageJson) {
|
|
1726
1481
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1727
1482
|
const sources = [];
|
|
1728
1483
|
let confidence = 0;
|
|
1729
1484
|
let version;
|
|
1730
1485
|
const deps = collectAllDependencies(pkg);
|
|
1731
|
-
if (deps['
|
|
1486
|
+
if (deps['@builder.io/qwik']) {
|
|
1732
1487
|
confidence += 70;
|
|
1733
|
-
version = parseVersionString(deps['
|
|
1734
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1488
|
+
version = parseVersionString(deps['@builder.io/qwik']);
|
|
1489
|
+
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
|
|
1735
1490
|
}
|
|
1736
|
-
if (
|
|
1737
|
-
confidence +=
|
|
1738
|
-
sources.push({ type: '
|
|
1491
|
+
if (deps['@builder.io/qwik-city']) {
|
|
1492
|
+
confidence += 20;
|
|
1493
|
+
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
|
|
1739
1494
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
|
|
1495
|
+
if (exists(join$1(projectPath, 'qwik.config.ts')) || exists(join$1(projectPath, 'qwik.config.js'))) {
|
|
1496
|
+
confidence += 10;
|
|
1497
|
+
sources.push({ type: 'config-file', path: 'qwik.config.*' });
|
|
1744
1498
|
}
|
|
1745
1499
|
if (confidence === 0) {
|
|
1746
1500
|
return null;
|
|
1747
1501
|
}
|
|
1748
1502
|
return {
|
|
1749
|
-
id: '
|
|
1750
|
-
name: '
|
|
1751
|
-
category: '
|
|
1503
|
+
id: 'qwik',
|
|
1504
|
+
name: 'Qwik',
|
|
1505
|
+
category: 'frontend',
|
|
1752
1506
|
version,
|
|
1753
1507
|
confidence: min(confidence, 100),
|
|
1754
1508
|
detectedFrom: sources,
|
|
@@ -1756,53 +1510,94 @@ function gatsbyDetector(projectPath, packageJson) {
|
|
|
1756
1510
|
}
|
|
1757
1511
|
|
|
1758
1512
|
/**
|
|
1759
|
-
* Detect
|
|
1513
|
+
* Detect React in project.
|
|
1760
1514
|
*
|
|
1761
1515
|
* @param projectPath - Project directory path
|
|
1762
1516
|
* @param packageJson - Optional pre-loaded package.json
|
|
1763
1517
|
* @returns Detection result or null if not detected
|
|
1518
|
+
*
|
|
1519
|
+
* @example Detecting React library
|
|
1520
|
+
* ```typescript
|
|
1521
|
+
* const result = reactDetector('/path/to/react-app', {
|
|
1522
|
+
* dependencies: { 'react': '^18.0.0', 'react-dom': '^18.0.0' }
|
|
1523
|
+
* })
|
|
1524
|
+
* // => {
|
|
1525
|
+
* // id: 'react',
|
|
1526
|
+
* // name: 'React',
|
|
1527
|
+
* // category: 'frontend',
|
|
1528
|
+
* // version: '18.0.0',
|
|
1529
|
+
* // confidence: 80,
|
|
1530
|
+
* // detectedFrom: [
|
|
1531
|
+
* // { type: 'package.json', field: 'dependencies.react' },
|
|
1532
|
+
* // { type: 'package.json', field: 'dependencies.react-dom' }
|
|
1533
|
+
* // ]
|
|
1534
|
+
* // }
|
|
1535
|
+
* ```
|
|
1764
1536
|
*/
|
|
1765
|
-
function
|
|
1537
|
+
function reactDetector(projectPath, packageJson) {
|
|
1766
1538
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1767
1539
|
const sources = [];
|
|
1768
1540
|
let confidence = 0;
|
|
1769
1541
|
let version;
|
|
1770
1542
|
const metaFrameworks = [];
|
|
1771
1543
|
const deps = collectAllDependencies(pkg);
|
|
1772
|
-
if (deps['
|
|
1773
|
-
confidence +=
|
|
1774
|
-
version = parseVersionString(deps['
|
|
1775
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1544
|
+
if (deps['react']) {
|
|
1545
|
+
confidence += 60;
|
|
1546
|
+
version = parseVersionString(deps['react']);
|
|
1547
|
+
sources.push({ type: 'package.json', field: 'dependencies.react' });
|
|
1776
1548
|
}
|
|
1777
|
-
if (deps['
|
|
1778
|
-
confidence +=
|
|
1779
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1549
|
+
if (deps['react-dom']) {
|
|
1550
|
+
confidence += 20;
|
|
1551
|
+
sources.push({ type: 'package.json', field: 'dependencies.react-dom' });
|
|
1780
1552
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1553
|
+
if (deps['react-native']) {
|
|
1554
|
+
confidence += 20;
|
|
1555
|
+
sources.push({ type: 'package.json', field: 'dependencies.react-native' });
|
|
1556
|
+
}
|
|
1557
|
+
const hasJsxFiles = exists(join$1(projectPath, 'src', 'App.tsx')) ||
|
|
1558
|
+
exists(join$1(projectPath, 'src', 'App.jsx')) ||
|
|
1559
|
+
exists(join$1(projectPath, 'src', 'index.tsx')) ||
|
|
1560
|
+
exists(join$1(projectPath, 'src', 'index.jsx'));
|
|
1561
|
+
if (hasJsxFiles) {
|
|
1783
1562
|
confidence += 10;
|
|
1784
|
-
sources.push({ type: 'directory', path: 'src/*.
|
|
1563
|
+
sources.push({ type: 'directory', path: 'src/*.tsx or src/*.jsx' });
|
|
1785
1564
|
}
|
|
1786
|
-
if (
|
|
1787
|
-
|
|
1788
|
-
|
|
1565
|
+
if (deps['next']) {
|
|
1566
|
+
metaFrameworks.push({
|
|
1567
|
+
id: 'nextjs',
|
|
1568
|
+
name: 'Next.js',
|
|
1569
|
+
category: 'meta-framework',
|
|
1570
|
+
version: parseVersionString(deps['next']),
|
|
1571
|
+
confidence: 90,
|
|
1572
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }],
|
|
1573
|
+
});
|
|
1789
1574
|
}
|
|
1790
|
-
if (deps['
|
|
1575
|
+
if (deps['gatsby']) {
|
|
1791
1576
|
metaFrameworks.push({
|
|
1792
|
-
id: '
|
|
1793
|
-
name: '
|
|
1577
|
+
id: 'gatsby',
|
|
1578
|
+
name: 'Gatsby',
|
|
1794
1579
|
category: 'meta-framework',
|
|
1795
|
-
version: parseVersionString(deps['
|
|
1580
|
+
version: parseVersionString(deps['gatsby']),
|
|
1796
1581
|
confidence: 90,
|
|
1797
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.
|
|
1582
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
if (deps['@remix-run/react'] || deps['remix']) {
|
|
1586
|
+
metaFrameworks.push({
|
|
1587
|
+
id: 'remix',
|
|
1588
|
+
name: 'Remix',
|
|
1589
|
+
category: 'meta-framework',
|
|
1590
|
+
version: parseVersionString(deps['@remix-run/react'] ?? deps['remix']),
|
|
1591
|
+
confidence: 90,
|
|
1592
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.@remix-run/react' }],
|
|
1798
1593
|
});
|
|
1799
1594
|
}
|
|
1800
1595
|
if (confidence === 0) {
|
|
1801
1596
|
return null;
|
|
1802
1597
|
}
|
|
1803
1598
|
return {
|
|
1804
|
-
id: '
|
|
1805
|
-
name: '
|
|
1599
|
+
id: 'react',
|
|
1600
|
+
name: 'React',
|
|
1806
1601
|
category: 'frontend',
|
|
1807
1602
|
version,
|
|
1808
1603
|
confidence: min(confidence, 100),
|
|
@@ -1812,37 +1607,58 @@ function vueDetector(projectPath, packageJson) {
|
|
|
1812
1607
|
}
|
|
1813
1608
|
|
|
1814
1609
|
/**
|
|
1815
|
-
* Detect
|
|
1610
|
+
* Detect Remix in project.
|
|
1816
1611
|
*
|
|
1817
1612
|
* @param projectPath - Project directory path
|
|
1818
1613
|
* @param packageJson - Optional pre-loaded package.json
|
|
1819
1614
|
* @returns Detection result or null if not detected
|
|
1615
|
+
*
|
|
1616
|
+
* @example Detecting Remix framework
|
|
1617
|
+
* ```typescript
|
|
1618
|
+
* const result = remixDetector('/path/to/remix-app', {
|
|
1619
|
+
* dependencies: {
|
|
1620
|
+
* '@remix-run/react': '^2.0.0',
|
|
1621
|
+
* '@remix-run/node': '^2.0.0'
|
|
1622
|
+
* }
|
|
1623
|
+
* })
|
|
1624
|
+
* // => {
|
|
1625
|
+
* // id: 'remix',
|
|
1626
|
+
* // name: 'Remix',
|
|
1627
|
+
* // category: 'meta-framework',
|
|
1628
|
+
* // version: '2.0.0',
|
|
1629
|
+
* // confidence: 90,
|
|
1630
|
+
* // detectedFrom: [
|
|
1631
|
+
* // { type: 'package.json', field: 'dependencies.@remix-run/react' },
|
|
1632
|
+
* // { type: 'package.json', field: 'dependencies.@remix-run/*' }
|
|
1633
|
+
* // ]
|
|
1634
|
+
* // }
|
|
1635
|
+
* ```
|
|
1820
1636
|
*/
|
|
1821
|
-
function
|
|
1637
|
+
function remixDetector(projectPath, packageJson) {
|
|
1822
1638
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1823
1639
|
const sources = [];
|
|
1824
1640
|
let confidence = 0;
|
|
1825
1641
|
let version;
|
|
1826
1642
|
const deps = collectAllDependencies(pkg);
|
|
1827
|
-
if (deps['
|
|
1643
|
+
if (deps['@remix-run/react']) {
|
|
1828
1644
|
confidence += 70;
|
|
1829
|
-
version = parseVersionString(deps['
|
|
1830
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1645
|
+
version = parseVersionString(deps['@remix-run/react']);
|
|
1646
|
+
sources.push({ type: 'package.json', field: 'dependencies.@remix-run/react' });
|
|
1831
1647
|
}
|
|
1832
|
-
if (
|
|
1833
|
-
confidence +=
|
|
1834
|
-
sources.push({ type: '
|
|
1648
|
+
if (deps['@remix-run/node'] || deps['@remix-run/cloudflare'] || deps['@remix-run/deno']) {
|
|
1649
|
+
confidence += 20;
|
|
1650
|
+
sources.push({ type: 'package.json', field: 'dependencies.@remix-run/*' });
|
|
1835
1651
|
}
|
|
1836
|
-
if (exists(join$1(projectPath, '
|
|
1837
|
-
confidence +=
|
|
1838
|
-
sources.push({ type: '
|
|
1652
|
+
if (exists(join$1(projectPath, 'remix.config.js')) || exists(join$1(projectPath, 'remix.config.ts'))) {
|
|
1653
|
+
confidence += 10;
|
|
1654
|
+
sources.push({ type: 'config-file', path: 'remix.config.*' });
|
|
1839
1655
|
}
|
|
1840
1656
|
if (confidence === 0) {
|
|
1841
1657
|
return null;
|
|
1842
1658
|
}
|
|
1843
1659
|
return {
|
|
1844
|
-
id: '
|
|
1845
|
-
name: '
|
|
1660
|
+
id: 'remix',
|
|
1661
|
+
name: 'Remix',
|
|
1846
1662
|
category: 'meta-framework',
|
|
1847
1663
|
version,
|
|
1848
1664
|
confidence: min(confidence, 100),
|
|
@@ -1851,47 +1667,55 @@ function nuxtDetector(projectPath, packageJson) {
|
|
|
1851
1667
|
}
|
|
1852
1668
|
|
|
1853
1669
|
/**
|
|
1854
|
-
* Detect
|
|
1670
|
+
* Detect Solid in project.
|
|
1855
1671
|
*
|
|
1856
1672
|
* @param projectPath - Project directory path
|
|
1857
1673
|
* @param packageJson - Optional pre-loaded package.json
|
|
1858
1674
|
* @returns Detection result or null if not detected
|
|
1675
|
+
*
|
|
1676
|
+
* @example Detecting Solid.js framework
|
|
1677
|
+
* ```typescript
|
|
1678
|
+
* const result = solidDetector('/path/to/solid-app', {
|
|
1679
|
+
* dependencies: { 'solid-js': '^1.8.0', 'vite-plugin-solid': '^2.0.0' }
|
|
1680
|
+
* })
|
|
1681
|
+
* // => {
|
|
1682
|
+
* // id: 'solid',
|
|
1683
|
+
* // name: 'Solid',
|
|
1684
|
+
* // category: 'frontend',
|
|
1685
|
+
* // version: '1.8.0',
|
|
1686
|
+
* // confidence: 90,
|
|
1687
|
+
* // detectedFrom: [
|
|
1688
|
+
* // { type: 'package.json', field: 'dependencies.solid-js' },
|
|
1689
|
+
* // { type: 'package.json', field: 'dependencies.vite-plugin-solid' }
|
|
1690
|
+
* // ]
|
|
1691
|
+
* // }
|
|
1692
|
+
* ```
|
|
1859
1693
|
*/
|
|
1860
|
-
function
|
|
1694
|
+
function solidDetector(projectPath, packageJson) {
|
|
1861
1695
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1862
1696
|
const sources = [];
|
|
1863
1697
|
let confidence = 0;
|
|
1864
1698
|
let version;
|
|
1865
1699
|
const deps = collectAllDependencies(pkg);
|
|
1866
|
-
if (deps['
|
|
1700
|
+
if (deps['solid-js']) {
|
|
1867
1701
|
confidence += 70;
|
|
1868
|
-
version = parseVersionString(deps['
|
|
1869
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1870
|
-
}
|
|
1871
|
-
if (deps['@angular/cli']) {
|
|
1872
|
-
confidence += 15;
|
|
1873
|
-
sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
|
|
1702
|
+
version = parseVersionString(deps['solid-js']);
|
|
1703
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
1874
1704
|
}
|
|
1875
|
-
if (
|
|
1876
|
-
confidence +=
|
|
1877
|
-
sources.push({ type: '
|
|
1705
|
+
if (deps['vite-plugin-solid']) {
|
|
1706
|
+
confidence += 20;
|
|
1707
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
1878
1708
|
}
|
|
1879
|
-
if (deps['
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
name: 'AngularJS (Legacy)',
|
|
1883
|
-
category: 'frontend',
|
|
1884
|
-
version: parseVersionString(deps['angular']),
|
|
1885
|
-
confidence: 80,
|
|
1886
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
1887
|
-
};
|
|
1709
|
+
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
1710
|
+
confidence += 10;
|
|
1711
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
1888
1712
|
}
|
|
1889
1713
|
if (confidence === 0) {
|
|
1890
1714
|
return null;
|
|
1891
1715
|
}
|
|
1892
1716
|
return {
|
|
1893
|
-
id: '
|
|
1894
|
-
name: '
|
|
1717
|
+
id: 'solid',
|
|
1718
|
+
name: 'Solid',
|
|
1895
1719
|
category: 'frontend',
|
|
1896
1720
|
version,
|
|
1897
1721
|
confidence: min(confidence, 100),
|
|
@@ -1905,6 +1729,21 @@ function angularDetector(projectPath, packageJson) {
|
|
|
1905
1729
|
* @param projectPath - Project directory path
|
|
1906
1730
|
* @param packageJson - Optional pre-loaded package.json
|
|
1907
1731
|
* @returns Detection result or null if not detected
|
|
1732
|
+
*
|
|
1733
|
+
* @example Detecting Svelte framework
|
|
1734
|
+
* ```typescript
|
|
1735
|
+
* const result = svelteDetector('/path/to/svelte-app', {
|
|
1736
|
+
* devDependencies: { 'svelte': '^4.0.0' }
|
|
1737
|
+
* })
|
|
1738
|
+
* // => {
|
|
1739
|
+
* // id: 'svelte',
|
|
1740
|
+
* // name: 'Svelte',
|
|
1741
|
+
* // category: 'frontend',
|
|
1742
|
+
* // version: '4.0.0',
|
|
1743
|
+
* // confidence: 70,
|
|
1744
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.svelte' }]
|
|
1745
|
+
* // }
|
|
1746
|
+
* ```
|
|
1908
1747
|
*/
|
|
1909
1748
|
function svelteDetector(projectPath, packageJson) {
|
|
1910
1749
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1957,6 +1796,21 @@ function svelteDetector(projectPath, packageJson) {
|
|
|
1957
1796
|
* @param projectPath - Project directory path
|
|
1958
1797
|
* @param packageJson - Optional pre-loaded package.json
|
|
1959
1798
|
* @returns Detection result or null if not detected
|
|
1799
|
+
*
|
|
1800
|
+
* @example Detecting SvelteKit framework
|
|
1801
|
+
* ```typescript
|
|
1802
|
+
* const result = sveltekitDetector('/path/to/sveltekit-app', {
|
|
1803
|
+
* devDependencies: { '@sveltejs/kit': '^2.0.0', 'svelte': '^4.0.0' }
|
|
1804
|
+
* })
|
|
1805
|
+
* // => {
|
|
1806
|
+
* // id: 'sveltekit',
|
|
1807
|
+
* // name: 'SvelteKit',
|
|
1808
|
+
* // category: 'meta-framework',
|
|
1809
|
+
* // version: '2.0.0',
|
|
1810
|
+
* // confidence: 70,
|
|
1811
|
+
* // detectedFrom: [{ type: 'package.json', field: 'dependencies.@sveltejs/kit' }]
|
|
1812
|
+
* // }
|
|
1813
|
+
* ```
|
|
1960
1814
|
*/
|
|
1961
1815
|
function sveltekitDetector(projectPath, packageJson) {
|
|
1962
1816
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1964,7 +1818,6 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
1964
1818
|
let confidence = 0;
|
|
1965
1819
|
let version;
|
|
1966
1820
|
const deps = collectAllDependencies(pkg);
|
|
1967
|
-
// @sveltejs/kit package
|
|
1968
1821
|
if (deps['@sveltejs/kit']) {
|
|
1969
1822
|
confidence += 70;
|
|
1970
1823
|
version = parseVersionString(deps['@sveltejs/kit']);
|
|
@@ -1992,123 +1845,76 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
1992
1845
|
}
|
|
1993
1846
|
|
|
1994
1847
|
/**
|
|
1995
|
-
* Detect
|
|
1848
|
+
* Detect Vue in project.
|
|
1996
1849
|
*
|
|
1997
1850
|
* @param projectPath - Project directory path
|
|
1998
1851
|
* @param packageJson - Optional pre-loaded package.json
|
|
1999
1852
|
* @returns Detection result or null if not detected
|
|
2000
|
-
*/
|
|
2001
|
-
function solidDetector(projectPath, packageJson) {
|
|
2002
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2003
|
-
const sources = [];
|
|
2004
|
-
let confidence = 0;
|
|
2005
|
-
let version;
|
|
2006
|
-
const deps = collectAllDependencies(pkg);
|
|
2007
|
-
if (deps['solid-js']) {
|
|
2008
|
-
confidence += 70;
|
|
2009
|
-
version = parseVersionString(deps['solid-js']);
|
|
2010
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
2011
|
-
}
|
|
2012
|
-
if (deps['vite-plugin-solid']) {
|
|
2013
|
-
confidence += 20;
|
|
2014
|
-
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
2015
|
-
}
|
|
2016
|
-
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
2017
|
-
confidence += 10;
|
|
2018
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
2019
|
-
}
|
|
2020
|
-
if (confidence === 0) {
|
|
2021
|
-
return null;
|
|
2022
|
-
}
|
|
2023
|
-
return {
|
|
2024
|
-
id: 'solid',
|
|
2025
|
-
name: 'Solid',
|
|
2026
|
-
category: 'frontend',
|
|
2027
|
-
version,
|
|
2028
|
-
confidence: min(confidence, 100),
|
|
2029
|
-
detectedFrom: sources,
|
|
2030
|
-
};
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
/**
|
|
2034
|
-
* Detect Qwik in project.
|
|
2035
1853
|
*
|
|
2036
|
-
* @
|
|
2037
|
-
*
|
|
2038
|
-
*
|
|
1854
|
+
* @example Detecting Vue.js framework
|
|
1855
|
+
* ```typescript
|
|
1856
|
+
* const result = vueDetector('/path/to/vue-app', {
|
|
1857
|
+
* dependencies: { 'vue': '^3.0.0', '@vue/cli-service': '^5.0.0' }
|
|
1858
|
+
* })
|
|
1859
|
+
* // => {
|
|
1860
|
+
* // id: 'vue',
|
|
1861
|
+
* // name: 'Vue',
|
|
1862
|
+
* // category: 'frontend',
|
|
1863
|
+
* // version: '3.0.0',
|
|
1864
|
+
* // confidence: 85,
|
|
1865
|
+
* // detectedFrom: [
|
|
1866
|
+
* // { type: 'package.json', field: 'dependencies.vue' },
|
|
1867
|
+
* // { type: 'package.json', field: 'dependencies.@vue/cli-service' }
|
|
1868
|
+
* // ]
|
|
1869
|
+
* // }
|
|
1870
|
+
* ```
|
|
2039
1871
|
*/
|
|
2040
|
-
function
|
|
1872
|
+
function vueDetector(projectPath, packageJson) {
|
|
2041
1873
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2042
1874
|
const sources = [];
|
|
2043
1875
|
let confidence = 0;
|
|
2044
1876
|
let version;
|
|
1877
|
+
const metaFrameworks = [];
|
|
2045
1878
|
const deps = collectAllDependencies(pkg);
|
|
2046
|
-
|
|
2047
|
-
if (deps['@builder.io/qwik']) {
|
|
1879
|
+
if (deps['vue']) {
|
|
2048
1880
|
confidence += 70;
|
|
2049
|
-
version = parseVersionString(deps['
|
|
2050
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1881
|
+
version = parseVersionString(deps['vue']);
|
|
1882
|
+
sources.push({ type: 'package.json', field: 'dependencies.vue' });
|
|
2051
1883
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
|
|
1884
|
+
if (deps['@vue/cli-service']) {
|
|
1885
|
+
confidence += 15;
|
|
1886
|
+
sources.push({ type: 'package.json', field: 'dependencies.@vue/cli-service' });
|
|
2056
1887
|
}
|
|
2057
|
-
|
|
1888
|
+
const hasVueFiles = exists(join$1(projectPath, 'src', 'App.vue')) || exists(join$1(projectPath, 'src', 'main.vue'));
|
|
1889
|
+
if (hasVueFiles) {
|
|
2058
1890
|
confidence += 10;
|
|
2059
|
-
sources.push({ type: '
|
|
2060
|
-
}
|
|
2061
|
-
if (confidence === 0) {
|
|
2062
|
-
return null;
|
|
2063
|
-
}
|
|
2064
|
-
return {
|
|
2065
|
-
id: 'qwik',
|
|
2066
|
-
name: 'Qwik',
|
|
2067
|
-
category: 'frontend',
|
|
2068
|
-
version,
|
|
2069
|
-
confidence: min(confidence, 100),
|
|
2070
|
-
detectedFrom: sources,
|
|
2071
|
-
};
|
|
2072
|
-
}
|
|
2073
|
-
|
|
2074
|
-
/**
|
|
2075
|
-
* Detect Astro in project.
|
|
2076
|
-
*
|
|
2077
|
-
* @param projectPath - Project directory path
|
|
2078
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2079
|
-
* @returns Detection result or null if not detected
|
|
2080
|
-
*/
|
|
2081
|
-
function astroDetector(projectPath, packageJson) {
|
|
2082
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2083
|
-
const sources = [];
|
|
2084
|
-
let confidence = 0;
|
|
2085
|
-
let version;
|
|
2086
|
-
const deps = collectAllDependencies(pkg);
|
|
2087
|
-
if (deps['astro']) {
|
|
2088
|
-
confidence += 70;
|
|
2089
|
-
version = parseVersionString(deps['astro']);
|
|
2090
|
-
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
2091
|
-
}
|
|
2092
|
-
if (exists(join$1(projectPath, 'astro.config.mjs')) ||
|
|
2093
|
-
exists(join$1(projectPath, 'astro.config.ts')) ||
|
|
2094
|
-
exists(join$1(projectPath, 'astro.config.js'))) {
|
|
2095
|
-
confidence += 25;
|
|
2096
|
-
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
1891
|
+
sources.push({ type: 'directory', path: 'src/*.vue' });
|
|
2097
1892
|
}
|
|
2098
|
-
if (exists(join$1(projectPath, '
|
|
1893
|
+
if (exists(join$1(projectPath, 'vue.config.js'))) {
|
|
2099
1894
|
confidence += 5;
|
|
2100
|
-
sources.push({ type: '
|
|
1895
|
+
sources.push({ type: 'config-file', path: 'vue.config.js' });
|
|
1896
|
+
}
|
|
1897
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
1898
|
+
metaFrameworks.push({
|
|
1899
|
+
id: 'nuxt',
|
|
1900
|
+
name: 'Nuxt',
|
|
1901
|
+
category: 'meta-framework',
|
|
1902
|
+
version: parseVersionString(deps['nuxt'] ?? deps['nuxt3']),
|
|
1903
|
+
confidence: 90,
|
|
1904
|
+
detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }],
|
|
1905
|
+
});
|
|
2101
1906
|
}
|
|
2102
1907
|
if (confidence === 0) {
|
|
2103
1908
|
return null;
|
|
2104
1909
|
}
|
|
2105
1910
|
return {
|
|
2106
|
-
id: '
|
|
2107
|
-
name: '
|
|
2108
|
-
category: '
|
|
1911
|
+
id: 'vue',
|
|
1912
|
+
name: 'Vue',
|
|
1913
|
+
category: 'frontend',
|
|
2109
1914
|
version,
|
|
2110
1915
|
confidence: min(confidence, 100),
|
|
2111
1916
|
detectedFrom: sources,
|
|
1917
|
+
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
2112
1918
|
};
|
|
2113
1919
|
}
|
|
2114
1920
|
|
|
@@ -2135,6 +1941,14 @@ const frameworkDetectors = [
|
|
|
2135
1941
|
* @param projectPath - Project directory path
|
|
2136
1942
|
* @param packageJson - Optional pre-loaded package.json
|
|
2137
1943
|
* @returns Detection result or null if not detected
|
|
1944
|
+
*
|
|
1945
|
+
* @example Detecting AngularJS framework
|
|
1946
|
+
* ```typescript
|
|
1947
|
+
* const result = angularJSDetector('/path/to/project', {
|
|
1948
|
+
* dependencies: { angular: '^1.8.0', 'angular-route': '^1.8.0' },
|
|
1949
|
+
* })
|
|
1950
|
+
* // => { id: 'angularjs', name: 'AngularJS', confidence: 85, version: '1.8.0', ... }
|
|
1951
|
+
* ```
|
|
2138
1952
|
*/
|
|
2139
1953
|
function angularJSDetector(projectPath, packageJson) {
|
|
2140
1954
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2142,23 +1956,19 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
2142
1956
|
let confidence = 0;
|
|
2143
1957
|
let version;
|
|
2144
1958
|
const deps = collectAllDependencies(pkg);
|
|
2145
|
-
// AngularJS package (angular, not @angular/core)
|
|
2146
1959
|
if (deps['angular']) {
|
|
2147
1960
|
confidence += 70;
|
|
2148
1961
|
version = parseVersionString(deps['angular']);
|
|
2149
1962
|
sources.push({ type: 'package.json', field: 'dependencies.angular' });
|
|
2150
1963
|
}
|
|
2151
|
-
// AngularJS router
|
|
2152
1964
|
if (deps['angular-route']) {
|
|
2153
1965
|
confidence += 15;
|
|
2154
1966
|
sources.push({ type: 'package.json', field: 'dependencies.angular-route' });
|
|
2155
1967
|
}
|
|
2156
|
-
// AngularJS resource
|
|
2157
1968
|
if (deps['angular-resource']) {
|
|
2158
1969
|
confidence += 10;
|
|
2159
1970
|
sources.push({ type: 'package.json', field: 'dependencies.angular-resource' });
|
|
2160
1971
|
}
|
|
2161
|
-
// AngularJS animate
|
|
2162
1972
|
if (deps['angular-animate']) {
|
|
2163
1973
|
confidence += 5;
|
|
2164
1974
|
sources.push({ type: 'package.json', field: 'dependencies.angular-animate' });
|
|
@@ -2182,6 +1992,14 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
2182
1992
|
* @param projectPath - Project directory path
|
|
2183
1993
|
* @param packageJson - Optional pre-loaded package.json
|
|
2184
1994
|
* @returns Detection result or null if not detected
|
|
1995
|
+
*
|
|
1996
|
+
* @example Detecting Backbone.js framework
|
|
1997
|
+
* ```typescript
|
|
1998
|
+
* const result = backboneDetector('/path/to/project', {
|
|
1999
|
+
* dependencies: { backbone: '^1.4.0', underscore: '^1.13.0' },
|
|
2000
|
+
* })
|
|
2001
|
+
* // => { id: 'backbone', name: 'Backbone.js', confidence: 85, version: '1.4.0', ... }
|
|
2002
|
+
* ```
|
|
2185
2003
|
*/
|
|
2186
2004
|
function backboneDetector(projectPath, packageJson) {
|
|
2187
2005
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2189,23 +2007,19 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
2189
2007
|
let confidence = 0;
|
|
2190
2008
|
let version;
|
|
2191
2009
|
const deps = collectAllDependencies(pkg);
|
|
2192
|
-
// Backbone package
|
|
2193
2010
|
if (deps['backbone']) {
|
|
2194
2011
|
confidence += 70;
|
|
2195
2012
|
version = parseVersionString(deps['backbone']);
|
|
2196
2013
|
sources.push({ type: 'package.json', field: 'dependencies.backbone' });
|
|
2197
|
-
// Underscore (commonly used with Backbone)
|
|
2198
2014
|
if (deps['underscore']) {
|
|
2199
2015
|
confidence += 15;
|
|
2200
2016
|
sources.push({ type: 'package.json', field: 'dependencies.underscore' });
|
|
2201
2017
|
}
|
|
2202
|
-
// Lodash can be used as underscore replacement
|
|
2203
2018
|
if (deps['lodash']) {
|
|
2204
2019
|
confidence += 5;
|
|
2205
2020
|
sources.push({ type: 'package.json', field: 'dependencies.lodash' });
|
|
2206
2021
|
}
|
|
2207
2022
|
}
|
|
2208
|
-
// Marionette (Backbone framework)
|
|
2209
2023
|
if (deps['backbone.marionette'] || deps['marionette']) {
|
|
2210
2024
|
confidence += 10;
|
|
2211
2025
|
sources.push({ type: 'package.json', field: 'dependencies.backbone.marionette' });
|
|
@@ -2229,6 +2043,15 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
2229
2043
|
* @param projectPath - Project directory path
|
|
2230
2044
|
* @param packageJson - Optional pre-loaded package.json
|
|
2231
2045
|
* @returns Detection result or null if not detected
|
|
2046
|
+
*
|
|
2047
|
+
* @example Detecting Ember.js framework
|
|
2048
|
+
* ```typescript
|
|
2049
|
+
* const result = emberDetector('/path/to/project', {
|
|
2050
|
+
* dependencies: { 'ember-source': '^4.0.0' },
|
|
2051
|
+
* devDependencies: { 'ember-cli': '^4.0.0' },
|
|
2052
|
+
* })
|
|
2053
|
+
* // => { id: 'ember', name: 'Ember.js', confidence: 90, version: '4.0.0', ... }
|
|
2054
|
+
* ```
|
|
2232
2055
|
*/
|
|
2233
2056
|
function emberDetector(projectPath, packageJson) {
|
|
2234
2057
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2236,18 +2059,15 @@ function emberDetector(projectPath, packageJson) {
|
|
|
2236
2059
|
let confidence = 0;
|
|
2237
2060
|
let version;
|
|
2238
2061
|
const deps = collectAllDependencies(pkg);
|
|
2239
|
-
// Ember source package
|
|
2240
2062
|
if (deps['ember-source']) {
|
|
2241
2063
|
confidence += 70;
|
|
2242
2064
|
version = parseVersionString(deps['ember-source']);
|
|
2243
2065
|
sources.push({ type: 'package.json', field: 'dependencies.ember-source' });
|
|
2244
2066
|
}
|
|
2245
|
-
// Ember CLI
|
|
2246
2067
|
if (deps['ember-cli']) {
|
|
2247
2068
|
confidence += 20;
|
|
2248
2069
|
sources.push({ type: 'package.json', field: 'devDependencies.ember-cli' });
|
|
2249
2070
|
}
|
|
2250
|
-
// Ember Data
|
|
2251
2071
|
if (deps['ember-data']) {
|
|
2252
2072
|
confidence += 10;
|
|
2253
2073
|
sources.push({ type: 'package.json', field: 'dependencies.ember-data' });
|
|
@@ -2271,50 +2091,105 @@ function emberDetector(projectPath, packageJson) {
|
|
|
2271
2091
|
* @param projectPath - Project directory path
|
|
2272
2092
|
* @param packageJson - Optional pre-loaded package.json
|
|
2273
2093
|
* @returns Detection result or null if not detected
|
|
2094
|
+
*
|
|
2095
|
+
* @example Detecting jQuery library
|
|
2096
|
+
* ```typescript
|
|
2097
|
+
* const result = jqueryDetector('/path/to/project', {
|
|
2098
|
+
* dependencies: { jquery: '^3.6.0', 'jquery-ui': '^1.13.0' },
|
|
2099
|
+
* })
|
|
2100
|
+
* // => { id: 'jquery', name: 'jQuery', confidence: 90, version: '3.6.0', ... }
|
|
2101
|
+
* ```
|
|
2102
|
+
*/
|
|
2103
|
+
function jqueryDetector(projectPath, packageJson) {
|
|
2104
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2105
|
+
const sources = [];
|
|
2106
|
+
let confidence = 0;
|
|
2107
|
+
let version;
|
|
2108
|
+
const deps = collectAllDependencies(pkg);
|
|
2109
|
+
if (deps['jquery']) {
|
|
2110
|
+
confidence += 80;
|
|
2111
|
+
version = parseVersionString(deps['jquery']);
|
|
2112
|
+
sources.push({ type: 'package.json', field: 'dependencies.jquery' });
|
|
2113
|
+
}
|
|
2114
|
+
if (deps['jquery-ui']) {
|
|
2115
|
+
confidence += 10;
|
|
2116
|
+
sources.push({ type: 'package.json', field: 'dependencies.jquery-ui' });
|
|
2117
|
+
}
|
|
2118
|
+
if (deps['jquery-validation']) {
|
|
2119
|
+
confidence += 5;
|
|
2120
|
+
sources.push({ type: 'package.json', field: 'dependencies.jquery-validation' });
|
|
2121
|
+
}
|
|
2122
|
+
if (confidence === 0) {
|
|
2123
|
+
return null;
|
|
2124
|
+
}
|
|
2125
|
+
return {
|
|
2126
|
+
id: 'jquery',
|
|
2127
|
+
name: 'jQuery',
|
|
2128
|
+
category: 'legacy-frontend',
|
|
2129
|
+
version,
|
|
2130
|
+
confidence: min(confidence, 100),
|
|
2131
|
+
detectedFrom: sources,
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
/** All legacy framework detectors */
|
|
2136
|
+
const legacyDetectors = [
|
|
2137
|
+
{ id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
|
|
2138
|
+
{ id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
|
|
2139
|
+
{ id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
|
|
2140
|
+
{ id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
|
|
2141
|
+
];
|
|
2142
|
+
|
|
2143
|
+
/**
|
|
2144
|
+
* Detect Biome in project.
|
|
2145
|
+
*
|
|
2146
|
+
* @param projectPath - Project directory path
|
|
2147
|
+
* @param packageJson - Optional pre-loaded package.json
|
|
2148
|
+
* @returns Detection result or null if not detected
|
|
2149
|
+
*
|
|
2150
|
+
* @example Detecting Biome linter
|
|
2151
|
+
* ```typescript
|
|
2152
|
+
* const result = biomeDetector('/path/to/project', {
|
|
2153
|
+
* devDependencies: { '@biomejs/biome': '^1.5.0' },
|
|
2154
|
+
* })
|
|
2155
|
+
* // => { id: 'biome', name: 'Biome', confidence: 70, version: '1.5.0', ... }
|
|
2156
|
+
* ```
|
|
2274
2157
|
*/
|
|
2275
|
-
function
|
|
2158
|
+
function biomeDetector(projectPath, packageJson) {
|
|
2276
2159
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2277
2160
|
const sources = [];
|
|
2278
2161
|
let confidence = 0;
|
|
2162
|
+
let configPath;
|
|
2279
2163
|
let version;
|
|
2280
2164
|
const deps = collectAllDependencies(pkg);
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
sources.push({ type: 'package.json', field: 'dependencies.jquery' });
|
|
2165
|
+
if (deps['@biomejs/biome']) {
|
|
2166
|
+
confidence += 70;
|
|
2167
|
+
version = parseVersionString(deps['@biomejs/biome']);
|
|
2168
|
+
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2286
2169
|
}
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
sources.push({ type: '
|
|
2170
|
+
if (exists(join$1(projectPath, 'biome.json'))) {
|
|
2171
|
+
confidence += 30;
|
|
2172
|
+
configPath = 'biome.json';
|
|
2173
|
+
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2291
2174
|
}
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
sources.push({ type: '
|
|
2175
|
+
if (!configPath && exists(join$1(projectPath, 'biome.jsonc'))) {
|
|
2176
|
+
confidence += 30;
|
|
2177
|
+
configPath = 'biome.jsonc';
|
|
2178
|
+
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
2296
2179
|
}
|
|
2297
2180
|
if (confidence === 0) {
|
|
2298
2181
|
return null;
|
|
2299
2182
|
}
|
|
2300
2183
|
return {
|
|
2301
|
-
id: '
|
|
2302
|
-
name: '
|
|
2303
|
-
category: 'legacy-frontend',
|
|
2184
|
+
id: 'biome',
|
|
2185
|
+
name: 'Biome',
|
|
2304
2186
|
version,
|
|
2187
|
+
configPath,
|
|
2305
2188
|
confidence: min(confidence, 100),
|
|
2306
2189
|
detectedFrom: sources,
|
|
2307
2190
|
};
|
|
2308
2191
|
}
|
|
2309
2192
|
|
|
2310
|
-
/** All legacy framework detectors */
|
|
2311
|
-
const legacyDetectors = [
|
|
2312
|
-
{ id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
|
|
2313
|
-
{ id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
|
|
2314
|
-
{ id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
|
|
2315
|
-
{ id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
|
|
2316
|
-
];
|
|
2317
|
-
|
|
2318
2193
|
/** Config patterns for ESLint */
|
|
2319
2194
|
const ESLINT_CONFIG_PATTERNS = [
|
|
2320
2195
|
'eslint.config.js',
|
|
@@ -2334,6 +2209,15 @@ const ESLINT_CONFIG_PATTERNS = [
|
|
|
2334
2209
|
* @param projectPath - Project directory path
|
|
2335
2210
|
* @param packageJson - Optional pre-loaded package.json
|
|
2336
2211
|
* @returns Detection result or null if not detected
|
|
2212
|
+
*
|
|
2213
|
+
* @example Detecting ESLint linter
|
|
2214
|
+
* ```typescript
|
|
2215
|
+
* const result = eslintDetector('/path/to/project', {
|
|
2216
|
+
* devDependencies: { eslint: '^8.50.0', '@typescript-eslint/parser': '^6.0.0' },
|
|
2217
|
+
* scripts: { lint: 'eslint src/' },
|
|
2218
|
+
* })
|
|
2219
|
+
* // => { id: 'eslint', name: 'ESLint', confidence: 65, version: '8.50.0', ... }
|
|
2220
|
+
* ```
|
|
2337
2221
|
*/
|
|
2338
2222
|
function eslintDetector(projectPath, packageJson) {
|
|
2339
2223
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2397,6 +2281,15 @@ const PRETTIER_CONFIG_PATTERNS = [
|
|
|
2397
2281
|
* @param projectPath - Project directory path
|
|
2398
2282
|
* @param packageJson - Optional pre-loaded package.json
|
|
2399
2283
|
* @returns Detection result or null if not detected
|
|
2284
|
+
*
|
|
2285
|
+
* @example Detecting Prettier formatter
|
|
2286
|
+
* ```typescript
|
|
2287
|
+
* const result = prettierDetector('/path/to/project', {
|
|
2288
|
+
* devDependencies: { prettier: '^3.0.0' },
|
|
2289
|
+
* scripts: { format: 'prettier --write .' },
|
|
2290
|
+
* })
|
|
2291
|
+
* // => { id: 'prettier', name: 'Prettier', confidence: 55, version: '3.0.0', ... }
|
|
2292
|
+
* ```
|
|
2400
2293
|
*/
|
|
2401
2294
|
function prettierDetector(projectPath, packageJson) {
|
|
2402
2295
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2418,7 +2311,6 @@ function prettierDetector(projectPath, packageJson) {
|
|
|
2418
2311
|
confidence += 30;
|
|
2419
2312
|
sources.push({ type: 'package.json', field: 'prettier' });
|
|
2420
2313
|
}
|
|
2421
|
-
// .prettierignore file
|
|
2422
2314
|
if (exists(join$1(projectPath, '.prettierignore'))) {
|
|
2423
2315
|
confidence += 10;
|
|
2424
2316
|
sources.push({ type: 'config-file', path: '.prettierignore' });
|
|
@@ -2460,6 +2352,14 @@ const STYLELINT_CONFIG_PATTERNS = [
|
|
|
2460
2352
|
* @param projectPath - Project directory path
|
|
2461
2353
|
* @param packageJson - Optional pre-loaded package.json
|
|
2462
2354
|
* @returns Detection result or null if not detected
|
|
2355
|
+
*
|
|
2356
|
+
* @example Detecting Stylelint linter
|
|
2357
|
+
* ```typescript
|
|
2358
|
+
* const result = stylelintDetector('/path/to/project', {
|
|
2359
|
+
* devDependencies: { stylelint: '^15.0.0', 'stylelint-config-standard': '^30.0.0' },
|
|
2360
|
+
* })
|
|
2361
|
+
* // => { id: 'stylelint', name: 'Stylelint', confidence: 65, version: '15.0.0', ... }
|
|
2362
|
+
* ```
|
|
2463
2363
|
*/
|
|
2464
2364
|
function stylelintDetector(projectPath, packageJson) {
|
|
2465
2365
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2499,49 +2399,6 @@ function stylelintDetector(projectPath, packageJson) {
|
|
|
2499
2399
|
};
|
|
2500
2400
|
}
|
|
2501
2401
|
|
|
2502
|
-
/**
|
|
2503
|
-
* Detect Biome in project.
|
|
2504
|
-
*
|
|
2505
|
-
* @param projectPath - Project directory path
|
|
2506
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2507
|
-
* @returns Detection result or null if not detected
|
|
2508
|
-
*/
|
|
2509
|
-
function biomeDetector(projectPath, packageJson) {
|
|
2510
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2511
|
-
const sources = [];
|
|
2512
|
-
let confidence = 0;
|
|
2513
|
-
let configPath;
|
|
2514
|
-
let version;
|
|
2515
|
-
const deps = collectAllDependencies(pkg);
|
|
2516
|
-
// @biomejs/biome package
|
|
2517
|
-
if (deps['@biomejs/biome']) {
|
|
2518
|
-
confidence += 70;
|
|
2519
|
-
version = parseVersionString(deps['@biomejs/biome']);
|
|
2520
|
-
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2521
|
-
}
|
|
2522
|
-
if (exists(join$1(projectPath, 'biome.json'))) {
|
|
2523
|
-
confidence += 30;
|
|
2524
|
-
configPath = 'biome.json';
|
|
2525
|
-
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2526
|
-
}
|
|
2527
|
-
if (!configPath && exists(join$1(projectPath, 'biome.jsonc'))) {
|
|
2528
|
-
confidence += 30;
|
|
2529
|
-
configPath = 'biome.jsonc';
|
|
2530
|
-
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
2531
|
-
}
|
|
2532
|
-
if (confidence === 0) {
|
|
2533
|
-
return null;
|
|
2534
|
-
}
|
|
2535
|
-
return {
|
|
2536
|
-
id: 'biome',
|
|
2537
|
-
name: 'Biome',
|
|
2538
|
-
version,
|
|
2539
|
-
configPath,
|
|
2540
|
-
confidence: min(confidence, 100),
|
|
2541
|
-
detectedFrom: sources,
|
|
2542
|
-
};
|
|
2543
|
-
}
|
|
2544
|
-
|
|
2545
2402
|
/** All linting tool detectors */
|
|
2546
2403
|
const lintingDetectors = [
|
|
2547
2404
|
{ id: 'eslint', name: 'ESLint', detect: eslintDetector },
|
|
@@ -2551,140 +2408,179 @@ const lintingDetectors = [
|
|
|
2551
2408
|
];
|
|
2552
2409
|
|
|
2553
2410
|
/**
|
|
2554
|
-
* Detect
|
|
2411
|
+
* Detect Lerna in project.
|
|
2555
2412
|
*
|
|
2556
2413
|
* @param workspacePath - Workspace directory path
|
|
2557
2414
|
* @param packageJson - Optional pre-loaded package.json
|
|
2558
2415
|
* @returns Detection result or null if not detected
|
|
2416
|
+
*
|
|
2417
|
+
* @example Detecting Lerna monorepo
|
|
2418
|
+
* ```typescript
|
|
2419
|
+
* // Project with lerna.json config file
|
|
2420
|
+
* const result = lernaDetector('/path/to/lerna-project')
|
|
2421
|
+
* // => {
|
|
2422
|
+
* // id: 'lerna',
|
|
2423
|
+
* // name: 'Lerna',
|
|
2424
|
+
* // confidence: 80,
|
|
2425
|
+
* // configPath: 'lerna.json',
|
|
2426
|
+
* // detectedFrom: [{ type: 'config-file', path: 'lerna.json' }]
|
|
2427
|
+
* // }
|
|
2428
|
+
* ```
|
|
2559
2429
|
*/
|
|
2560
|
-
function
|
|
2430
|
+
function lernaDetector(workspacePath, packageJson) {
|
|
2561
2431
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2562
2432
|
const sources = [];
|
|
2563
2433
|
let confidence = 0;
|
|
2564
2434
|
let version;
|
|
2565
|
-
let
|
|
2566
|
-
const
|
|
2567
|
-
if (exists(
|
|
2568
|
-
confidence +=
|
|
2569
|
-
|
|
2435
|
+
let configPath;
|
|
2436
|
+
const lernaJsonPath = join$1(workspacePath, 'lerna.json');
|
|
2437
|
+
if (exists(lernaJsonPath)) {
|
|
2438
|
+
confidence += 80;
|
|
2439
|
+
configPath = 'lerna.json';
|
|
2440
|
+
sources.push({ type: 'config-file', path: 'lerna.json' });
|
|
2570
2441
|
}
|
|
2571
2442
|
const deps = collectAllDependencies(pkg);
|
|
2572
|
-
if (deps['
|
|
2573
|
-
confidence +=
|
|
2574
|
-
version = parseVersionString(deps['
|
|
2575
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2576
|
-
}
|
|
2577
|
-
const hasApps = exists(join$1(workspacePath, 'apps'));
|
|
2578
|
-
const hasLibs = exists(join$1(workspacePath, 'libs'));
|
|
2579
|
-
if (hasApps || hasLibs) {
|
|
2580
|
-
confidence += 10;
|
|
2581
|
-
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
2582
|
-
workspaceLayout = {
|
|
2583
|
-
appsDir: hasApps ? 'apps' : '',
|
|
2584
|
-
libsDir: hasLibs ? 'libs' : '',
|
|
2585
|
-
};
|
|
2443
|
+
if (deps['lerna']) {
|
|
2444
|
+
confidence += 15;
|
|
2445
|
+
version = parseVersionString(deps['lerna']);
|
|
2446
|
+
sources.push({ type: 'package.json', field: 'dependencies.lerna' });
|
|
2586
2447
|
}
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
sources.push({ type: 'package.json', field: '@nx/* packages' });
|
|
2448
|
+
if (exists(join$1(workspacePath, 'packages'))) {
|
|
2449
|
+
confidence += 5;
|
|
2450
|
+
sources.push({ type: 'directory', path: 'packages/' });
|
|
2591
2451
|
}
|
|
2592
2452
|
if (confidence === 0) {
|
|
2593
2453
|
return null;
|
|
2594
2454
|
}
|
|
2595
2455
|
return {
|
|
2596
|
-
id: '
|
|
2597
|
-
name: '
|
|
2456
|
+
id: 'lerna',
|
|
2457
|
+
name: 'Lerna',
|
|
2598
2458
|
version,
|
|
2599
|
-
configPath
|
|
2459
|
+
configPath,
|
|
2600
2460
|
confidence: min(confidence, 100),
|
|
2601
2461
|
detectedFrom: sources,
|
|
2602
|
-
workspaceLayout,
|
|
2603
2462
|
};
|
|
2604
2463
|
}
|
|
2605
2464
|
|
|
2606
2465
|
/**
|
|
2607
|
-
* Detect
|
|
2466
|
+
* Detect npm workspaces in project.
|
|
2608
2467
|
*
|
|
2609
2468
|
* @param workspacePath - Workspace directory path
|
|
2610
2469
|
* @param packageJson - Optional pre-loaded package.json
|
|
2611
2470
|
* @returns Detection result or null if not detected
|
|
2471
|
+
*
|
|
2472
|
+
* @example Detecting npm workspaces
|
|
2473
|
+
* ```typescript
|
|
2474
|
+
* // Project with workspaces in package.json and package-lock.json
|
|
2475
|
+
* const result = npmWorkspacesDetector('/path/to/npm-project')
|
|
2476
|
+
* // => {
|
|
2477
|
+
* // id: 'npm-workspaces',
|
|
2478
|
+
* // name: 'npm Workspaces',
|
|
2479
|
+
* // confidence: 90,
|
|
2480
|
+
* // configPath: 'package.json',
|
|
2481
|
+
* // detectedFrom: [
|
|
2482
|
+
* // { type: 'package.json', field: 'workspaces' },
|
|
2483
|
+
* // { type: 'lockfile', path: 'package-lock.json' }
|
|
2484
|
+
* // ]
|
|
2485
|
+
* // }
|
|
2486
|
+
* ```
|
|
2612
2487
|
*/
|
|
2613
|
-
function
|
|
2488
|
+
function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
2614
2489
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2615
2490
|
const sources = [];
|
|
2616
2491
|
let confidence = 0;
|
|
2617
|
-
|
|
2618
|
-
let configPath;
|
|
2619
|
-
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
2620
|
-
if (exists(turboJsonPath)) {
|
|
2492
|
+
if (pkg?.workspaces) {
|
|
2621
2493
|
confidence += 80;
|
|
2622
|
-
|
|
2623
|
-
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2494
|
+
sources.push({ type: 'package.json', field: 'workspaces' });
|
|
2624
2495
|
}
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
version = parseVersionString(deps['turbo']);
|
|
2629
|
-
sources.push({ type: 'package.json', field: 'dependencies.turbo' });
|
|
2496
|
+
if (exists(join$1(workspacePath, 'package-lock.json'))) {
|
|
2497
|
+
confidence += 10;
|
|
2498
|
+
sources.push({ type: 'lockfile', path: 'package-lock.json' });
|
|
2630
2499
|
}
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
confidence += 5;
|
|
2634
|
-
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
2500
|
+
if (exists(join$1(workspacePath, 'yarn.lock'))) {
|
|
2501
|
+
return null;
|
|
2635
2502
|
}
|
|
2636
2503
|
if (confidence === 0) {
|
|
2637
2504
|
return null;
|
|
2638
2505
|
}
|
|
2639
2506
|
return {
|
|
2640
|
-
id: '
|
|
2641
|
-
name: '
|
|
2642
|
-
|
|
2643
|
-
configPath,
|
|
2507
|
+
id: 'npm-workspaces',
|
|
2508
|
+
name: 'npm Workspaces',
|
|
2509
|
+
configPath: 'package.json',
|
|
2644
2510
|
confidence: min(confidence, 100),
|
|
2645
2511
|
detectedFrom: sources,
|
|
2646
2512
|
};
|
|
2647
2513
|
}
|
|
2648
2514
|
|
|
2649
2515
|
/**
|
|
2650
|
-
* Detect
|
|
2516
|
+
* Detect NX in project.
|
|
2651
2517
|
*
|
|
2652
2518
|
* @param workspacePath - Workspace directory path
|
|
2653
2519
|
* @param packageJson - Optional pre-loaded package.json
|
|
2654
2520
|
* @returns Detection result or null if not detected
|
|
2521
|
+
*
|
|
2522
|
+
* @example Detecting NX workspace
|
|
2523
|
+
* ```typescript
|
|
2524
|
+
* // Project with nx.json and apps/libs directories
|
|
2525
|
+
* const result = nxDetector('/path/to/nx-workspace')
|
|
2526
|
+
* // => {
|
|
2527
|
+
* // id: 'nx',
|
|
2528
|
+
* // name: 'NX',
|
|
2529
|
+
* // confidence: 100,
|
|
2530
|
+
* // configPath: 'nx.json',
|
|
2531
|
+
* // version: '17.0.0',
|
|
2532
|
+
* // workspaceLayout: { appsDir: 'apps', libsDir: 'libs' },
|
|
2533
|
+
* // detectedFrom: [
|
|
2534
|
+
* // { type: 'config-file', path: 'nx.json' },
|
|
2535
|
+
* // { type: 'package.json', field: 'dependencies.nx' },
|
|
2536
|
+
* // { type: 'directory', path: 'apps/ or libs/' }
|
|
2537
|
+
* // ]
|
|
2538
|
+
* // }
|
|
2539
|
+
* ```
|
|
2655
2540
|
*/
|
|
2656
|
-
function
|
|
2541
|
+
function nxDetector(workspacePath, packageJson) {
|
|
2657
2542
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2658
2543
|
const sources = [];
|
|
2659
2544
|
let confidence = 0;
|
|
2660
2545
|
let version;
|
|
2661
|
-
let
|
|
2662
|
-
const
|
|
2663
|
-
if (exists(
|
|
2664
|
-
confidence +=
|
|
2665
|
-
|
|
2666
|
-
sources.push({ type: 'config-file', path: 'lerna.json' });
|
|
2546
|
+
let workspaceLayout;
|
|
2547
|
+
const nxJsonPath = join$1(workspacePath, 'nx.json');
|
|
2548
|
+
if (exists(nxJsonPath)) {
|
|
2549
|
+
confidence += 70;
|
|
2550
|
+
sources.push({ type: 'config-file', path: 'nx.json' });
|
|
2667
2551
|
}
|
|
2668
2552
|
const deps = collectAllDependencies(pkg);
|
|
2669
|
-
if (deps['
|
|
2670
|
-
confidence +=
|
|
2671
|
-
version = parseVersionString(deps['
|
|
2672
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2553
|
+
if (deps['nx']) {
|
|
2554
|
+
confidence += 20;
|
|
2555
|
+
version = parseVersionString(deps['nx']);
|
|
2556
|
+
sources.push({ type: 'package.json', field: 'dependencies.nx' });
|
|
2673
2557
|
}
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2558
|
+
const hasApps = exists(join$1(workspacePath, 'apps'));
|
|
2559
|
+
const hasLibs = exists(join$1(workspacePath, 'libs'));
|
|
2560
|
+
if (hasApps || hasLibs) {
|
|
2561
|
+
confidence += 10;
|
|
2562
|
+
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
2563
|
+
workspaceLayout = {
|
|
2564
|
+
appsDir: hasApps ? 'apps' : '',
|
|
2565
|
+
libsDir: hasLibs ? 'libs' : '',
|
|
2566
|
+
};
|
|
2567
|
+
}
|
|
2568
|
+
const nxPackages = keys(deps).filter((d) => d.startsWith('@nx/') || d.startsWith('@nrwl/'));
|
|
2569
|
+
if (nxPackages.length > 0) {
|
|
2570
|
+
confidence += 10;
|
|
2571
|
+
sources.push({ type: 'package.json', field: '@nx/* packages' });
|
|
2677
2572
|
}
|
|
2678
2573
|
if (confidence === 0) {
|
|
2679
2574
|
return null;
|
|
2680
2575
|
}
|
|
2681
2576
|
return {
|
|
2682
|
-
id: '
|
|
2683
|
-
name: '
|
|
2577
|
+
id: 'nx',
|
|
2578
|
+
name: 'NX',
|
|
2684
2579
|
version,
|
|
2685
|
-
configPath,
|
|
2580
|
+
configPath: exists(nxJsonPath) ? 'nx.json' : undefined,
|
|
2686
2581
|
confidence: min(confidence, 100),
|
|
2687
2582
|
detectedFrom: sources,
|
|
2583
|
+
workspaceLayout,
|
|
2688
2584
|
};
|
|
2689
2585
|
}
|
|
2690
2586
|
|
|
@@ -2694,6 +2590,19 @@ function lernaDetector(workspacePath, packageJson) {
|
|
|
2694
2590
|
* @param workspacePath - Workspace directory path
|
|
2695
2591
|
* @param packageJson - Optional pre-loaded package.json
|
|
2696
2592
|
* @returns Detection result or null if not detected
|
|
2593
|
+
*
|
|
2594
|
+
* @example Detecting Rush monorepo
|
|
2595
|
+
* ```typescript
|
|
2596
|
+
* // Project with rush.json config file
|
|
2597
|
+
* const result = rushDetector('/path/to/rush-project')
|
|
2598
|
+
* // => {
|
|
2599
|
+
* // id: 'rush',
|
|
2600
|
+
* // name: 'Rush',
|
|
2601
|
+
* // confidence: 90,
|
|
2602
|
+
* // configPath: 'rush.json',
|
|
2603
|
+
* // detectedFrom: [{ type: 'config-file', path: 'rush.json' }]
|
|
2604
|
+
* // }
|
|
2605
|
+
* ```
|
|
2697
2606
|
*/
|
|
2698
2607
|
function rushDetector(workspacePath, packageJson) {
|
|
2699
2608
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2722,40 +2631,8 @@ function rushDetector(workspacePath, packageJson) {
|
|
|
2722
2631
|
}
|
|
2723
2632
|
return {
|
|
2724
2633
|
id: 'rush',
|
|
2725
|
-
name: 'Rush',
|
|
2726
|
-
version,
|
|
2727
|
-
configPath,
|
|
2728
|
-
confidence: min(confidence, 100),
|
|
2729
|
-
detectedFrom: sources,
|
|
2730
|
-
};
|
|
2731
|
-
}
|
|
2732
|
-
|
|
2733
|
-
/**
|
|
2734
|
-
* Detect pnpm workspaces in project.
|
|
2735
|
-
*
|
|
2736
|
-
* @param workspacePath - Workspace directory path
|
|
2737
|
-
* @returns Detection result or null if not detected
|
|
2738
|
-
*/
|
|
2739
|
-
function pnpmWorkspacesDetector(workspacePath) {
|
|
2740
|
-
const sources = [];
|
|
2741
|
-
let confidence = 0;
|
|
2742
|
-
let configPath;
|
|
2743
|
-
const pnpmWorkspacePath = join$1(workspacePath, 'pnpm-workspace.yaml');
|
|
2744
|
-
if (exists(pnpmWorkspacePath)) {
|
|
2745
|
-
confidence += 90;
|
|
2746
|
-
configPath = 'pnpm-workspace.yaml';
|
|
2747
|
-
sources.push({ type: 'config-file', path: 'pnpm-workspace.yaml' });
|
|
2748
|
-
}
|
|
2749
|
-
if (exists(join$1(workspacePath, 'pnpm-lock.yaml'))) {
|
|
2750
|
-
confidence += 10;
|
|
2751
|
-
sources.push({ type: 'lockfile', path: 'pnpm-lock.yaml' });
|
|
2752
|
-
}
|
|
2753
|
-
if (confidence === 0) {
|
|
2754
|
-
return null;
|
|
2755
|
-
}
|
|
2756
|
-
return {
|
|
2757
|
-
id: 'pnpm-workspaces',
|
|
2758
|
-
name: 'pnpm Workspaces',
|
|
2634
|
+
name: 'Rush',
|
|
2635
|
+
version,
|
|
2759
2636
|
configPath,
|
|
2760
2637
|
confidence: min(confidence, 100),
|
|
2761
2638
|
detectedFrom: sources,
|
|
@@ -2763,34 +2640,60 @@ function pnpmWorkspacesDetector(workspacePath) {
|
|
|
2763
2640
|
}
|
|
2764
2641
|
|
|
2765
2642
|
/**
|
|
2766
|
-
* Detect
|
|
2643
|
+
* Detect Turborepo in project.
|
|
2767
2644
|
*
|
|
2768
2645
|
* @param workspacePath - Workspace directory path
|
|
2769
2646
|
* @param packageJson - Optional pre-loaded package.json
|
|
2770
2647
|
* @returns Detection result or null if not detected
|
|
2648
|
+
*
|
|
2649
|
+
* @example Detecting Turborepo monorepo
|
|
2650
|
+
* ```typescript
|
|
2651
|
+
* // Project with turbo.json and turbo dependency
|
|
2652
|
+
* const result = turborepoDetector('/path/to/turbo-project')
|
|
2653
|
+
* // => {
|
|
2654
|
+
* // id: 'turborepo',
|
|
2655
|
+
* // name: 'Turborepo',
|
|
2656
|
+
* // confidence: 95,
|
|
2657
|
+
* // configPath: 'turbo.json',
|
|
2658
|
+
* // version: '2.0.0',
|
|
2659
|
+
* // detectedFrom: [
|
|
2660
|
+
* // { type: 'config-file', path: 'turbo.json' },
|
|
2661
|
+
* // { type: 'package.json', field: 'dependencies.turbo' }
|
|
2662
|
+
* // ]
|
|
2663
|
+
* // }
|
|
2664
|
+
* ```
|
|
2771
2665
|
*/
|
|
2772
|
-
function
|
|
2666
|
+
function turborepoDetector(workspacePath, packageJson) {
|
|
2773
2667
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2774
2668
|
const sources = [];
|
|
2775
2669
|
let confidence = 0;
|
|
2776
|
-
|
|
2670
|
+
let version;
|
|
2671
|
+
let configPath;
|
|
2672
|
+
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
2673
|
+
if (exists(turboJsonPath)) {
|
|
2777
2674
|
confidence += 80;
|
|
2778
|
-
|
|
2675
|
+
configPath = 'turbo.json';
|
|
2676
|
+
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2779
2677
|
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2678
|
+
const deps = collectAllDependencies(pkg);
|
|
2679
|
+
if (deps['turbo']) {
|
|
2680
|
+
confidence += 15;
|
|
2681
|
+
version = parseVersionString(deps['turbo']);
|
|
2682
|
+
sources.push({ type: 'package.json', field: 'dependencies.turbo' });
|
|
2783
2683
|
}
|
|
2784
|
-
|
|
2785
|
-
|
|
2684
|
+
const scripts = pkg?.scripts ?? {};
|
|
2685
|
+
if (values(scripts).some((s) => s?.includes('turbo'))) {
|
|
2686
|
+
confidence += 5;
|
|
2687
|
+
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
2786
2688
|
}
|
|
2787
2689
|
if (confidence === 0) {
|
|
2788
2690
|
return null;
|
|
2789
2691
|
}
|
|
2790
2692
|
return {
|
|
2791
|
-
id: '
|
|
2792
|
-
name: '
|
|
2793
|
-
|
|
2693
|
+
id: 'turborepo',
|
|
2694
|
+
name: 'Turborepo',
|
|
2695
|
+
version,
|
|
2696
|
+
configPath,
|
|
2794
2697
|
confidence: min(confidence, 100),
|
|
2795
2698
|
detectedFrom: sources,
|
|
2796
2699
|
};
|
|
@@ -2802,6 +2705,23 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
|
2802
2705
|
* @param workspacePath - Workspace directory path
|
|
2803
2706
|
* @param packageJson - Optional pre-loaded package.json
|
|
2804
2707
|
* @returns Detection result or null if not detected
|
|
2708
|
+
*
|
|
2709
|
+
* @example Detecting yarn workspaces
|
|
2710
|
+
* ```typescript
|
|
2711
|
+
* // Project with workspaces in package.json and yarn.lock
|
|
2712
|
+
* const result = yarnWorkspacesDetector('/path/to/yarn-project')
|
|
2713
|
+
* // => {
|
|
2714
|
+
* // id: 'yarn-workspaces',
|
|
2715
|
+
* // name: 'Yarn Workspaces',
|
|
2716
|
+
* // confidence: 100,
|
|
2717
|
+
* // configPath: 'package.json',
|
|
2718
|
+
* // detectedFrom: [
|
|
2719
|
+
* // { type: 'package.json', field: 'workspaces' },
|
|
2720
|
+
* // { type: 'lockfile', path: 'yarn.lock' },
|
|
2721
|
+
* // { type: 'config-file', path: '.yarnrc.yml' }
|
|
2722
|
+
* // ]
|
|
2723
|
+
* // }
|
|
2724
|
+
* ```
|
|
2805
2725
|
*/
|
|
2806
2726
|
function yarnWorkspacesDetector(workspacePath, packageJson) {
|
|
2807
2727
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2842,55 +2762,58 @@ const monorepoDetectors = [
|
|
|
2842
2762
|
{ id: 'yarn-workspaces', name: 'Yarn Workspaces', detect: yarnWorkspacesDetector },
|
|
2843
2763
|
];
|
|
2844
2764
|
|
|
2845
|
-
/** Config patterns for
|
|
2846
|
-
const
|
|
2765
|
+
/** Config patterns for Cypress */
|
|
2766
|
+
const CYPRESS_CONFIG_PATTERNS = ['cypress.config.js', 'cypress.config.ts', 'cypress.config.mjs', 'cypress.json'];
|
|
2847
2767
|
/**
|
|
2848
|
-
* Detect
|
|
2768
|
+
* Detect Cypress in project.
|
|
2849
2769
|
*
|
|
2850
2770
|
* @param projectPath - Project directory path
|
|
2851
2771
|
* @param packageJson - Optional pre-loaded package.json
|
|
2852
2772
|
* @returns Detection result or null if not detected
|
|
2773
|
+
*
|
|
2774
|
+
* @example Detecting Cypress testing framework
|
|
2775
|
+
* ```typescript
|
|
2776
|
+
* import { cypressDetector } from '@hyperfrontend/project-scope'
|
|
2777
|
+
*
|
|
2778
|
+
* const result = cypressDetector('./my-project')
|
|
2779
|
+
* if (result) {
|
|
2780
|
+
* console.log(`Cypress ${result.version} detected (${result.confidence}% confidence)`)
|
|
2781
|
+
* // => "Cypress 13.6.0 detected (95% confidence)"
|
|
2782
|
+
* }
|
|
2783
|
+
* ```
|
|
2853
2784
|
*/
|
|
2854
|
-
function
|
|
2785
|
+
function cypressDetector(projectPath, packageJson) {
|
|
2855
2786
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2856
2787
|
const sources = [];
|
|
2857
2788
|
let confidence = 0;
|
|
2858
2789
|
let version;
|
|
2859
2790
|
const deps = collectAllDependencies(pkg);
|
|
2860
|
-
if (deps['
|
|
2791
|
+
if (deps['cypress']) {
|
|
2861
2792
|
confidence += 60;
|
|
2862
|
-
version = parseVersionString(deps['
|
|
2863
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2793
|
+
version = parseVersionString(deps['cypress']);
|
|
2794
|
+
sources.push({ type: 'package.json', field: 'dependencies.cypress' });
|
|
2864
2795
|
}
|
|
2865
|
-
const configPath = locateConfigFile(projectPath,
|
|
2796
|
+
const configPath = locateConfigFile(projectPath, CYPRESS_CONFIG_PATTERNS);
|
|
2866
2797
|
if (configPath) {
|
|
2867
2798
|
confidence += 30;
|
|
2868
2799
|
sources.push({ type: 'config-file', path: configPath });
|
|
2869
2800
|
}
|
|
2870
|
-
if (
|
|
2871
|
-
confidence += 20;
|
|
2872
|
-
sources.push({ type: 'package.json', field: 'jest' });
|
|
2873
|
-
}
|
|
2874
|
-
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
2875
|
-
if (testScript.includes('jest')) {
|
|
2801
|
+
if (exists(join$1(projectPath, 'cypress'))) {
|
|
2876
2802
|
confidence += 10;
|
|
2877
|
-
sources.push({ type: '
|
|
2878
|
-
}
|
|
2879
|
-
if (deps['@types/jest']) {
|
|
2880
|
-
confidence += 5;
|
|
2881
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
2803
|
+
sources.push({ type: 'directory', path: 'cypress/' });
|
|
2882
2804
|
}
|
|
2883
|
-
|
|
2805
|
+
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
2806
|
+
if (e2eScript.includes('cypress')) {
|
|
2884
2807
|
confidence += 5;
|
|
2885
|
-
sources.push({ type: 'package.json', field: '
|
|
2808
|
+
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
2886
2809
|
}
|
|
2887
2810
|
if (confidence === 0) {
|
|
2888
2811
|
return null;
|
|
2889
2812
|
}
|
|
2890
2813
|
return {
|
|
2891
|
-
id: '
|
|
2892
|
-
name: '
|
|
2893
|
-
type: '
|
|
2814
|
+
id: 'cypress',
|
|
2815
|
+
name: 'Cypress',
|
|
2816
|
+
type: 'e2e',
|
|
2894
2817
|
version,
|
|
2895
2818
|
configPath,
|
|
2896
2819
|
confidence: min(confidence, 100),
|
|
@@ -2898,51 +2821,66 @@ function jestDetector(projectPath, packageJson) {
|
|
|
2898
2821
|
};
|
|
2899
2822
|
}
|
|
2900
2823
|
|
|
2901
|
-
/** Config patterns for
|
|
2902
|
-
const
|
|
2824
|
+
/** Config patterns for Jest */
|
|
2825
|
+
const JEST_CONFIG_PATTERNS = ['jest.config.js', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json'];
|
|
2903
2826
|
/**
|
|
2904
|
-
* Detect
|
|
2827
|
+
* Detect Jest in project.
|
|
2905
2828
|
*
|
|
2906
2829
|
* @param projectPath - Project directory path
|
|
2907
2830
|
* @param packageJson - Optional pre-loaded package.json
|
|
2908
2831
|
* @returns Detection result or null if not detected
|
|
2832
|
+
*
|
|
2833
|
+
* @example Detecting Jest testing framework
|
|
2834
|
+
* ```typescript
|
|
2835
|
+
* import { jestDetector } from '@hyperfrontend/project-scope'
|
|
2836
|
+
*
|
|
2837
|
+
* const result = jestDetector('./my-project')
|
|
2838
|
+
* if (result) {
|
|
2839
|
+
* console.log(`Jest ${result.version} detected`)
|
|
2840
|
+
* console.log('Sources:', result.detectedFrom.map(s => s.type))
|
|
2841
|
+
* // => "Sources: ['package.json', 'config-file']"
|
|
2842
|
+
* }
|
|
2843
|
+
* ```
|
|
2909
2844
|
*/
|
|
2910
|
-
function
|
|
2845
|
+
function jestDetector(projectPath, packageJson) {
|
|
2911
2846
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2912
2847
|
const sources = [];
|
|
2913
2848
|
let confidence = 0;
|
|
2914
2849
|
let version;
|
|
2915
2850
|
const deps = collectAllDependencies(pkg);
|
|
2916
|
-
if (deps['
|
|
2917
|
-
confidence +=
|
|
2918
|
-
version = parseVersionString(deps['
|
|
2919
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2851
|
+
if (deps['jest']) {
|
|
2852
|
+
confidence += 60;
|
|
2853
|
+
version = parseVersionString(deps['jest']);
|
|
2854
|
+
sources.push({ type: 'package.json', field: 'dependencies.jest' });
|
|
2920
2855
|
}
|
|
2921
|
-
const configPath = locateConfigFile(projectPath,
|
|
2856
|
+
const configPath = locateConfigFile(projectPath, JEST_CONFIG_PATTERNS);
|
|
2922
2857
|
if (configPath) {
|
|
2923
|
-
confidence +=
|
|
2858
|
+
confidence += 30;
|
|
2924
2859
|
sources.push({ type: 'config-file', path: configPath });
|
|
2925
2860
|
}
|
|
2926
|
-
if (
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
exists(join$1(projectPath, 'vite.config.mjs'));
|
|
2930
|
-
if (viteConfig && deps['vitest']) {
|
|
2931
|
-
confidence += 5;
|
|
2932
|
-
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
2933
|
-
}
|
|
2861
|
+
if (pkg && 'jest' in pkg) {
|
|
2862
|
+
confidence += 20;
|
|
2863
|
+
sources.push({ type: 'package.json', field: 'jest' });
|
|
2934
2864
|
}
|
|
2935
2865
|
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
2936
|
-
if (testScript.includes('
|
|
2866
|
+
if (testScript.includes('jest')) {
|
|
2937
2867
|
confidence += 10;
|
|
2938
2868
|
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
2939
2869
|
}
|
|
2870
|
+
if (deps['@types/jest']) {
|
|
2871
|
+
confidence += 5;
|
|
2872
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
2873
|
+
}
|
|
2874
|
+
if (deps['ts-jest']) {
|
|
2875
|
+
confidence += 5;
|
|
2876
|
+
sources.push({ type: 'package.json', field: 'dependencies.ts-jest' });
|
|
2877
|
+
}
|
|
2940
2878
|
if (confidence === 0) {
|
|
2941
2879
|
return null;
|
|
2942
2880
|
}
|
|
2943
2881
|
return {
|
|
2944
|
-
id: '
|
|
2945
|
-
name: '
|
|
2882
|
+
id: 'jest',
|
|
2883
|
+
name: 'Jest',
|
|
2946
2884
|
type: 'unit',
|
|
2947
2885
|
version,
|
|
2948
2886
|
configPath,
|
|
@@ -2959,6 +2897,17 @@ const MOCHA_CONFIG_PATTERNS = ['.mocharc.js', '.mocharc.json', '.mocharc.yaml',
|
|
|
2959
2897
|
* @param projectPath - Project directory path
|
|
2960
2898
|
* @param packageJson - Optional pre-loaded package.json
|
|
2961
2899
|
* @returns Detection result or null if not detected
|
|
2900
|
+
*
|
|
2901
|
+
* @example Detecting Mocha testing framework
|
|
2902
|
+
* ```typescript
|
|
2903
|
+
* import { mochaDetector } from '@hyperfrontend/project-scope'
|
|
2904
|
+
*
|
|
2905
|
+
* const result = mochaDetector('./my-project')
|
|
2906
|
+
* if (result) {
|
|
2907
|
+
* console.log(`Mocha ${result.version} detected (${result.confidence}%)`)
|
|
2908
|
+
* // => "Mocha 10.2.0 detected (95%)"
|
|
2909
|
+
* }
|
|
2910
|
+
* ```
|
|
2962
2911
|
*/
|
|
2963
2912
|
function mochaDetector(projectPath, packageJson) {
|
|
2964
2913
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3003,37 +2952,53 @@ function mochaDetector(projectPath, packageJson) {
|
|
|
3003
2952
|
};
|
|
3004
2953
|
}
|
|
3005
2954
|
|
|
3006
|
-
/** Config patterns for
|
|
3007
|
-
const
|
|
2955
|
+
/** Config patterns for Playwright */
|
|
2956
|
+
const PLAYWRIGHT_CONFIG_PATTERNS = ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs'];
|
|
3008
2957
|
/**
|
|
3009
|
-
* Detect
|
|
2958
|
+
* Detect Playwright in project.
|
|
3010
2959
|
*
|
|
3011
2960
|
* @param projectPath - Project directory path
|
|
3012
2961
|
* @param packageJson - Optional pre-loaded package.json
|
|
3013
2962
|
* @returns Detection result or null if not detected
|
|
2963
|
+
*
|
|
2964
|
+
* @example Detecting Playwright testing framework
|
|
2965
|
+
* ```typescript
|
|
2966
|
+
* import { playwrightDetector } from '@hyperfrontend/project-scope'
|
|
2967
|
+
*
|
|
2968
|
+
* const result = playwrightDetector('./my-project')
|
|
2969
|
+
* if (result) {
|
|
2970
|
+
* console.log(`Playwright ${result.version} (${result.type} tests)`)
|
|
2971
|
+
* // => "Playwright 1.42.0 (e2e tests)"
|
|
2972
|
+
* }
|
|
2973
|
+
* ```
|
|
3014
2974
|
*/
|
|
3015
|
-
function
|
|
2975
|
+
function playwrightDetector(projectPath, packageJson) {
|
|
3016
2976
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3017
2977
|
const sources = [];
|
|
3018
2978
|
let confidence = 0;
|
|
3019
2979
|
let version;
|
|
3020
2980
|
const deps = collectAllDependencies(pkg);
|
|
3021
|
-
if (deps['
|
|
3022
|
-
confidence +=
|
|
3023
|
-
version = parseVersionString(deps['
|
|
3024
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
2981
|
+
if (deps['@playwright/test']) {
|
|
2982
|
+
confidence += 70;
|
|
2983
|
+
version = parseVersionString(deps['@playwright/test']);
|
|
2984
|
+
sources.push({ type: 'package.json', field: 'dependencies.@playwright/test' });
|
|
3025
2985
|
}
|
|
3026
|
-
|
|
2986
|
+
if (deps['playwright']) {
|
|
2987
|
+
confidence += 50;
|
|
2988
|
+
version = version ?? parseVersionString(deps['playwright']);
|
|
2989
|
+
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
2990
|
+
}
|
|
2991
|
+
const configPath = locateConfigFile(projectPath, PLAYWRIGHT_CONFIG_PATTERNS);
|
|
3027
2992
|
if (configPath) {
|
|
3028
|
-
confidence +=
|
|
2993
|
+
confidence += 25;
|
|
3029
2994
|
sources.push({ type: 'config-file', path: configPath });
|
|
3030
2995
|
}
|
|
3031
|
-
if (exists(join$1(projectPath, '
|
|
3032
|
-
confidence +=
|
|
3033
|
-
sources.push({ type: 'directory', path: '
|
|
2996
|
+
if (exists(join$1(projectPath, 'e2e')) || exists(join$1(projectPath, 'tests'))) {
|
|
2997
|
+
confidence += 5;
|
|
2998
|
+
sources.push({ type: 'directory', path: 'e2e/ or tests/' });
|
|
3034
2999
|
}
|
|
3035
3000
|
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
3036
|
-
if (e2eScript.includes('
|
|
3001
|
+
if (e2eScript.includes('playwright')) {
|
|
3037
3002
|
confidence += 5;
|
|
3038
3003
|
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
3039
3004
|
}
|
|
@@ -3041,8 +3006,8 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3041
3006
|
return null;
|
|
3042
3007
|
}
|
|
3043
3008
|
return {
|
|
3044
|
-
id: '
|
|
3045
|
-
name: '
|
|
3009
|
+
id: 'playwright',
|
|
3010
|
+
name: 'Playwright',
|
|
3046
3011
|
type: 'e2e',
|
|
3047
3012
|
version,
|
|
3048
3013
|
configPath,
|
|
@@ -3051,52 +3016,64 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3051
3016
|
};
|
|
3052
3017
|
}
|
|
3053
3018
|
|
|
3054
|
-
/** Config patterns for
|
|
3055
|
-
const
|
|
3019
|
+
/** Config patterns for Vitest */
|
|
3020
|
+
const VITEST_CONFIG_PATTERNS = ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'];
|
|
3056
3021
|
/**
|
|
3057
|
-
* Detect
|
|
3022
|
+
* Detect Vitest in project.
|
|
3058
3023
|
*
|
|
3059
3024
|
* @param projectPath - Project directory path
|
|
3060
3025
|
* @param packageJson - Optional pre-loaded package.json
|
|
3061
3026
|
* @returns Detection result or null if not detected
|
|
3027
|
+
*
|
|
3028
|
+
* @example Detecting Vitest testing framework
|
|
3029
|
+
* ```typescript
|
|
3030
|
+
* import { vitestDetector } from '@hyperfrontend/project-scope'
|
|
3031
|
+
*
|
|
3032
|
+
* const result = vitestDetector('./my-project')
|
|
3033
|
+
* if (result) {
|
|
3034
|
+
* console.log(`Vitest ${result.version} detected`)
|
|
3035
|
+
* console.log('Config:', result.configPath)
|
|
3036
|
+
* // => "Config: vitest.config.ts"
|
|
3037
|
+
* }
|
|
3038
|
+
* ```
|
|
3062
3039
|
*/
|
|
3063
|
-
function
|
|
3040
|
+
function vitestDetector(projectPath, packageJson) {
|
|
3064
3041
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3065
3042
|
const sources = [];
|
|
3066
3043
|
let confidence = 0;
|
|
3067
3044
|
let version;
|
|
3068
3045
|
const deps = collectAllDependencies(pkg);
|
|
3069
|
-
if (deps['
|
|
3046
|
+
if (deps['vitest']) {
|
|
3070
3047
|
confidence += 70;
|
|
3071
|
-
version = parseVersionString(deps['
|
|
3072
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
3073
|
-
}
|
|
3074
|
-
if (deps['playwright']) {
|
|
3075
|
-
confidence += 50;
|
|
3076
|
-
version = version ?? parseVersionString(deps['playwright']);
|
|
3077
|
-
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
3048
|
+
version = parseVersionString(deps['vitest']);
|
|
3049
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
3078
3050
|
}
|
|
3079
|
-
const configPath = locateConfigFile(projectPath,
|
|
3051
|
+
const configPath = locateConfigFile(projectPath, VITEST_CONFIG_PATTERNS);
|
|
3080
3052
|
if (configPath) {
|
|
3081
3053
|
confidence += 25;
|
|
3082
3054
|
sources.push({ type: 'config-file', path: configPath });
|
|
3083
3055
|
}
|
|
3084
|
-
if (
|
|
3085
|
-
|
|
3086
|
-
|
|
3056
|
+
if (!configPath) {
|
|
3057
|
+
const viteConfig = exists(join$1(projectPath, 'vite.config.ts')) ||
|
|
3058
|
+
exists(join$1(projectPath, 'vite.config.js')) ||
|
|
3059
|
+
exists(join$1(projectPath, 'vite.config.mjs'));
|
|
3060
|
+
if (viteConfig && deps['vitest']) {
|
|
3061
|
+
confidence += 5;
|
|
3062
|
+
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
3063
|
+
}
|
|
3087
3064
|
}
|
|
3088
|
-
const
|
|
3089
|
-
if (
|
|
3090
|
-
confidence +=
|
|
3091
|
-
sources.push({ type: 'package.json', field: 'scripts.
|
|
3065
|
+
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
3066
|
+
if (testScript.includes('vitest')) {
|
|
3067
|
+
confidence += 10;
|
|
3068
|
+
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
3092
3069
|
}
|
|
3093
3070
|
if (confidence === 0) {
|
|
3094
3071
|
return null;
|
|
3095
3072
|
}
|
|
3096
3073
|
return {
|
|
3097
|
-
id: '
|
|
3098
|
-
name: '
|
|
3099
|
-
type: '
|
|
3074
|
+
id: 'vitest',
|
|
3075
|
+
name: 'Vitest',
|
|
3076
|
+
type: 'unit',
|
|
3100
3077
|
version,
|
|
3101
3078
|
configPath,
|
|
3102
3079
|
confidence: min(confidence, 100),
|
|
@@ -3125,7 +3102,6 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3125
3102
|
if (!content)
|
|
3126
3103
|
return undefined;
|
|
3127
3104
|
try {
|
|
3128
|
-
// Simple JSON parsing - doesn't handle comments but good enough for strict check
|
|
3129
3105
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
3130
3106
|
const parsed = parse(cleanContent);
|
|
3131
3107
|
return parsed?.compilerOptions?.strict === true;
|
|
@@ -3140,6 +3116,19 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3140
3116
|
* @param projectPath - Project directory path
|
|
3141
3117
|
* @param packageJson - Optional pre-loaded package.json
|
|
3142
3118
|
* @returns Detection result or null if not detected
|
|
3119
|
+
*
|
|
3120
|
+
* @example Detecting TypeScript
|
|
3121
|
+
* ```typescript
|
|
3122
|
+
* import { typescriptDetector } from '@hyperfrontend/project-scope'
|
|
3123
|
+
*
|
|
3124
|
+
* const result = typescriptDetector('./my-project')
|
|
3125
|
+
* if (result) {
|
|
3126
|
+
* console.log(`TypeScript ${result.version}`)
|
|
3127
|
+
* console.log(`Strict mode: ${result.strictMode ?? 'unknown'}`)
|
|
3128
|
+
* // => "TypeScript 5.3.0"
|
|
3129
|
+
* // => "Strict mode: true"
|
|
3130
|
+
* }
|
|
3131
|
+
* ```
|
|
3143
3132
|
*/
|
|
3144
3133
|
function typescriptDetector(projectPath, packageJson) {
|
|
3145
3134
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3148,19 +3137,16 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3148
3137
|
let configPath;
|
|
3149
3138
|
let version;
|
|
3150
3139
|
const deps = collectAllDependencies(pkg);
|
|
3151
|
-
// TypeScript package
|
|
3152
3140
|
if (deps['typescript']) {
|
|
3153
3141
|
confidence += 50;
|
|
3154
3142
|
version = parseVersionString(deps['typescript']);
|
|
3155
3143
|
sources.push({ type: 'package.json', field: 'dependencies.typescript' });
|
|
3156
3144
|
}
|
|
3157
|
-
// tsconfig.json
|
|
3158
3145
|
if (exists(join$1(projectPath, 'tsconfig.json'))) {
|
|
3159
3146
|
confidence += 40;
|
|
3160
3147
|
configPath = 'tsconfig.json';
|
|
3161
3148
|
sources.push({ type: 'config-file', path: 'tsconfig.json' });
|
|
3162
3149
|
}
|
|
3163
|
-
// tsconfig.*.json variants
|
|
3164
3150
|
const tsconfigVariants = ['tsconfig.build.json', 'tsconfig.lib.json', 'tsconfig.spec.json', 'tsconfig.app.json'];
|
|
3165
3151
|
for (const variant of tsconfigVariants) {
|
|
3166
3152
|
if (exists(join$1(projectPath, variant))) {
|
|
@@ -3169,7 +3155,6 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3169
3155
|
break;
|
|
3170
3156
|
}
|
|
3171
3157
|
}
|
|
3172
|
-
// @types packages
|
|
3173
3158
|
const typePackages = keys(deps).filter((d) => d.startsWith('@types/'));
|
|
3174
3159
|
if (typePackages.length > 0) {
|
|
3175
3160
|
confidence += 10;
|
|
@@ -3195,6 +3180,17 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3195
3180
|
* @param projectPath - Project directory path
|
|
3196
3181
|
* @param packageJson - Optional pre-loaded package.json
|
|
3197
3182
|
* @returns Detection result or null if not detected
|
|
3183
|
+
*
|
|
3184
|
+
* @example Detecting Flow type system
|
|
3185
|
+
* ```typescript
|
|
3186
|
+
* import { flowDetector } from '@hyperfrontend/project-scope'
|
|
3187
|
+
*
|
|
3188
|
+
* const result = flowDetector('./my-project')
|
|
3189
|
+
* if (result) {
|
|
3190
|
+
* console.log(`Flow ${result.version} with config: ${result.configPath}`)
|
|
3191
|
+
* // => "Flow 0.232.0 with config: .flowconfig"
|
|
3192
|
+
* }
|
|
3193
|
+
* ```
|
|
3198
3194
|
*/
|
|
3199
3195
|
function flowDetector(projectPath, packageJson) {
|
|
3200
3196
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3203,24 +3199,20 @@ function flowDetector(projectPath, packageJson) {
|
|
|
3203
3199
|
let configPath;
|
|
3204
3200
|
let version;
|
|
3205
3201
|
const deps = collectAllDependencies(pkg);
|
|
3206
|
-
// flow-bin package
|
|
3207
3202
|
if (deps['flow-bin']) {
|
|
3208
3203
|
confidence += 60;
|
|
3209
3204
|
version = parseVersionString(deps['flow-bin']);
|
|
3210
3205
|
sources.push({ type: 'package.json', field: 'dependencies.flow-bin' });
|
|
3211
3206
|
}
|
|
3212
|
-
// .flowconfig
|
|
3213
3207
|
if (exists(join$1(projectPath, '.flowconfig'))) {
|
|
3214
3208
|
confidence += 40;
|
|
3215
3209
|
configPath = '.flowconfig';
|
|
3216
3210
|
sources.push({ type: 'config-file', path: '.flowconfig' });
|
|
3217
3211
|
}
|
|
3218
|
-
// flow-typed directory
|
|
3219
3212
|
if (exists(join$1(projectPath, 'flow-typed'))) {
|
|
3220
3213
|
confidence += 10;
|
|
3221
3214
|
sources.push({ type: 'directory', path: 'flow-typed/' });
|
|
3222
3215
|
}
|
|
3223
|
-
// @babel/preset-flow
|
|
3224
3216
|
if (deps['@babel/preset-flow']) {
|
|
3225
3217
|
confidence += 10;
|
|
3226
3218
|
sources.push({ type: 'package.json', field: 'dependencies.@babel/preset-flow' });
|
|
@@ -3244,7 +3236,6 @@ function flowDetector(projectPath, packageJson) {
|
|
|
3244
3236
|
* @returns `true` if the content contains JSDoc type annotations.
|
|
3245
3237
|
*/
|
|
3246
3238
|
function hasJsDocTypes(content) {
|
|
3247
|
-
// Check for JSDoc type annotations
|
|
3248
3239
|
return (content.includes('@type {') ||
|
|
3249
3240
|
content.includes('@param {') ||
|
|
3250
3241
|
content.includes('@returns {') ||
|
|
@@ -3257,20 +3248,29 @@ function hasJsDocTypes(content) {
|
|
|
3257
3248
|
* @param projectPath - Project directory path
|
|
3258
3249
|
* @param packageJson - Optional pre-loaded package.json
|
|
3259
3250
|
* @returns Detection result or null if not detected
|
|
3251
|
+
*
|
|
3252
|
+
* @example Detecting JSDoc type annotations
|
|
3253
|
+
* ```typescript
|
|
3254
|
+
* import { jsdocDetector } from '@hyperfrontend/project-scope'
|
|
3255
|
+
*
|
|
3256
|
+
* const result = jsdocDetector('./my-project')
|
|
3257
|
+
* if (result) {
|
|
3258
|
+
* console.log('JSDoc types detected')
|
|
3259
|
+
* console.log('Sources:', result.detectedFrom.map(s => s.path ?? s.field))
|
|
3260
|
+
* // => "Sources: ['jsconfig.json', 'src/utils.js (JSDoc annotations)']"
|
|
3261
|
+
* }
|
|
3262
|
+
* ```
|
|
3260
3263
|
*/
|
|
3261
3264
|
function jsdocDetector(projectPath, packageJson) {
|
|
3262
3265
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3263
3266
|
const sources = [];
|
|
3264
3267
|
let confidence = 0;
|
|
3265
3268
|
const deps = collectAllDependencies(pkg);
|
|
3266
|
-
// jsdoc package
|
|
3267
3269
|
if (deps['jsdoc']) {
|
|
3268
3270
|
confidence += 30;
|
|
3269
3271
|
sources.push({ type: 'package.json', field: 'dependencies.jsdoc' });
|
|
3270
3272
|
}
|
|
3271
|
-
// typescript with checkJs (JSDoc type checking)
|
|
3272
3273
|
if (deps['typescript']) {
|
|
3273
|
-
// Check if checkJs is enabled in tsconfig
|
|
3274
3274
|
const tsconfigPath = join$1(projectPath, 'tsconfig.json');
|
|
3275
3275
|
const content = readFileIfExists(tsconfigPath);
|
|
3276
3276
|
if (content) {
|
|
@@ -3287,12 +3287,10 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
3287
3287
|
}
|
|
3288
3288
|
}
|
|
3289
3289
|
}
|
|
3290
|
-
// Check for jsconfig.json (VS Code JS type checking)
|
|
3291
3290
|
if (exists(join$1(projectPath, 'jsconfig.json'))) {
|
|
3292
3291
|
confidence += 40;
|
|
3293
3292
|
sources.push({ type: 'config-file', path: 'jsconfig.json' });
|
|
3294
3293
|
}
|
|
3295
|
-
// Sample check for JSDoc annotations in source files
|
|
3296
3294
|
const srcDir = join$1(projectPath, 'src');
|
|
3297
3295
|
if (exists(srcDir)) {
|
|
3298
3296
|
try {
|
|
@@ -3343,8 +3341,6 @@ const detectAllCache = createCache({ ttl: 60000, maxSize: 50 });
|
|
|
3343
3341
|
function isDetectAllOptions(value) {
|
|
3344
3342
|
if (typeof value !== 'object' || value === null)
|
|
3345
3343
|
return false;
|
|
3346
|
-
// DetectAllOptions has skipCache or packageJson fields specifically
|
|
3347
|
-
// PackageJson never has skipCache field
|
|
3348
3344
|
return 'skipCache' in value || 'packageJson' in value;
|
|
3349
3345
|
}
|
|
3350
3346
|
/**
|
|
@@ -3357,7 +3353,7 @@ function isDetectAllOptions(value) {
|
|
|
3357
3353
|
* @param packageJsonOrOptions - Optional pre-loaded package.json or options object
|
|
3358
3354
|
* @returns All detection results organized by category
|
|
3359
3355
|
*
|
|
3360
|
-
* @example
|
|
3356
|
+
* @example Running all tech detectors
|
|
3361
3357
|
* ```typescript
|
|
3362
3358
|
* import { detectAll } from '@hyperfrontend/project-scope'
|
|
3363
3359
|
*
|
|
@@ -3376,9 +3372,7 @@ function isDetectAllOptions(value) {
|
|
|
3376
3372
|
* ```
|
|
3377
3373
|
*/
|
|
3378
3374
|
function detectAll(projectPath, packageJsonOrOptions) {
|
|
3379
|
-
// Handle backward-compatible arguments
|
|
3380
3375
|
const options = isDetectAllOptions(packageJsonOrOptions) ? packageJsonOrOptions : { packageJson: packageJsonOrOptions };
|
|
3381
|
-
// Check cache first (unless skipCache is true)
|
|
3382
3376
|
if (!options.skipCache) {
|
|
3383
3377
|
const cached = detectAllCache.get(projectPath);
|
|
3384
3378
|
if (cached) {
|
|
@@ -3429,7 +3423,6 @@ function detectAll(projectPath, packageJsonOrOptions) {
|
|
|
3429
3423
|
legacyFrameworks: result.legacyFrameworks.map((f) => f.id),
|
|
3430
3424
|
testingFrameworks: result.testingFrameworks.map((f) => f.id),
|
|
3431
3425
|
});
|
|
3432
|
-
// Cache the result
|
|
3433
3426
|
detectAllCache.set(projectPath, result);
|
|
3434
3427
|
return result;
|
|
3435
3428
|
}
|
|
@@ -3477,7 +3470,7 @@ function buildSummary(frontend, backend, testing) {
|
|
|
3477
3470
|
* @param options - Identification options
|
|
3478
3471
|
* @returns Framework identification result
|
|
3479
3472
|
*
|
|
3480
|
-
* @example
|
|
3473
|
+
* @example Identifying all frameworks in project
|
|
3481
3474
|
* ```typescript
|
|
3482
3475
|
* import { identifyFrameworks } from '@hyperfrontend/project-scope'
|
|
3483
3476
|
*
|
|
@@ -3592,6 +3585,14 @@ function identifyFrameworks(projectPath, options) {
|
|
|
3592
3585
|
* Clear the framework identification cache.
|
|
3593
3586
|
*
|
|
3594
3587
|
* Useful for testing or when the project files have changed.
|
|
3588
|
+
*
|
|
3589
|
+
* @example Clearing the framework cache
|
|
3590
|
+
* ```typescript
|
|
3591
|
+
* import { clearFrameworkIdentificationCache } from '@hyperfrontend/project-scope'
|
|
3592
|
+
*
|
|
3593
|
+
* // Reset cache before re-identifying frameworks
|
|
3594
|
+
* clearFrameworkIdentificationCache()
|
|
3595
|
+
* ```
|
|
3595
3596
|
*/
|
|
3596
3597
|
function clearFrameworkIdentificationCache() {
|
|
3597
3598
|
frameworkIdCache.clear();
|
|
@@ -3603,6 +3604,15 @@ function clearFrameworkIdentificationCache() {
|
|
|
3603
3604
|
* @param frameworkId - Framework identifier to check
|
|
3604
3605
|
* @param minConfidence - Minimum confidence threshold (default: 50)
|
|
3605
3606
|
* @returns True if the framework is detected with sufficient confidence
|
|
3607
|
+
*
|
|
3608
|
+
* @example Checking for a specific framework
|
|
3609
|
+
* ```typescript
|
|
3610
|
+
* import { usesFramework } from '@hyperfrontend/project-scope'
|
|
3611
|
+
*
|
|
3612
|
+
* if (usesFramework('/path/to/project', 'react', 70)) {
|
|
3613
|
+
* console.log('Project uses React with high confidence')
|
|
3614
|
+
* }
|
|
3615
|
+
* ```
|
|
3606
3616
|
*/
|
|
3607
3617
|
function usesFramework(projectPath, frameworkId, minConfidence = 50) {
|
|
3608
3618
|
const identification = identifyFrameworks(projectPath, { minConfidence });
|
|
@@ -3611,4 +3621,3 @@ function usesFramework(projectPath, frameworkId, minConfidence = 50) {
|
|
|
3611
3621
|
}
|
|
3612
3622
|
|
|
3613
3623
|
export { clearFrameworkIdentificationCache, identifyFrameworks, usesFramework };
|
|
3614
|
-
//# sourceMappingURL=index.esm.js.map
|