@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,431 +1,19 @@
|
|
|
1
1
|
import { join as join$1 } from 'node:path';
|
|
2
|
+
import { stringify, parse } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.esm.js';
|
|
3
|
+
import { min, round } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.esm.js';
|
|
4
|
+
import { freeze, entries, keys, defineProperties, values } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.esm.js';
|
|
2
5
|
import { existsSync, readFileSync, statSync, lstatSync, readdirSync } from 'node:fs';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
|
|
16
|
-
*/
|
|
17
|
-
const parse = _JSON.parse;
|
|
18
|
-
/**
|
|
19
|
-
* (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
|
20
|
-
*/
|
|
21
|
-
const stringify = _JSON.stringify;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Safe copies of Math built-in methods.
|
|
25
|
-
*
|
|
26
|
-
* These references are captured at module initialization time to protect against
|
|
27
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
28
|
-
*
|
|
29
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/math
|
|
30
|
-
*/
|
|
31
|
-
// Capture references at module initialization time
|
|
32
|
-
const _Math = globalThis.Math;
|
|
33
|
-
/**
|
|
34
|
-
* (Safe copy) Returns the value of a number rounded to the nearest integer.
|
|
35
|
-
*/
|
|
36
|
-
const round = _Math.round;
|
|
37
|
-
/**
|
|
38
|
-
* (Safe copy) Returns the smaller of zero or more numbers.
|
|
39
|
-
*/
|
|
40
|
-
const min = _Math.min;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Safe copies of Object built-in methods.
|
|
44
|
-
*
|
|
45
|
-
* These references are captured at module initialization time to protect against
|
|
46
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
47
|
-
*
|
|
48
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/object
|
|
49
|
-
*/
|
|
50
|
-
// Capture references at module initialization time
|
|
51
|
-
const _Object = globalThis.Object;
|
|
52
|
-
/**
|
|
53
|
-
* (Safe copy) Prevents modification of existing property attributes and values,
|
|
54
|
-
* and prevents the addition of new properties.
|
|
55
|
-
*/
|
|
56
|
-
const freeze = _Object.freeze;
|
|
57
|
-
/**
|
|
58
|
-
* (Safe copy) Returns the names of the enumerable string properties and methods of an object.
|
|
59
|
-
*/
|
|
60
|
-
const keys = _Object.keys;
|
|
61
|
-
/**
|
|
62
|
-
* (Safe copy) Returns an array of key/values of the enumerable own properties of an object.
|
|
63
|
-
*/
|
|
64
|
-
const entries = _Object.entries;
|
|
65
|
-
/**
|
|
66
|
-
* (Safe copy) Returns an array of values of the enumerable own properties of an object.
|
|
67
|
-
*/
|
|
68
|
-
const values = _Object.values;
|
|
69
|
-
/**
|
|
70
|
-
* (Safe copy) Adds one or more properties to an object, and/or modifies attributes of existing properties.
|
|
71
|
-
*/
|
|
72
|
-
const defineProperties = _Object.defineProperties;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Safe copies of Error built-ins via factory functions.
|
|
76
|
-
*
|
|
77
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
78
|
-
* provides factory functions that use Reflect.construct internally.
|
|
79
|
-
*
|
|
80
|
-
* These references are captured at module initialization time to protect against
|
|
81
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
82
|
-
*
|
|
83
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
84
|
-
*/
|
|
85
|
-
// Capture references at module initialization time
|
|
86
|
-
const _Error = globalThis.Error;
|
|
87
|
-
const _Reflect$2 = globalThis.Reflect;
|
|
88
|
-
/**
|
|
89
|
-
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
90
|
-
* Use this instead of `new Error()`.
|
|
91
|
-
*
|
|
92
|
-
* @param message - Optional error message.
|
|
93
|
-
* @param options - Optional error options.
|
|
94
|
-
* @returns A new Error instance.
|
|
95
|
-
*/
|
|
96
|
-
const createError = (message, options) => _Reflect$2.construct(_Error, [message, options]);
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Safe copies of Array built-in static methods.
|
|
100
|
-
*
|
|
101
|
-
* These references are captured at module initialization time to protect against
|
|
102
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
103
|
-
*
|
|
104
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
105
|
-
*/
|
|
106
|
-
// Capture references at module initialization time
|
|
107
|
-
const _Array = globalThis.Array;
|
|
108
|
-
/**
|
|
109
|
-
* (Safe copy) Determines whether the passed value is an Array.
|
|
110
|
-
*/
|
|
111
|
-
const isArray = _Array.isArray;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Safe copies of Console built-in methods.
|
|
115
|
-
*
|
|
116
|
-
* These references are captured at module initialization time to protect against
|
|
117
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
118
|
-
*
|
|
119
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/console
|
|
120
|
-
*/
|
|
121
|
-
// Capture references at module initialization time
|
|
122
|
-
const _console = globalThis.console;
|
|
123
|
-
/**
|
|
124
|
-
* (Safe copy) Outputs a message to the console.
|
|
125
|
-
*/
|
|
126
|
-
const log = _console.log.bind(_console);
|
|
127
|
-
/**
|
|
128
|
-
* (Safe copy) Outputs a warning message to the console.
|
|
129
|
-
*/
|
|
130
|
-
const warn = _console.warn.bind(_console);
|
|
131
|
-
/**
|
|
132
|
-
* (Safe copy) Outputs an error message to the console.
|
|
133
|
-
*/
|
|
134
|
-
const error = _console.error.bind(_console);
|
|
135
|
-
/**
|
|
136
|
-
* (Safe copy) Outputs an informational message to the console.
|
|
137
|
-
*/
|
|
138
|
-
const info = _console.info.bind(_console);
|
|
139
|
-
/**
|
|
140
|
-
* (Safe copy) Outputs a debug message to the console.
|
|
141
|
-
*/
|
|
142
|
-
const debug = _console.debug.bind(_console);
|
|
143
|
-
/**
|
|
144
|
-
* (Safe copy) Outputs a stack trace to the console.
|
|
145
|
-
*/
|
|
146
|
-
_console.trace.bind(_console);
|
|
147
|
-
/**
|
|
148
|
-
* (Safe copy) Displays an interactive listing of the properties of a specified object.
|
|
149
|
-
*/
|
|
150
|
-
_console.dir.bind(_console);
|
|
151
|
-
/**
|
|
152
|
-
* (Safe copy) Displays tabular data as a table.
|
|
153
|
-
*/
|
|
154
|
-
_console.table.bind(_console);
|
|
155
|
-
/**
|
|
156
|
-
* (Safe copy) Writes an error message to the console if the assertion is false.
|
|
157
|
-
*/
|
|
158
|
-
_console.assert.bind(_console);
|
|
159
|
-
/**
|
|
160
|
-
* (Safe copy) Clears the console.
|
|
161
|
-
*/
|
|
162
|
-
_console.clear.bind(_console);
|
|
163
|
-
/**
|
|
164
|
-
* (Safe copy) Logs the number of times that this particular call to count() has been called.
|
|
165
|
-
*/
|
|
166
|
-
_console.count.bind(_console);
|
|
167
|
-
/**
|
|
168
|
-
* (Safe copy) Resets the counter used with console.count().
|
|
169
|
-
*/
|
|
170
|
-
_console.countReset.bind(_console);
|
|
171
|
-
/**
|
|
172
|
-
* (Safe copy) Creates a new inline group in the console.
|
|
173
|
-
*/
|
|
174
|
-
_console.group.bind(_console);
|
|
175
|
-
/**
|
|
176
|
-
* (Safe copy) Creates a new inline group in the console that is initially collapsed.
|
|
177
|
-
*/
|
|
178
|
-
_console.groupCollapsed.bind(_console);
|
|
179
|
-
/**
|
|
180
|
-
* (Safe copy) Exits the current inline group.
|
|
181
|
-
*/
|
|
182
|
-
_console.groupEnd.bind(_console);
|
|
183
|
-
/**
|
|
184
|
-
* (Safe copy) Starts a timer with a name specified as an input parameter.
|
|
185
|
-
*/
|
|
186
|
-
_console.time.bind(_console);
|
|
187
|
-
/**
|
|
188
|
-
* (Safe copy) Stops a timer that was previously started.
|
|
189
|
-
*/
|
|
190
|
-
_console.timeEnd.bind(_console);
|
|
191
|
-
/**
|
|
192
|
-
* (Safe copy) Logs the current value of a timer that was previously started.
|
|
193
|
-
*/
|
|
194
|
-
_console.timeLog.bind(_console);
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Safe copies of Set built-in via factory function.
|
|
198
|
-
*
|
|
199
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
200
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
201
|
-
*
|
|
202
|
-
* These references are captured at module initialization time to protect against
|
|
203
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
204
|
-
*
|
|
205
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/set
|
|
206
|
-
*/
|
|
207
|
-
// Capture references at module initialization time
|
|
208
|
-
const _Set = globalThis.Set;
|
|
209
|
-
const _Reflect$1 = globalThis.Reflect;
|
|
210
|
-
/**
|
|
211
|
-
* (Safe copy) Creates a new Set using the captured Set constructor.
|
|
212
|
-
* Use this instead of `new Set()`.
|
|
213
|
-
*
|
|
214
|
-
* @param iterable - Optional iterable of values.
|
|
215
|
-
* @returns A new Set instance.
|
|
216
|
-
*/
|
|
217
|
-
const createSet = (iterable) => _Reflect$1.construct(_Set, iterable ? [iterable] : []);
|
|
218
|
-
|
|
219
|
-
const registeredClasses = [];
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Returns the data type of the target.
|
|
223
|
-
* Uses native `typeof` operator, however, makes distinction between `null`, `array`, and `object`.
|
|
224
|
-
* Also, when classes are registered via `registerClass`, it checks if objects are instance of any known registered class.
|
|
225
|
-
*
|
|
226
|
-
* @param target - The target to get the data type of.
|
|
227
|
-
* @returns The data type of the target.
|
|
228
|
-
*/
|
|
229
|
-
const getType = (target) => {
|
|
230
|
-
if (target === null)
|
|
231
|
-
return 'null';
|
|
232
|
-
const nativeDataType = typeof target;
|
|
233
|
-
if (nativeDataType === 'object') {
|
|
234
|
-
if (isArray(target))
|
|
235
|
-
return 'array';
|
|
236
|
-
for (const registeredClass of registeredClasses) {
|
|
237
|
-
if (target instanceof registeredClass)
|
|
238
|
-
return registeredClass.name;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return nativeDataType;
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Safe copies of Map built-in via factory function.
|
|
246
|
-
*
|
|
247
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
248
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
249
|
-
*
|
|
250
|
-
* These references are captured at module initialization time to protect against
|
|
251
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
252
|
-
*
|
|
253
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/map
|
|
254
|
-
*/
|
|
255
|
-
// Capture references at module initialization time
|
|
256
|
-
const _Map = globalThis.Map;
|
|
257
|
-
const _Reflect = globalThis.Reflect;
|
|
258
|
-
/**
|
|
259
|
-
* (Safe copy) Creates a new Map using the captured Map constructor.
|
|
260
|
-
* Use this instead of `new Map()`.
|
|
261
|
-
*
|
|
262
|
-
* @param iterable - Optional iterable of key-value pairs.
|
|
263
|
-
* @returns A new Map instance.
|
|
264
|
-
*/
|
|
265
|
-
const createMap = (iterable) => _Reflect.construct(_Map, iterable ? [iterable] : []);
|
|
266
|
-
|
|
267
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
268
|
-
/**
|
|
269
|
-
* Creates a wrapper function that only executes the wrapped function if the condition function returns true.
|
|
270
|
-
*
|
|
271
|
-
* @param func - The function to be conditionally executed.
|
|
272
|
-
* @param conditionFunc - A function that returns a boolean, determining if `func` should be executed.
|
|
273
|
-
* @returns A wrapped version of `func` that executes conditionally.
|
|
274
|
-
*/
|
|
275
|
-
function createConditionalExecutionFunction(func, conditionFunc) {
|
|
276
|
-
return function (...args) {
|
|
277
|
-
if (conditionFunc()) {
|
|
278
|
-
return func(...args);
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
284
|
-
/**
|
|
285
|
-
* Creates a wrapper function that silently ignores any errors thrown by the wrapped void function.
|
|
286
|
-
* This function is specifically for wrapping functions that do not return a value (void functions).
|
|
287
|
-
* Exceptions are swallowed without any logging or handling.
|
|
288
|
-
*
|
|
289
|
-
* @param func - The void function to be wrapped.
|
|
290
|
-
* @returns A wrapped version of the input function that ignores errors.
|
|
291
|
-
*/
|
|
292
|
-
function createErrorIgnoringFunction(func) {
|
|
293
|
-
return function (...args) {
|
|
294
|
-
try {
|
|
295
|
-
func(...args);
|
|
296
|
-
}
|
|
297
|
-
catch {
|
|
298
|
-
// Deliberately swallowing/ignoring the exception
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
304
|
-
/**
|
|
305
|
-
* A no-operation function (noop) that does nothing regardless of the arguments passed.
|
|
306
|
-
* It is designed to be as permissive as possible in its typing without using the `Function` keyword.
|
|
307
|
-
*
|
|
308
|
-
* @param args - Any arguments passed to the function (ignored)
|
|
309
|
-
*/
|
|
310
|
-
const noop = (...args) => {
|
|
311
|
-
// Intentionally does nothing
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
const logLevels = ['none', 'error', 'warn', 'log', 'info', 'debug'];
|
|
315
|
-
const priority = {
|
|
316
|
-
error: 4,
|
|
317
|
-
warn: 3,
|
|
318
|
-
log: 2,
|
|
319
|
-
info: 1,
|
|
320
|
-
debug: 0,
|
|
321
|
-
};
|
|
322
|
-
/**
|
|
323
|
-
* Validates whether a given string is a valid log level.
|
|
324
|
-
*
|
|
325
|
-
* @param level - The log level to validate
|
|
326
|
-
* @returns True if the level is valid, false otherwise
|
|
327
|
-
*/
|
|
328
|
-
function isValidLogLevel(level) {
|
|
329
|
-
return logLevels.includes(level);
|
|
330
|
-
}
|
|
331
|
-
/**
|
|
332
|
-
* Creates a log level configuration manager for controlling logging behavior.
|
|
333
|
-
* Provides methods to get, set, and evaluate log levels based on priority.
|
|
334
|
-
*
|
|
335
|
-
* @param level - The initial log level (defaults to 'error')
|
|
336
|
-
* @returns A configuration object with log level management methods
|
|
337
|
-
* @throws {Error} When the provided level is not a valid log level
|
|
338
|
-
*/
|
|
339
|
-
function createLogLevelConfig(level = 'error') {
|
|
340
|
-
if (!isValidLogLevel(level)) {
|
|
341
|
-
throw createError('Cannot create log level configuration with a valid default log level');
|
|
342
|
-
}
|
|
343
|
-
const state = { level };
|
|
344
|
-
const getLogLevel = () => state.level;
|
|
345
|
-
const setLogLevel = (level) => {
|
|
346
|
-
if (!isValidLogLevel(level)) {
|
|
347
|
-
throw createError(`Cannot set value '${level}' level. Expected levels are ${logLevels}.`);
|
|
348
|
-
}
|
|
349
|
-
state.level = level;
|
|
350
|
-
};
|
|
351
|
-
const shouldLog = (level) => {
|
|
352
|
-
if (state.level === 'none' || level === 'none' || !isValidLogLevel(level)) {
|
|
353
|
-
return false;
|
|
354
|
-
}
|
|
355
|
-
return priority[level] >= priority[state.level];
|
|
356
|
-
};
|
|
357
|
-
return freeze({
|
|
358
|
-
getLogLevel,
|
|
359
|
-
setLogLevel,
|
|
360
|
-
shouldLog,
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Creates a logger instance with configurable log level filtering.
|
|
366
|
-
* Each log function is wrapped to respect the current log level setting.
|
|
367
|
-
*
|
|
368
|
-
* @param error - Function to handle error-level logs (required)
|
|
369
|
-
* @param warn - Function to handle warning-level logs (optional, defaults to noop)
|
|
370
|
-
* @param log - Function to handle standard logs (optional, defaults to noop)
|
|
371
|
-
* @param info - Function to handle info-level logs (optional, defaults to noop)
|
|
372
|
-
* @param debug - Function to handle debug-level logs (optional, defaults to noop)
|
|
373
|
-
* @returns A frozen logger object with log methods and level control
|
|
374
|
-
* @throws {ErrorLevelFn} When any provided log function is invalid
|
|
375
|
-
*/
|
|
376
|
-
function createLogger(error, warn = noop, log = noop, info = noop, debug = noop) {
|
|
377
|
-
if (notValidLogFn(error)) {
|
|
378
|
-
throw createError(notFnMsg('error'));
|
|
379
|
-
}
|
|
380
|
-
if (notValidLogFn(warn)) {
|
|
381
|
-
throw createError(notFnMsg('warn'));
|
|
382
|
-
}
|
|
383
|
-
if (notValidLogFn(log)) {
|
|
384
|
-
throw createError(notFnMsg('log'));
|
|
385
|
-
}
|
|
386
|
-
if (notValidLogFn(info)) {
|
|
387
|
-
throw createError(notFnMsg('info'));
|
|
388
|
-
}
|
|
389
|
-
if (notValidLogFn(debug)) {
|
|
390
|
-
throw createError(notFnMsg('debug'));
|
|
391
|
-
}
|
|
392
|
-
const { setLogLevel, getLogLevel, shouldLog } = createLogLevelConfig();
|
|
393
|
-
const wrapLogFn = (fn, level) => {
|
|
394
|
-
if (fn === noop)
|
|
395
|
-
return fn;
|
|
396
|
-
const condition = () => shouldLog(level);
|
|
397
|
-
return createConditionalExecutionFunction(createErrorIgnoringFunction(fn), condition);
|
|
398
|
-
};
|
|
399
|
-
return freeze({
|
|
400
|
-
error: wrapLogFn(error, 'error'),
|
|
401
|
-
warn: wrapLogFn(warn, 'warn'),
|
|
402
|
-
log: wrapLogFn(log, 'log'),
|
|
403
|
-
info: wrapLogFn(info, 'info'),
|
|
404
|
-
debug: wrapLogFn(debug, 'debug'),
|
|
405
|
-
setLogLevel,
|
|
406
|
-
getLogLevel,
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* Validates whether a given value is a valid log function.
|
|
411
|
-
*
|
|
412
|
-
* @param fn - The value to validate
|
|
413
|
-
* @returns True if the value is not a function (invalid), false if it is valid
|
|
414
|
-
*/
|
|
415
|
-
function notValidLogFn(fn) {
|
|
416
|
-
return getType(fn) !== 'function' && fn !== noop;
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* Generates an error message for invalid log function parameters.
|
|
420
|
-
*
|
|
421
|
-
* @param label - The name of the log function that failed validation
|
|
422
|
-
* @returns A formatted error message string
|
|
423
|
-
*/
|
|
424
|
-
function notFnMsg(label) {
|
|
425
|
-
return `Cannot create a logger when ${label} is not a function`;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
createLogger(error, warn, log, info, debug);
|
|
6
|
+
import { isArray } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.esm.js';
|
|
7
|
+
import { error, warn, log, info, debug } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.esm.js';
|
|
8
|
+
import { createSet } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.esm.js';
|
|
9
|
+
import { createLogger } from '../../_dependencies/@hyperfrontend/logging/index.esm.js';
|
|
10
|
+
import { createError } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js';
|
|
11
|
+
import { createMap } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.esm.js';
|
|
12
|
+
import { 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';
|
|
429
17
|
|
|
430
18
|
/**
|
|
431
19
|
* Global log level registry.
|
|
@@ -465,6 +53,13 @@ function isSensitiveKey(key) {
|
|
|
465
53
|
*
|
|
466
54
|
* @param obj - Object to sanitize
|
|
467
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
|
+
* ```
|
|
468
63
|
*/
|
|
469
64
|
function sanitize(obj) {
|
|
470
65
|
if (obj === null || obj === undefined) {
|
|
@@ -515,7 +110,7 @@ function formatMessage(namespace, message, meta) {
|
|
|
515
110
|
* @param options - Logger configuration options
|
|
516
111
|
* @returns A configured scoped logger instance
|
|
517
112
|
*
|
|
518
|
-
* @example
|
|
113
|
+
* @example Creating a scoped logger
|
|
519
114
|
* ```typescript
|
|
520
115
|
* const logger = createScopedLogger('project-scope')
|
|
521
116
|
* logger.setLogLevel('debug')
|
|
@@ -530,14 +125,11 @@ function formatMessage(namespace, message, meta) {
|
|
|
530
125
|
*/
|
|
531
126
|
function createScopedLogger(namespace, options = {}) {
|
|
532
127
|
const { level = 'error', sanitizeSecrets = true } = options;
|
|
533
|
-
// Create wrapper functions that add namespace prefix and sanitization
|
|
534
128
|
const createLogFn = (baseFn) => (message, meta) => {
|
|
535
129
|
const processedMeta = sanitizeSecrets && meta ? sanitize(meta) : meta;
|
|
536
130
|
baseFn(formatMessage(namespace, message, processedMeta));
|
|
537
131
|
};
|
|
538
|
-
// Create base logger with wrapped functions
|
|
539
132
|
const baseLogger = createLogger(createLogFn(error), createLogFn(warn), createLogFn(log), createLogFn(info), createLogFn(debug));
|
|
540
|
-
// Set initial log level (use global override if set)
|
|
541
133
|
baseLogger.setLogLevel(level);
|
|
542
134
|
const scopedLogger = freeze({
|
|
543
135
|
error: (message, meta) => baseLogger.error(message, meta),
|
|
@@ -548,7 +140,6 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
548
140
|
setLogLevel: baseLogger.setLogLevel,
|
|
549
141
|
getLogLevel: baseLogger.getLogLevel,
|
|
550
142
|
});
|
|
551
|
-
// Register logger for global level management
|
|
552
143
|
loggerRegistry.add(scopedLogger);
|
|
553
144
|
return scopedLogger;
|
|
554
145
|
}
|
|
@@ -556,7 +147,7 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
556
147
|
* Default logger instance for the project-scope library.
|
|
557
148
|
* Use this for general logging within the library.
|
|
558
149
|
*
|
|
559
|
-
* @example
|
|
150
|
+
* @example Using the default logger
|
|
560
151
|
* ```typescript
|
|
561
152
|
* import { logger } from '@hyperfrontend/project-scope/core'
|
|
562
153
|
*
|
|
@@ -574,6 +165,15 @@ createScopedLogger('project-scope:fs');
|
|
|
574
165
|
* @param code - The category code for this type of filesystem failure
|
|
575
166
|
* @param context - Additional context including path, operation, and cause
|
|
576
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
|
+
* ```
|
|
577
177
|
*/
|
|
578
178
|
function createFileSystemError(message, code, context) {
|
|
579
179
|
const error = createError(message);
|
|
@@ -589,6 +189,14 @@ function createFileSystemError(message, code, context) {
|
|
|
589
189
|
* @param filePath - Path to file
|
|
590
190
|
* @param encoding - File encoding (default: utf-8)
|
|
591
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
|
+
* ```
|
|
592
200
|
*/
|
|
593
201
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
594
202
|
if (!existsSync(filePath)) {
|
|
@@ -602,56 +210,6 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
602
210
|
}
|
|
603
211
|
}
|
|
604
212
|
|
|
605
|
-
createScopedLogger('project-scope:fs:write');
|
|
606
|
-
|
|
607
|
-
/**
|
|
608
|
-
* Get file stats with error handling.
|
|
609
|
-
*
|
|
610
|
-
* @param filePath - Path to file
|
|
611
|
-
* @param followSymlinks - Whether to follow symlinks (default: true)
|
|
612
|
-
* @returns File stats or null if path doesn't exist
|
|
613
|
-
*/
|
|
614
|
-
function getFileStat(filePath, followSymlinks = true) {
|
|
615
|
-
if (!existsSync(filePath)) {
|
|
616
|
-
return null;
|
|
617
|
-
}
|
|
618
|
-
try {
|
|
619
|
-
const stat = followSymlinks ? statSync(filePath) : lstatSync(filePath);
|
|
620
|
-
return {
|
|
621
|
-
isFile: stat.isFile(),
|
|
622
|
-
isDirectory: stat.isDirectory(),
|
|
623
|
-
isSymlink: stat.isSymbolicLink(),
|
|
624
|
-
size: stat.size,
|
|
625
|
-
created: stat.birthtime,
|
|
626
|
-
modified: stat.mtime,
|
|
627
|
-
accessed: stat.atime,
|
|
628
|
-
mode: stat.mode,
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
catch {
|
|
632
|
-
return null;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Check if path is a directory.
|
|
637
|
-
*
|
|
638
|
-
* @param dirPath - Path to check
|
|
639
|
-
* @returns True if path is a directory
|
|
640
|
-
*/
|
|
641
|
-
function isDirectory(dirPath) {
|
|
642
|
-
const stats = getFileStat(dirPath);
|
|
643
|
-
return stats?.isDirectory ?? false;
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* Check if path exists.
|
|
647
|
-
*
|
|
648
|
-
* @param filePath - Path to check
|
|
649
|
-
* @returns True if path exists
|
|
650
|
-
*/
|
|
651
|
-
function exists(filePath) {
|
|
652
|
-
return existsSync(filePath);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
213
|
const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
656
214
|
/**
|
|
657
215
|
* List immediate contents of a directory.
|
|
@@ -660,7 +218,7 @@ const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
|
660
218
|
* @returns Array of entries with metadata for each file/directory
|
|
661
219
|
* @throws {Error} If directory doesn't exist or isn't a directory
|
|
662
220
|
*
|
|
663
|
-
* @example
|
|
221
|
+
* @example Listing directory contents
|
|
664
222
|
* ```typescript
|
|
665
223
|
* import { readDirectory } from '@hyperfrontend/project-scope'
|
|
666
224
|
*
|
|
@@ -701,19 +259,10 @@ function readDirectory(dirPath) {
|
|
|
701
259
|
}
|
|
702
260
|
}
|
|
703
261
|
|
|
704
|
-
/**
|
|
705
|
-
* Join path segments.
|
|
706
|
-
* Uses platform-specific separators (e.g., / or \).
|
|
707
|
-
*
|
|
708
|
-
* @param paths - Path segments to join
|
|
709
|
-
* @returns Joined path
|
|
710
|
-
*/
|
|
711
|
-
function join(...paths) {
|
|
712
|
-
return join$1(...paths);
|
|
713
|
-
}
|
|
714
|
-
|
|
715
262
|
createScopedLogger('project-scope:fs:traversal');
|
|
716
263
|
|
|
264
|
+
createScopedLogger('project-scope:fs:write');
|
|
265
|
+
|
|
717
266
|
const packageLogger = createScopedLogger('project-scope:project:package');
|
|
718
267
|
/**
|
|
719
268
|
* Verifies that a value is an object with only string values,
|
|
@@ -783,6 +332,16 @@ function validatePackageJson(data) {
|
|
|
783
332
|
*
|
|
784
333
|
* @param projectPath - Project directory path or path to package.json
|
|
785
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
|
+
* ```
|
|
786
345
|
*/
|
|
787
346
|
function readPackageJsonIfExists(projectPath) {
|
|
788
347
|
const packageJsonPath = projectPath.endsWith('package.json') ? projectPath : join$1(projectPath, 'package.json');
|
|
@@ -803,228 +362,46 @@ function readPackageJsonIfExists(projectPath) {
|
|
|
803
362
|
}
|
|
804
363
|
|
|
805
364
|
/**
|
|
806
|
-
*
|
|
807
|
-
*/
|
|
808
|
-
const cacheRegistry = createSet();
|
|
809
|
-
/**
|
|
810
|
-
* Create a cache with optional TTL and size limits.
|
|
811
|
-
*
|
|
812
|
-
* The cache provides a simple key-value store with:
|
|
813
|
-
* - Optional TTL (time-to-live) for automatic expiration
|
|
814
|
-
* - Optional maxSize for limiting cache size with FIFO eviction
|
|
815
|
-
* - Lazy expiration (entries are checked on access)
|
|
816
|
-
*
|
|
817
|
-
* @param options - Cache configuration options
|
|
818
|
-
* @returns Cache instance
|
|
365
|
+
* Detect Express in project.
|
|
819
366
|
*
|
|
820
|
-
* @
|
|
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
|
|
821
371
|
* ```typescript
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
*
|
|
826
|
-
*
|
|
827
|
-
* // Cache with TTL (expires after 60 seconds)
|
|
828
|
-
* const ttlCache = createCache<string, object>({ ttl: 60000 })
|
|
829
|
-
*
|
|
830
|
-
* // Cache with max size (evicts oldest when full)
|
|
831
|
-
* const lruCache = createCache<string, object>({ maxSize: 100 })
|
|
372
|
+
* const pkg = {
|
|
373
|
+
* dependencies: { express: '^4.18.2', cors: '^2.8.5' },
|
|
374
|
+
* devDependencies: { '@types/express': '^4.17.17' },
|
|
375
|
+
* }
|
|
832
376
|
*
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
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
|
+
* // }
|
|
838
389
|
* ```
|
|
839
390
|
*/
|
|
840
|
-
function
|
|
841
|
-
const
|
|
842
|
-
const
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
*/
|
|
851
|
-
function isExpired(entry) {
|
|
852
|
-
if (ttl === undefined)
|
|
853
|
-
return false;
|
|
854
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
855
|
-
return Date.now() - entry.timestamp > ttl;
|
|
856
|
-
}
|
|
857
|
-
/**
|
|
858
|
-
* Evict oldest entries to make room for new ones.
|
|
859
|
-
*/
|
|
860
|
-
function evictIfNeeded() {
|
|
861
|
-
if (maxSize === undefined)
|
|
862
|
-
return;
|
|
863
|
-
while (store.size >= maxSize && insertionOrder.length > 0) {
|
|
864
|
-
const oldestKey = insertionOrder.shift();
|
|
865
|
-
if (oldestKey !== undefined) {
|
|
866
|
-
store.delete(oldestKey);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
391
|
+
function expressDetector(projectPath, packageJson) {
|
|
392
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
393
|
+
const sources = [];
|
|
394
|
+
let confidence = 0;
|
|
395
|
+
let version;
|
|
396
|
+
const deps = collectAllDependencies(pkg);
|
|
397
|
+
if (deps['express']) {
|
|
398
|
+
confidence += 80;
|
|
399
|
+
version = parseVersionString(deps['express']);
|
|
400
|
+
sources.push({ type: 'package.json', field: 'dependencies.express' });
|
|
869
401
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
* @param key - Key to remove from order tracking
|
|
874
|
-
*/
|
|
875
|
-
function removeFromOrder(key) {
|
|
876
|
-
const index = insertionOrder.indexOf(key);
|
|
877
|
-
if (index !== -1) {
|
|
878
|
-
insertionOrder.splice(index, 1);
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
const cache = {
|
|
882
|
-
get(key) {
|
|
883
|
-
const entry = store.get(key);
|
|
884
|
-
if (!entry)
|
|
885
|
-
return undefined;
|
|
886
|
-
if (isExpired(entry)) {
|
|
887
|
-
store.delete(key);
|
|
888
|
-
removeFromOrder(key);
|
|
889
|
-
return undefined;
|
|
890
|
-
}
|
|
891
|
-
return entry.value;
|
|
892
|
-
},
|
|
893
|
-
set(key, value) {
|
|
894
|
-
// If key exists, remove from order first
|
|
895
|
-
if (store.has(key)) {
|
|
896
|
-
removeFromOrder(key);
|
|
897
|
-
}
|
|
898
|
-
else {
|
|
899
|
-
// Evict if needed before adding new entry
|
|
900
|
-
evictIfNeeded();
|
|
901
|
-
}
|
|
902
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
903
|
-
store.set(key, { value, timestamp: Date.now() });
|
|
904
|
-
insertionOrder.push(key);
|
|
905
|
-
},
|
|
906
|
-
has(key) {
|
|
907
|
-
const entry = store.get(key);
|
|
908
|
-
if (!entry)
|
|
909
|
-
return false;
|
|
910
|
-
if (isExpired(entry)) {
|
|
911
|
-
store.delete(key);
|
|
912
|
-
removeFromOrder(key);
|
|
913
|
-
return false;
|
|
914
|
-
}
|
|
915
|
-
return true;
|
|
916
|
-
},
|
|
917
|
-
delete(key) {
|
|
918
|
-
removeFromOrder(key);
|
|
919
|
-
return store.delete(key);
|
|
920
|
-
},
|
|
921
|
-
clear() {
|
|
922
|
-
store.clear();
|
|
923
|
-
insertionOrder.length = 0;
|
|
924
|
-
},
|
|
925
|
-
size() {
|
|
926
|
-
return store.size;
|
|
927
|
-
},
|
|
928
|
-
keys() {
|
|
929
|
-
return [...insertionOrder];
|
|
930
|
-
},
|
|
931
|
-
};
|
|
932
|
-
// Register cache for global operations
|
|
933
|
-
cacheRegistry.add(cache);
|
|
934
|
-
return freeze(cache);
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
/**
|
|
938
|
-
* Get combined dependencies from package.json.
|
|
939
|
-
* Merges dependencies, devDependencies, peerDependencies, and optionalDependencies.
|
|
940
|
-
*
|
|
941
|
-
* @param packageJson - The package.json object to extract dependencies from
|
|
942
|
-
* @returns Combined dependencies as a single record
|
|
943
|
-
*/
|
|
944
|
-
function collectAllDependencies(packageJson) {
|
|
945
|
-
return {
|
|
946
|
-
...packageJson?.dependencies,
|
|
947
|
-
...packageJson?.devDependencies,
|
|
948
|
-
...packageJson?.peerDependencies,
|
|
949
|
-
...packageJson?.optionalDependencies,
|
|
950
|
-
};
|
|
951
|
-
}
|
|
952
|
-
/**
|
|
953
|
-
* Extract clean version from dependency version string.
|
|
954
|
-
* Removes semver prefixes like ^, ~, >=, etc.
|
|
955
|
-
* Uses character-by-character parsing to avoid ReDoS vulnerabilities.
|
|
956
|
-
*
|
|
957
|
-
* @param versionString - The version string with optional prefix characters
|
|
958
|
-
* @returns The cleaned version string without prefix characters
|
|
959
|
-
*/
|
|
960
|
-
function parseVersionString(versionString) {
|
|
961
|
-
if (versionString === undefined || versionString === null)
|
|
962
|
-
return undefined;
|
|
963
|
-
// Manual parsing instead of regex to avoid ReDoS
|
|
964
|
-
let start = 0;
|
|
965
|
-
while (start < versionString.length) {
|
|
966
|
-
const char = versionString[start];
|
|
967
|
-
if (char !== '^' && char !== '~' && char !== '>' && char !== '=' && char !== '<') {
|
|
968
|
-
break;
|
|
969
|
-
}
|
|
970
|
-
start++;
|
|
971
|
-
}
|
|
972
|
-
return versionString.slice(start);
|
|
973
|
-
}
|
|
974
|
-
/**
|
|
975
|
-
* Find first matching config file in project.
|
|
976
|
-
* Note: Name avoids similarity to fs.readFile/fs.readFileSync.
|
|
977
|
-
*
|
|
978
|
-
* @param projectPath - The project directory path
|
|
979
|
-
* @param patterns - Array of config file patterns to search for
|
|
980
|
-
* @returns The first matching config file path or undefined
|
|
981
|
-
*/
|
|
982
|
-
function locateConfigFile(projectPath, patterns) {
|
|
983
|
-
for (const pattern of patterns) {
|
|
984
|
-
const fullPath = join(projectPath, pattern);
|
|
985
|
-
if (exists(fullPath)) {
|
|
986
|
-
return pattern;
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
return undefined;
|
|
990
|
-
}
|
|
991
|
-
/**
|
|
992
|
-
* Find scripts containing a specific command.
|
|
993
|
-
*
|
|
994
|
-
* @param scripts - The scripts object from package.json
|
|
995
|
-
* @param command - The command string to search for
|
|
996
|
-
* @returns Array of script names that contain the command
|
|
997
|
-
*/
|
|
998
|
-
function filterScriptsByCommand(scripts, command) {
|
|
999
|
-
if (!scripts)
|
|
1000
|
-
return [];
|
|
1001
|
-
return entries(scripts)
|
|
1002
|
-
.filter(([, script]) => script.includes(command))
|
|
1003
|
-
.map(([name]) => name);
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
/**
|
|
1007
|
-
* Detect Express in project.
|
|
1008
|
-
*
|
|
1009
|
-
* @param projectPath - Project directory path
|
|
1010
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
1011
|
-
* @returns Detection result or null if not detected
|
|
1012
|
-
*/
|
|
1013
|
-
function expressDetector(projectPath, packageJson) {
|
|
1014
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1015
|
-
const sources = [];
|
|
1016
|
-
let confidence = 0;
|
|
1017
|
-
let version;
|
|
1018
|
-
const deps = collectAllDependencies(pkg);
|
|
1019
|
-
if (deps['express']) {
|
|
1020
|
-
confidence += 80;
|
|
1021
|
-
version = parseVersionString(deps['express']);
|
|
1022
|
-
sources.push({ type: 'package.json', field: 'dependencies.express' });
|
|
1023
|
-
}
|
|
1024
|
-
// @types/express (indicates usage)
|
|
1025
|
-
if (deps['@types/express']) {
|
|
1026
|
-
confidence += 10;
|
|
1027
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/express' });
|
|
402
|
+
if (deps['@types/express']) {
|
|
403
|
+
confidence += 10;
|
|
404
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/express' });
|
|
1028
405
|
}
|
|
1029
406
|
const expressMiddleware = keys(deps).filter((d) => d.includes('express-') || d === 'body-parser' || d === 'cors' || d === 'helmet' || d === 'morgan');
|
|
1030
407
|
if (expressMiddleware.length > 0) {
|
|
@@ -1044,87 +421,109 @@ function expressDetector(projectPath, packageJson) {
|
|
|
1044
421
|
}
|
|
1045
422
|
|
|
1046
423
|
/**
|
|
1047
|
-
* Detect
|
|
424
|
+
* Detect Fastify in project.
|
|
1048
425
|
*
|
|
1049
426
|
* @param projectPath - Project directory path
|
|
1050
427
|
* @param packageJson - Optional pre-loaded package.json
|
|
1051
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
|
+
* ```
|
|
1052
447
|
*/
|
|
1053
|
-
function
|
|
448
|
+
function fastifyDetector(projectPath, packageJson) {
|
|
1054
449
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1055
450
|
const sources = [];
|
|
1056
451
|
let confidence = 0;
|
|
1057
452
|
let version;
|
|
1058
|
-
let configPath;
|
|
1059
453
|
const deps = collectAllDependencies(pkg);
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
|
|
1065
|
-
}
|
|
1066
|
-
// @nestjs/common
|
|
1067
|
-
if (deps['@nestjs/common']) {
|
|
1068
|
-
confidence += 15;
|
|
1069
|
-
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' });
|
|
1070
458
|
}
|
|
1071
|
-
|
|
459
|
+
const fastifyPlugins = keys(deps).filter((d) => d.startsWith('@fastify/') || d.startsWith('fastify-'));
|
|
460
|
+
if (fastifyPlugins.length > 0) {
|
|
1072
461
|
confidence += 15;
|
|
1073
|
-
|
|
1074
|
-
sources.push({ type: 'config-file', path: 'nest-cli.json' });
|
|
462
|
+
sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
|
|
1075
463
|
}
|
|
1076
|
-
|
|
1077
|
-
if (nestPackages.length > 2) {
|
|
464
|
+
if (deps['@types/fastify']) {
|
|
1078
465
|
confidence += 5;
|
|
1079
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
466
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
1080
467
|
}
|
|
1081
468
|
if (confidence === 0) {
|
|
1082
469
|
return null;
|
|
1083
470
|
}
|
|
1084
471
|
return {
|
|
1085
|
-
id: '
|
|
1086
|
-
name: '
|
|
472
|
+
id: 'fastify',
|
|
473
|
+
name: 'Fastify',
|
|
1087
474
|
version,
|
|
1088
|
-
configPath,
|
|
1089
475
|
confidence: min(confidence, 100),
|
|
1090
476
|
detectedFrom: sources,
|
|
1091
477
|
};
|
|
1092
478
|
}
|
|
1093
479
|
|
|
1094
480
|
/**
|
|
1095
|
-
* Detect
|
|
481
|
+
* Detect Hono in project.
|
|
1096
482
|
*
|
|
1097
483
|
* @param projectPath - Project directory path
|
|
1098
484
|
* @param packageJson - Optional pre-loaded package.json
|
|
1099
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
|
+
* ```
|
|
1100
504
|
*/
|
|
1101
|
-
function
|
|
505
|
+
function honoDetector(projectPath, packageJson) {
|
|
1102
506
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1103
507
|
const sources = [];
|
|
1104
508
|
let confidence = 0;
|
|
1105
509
|
let version;
|
|
1106
510
|
const deps = collectAllDependencies(pkg);
|
|
1107
|
-
if (deps['
|
|
1108
|
-
confidence +=
|
|
1109
|
-
version = parseVersionString(deps['
|
|
1110
|
-
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' });
|
|
1111
515
|
}
|
|
1112
|
-
const
|
|
1113
|
-
if (
|
|
516
|
+
const honoAdapters = keys(deps).filter((d) => d.startsWith('@hono/'));
|
|
517
|
+
if (honoAdapters.length > 0) {
|
|
1114
518
|
confidence += 15;
|
|
1115
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1116
|
-
}
|
|
1117
|
-
// @types/fastify (older versions)
|
|
1118
|
-
if (deps['@types/fastify']) {
|
|
1119
|
-
confidence += 5;
|
|
1120
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
519
|
+
sources.push({ type: 'package.json', field: 'dependencies (@hono adapters)' });
|
|
1121
520
|
}
|
|
1122
521
|
if (confidence === 0) {
|
|
1123
522
|
return null;
|
|
1124
523
|
}
|
|
1125
524
|
return {
|
|
1126
|
-
id: '
|
|
1127
|
-
name: '
|
|
525
|
+
id: 'hono',
|
|
526
|
+
name: 'Hono',
|
|
1128
527
|
version,
|
|
1129
528
|
confidence: min(confidence, 100),
|
|
1130
529
|
detectedFrom: sources,
|
|
@@ -1137,6 +536,26 @@ function fastifyDetector(projectPath, packageJson) {
|
|
|
1137
536
|
* @param projectPath - Project directory path
|
|
1138
537
|
* @param packageJson - Optional pre-loaded package.json
|
|
1139
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
|
+
* ```
|
|
1140
559
|
*/
|
|
1141
560
|
function koaDetector(projectPath, packageJson) {
|
|
1142
561
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1149,7 +568,6 @@ function koaDetector(projectPath, packageJson) {
|
|
|
1149
568
|
version = parseVersionString(deps['koa']);
|
|
1150
569
|
sources.push({ type: 'package.json', field: 'dependencies.koa' });
|
|
1151
570
|
}
|
|
1152
|
-
// @types/koa
|
|
1153
571
|
if (deps['@types/koa']) {
|
|
1154
572
|
confidence += 10;
|
|
1155
573
|
sources.push({ type: 'package.json', field: 'dependencies.@types/koa' });
|
|
@@ -1172,35 +590,72 @@ function koaDetector(projectPath, packageJson) {
|
|
|
1172
590
|
}
|
|
1173
591
|
|
|
1174
592
|
/**
|
|
1175
|
-
* Detect
|
|
593
|
+
* Detect NestJS in project.
|
|
1176
594
|
*
|
|
1177
595
|
* @param projectPath - Project directory path
|
|
1178
596
|
* @param packageJson - Optional pre-loaded package.json
|
|
1179
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
|
+
* ```
|
|
1180
624
|
*/
|
|
1181
|
-
function
|
|
625
|
+
function nestDetector(projectPath, packageJson) {
|
|
1182
626
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1183
627
|
const sources = [];
|
|
1184
628
|
let confidence = 0;
|
|
1185
629
|
let version;
|
|
630
|
+
let configPath;
|
|
1186
631
|
const deps = collectAllDependencies(pkg);
|
|
1187
|
-
if (deps['
|
|
1188
|
-
confidence +=
|
|
1189
|
-
version = parseVersionString(deps['
|
|
1190
|
-
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' });
|
|
1191
636
|
}
|
|
1192
|
-
|
|
1193
|
-
if (honoAdapters.length > 0) {
|
|
637
|
+
if (deps['@nestjs/common']) {
|
|
1194
638
|
confidence += 15;
|
|
1195
|
-
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)' });
|
|
1196
650
|
}
|
|
1197
651
|
if (confidence === 0) {
|
|
1198
652
|
return null;
|
|
1199
653
|
}
|
|
1200
654
|
return {
|
|
1201
|
-
id: '
|
|
1202
|
-
name: '
|
|
655
|
+
id: 'nestjs',
|
|
656
|
+
name: 'NestJS',
|
|
1203
657
|
version,
|
|
658
|
+
configPath,
|
|
1204
659
|
confidence: min(confidence, 100),
|
|
1205
660
|
detectedFrom: sources,
|
|
1206
661
|
};
|
|
@@ -1215,52 +670,64 @@ const backendDetectors = [
|
|
|
1215
670
|
{ id: 'hono', name: 'Hono', detect: honoDetector },
|
|
1216
671
|
];
|
|
1217
672
|
|
|
1218
|
-
/** Config patterns for
|
|
1219
|
-
const
|
|
1220
|
-
'webpack.config.js',
|
|
1221
|
-
'webpack.config.ts',
|
|
1222
|
-
'webpack.config.cjs',
|
|
1223
|
-
'webpack.config.mjs',
|
|
1224
|
-
'webpack.config.babel.js',
|
|
1225
|
-
];
|
|
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'];
|
|
1226
675
|
/**
|
|
1227
|
-
* Detect
|
|
676
|
+
* Detect Babel in project.
|
|
1228
677
|
*
|
|
1229
678
|
* @param projectPath - Project directory path
|
|
1230
679
|
* @param packageJson - Optional pre-loaded package.json
|
|
1231
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
|
+
* ```
|
|
1232
699
|
*/
|
|
1233
|
-
function
|
|
700
|
+
function babelDetector(projectPath, packageJson) {
|
|
1234
701
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1235
702
|
const sources = [];
|
|
1236
703
|
let confidence = 0;
|
|
1237
704
|
let version;
|
|
1238
705
|
const deps = collectAllDependencies(pkg);
|
|
1239
|
-
if (deps['
|
|
706
|
+
if (deps['@babel/core']) {
|
|
1240
707
|
confidence += 50;
|
|
1241
|
-
version = parseVersionString(deps['
|
|
1242
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
708
|
+
version = parseVersionString(deps['@babel/core']);
|
|
709
|
+
sources.push({ type: 'package.json', field: 'dependencies.@babel/core' });
|
|
1243
710
|
}
|
|
1244
|
-
const configPath = locateConfigFile(projectPath,
|
|
711
|
+
const configPath = locateConfigFile(projectPath, BABEL_CONFIG_PATTERNS);
|
|
1245
712
|
if (configPath) {
|
|
1246
713
|
confidence += 40;
|
|
1247
714
|
sources.push({ type: 'config-file', path: configPath });
|
|
1248
715
|
}
|
|
1249
|
-
if (
|
|
1250
|
-
confidence +=
|
|
1251
|
-
sources.push({ type: 'package.json', field: '
|
|
716
|
+
if (pkg && 'babel' in pkg) {
|
|
717
|
+
confidence += 30;
|
|
718
|
+
sources.push({ type: 'package.json', field: 'babel' });
|
|
1252
719
|
}
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
confidence
|
|
1256
|
-
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)' });
|
|
1257
724
|
}
|
|
1258
725
|
if (confidence === 0) {
|
|
1259
726
|
return null;
|
|
1260
727
|
}
|
|
1261
728
|
return {
|
|
1262
|
-
id: '
|
|
1263
|
-
name: '
|
|
729
|
+
id: 'babel',
|
|
730
|
+
name: 'Babel',
|
|
1264
731
|
version,
|
|
1265
732
|
configPath,
|
|
1266
733
|
confidence: min(confidence, 100),
|
|
@@ -1268,94 +735,126 @@ function webpackDetector(projectPath, packageJson) {
|
|
|
1268
735
|
};
|
|
1269
736
|
}
|
|
1270
737
|
|
|
1271
|
-
/** Config patterns for Vite */
|
|
1272
|
-
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
1273
738
|
/**
|
|
1274
|
-
* Detect
|
|
739
|
+
* Detect esbuild in project.
|
|
1275
740
|
*
|
|
1276
741
|
* @param projectPath - Project directory path
|
|
1277
742
|
* @param packageJson - Optional pre-loaded package.json
|
|
1278
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
|
+
* ```
|
|
1279
763
|
*/
|
|
1280
|
-
function
|
|
764
|
+
function esbuildDetector(projectPath, packageJson) {
|
|
1281
765
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1282
766
|
const sources = [];
|
|
1283
767
|
let confidence = 0;
|
|
1284
768
|
let version;
|
|
1285
769
|
const deps = collectAllDependencies(pkg);
|
|
1286
|
-
if (deps['
|
|
1287
|
-
confidence +=
|
|
1288
|
-
version = parseVersionString(deps['
|
|
1289
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1290
|
-
}
|
|
1291
|
-
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
1292
|
-
if (configPath) {
|
|
1293
|
-
confidence += 35;
|
|
1294
|
-
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' });
|
|
1295
774
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
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)' });
|
|
1299
779
|
}
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
confidence
|
|
1303
|
-
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}` });
|
|
1304
784
|
}
|
|
1305
785
|
if (confidence === 0) {
|
|
1306
786
|
return null;
|
|
1307
787
|
}
|
|
1308
788
|
return {
|
|
1309
|
-
id: '
|
|
1310
|
-
name: '
|
|
789
|
+
id: 'esbuild',
|
|
790
|
+
name: 'esbuild',
|
|
1311
791
|
version,
|
|
1312
|
-
configPath,
|
|
1313
792
|
confidence: min(confidence, 100),
|
|
1314
793
|
detectedFrom: sources,
|
|
1315
794
|
};
|
|
1316
795
|
}
|
|
1317
796
|
|
|
1318
|
-
/** Config patterns for
|
|
1319
|
-
const
|
|
797
|
+
/** Config patterns for Parcel */
|
|
798
|
+
const PARCEL_CONFIG_PATTERNS = ['.parcelrc'];
|
|
1320
799
|
/**
|
|
1321
|
-
* Detect
|
|
800
|
+
* Detect Parcel in project.
|
|
1322
801
|
*
|
|
1323
802
|
* @param projectPath - Project directory path
|
|
1324
803
|
* @param packageJson - Optional pre-loaded package.json
|
|
1325
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
|
+
* ```
|
|
1326
825
|
*/
|
|
1327
|
-
function
|
|
826
|
+
function parcelDetector(projectPath, packageJson) {
|
|
1328
827
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1329
828
|
const sources = [];
|
|
1330
829
|
let confidence = 0;
|
|
1331
830
|
let version;
|
|
1332
831
|
const deps = collectAllDependencies(pkg);
|
|
1333
|
-
if (deps['
|
|
1334
|
-
confidence +=
|
|
1335
|
-
version = parseVersionString(deps['
|
|
1336
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1337
|
-
}
|
|
1338
|
-
|
|
832
|
+
if (deps['parcel']) {
|
|
833
|
+
confidence += 60;
|
|
834
|
+
version = parseVersionString(deps['parcel']);
|
|
835
|
+
sources.push({ type: 'package.json', field: 'dependencies.parcel' });
|
|
836
|
+
}
|
|
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);
|
|
1339
843
|
if (configPath) {
|
|
1340
|
-
confidence +=
|
|
844
|
+
confidence += 30;
|
|
1341
845
|
sources.push({ type: 'config-file', path: configPath });
|
|
1342
846
|
}
|
|
1343
|
-
const
|
|
1344
|
-
if (rollupPlugins.length > 0) {
|
|
1345
|
-
confidence += 10;
|
|
1346
|
-
sources.push({ type: 'package.json', field: 'dependencies (rollup plugins)' });
|
|
1347
|
-
}
|
|
1348
|
-
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'rollup');
|
|
847
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'parcel');
|
|
1349
848
|
for (const name of scriptMatches) {
|
|
1350
|
-
confidence = min(confidence +
|
|
849
|
+
confidence = min(confidence + 10, 100);
|
|
1351
850
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1352
851
|
}
|
|
1353
852
|
if (confidence === 0) {
|
|
1354
853
|
return null;
|
|
1355
854
|
}
|
|
1356
855
|
return {
|
|
1357
|
-
id: '
|
|
1358
|
-
name: '
|
|
856
|
+
id: 'parcel',
|
|
857
|
+
name: 'Parcel',
|
|
1359
858
|
version,
|
|
1360
859
|
configPath,
|
|
1361
860
|
confidence: min(confidence, 100),
|
|
@@ -1363,86 +862,134 @@ function rollupDetector(projectPath, packageJson) {
|
|
|
1363
862
|
};
|
|
1364
863
|
}
|
|
1365
864
|
|
|
865
|
+
/** Config patterns for Rollup */
|
|
866
|
+
const ROLLUP_CONFIG_PATTERNS = ['rollup.config.js', 'rollup.config.ts', 'rollup.config.mjs', 'rollup.config.cjs'];
|
|
1366
867
|
/**
|
|
1367
|
-
* Detect
|
|
868
|
+
* Detect Rollup in project.
|
|
1368
869
|
*
|
|
1369
870
|
* @param projectPath - Project directory path
|
|
1370
871
|
* @param packageJson - Optional pre-loaded package.json
|
|
1371
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
|
+
* ```
|
|
1372
895
|
*/
|
|
1373
|
-
function
|
|
896
|
+
function rollupDetector(projectPath, packageJson) {
|
|
1374
897
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1375
898
|
const sources = [];
|
|
1376
899
|
let confidence = 0;
|
|
1377
900
|
let version;
|
|
1378
901
|
const deps = collectAllDependencies(pkg);
|
|
1379
|
-
if (deps['
|
|
1380
|
-
confidence +=
|
|
1381
|
-
version = parseVersionString(deps['
|
|
1382
|
-
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' });
|
|
1383
906
|
}
|
|
1384
|
-
const
|
|
1385
|
-
if (
|
|
1386
|
-
confidence +=
|
|
1387
|
-
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 });
|
|
1388
911
|
}
|
|
1389
|
-
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');
|
|
1390
918
|
for (const name of scriptMatches) {
|
|
1391
|
-
confidence = min(confidence +
|
|
919
|
+
confidence = min(confidence + 5, 100);
|
|
1392
920
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1393
921
|
}
|
|
1394
922
|
if (confidence === 0) {
|
|
1395
923
|
return null;
|
|
1396
924
|
}
|
|
1397
925
|
return {
|
|
1398
|
-
id: '
|
|
1399
|
-
name: '
|
|
926
|
+
id: 'rollup',
|
|
927
|
+
name: 'Rollup',
|
|
1400
928
|
version,
|
|
929
|
+
configPath,
|
|
1401
930
|
confidence: min(confidence, 100),
|
|
1402
931
|
detectedFrom: sources,
|
|
1403
932
|
};
|
|
1404
933
|
}
|
|
1405
934
|
|
|
1406
|
-
/** Config patterns for
|
|
1407
|
-
const
|
|
935
|
+
/** Config patterns for SWC */
|
|
936
|
+
const SWC_CONFIG_PATTERNS = ['.swcrc', 'swc.config.js'];
|
|
1408
937
|
/**
|
|
1409
|
-
* Detect
|
|
938
|
+
* Detect SWC in project.
|
|
1410
939
|
*
|
|
1411
940
|
* @param projectPath - Project directory path
|
|
1412
941
|
* @param packageJson - Optional pre-loaded package.json
|
|
1413
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
|
+
* ```
|
|
1414
961
|
*/
|
|
1415
|
-
function
|
|
962
|
+
function swcDetector(projectPath, packageJson) {
|
|
1416
963
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1417
964
|
const sources = [];
|
|
1418
965
|
let confidence = 0;
|
|
1419
966
|
let version;
|
|
1420
967
|
const deps = collectAllDependencies(pkg);
|
|
1421
|
-
if (deps['@
|
|
1422
|
-
confidence +=
|
|
1423
|
-
version = parseVersionString(deps['@
|
|
1424
|
-
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' });
|
|
1425
972
|
}
|
|
1426
|
-
const configPath = locateConfigFile(projectPath,
|
|
973
|
+
const configPath = locateConfigFile(projectPath, SWC_CONFIG_PATTERNS);
|
|
1427
974
|
if (configPath) {
|
|
1428
|
-
confidence +=
|
|
975
|
+
confidence += 35;
|
|
1429
976
|
sources.push({ type: 'config-file', path: configPath });
|
|
1430
977
|
}
|
|
1431
|
-
if (
|
|
1432
|
-
confidence += 30;
|
|
1433
|
-
sources.push({ type: 'package.json', field: 'babel' });
|
|
1434
|
-
}
|
|
1435
|
-
const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
1436
|
-
if (babelPackages.length > 1) {
|
|
978
|
+
if (deps['@swc/cli']) {
|
|
1437
979
|
confidence += 10;
|
|
1438
|
-
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)' });
|
|
1439
986
|
}
|
|
1440
987
|
if (confidence === 0) {
|
|
1441
988
|
return null;
|
|
1442
989
|
}
|
|
1443
990
|
return {
|
|
1444
|
-
id: '
|
|
1445
|
-
name: '
|
|
991
|
+
id: 'swc',
|
|
992
|
+
name: 'SWC',
|
|
1446
993
|
version,
|
|
1447
994
|
configPath,
|
|
1448
995
|
confidence: min(confidence, 100),
|
|
@@ -1450,46 +997,69 @@ function babelDetector(projectPath, packageJson) {
|
|
|
1450
997
|
};
|
|
1451
998
|
}
|
|
1452
999
|
|
|
1453
|
-
/** Config patterns for
|
|
1454
|
-
const
|
|
1000
|
+
/** Config patterns for Vite */
|
|
1001
|
+
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
1455
1002
|
/**
|
|
1456
|
-
* Detect
|
|
1003
|
+
* Detect Vite in project.
|
|
1457
1004
|
*
|
|
1458
1005
|
* @param projectPath - Project directory path
|
|
1459
1006
|
* @param packageJson - Optional pre-loaded package.json
|
|
1460
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
|
+
* ```
|
|
1461
1031
|
*/
|
|
1462
|
-
function
|
|
1032
|
+
function viteDetector(projectPath, packageJson) {
|
|
1463
1033
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1464
1034
|
const sources = [];
|
|
1465
1035
|
let confidence = 0;
|
|
1466
1036
|
let version;
|
|
1467
1037
|
const deps = collectAllDependencies(pkg);
|
|
1468
|
-
if (deps['
|
|
1038
|
+
if (deps['vite']) {
|
|
1469
1039
|
confidence += 60;
|
|
1470
|
-
version = parseVersionString(deps['
|
|
1471
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1040
|
+
version = parseVersionString(deps['vite']);
|
|
1041
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite' });
|
|
1472
1042
|
}
|
|
1473
|
-
const configPath = locateConfigFile(projectPath,
|
|
1043
|
+
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
1474
1044
|
if (configPath) {
|
|
1475
1045
|
confidence += 35;
|
|
1476
1046
|
sources.push({ type: 'config-file', path: configPath });
|
|
1477
1047
|
}
|
|
1478
|
-
if (deps['
|
|
1048
|
+
if (deps['vitest']) {
|
|
1479
1049
|
confidence += 10;
|
|
1480
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1050
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
1481
1051
|
}
|
|
1482
|
-
const
|
|
1483
|
-
if (
|
|
1484
|
-
confidence +=
|
|
1485
|
-
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)' });
|
|
1486
1056
|
}
|
|
1487
1057
|
if (confidence === 0) {
|
|
1488
1058
|
return null;
|
|
1489
1059
|
}
|
|
1490
1060
|
return {
|
|
1491
|
-
id: '
|
|
1492
|
-
name: '
|
|
1061
|
+
id: 'vite',
|
|
1062
|
+
name: 'Vite',
|
|
1493
1063
|
version,
|
|
1494
1064
|
configPath,
|
|
1495
1065
|
confidence: min(confidence, 100),
|
|
@@ -1497,47 +1067,72 @@ function swcDetector(projectPath, packageJson) {
|
|
|
1497
1067
|
};
|
|
1498
1068
|
}
|
|
1499
1069
|
|
|
1500
|
-
/** Config patterns for
|
|
1501
|
-
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
|
+
];
|
|
1502
1078
|
/**
|
|
1503
|
-
* Detect
|
|
1079
|
+
* Detect Webpack in project.
|
|
1504
1080
|
*
|
|
1505
1081
|
* @param projectPath - Project directory path
|
|
1506
1082
|
* @param packageJson - Optional pre-loaded package.json
|
|
1507
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
|
+
* ```
|
|
1508
1104
|
*/
|
|
1509
|
-
function
|
|
1105
|
+
function webpackDetector(projectPath, packageJson) {
|
|
1510
1106
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1511
1107
|
const sources = [];
|
|
1512
1108
|
let confidence = 0;
|
|
1513
1109
|
let version;
|
|
1514
1110
|
const deps = collectAllDependencies(pkg);
|
|
1515
|
-
if (deps['
|
|
1516
|
-
confidence +=
|
|
1517
|
-
version = parseVersionString(deps['
|
|
1518
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1519
|
-
}
|
|
1520
|
-
if (deps['parcel-bundler']) {
|
|
1521
|
-
confidence += 60;
|
|
1522
|
-
version = parseVersionString(deps['parcel-bundler']);
|
|
1523
|
-
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' });
|
|
1524
1115
|
}
|
|
1525
|
-
const configPath = locateConfigFile(projectPath,
|
|
1116
|
+
const configPath = locateConfigFile(projectPath, WEBPACK_CONFIG_PATTERNS);
|
|
1526
1117
|
if (configPath) {
|
|
1527
|
-
confidence +=
|
|
1118
|
+
confidence += 40;
|
|
1528
1119
|
sources.push({ type: 'config-file', path: configPath });
|
|
1529
1120
|
}
|
|
1530
|
-
|
|
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');
|
|
1531
1126
|
for (const name of scriptMatches) {
|
|
1532
|
-
confidence = min(confidence +
|
|
1127
|
+
confidence = min(confidence + 5, 100);
|
|
1533
1128
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1534
1129
|
}
|
|
1535
1130
|
if (confidence === 0) {
|
|
1536
1131
|
return null;
|
|
1537
1132
|
}
|
|
1538
1133
|
return {
|
|
1539
|
-
id: '
|
|
1540
|
-
name: '
|
|
1134
|
+
id: 'webpack',
|
|
1135
|
+
name: 'Webpack',
|
|
1541
1136
|
version,
|
|
1542
1137
|
configPath,
|
|
1543
1138
|
confidence: min(confidence, 100),
|
|
@@ -1557,81 +1152,187 @@ const buildToolDetectors = [
|
|
|
1557
1152
|
];
|
|
1558
1153
|
|
|
1559
1154
|
/**
|
|
1560
|
-
* Detect
|
|
1155
|
+
* Detect Angular in project.
|
|
1561
1156
|
*
|
|
1562
1157
|
* @param projectPath - Project directory path
|
|
1563
1158
|
* @param packageJson - Optional pre-loaded package.json
|
|
1564
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
|
+
* ```
|
|
1565
1178
|
*/
|
|
1566
|
-
function
|
|
1179
|
+
function angularDetector(projectPath, packageJson) {
|
|
1567
1180
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1568
1181
|
const sources = [];
|
|
1569
1182
|
let confidence = 0;
|
|
1570
1183
|
let version;
|
|
1571
|
-
const metaFrameworks = [];
|
|
1572
1184
|
const deps = collectAllDependencies(pkg);
|
|
1573
|
-
if (deps['
|
|
1574
|
-
confidence +=
|
|
1575
|
-
version = parseVersionString(deps['
|
|
1576
|
-
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' });
|
|
1577
1189
|
}
|
|
1578
|
-
if (deps['
|
|
1579
|
-
confidence +=
|
|
1580
|
-
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' });
|
|
1581
1193
|
}
|
|
1582
|
-
if (
|
|
1583
|
-
confidence +=
|
|
1584
|
-
sources.push({ type: '
|
|
1194
|
+
if (exists(join$1(projectPath, 'angular.json'))) {
|
|
1195
|
+
confidence += 15;
|
|
1196
|
+
sources.push({ type: 'config-file', path: 'angular.json' });
|
|
1585
1197
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
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
|
+
};
|
|
1593
1207
|
}
|
|
1594
|
-
if (
|
|
1595
|
-
|
|
1596
|
-
id: 'nextjs',
|
|
1597
|
-
name: 'Next.js',
|
|
1598
|
-
category: 'meta-framework',
|
|
1599
|
-
version: parseVersionString(deps['next']),
|
|
1600
|
-
confidence: 90,
|
|
1601
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }],
|
|
1602
|
-
});
|
|
1208
|
+
if (confidence === 0) {
|
|
1209
|
+
return null;
|
|
1603
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);
|
|
1604
1312
|
if (deps['gatsby']) {
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
category: 'meta-framework',
|
|
1609
|
-
version: parseVersionString(deps['gatsby']),
|
|
1610
|
-
confidence: 90,
|
|
1611
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
1612
|
-
});
|
|
1313
|
+
confidence += 70;
|
|
1314
|
+
version = parseVersionString(deps['gatsby']);
|
|
1315
|
+
sources.push({ type: 'package.json', field: 'dependencies.gatsby' });
|
|
1613
1316
|
}
|
|
1614
|
-
if (
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
});
|
|
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)' });
|
|
1623
1325
|
}
|
|
1624
1326
|
if (confidence === 0) {
|
|
1625
1327
|
return null;
|
|
1626
1328
|
}
|
|
1627
1329
|
return {
|
|
1628
|
-
id: '
|
|
1629
|
-
name: '
|
|
1630
|
-
category: '
|
|
1330
|
+
id: 'gatsby',
|
|
1331
|
+
name: 'Gatsby',
|
|
1332
|
+
category: 'meta-framework',
|
|
1631
1333
|
version,
|
|
1632
1334
|
confidence: min(confidence, 100),
|
|
1633
1335
|
detectedFrom: sources,
|
|
1634
|
-
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
1635
1336
|
};
|
|
1636
1337
|
}
|
|
1637
1338
|
|
|
@@ -1641,6 +1342,21 @@ function reactDetector(projectPath, packageJson) {
|
|
|
1641
1342
|
* @param projectPath - Project directory path
|
|
1642
1343
|
* @param packageJson - Optional pre-loaded package.json
|
|
1643
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
|
+
* ```
|
|
1644
1360
|
*/
|
|
1645
1361
|
function nextjsDetector(projectPath, packageJson) {
|
|
1646
1362
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1680,38 +1396,52 @@ function nextjsDetector(projectPath, packageJson) {
|
|
|
1680
1396
|
}
|
|
1681
1397
|
|
|
1682
1398
|
/**
|
|
1683
|
-
* Detect
|
|
1399
|
+
* Detect Nuxt in project.
|
|
1684
1400
|
*
|
|
1685
1401
|
* @param projectPath - Project directory path
|
|
1686
1402
|
* @param packageJson - Optional pre-loaded package.json
|
|
1687
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
|
+
* ```
|
|
1688
1419
|
*/
|
|
1689
|
-
function
|
|
1420
|
+
function nuxtDetector(projectPath, packageJson) {
|
|
1690
1421
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1691
1422
|
const sources = [];
|
|
1692
1423
|
let confidence = 0;
|
|
1693
1424
|
let version;
|
|
1694
1425
|
const deps = collectAllDependencies(pkg);
|
|
1695
|
-
|
|
1696
|
-
if (deps['@remix-run/react']) {
|
|
1426
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
1697
1427
|
confidence += 70;
|
|
1698
|
-
version = parseVersionString(deps['
|
|
1699
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1428
|
+
version = parseVersionString(deps['nuxt'] ?? deps['nuxt3']);
|
|
1429
|
+
sources.push({ type: 'package.json', field: 'dependencies.nuxt' });
|
|
1700
1430
|
}
|
|
1701
|
-
if (
|
|
1702
|
-
confidence +=
|
|
1703
|
-
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.*' });
|
|
1704
1434
|
}
|
|
1705
|
-
if (exists(join$1(projectPath, '
|
|
1706
|
-
confidence +=
|
|
1707
|
-
sources.push({ type: '
|
|
1435
|
+
if (exists(join$1(projectPath, 'pages'))) {
|
|
1436
|
+
confidence += 5;
|
|
1437
|
+
sources.push({ type: 'directory', path: 'pages/' });
|
|
1708
1438
|
}
|
|
1709
1439
|
if (confidence === 0) {
|
|
1710
1440
|
return null;
|
|
1711
1441
|
}
|
|
1712
1442
|
return {
|
|
1713
|
-
id: '
|
|
1714
|
-
name: '
|
|
1443
|
+
id: 'nuxt',
|
|
1444
|
+
name: 'Nuxt',
|
|
1715
1445
|
category: 'meta-framework',
|
|
1716
1446
|
version,
|
|
1717
1447
|
confidence: min(confidence, 100),
|
|
@@ -1720,39 +1450,59 @@ function remixDetector(projectPath, packageJson) {
|
|
|
1720
1450
|
}
|
|
1721
1451
|
|
|
1722
1452
|
/**
|
|
1723
|
-
* Detect
|
|
1453
|
+
* Detect Qwik in project.
|
|
1724
1454
|
*
|
|
1725
1455
|
* @param projectPath - Project directory path
|
|
1726
1456
|
* @param packageJson - Optional pre-loaded package.json
|
|
1727
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
|
+
* ```
|
|
1728
1479
|
*/
|
|
1729
|
-
function
|
|
1480
|
+
function qwikDetector(projectPath, packageJson) {
|
|
1730
1481
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1731
1482
|
const sources = [];
|
|
1732
1483
|
let confidence = 0;
|
|
1733
1484
|
let version;
|
|
1734
1485
|
const deps = collectAllDependencies(pkg);
|
|
1735
|
-
if (deps['
|
|
1486
|
+
if (deps['@builder.io/qwik']) {
|
|
1736
1487
|
confidence += 70;
|
|
1737
|
-
version = parseVersionString(deps['
|
|
1738
|
-
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' });
|
|
1739
1490
|
}
|
|
1740
|
-
if (
|
|
1741
|
-
confidence +=
|
|
1742
|
-
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' });
|
|
1743
1494
|
}
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
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.*' });
|
|
1748
1498
|
}
|
|
1749
1499
|
if (confidence === 0) {
|
|
1750
1500
|
return null;
|
|
1751
1501
|
}
|
|
1752
1502
|
return {
|
|
1753
|
-
id: '
|
|
1754
|
-
name: '
|
|
1755
|
-
category: '
|
|
1503
|
+
id: 'qwik',
|
|
1504
|
+
name: 'Qwik',
|
|
1505
|
+
category: 'frontend',
|
|
1756
1506
|
version,
|
|
1757
1507
|
confidence: min(confidence, 100),
|
|
1758
1508
|
detectedFrom: sources,
|
|
@@ -1760,53 +1510,94 @@ function gatsbyDetector(projectPath, packageJson) {
|
|
|
1760
1510
|
}
|
|
1761
1511
|
|
|
1762
1512
|
/**
|
|
1763
|
-
* Detect
|
|
1513
|
+
* Detect React in project.
|
|
1764
1514
|
*
|
|
1765
1515
|
* @param projectPath - Project directory path
|
|
1766
1516
|
* @param packageJson - Optional pre-loaded package.json
|
|
1767
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
|
+
* ```
|
|
1768
1536
|
*/
|
|
1769
|
-
function
|
|
1537
|
+
function reactDetector(projectPath, packageJson) {
|
|
1770
1538
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1771
1539
|
const sources = [];
|
|
1772
1540
|
let confidence = 0;
|
|
1773
1541
|
let version;
|
|
1774
1542
|
const metaFrameworks = [];
|
|
1775
1543
|
const deps = collectAllDependencies(pkg);
|
|
1776
|
-
if (deps['
|
|
1777
|
-
confidence +=
|
|
1778
|
-
version = parseVersionString(deps['
|
|
1779
|
-
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' });
|
|
1780
1548
|
}
|
|
1781
|
-
if (deps['
|
|
1782
|
-
confidence +=
|
|
1783
|
-
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' });
|
|
1784
1552
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
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) {
|
|
1787
1562
|
confidence += 10;
|
|
1788
|
-
sources.push({ type: 'directory', path: 'src/*.
|
|
1563
|
+
sources.push({ type: 'directory', path: 'src/*.tsx or src/*.jsx' });
|
|
1789
1564
|
}
|
|
1790
|
-
if (
|
|
1791
|
-
|
|
1792
|
-
|
|
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
|
+
});
|
|
1793
1574
|
}
|
|
1794
|
-
if (deps['
|
|
1575
|
+
if (deps['gatsby']) {
|
|
1795
1576
|
metaFrameworks.push({
|
|
1796
|
-
id: '
|
|
1797
|
-
name: '
|
|
1577
|
+
id: 'gatsby',
|
|
1578
|
+
name: 'Gatsby',
|
|
1798
1579
|
category: 'meta-framework',
|
|
1799
|
-
version: parseVersionString(deps['
|
|
1580
|
+
version: parseVersionString(deps['gatsby']),
|
|
1800
1581
|
confidence: 90,
|
|
1801
|
-
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' }],
|
|
1802
1593
|
});
|
|
1803
1594
|
}
|
|
1804
1595
|
if (confidence === 0) {
|
|
1805
1596
|
return null;
|
|
1806
1597
|
}
|
|
1807
1598
|
return {
|
|
1808
|
-
id: '
|
|
1809
|
-
name: '
|
|
1599
|
+
id: 'react',
|
|
1600
|
+
name: 'React',
|
|
1810
1601
|
category: 'frontend',
|
|
1811
1602
|
version,
|
|
1812
1603
|
confidence: min(confidence, 100),
|
|
@@ -1816,37 +1607,58 @@ function vueDetector(projectPath, packageJson) {
|
|
|
1816
1607
|
}
|
|
1817
1608
|
|
|
1818
1609
|
/**
|
|
1819
|
-
* Detect
|
|
1610
|
+
* Detect Remix in project.
|
|
1820
1611
|
*
|
|
1821
1612
|
* @param projectPath - Project directory path
|
|
1822
1613
|
* @param packageJson - Optional pre-loaded package.json
|
|
1823
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
|
+
* ```
|
|
1824
1636
|
*/
|
|
1825
|
-
function
|
|
1637
|
+
function remixDetector(projectPath, packageJson) {
|
|
1826
1638
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1827
1639
|
const sources = [];
|
|
1828
1640
|
let confidence = 0;
|
|
1829
1641
|
let version;
|
|
1830
1642
|
const deps = collectAllDependencies(pkg);
|
|
1831
|
-
if (deps['
|
|
1643
|
+
if (deps['@remix-run/react']) {
|
|
1832
1644
|
confidence += 70;
|
|
1833
|
-
version = parseVersionString(deps['
|
|
1834
|
-
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' });
|
|
1835
1647
|
}
|
|
1836
|
-
if (
|
|
1837
|
-
confidence +=
|
|
1838
|
-
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/*' });
|
|
1839
1651
|
}
|
|
1840
|
-
if (exists(join$1(projectPath, '
|
|
1841
|
-
confidence +=
|
|
1842
|
-
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.*' });
|
|
1843
1655
|
}
|
|
1844
1656
|
if (confidence === 0) {
|
|
1845
1657
|
return null;
|
|
1846
1658
|
}
|
|
1847
1659
|
return {
|
|
1848
|
-
id: '
|
|
1849
|
-
name: '
|
|
1660
|
+
id: 'remix',
|
|
1661
|
+
name: 'Remix',
|
|
1850
1662
|
category: 'meta-framework',
|
|
1851
1663
|
version,
|
|
1852
1664
|
confidence: min(confidence, 100),
|
|
@@ -1855,47 +1667,55 @@ function nuxtDetector(projectPath, packageJson) {
|
|
|
1855
1667
|
}
|
|
1856
1668
|
|
|
1857
1669
|
/**
|
|
1858
|
-
* Detect
|
|
1670
|
+
* Detect Solid in project.
|
|
1859
1671
|
*
|
|
1860
1672
|
* @param projectPath - Project directory path
|
|
1861
1673
|
* @param packageJson - Optional pre-loaded package.json
|
|
1862
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
|
+
* ```
|
|
1863
1693
|
*/
|
|
1864
|
-
function
|
|
1694
|
+
function solidDetector(projectPath, packageJson) {
|
|
1865
1695
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1866
1696
|
const sources = [];
|
|
1867
1697
|
let confidence = 0;
|
|
1868
1698
|
let version;
|
|
1869
1699
|
const deps = collectAllDependencies(pkg);
|
|
1870
|
-
if (deps['
|
|
1700
|
+
if (deps['solid-js']) {
|
|
1871
1701
|
confidence += 70;
|
|
1872
|
-
version = parseVersionString(deps['
|
|
1873
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1874
|
-
}
|
|
1875
|
-
if (deps['@angular/cli']) {
|
|
1876
|
-
confidence += 15;
|
|
1877
|
-
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' });
|
|
1878
1704
|
}
|
|
1879
|
-
if (
|
|
1880
|
-
confidence +=
|
|
1881
|
-
sources.push({ type: '
|
|
1705
|
+
if (deps['vite-plugin-solid']) {
|
|
1706
|
+
confidence += 20;
|
|
1707
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
1882
1708
|
}
|
|
1883
|
-
if (deps['
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
name: 'AngularJS (Legacy)',
|
|
1887
|
-
category: 'frontend',
|
|
1888
|
-
version: parseVersionString(deps['angular']),
|
|
1889
|
-
confidence: 80,
|
|
1890
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
1891
|
-
};
|
|
1709
|
+
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
1710
|
+
confidence += 10;
|
|
1711
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
1892
1712
|
}
|
|
1893
1713
|
if (confidence === 0) {
|
|
1894
1714
|
return null;
|
|
1895
1715
|
}
|
|
1896
1716
|
return {
|
|
1897
|
-
id: '
|
|
1898
|
-
name: '
|
|
1717
|
+
id: 'solid',
|
|
1718
|
+
name: 'Solid',
|
|
1899
1719
|
category: 'frontend',
|
|
1900
1720
|
version,
|
|
1901
1721
|
confidence: min(confidence, 100),
|
|
@@ -1909,6 +1729,21 @@ function angularDetector(projectPath, packageJson) {
|
|
|
1909
1729
|
* @param projectPath - Project directory path
|
|
1910
1730
|
* @param packageJson - Optional pre-loaded package.json
|
|
1911
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
|
+
* ```
|
|
1912
1747
|
*/
|
|
1913
1748
|
function svelteDetector(projectPath, packageJson) {
|
|
1914
1749
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1961,6 +1796,21 @@ function svelteDetector(projectPath, packageJson) {
|
|
|
1961
1796
|
* @param projectPath - Project directory path
|
|
1962
1797
|
* @param packageJson - Optional pre-loaded package.json
|
|
1963
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
|
+
* ```
|
|
1964
1814
|
*/
|
|
1965
1815
|
function sveltekitDetector(projectPath, packageJson) {
|
|
1966
1816
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1968,7 +1818,6 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
1968
1818
|
let confidence = 0;
|
|
1969
1819
|
let version;
|
|
1970
1820
|
const deps = collectAllDependencies(pkg);
|
|
1971
|
-
// @sveltejs/kit package
|
|
1972
1821
|
if (deps['@sveltejs/kit']) {
|
|
1973
1822
|
confidence += 70;
|
|
1974
1823
|
version = parseVersionString(deps['@sveltejs/kit']);
|
|
@@ -1996,123 +1845,76 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
1996
1845
|
}
|
|
1997
1846
|
|
|
1998
1847
|
/**
|
|
1999
|
-
* Detect
|
|
1848
|
+
* Detect Vue in project.
|
|
2000
1849
|
*
|
|
2001
1850
|
* @param projectPath - Project directory path
|
|
2002
1851
|
* @param packageJson - Optional pre-loaded package.json
|
|
2003
1852
|
* @returns Detection result or null if not detected
|
|
2004
|
-
*/
|
|
2005
|
-
function solidDetector(projectPath, packageJson) {
|
|
2006
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2007
|
-
const sources = [];
|
|
2008
|
-
let confidence = 0;
|
|
2009
|
-
let version;
|
|
2010
|
-
const deps = collectAllDependencies(pkg);
|
|
2011
|
-
if (deps['solid-js']) {
|
|
2012
|
-
confidence += 70;
|
|
2013
|
-
version = parseVersionString(deps['solid-js']);
|
|
2014
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
2015
|
-
}
|
|
2016
|
-
if (deps['vite-plugin-solid']) {
|
|
2017
|
-
confidence += 20;
|
|
2018
|
-
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
2019
|
-
}
|
|
2020
|
-
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
2021
|
-
confidence += 10;
|
|
2022
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
2023
|
-
}
|
|
2024
|
-
if (confidence === 0) {
|
|
2025
|
-
return null;
|
|
2026
|
-
}
|
|
2027
|
-
return {
|
|
2028
|
-
id: 'solid',
|
|
2029
|
-
name: 'Solid',
|
|
2030
|
-
category: 'frontend',
|
|
2031
|
-
version,
|
|
2032
|
-
confidence: min(confidence, 100),
|
|
2033
|
-
detectedFrom: sources,
|
|
2034
|
-
};
|
|
2035
|
-
}
|
|
2036
|
-
|
|
2037
|
-
/**
|
|
2038
|
-
* Detect Qwik in project.
|
|
2039
1853
|
*
|
|
2040
|
-
* @
|
|
2041
|
-
*
|
|
2042
|
-
*
|
|
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
|
+
* ```
|
|
2043
1871
|
*/
|
|
2044
|
-
function
|
|
1872
|
+
function vueDetector(projectPath, packageJson) {
|
|
2045
1873
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2046
1874
|
const sources = [];
|
|
2047
1875
|
let confidence = 0;
|
|
2048
1876
|
let version;
|
|
1877
|
+
const metaFrameworks = [];
|
|
2049
1878
|
const deps = collectAllDependencies(pkg);
|
|
2050
|
-
|
|
2051
|
-
if (deps['@builder.io/qwik']) {
|
|
1879
|
+
if (deps['vue']) {
|
|
2052
1880
|
confidence += 70;
|
|
2053
|
-
version = parseVersionString(deps['
|
|
2054
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1881
|
+
version = parseVersionString(deps['vue']);
|
|
1882
|
+
sources.push({ type: 'package.json', field: 'dependencies.vue' });
|
|
2055
1883
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
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' });
|
|
2060
1887
|
}
|
|
2061
|
-
|
|
1888
|
+
const hasVueFiles = exists(join$1(projectPath, 'src', 'App.vue')) || exists(join$1(projectPath, 'src', 'main.vue'));
|
|
1889
|
+
if (hasVueFiles) {
|
|
2062
1890
|
confidence += 10;
|
|
2063
|
-
sources.push({ type: '
|
|
2064
|
-
}
|
|
2065
|
-
if (confidence === 0) {
|
|
2066
|
-
return null;
|
|
2067
|
-
}
|
|
2068
|
-
return {
|
|
2069
|
-
id: 'qwik',
|
|
2070
|
-
name: 'Qwik',
|
|
2071
|
-
category: 'frontend',
|
|
2072
|
-
version,
|
|
2073
|
-
confidence: min(confidence, 100),
|
|
2074
|
-
detectedFrom: sources,
|
|
2075
|
-
};
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
/**
|
|
2079
|
-
* Detect Astro in project.
|
|
2080
|
-
*
|
|
2081
|
-
* @param projectPath - Project directory path
|
|
2082
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2083
|
-
* @returns Detection result or null if not detected
|
|
2084
|
-
*/
|
|
2085
|
-
function astroDetector(projectPath, packageJson) {
|
|
2086
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2087
|
-
const sources = [];
|
|
2088
|
-
let confidence = 0;
|
|
2089
|
-
let version;
|
|
2090
|
-
const deps = collectAllDependencies(pkg);
|
|
2091
|
-
if (deps['astro']) {
|
|
2092
|
-
confidence += 70;
|
|
2093
|
-
version = parseVersionString(deps['astro']);
|
|
2094
|
-
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
2095
|
-
}
|
|
2096
|
-
if (exists(join$1(projectPath, 'astro.config.mjs')) ||
|
|
2097
|
-
exists(join$1(projectPath, 'astro.config.ts')) ||
|
|
2098
|
-
exists(join$1(projectPath, 'astro.config.js'))) {
|
|
2099
|
-
confidence += 25;
|
|
2100
|
-
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
1891
|
+
sources.push({ type: 'directory', path: 'src/*.vue' });
|
|
2101
1892
|
}
|
|
2102
|
-
if (exists(join$1(projectPath, '
|
|
1893
|
+
if (exists(join$1(projectPath, 'vue.config.js'))) {
|
|
2103
1894
|
confidence += 5;
|
|
2104
|
-
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
|
+
});
|
|
2105
1906
|
}
|
|
2106
1907
|
if (confidence === 0) {
|
|
2107
1908
|
return null;
|
|
2108
1909
|
}
|
|
2109
1910
|
return {
|
|
2110
|
-
id: '
|
|
2111
|
-
name: '
|
|
2112
|
-
category: '
|
|
1911
|
+
id: 'vue',
|
|
1912
|
+
name: 'Vue',
|
|
1913
|
+
category: 'frontend',
|
|
2113
1914
|
version,
|
|
2114
1915
|
confidence: min(confidence, 100),
|
|
2115
1916
|
detectedFrom: sources,
|
|
1917
|
+
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
2116
1918
|
};
|
|
2117
1919
|
}
|
|
2118
1920
|
|
|
@@ -2139,6 +1941,14 @@ const frameworkDetectors = [
|
|
|
2139
1941
|
* @param projectPath - Project directory path
|
|
2140
1942
|
* @param packageJson - Optional pre-loaded package.json
|
|
2141
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
|
+
* ```
|
|
2142
1952
|
*/
|
|
2143
1953
|
function angularJSDetector(projectPath, packageJson) {
|
|
2144
1954
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2146,23 +1956,19 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
2146
1956
|
let confidence = 0;
|
|
2147
1957
|
let version;
|
|
2148
1958
|
const deps = collectAllDependencies(pkg);
|
|
2149
|
-
// AngularJS package (angular, not @angular/core)
|
|
2150
1959
|
if (deps['angular']) {
|
|
2151
1960
|
confidence += 70;
|
|
2152
1961
|
version = parseVersionString(deps['angular']);
|
|
2153
1962
|
sources.push({ type: 'package.json', field: 'dependencies.angular' });
|
|
2154
1963
|
}
|
|
2155
|
-
// AngularJS router
|
|
2156
1964
|
if (deps['angular-route']) {
|
|
2157
1965
|
confidence += 15;
|
|
2158
1966
|
sources.push({ type: 'package.json', field: 'dependencies.angular-route' });
|
|
2159
1967
|
}
|
|
2160
|
-
// AngularJS resource
|
|
2161
1968
|
if (deps['angular-resource']) {
|
|
2162
1969
|
confidence += 10;
|
|
2163
1970
|
sources.push({ type: 'package.json', field: 'dependencies.angular-resource' });
|
|
2164
1971
|
}
|
|
2165
|
-
// AngularJS animate
|
|
2166
1972
|
if (deps['angular-animate']) {
|
|
2167
1973
|
confidence += 5;
|
|
2168
1974
|
sources.push({ type: 'package.json', field: 'dependencies.angular-animate' });
|
|
@@ -2186,6 +1992,14 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
2186
1992
|
* @param projectPath - Project directory path
|
|
2187
1993
|
* @param packageJson - Optional pre-loaded package.json
|
|
2188
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
|
+
* ```
|
|
2189
2003
|
*/
|
|
2190
2004
|
function backboneDetector(projectPath, packageJson) {
|
|
2191
2005
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2193,23 +2007,19 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
2193
2007
|
let confidence = 0;
|
|
2194
2008
|
let version;
|
|
2195
2009
|
const deps = collectAllDependencies(pkg);
|
|
2196
|
-
// Backbone package
|
|
2197
2010
|
if (deps['backbone']) {
|
|
2198
2011
|
confidence += 70;
|
|
2199
2012
|
version = parseVersionString(deps['backbone']);
|
|
2200
2013
|
sources.push({ type: 'package.json', field: 'dependencies.backbone' });
|
|
2201
|
-
// Underscore (commonly used with Backbone)
|
|
2202
2014
|
if (deps['underscore']) {
|
|
2203
2015
|
confidence += 15;
|
|
2204
2016
|
sources.push({ type: 'package.json', field: 'dependencies.underscore' });
|
|
2205
2017
|
}
|
|
2206
|
-
// Lodash can be used as underscore replacement
|
|
2207
2018
|
if (deps['lodash']) {
|
|
2208
2019
|
confidence += 5;
|
|
2209
2020
|
sources.push({ type: 'package.json', field: 'dependencies.lodash' });
|
|
2210
2021
|
}
|
|
2211
2022
|
}
|
|
2212
|
-
// Marionette (Backbone framework)
|
|
2213
2023
|
if (deps['backbone.marionette'] || deps['marionette']) {
|
|
2214
2024
|
confidence += 10;
|
|
2215
2025
|
sources.push({ type: 'package.json', field: 'dependencies.backbone.marionette' });
|
|
@@ -2233,6 +2043,15 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
2233
2043
|
* @param projectPath - Project directory path
|
|
2234
2044
|
* @param packageJson - Optional pre-loaded package.json
|
|
2235
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
|
+
* ```
|
|
2236
2055
|
*/
|
|
2237
2056
|
function emberDetector(projectPath, packageJson) {
|
|
2238
2057
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2240,18 +2059,15 @@ function emberDetector(projectPath, packageJson) {
|
|
|
2240
2059
|
let confidence = 0;
|
|
2241
2060
|
let version;
|
|
2242
2061
|
const deps = collectAllDependencies(pkg);
|
|
2243
|
-
// Ember source package
|
|
2244
2062
|
if (deps['ember-source']) {
|
|
2245
2063
|
confidence += 70;
|
|
2246
2064
|
version = parseVersionString(deps['ember-source']);
|
|
2247
2065
|
sources.push({ type: 'package.json', field: 'dependencies.ember-source' });
|
|
2248
2066
|
}
|
|
2249
|
-
// Ember CLI
|
|
2250
2067
|
if (deps['ember-cli']) {
|
|
2251
2068
|
confidence += 20;
|
|
2252
2069
|
sources.push({ type: 'package.json', field: 'devDependencies.ember-cli' });
|
|
2253
2070
|
}
|
|
2254
|
-
// Ember Data
|
|
2255
2071
|
if (deps['ember-data']) {
|
|
2256
2072
|
confidence += 10;
|
|
2257
2073
|
sources.push({ type: 'package.json', field: 'dependencies.ember-data' });
|
|
@@ -2275,6 +2091,14 @@ function emberDetector(projectPath, packageJson) {
|
|
|
2275
2091
|
* @param projectPath - Project directory path
|
|
2276
2092
|
* @param packageJson - Optional pre-loaded package.json
|
|
2277
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
|
+
* ```
|
|
2278
2102
|
*/
|
|
2279
2103
|
function jqueryDetector(projectPath, packageJson) {
|
|
2280
2104
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2282,43 +2106,90 @@ function jqueryDetector(projectPath, packageJson) {
|
|
|
2282
2106
|
let confidence = 0;
|
|
2283
2107
|
let version;
|
|
2284
2108
|
const deps = collectAllDependencies(pkg);
|
|
2285
|
-
// jQuery package
|
|
2286
2109
|
if (deps['jquery']) {
|
|
2287
2110
|
confidence += 80;
|
|
2288
2111
|
version = parseVersionString(deps['jquery']);
|
|
2289
2112
|
sources.push({ type: 'package.json', field: 'dependencies.jquery' });
|
|
2290
2113
|
}
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
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
|
+
* ```
|
|
2157
|
+
*/
|
|
2158
|
+
function biomeDetector(projectPath, packageJson) {
|
|
2159
|
+
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2160
|
+
const sources = [];
|
|
2161
|
+
let confidence = 0;
|
|
2162
|
+
let configPath;
|
|
2163
|
+
let version;
|
|
2164
|
+
const deps = collectAllDependencies(pkg);
|
|
2165
|
+
if (deps['@biomejs/biome']) {
|
|
2166
|
+
confidence += 70;
|
|
2167
|
+
version = parseVersionString(deps['@biomejs/biome']);
|
|
2168
|
+
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2169
|
+
}
|
|
2170
|
+
if (exists(join$1(projectPath, 'biome.json'))) {
|
|
2171
|
+
confidence += 30;
|
|
2172
|
+
configPath = 'biome.json';
|
|
2173
|
+
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2295
2174
|
}
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
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' });
|
|
2300
2179
|
}
|
|
2301
2180
|
if (confidence === 0) {
|
|
2302
2181
|
return null;
|
|
2303
2182
|
}
|
|
2304
2183
|
return {
|
|
2305
|
-
id: '
|
|
2306
|
-
name: '
|
|
2307
|
-
category: 'legacy-frontend',
|
|
2184
|
+
id: 'biome',
|
|
2185
|
+
name: 'Biome',
|
|
2308
2186
|
version,
|
|
2187
|
+
configPath,
|
|
2309
2188
|
confidence: min(confidence, 100),
|
|
2310
2189
|
detectedFrom: sources,
|
|
2311
2190
|
};
|
|
2312
2191
|
}
|
|
2313
2192
|
|
|
2314
|
-
/** All legacy framework detectors */
|
|
2315
|
-
const legacyDetectors = [
|
|
2316
|
-
{ id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
|
|
2317
|
-
{ id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
|
|
2318
|
-
{ id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
|
|
2319
|
-
{ id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
|
|
2320
|
-
];
|
|
2321
|
-
|
|
2322
2193
|
/** Config patterns for ESLint */
|
|
2323
2194
|
const ESLINT_CONFIG_PATTERNS = [
|
|
2324
2195
|
'eslint.config.js',
|
|
@@ -2338,6 +2209,15 @@ const ESLINT_CONFIG_PATTERNS = [
|
|
|
2338
2209
|
* @param projectPath - Project directory path
|
|
2339
2210
|
* @param packageJson - Optional pre-loaded package.json
|
|
2340
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
|
+
* ```
|
|
2341
2221
|
*/
|
|
2342
2222
|
function eslintDetector(projectPath, packageJson) {
|
|
2343
2223
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2401,6 +2281,15 @@ const PRETTIER_CONFIG_PATTERNS = [
|
|
|
2401
2281
|
* @param projectPath - Project directory path
|
|
2402
2282
|
* @param packageJson - Optional pre-loaded package.json
|
|
2403
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
|
+
* ```
|
|
2404
2293
|
*/
|
|
2405
2294
|
function prettierDetector(projectPath, packageJson) {
|
|
2406
2295
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2422,7 +2311,6 @@ function prettierDetector(projectPath, packageJson) {
|
|
|
2422
2311
|
confidence += 30;
|
|
2423
2312
|
sources.push({ type: 'package.json', field: 'prettier' });
|
|
2424
2313
|
}
|
|
2425
|
-
// .prettierignore file
|
|
2426
2314
|
if (exists(join$1(projectPath, '.prettierignore'))) {
|
|
2427
2315
|
confidence += 10;
|
|
2428
2316
|
sources.push({ type: 'config-file', path: '.prettierignore' });
|
|
@@ -2464,6 +2352,14 @@ const STYLELINT_CONFIG_PATTERNS = [
|
|
|
2464
2352
|
* @param projectPath - Project directory path
|
|
2465
2353
|
* @param packageJson - Optional pre-loaded package.json
|
|
2466
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
|
+
* ```
|
|
2467
2363
|
*/
|
|
2468
2364
|
function stylelintDetector(projectPath, packageJson) {
|
|
2469
2365
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2503,49 +2399,6 @@ function stylelintDetector(projectPath, packageJson) {
|
|
|
2503
2399
|
};
|
|
2504
2400
|
}
|
|
2505
2401
|
|
|
2506
|
-
/**
|
|
2507
|
-
* Detect Biome in project.
|
|
2508
|
-
*
|
|
2509
|
-
* @param projectPath - Project directory path
|
|
2510
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2511
|
-
* @returns Detection result or null if not detected
|
|
2512
|
-
*/
|
|
2513
|
-
function biomeDetector(projectPath, packageJson) {
|
|
2514
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2515
|
-
const sources = [];
|
|
2516
|
-
let confidence = 0;
|
|
2517
|
-
let configPath;
|
|
2518
|
-
let version;
|
|
2519
|
-
const deps = collectAllDependencies(pkg);
|
|
2520
|
-
// @biomejs/biome package
|
|
2521
|
-
if (deps['@biomejs/biome']) {
|
|
2522
|
-
confidence += 70;
|
|
2523
|
-
version = parseVersionString(deps['@biomejs/biome']);
|
|
2524
|
-
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2525
|
-
}
|
|
2526
|
-
if (exists(join$1(projectPath, 'biome.json'))) {
|
|
2527
|
-
confidence += 30;
|
|
2528
|
-
configPath = 'biome.json';
|
|
2529
|
-
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2530
|
-
}
|
|
2531
|
-
if (!configPath && exists(join$1(projectPath, 'biome.jsonc'))) {
|
|
2532
|
-
confidence += 30;
|
|
2533
|
-
configPath = 'biome.jsonc';
|
|
2534
|
-
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
2535
|
-
}
|
|
2536
|
-
if (confidence === 0) {
|
|
2537
|
-
return null;
|
|
2538
|
-
}
|
|
2539
|
-
return {
|
|
2540
|
-
id: 'biome',
|
|
2541
|
-
name: 'Biome',
|
|
2542
|
-
version,
|
|
2543
|
-
configPath,
|
|
2544
|
-
confidence: min(confidence, 100),
|
|
2545
|
-
detectedFrom: sources,
|
|
2546
|
-
};
|
|
2547
|
-
}
|
|
2548
|
-
|
|
2549
2402
|
/** All linting tool detectors */
|
|
2550
2403
|
const lintingDetectors = [
|
|
2551
2404
|
{ id: 'eslint', name: 'ESLint', detect: eslintDetector },
|
|
@@ -2555,140 +2408,179 @@ const lintingDetectors = [
|
|
|
2555
2408
|
];
|
|
2556
2409
|
|
|
2557
2410
|
/**
|
|
2558
|
-
* Detect
|
|
2411
|
+
* Detect Lerna in project.
|
|
2559
2412
|
*
|
|
2560
2413
|
* @param workspacePath - Workspace directory path
|
|
2561
2414
|
* @param packageJson - Optional pre-loaded package.json
|
|
2562
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
|
+
* ```
|
|
2563
2429
|
*/
|
|
2564
|
-
function
|
|
2430
|
+
function lernaDetector(workspacePath, packageJson) {
|
|
2565
2431
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2566
2432
|
const sources = [];
|
|
2567
2433
|
let confidence = 0;
|
|
2568
2434
|
let version;
|
|
2569
|
-
let
|
|
2570
|
-
const
|
|
2571
|
-
if (exists(
|
|
2572
|
-
confidence +=
|
|
2573
|
-
|
|
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' });
|
|
2574
2441
|
}
|
|
2575
2442
|
const deps = collectAllDependencies(pkg);
|
|
2576
|
-
if (deps['
|
|
2577
|
-
confidence +=
|
|
2578
|
-
version = parseVersionString(deps['
|
|
2579
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2580
|
-
}
|
|
2581
|
-
const hasApps = exists(join$1(workspacePath, 'apps'));
|
|
2582
|
-
const hasLibs = exists(join$1(workspacePath, 'libs'));
|
|
2583
|
-
if (hasApps || hasLibs) {
|
|
2584
|
-
confidence += 10;
|
|
2585
|
-
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
2586
|
-
workspaceLayout = {
|
|
2587
|
-
appsDir: hasApps ? 'apps' : '',
|
|
2588
|
-
libsDir: hasLibs ? 'libs' : '',
|
|
2589
|
-
};
|
|
2443
|
+
if (deps['lerna']) {
|
|
2444
|
+
confidence += 15;
|
|
2445
|
+
version = parseVersionString(deps['lerna']);
|
|
2446
|
+
sources.push({ type: 'package.json', field: 'dependencies.lerna' });
|
|
2590
2447
|
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
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/' });
|
|
2595
2451
|
}
|
|
2596
2452
|
if (confidence === 0) {
|
|
2597
2453
|
return null;
|
|
2598
2454
|
}
|
|
2599
2455
|
return {
|
|
2600
|
-
id: '
|
|
2601
|
-
name: '
|
|
2456
|
+
id: 'lerna',
|
|
2457
|
+
name: 'Lerna',
|
|
2602
2458
|
version,
|
|
2603
|
-
configPath
|
|
2459
|
+
configPath,
|
|
2604
2460
|
confidence: min(confidence, 100),
|
|
2605
2461
|
detectedFrom: sources,
|
|
2606
|
-
workspaceLayout,
|
|
2607
2462
|
};
|
|
2608
2463
|
}
|
|
2609
2464
|
|
|
2610
2465
|
/**
|
|
2611
|
-
* Detect
|
|
2466
|
+
* Detect npm workspaces in project.
|
|
2612
2467
|
*
|
|
2613
2468
|
* @param workspacePath - Workspace directory path
|
|
2614
2469
|
* @param packageJson - Optional pre-loaded package.json
|
|
2615
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
|
+
* ```
|
|
2616
2487
|
*/
|
|
2617
|
-
function
|
|
2488
|
+
function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
2618
2489
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2619
2490
|
const sources = [];
|
|
2620
2491
|
let confidence = 0;
|
|
2621
|
-
|
|
2622
|
-
let configPath;
|
|
2623
|
-
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
2624
|
-
if (exists(turboJsonPath)) {
|
|
2492
|
+
if (pkg?.workspaces) {
|
|
2625
2493
|
confidence += 80;
|
|
2626
|
-
|
|
2627
|
-
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2494
|
+
sources.push({ type: 'package.json', field: 'workspaces' });
|
|
2628
2495
|
}
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
version = parseVersionString(deps['turbo']);
|
|
2633
|
-
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' });
|
|
2634
2499
|
}
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
confidence += 5;
|
|
2638
|
-
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
2500
|
+
if (exists(join$1(workspacePath, 'yarn.lock'))) {
|
|
2501
|
+
return null;
|
|
2639
2502
|
}
|
|
2640
2503
|
if (confidence === 0) {
|
|
2641
2504
|
return null;
|
|
2642
2505
|
}
|
|
2643
2506
|
return {
|
|
2644
|
-
id: '
|
|
2645
|
-
name: '
|
|
2646
|
-
|
|
2647
|
-
configPath,
|
|
2507
|
+
id: 'npm-workspaces',
|
|
2508
|
+
name: 'npm Workspaces',
|
|
2509
|
+
configPath: 'package.json',
|
|
2648
2510
|
confidence: min(confidence, 100),
|
|
2649
2511
|
detectedFrom: sources,
|
|
2650
2512
|
};
|
|
2651
2513
|
}
|
|
2652
2514
|
|
|
2653
2515
|
/**
|
|
2654
|
-
* Detect
|
|
2516
|
+
* Detect NX in project.
|
|
2655
2517
|
*
|
|
2656
2518
|
* @param workspacePath - Workspace directory path
|
|
2657
2519
|
* @param packageJson - Optional pre-loaded package.json
|
|
2658
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
|
+
* ```
|
|
2659
2540
|
*/
|
|
2660
|
-
function
|
|
2541
|
+
function nxDetector(workspacePath, packageJson) {
|
|
2661
2542
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2662
2543
|
const sources = [];
|
|
2663
2544
|
let confidence = 0;
|
|
2664
2545
|
let version;
|
|
2665
|
-
let
|
|
2666
|
-
const
|
|
2667
|
-
if (exists(
|
|
2668
|
-
confidence +=
|
|
2669
|
-
|
|
2670
|
-
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' });
|
|
2671
2551
|
}
|
|
2672
2552
|
const deps = collectAllDependencies(pkg);
|
|
2673
|
-
if (deps['
|
|
2674
|
-
confidence +=
|
|
2675
|
-
version = parseVersionString(deps['
|
|
2676
|
-
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' });
|
|
2677
2557
|
}
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
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' });
|
|
2681
2572
|
}
|
|
2682
2573
|
if (confidence === 0) {
|
|
2683
2574
|
return null;
|
|
2684
2575
|
}
|
|
2685
2576
|
return {
|
|
2686
|
-
id: '
|
|
2687
|
-
name: '
|
|
2577
|
+
id: 'nx',
|
|
2578
|
+
name: 'NX',
|
|
2688
2579
|
version,
|
|
2689
|
-
configPath,
|
|
2580
|
+
configPath: exists(nxJsonPath) ? 'nx.json' : undefined,
|
|
2690
2581
|
confidence: min(confidence, 100),
|
|
2691
2582
|
detectedFrom: sources,
|
|
2583
|
+
workspaceLayout,
|
|
2692
2584
|
};
|
|
2693
2585
|
}
|
|
2694
2586
|
|
|
@@ -2698,6 +2590,19 @@ function lernaDetector(workspacePath, packageJson) {
|
|
|
2698
2590
|
* @param workspacePath - Workspace directory path
|
|
2699
2591
|
* @param packageJson - Optional pre-loaded package.json
|
|
2700
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
|
+
* ```
|
|
2701
2606
|
*/
|
|
2702
2607
|
function rushDetector(workspacePath, packageJson) {
|
|
2703
2608
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2711,55 +2616,23 @@ function rushDetector(workspacePath, packageJson) {
|
|
|
2711
2616
|
configPath = 'rush.json';
|
|
2712
2617
|
sources.push({ type: 'config-file', path: 'rush.json' });
|
|
2713
2618
|
}
|
|
2714
|
-
const deps = collectAllDependencies(pkg);
|
|
2715
|
-
if (deps['@microsoft/rush']) {
|
|
2716
|
-
confidence += 10;
|
|
2717
|
-
version = parseVersionString(deps['@microsoft/rush']);
|
|
2718
|
-
sources.push({ type: 'package.json', field: 'dependencies.@microsoft/rush' });
|
|
2719
|
-
}
|
|
2720
|
-
if (exists(join$1(workspacePath, 'common', 'config', 'rush'))) {
|
|
2721
|
-
confidence += 5;
|
|
2722
|
-
sources.push({ type: 'directory', path: 'common/config/rush/' });
|
|
2723
|
-
}
|
|
2724
|
-
if (confidence === 0) {
|
|
2725
|
-
return null;
|
|
2726
|
-
}
|
|
2727
|
-
return {
|
|
2728
|
-
id: 'rush',
|
|
2729
|
-
name: 'Rush',
|
|
2730
|
-
version,
|
|
2731
|
-
configPath,
|
|
2732
|
-
confidence: min(confidence, 100),
|
|
2733
|
-
detectedFrom: sources,
|
|
2734
|
-
};
|
|
2735
|
-
}
|
|
2736
|
-
|
|
2737
|
-
/**
|
|
2738
|
-
* Detect pnpm workspaces in project.
|
|
2739
|
-
*
|
|
2740
|
-
* @param workspacePath - Workspace directory path
|
|
2741
|
-
* @returns Detection result or null if not detected
|
|
2742
|
-
*/
|
|
2743
|
-
function pnpmWorkspacesDetector(workspacePath) {
|
|
2744
|
-
const sources = [];
|
|
2745
|
-
let confidence = 0;
|
|
2746
|
-
let configPath;
|
|
2747
|
-
const pnpmWorkspacePath = join$1(workspacePath, 'pnpm-workspace.yaml');
|
|
2748
|
-
if (exists(pnpmWorkspacePath)) {
|
|
2749
|
-
confidence += 90;
|
|
2750
|
-
configPath = 'pnpm-workspace.yaml';
|
|
2751
|
-
sources.push({ type: 'config-file', path: 'pnpm-workspace.yaml' });
|
|
2752
|
-
}
|
|
2753
|
-
if (exists(join$1(workspacePath, 'pnpm-lock.yaml'))) {
|
|
2619
|
+
const deps = collectAllDependencies(pkg);
|
|
2620
|
+
if (deps['@microsoft/rush']) {
|
|
2754
2621
|
confidence += 10;
|
|
2755
|
-
|
|
2622
|
+
version = parseVersionString(deps['@microsoft/rush']);
|
|
2623
|
+
sources.push({ type: 'package.json', field: 'dependencies.@microsoft/rush' });
|
|
2624
|
+
}
|
|
2625
|
+
if (exists(join$1(workspacePath, 'common', 'config', 'rush'))) {
|
|
2626
|
+
confidence += 5;
|
|
2627
|
+
sources.push({ type: 'directory', path: 'common/config/rush/' });
|
|
2756
2628
|
}
|
|
2757
2629
|
if (confidence === 0) {
|
|
2758
2630
|
return null;
|
|
2759
2631
|
}
|
|
2760
2632
|
return {
|
|
2761
|
-
id: '
|
|
2762
|
-
name: '
|
|
2633
|
+
id: 'rush',
|
|
2634
|
+
name: 'Rush',
|
|
2635
|
+
version,
|
|
2763
2636
|
configPath,
|
|
2764
2637
|
confidence: min(confidence, 100),
|
|
2765
2638
|
detectedFrom: sources,
|
|
@@ -2767,34 +2640,60 @@ function pnpmWorkspacesDetector(workspacePath) {
|
|
|
2767
2640
|
}
|
|
2768
2641
|
|
|
2769
2642
|
/**
|
|
2770
|
-
* Detect
|
|
2643
|
+
* Detect Turborepo in project.
|
|
2771
2644
|
*
|
|
2772
2645
|
* @param workspacePath - Workspace directory path
|
|
2773
2646
|
* @param packageJson - Optional pre-loaded package.json
|
|
2774
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
|
+
* ```
|
|
2775
2665
|
*/
|
|
2776
|
-
function
|
|
2666
|
+
function turborepoDetector(workspacePath, packageJson) {
|
|
2777
2667
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2778
2668
|
const sources = [];
|
|
2779
2669
|
let confidence = 0;
|
|
2780
|
-
|
|
2670
|
+
let version;
|
|
2671
|
+
let configPath;
|
|
2672
|
+
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
2673
|
+
if (exists(turboJsonPath)) {
|
|
2781
2674
|
confidence += 80;
|
|
2782
|
-
|
|
2675
|
+
configPath = 'turbo.json';
|
|
2676
|
+
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2783
2677
|
}
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
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' });
|
|
2787
2683
|
}
|
|
2788
|
-
|
|
2789
|
-
|
|
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)' });
|
|
2790
2688
|
}
|
|
2791
2689
|
if (confidence === 0) {
|
|
2792
2690
|
return null;
|
|
2793
2691
|
}
|
|
2794
2692
|
return {
|
|
2795
|
-
id: '
|
|
2796
|
-
name: '
|
|
2797
|
-
|
|
2693
|
+
id: 'turborepo',
|
|
2694
|
+
name: 'Turborepo',
|
|
2695
|
+
version,
|
|
2696
|
+
configPath,
|
|
2798
2697
|
confidence: min(confidence, 100),
|
|
2799
2698
|
detectedFrom: sources,
|
|
2800
2699
|
};
|
|
@@ -2806,6 +2705,23 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
|
2806
2705
|
* @param workspacePath - Workspace directory path
|
|
2807
2706
|
* @param packageJson - Optional pre-loaded package.json
|
|
2808
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
|
+
* ```
|
|
2809
2725
|
*/
|
|
2810
2726
|
function yarnWorkspacesDetector(workspacePath, packageJson) {
|
|
2811
2727
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2846,55 +2762,58 @@ const monorepoDetectors = [
|
|
|
2846
2762
|
{ id: 'yarn-workspaces', name: 'Yarn Workspaces', detect: yarnWorkspacesDetector },
|
|
2847
2763
|
];
|
|
2848
2764
|
|
|
2849
|
-
/** Config patterns for
|
|
2850
|
-
const
|
|
2765
|
+
/** Config patterns for Cypress */
|
|
2766
|
+
const CYPRESS_CONFIG_PATTERNS = ['cypress.config.js', 'cypress.config.ts', 'cypress.config.mjs', 'cypress.json'];
|
|
2851
2767
|
/**
|
|
2852
|
-
* Detect
|
|
2768
|
+
* Detect Cypress in project.
|
|
2853
2769
|
*
|
|
2854
2770
|
* @param projectPath - Project directory path
|
|
2855
2771
|
* @param packageJson - Optional pre-loaded package.json
|
|
2856
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
|
+
* ```
|
|
2857
2784
|
*/
|
|
2858
|
-
function
|
|
2785
|
+
function cypressDetector(projectPath, packageJson) {
|
|
2859
2786
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2860
2787
|
const sources = [];
|
|
2861
2788
|
let confidence = 0;
|
|
2862
2789
|
let version;
|
|
2863
2790
|
const deps = collectAllDependencies(pkg);
|
|
2864
|
-
if (deps['
|
|
2791
|
+
if (deps['cypress']) {
|
|
2865
2792
|
confidence += 60;
|
|
2866
|
-
version = parseVersionString(deps['
|
|
2867
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2793
|
+
version = parseVersionString(deps['cypress']);
|
|
2794
|
+
sources.push({ type: 'package.json', field: 'dependencies.cypress' });
|
|
2868
2795
|
}
|
|
2869
|
-
const configPath = locateConfigFile(projectPath,
|
|
2796
|
+
const configPath = locateConfigFile(projectPath, CYPRESS_CONFIG_PATTERNS);
|
|
2870
2797
|
if (configPath) {
|
|
2871
2798
|
confidence += 30;
|
|
2872
2799
|
sources.push({ type: 'config-file', path: configPath });
|
|
2873
2800
|
}
|
|
2874
|
-
if (
|
|
2875
|
-
confidence += 20;
|
|
2876
|
-
sources.push({ type: 'package.json', field: 'jest' });
|
|
2877
|
-
}
|
|
2878
|
-
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
2879
|
-
if (testScript.includes('jest')) {
|
|
2801
|
+
if (exists(join$1(projectPath, 'cypress'))) {
|
|
2880
2802
|
confidence += 10;
|
|
2881
|
-
sources.push({ type: '
|
|
2882
|
-
}
|
|
2883
|
-
if (deps['@types/jest']) {
|
|
2884
|
-
confidence += 5;
|
|
2885
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
2803
|
+
sources.push({ type: 'directory', path: 'cypress/' });
|
|
2886
2804
|
}
|
|
2887
|
-
|
|
2805
|
+
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
2806
|
+
if (e2eScript.includes('cypress')) {
|
|
2888
2807
|
confidence += 5;
|
|
2889
|
-
sources.push({ type: 'package.json', field: '
|
|
2808
|
+
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
2890
2809
|
}
|
|
2891
2810
|
if (confidence === 0) {
|
|
2892
2811
|
return null;
|
|
2893
2812
|
}
|
|
2894
2813
|
return {
|
|
2895
|
-
id: '
|
|
2896
|
-
name: '
|
|
2897
|
-
type: '
|
|
2814
|
+
id: 'cypress',
|
|
2815
|
+
name: 'Cypress',
|
|
2816
|
+
type: 'e2e',
|
|
2898
2817
|
version,
|
|
2899
2818
|
configPath,
|
|
2900
2819
|
confidence: min(confidence, 100),
|
|
@@ -2902,51 +2821,66 @@ function jestDetector(projectPath, packageJson) {
|
|
|
2902
2821
|
};
|
|
2903
2822
|
}
|
|
2904
2823
|
|
|
2905
|
-
/** Config patterns for
|
|
2906
|
-
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'];
|
|
2907
2826
|
/**
|
|
2908
|
-
* Detect
|
|
2827
|
+
* Detect Jest in project.
|
|
2909
2828
|
*
|
|
2910
2829
|
* @param projectPath - Project directory path
|
|
2911
2830
|
* @param packageJson - Optional pre-loaded package.json
|
|
2912
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
|
+
* ```
|
|
2913
2844
|
*/
|
|
2914
|
-
function
|
|
2845
|
+
function jestDetector(projectPath, packageJson) {
|
|
2915
2846
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2916
2847
|
const sources = [];
|
|
2917
2848
|
let confidence = 0;
|
|
2918
2849
|
let version;
|
|
2919
2850
|
const deps = collectAllDependencies(pkg);
|
|
2920
|
-
if (deps['
|
|
2921
|
-
confidence +=
|
|
2922
|
-
version = parseVersionString(deps['
|
|
2923
|
-
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' });
|
|
2924
2855
|
}
|
|
2925
|
-
const configPath = locateConfigFile(projectPath,
|
|
2856
|
+
const configPath = locateConfigFile(projectPath, JEST_CONFIG_PATTERNS);
|
|
2926
2857
|
if (configPath) {
|
|
2927
|
-
confidence +=
|
|
2858
|
+
confidence += 30;
|
|
2928
2859
|
sources.push({ type: 'config-file', path: configPath });
|
|
2929
2860
|
}
|
|
2930
|
-
if (
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
exists(join$1(projectPath, 'vite.config.mjs'));
|
|
2934
|
-
if (viteConfig && deps['vitest']) {
|
|
2935
|
-
confidence += 5;
|
|
2936
|
-
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
2937
|
-
}
|
|
2861
|
+
if (pkg && 'jest' in pkg) {
|
|
2862
|
+
confidence += 20;
|
|
2863
|
+
sources.push({ type: 'package.json', field: 'jest' });
|
|
2938
2864
|
}
|
|
2939
2865
|
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
2940
|
-
if (testScript.includes('
|
|
2866
|
+
if (testScript.includes('jest')) {
|
|
2941
2867
|
confidence += 10;
|
|
2942
2868
|
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
2943
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
|
+
}
|
|
2944
2878
|
if (confidence === 0) {
|
|
2945
2879
|
return null;
|
|
2946
2880
|
}
|
|
2947
2881
|
return {
|
|
2948
|
-
id: '
|
|
2949
|
-
name: '
|
|
2882
|
+
id: 'jest',
|
|
2883
|
+
name: 'Jest',
|
|
2950
2884
|
type: 'unit',
|
|
2951
2885
|
version,
|
|
2952
2886
|
configPath,
|
|
@@ -2963,6 +2897,17 @@ const MOCHA_CONFIG_PATTERNS = ['.mocharc.js', '.mocharc.json', '.mocharc.yaml',
|
|
|
2963
2897
|
* @param projectPath - Project directory path
|
|
2964
2898
|
* @param packageJson - Optional pre-loaded package.json
|
|
2965
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
|
+
* ```
|
|
2966
2911
|
*/
|
|
2967
2912
|
function mochaDetector(projectPath, packageJson) {
|
|
2968
2913
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3007,37 +2952,53 @@ function mochaDetector(projectPath, packageJson) {
|
|
|
3007
2952
|
};
|
|
3008
2953
|
}
|
|
3009
2954
|
|
|
3010
|
-
/** Config patterns for
|
|
3011
|
-
const
|
|
2955
|
+
/** Config patterns for Playwright */
|
|
2956
|
+
const PLAYWRIGHT_CONFIG_PATTERNS = ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs'];
|
|
3012
2957
|
/**
|
|
3013
|
-
* Detect
|
|
2958
|
+
* Detect Playwright in project.
|
|
3014
2959
|
*
|
|
3015
2960
|
* @param projectPath - Project directory path
|
|
3016
2961
|
* @param packageJson - Optional pre-loaded package.json
|
|
3017
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
|
+
* ```
|
|
3018
2974
|
*/
|
|
3019
|
-
function
|
|
2975
|
+
function playwrightDetector(projectPath, packageJson) {
|
|
3020
2976
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3021
2977
|
const sources = [];
|
|
3022
2978
|
let confidence = 0;
|
|
3023
2979
|
let version;
|
|
3024
2980
|
const deps = collectAllDependencies(pkg);
|
|
3025
|
-
if (deps['
|
|
3026
|
-
confidence +=
|
|
3027
|
-
version = parseVersionString(deps['
|
|
3028
|
-
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' });
|
|
3029
2985
|
}
|
|
3030
|
-
|
|
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);
|
|
3031
2992
|
if (configPath) {
|
|
3032
|
-
confidence +=
|
|
2993
|
+
confidence += 25;
|
|
3033
2994
|
sources.push({ type: 'config-file', path: configPath });
|
|
3034
2995
|
}
|
|
3035
|
-
if (exists(join$1(projectPath, '
|
|
3036
|
-
confidence +=
|
|
3037
|
-
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/' });
|
|
3038
2999
|
}
|
|
3039
3000
|
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
3040
|
-
if (e2eScript.includes('
|
|
3001
|
+
if (e2eScript.includes('playwright')) {
|
|
3041
3002
|
confidence += 5;
|
|
3042
3003
|
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
3043
3004
|
}
|
|
@@ -3045,8 +3006,8 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3045
3006
|
return null;
|
|
3046
3007
|
}
|
|
3047
3008
|
return {
|
|
3048
|
-
id: '
|
|
3049
|
-
name: '
|
|
3009
|
+
id: 'playwright',
|
|
3010
|
+
name: 'Playwright',
|
|
3050
3011
|
type: 'e2e',
|
|
3051
3012
|
version,
|
|
3052
3013
|
configPath,
|
|
@@ -3055,52 +3016,64 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3055
3016
|
};
|
|
3056
3017
|
}
|
|
3057
3018
|
|
|
3058
|
-
/** Config patterns for
|
|
3059
|
-
const
|
|
3019
|
+
/** Config patterns for Vitest */
|
|
3020
|
+
const VITEST_CONFIG_PATTERNS = ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'];
|
|
3060
3021
|
/**
|
|
3061
|
-
* Detect
|
|
3022
|
+
* Detect Vitest in project.
|
|
3062
3023
|
*
|
|
3063
3024
|
* @param projectPath - Project directory path
|
|
3064
3025
|
* @param packageJson - Optional pre-loaded package.json
|
|
3065
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
|
+
* ```
|
|
3066
3039
|
*/
|
|
3067
|
-
function
|
|
3040
|
+
function vitestDetector(projectPath, packageJson) {
|
|
3068
3041
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3069
3042
|
const sources = [];
|
|
3070
3043
|
let confidence = 0;
|
|
3071
3044
|
let version;
|
|
3072
3045
|
const deps = collectAllDependencies(pkg);
|
|
3073
|
-
if (deps['
|
|
3046
|
+
if (deps['vitest']) {
|
|
3074
3047
|
confidence += 70;
|
|
3075
|
-
version = parseVersionString(deps['
|
|
3076
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
3077
|
-
}
|
|
3078
|
-
if (deps['playwright']) {
|
|
3079
|
-
confidence += 50;
|
|
3080
|
-
version = version ?? parseVersionString(deps['playwright']);
|
|
3081
|
-
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
3048
|
+
version = parseVersionString(deps['vitest']);
|
|
3049
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
3082
3050
|
}
|
|
3083
|
-
const configPath = locateConfigFile(projectPath,
|
|
3051
|
+
const configPath = locateConfigFile(projectPath, VITEST_CONFIG_PATTERNS);
|
|
3084
3052
|
if (configPath) {
|
|
3085
3053
|
confidence += 25;
|
|
3086
3054
|
sources.push({ type: 'config-file', path: configPath });
|
|
3087
3055
|
}
|
|
3088
|
-
if (
|
|
3089
|
-
|
|
3090
|
-
|
|
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
|
+
}
|
|
3091
3064
|
}
|
|
3092
|
-
const
|
|
3093
|
-
if (
|
|
3094
|
-
confidence +=
|
|
3095
|
-
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' });
|
|
3096
3069
|
}
|
|
3097
3070
|
if (confidence === 0) {
|
|
3098
3071
|
return null;
|
|
3099
3072
|
}
|
|
3100
3073
|
return {
|
|
3101
|
-
id: '
|
|
3102
|
-
name: '
|
|
3103
|
-
type: '
|
|
3074
|
+
id: 'vitest',
|
|
3075
|
+
name: 'Vitest',
|
|
3076
|
+
type: 'unit',
|
|
3104
3077
|
version,
|
|
3105
3078
|
configPath,
|
|
3106
3079
|
confidence: min(confidence, 100),
|
|
@@ -3129,7 +3102,6 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3129
3102
|
if (!content)
|
|
3130
3103
|
return undefined;
|
|
3131
3104
|
try {
|
|
3132
|
-
// Simple JSON parsing - doesn't handle comments but good enough for strict check
|
|
3133
3105
|
const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
3134
3106
|
const parsed = parse(cleanContent);
|
|
3135
3107
|
return parsed?.compilerOptions?.strict === true;
|
|
@@ -3144,6 +3116,19 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3144
3116
|
* @param projectPath - Project directory path
|
|
3145
3117
|
* @param packageJson - Optional pre-loaded package.json
|
|
3146
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
|
+
* ```
|
|
3147
3132
|
*/
|
|
3148
3133
|
function typescriptDetector(projectPath, packageJson) {
|
|
3149
3134
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3152,19 +3137,16 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3152
3137
|
let configPath;
|
|
3153
3138
|
let version;
|
|
3154
3139
|
const deps = collectAllDependencies(pkg);
|
|
3155
|
-
// TypeScript package
|
|
3156
3140
|
if (deps['typescript']) {
|
|
3157
3141
|
confidence += 50;
|
|
3158
3142
|
version = parseVersionString(deps['typescript']);
|
|
3159
3143
|
sources.push({ type: 'package.json', field: 'dependencies.typescript' });
|
|
3160
3144
|
}
|
|
3161
|
-
// tsconfig.json
|
|
3162
3145
|
if (exists(join$1(projectPath, 'tsconfig.json'))) {
|
|
3163
3146
|
confidence += 40;
|
|
3164
3147
|
configPath = 'tsconfig.json';
|
|
3165
3148
|
sources.push({ type: 'config-file', path: 'tsconfig.json' });
|
|
3166
3149
|
}
|
|
3167
|
-
// tsconfig.*.json variants
|
|
3168
3150
|
const tsconfigVariants = ['tsconfig.build.json', 'tsconfig.lib.json', 'tsconfig.spec.json', 'tsconfig.app.json'];
|
|
3169
3151
|
for (const variant of tsconfigVariants) {
|
|
3170
3152
|
if (exists(join$1(projectPath, variant))) {
|
|
@@ -3173,7 +3155,6 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3173
3155
|
break;
|
|
3174
3156
|
}
|
|
3175
3157
|
}
|
|
3176
|
-
// @types packages
|
|
3177
3158
|
const typePackages = keys(deps).filter((d) => d.startsWith('@types/'));
|
|
3178
3159
|
if (typePackages.length > 0) {
|
|
3179
3160
|
confidence += 10;
|
|
@@ -3199,6 +3180,17 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3199
3180
|
* @param projectPath - Project directory path
|
|
3200
3181
|
* @param packageJson - Optional pre-loaded package.json
|
|
3201
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
|
+
* ```
|
|
3202
3194
|
*/
|
|
3203
3195
|
function flowDetector(projectPath, packageJson) {
|
|
3204
3196
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3207,24 +3199,20 @@ function flowDetector(projectPath, packageJson) {
|
|
|
3207
3199
|
let configPath;
|
|
3208
3200
|
let version;
|
|
3209
3201
|
const deps = collectAllDependencies(pkg);
|
|
3210
|
-
// flow-bin package
|
|
3211
3202
|
if (deps['flow-bin']) {
|
|
3212
3203
|
confidence += 60;
|
|
3213
3204
|
version = parseVersionString(deps['flow-bin']);
|
|
3214
3205
|
sources.push({ type: 'package.json', field: 'dependencies.flow-bin' });
|
|
3215
3206
|
}
|
|
3216
|
-
// .flowconfig
|
|
3217
3207
|
if (exists(join$1(projectPath, '.flowconfig'))) {
|
|
3218
3208
|
confidence += 40;
|
|
3219
3209
|
configPath = '.flowconfig';
|
|
3220
3210
|
sources.push({ type: 'config-file', path: '.flowconfig' });
|
|
3221
3211
|
}
|
|
3222
|
-
// flow-typed directory
|
|
3223
3212
|
if (exists(join$1(projectPath, 'flow-typed'))) {
|
|
3224
3213
|
confidence += 10;
|
|
3225
3214
|
sources.push({ type: 'directory', path: 'flow-typed/' });
|
|
3226
3215
|
}
|
|
3227
|
-
// @babel/preset-flow
|
|
3228
3216
|
if (deps['@babel/preset-flow']) {
|
|
3229
3217
|
confidence += 10;
|
|
3230
3218
|
sources.push({ type: 'package.json', field: 'dependencies.@babel/preset-flow' });
|
|
@@ -3248,7 +3236,6 @@ function flowDetector(projectPath, packageJson) {
|
|
|
3248
3236
|
* @returns `true` if the content contains JSDoc type annotations.
|
|
3249
3237
|
*/
|
|
3250
3238
|
function hasJsDocTypes(content) {
|
|
3251
|
-
// Check for JSDoc type annotations
|
|
3252
3239
|
return (content.includes('@type {') ||
|
|
3253
3240
|
content.includes('@param {') ||
|
|
3254
3241
|
content.includes('@returns {') ||
|
|
@@ -3261,20 +3248,29 @@ function hasJsDocTypes(content) {
|
|
|
3261
3248
|
* @param projectPath - Project directory path
|
|
3262
3249
|
* @param packageJson - Optional pre-loaded package.json
|
|
3263
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
|
+
* ```
|
|
3264
3263
|
*/
|
|
3265
3264
|
function jsdocDetector(projectPath, packageJson) {
|
|
3266
3265
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3267
3266
|
const sources = [];
|
|
3268
3267
|
let confidence = 0;
|
|
3269
3268
|
const deps = collectAllDependencies(pkg);
|
|
3270
|
-
// jsdoc package
|
|
3271
3269
|
if (deps['jsdoc']) {
|
|
3272
3270
|
confidence += 30;
|
|
3273
3271
|
sources.push({ type: 'package.json', field: 'dependencies.jsdoc' });
|
|
3274
3272
|
}
|
|
3275
|
-
// typescript with checkJs (JSDoc type checking)
|
|
3276
3273
|
if (deps['typescript']) {
|
|
3277
|
-
// Check if checkJs is enabled in tsconfig
|
|
3278
3274
|
const tsconfigPath = join$1(projectPath, 'tsconfig.json');
|
|
3279
3275
|
const content = readFileIfExists(tsconfigPath);
|
|
3280
3276
|
if (content) {
|
|
@@ -3291,12 +3287,10 @@ function jsdocDetector(projectPath, packageJson) {
|
|
|
3291
3287
|
}
|
|
3292
3288
|
}
|
|
3293
3289
|
}
|
|
3294
|
-
// Check for jsconfig.json (VS Code JS type checking)
|
|
3295
3290
|
if (exists(join$1(projectPath, 'jsconfig.json'))) {
|
|
3296
3291
|
confidence += 40;
|
|
3297
3292
|
sources.push({ type: 'config-file', path: 'jsconfig.json' });
|
|
3298
3293
|
}
|
|
3299
|
-
// Sample check for JSDoc annotations in source files
|
|
3300
3294
|
const srcDir = join$1(projectPath, 'src');
|
|
3301
3295
|
if (exists(srcDir)) {
|
|
3302
3296
|
try {
|
|
@@ -3347,8 +3341,6 @@ const detectAllCache = createCache({ ttl: 60000, maxSize: 50 });
|
|
|
3347
3341
|
function isDetectAllOptions(value) {
|
|
3348
3342
|
if (typeof value !== 'object' || value === null)
|
|
3349
3343
|
return false;
|
|
3350
|
-
// DetectAllOptions has skipCache or packageJson fields specifically
|
|
3351
|
-
// PackageJson never has skipCache field
|
|
3352
3344
|
return 'skipCache' in value || 'packageJson' in value;
|
|
3353
3345
|
}
|
|
3354
3346
|
/**
|
|
@@ -3361,7 +3353,7 @@ function isDetectAllOptions(value) {
|
|
|
3361
3353
|
* @param packageJsonOrOptions - Optional pre-loaded package.json or options object
|
|
3362
3354
|
* @returns All detection results organized by category
|
|
3363
3355
|
*
|
|
3364
|
-
* @example
|
|
3356
|
+
* @example Running all tech detectors
|
|
3365
3357
|
* ```typescript
|
|
3366
3358
|
* import { detectAll } from '@hyperfrontend/project-scope'
|
|
3367
3359
|
*
|
|
@@ -3380,9 +3372,7 @@ function isDetectAllOptions(value) {
|
|
|
3380
3372
|
* ```
|
|
3381
3373
|
*/
|
|
3382
3374
|
function detectAll(projectPath, packageJsonOrOptions) {
|
|
3383
|
-
// Handle backward-compatible arguments
|
|
3384
3375
|
const options = isDetectAllOptions(packageJsonOrOptions) ? packageJsonOrOptions : { packageJson: packageJsonOrOptions };
|
|
3385
|
-
// Check cache first (unless skipCache is true)
|
|
3386
3376
|
if (!options.skipCache) {
|
|
3387
3377
|
const cached = detectAllCache.get(projectPath);
|
|
3388
3378
|
if (cached) {
|
|
@@ -3433,7 +3423,6 @@ function detectAll(projectPath, packageJsonOrOptions) {
|
|
|
3433
3423
|
legacyFrameworks: result.legacyFrameworks.map((f) => f.id),
|
|
3434
3424
|
testingFrameworks: result.testingFrameworks.map((f) => f.id),
|
|
3435
3425
|
});
|
|
3436
|
-
// Cache the result
|
|
3437
3426
|
detectAllCache.set(projectPath, result);
|
|
3438
3427
|
return result;
|
|
3439
3428
|
}
|
|
@@ -3456,7 +3445,7 @@ const projectTypeLogger = createScopedLogger('project-scope:heuristics:project-t
|
|
|
3456
3445
|
* @param options - Detection options
|
|
3457
3446
|
* @returns Project type detection result with confidence score
|
|
3458
3447
|
*
|
|
3459
|
-
* @example
|
|
3448
|
+
* @example Detecting project type
|
|
3460
3449
|
* ```typescript
|
|
3461
3450
|
* import { detectProjectType } from '@hyperfrontend/project-scope'
|
|
3462
3451
|
*
|
|
@@ -3628,4 +3617,3 @@ function detectProjectType(projectPath, options) {
|
|
|
3628
3617
|
}
|
|
3629
3618
|
|
|
3630
3619
|
export { detectProjectType };
|
|
3631
|
-
//# sourceMappingURL=index.esm.js.map
|