@hyperfrontend/project-scope 0.2.1 → 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 +7 -1
- package/README.md +3 -4
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.cjs.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.cjs.js +13 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.esm.js +8 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.cjs.js +10 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.esm.js +8 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.cjs.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.cjs.js +9 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.esm.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.cjs.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.esm.js +7 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.cjs.js +15 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.esm.js +9 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.cjs.js +6 -0
- package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.esm.js +5 -0
- package/_dependencies/@hyperfrontend/logging/index.cjs.js +191 -0
- package/_dependencies/@hyperfrontend/logging/index.d.ts +151 -0
- package/_dependencies/@hyperfrontend/logging/index.esm.js +186 -0
- package/_shared/core/cache/index.cjs.js +135 -0
- package/_shared/core/cache/index.esm.js +128 -0
- package/_shared/core/errors/structured-errors/index.cjs.js +28 -0
- package/_shared/core/errors/structured-errors/index.esm.js +23 -0
- package/_shared/core/fs/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 +1702 -1910
- package/cli/index.d.ts +273 -7
- package/cli/index.d.ts.map +1 -1
- package/cli/index.esm.js +1586 -1794
- package/core/encoding/index.cjs.js +86 -401
- package/core/encoding/index.d.ts +186 -3
- package/core/encoding/index.d.ts.map +1 -1
- package/core/encoding/index.esm.js +78 -392
- package/core/fs/index.cjs.js +231 -581
- package/core/fs/index.d.ts +479 -6
- package/core/fs/index.d.ts.map +1 -1
- package/core/fs/index.esm.js +221 -571
- package/core/index.cjs.js +518 -1748
- package/core/index.d.ts +486 -9
- package/core/index.d.ts.map +1 -1
- package/core/index.esm.js +501 -1728
- package/core/path/index.cjs.js +6 -234
- package/core/path/index.d.ts +306 -5
- package/core/path/index.d.ts.map +1 -1
- package/core/path/index.esm.js +4 -232
- package/core/platform/index.cjs.js +5 -216
- package/core/platform/index.d.ts +185 -3
- package/core/platform/index.d.ts.map +1 -1
- package/core/platform/index.esm.js +3 -212
- package/heuristics/dependencies/index.cjs.js +95 -492
- package/heuristics/dependencies/index.d.ts +99 -2
- package/heuristics/dependencies/index.d.ts.map +1 -1
- package/heuristics/dependencies/index.esm.js +69 -466
- package/heuristics/entry-points/index.cjs.js +91 -795
- 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 +72 -776
- package/heuristics/framework/index.cjs.js +1481 -1410
- package/heuristics/framework/index.d.ts +104 -2
- package/heuristics/framework/index.d.ts.map +1 -1
- package/heuristics/framework/index.esm.js +1417 -1346
- package/heuristics/index.cjs.js +3206 -3301
- package/heuristics/index.d.ts +4 -5
- package/heuristics/index.d.ts.map +1 -1
- package/heuristics/index.esm.js +3231 -3326
- package/heuristics/project-type/index.cjs.js +1487 -1437
- 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 +1416 -1366
- package/index.cjs.js +3044 -3533
- package/index.d.ts +44 -10
- package/index.d.ts.map +1 -1
- package/index.esm.js +2900 -3377
- 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 -577
- package/nx/index.d.ts +279 -4
- package/nx/index.d.ts.map +1 -1
- package/nx/index.esm.js +145 -554
- package/package.json +13 -12
- package/project/config/index.cjs.js +122 -1062
- package/project/config/index.d.ts +202 -4
- package/project/config/index.d.ts.map +1 -1
- package/project/config/index.esm.js +105 -1043
- package/project/index.cjs.js +323 -1100
- package/project/index.d.ts +4 -5
- package/project/index.d.ts.map +1 -1
- package/project/index.esm.js +302 -1076
- package/project/package/index.cjs.js +191 -472
- package/project/package/index.d.ts +280 -3
- package/project/package/index.d.ts.map +1 -1
- package/project/package/index.esm.js +178 -458
- package/project/root/index.cjs.js +107 -416
- package/project/root/index.d.ts +83 -2
- package/project/root/index.d.ts.map +1 -1
- package/project/root/index.esm.js +96 -405
- package/project/traversal/index.cjs.js +94 -621
- package/project/traversal/index.d.ts +165 -3
- package/project/traversal/index.d.ts.map +1 -1
- package/project/traversal/index.esm.js +80 -607
- package/tech/backend/index.cjs.js +221 -507
- package/tech/backend/index.d.ts +205 -8
- package/tech/backend/index.d.ts.map +1 -1
- package/tech/backend/index.esm.js +200 -486
- package/tech/build/index.cjs.js +348 -635
- package/tech/build/index.d.ts +276 -10
- package/tech/build/index.d.ts.map +1 -1
- package/tech/build/index.esm.js +326 -613
- package/tech/frontend/index.cjs.js +505 -684
- package/tech/frontend/index.d.ts +379 -15
- package/tech/frontend/index.d.ts.map +1 -1
- package/tech/frontend/index.esm.js +481 -660
- package/tech/index.cjs.js +1580 -1420
- package/tech/index.d.ts +55 -32
- package/tech/index.d.ts.map +1 -1
- package/tech/index.esm.js +1513 -1353
- package/tech/legacy/index.cjs.js +97 -448
- package/tech/legacy/index.d.ts +125 -7
- package/tech/legacy/index.d.ts.map +1 -1
- package/tech/legacy/index.esm.js +79 -430
- package/tech/linting/index.cjs.js +136 -522
- package/tech/linting/index.d.ts +129 -7
- package/tech/linting/index.d.ts.map +1 -1
- package/tech/linting/index.esm.js +116 -502
- package/tech/monorepo/index.cjs.js +244 -572
- package/tech/monorepo/index.d.ts +241 -10
- package/tech/monorepo/index.d.ts.map +1 -1
- package/tech/monorepo/index.esm.js +224 -552
- package/tech/testing/index.cjs.js +214 -570
- package/tech/testing/index.d.ts +176 -8
- package/tech/testing/index.d.ts.map +1 -1
- package/tech/testing/index.esm.js +196 -552
- package/tech/types/index.cjs.js +121 -505
- package/tech/types/index.d.ts +120 -2
- package/tech/types/index.d.ts.map +1 -1
- package/tech/types/index.esm.js +99 -483
- package/vfs/index.cjs.js +647 -1142
- package/vfs/index.d.ts +360 -6
- package/vfs/index.d.ts.map +1 -1
- package/vfs/index.esm.js +672 -1167
- package/ARCHITECTURE.md +0 -370
- package/analyze.d.ts +0 -33
- package/analyze.d.ts.map +0 -1
- package/cli/commands/analyze.d.ts +0 -28
- package/cli/commands/analyze.d.ts.map +0 -1
- package/cli/commands/config.d.ts +0 -27
- package/cli/commands/config.d.ts.map +0 -1
- package/cli/commands/deps.d.ts +0 -24
- package/cli/commands/deps.d.ts.map +0 -1
- package/cli/commands/tree.d.ts +0 -36
- package/cli/commands/tree.d.ts.map +0 -1
- package/cli/index.cjs.js.map +0 -1
- package/cli/index.esm.js.map +0 -1
- package/cli/run.d.ts +0 -25
- package/cli/run.d.ts.map +0 -1
- package/cli/types.d.ts +0 -55
- package/cli/types.d.ts.map +0 -1
- package/core/cache.d.ts +0 -158
- package/core/cache.d.ts.map +0 -1
- package/core/encoding/convert.d.ts +0 -32
- package/core/encoding/convert.d.ts.map +0 -1
- package/core/encoding/detect.d.ts +0 -91
- package/core/encoding/detect.d.ts.map +0 -1
- package/core/encoding/index.cjs.js.map +0 -1
- package/core/encoding/index.esm.js.map +0 -1
- package/core/errors/structured-errors.d.ts +0 -66
- package/core/errors/structured-errors.d.ts.map +0 -1
- package/core/fs/directory.d.ts +0 -91
- package/core/fs/directory.d.ts.map +0 -1
- package/core/fs/index.cjs.js.map +0 -1
- package/core/fs/index.esm.js.map +0 -1
- package/core/fs/read.d.ts +0 -94
- package/core/fs/read.d.ts.map +0 -1
- package/core/fs/stat.d.ts +0 -58
- package/core/fs/stat.d.ts.map +0 -1
- package/core/fs/traversal.d.ts +0 -26
- package/core/fs/traversal.d.ts.map +0 -1
- package/core/fs/write.d.ts +0 -75
- package/core/fs/write.d.ts.map +0 -1
- package/core/index.cjs.js.map +0 -1
- package/core/index.esm.js.map +0 -1
- package/core/logger.d.ts +0 -111
- package/core/logger.d.ts.map +0 -1
- package/core/path/index.cjs.js.map +0 -1
- package/core/path/index.esm.js.map +0 -1
- package/core/path/join.d.ts +0 -17
- package/core/path/join.d.ts.map +0 -1
- package/core/path/normalize.d.ts +0 -37
- package/core/path/normalize.d.ts.map +0 -1
- package/core/path/resolve.d.ts +0 -52
- package/core/path/resolve.d.ts.map +0 -1
- package/core/path/segments.d.ts +0 -59
- package/core/path/segments.d.ts.map +0 -1
- package/core/patterns/glob.d.ts +0 -42
- package/core/patterns/glob.d.ts.map +0 -1
- package/core/platform/detect.d.ts +0 -66
- package/core/platform/detect.d.ts.map +0 -1
- package/core/platform/index.cjs.js.map +0 -1
- package/core/platform/index.esm.js.map +0 -1
- package/core/platform/line-endings.d.ts +0 -48
- package/core/platform/line-endings.d.ts.map +0 -1
- package/heuristics/dependencies/analyze.d.ts +0 -77
- package/heuristics/dependencies/analyze.d.ts.map +0 -1
- package/heuristics/dependencies/index.cjs.js.map +0 -1
- package/heuristics/dependencies/index.esm.js.map +0 -1
- package/heuristics/entry-points/discover.d.ts +0 -113
- package/heuristics/entry-points/discover.d.ts.map +0 -1
- package/heuristics/entry-points/index.cjs.js.map +0 -1
- package/heuristics/entry-points/index.esm.js.map +0 -1
- package/heuristics/framework/identify.d.ts +0 -84
- package/heuristics/framework/identify.d.ts.map +0 -1
- package/heuristics/framework/index.cjs.js.map +0 -1
- package/heuristics/framework/index.esm.js.map +0 -1
- package/heuristics/index.cjs.js.map +0 -1
- package/heuristics/index.esm.js.map +0 -1
- package/heuristics/project-type/detect.d.ts +0 -61
- package/heuristics/project-type/detect.d.ts.map +0 -1
- package/heuristics/project-type/index.cjs.js.map +0 -1
- package/heuristics/project-type/index.esm.js.map +0 -1
- package/index.cjs.js.map +0 -1
- package/index.esm.js.map +0 -1
- package/models/index.cjs.js.map +0 -1
- package/models/index.esm.js.map +0 -1
- package/nx/detect.d.ts +0 -105
- package/nx/detect.d.ts.map +0 -1
- package/nx/devkit-loader.d.ts +0 -62
- package/nx/devkit-loader.d.ts.map +0 -1
- package/nx/index.cjs.js.map +0 -1
- package/nx/index.esm.js.map +0 -1
- package/nx/project-config.d.ts +0 -111
- package/nx/project-config.d.ts.map +0 -1
- package/project/config/detect.d.ts +0 -77
- package/project/config/detect.d.ts.map +0 -1
- package/project/config/index.cjs.js.map +0 -1
- package/project/config/index.esm.js.map +0 -1
- package/project/config/parse.d.ts +0 -53
- package/project/config/parse.d.ts.map +0 -1
- package/project/config/patterns.d.ts +0 -31
- package/project/config/patterns.d.ts.map +0 -1
- package/project/index.cjs.js.map +0 -1
- package/project/index.esm.js.map +0 -1
- package/project/package/dependencies.d.ts +0 -101
- package/project/package/dependencies.d.ts.map +0 -1
- package/project/package/index.cjs.js.map +0 -1
- package/project/package/index.esm.js.map +0 -1
- package/project/package/read.d.ts +0 -67
- package/project/package/read.d.ts.map +0 -1
- package/project/root/detect.d.ts +0 -65
- package/project/root/detect.d.ts.map +0 -1
- package/project/root/index.cjs.js.map +0 -1
- package/project/root/index.esm.js.map +0 -1
- package/project/traversal/index.cjs.js.map +0 -1
- package/project/traversal/index.esm.js.map +0 -1
- package/project/traversal/search.d.ts +0 -59
- package/project/traversal/search.d.ts.map +0 -1
- package/project/traversal/walk.d.ts +0 -63
- package/project/traversal/walk.d.ts.map +0 -1
- package/tech/backend/detect-all.d.ts +0 -13
- package/tech/backend/detect-all.d.ts.map +0 -1
- package/tech/backend/express.d.ts +0 -11
- package/tech/backend/express.d.ts.map +0 -1
- package/tech/backend/fastify.d.ts +0 -11
- package/tech/backend/fastify.d.ts.map +0 -1
- package/tech/backend/hono.d.ts +0 -11
- package/tech/backend/hono.d.ts.map +0 -1
- package/tech/backend/index.cjs.js.map +0 -1
- package/tech/backend/index.esm.js.map +0 -1
- package/tech/backend/koa.d.ts +0 -11
- package/tech/backend/koa.d.ts.map +0 -1
- package/tech/backend/nestjs.d.ts +0 -11
- package/tech/backend/nestjs.d.ts.map +0 -1
- package/tech/backend/types.d.ts +0 -31
- package/tech/backend/types.d.ts.map +0 -1
- package/tech/build/babel.d.ts +0 -13
- package/tech/build/babel.d.ts.map +0 -1
- package/tech/build/detect-all.d.ts +0 -13
- package/tech/build/detect-all.d.ts.map +0 -1
- package/tech/build/esbuild.d.ts +0 -11
- package/tech/build/esbuild.d.ts.map +0 -1
- package/tech/build/index.cjs.js.map +0 -1
- package/tech/build/index.esm.js.map +0 -1
- package/tech/build/parcel.d.ts +0 -13
- package/tech/build/parcel.d.ts.map +0 -1
- package/tech/build/rollup.d.ts +0 -13
- package/tech/build/rollup.d.ts.map +0 -1
- package/tech/build/swc.d.ts +0 -13
- package/tech/build/swc.d.ts.map +0 -1
- package/tech/build/types.d.ts +0 -31
- package/tech/build/types.d.ts.map +0 -1
- package/tech/build/vite.d.ts +0 -13
- package/tech/build/vite.d.ts.map +0 -1
- package/tech/build/webpack.d.ts +0 -13
- package/tech/build/webpack.d.ts.map +0 -1
- package/tech/frontend/angular.d.ts +0 -11
- package/tech/frontend/angular.d.ts.map +0 -1
- package/tech/frontend/astro.d.ts +0 -11
- package/tech/frontend/astro.d.ts.map +0 -1
- package/tech/frontend/detect-all.d.ts +0 -13
- package/tech/frontend/detect-all.d.ts.map +0 -1
- package/tech/frontend/gatsby.d.ts +0 -11
- package/tech/frontend/gatsby.d.ts.map +0 -1
- package/tech/frontend/index.cjs.js.map +0 -1
- package/tech/frontend/index.esm.js.map +0 -1
- package/tech/frontend/nextjs.d.ts +0 -11
- package/tech/frontend/nextjs.d.ts.map +0 -1
- package/tech/frontend/nuxt.d.ts +0 -11
- package/tech/frontend/nuxt.d.ts.map +0 -1
- package/tech/frontend/qwik.d.ts +0 -11
- package/tech/frontend/qwik.d.ts.map +0 -1
- package/tech/frontend/react.d.ts +0 -11
- package/tech/frontend/react.d.ts.map +0 -1
- package/tech/frontend/remix.d.ts +0 -11
- package/tech/frontend/remix.d.ts.map +0 -1
- package/tech/frontend/solid.d.ts +0 -11
- package/tech/frontend/solid.d.ts.map +0 -1
- package/tech/frontend/svelte.d.ts +0 -11
- package/tech/frontend/svelte.d.ts.map +0 -1
- package/tech/frontend/sveltekit.d.ts +0 -11
- package/tech/frontend/sveltekit.d.ts.map +0 -1
- package/tech/frontend/types.d.ts +0 -35
- package/tech/frontend/types.d.ts.map +0 -1
- package/tech/frontend/vue.d.ts +0 -11
- package/tech/frontend/vue.d.ts.map +0 -1
- package/tech/index.cjs.js.map +0 -1
- package/tech/index.esm.js.map +0 -1
- package/tech/legacy/angularjs.d.ts +0 -12
- package/tech/legacy/angularjs.d.ts.map +0 -1
- package/tech/legacy/backbone.d.ts +0 -11
- package/tech/legacy/backbone.d.ts.map +0 -1
- package/tech/legacy/detect-all.d.ts +0 -13
- package/tech/legacy/detect-all.d.ts.map +0 -1
- package/tech/legacy/ember.d.ts +0 -11
- package/tech/legacy/ember.d.ts.map +0 -1
- package/tech/legacy/index.cjs.js.map +0 -1
- package/tech/legacy/index.esm.js.map +0 -1
- package/tech/legacy/jquery.d.ts +0 -11
- package/tech/legacy/jquery.d.ts.map +0 -1
- package/tech/legacy/types.d.ts +0 -33
- package/tech/legacy/types.d.ts.map +0 -1
- package/tech/linting/biome.d.ts +0 -11
- package/tech/linting/biome.d.ts.map +0 -1
- package/tech/linting/detect-all.d.ts +0 -13
- package/tech/linting/detect-all.d.ts.map +0 -1
- package/tech/linting/eslint.d.ts +0 -13
- package/tech/linting/eslint.d.ts.map +0 -1
- package/tech/linting/index.cjs.js.map +0 -1
- package/tech/linting/index.esm.js.map +0 -1
- package/tech/linting/prettier.d.ts +0 -13
- package/tech/linting/prettier.d.ts.map +0 -1
- package/tech/linting/stylelint.d.ts +0 -13
- package/tech/linting/stylelint.d.ts.map +0 -1
- package/tech/linting/types.d.ts +0 -31
- package/tech/linting/types.d.ts.map +0 -1
- package/tech/monorepo/detect-all.d.ts +0 -13
- package/tech/monorepo/detect-all.d.ts.map +0 -1
- package/tech/monorepo/index.cjs.js.map +0 -1
- package/tech/monorepo/index.esm.js.map +0 -1
- package/tech/monorepo/lerna.d.ts +0 -11
- package/tech/monorepo/lerna.d.ts.map +0 -1
- package/tech/monorepo/npm-workspaces.d.ts +0 -11
- package/tech/monorepo/npm-workspaces.d.ts.map +0 -1
- package/tech/monorepo/nx.d.ts +0 -11
- package/tech/monorepo/nx.d.ts.map +0 -1
- package/tech/monorepo/pnpm-workspaces.d.ts +0 -9
- package/tech/monorepo/pnpm-workspaces.d.ts.map +0 -1
- package/tech/monorepo/rush.d.ts +0 -11
- package/tech/monorepo/rush.d.ts.map +0 -1
- package/tech/monorepo/turborepo.d.ts +0 -11
- package/tech/monorepo/turborepo.d.ts.map +0 -1
- package/tech/monorepo/types.d.ts +0 -39
- package/tech/monorepo/types.d.ts.map +0 -1
- package/tech/monorepo/yarn-workspaces.d.ts +0 -11
- package/tech/monorepo/yarn-workspaces.d.ts.map +0 -1
- package/tech/shared-utils/detector-helpers.d.ts +0 -52
- package/tech/shared-utils/detector-helpers.d.ts.map +0 -1
- package/tech/shared-utils/types.d.ts +0 -41
- package/tech/shared-utils/types.d.ts.map +0 -1
- package/tech/testing/cypress.d.ts +0 -13
- package/tech/testing/cypress.d.ts.map +0 -1
- package/tech/testing/detect-all.d.ts +0 -13
- package/tech/testing/detect-all.d.ts.map +0 -1
- package/tech/testing/index.cjs.js.map +0 -1
- package/tech/testing/index.esm.js.map +0 -1
- package/tech/testing/jest.d.ts +0 -13
- package/tech/testing/jest.d.ts.map +0 -1
- package/tech/testing/mocha.d.ts +0 -13
- package/tech/testing/mocha.d.ts.map +0 -1
- package/tech/testing/playwright.d.ts +0 -13
- package/tech/testing/playwright.d.ts.map +0 -1
- package/tech/testing/types.d.ts +0 -35
- package/tech/testing/types.d.ts.map +0 -1
- package/tech/testing/vitest.d.ts +0 -13
- package/tech/testing/vitest.d.ts.map +0 -1
- package/tech/types/detectors.d.ts +0 -67
- package/tech/types/detectors.d.ts.map +0 -1
- package/tech/types/index.cjs.js.map +0 -1
- package/tech/types/index.esm.js.map +0 -1
- package/vfs/commit.d.ts +0 -32
- package/vfs/commit.d.ts.map +0 -1
- package/vfs/diff.d.ts +0 -73
- package/vfs/diff.d.ts.map +0 -1
- package/vfs/factory.d.ts +0 -37
- package/vfs/factory.d.ts.map +0 -1
- package/vfs/fs-tree.d.ts +0 -13
- package/vfs/fs-tree.d.ts.map +0 -1
- package/vfs/index.cjs.js.map +0 -1
- package/vfs/index.esm.js.map +0 -1
- package/vfs/types.d.ts +0 -179
- package/vfs/types.d.ts.map +0 -1
|
@@ -1,423 +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
|
-
* (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
|
|
15
|
-
*/
|
|
16
|
-
const parse = _JSON.parse;
|
|
17
|
-
/**
|
|
18
|
-
* (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
|
19
|
-
*/
|
|
20
|
-
const stringify = _JSON.stringify;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Safe copies of Math built-in methods.
|
|
24
|
-
*
|
|
25
|
-
* These references are captured at module initialization time to protect against
|
|
26
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
27
|
-
*
|
|
28
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/math
|
|
29
|
-
*/
|
|
30
|
-
const _Math = globalThis.Math;
|
|
31
|
-
/**
|
|
32
|
-
* (Safe copy) Returns the value of a number rounded to the nearest integer.
|
|
33
|
-
*/
|
|
34
|
-
const round = _Math.round;
|
|
35
|
-
/**
|
|
36
|
-
* (Safe copy) Returns the smaller of zero or more numbers.
|
|
37
|
-
*/
|
|
38
|
-
const min = _Math.min;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Safe copies of Object built-in methods.
|
|
42
|
-
*
|
|
43
|
-
* These references are captured at module initialization time to protect against
|
|
44
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
45
|
-
*
|
|
46
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/object
|
|
47
|
-
*/
|
|
48
|
-
const _Object = globalThis.Object;
|
|
49
|
-
/**
|
|
50
|
-
* (Safe copy) Prevents modification of existing property attributes and values,
|
|
51
|
-
* and prevents the addition of new properties.
|
|
52
|
-
*/
|
|
53
|
-
const freeze = _Object.freeze;
|
|
54
|
-
/**
|
|
55
|
-
* (Safe copy) Returns the names of the enumerable string properties and methods of an object.
|
|
56
|
-
*/
|
|
57
|
-
const keys = _Object.keys;
|
|
58
|
-
/**
|
|
59
|
-
* (Safe copy) Returns an array of key/values of the enumerable own properties of an object.
|
|
60
|
-
*/
|
|
61
|
-
const entries = _Object.entries;
|
|
62
|
-
/**
|
|
63
|
-
* (Safe copy) Returns an array of values of the enumerable own properties of an object.
|
|
64
|
-
*/
|
|
65
|
-
const values = _Object.values;
|
|
66
|
-
/**
|
|
67
|
-
* (Safe copy) Adds one or more properties to an object, and/or modifies attributes of existing properties.
|
|
68
|
-
*/
|
|
69
|
-
const defineProperties = _Object.defineProperties;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Safe copies of Error built-ins via factory functions.
|
|
73
|
-
*
|
|
74
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
75
|
-
* provides factory functions that use Reflect.construct internally.
|
|
76
|
-
*
|
|
77
|
-
* These references are captured at module initialization time to protect against
|
|
78
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
79
|
-
*
|
|
80
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
81
|
-
*/
|
|
82
|
-
const _Error = globalThis.Error;
|
|
83
|
-
const _Reflect$2 = globalThis.Reflect;
|
|
84
|
-
/**
|
|
85
|
-
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
86
|
-
* Use this instead of `new Error()`.
|
|
87
|
-
*
|
|
88
|
-
* @param message - Optional error message.
|
|
89
|
-
* @param options - Optional error options.
|
|
90
|
-
* @returns A new Error instance.
|
|
91
|
-
*/
|
|
92
|
-
const createError = (message, options) => _Reflect$2.construct(_Error, [message, options]);
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Safe copies of Array built-in static methods.
|
|
96
|
-
*
|
|
97
|
-
* These references are captured at module initialization time to protect against
|
|
98
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
99
|
-
*
|
|
100
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/array
|
|
101
|
-
*/
|
|
102
|
-
const _Array = globalThis.Array;
|
|
103
|
-
/**
|
|
104
|
-
* (Safe copy) Determines whether the passed value is an Array.
|
|
105
|
-
*/
|
|
106
|
-
const isArray = _Array.isArray;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Safe copies of Console built-in methods.
|
|
110
|
-
*
|
|
111
|
-
* These references are captured at module initialization time to protect against
|
|
112
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
113
|
-
*
|
|
114
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/console
|
|
115
|
-
*/
|
|
116
|
-
const _console = globalThis.console;
|
|
117
|
-
/**
|
|
118
|
-
* (Safe copy) Outputs a message to the console.
|
|
119
|
-
*/
|
|
120
|
-
const log = _console.log.bind(_console);
|
|
121
|
-
/**
|
|
122
|
-
* (Safe copy) Outputs a warning message to the console.
|
|
123
|
-
*/
|
|
124
|
-
const warn = _console.warn.bind(_console);
|
|
125
|
-
/**
|
|
126
|
-
* (Safe copy) Outputs an error message to the console.
|
|
127
|
-
*/
|
|
128
|
-
const error = _console.error.bind(_console);
|
|
129
|
-
/**
|
|
130
|
-
* (Safe copy) Outputs an informational message to the console.
|
|
131
|
-
*/
|
|
132
|
-
const info = _console.info.bind(_console);
|
|
133
|
-
/**
|
|
134
|
-
* (Safe copy) Outputs a debug message to the console.
|
|
135
|
-
*/
|
|
136
|
-
const debug = _console.debug.bind(_console);
|
|
137
|
-
/**
|
|
138
|
-
* (Safe copy) Outputs a stack trace to the console.
|
|
139
|
-
*/
|
|
140
|
-
_console.trace.bind(_console);
|
|
141
|
-
/**
|
|
142
|
-
* (Safe copy) Displays an interactive listing of the properties of a specified object.
|
|
143
|
-
*/
|
|
144
|
-
_console.dir.bind(_console);
|
|
145
|
-
/**
|
|
146
|
-
* (Safe copy) Displays tabular data as a table.
|
|
147
|
-
*/
|
|
148
|
-
_console.table.bind(_console);
|
|
149
|
-
/**
|
|
150
|
-
* (Safe copy) Writes an error message to the console if the assertion is false.
|
|
151
|
-
*/
|
|
152
|
-
_console.assert.bind(_console);
|
|
153
|
-
/**
|
|
154
|
-
* (Safe copy) Clears the console.
|
|
155
|
-
*/
|
|
156
|
-
_console.clear.bind(_console);
|
|
157
|
-
/**
|
|
158
|
-
* (Safe copy) Logs the number of times that this particular call to count() has been called.
|
|
159
|
-
*/
|
|
160
|
-
_console.count.bind(_console);
|
|
161
|
-
/**
|
|
162
|
-
* (Safe copy) Resets the counter used with console.count().
|
|
163
|
-
*/
|
|
164
|
-
_console.countReset.bind(_console);
|
|
165
|
-
/**
|
|
166
|
-
* (Safe copy) Creates a new inline group in the console.
|
|
167
|
-
*/
|
|
168
|
-
_console.group.bind(_console);
|
|
169
|
-
/**
|
|
170
|
-
* (Safe copy) Creates a new inline group in the console that is initially collapsed.
|
|
171
|
-
*/
|
|
172
|
-
_console.groupCollapsed.bind(_console);
|
|
173
|
-
/**
|
|
174
|
-
* (Safe copy) Exits the current inline group.
|
|
175
|
-
*/
|
|
176
|
-
_console.groupEnd.bind(_console);
|
|
177
|
-
/**
|
|
178
|
-
* (Safe copy) Starts a timer with a name specified as an input parameter.
|
|
179
|
-
*/
|
|
180
|
-
_console.time.bind(_console);
|
|
181
|
-
/**
|
|
182
|
-
* (Safe copy) Stops a timer that was previously started.
|
|
183
|
-
*/
|
|
184
|
-
_console.timeEnd.bind(_console);
|
|
185
|
-
/**
|
|
186
|
-
* (Safe copy) Logs the current value of a timer that was previously started.
|
|
187
|
-
*/
|
|
188
|
-
_console.timeLog.bind(_console);
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Safe copies of Set built-in via factory function.
|
|
192
|
-
*
|
|
193
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
194
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
195
|
-
*
|
|
196
|
-
* These references are captured at module initialization time to protect against
|
|
197
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
198
|
-
*
|
|
199
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/set
|
|
200
|
-
*/
|
|
201
|
-
const _Set = globalThis.Set;
|
|
202
|
-
const _Reflect$1 = globalThis.Reflect;
|
|
203
|
-
/**
|
|
204
|
-
* (Safe copy) Creates a new Set using the captured Set constructor.
|
|
205
|
-
* Use this instead of `new Set()`.
|
|
206
|
-
*
|
|
207
|
-
* @param iterable - Optional iterable of values.
|
|
208
|
-
* @returns A new Set instance.
|
|
209
|
-
*/
|
|
210
|
-
const createSet = (iterable) => _Reflect$1.construct(_Set, iterable ? [iterable] : []);
|
|
211
|
-
|
|
212
|
-
const registeredClasses = [];
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Returns the data type of the target.
|
|
216
|
-
* Uses native `typeof` operator, however, makes distinction between `null`, `array`, and `object`.
|
|
217
|
-
* Also, when classes are registered via `registerClass`, it checks if objects are instance of any known registered class.
|
|
218
|
-
*
|
|
219
|
-
* @param target - The target to get the data type of.
|
|
220
|
-
* @returns The data type of the target.
|
|
221
|
-
*/
|
|
222
|
-
const getType = (target) => {
|
|
223
|
-
if (target === null)
|
|
224
|
-
return 'null';
|
|
225
|
-
const nativeDataType = typeof target;
|
|
226
|
-
if (nativeDataType === 'object') {
|
|
227
|
-
if (isArray(target))
|
|
228
|
-
return 'array';
|
|
229
|
-
for (const registeredClass of registeredClasses) {
|
|
230
|
-
if (target instanceof registeredClass)
|
|
231
|
-
return registeredClass.name;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
return nativeDataType;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Safe copies of Map built-in via factory function.
|
|
239
|
-
*
|
|
240
|
-
* Since constructors cannot be safely captured via Object.assign, this module
|
|
241
|
-
* provides a factory function that uses Reflect.construct internally.
|
|
242
|
-
*
|
|
243
|
-
* These references are captured at module initialization time to protect against
|
|
244
|
-
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
245
|
-
*
|
|
246
|
-
* @module @hyperfrontend/immutable-api-utils/built-in-copy/map
|
|
247
|
-
*/
|
|
248
|
-
const _Map = globalThis.Map;
|
|
249
|
-
const _Reflect = globalThis.Reflect;
|
|
250
|
-
/**
|
|
251
|
-
* (Safe copy) Creates a new Map using the captured Map constructor.
|
|
252
|
-
* Use this instead of `new Map()`.
|
|
253
|
-
*
|
|
254
|
-
* @param iterable - Optional iterable of key-value pairs.
|
|
255
|
-
* @returns A new Map instance.
|
|
256
|
-
*/
|
|
257
|
-
const createMap = (iterable) => _Reflect.construct(_Map, iterable ? [iterable] : []);
|
|
258
|
-
|
|
259
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
260
|
-
/**
|
|
261
|
-
* Creates a wrapper function that only executes the wrapped function if the condition function returns true.
|
|
262
|
-
*
|
|
263
|
-
* @param func - The function to be conditionally executed.
|
|
264
|
-
* @param conditionFunc - A function that returns a boolean, determining if `func` should be executed.
|
|
265
|
-
* @returns A wrapped version of `func` that executes conditionally.
|
|
266
|
-
*/
|
|
267
|
-
function createConditionalExecutionFunction(func, conditionFunc) {
|
|
268
|
-
return function (...args) {
|
|
269
|
-
if (conditionFunc()) {
|
|
270
|
-
return func(...args);
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
276
|
-
/**
|
|
277
|
-
* Creates a wrapper function that silently ignores any errors thrown by the wrapped void function.
|
|
278
|
-
* This function is specifically for wrapping functions that do not return a value (void functions).
|
|
279
|
-
* Exceptions are swallowed without any logging or handling.
|
|
280
|
-
*
|
|
281
|
-
* @param func - The void function to be wrapped.
|
|
282
|
-
* @returns A wrapped version of the input function that ignores errors.
|
|
283
|
-
*/
|
|
284
|
-
function createErrorIgnoringFunction(func) {
|
|
285
|
-
return function (...args) {
|
|
286
|
-
try {
|
|
287
|
-
func(...args);
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
// Deliberately swallowing/ignoring the exception
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
296
|
-
/**
|
|
297
|
-
* A no-operation function (noop) that does nothing regardless of the arguments passed.
|
|
298
|
-
* It is designed to be as permissive as possible in its typing without using the `Function` keyword.
|
|
299
|
-
*
|
|
300
|
-
* @param args - Any arguments passed to the function (ignored)
|
|
301
|
-
*/
|
|
302
|
-
const noop = (...args) => {
|
|
303
|
-
// Intentionally does nothing
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const logLevels = ['none', 'error', 'warn', 'log', 'info', 'debug'];
|
|
307
|
-
const priority = {
|
|
308
|
-
error: 4,
|
|
309
|
-
warn: 3,
|
|
310
|
-
log: 2,
|
|
311
|
-
info: 1,
|
|
312
|
-
debug: 0,
|
|
313
|
-
};
|
|
314
|
-
/**
|
|
315
|
-
* Validates whether a given string is a valid log level.
|
|
316
|
-
*
|
|
317
|
-
* @param level - The log level to validate
|
|
318
|
-
* @returns True if the level is valid, false otherwise
|
|
319
|
-
*/
|
|
320
|
-
function isValidLogLevel(level) {
|
|
321
|
-
return logLevels.includes(level);
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Creates a log level configuration manager for controlling logging behavior.
|
|
325
|
-
* Provides methods to get, set, and evaluate log levels based on priority.
|
|
326
|
-
*
|
|
327
|
-
* @param level - The initial log level (defaults to 'error')
|
|
328
|
-
* @returns A configuration object with log level management methods
|
|
329
|
-
* @throws {Error} When the provided level is not a valid log level
|
|
330
|
-
*/
|
|
331
|
-
function createLogLevelConfig(level = 'error') {
|
|
332
|
-
if (!isValidLogLevel(level)) {
|
|
333
|
-
throw createError('Cannot create log level configuration with a valid default log level');
|
|
334
|
-
}
|
|
335
|
-
const state = { level };
|
|
336
|
-
const getLogLevel = () => state.level;
|
|
337
|
-
const setLogLevel = (level) => {
|
|
338
|
-
if (!isValidLogLevel(level)) {
|
|
339
|
-
throw createError(`Cannot set value '${level}' level. Expected levels are ${logLevels}.`);
|
|
340
|
-
}
|
|
341
|
-
state.level = level;
|
|
342
|
-
};
|
|
343
|
-
const shouldLog = (level) => {
|
|
344
|
-
if (state.level === 'none' || level === 'none' || !isValidLogLevel(level)) {
|
|
345
|
-
return false;
|
|
346
|
-
}
|
|
347
|
-
return priority[level] >= priority[state.level];
|
|
348
|
-
};
|
|
349
|
-
return freeze({
|
|
350
|
-
getLogLevel,
|
|
351
|
-
setLogLevel,
|
|
352
|
-
shouldLog,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Creates a logger instance with configurable log level filtering.
|
|
358
|
-
* Each log function is wrapped to respect the current log level setting.
|
|
359
|
-
*
|
|
360
|
-
* @param error - Function to handle error-level logs (required)
|
|
361
|
-
* @param warn - Function to handle warning-level logs (optional, defaults to noop)
|
|
362
|
-
* @param log - Function to handle standard logs (optional, defaults to noop)
|
|
363
|
-
* @param info - Function to handle info-level logs (optional, defaults to noop)
|
|
364
|
-
* @param debug - Function to handle debug-level logs (optional, defaults to noop)
|
|
365
|
-
* @returns A frozen logger object with log methods and level control
|
|
366
|
-
* @throws {ErrorLevelFn} When any provided log function is invalid
|
|
367
|
-
*/
|
|
368
|
-
function createLogger(error, warn = noop, log = noop, info = noop, debug = noop) {
|
|
369
|
-
if (notValidLogFn(error)) {
|
|
370
|
-
throw createError(notFnMsg('error'));
|
|
371
|
-
}
|
|
372
|
-
if (notValidLogFn(warn)) {
|
|
373
|
-
throw createError(notFnMsg('warn'));
|
|
374
|
-
}
|
|
375
|
-
if (notValidLogFn(log)) {
|
|
376
|
-
throw createError(notFnMsg('log'));
|
|
377
|
-
}
|
|
378
|
-
if (notValidLogFn(info)) {
|
|
379
|
-
throw createError(notFnMsg('info'));
|
|
380
|
-
}
|
|
381
|
-
if (notValidLogFn(debug)) {
|
|
382
|
-
throw createError(notFnMsg('debug'));
|
|
383
|
-
}
|
|
384
|
-
const { setLogLevel, getLogLevel, shouldLog } = createLogLevelConfig();
|
|
385
|
-
const wrapLogFn = (fn, level) => {
|
|
386
|
-
if (fn === noop)
|
|
387
|
-
return fn;
|
|
388
|
-
const condition = () => shouldLog(level);
|
|
389
|
-
return createConditionalExecutionFunction(createErrorIgnoringFunction(fn), condition);
|
|
390
|
-
};
|
|
391
|
-
return freeze({
|
|
392
|
-
error: wrapLogFn(error, 'error'),
|
|
393
|
-
warn: wrapLogFn(warn, 'warn'),
|
|
394
|
-
log: wrapLogFn(log, 'log'),
|
|
395
|
-
info: wrapLogFn(info, 'info'),
|
|
396
|
-
debug: wrapLogFn(debug, 'debug'),
|
|
397
|
-
setLogLevel,
|
|
398
|
-
getLogLevel,
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Validates whether a given value is a valid log function.
|
|
403
|
-
*
|
|
404
|
-
* @param fn - The value to validate
|
|
405
|
-
* @returns True if the value is not a function (invalid), false if it is valid
|
|
406
|
-
*/
|
|
407
|
-
function notValidLogFn(fn) {
|
|
408
|
-
return getType(fn) !== 'function' && fn !== noop;
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Generates an error message for invalid log function parameters.
|
|
412
|
-
*
|
|
413
|
-
* @param label - The name of the log function that failed validation
|
|
414
|
-
* @returns A formatted error message string
|
|
415
|
-
*/
|
|
416
|
-
function notFnMsg(label) {
|
|
417
|
-
return `Cannot create a logger when ${label} is not a function`;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
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';
|
|
421
17
|
|
|
422
18
|
/**
|
|
423
19
|
* Global log level registry.
|
|
@@ -457,6 +53,13 @@ function isSensitiveKey(key) {
|
|
|
457
53
|
*
|
|
458
54
|
* @param obj - Object to sanitize
|
|
459
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
|
+
* ```
|
|
460
63
|
*/
|
|
461
64
|
function sanitize(obj) {
|
|
462
65
|
if (obj === null || obj === undefined) {
|
|
@@ -507,7 +110,7 @@ function formatMessage(namespace, message, meta) {
|
|
|
507
110
|
* @param options - Logger configuration options
|
|
508
111
|
* @returns A configured scoped logger instance
|
|
509
112
|
*
|
|
510
|
-
* @example
|
|
113
|
+
* @example Creating a scoped logger
|
|
511
114
|
* ```typescript
|
|
512
115
|
* const logger = createScopedLogger('project-scope')
|
|
513
116
|
* logger.setLogLevel('debug')
|
|
@@ -544,7 +147,7 @@ function createScopedLogger(namespace, options = {}) {
|
|
|
544
147
|
* Default logger instance for the project-scope library.
|
|
545
148
|
* Use this for general logging within the library.
|
|
546
149
|
*
|
|
547
|
-
* @example
|
|
150
|
+
* @example Using the default logger
|
|
548
151
|
* ```typescript
|
|
549
152
|
* import { logger } from '@hyperfrontend/project-scope/core'
|
|
550
153
|
*
|
|
@@ -562,6 +165,15 @@ createScopedLogger('project-scope:fs');
|
|
|
562
165
|
* @param code - The category code for this type of filesystem failure
|
|
563
166
|
* @param context - Additional context including path, operation, and cause
|
|
564
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
|
+
* ```
|
|
565
177
|
*/
|
|
566
178
|
function createFileSystemError(message, code, context) {
|
|
567
179
|
const error = createError(message);
|
|
@@ -577,6 +189,14 @@ function createFileSystemError(message, code, context) {
|
|
|
577
189
|
* @param filePath - Path to file
|
|
578
190
|
* @param encoding - File encoding (default: utf-8)
|
|
579
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
|
+
* ```
|
|
580
200
|
*/
|
|
581
201
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
582
202
|
if (!existsSync(filePath)) {
|
|
@@ -590,56 +210,6 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
590
210
|
}
|
|
591
211
|
}
|
|
592
212
|
|
|
593
|
-
createScopedLogger('project-scope:fs:write');
|
|
594
|
-
|
|
595
|
-
/**
|
|
596
|
-
* Get file stats with error handling.
|
|
597
|
-
*
|
|
598
|
-
* @param filePath - Path to file
|
|
599
|
-
* @param followSymlinks - Whether to follow symlinks (default: true)
|
|
600
|
-
* @returns File stats or null if path doesn't exist
|
|
601
|
-
*/
|
|
602
|
-
function getFileStat(filePath, followSymlinks = true) {
|
|
603
|
-
if (!existsSync(filePath)) {
|
|
604
|
-
return null;
|
|
605
|
-
}
|
|
606
|
-
try {
|
|
607
|
-
const stat = followSymlinks ? statSync(filePath) : lstatSync(filePath);
|
|
608
|
-
return {
|
|
609
|
-
isFile: stat.isFile(),
|
|
610
|
-
isDirectory: stat.isDirectory(),
|
|
611
|
-
isSymlink: stat.isSymbolicLink(),
|
|
612
|
-
size: stat.size,
|
|
613
|
-
created: stat.birthtime,
|
|
614
|
-
modified: stat.mtime,
|
|
615
|
-
accessed: stat.atime,
|
|
616
|
-
mode: stat.mode,
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
catch {
|
|
620
|
-
return null;
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* Check if path is a directory.
|
|
625
|
-
*
|
|
626
|
-
* @param dirPath - Path to check
|
|
627
|
-
* @returns True if path is a directory
|
|
628
|
-
*/
|
|
629
|
-
function isDirectory(dirPath) {
|
|
630
|
-
const stats = getFileStat(dirPath);
|
|
631
|
-
return stats?.isDirectory ?? false;
|
|
632
|
-
}
|
|
633
|
-
/**
|
|
634
|
-
* Check if path exists.
|
|
635
|
-
*
|
|
636
|
-
* @param filePath - Path to check
|
|
637
|
-
* @returns True if path exists
|
|
638
|
-
*/
|
|
639
|
-
function exists(filePath) {
|
|
640
|
-
return existsSync(filePath);
|
|
641
|
-
}
|
|
642
|
-
|
|
643
213
|
const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
644
214
|
/**
|
|
645
215
|
* List immediate contents of a directory.
|
|
@@ -648,7 +218,7 @@ const fsDirLogger = createScopedLogger('project-scope:fs:dir');
|
|
|
648
218
|
* @returns Array of entries with metadata for each file/directory
|
|
649
219
|
* @throws {Error} If directory doesn't exist or isn't a directory
|
|
650
220
|
*
|
|
651
|
-
* @example
|
|
221
|
+
* @example Listing directory contents
|
|
652
222
|
* ```typescript
|
|
653
223
|
* import { readDirectory } from '@hyperfrontend/project-scope'
|
|
654
224
|
*
|
|
@@ -689,19 +259,10 @@ function readDirectory(dirPath) {
|
|
|
689
259
|
}
|
|
690
260
|
}
|
|
691
261
|
|
|
692
|
-
/**
|
|
693
|
-
* Join path segments.
|
|
694
|
-
* Uses platform-specific separators (e.g., / or \).
|
|
695
|
-
*
|
|
696
|
-
* @param paths - Path segments to join
|
|
697
|
-
* @returns Joined path
|
|
698
|
-
*/
|
|
699
|
-
function join(...paths) {
|
|
700
|
-
return join$1(...paths);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
262
|
createScopedLogger('project-scope:fs:traversal');
|
|
704
263
|
|
|
264
|
+
createScopedLogger('project-scope:fs:write');
|
|
265
|
+
|
|
705
266
|
const packageLogger = createScopedLogger('project-scope:project:package');
|
|
706
267
|
/**
|
|
707
268
|
* Verifies that a value is an object with only string values,
|
|
@@ -771,6 +332,16 @@ function validatePackageJson(data) {
|
|
|
771
332
|
*
|
|
772
333
|
* @param projectPath - Project directory path or path to package.json
|
|
773
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
|
+
* ```
|
|
774
345
|
*/
|
|
775
346
|
function readPackageJsonIfExists(projectPath) {
|
|
776
347
|
const packageJsonPath = projectPath.endsWith('package.json') ? projectPath : join$1(projectPath, 'package.json');
|
|
@@ -791,222 +362,46 @@ function readPackageJsonIfExists(projectPath) {
|
|
|
791
362
|
}
|
|
792
363
|
|
|
793
364
|
/**
|
|
794
|
-
*
|
|
795
|
-
*/
|
|
796
|
-
const cacheRegistry = createSet();
|
|
797
|
-
/**
|
|
798
|
-
* Create a cache with optional TTL and size limits.
|
|
799
|
-
*
|
|
800
|
-
* The cache provides a simple key-value store with:
|
|
801
|
-
* - Optional TTL (time-to-live) for automatic expiration
|
|
802
|
-
* - Optional maxSize for limiting cache size with FIFO eviction
|
|
803
|
-
* - Lazy expiration (entries are checked on access)
|
|
804
|
-
*
|
|
805
|
-
* @param options - Cache configuration options
|
|
806
|
-
* @returns Cache instance
|
|
365
|
+
* Detect Express in project.
|
|
807
366
|
*
|
|
808
|
-
* @
|
|
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
|
|
809
371
|
* ```typescript
|
|
810
|
-
*
|
|
811
|
-
*
|
|
812
|
-
*
|
|
813
|
-
*
|
|
814
|
-
*
|
|
815
|
-
* // Cache with TTL (expires after 60 seconds)
|
|
816
|
-
* const ttlCache = createCache<string, object>({ ttl: 60000 })
|
|
817
|
-
*
|
|
818
|
-
* // Cache with max size (evicts oldest when full)
|
|
819
|
-
* 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
|
+
* }
|
|
820
376
|
*
|
|
821
|
-
*
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
*
|
|
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
|
+
* // }
|
|
826
389
|
* ```
|
|
827
390
|
*/
|
|
828
|
-
function
|
|
829
|
-
const
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
function isExpired(entry) {
|
|
839
|
-
if (ttl === undefined)
|
|
840
|
-
return false;
|
|
841
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
842
|
-
return Date.now() - entry.timestamp > ttl;
|
|
843
|
-
}
|
|
844
|
-
/**
|
|
845
|
-
* Evict oldest entries to make room for new ones.
|
|
846
|
-
*/
|
|
847
|
-
function evictIfNeeded() {
|
|
848
|
-
if (maxSize === undefined)
|
|
849
|
-
return;
|
|
850
|
-
while (store.size >= maxSize && insertionOrder.length > 0) {
|
|
851
|
-
const oldestKey = insertionOrder.shift();
|
|
852
|
-
if (oldestKey !== undefined) {
|
|
853
|
-
store.delete(oldestKey);
|
|
854
|
-
}
|
|
855
|
-
}
|
|
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' });
|
|
856
401
|
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
* @param key - Key to remove from order tracking
|
|
861
|
-
*/
|
|
862
|
-
function removeFromOrder(key) {
|
|
863
|
-
const index = insertionOrder.indexOf(key);
|
|
864
|
-
if (index !== -1) {
|
|
865
|
-
insertionOrder.splice(index, 1);
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
const cache = {
|
|
869
|
-
get(key) {
|
|
870
|
-
const entry = store.get(key);
|
|
871
|
-
if (!entry)
|
|
872
|
-
return undefined;
|
|
873
|
-
if (isExpired(entry)) {
|
|
874
|
-
store.delete(key);
|
|
875
|
-
removeFromOrder(key);
|
|
876
|
-
return undefined;
|
|
877
|
-
}
|
|
878
|
-
return entry.value;
|
|
879
|
-
},
|
|
880
|
-
set(key, value) {
|
|
881
|
-
if (store.has(key)) {
|
|
882
|
-
removeFromOrder(key);
|
|
883
|
-
}
|
|
884
|
-
else {
|
|
885
|
-
evictIfNeeded();
|
|
886
|
-
}
|
|
887
|
-
// eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
|
|
888
|
-
store.set(key, { value, timestamp: Date.now() });
|
|
889
|
-
insertionOrder.push(key);
|
|
890
|
-
},
|
|
891
|
-
has(key) {
|
|
892
|
-
const entry = store.get(key);
|
|
893
|
-
if (!entry)
|
|
894
|
-
return false;
|
|
895
|
-
if (isExpired(entry)) {
|
|
896
|
-
store.delete(key);
|
|
897
|
-
removeFromOrder(key);
|
|
898
|
-
return false;
|
|
899
|
-
}
|
|
900
|
-
return true;
|
|
901
|
-
},
|
|
902
|
-
delete(key) {
|
|
903
|
-
removeFromOrder(key);
|
|
904
|
-
return store.delete(key);
|
|
905
|
-
},
|
|
906
|
-
clear() {
|
|
907
|
-
store.clear();
|
|
908
|
-
insertionOrder.length = 0;
|
|
909
|
-
},
|
|
910
|
-
size() {
|
|
911
|
-
return store.size;
|
|
912
|
-
},
|
|
913
|
-
keys() {
|
|
914
|
-
return [...insertionOrder];
|
|
915
|
-
},
|
|
916
|
-
};
|
|
917
|
-
cacheRegistry.add(cache);
|
|
918
|
-
return freeze(cache);
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
/**
|
|
922
|
-
* Get combined dependencies from package.json.
|
|
923
|
-
* Merges dependencies, devDependencies, peerDependencies, and optionalDependencies.
|
|
924
|
-
*
|
|
925
|
-
* @param packageJson - The package.json object to extract dependencies from
|
|
926
|
-
* @returns Combined dependencies as a single record
|
|
927
|
-
*/
|
|
928
|
-
function collectAllDependencies(packageJson) {
|
|
929
|
-
return {
|
|
930
|
-
...packageJson?.dependencies,
|
|
931
|
-
...packageJson?.devDependencies,
|
|
932
|
-
...packageJson?.peerDependencies,
|
|
933
|
-
...packageJson?.optionalDependencies,
|
|
934
|
-
};
|
|
935
|
-
}
|
|
936
|
-
/**
|
|
937
|
-
* Extract clean version from dependency version string.
|
|
938
|
-
* Removes semver prefixes like ^, ~, >=, etc.
|
|
939
|
-
* Uses character-by-character parsing to avoid ReDoS vulnerabilities.
|
|
940
|
-
*
|
|
941
|
-
* @param versionString - The version string with optional prefix characters
|
|
942
|
-
* @returns The cleaned version string without prefix characters
|
|
943
|
-
*/
|
|
944
|
-
function parseVersionString(versionString) {
|
|
945
|
-
if (versionString === undefined || versionString === null)
|
|
946
|
-
return undefined;
|
|
947
|
-
let start = 0;
|
|
948
|
-
while (start < versionString.length) {
|
|
949
|
-
const char = versionString[start];
|
|
950
|
-
if (char !== '^' && char !== '~' && char !== '>' && char !== '=' && char !== '<') {
|
|
951
|
-
break;
|
|
952
|
-
}
|
|
953
|
-
start++;
|
|
954
|
-
}
|
|
955
|
-
return versionString.slice(start);
|
|
956
|
-
}
|
|
957
|
-
/**
|
|
958
|
-
* Find first matching config file in project.
|
|
959
|
-
* Note: Name avoids similarity to fs.readFile/fs.readFileSync.
|
|
960
|
-
*
|
|
961
|
-
* @param projectPath - The project directory path
|
|
962
|
-
* @param patterns - Array of config file patterns to search for
|
|
963
|
-
* @returns The first matching config file path or undefined
|
|
964
|
-
*/
|
|
965
|
-
function locateConfigFile(projectPath, patterns) {
|
|
966
|
-
for (const pattern of patterns) {
|
|
967
|
-
const fullPath = join(projectPath, pattern);
|
|
968
|
-
if (exists(fullPath)) {
|
|
969
|
-
return pattern;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
return undefined;
|
|
973
|
-
}
|
|
974
|
-
/**
|
|
975
|
-
* Find scripts containing a specific command.
|
|
976
|
-
*
|
|
977
|
-
* @param scripts - The scripts object from package.json
|
|
978
|
-
* @param command - The command string to search for
|
|
979
|
-
* @returns Array of script names that contain the command
|
|
980
|
-
*/
|
|
981
|
-
function filterScriptsByCommand(scripts, command) {
|
|
982
|
-
if (!scripts)
|
|
983
|
-
return [];
|
|
984
|
-
return entries(scripts)
|
|
985
|
-
.filter(([, script]) => script.includes(command))
|
|
986
|
-
.map(([name]) => name);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
/**
|
|
990
|
-
* Detect Express in project.
|
|
991
|
-
*
|
|
992
|
-
* @param projectPath - Project directory path
|
|
993
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
994
|
-
* @returns Detection result or null if not detected
|
|
995
|
-
*/
|
|
996
|
-
function expressDetector(projectPath, packageJson) {
|
|
997
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
998
|
-
const sources = [];
|
|
999
|
-
let confidence = 0;
|
|
1000
|
-
let version;
|
|
1001
|
-
const deps = collectAllDependencies(pkg);
|
|
1002
|
-
if (deps['express']) {
|
|
1003
|
-
confidence += 80;
|
|
1004
|
-
version = parseVersionString(deps['express']);
|
|
1005
|
-
sources.push({ type: 'package.json', field: 'dependencies.express' });
|
|
1006
|
-
}
|
|
1007
|
-
if (deps['@types/express']) {
|
|
1008
|
-
confidence += 10;
|
|
1009
|
-
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' });
|
|
1010
405
|
}
|
|
1011
406
|
const expressMiddleware = keys(deps).filter((d) => d.includes('express-') || d === 'body-parser' || d === 'cors' || d === 'helmet' || d === 'morgan');
|
|
1012
407
|
if (expressMiddleware.length > 0) {
|
|
@@ -1026,84 +421,109 @@ function expressDetector(projectPath, packageJson) {
|
|
|
1026
421
|
}
|
|
1027
422
|
|
|
1028
423
|
/**
|
|
1029
|
-
* Detect
|
|
424
|
+
* Detect Fastify in project.
|
|
1030
425
|
*
|
|
1031
426
|
* @param projectPath - Project directory path
|
|
1032
427
|
* @param packageJson - Optional pre-loaded package.json
|
|
1033
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
|
+
* ```
|
|
1034
447
|
*/
|
|
1035
|
-
function
|
|
448
|
+
function fastifyDetector(projectPath, packageJson) {
|
|
1036
449
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1037
450
|
const sources = [];
|
|
1038
451
|
let confidence = 0;
|
|
1039
452
|
let version;
|
|
1040
|
-
let configPath;
|
|
1041
453
|
const deps = collectAllDependencies(pkg);
|
|
1042
|
-
if (deps['
|
|
1043
|
-
confidence +=
|
|
1044
|
-
version = parseVersionString(deps['
|
|
1045
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1046
|
-
}
|
|
1047
|
-
if (deps['@nestjs/common']) {
|
|
1048
|
-
confidence += 15;
|
|
1049
|
-
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' });
|
|
1050
458
|
}
|
|
1051
|
-
|
|
459
|
+
const fastifyPlugins = keys(deps).filter((d) => d.startsWith('@fastify/') || d.startsWith('fastify-'));
|
|
460
|
+
if (fastifyPlugins.length > 0) {
|
|
1052
461
|
confidence += 15;
|
|
1053
|
-
|
|
1054
|
-
sources.push({ type: 'config-file', path: 'nest-cli.json' });
|
|
462
|
+
sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
|
|
1055
463
|
}
|
|
1056
|
-
|
|
1057
|
-
if (nestPackages.length > 2) {
|
|
464
|
+
if (deps['@types/fastify']) {
|
|
1058
465
|
confidence += 5;
|
|
1059
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
466
|
+
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
1060
467
|
}
|
|
1061
468
|
if (confidence === 0) {
|
|
1062
469
|
return null;
|
|
1063
470
|
}
|
|
1064
471
|
return {
|
|
1065
|
-
id: '
|
|
1066
|
-
name: '
|
|
472
|
+
id: 'fastify',
|
|
473
|
+
name: 'Fastify',
|
|
1067
474
|
version,
|
|
1068
|
-
configPath,
|
|
1069
475
|
confidence: min(confidence, 100),
|
|
1070
476
|
detectedFrom: sources,
|
|
1071
477
|
};
|
|
1072
478
|
}
|
|
1073
479
|
|
|
1074
480
|
/**
|
|
1075
|
-
* Detect
|
|
481
|
+
* Detect Hono in project.
|
|
1076
482
|
*
|
|
1077
483
|
* @param projectPath - Project directory path
|
|
1078
484
|
* @param packageJson - Optional pre-loaded package.json
|
|
1079
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
|
+
* ```
|
|
1080
504
|
*/
|
|
1081
|
-
function
|
|
505
|
+
function honoDetector(projectPath, packageJson) {
|
|
1082
506
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1083
507
|
const sources = [];
|
|
1084
508
|
let confidence = 0;
|
|
1085
509
|
let version;
|
|
1086
510
|
const deps = collectAllDependencies(pkg);
|
|
1087
|
-
if (deps['
|
|
1088
|
-
confidence +=
|
|
1089
|
-
version = parseVersionString(deps['
|
|
1090
|
-
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' });
|
|
1091
515
|
}
|
|
1092
|
-
const
|
|
1093
|
-
if (
|
|
516
|
+
const honoAdapters = keys(deps).filter((d) => d.startsWith('@hono/'));
|
|
517
|
+
if (honoAdapters.length > 0) {
|
|
1094
518
|
confidence += 15;
|
|
1095
|
-
sources.push({ type: 'package.json', field: 'dependencies (
|
|
1096
|
-
}
|
|
1097
|
-
if (deps['@types/fastify']) {
|
|
1098
|
-
confidence += 5;
|
|
1099
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
|
|
519
|
+
sources.push({ type: 'package.json', field: 'dependencies (@hono adapters)' });
|
|
1100
520
|
}
|
|
1101
521
|
if (confidence === 0) {
|
|
1102
522
|
return null;
|
|
1103
523
|
}
|
|
1104
524
|
return {
|
|
1105
|
-
id: '
|
|
1106
|
-
name: '
|
|
525
|
+
id: 'hono',
|
|
526
|
+
name: 'Hono',
|
|
1107
527
|
version,
|
|
1108
528
|
confidence: min(confidence, 100),
|
|
1109
529
|
detectedFrom: sources,
|
|
@@ -1116,6 +536,26 @@ function fastifyDetector(projectPath, packageJson) {
|
|
|
1116
536
|
* @param projectPath - Project directory path
|
|
1117
537
|
* @param packageJson - Optional pre-loaded package.json
|
|
1118
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
|
+
* ```
|
|
1119
559
|
*/
|
|
1120
560
|
function koaDetector(projectPath, packageJson) {
|
|
1121
561
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1150,35 +590,72 @@ function koaDetector(projectPath, packageJson) {
|
|
|
1150
590
|
}
|
|
1151
591
|
|
|
1152
592
|
/**
|
|
1153
|
-
* Detect
|
|
593
|
+
* Detect NestJS in project.
|
|
1154
594
|
*
|
|
1155
595
|
* @param projectPath - Project directory path
|
|
1156
596
|
* @param packageJson - Optional pre-loaded package.json
|
|
1157
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
|
+
* ```
|
|
1158
624
|
*/
|
|
1159
|
-
function
|
|
625
|
+
function nestDetector(projectPath, packageJson) {
|
|
1160
626
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1161
627
|
const sources = [];
|
|
1162
628
|
let confidence = 0;
|
|
1163
629
|
let version;
|
|
630
|
+
let configPath;
|
|
1164
631
|
const deps = collectAllDependencies(pkg);
|
|
1165
|
-
if (deps['
|
|
1166
|
-
confidence +=
|
|
1167
|
-
version = parseVersionString(deps['
|
|
1168
|
-
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' });
|
|
1169
636
|
}
|
|
1170
|
-
|
|
1171
|
-
if (honoAdapters.length > 0) {
|
|
637
|
+
if (deps['@nestjs/common']) {
|
|
1172
638
|
confidence += 15;
|
|
1173
|
-
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)' });
|
|
1174
650
|
}
|
|
1175
651
|
if (confidence === 0) {
|
|
1176
652
|
return null;
|
|
1177
653
|
}
|
|
1178
654
|
return {
|
|
1179
|
-
id: '
|
|
1180
|
-
name: '
|
|
655
|
+
id: 'nestjs',
|
|
656
|
+
name: 'NestJS',
|
|
1181
657
|
version,
|
|
658
|
+
configPath,
|
|
1182
659
|
confidence: min(confidence, 100),
|
|
1183
660
|
detectedFrom: sources,
|
|
1184
661
|
};
|
|
@@ -1193,52 +670,64 @@ const backendDetectors = [
|
|
|
1193
670
|
{ id: 'hono', name: 'Hono', detect: honoDetector },
|
|
1194
671
|
];
|
|
1195
672
|
|
|
1196
|
-
/** Config patterns for
|
|
1197
|
-
const
|
|
1198
|
-
'webpack.config.js',
|
|
1199
|
-
'webpack.config.ts',
|
|
1200
|
-
'webpack.config.cjs',
|
|
1201
|
-
'webpack.config.mjs',
|
|
1202
|
-
'webpack.config.babel.js',
|
|
1203
|
-
];
|
|
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'];
|
|
1204
675
|
/**
|
|
1205
|
-
* Detect
|
|
676
|
+
* Detect Babel in project.
|
|
1206
677
|
*
|
|
1207
678
|
* @param projectPath - Project directory path
|
|
1208
679
|
* @param packageJson - Optional pre-loaded package.json
|
|
1209
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
|
+
* ```
|
|
1210
699
|
*/
|
|
1211
|
-
function
|
|
700
|
+
function babelDetector(projectPath, packageJson) {
|
|
1212
701
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1213
702
|
const sources = [];
|
|
1214
703
|
let confidence = 0;
|
|
1215
704
|
let version;
|
|
1216
705
|
const deps = collectAllDependencies(pkg);
|
|
1217
|
-
if (deps['
|
|
706
|
+
if (deps['@babel/core']) {
|
|
1218
707
|
confidence += 50;
|
|
1219
|
-
version = parseVersionString(deps['
|
|
1220
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
708
|
+
version = parseVersionString(deps['@babel/core']);
|
|
709
|
+
sources.push({ type: 'package.json', field: 'dependencies.@babel/core' });
|
|
1221
710
|
}
|
|
1222
|
-
const configPath = locateConfigFile(projectPath,
|
|
711
|
+
const configPath = locateConfigFile(projectPath, BABEL_CONFIG_PATTERNS);
|
|
1223
712
|
if (configPath) {
|
|
1224
713
|
confidence += 40;
|
|
1225
714
|
sources.push({ type: 'config-file', path: configPath });
|
|
1226
715
|
}
|
|
1227
|
-
if (
|
|
1228
|
-
confidence +=
|
|
1229
|
-
sources.push({ type: 'package.json', field: '
|
|
716
|
+
if (pkg && 'babel' in pkg) {
|
|
717
|
+
confidence += 30;
|
|
718
|
+
sources.push({ type: 'package.json', field: 'babel' });
|
|
1230
719
|
}
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
confidence
|
|
1234
|
-
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)' });
|
|
1235
724
|
}
|
|
1236
725
|
if (confidence === 0) {
|
|
1237
726
|
return null;
|
|
1238
727
|
}
|
|
1239
728
|
return {
|
|
1240
|
-
id: '
|
|
1241
|
-
name: '
|
|
729
|
+
id: 'babel',
|
|
730
|
+
name: 'Babel',
|
|
1242
731
|
version,
|
|
1243
732
|
configPath,
|
|
1244
733
|
confidence: min(confidence, 100),
|
|
@@ -1246,94 +735,126 @@ function webpackDetector(projectPath, packageJson) {
|
|
|
1246
735
|
};
|
|
1247
736
|
}
|
|
1248
737
|
|
|
1249
|
-
/** Config patterns for Vite */
|
|
1250
|
-
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
1251
738
|
/**
|
|
1252
|
-
* Detect
|
|
739
|
+
* Detect esbuild in project.
|
|
1253
740
|
*
|
|
1254
741
|
* @param projectPath - Project directory path
|
|
1255
742
|
* @param packageJson - Optional pre-loaded package.json
|
|
1256
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
|
+
* ```
|
|
1257
763
|
*/
|
|
1258
|
-
function
|
|
764
|
+
function esbuildDetector(projectPath, packageJson) {
|
|
1259
765
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1260
766
|
const sources = [];
|
|
1261
767
|
let confidence = 0;
|
|
1262
768
|
let version;
|
|
1263
769
|
const deps = collectAllDependencies(pkg);
|
|
1264
|
-
if (deps['
|
|
1265
|
-
confidence +=
|
|
1266
|
-
version = parseVersionString(deps['
|
|
1267
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1268
|
-
}
|
|
1269
|
-
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
1270
|
-
if (configPath) {
|
|
1271
|
-
confidence += 35;
|
|
1272
|
-
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' });
|
|
1273
774
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
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)' });
|
|
1277
779
|
}
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1280
|
-
confidence
|
|
1281
|
-
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}` });
|
|
1282
784
|
}
|
|
1283
785
|
if (confidence === 0) {
|
|
1284
786
|
return null;
|
|
1285
787
|
}
|
|
1286
788
|
return {
|
|
1287
|
-
id: '
|
|
1288
|
-
name: '
|
|
789
|
+
id: 'esbuild',
|
|
790
|
+
name: 'esbuild',
|
|
1289
791
|
version,
|
|
1290
|
-
configPath,
|
|
1291
792
|
confidence: min(confidence, 100),
|
|
1292
793
|
detectedFrom: sources,
|
|
1293
794
|
};
|
|
1294
795
|
}
|
|
1295
796
|
|
|
1296
|
-
/** Config patterns for
|
|
1297
|
-
const
|
|
797
|
+
/** Config patterns for Parcel */
|
|
798
|
+
const PARCEL_CONFIG_PATTERNS = ['.parcelrc'];
|
|
1298
799
|
/**
|
|
1299
|
-
* Detect
|
|
800
|
+
* Detect Parcel in project.
|
|
1300
801
|
*
|
|
1301
802
|
* @param projectPath - Project directory path
|
|
1302
803
|
* @param packageJson - Optional pre-loaded package.json
|
|
1303
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
|
+
* ```
|
|
1304
825
|
*/
|
|
1305
|
-
function
|
|
826
|
+
function parcelDetector(projectPath, packageJson) {
|
|
1306
827
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1307
828
|
const sources = [];
|
|
1308
829
|
let confidence = 0;
|
|
1309
830
|
let version;
|
|
1310
831
|
const deps = collectAllDependencies(pkg);
|
|
1311
|
-
if (deps['
|
|
1312
|
-
confidence +=
|
|
1313
|
-
version = parseVersionString(deps['
|
|
1314
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1315
|
-
}
|
|
1316
|
-
|
|
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);
|
|
1317
843
|
if (configPath) {
|
|
1318
|
-
confidence +=
|
|
844
|
+
confidence += 30;
|
|
1319
845
|
sources.push({ type: 'config-file', path: configPath });
|
|
1320
846
|
}
|
|
1321
|
-
const
|
|
1322
|
-
if (rollupPlugins.length > 0) {
|
|
1323
|
-
confidence += 10;
|
|
1324
|
-
sources.push({ type: 'package.json', field: 'dependencies (rollup plugins)' });
|
|
1325
|
-
}
|
|
1326
|
-
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'rollup');
|
|
847
|
+
const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'parcel');
|
|
1327
848
|
for (const name of scriptMatches) {
|
|
1328
|
-
confidence = min(confidence +
|
|
849
|
+
confidence = min(confidence + 10, 100);
|
|
1329
850
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1330
851
|
}
|
|
1331
852
|
if (confidence === 0) {
|
|
1332
853
|
return null;
|
|
1333
854
|
}
|
|
1334
855
|
return {
|
|
1335
|
-
id: '
|
|
1336
|
-
name: '
|
|
856
|
+
id: 'parcel',
|
|
857
|
+
name: 'Parcel',
|
|
1337
858
|
version,
|
|
1338
859
|
configPath,
|
|
1339
860
|
confidence: min(confidence, 100),
|
|
@@ -1341,86 +862,134 @@ function rollupDetector(projectPath, packageJson) {
|
|
|
1341
862
|
};
|
|
1342
863
|
}
|
|
1343
864
|
|
|
865
|
+
/** Config patterns for Rollup */
|
|
866
|
+
const ROLLUP_CONFIG_PATTERNS = ['rollup.config.js', 'rollup.config.ts', 'rollup.config.mjs', 'rollup.config.cjs'];
|
|
1344
867
|
/**
|
|
1345
|
-
* Detect
|
|
868
|
+
* Detect Rollup in project.
|
|
1346
869
|
*
|
|
1347
870
|
* @param projectPath - Project directory path
|
|
1348
871
|
* @param packageJson - Optional pre-loaded package.json
|
|
1349
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
|
+
* ```
|
|
1350
895
|
*/
|
|
1351
|
-
function
|
|
896
|
+
function rollupDetector(projectPath, packageJson) {
|
|
1352
897
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1353
898
|
const sources = [];
|
|
1354
899
|
let confidence = 0;
|
|
1355
900
|
let version;
|
|
1356
901
|
const deps = collectAllDependencies(pkg);
|
|
1357
|
-
if (deps['
|
|
1358
|
-
confidence +=
|
|
1359
|
-
version = parseVersionString(deps['
|
|
1360
|
-
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' });
|
|
1361
906
|
}
|
|
1362
|
-
const
|
|
1363
|
-
if (
|
|
1364
|
-
confidence +=
|
|
1365
|
-
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 });
|
|
1366
911
|
}
|
|
1367
|
-
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');
|
|
1368
918
|
for (const name of scriptMatches) {
|
|
1369
|
-
confidence = min(confidence +
|
|
919
|
+
confidence = min(confidence + 5, 100);
|
|
1370
920
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1371
921
|
}
|
|
1372
922
|
if (confidence === 0) {
|
|
1373
923
|
return null;
|
|
1374
924
|
}
|
|
1375
925
|
return {
|
|
1376
|
-
id: '
|
|
1377
|
-
name: '
|
|
926
|
+
id: 'rollup',
|
|
927
|
+
name: 'Rollup',
|
|
1378
928
|
version,
|
|
929
|
+
configPath,
|
|
1379
930
|
confidence: min(confidence, 100),
|
|
1380
931
|
detectedFrom: sources,
|
|
1381
932
|
};
|
|
1382
933
|
}
|
|
1383
934
|
|
|
1384
|
-
/** Config patterns for
|
|
1385
|
-
const
|
|
935
|
+
/** Config patterns for SWC */
|
|
936
|
+
const SWC_CONFIG_PATTERNS = ['.swcrc', 'swc.config.js'];
|
|
1386
937
|
/**
|
|
1387
|
-
* Detect
|
|
938
|
+
* Detect SWC in project.
|
|
1388
939
|
*
|
|
1389
940
|
* @param projectPath - Project directory path
|
|
1390
941
|
* @param packageJson - Optional pre-loaded package.json
|
|
1391
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
|
+
* ```
|
|
1392
961
|
*/
|
|
1393
|
-
function
|
|
962
|
+
function swcDetector(projectPath, packageJson) {
|
|
1394
963
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1395
964
|
const sources = [];
|
|
1396
965
|
let confidence = 0;
|
|
1397
966
|
let version;
|
|
1398
967
|
const deps = collectAllDependencies(pkg);
|
|
1399
|
-
if (deps['@
|
|
1400
|
-
confidence +=
|
|
1401
|
-
version = parseVersionString(deps['@
|
|
1402
|
-
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' });
|
|
1403
972
|
}
|
|
1404
|
-
const configPath = locateConfigFile(projectPath,
|
|
973
|
+
const configPath = locateConfigFile(projectPath, SWC_CONFIG_PATTERNS);
|
|
1405
974
|
if (configPath) {
|
|
1406
|
-
confidence +=
|
|
975
|
+
confidence += 35;
|
|
1407
976
|
sources.push({ type: 'config-file', path: configPath });
|
|
1408
977
|
}
|
|
1409
|
-
if (
|
|
1410
|
-
confidence += 30;
|
|
1411
|
-
sources.push({ type: 'package.json', field: 'babel' });
|
|
1412
|
-
}
|
|
1413
|
-
const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
|
|
1414
|
-
if (babelPackages.length > 1) {
|
|
978
|
+
if (deps['@swc/cli']) {
|
|
1415
979
|
confidence += 10;
|
|
1416
|
-
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)' });
|
|
1417
986
|
}
|
|
1418
987
|
if (confidence === 0) {
|
|
1419
988
|
return null;
|
|
1420
989
|
}
|
|
1421
990
|
return {
|
|
1422
|
-
id: '
|
|
1423
|
-
name: '
|
|
991
|
+
id: 'swc',
|
|
992
|
+
name: 'SWC',
|
|
1424
993
|
version,
|
|
1425
994
|
configPath,
|
|
1426
995
|
confidence: min(confidence, 100),
|
|
@@ -1428,46 +997,69 @@ function babelDetector(projectPath, packageJson) {
|
|
|
1428
997
|
};
|
|
1429
998
|
}
|
|
1430
999
|
|
|
1431
|
-
/** Config patterns for
|
|
1432
|
-
const
|
|
1000
|
+
/** Config patterns for Vite */
|
|
1001
|
+
const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
|
|
1433
1002
|
/**
|
|
1434
|
-
* Detect
|
|
1003
|
+
* Detect Vite in project.
|
|
1435
1004
|
*
|
|
1436
1005
|
* @param projectPath - Project directory path
|
|
1437
1006
|
* @param packageJson - Optional pre-loaded package.json
|
|
1438
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
|
+
* ```
|
|
1439
1031
|
*/
|
|
1440
|
-
function
|
|
1032
|
+
function viteDetector(projectPath, packageJson) {
|
|
1441
1033
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1442
1034
|
const sources = [];
|
|
1443
1035
|
let confidence = 0;
|
|
1444
1036
|
let version;
|
|
1445
1037
|
const deps = collectAllDependencies(pkg);
|
|
1446
|
-
if (deps['
|
|
1038
|
+
if (deps['vite']) {
|
|
1447
1039
|
confidence += 60;
|
|
1448
|
-
version = parseVersionString(deps['
|
|
1449
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1040
|
+
version = parseVersionString(deps['vite']);
|
|
1041
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite' });
|
|
1450
1042
|
}
|
|
1451
|
-
const configPath = locateConfigFile(projectPath,
|
|
1043
|
+
const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
|
|
1452
1044
|
if (configPath) {
|
|
1453
1045
|
confidence += 35;
|
|
1454
1046
|
sources.push({ type: 'config-file', path: configPath });
|
|
1455
1047
|
}
|
|
1456
|
-
if (deps['
|
|
1048
|
+
if (deps['vitest']) {
|
|
1457
1049
|
confidence += 10;
|
|
1458
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1050
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
1459
1051
|
}
|
|
1460
|
-
const
|
|
1461
|
-
if (
|
|
1462
|
-
confidence +=
|
|
1463
|
-
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)' });
|
|
1464
1056
|
}
|
|
1465
1057
|
if (confidence === 0) {
|
|
1466
1058
|
return null;
|
|
1467
1059
|
}
|
|
1468
1060
|
return {
|
|
1469
|
-
id: '
|
|
1470
|
-
name: '
|
|
1061
|
+
id: 'vite',
|
|
1062
|
+
name: 'Vite',
|
|
1471
1063
|
version,
|
|
1472
1064
|
configPath,
|
|
1473
1065
|
confidence: min(confidence, 100),
|
|
@@ -1475,47 +1067,72 @@ function swcDetector(projectPath, packageJson) {
|
|
|
1475
1067
|
};
|
|
1476
1068
|
}
|
|
1477
1069
|
|
|
1478
|
-
/** Config patterns for
|
|
1479
|
-
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
|
+
];
|
|
1480
1078
|
/**
|
|
1481
|
-
* Detect
|
|
1079
|
+
* Detect Webpack in project.
|
|
1482
1080
|
*
|
|
1483
1081
|
* @param projectPath - Project directory path
|
|
1484
1082
|
* @param packageJson - Optional pre-loaded package.json
|
|
1485
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
|
+
* ```
|
|
1486
1104
|
*/
|
|
1487
|
-
function
|
|
1105
|
+
function webpackDetector(projectPath, packageJson) {
|
|
1488
1106
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1489
1107
|
const sources = [];
|
|
1490
1108
|
let confidence = 0;
|
|
1491
1109
|
let version;
|
|
1492
1110
|
const deps = collectAllDependencies(pkg);
|
|
1493
|
-
if (deps['
|
|
1494
|
-
confidence +=
|
|
1495
|
-
version = parseVersionString(deps['
|
|
1496
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
1497
|
-
}
|
|
1498
|
-
if (deps['parcel-bundler']) {
|
|
1499
|
-
confidence += 60;
|
|
1500
|
-
version = parseVersionString(deps['parcel-bundler']);
|
|
1501
|
-
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' });
|
|
1502
1115
|
}
|
|
1503
|
-
const configPath = locateConfigFile(projectPath,
|
|
1116
|
+
const configPath = locateConfigFile(projectPath, WEBPACK_CONFIG_PATTERNS);
|
|
1504
1117
|
if (configPath) {
|
|
1505
|
-
confidence +=
|
|
1118
|
+
confidence += 40;
|
|
1506
1119
|
sources.push({ type: 'config-file', path: configPath });
|
|
1507
1120
|
}
|
|
1508
|
-
|
|
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');
|
|
1509
1126
|
for (const name of scriptMatches) {
|
|
1510
|
-
confidence = min(confidence +
|
|
1127
|
+
confidence = min(confidence + 5, 100);
|
|
1511
1128
|
sources.push({ type: 'package.json', field: `scripts.${name}` });
|
|
1512
1129
|
}
|
|
1513
1130
|
if (confidence === 0) {
|
|
1514
1131
|
return null;
|
|
1515
1132
|
}
|
|
1516
1133
|
return {
|
|
1517
|
-
id: '
|
|
1518
|
-
name: '
|
|
1134
|
+
id: 'webpack',
|
|
1135
|
+
name: 'Webpack',
|
|
1519
1136
|
version,
|
|
1520
1137
|
configPath,
|
|
1521
1138
|
confidence: min(confidence, 100),
|
|
@@ -1535,81 +1152,187 @@ const buildToolDetectors = [
|
|
|
1535
1152
|
];
|
|
1536
1153
|
|
|
1537
1154
|
/**
|
|
1538
|
-
* Detect
|
|
1155
|
+
* Detect Angular in project.
|
|
1539
1156
|
*
|
|
1540
1157
|
* @param projectPath - Project directory path
|
|
1541
1158
|
* @param packageJson - Optional pre-loaded package.json
|
|
1542
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
|
+
* ```
|
|
1543
1178
|
*/
|
|
1544
|
-
function
|
|
1179
|
+
function angularDetector(projectPath, packageJson) {
|
|
1545
1180
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1546
1181
|
const sources = [];
|
|
1547
1182
|
let confidence = 0;
|
|
1548
1183
|
let version;
|
|
1549
|
-
const metaFrameworks = [];
|
|
1550
1184
|
const deps = collectAllDependencies(pkg);
|
|
1551
|
-
if (deps['
|
|
1552
|
-
confidence +=
|
|
1553
|
-
version = parseVersionString(deps['
|
|
1554
|
-
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' });
|
|
1555
1189
|
}
|
|
1556
|
-
if (deps['
|
|
1557
|
-
confidence +=
|
|
1558
|
-
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' });
|
|
1559
1193
|
}
|
|
1560
|
-
if (
|
|
1561
|
-
confidence +=
|
|
1562
|
-
sources.push({ type: '
|
|
1194
|
+
if (exists(join$1(projectPath, 'angular.json'))) {
|
|
1195
|
+
confidence += 15;
|
|
1196
|
+
sources.push({ type: 'config-file', path: 'angular.json' });
|
|
1563
1197
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
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
|
+
};
|
|
1571
1207
|
}
|
|
1572
|
-
if (
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1208
|
+
if (confidence === 0) {
|
|
1209
|
+
return null;
|
|
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' });
|
|
1581
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);
|
|
1582
1312
|
if (deps['gatsby']) {
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
category: 'meta-framework',
|
|
1587
|
-
version: parseVersionString(deps['gatsby']),
|
|
1588
|
-
confidence: 90,
|
|
1589
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
|
|
1590
|
-
});
|
|
1313
|
+
confidence += 70;
|
|
1314
|
+
version = parseVersionString(deps['gatsby']);
|
|
1315
|
+
sources.push({ type: 'package.json', field: 'dependencies.gatsby' });
|
|
1591
1316
|
}
|
|
1592
|
-
if (
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
});
|
|
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)' });
|
|
1601
1325
|
}
|
|
1602
1326
|
if (confidence === 0) {
|
|
1603
1327
|
return null;
|
|
1604
1328
|
}
|
|
1605
1329
|
return {
|
|
1606
|
-
id: '
|
|
1607
|
-
name: '
|
|
1608
|
-
category: '
|
|
1330
|
+
id: 'gatsby',
|
|
1331
|
+
name: 'Gatsby',
|
|
1332
|
+
category: 'meta-framework',
|
|
1609
1333
|
version,
|
|
1610
1334
|
confidence: min(confidence, 100),
|
|
1611
1335
|
detectedFrom: sources,
|
|
1612
|
-
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
1613
1336
|
};
|
|
1614
1337
|
}
|
|
1615
1338
|
|
|
@@ -1619,6 +1342,21 @@ function reactDetector(projectPath, packageJson) {
|
|
|
1619
1342
|
* @param projectPath - Project directory path
|
|
1620
1343
|
* @param packageJson - Optional pre-loaded package.json
|
|
1621
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
|
+
* ```
|
|
1622
1360
|
*/
|
|
1623
1361
|
function nextjsDetector(projectPath, packageJson) {
|
|
1624
1362
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1658,37 +1396,52 @@ function nextjsDetector(projectPath, packageJson) {
|
|
|
1658
1396
|
}
|
|
1659
1397
|
|
|
1660
1398
|
/**
|
|
1661
|
-
* Detect
|
|
1399
|
+
* Detect Nuxt in project.
|
|
1662
1400
|
*
|
|
1663
1401
|
* @param projectPath - Project directory path
|
|
1664
1402
|
* @param packageJson - Optional pre-loaded package.json
|
|
1665
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
|
+
* ```
|
|
1666
1419
|
*/
|
|
1667
|
-
function
|
|
1420
|
+
function nuxtDetector(projectPath, packageJson) {
|
|
1668
1421
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1669
1422
|
const sources = [];
|
|
1670
1423
|
let confidence = 0;
|
|
1671
1424
|
let version;
|
|
1672
1425
|
const deps = collectAllDependencies(pkg);
|
|
1673
|
-
if (deps['
|
|
1426
|
+
if (deps['nuxt'] || deps['nuxt3']) {
|
|
1674
1427
|
confidence += 70;
|
|
1675
|
-
version = parseVersionString(deps['
|
|
1676
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1428
|
+
version = parseVersionString(deps['nuxt'] ?? deps['nuxt3']);
|
|
1429
|
+
sources.push({ type: 'package.json', field: 'dependencies.nuxt' });
|
|
1677
1430
|
}
|
|
1678
|
-
if (
|
|
1679
|
-
confidence +=
|
|
1680
|
-
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.*' });
|
|
1681
1434
|
}
|
|
1682
|
-
if (exists(join$1(projectPath, '
|
|
1683
|
-
confidence +=
|
|
1684
|
-
sources.push({ type: '
|
|
1435
|
+
if (exists(join$1(projectPath, 'pages'))) {
|
|
1436
|
+
confidence += 5;
|
|
1437
|
+
sources.push({ type: 'directory', path: 'pages/' });
|
|
1685
1438
|
}
|
|
1686
1439
|
if (confidence === 0) {
|
|
1687
1440
|
return null;
|
|
1688
1441
|
}
|
|
1689
1442
|
return {
|
|
1690
|
-
id: '
|
|
1691
|
-
name: '
|
|
1443
|
+
id: 'nuxt',
|
|
1444
|
+
name: 'Nuxt',
|
|
1692
1445
|
category: 'meta-framework',
|
|
1693
1446
|
version,
|
|
1694
1447
|
confidence: min(confidence, 100),
|
|
@@ -1697,39 +1450,59 @@ function remixDetector(projectPath, packageJson) {
|
|
|
1697
1450
|
}
|
|
1698
1451
|
|
|
1699
1452
|
/**
|
|
1700
|
-
* Detect
|
|
1453
|
+
* Detect Qwik in project.
|
|
1701
1454
|
*
|
|
1702
1455
|
* @param projectPath - Project directory path
|
|
1703
1456
|
* @param packageJson - Optional pre-loaded package.json
|
|
1704
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
|
+
* ```
|
|
1705
1479
|
*/
|
|
1706
|
-
function
|
|
1480
|
+
function qwikDetector(projectPath, packageJson) {
|
|
1707
1481
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1708
1482
|
const sources = [];
|
|
1709
1483
|
let confidence = 0;
|
|
1710
1484
|
let version;
|
|
1711
1485
|
const deps = collectAllDependencies(pkg);
|
|
1712
|
-
if (deps['
|
|
1486
|
+
if (deps['@builder.io/qwik']) {
|
|
1713
1487
|
confidence += 70;
|
|
1714
|
-
version = parseVersionString(deps['
|
|
1715
|
-
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' });
|
|
1716
1490
|
}
|
|
1717
|
-
if (
|
|
1718
|
-
confidence +=
|
|
1719
|
-
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' });
|
|
1720
1494
|
}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
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.*' });
|
|
1725
1498
|
}
|
|
1726
1499
|
if (confidence === 0) {
|
|
1727
1500
|
return null;
|
|
1728
1501
|
}
|
|
1729
1502
|
return {
|
|
1730
|
-
id: '
|
|
1731
|
-
name: '
|
|
1732
|
-
category: '
|
|
1503
|
+
id: 'qwik',
|
|
1504
|
+
name: 'Qwik',
|
|
1505
|
+
category: 'frontend',
|
|
1733
1506
|
version,
|
|
1734
1507
|
confidence: min(confidence, 100),
|
|
1735
1508
|
detectedFrom: sources,
|
|
@@ -1737,53 +1510,94 @@ function gatsbyDetector(projectPath, packageJson) {
|
|
|
1737
1510
|
}
|
|
1738
1511
|
|
|
1739
1512
|
/**
|
|
1740
|
-
* Detect
|
|
1513
|
+
* Detect React in project.
|
|
1741
1514
|
*
|
|
1742
1515
|
* @param projectPath - Project directory path
|
|
1743
1516
|
* @param packageJson - Optional pre-loaded package.json
|
|
1744
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
|
+
* ```
|
|
1745
1536
|
*/
|
|
1746
|
-
function
|
|
1537
|
+
function reactDetector(projectPath, packageJson) {
|
|
1747
1538
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1748
1539
|
const sources = [];
|
|
1749
1540
|
let confidence = 0;
|
|
1750
1541
|
let version;
|
|
1751
1542
|
const metaFrameworks = [];
|
|
1752
1543
|
const deps = collectAllDependencies(pkg);
|
|
1753
|
-
if (deps['
|
|
1754
|
-
confidence +=
|
|
1755
|
-
version = parseVersionString(deps['
|
|
1756
|
-
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' });
|
|
1757
1548
|
}
|
|
1758
|
-
if (deps['
|
|
1759
|
-
confidence +=
|
|
1760
|
-
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' });
|
|
1761
1552
|
}
|
|
1762
|
-
|
|
1763
|
-
|
|
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) {
|
|
1764
1562
|
confidence += 10;
|
|
1765
|
-
sources.push({ type: 'directory', path: 'src/*.
|
|
1563
|
+
sources.push({ type: 'directory', path: 'src/*.tsx or src/*.jsx' });
|
|
1766
1564
|
}
|
|
1767
|
-
if (
|
|
1768
|
-
|
|
1769
|
-
|
|
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
|
+
});
|
|
1770
1574
|
}
|
|
1771
|
-
if (deps['
|
|
1575
|
+
if (deps['gatsby']) {
|
|
1772
1576
|
metaFrameworks.push({
|
|
1773
|
-
id: '
|
|
1774
|
-
name: '
|
|
1577
|
+
id: 'gatsby',
|
|
1578
|
+
name: 'Gatsby',
|
|
1775
1579
|
category: 'meta-framework',
|
|
1776
|
-
version: parseVersionString(deps['
|
|
1580
|
+
version: parseVersionString(deps['gatsby']),
|
|
1777
1581
|
confidence: 90,
|
|
1778
|
-
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' }],
|
|
1779
1593
|
});
|
|
1780
1594
|
}
|
|
1781
1595
|
if (confidence === 0) {
|
|
1782
1596
|
return null;
|
|
1783
1597
|
}
|
|
1784
1598
|
return {
|
|
1785
|
-
id: '
|
|
1786
|
-
name: '
|
|
1599
|
+
id: 'react',
|
|
1600
|
+
name: 'React',
|
|
1787
1601
|
category: 'frontend',
|
|
1788
1602
|
version,
|
|
1789
1603
|
confidence: min(confidence, 100),
|
|
@@ -1793,37 +1607,58 @@ function vueDetector(projectPath, packageJson) {
|
|
|
1793
1607
|
}
|
|
1794
1608
|
|
|
1795
1609
|
/**
|
|
1796
|
-
* Detect
|
|
1610
|
+
* Detect Remix in project.
|
|
1797
1611
|
*
|
|
1798
1612
|
* @param projectPath - Project directory path
|
|
1799
1613
|
* @param packageJson - Optional pre-loaded package.json
|
|
1800
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
|
+
* ```
|
|
1801
1636
|
*/
|
|
1802
|
-
function
|
|
1637
|
+
function remixDetector(projectPath, packageJson) {
|
|
1803
1638
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1804
1639
|
const sources = [];
|
|
1805
1640
|
let confidence = 0;
|
|
1806
1641
|
let version;
|
|
1807
1642
|
const deps = collectAllDependencies(pkg);
|
|
1808
|
-
if (deps['
|
|
1643
|
+
if (deps['@remix-run/react']) {
|
|
1809
1644
|
confidence += 70;
|
|
1810
|
-
version = parseVersionString(deps['
|
|
1811
|
-
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' });
|
|
1812
1647
|
}
|
|
1813
|
-
if (
|
|
1814
|
-
confidence +=
|
|
1815
|
-
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/*' });
|
|
1816
1651
|
}
|
|
1817
|
-
if (exists(join$1(projectPath, '
|
|
1818
|
-
confidence +=
|
|
1819
|
-
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.*' });
|
|
1820
1655
|
}
|
|
1821
1656
|
if (confidence === 0) {
|
|
1822
1657
|
return null;
|
|
1823
1658
|
}
|
|
1824
1659
|
return {
|
|
1825
|
-
id: '
|
|
1826
|
-
name: '
|
|
1660
|
+
id: 'remix',
|
|
1661
|
+
name: 'Remix',
|
|
1827
1662
|
category: 'meta-framework',
|
|
1828
1663
|
version,
|
|
1829
1664
|
confidence: min(confidence, 100),
|
|
@@ -1832,47 +1667,55 @@ function nuxtDetector(projectPath, packageJson) {
|
|
|
1832
1667
|
}
|
|
1833
1668
|
|
|
1834
1669
|
/**
|
|
1835
|
-
* Detect
|
|
1670
|
+
* Detect Solid in project.
|
|
1836
1671
|
*
|
|
1837
1672
|
* @param projectPath - Project directory path
|
|
1838
1673
|
* @param packageJson - Optional pre-loaded package.json
|
|
1839
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
|
+
* ```
|
|
1840
1693
|
*/
|
|
1841
|
-
function
|
|
1694
|
+
function solidDetector(projectPath, packageJson) {
|
|
1842
1695
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1843
1696
|
const sources = [];
|
|
1844
1697
|
let confidence = 0;
|
|
1845
1698
|
let version;
|
|
1846
1699
|
const deps = collectAllDependencies(pkg);
|
|
1847
|
-
if (deps['
|
|
1700
|
+
if (deps['solid-js']) {
|
|
1848
1701
|
confidence += 70;
|
|
1849
|
-
version = parseVersionString(deps['
|
|
1850
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1851
|
-
}
|
|
1852
|
-
if (deps['@angular/cli']) {
|
|
1853
|
-
confidence += 15;
|
|
1854
|
-
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' });
|
|
1855
1704
|
}
|
|
1856
|
-
if (
|
|
1857
|
-
confidence +=
|
|
1858
|
-
sources.push({ type: '
|
|
1705
|
+
if (deps['vite-plugin-solid']) {
|
|
1706
|
+
confidence += 20;
|
|
1707
|
+
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
1859
1708
|
}
|
|
1860
|
-
if (deps['
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
name: 'AngularJS (Legacy)',
|
|
1864
|
-
category: 'frontend',
|
|
1865
|
-
version: parseVersionString(deps['angular']),
|
|
1866
|
-
confidence: 80,
|
|
1867
|
-
detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
|
|
1868
|
-
};
|
|
1709
|
+
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
1710
|
+
confidence += 10;
|
|
1711
|
+
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
1869
1712
|
}
|
|
1870
1713
|
if (confidence === 0) {
|
|
1871
1714
|
return null;
|
|
1872
1715
|
}
|
|
1873
1716
|
return {
|
|
1874
|
-
id: '
|
|
1875
|
-
name: '
|
|
1717
|
+
id: 'solid',
|
|
1718
|
+
name: 'Solid',
|
|
1876
1719
|
category: 'frontend',
|
|
1877
1720
|
version,
|
|
1878
1721
|
confidence: min(confidence, 100),
|
|
@@ -1886,6 +1729,21 @@ function angularDetector(projectPath, packageJson) {
|
|
|
1886
1729
|
* @param projectPath - Project directory path
|
|
1887
1730
|
* @param packageJson - Optional pre-loaded package.json
|
|
1888
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
|
+
* ```
|
|
1889
1747
|
*/
|
|
1890
1748
|
function svelteDetector(projectPath, packageJson) {
|
|
1891
1749
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1938,6 +1796,21 @@ function svelteDetector(projectPath, packageJson) {
|
|
|
1938
1796
|
* @param projectPath - Project directory path
|
|
1939
1797
|
* @param packageJson - Optional pre-loaded package.json
|
|
1940
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
|
+
* ```
|
|
1941
1814
|
*/
|
|
1942
1815
|
function sveltekitDetector(projectPath, packageJson) {
|
|
1943
1816
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -1972,121 +1845,76 @@ function sveltekitDetector(projectPath, packageJson) {
|
|
|
1972
1845
|
}
|
|
1973
1846
|
|
|
1974
1847
|
/**
|
|
1975
|
-
* Detect
|
|
1848
|
+
* Detect Vue in project.
|
|
1976
1849
|
*
|
|
1977
1850
|
* @param projectPath - Project directory path
|
|
1978
1851
|
* @param packageJson - Optional pre-loaded package.json
|
|
1979
1852
|
* @returns Detection result or null if not detected
|
|
1980
|
-
*/
|
|
1981
|
-
function solidDetector(projectPath, packageJson) {
|
|
1982
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
1983
|
-
const sources = [];
|
|
1984
|
-
let confidence = 0;
|
|
1985
|
-
let version;
|
|
1986
|
-
const deps = collectAllDependencies(pkg);
|
|
1987
|
-
if (deps['solid-js']) {
|
|
1988
|
-
confidence += 70;
|
|
1989
|
-
version = parseVersionString(deps['solid-js']);
|
|
1990
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
|
|
1991
|
-
}
|
|
1992
|
-
if (deps['vite-plugin-solid']) {
|
|
1993
|
-
confidence += 20;
|
|
1994
|
-
sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
|
|
1995
|
-
}
|
|
1996
|
-
if (deps['solid-start'] || deps['@solidjs/start']) {
|
|
1997
|
-
confidence += 10;
|
|
1998
|
-
sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
|
|
1999
|
-
}
|
|
2000
|
-
if (confidence === 0) {
|
|
2001
|
-
return null;
|
|
2002
|
-
}
|
|
2003
|
-
return {
|
|
2004
|
-
id: 'solid',
|
|
2005
|
-
name: 'Solid',
|
|
2006
|
-
category: 'frontend',
|
|
2007
|
-
version,
|
|
2008
|
-
confidence: min(confidence, 100),
|
|
2009
|
-
detectedFrom: sources,
|
|
2010
|
-
};
|
|
2011
|
-
}
|
|
2012
|
-
|
|
2013
|
-
/**
|
|
2014
|
-
* Detect Qwik in project.
|
|
2015
1853
|
*
|
|
2016
|
-
* @
|
|
2017
|
-
*
|
|
2018
|
-
*
|
|
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
|
+
* ```
|
|
2019
1871
|
*/
|
|
2020
|
-
function
|
|
1872
|
+
function vueDetector(projectPath, packageJson) {
|
|
2021
1873
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2022
1874
|
const sources = [];
|
|
2023
1875
|
let confidence = 0;
|
|
2024
1876
|
let version;
|
|
1877
|
+
const metaFrameworks = [];
|
|
2025
1878
|
const deps = collectAllDependencies(pkg);
|
|
2026
|
-
if (deps['
|
|
1879
|
+
if (deps['vue']) {
|
|
2027
1880
|
confidence += 70;
|
|
2028
|
-
version = parseVersionString(deps['
|
|
2029
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
1881
|
+
version = parseVersionString(deps['vue']);
|
|
1882
|
+
sources.push({ type: 'package.json', field: 'dependencies.vue' });
|
|
2030
1883
|
}
|
|
2031
|
-
if (deps['@
|
|
2032
|
-
confidence +=
|
|
2033
|
-
sources.push({ type: 'package.json', field: 'dependencies.@
|
|
1884
|
+
if (deps['@vue/cli-service']) {
|
|
1885
|
+
confidence += 15;
|
|
1886
|
+
sources.push({ type: 'package.json', field: 'dependencies.@vue/cli-service' });
|
|
2034
1887
|
}
|
|
2035
|
-
|
|
1888
|
+
const hasVueFiles = exists(join$1(projectPath, 'src', 'App.vue')) || exists(join$1(projectPath, 'src', 'main.vue'));
|
|
1889
|
+
if (hasVueFiles) {
|
|
2036
1890
|
confidence += 10;
|
|
2037
|
-
sources.push({ type: '
|
|
2038
|
-
}
|
|
2039
|
-
if (confidence === 0) {
|
|
2040
|
-
return null;
|
|
2041
|
-
}
|
|
2042
|
-
return {
|
|
2043
|
-
id: 'qwik',
|
|
2044
|
-
name: 'Qwik',
|
|
2045
|
-
category: 'frontend',
|
|
2046
|
-
version,
|
|
2047
|
-
confidence: min(confidence, 100),
|
|
2048
|
-
detectedFrom: sources,
|
|
2049
|
-
};
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
/**
|
|
2053
|
-
* Detect Astro in project.
|
|
2054
|
-
*
|
|
2055
|
-
* @param projectPath - Project directory path
|
|
2056
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2057
|
-
* @returns Detection result or null if not detected
|
|
2058
|
-
*/
|
|
2059
|
-
function astroDetector(projectPath, packageJson) {
|
|
2060
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2061
|
-
const sources = [];
|
|
2062
|
-
let confidence = 0;
|
|
2063
|
-
let version;
|
|
2064
|
-
const deps = collectAllDependencies(pkg);
|
|
2065
|
-
if (deps['astro']) {
|
|
2066
|
-
confidence += 70;
|
|
2067
|
-
version = parseVersionString(deps['astro']);
|
|
2068
|
-
sources.push({ type: 'package.json', field: 'dependencies.astro' });
|
|
2069
|
-
}
|
|
2070
|
-
if (exists(join$1(projectPath, 'astro.config.mjs')) ||
|
|
2071
|
-
exists(join$1(projectPath, 'astro.config.ts')) ||
|
|
2072
|
-
exists(join$1(projectPath, 'astro.config.js'))) {
|
|
2073
|
-
confidence += 25;
|
|
2074
|
-
sources.push({ type: 'config-file', path: 'astro.config.*' });
|
|
1891
|
+
sources.push({ type: 'directory', path: 'src/*.vue' });
|
|
2075
1892
|
}
|
|
2076
|
-
if (exists(join$1(projectPath, '
|
|
1893
|
+
if (exists(join$1(projectPath, 'vue.config.js'))) {
|
|
2077
1894
|
confidence += 5;
|
|
2078
|
-
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
|
+
});
|
|
2079
1906
|
}
|
|
2080
1907
|
if (confidence === 0) {
|
|
2081
1908
|
return null;
|
|
2082
1909
|
}
|
|
2083
1910
|
return {
|
|
2084
|
-
id: '
|
|
2085
|
-
name: '
|
|
2086
|
-
category: '
|
|
1911
|
+
id: 'vue',
|
|
1912
|
+
name: 'Vue',
|
|
1913
|
+
category: 'frontend',
|
|
2087
1914
|
version,
|
|
2088
1915
|
confidence: min(confidence, 100),
|
|
2089
1916
|
detectedFrom: sources,
|
|
1917
|
+
metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
|
|
2090
1918
|
};
|
|
2091
1919
|
}
|
|
2092
1920
|
|
|
@@ -2113,6 +1941,14 @@ const frameworkDetectors = [
|
|
|
2113
1941
|
* @param projectPath - Project directory path
|
|
2114
1942
|
* @param packageJson - Optional pre-loaded package.json
|
|
2115
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
|
+
* ```
|
|
2116
1952
|
*/
|
|
2117
1953
|
function angularJSDetector(projectPath, packageJson) {
|
|
2118
1954
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2156,6 +1992,14 @@ function angularJSDetector(projectPath, packageJson) {
|
|
|
2156
1992
|
* @param projectPath - Project directory path
|
|
2157
1993
|
* @param packageJson - Optional pre-loaded package.json
|
|
2158
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
|
+
* ```
|
|
2159
2003
|
*/
|
|
2160
2004
|
function backboneDetector(projectPath, packageJson) {
|
|
2161
2005
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2199,6 +2043,15 @@ function backboneDetector(projectPath, packageJson) {
|
|
|
2199
2043
|
* @param projectPath - Project directory path
|
|
2200
2044
|
* @param packageJson - Optional pre-loaded package.json
|
|
2201
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
|
+
* ```
|
|
2202
2055
|
*/
|
|
2203
2056
|
function emberDetector(projectPath, packageJson) {
|
|
2204
2057
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2238,6 +2091,14 @@ function emberDetector(projectPath, packageJson) {
|
|
|
2238
2091
|
* @param projectPath - Project directory path
|
|
2239
2092
|
* @param packageJson - Optional pre-loaded package.json
|
|
2240
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
|
+
* ```
|
|
2241
2102
|
*/
|
|
2242
2103
|
function jqueryDetector(projectPath, packageJson) {
|
|
2243
2104
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2250,35 +2111,85 @@ function jqueryDetector(projectPath, packageJson) {
|
|
|
2250
2111
|
version = parseVersionString(deps['jquery']);
|
|
2251
2112
|
sources.push({ type: 'package.json', field: 'dependencies.jquery' });
|
|
2252
2113
|
}
|
|
2253
|
-
if (deps['jquery-ui']) {
|
|
2254
|
-
confidence += 10;
|
|
2255
|
-
sources.push({ type: 'package.json', field: 'dependencies.jquery-ui' });
|
|
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' });
|
|
2256
2174
|
}
|
|
2257
|
-
if (
|
|
2258
|
-
confidence +=
|
|
2259
|
-
|
|
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' });
|
|
2260
2179
|
}
|
|
2261
2180
|
if (confidence === 0) {
|
|
2262
2181
|
return null;
|
|
2263
2182
|
}
|
|
2264
2183
|
return {
|
|
2265
|
-
id: '
|
|
2266
|
-
name: '
|
|
2267
|
-
category: 'legacy-frontend',
|
|
2184
|
+
id: 'biome',
|
|
2185
|
+
name: 'Biome',
|
|
2268
2186
|
version,
|
|
2187
|
+
configPath,
|
|
2269
2188
|
confidence: min(confidence, 100),
|
|
2270
2189
|
detectedFrom: sources,
|
|
2271
2190
|
};
|
|
2272
2191
|
}
|
|
2273
2192
|
|
|
2274
|
-
/** All legacy framework detectors */
|
|
2275
|
-
const legacyDetectors = [
|
|
2276
|
-
{ id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
|
|
2277
|
-
{ id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
|
|
2278
|
-
{ id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
|
|
2279
|
-
{ id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
|
|
2280
|
-
];
|
|
2281
|
-
|
|
2282
2193
|
/** Config patterns for ESLint */
|
|
2283
2194
|
const ESLINT_CONFIG_PATTERNS = [
|
|
2284
2195
|
'eslint.config.js',
|
|
@@ -2298,6 +2209,15 @@ const ESLINT_CONFIG_PATTERNS = [
|
|
|
2298
2209
|
* @param projectPath - Project directory path
|
|
2299
2210
|
* @param packageJson - Optional pre-loaded package.json
|
|
2300
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
|
+
* ```
|
|
2301
2221
|
*/
|
|
2302
2222
|
function eslintDetector(projectPath, packageJson) {
|
|
2303
2223
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2361,6 +2281,15 @@ const PRETTIER_CONFIG_PATTERNS = [
|
|
|
2361
2281
|
* @param projectPath - Project directory path
|
|
2362
2282
|
* @param packageJson - Optional pre-loaded package.json
|
|
2363
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
|
+
* ```
|
|
2364
2293
|
*/
|
|
2365
2294
|
function prettierDetector(projectPath, packageJson) {
|
|
2366
2295
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2423,6 +2352,14 @@ const STYLELINT_CONFIG_PATTERNS = [
|
|
|
2423
2352
|
* @param projectPath - Project directory path
|
|
2424
2353
|
* @param packageJson - Optional pre-loaded package.json
|
|
2425
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
|
+
* ```
|
|
2426
2363
|
*/
|
|
2427
2364
|
function stylelintDetector(projectPath, packageJson) {
|
|
2428
2365
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2462,48 +2399,6 @@ function stylelintDetector(projectPath, packageJson) {
|
|
|
2462
2399
|
};
|
|
2463
2400
|
}
|
|
2464
2401
|
|
|
2465
|
-
/**
|
|
2466
|
-
* Detect Biome in project.
|
|
2467
|
-
*
|
|
2468
|
-
* @param projectPath - Project directory path
|
|
2469
|
-
* @param packageJson - Optional pre-loaded package.json
|
|
2470
|
-
* @returns Detection result or null if not detected
|
|
2471
|
-
*/
|
|
2472
|
-
function biomeDetector(projectPath, packageJson) {
|
|
2473
|
-
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2474
|
-
const sources = [];
|
|
2475
|
-
let confidence = 0;
|
|
2476
|
-
let configPath;
|
|
2477
|
-
let version;
|
|
2478
|
-
const deps = collectAllDependencies(pkg);
|
|
2479
|
-
if (deps['@biomejs/biome']) {
|
|
2480
|
-
confidence += 70;
|
|
2481
|
-
version = parseVersionString(deps['@biomejs/biome']);
|
|
2482
|
-
sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
|
|
2483
|
-
}
|
|
2484
|
-
if (exists(join$1(projectPath, 'biome.json'))) {
|
|
2485
|
-
confidence += 30;
|
|
2486
|
-
configPath = 'biome.json';
|
|
2487
|
-
sources.push({ type: 'config-file', path: 'biome.json' });
|
|
2488
|
-
}
|
|
2489
|
-
if (!configPath && exists(join$1(projectPath, 'biome.jsonc'))) {
|
|
2490
|
-
confidence += 30;
|
|
2491
|
-
configPath = 'biome.jsonc';
|
|
2492
|
-
sources.push({ type: 'config-file', path: 'biome.jsonc' });
|
|
2493
|
-
}
|
|
2494
|
-
if (confidence === 0) {
|
|
2495
|
-
return null;
|
|
2496
|
-
}
|
|
2497
|
-
return {
|
|
2498
|
-
id: 'biome',
|
|
2499
|
-
name: 'Biome',
|
|
2500
|
-
version,
|
|
2501
|
-
configPath,
|
|
2502
|
-
confidence: min(confidence, 100),
|
|
2503
|
-
detectedFrom: sources,
|
|
2504
|
-
};
|
|
2505
|
-
}
|
|
2506
|
-
|
|
2507
2402
|
/** All linting tool detectors */
|
|
2508
2403
|
const lintingDetectors = [
|
|
2509
2404
|
{ id: 'eslint', name: 'ESLint', detect: eslintDetector },
|
|
@@ -2513,140 +2408,179 @@ const lintingDetectors = [
|
|
|
2513
2408
|
];
|
|
2514
2409
|
|
|
2515
2410
|
/**
|
|
2516
|
-
* Detect
|
|
2411
|
+
* Detect Lerna in project.
|
|
2517
2412
|
*
|
|
2518
2413
|
* @param workspacePath - Workspace directory path
|
|
2519
2414
|
* @param packageJson - Optional pre-loaded package.json
|
|
2520
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
|
+
* ```
|
|
2521
2429
|
*/
|
|
2522
|
-
function
|
|
2430
|
+
function lernaDetector(workspacePath, packageJson) {
|
|
2523
2431
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2524
2432
|
const sources = [];
|
|
2525
2433
|
let confidence = 0;
|
|
2526
2434
|
let version;
|
|
2527
|
-
let
|
|
2528
|
-
const
|
|
2529
|
-
if (exists(
|
|
2530
|
-
confidence +=
|
|
2531
|
-
|
|
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' });
|
|
2532
2441
|
}
|
|
2533
2442
|
const deps = collectAllDependencies(pkg);
|
|
2534
|
-
if (deps['
|
|
2535
|
-
confidence +=
|
|
2536
|
-
version = parseVersionString(deps['
|
|
2537
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2538
|
-
}
|
|
2539
|
-
const hasApps = exists(join$1(workspacePath, 'apps'));
|
|
2540
|
-
const hasLibs = exists(join$1(workspacePath, 'libs'));
|
|
2541
|
-
if (hasApps || hasLibs) {
|
|
2542
|
-
confidence += 10;
|
|
2543
|
-
sources.push({ type: 'directory', path: 'apps/ or libs/' });
|
|
2544
|
-
workspaceLayout = {
|
|
2545
|
-
appsDir: hasApps ? 'apps' : '',
|
|
2546
|
-
libsDir: hasLibs ? 'libs' : '',
|
|
2547
|
-
};
|
|
2443
|
+
if (deps['lerna']) {
|
|
2444
|
+
confidence += 15;
|
|
2445
|
+
version = parseVersionString(deps['lerna']);
|
|
2446
|
+
sources.push({ type: 'package.json', field: 'dependencies.lerna' });
|
|
2548
2447
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
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/' });
|
|
2553
2451
|
}
|
|
2554
2452
|
if (confidence === 0) {
|
|
2555
2453
|
return null;
|
|
2556
2454
|
}
|
|
2557
2455
|
return {
|
|
2558
|
-
id: '
|
|
2559
|
-
name: '
|
|
2456
|
+
id: 'lerna',
|
|
2457
|
+
name: 'Lerna',
|
|
2560
2458
|
version,
|
|
2561
|
-
configPath
|
|
2459
|
+
configPath,
|
|
2562
2460
|
confidence: min(confidence, 100),
|
|
2563
2461
|
detectedFrom: sources,
|
|
2564
|
-
workspaceLayout,
|
|
2565
2462
|
};
|
|
2566
2463
|
}
|
|
2567
2464
|
|
|
2568
2465
|
/**
|
|
2569
|
-
* Detect
|
|
2466
|
+
* Detect npm workspaces in project.
|
|
2570
2467
|
*
|
|
2571
2468
|
* @param workspacePath - Workspace directory path
|
|
2572
2469
|
* @param packageJson - Optional pre-loaded package.json
|
|
2573
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
|
+
* ```
|
|
2574
2487
|
*/
|
|
2575
|
-
function
|
|
2488
|
+
function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
2576
2489
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2577
2490
|
const sources = [];
|
|
2578
2491
|
let confidence = 0;
|
|
2579
|
-
|
|
2580
|
-
let configPath;
|
|
2581
|
-
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
2582
|
-
if (exists(turboJsonPath)) {
|
|
2492
|
+
if (pkg?.workspaces) {
|
|
2583
2493
|
confidence += 80;
|
|
2584
|
-
|
|
2585
|
-
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2494
|
+
sources.push({ type: 'package.json', field: 'workspaces' });
|
|
2586
2495
|
}
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
version = parseVersionString(deps['turbo']);
|
|
2591
|
-
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' });
|
|
2592
2499
|
}
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
confidence += 5;
|
|
2596
|
-
sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
|
|
2500
|
+
if (exists(join$1(workspacePath, 'yarn.lock'))) {
|
|
2501
|
+
return null;
|
|
2597
2502
|
}
|
|
2598
2503
|
if (confidence === 0) {
|
|
2599
2504
|
return null;
|
|
2600
2505
|
}
|
|
2601
2506
|
return {
|
|
2602
|
-
id: '
|
|
2603
|
-
name: '
|
|
2604
|
-
|
|
2605
|
-
configPath,
|
|
2507
|
+
id: 'npm-workspaces',
|
|
2508
|
+
name: 'npm Workspaces',
|
|
2509
|
+
configPath: 'package.json',
|
|
2606
2510
|
confidence: min(confidence, 100),
|
|
2607
2511
|
detectedFrom: sources,
|
|
2608
2512
|
};
|
|
2609
2513
|
}
|
|
2610
2514
|
|
|
2611
2515
|
/**
|
|
2612
|
-
* Detect
|
|
2516
|
+
* Detect NX in project.
|
|
2613
2517
|
*
|
|
2614
2518
|
* @param workspacePath - Workspace directory path
|
|
2615
2519
|
* @param packageJson - Optional pre-loaded package.json
|
|
2616
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
|
+
* ```
|
|
2617
2540
|
*/
|
|
2618
|
-
function
|
|
2541
|
+
function nxDetector(workspacePath, packageJson) {
|
|
2619
2542
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2620
2543
|
const sources = [];
|
|
2621
2544
|
let confidence = 0;
|
|
2622
2545
|
let version;
|
|
2623
|
-
let
|
|
2624
|
-
const
|
|
2625
|
-
if (exists(
|
|
2626
|
-
confidence +=
|
|
2627
|
-
|
|
2628
|
-
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' });
|
|
2629
2551
|
}
|
|
2630
2552
|
const deps = collectAllDependencies(pkg);
|
|
2631
|
-
if (deps['
|
|
2632
|
-
confidence +=
|
|
2633
|
-
version = parseVersionString(deps['
|
|
2634
|
-
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' });
|
|
2635
2557
|
}
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
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' });
|
|
2639
2572
|
}
|
|
2640
2573
|
if (confidence === 0) {
|
|
2641
2574
|
return null;
|
|
2642
2575
|
}
|
|
2643
2576
|
return {
|
|
2644
|
-
id: '
|
|
2645
|
-
name: '
|
|
2577
|
+
id: 'nx',
|
|
2578
|
+
name: 'NX',
|
|
2646
2579
|
version,
|
|
2647
|
-
configPath,
|
|
2580
|
+
configPath: exists(nxJsonPath) ? 'nx.json' : undefined,
|
|
2648
2581
|
confidence: min(confidence, 100),
|
|
2649
2582
|
detectedFrom: sources,
|
|
2583
|
+
workspaceLayout,
|
|
2650
2584
|
};
|
|
2651
2585
|
}
|
|
2652
2586
|
|
|
@@ -2656,6 +2590,19 @@ function lernaDetector(workspacePath, packageJson) {
|
|
|
2656
2590
|
* @param workspacePath - Workspace directory path
|
|
2657
2591
|
* @param packageJson - Optional pre-loaded package.json
|
|
2658
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
|
+
* ```
|
|
2659
2606
|
*/
|
|
2660
2607
|
function rushDetector(workspacePath, packageJson) {
|
|
2661
2608
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2670,54 +2617,22 @@ function rushDetector(workspacePath, packageJson) {
|
|
|
2670
2617
|
sources.push({ type: 'config-file', path: 'rush.json' });
|
|
2671
2618
|
}
|
|
2672
2619
|
const deps = collectAllDependencies(pkg);
|
|
2673
|
-
if (deps['@microsoft/rush']) {
|
|
2674
|
-
confidence += 10;
|
|
2675
|
-
version = parseVersionString(deps['@microsoft/rush']);
|
|
2676
|
-
sources.push({ type: 'package.json', field: 'dependencies.@microsoft/rush' });
|
|
2677
|
-
}
|
|
2678
|
-
if (exists(join$1(workspacePath, 'common', 'config', 'rush'))) {
|
|
2679
|
-
confidence += 5;
|
|
2680
|
-
sources.push({ type: 'directory', path: 'common/config/rush/' });
|
|
2681
|
-
}
|
|
2682
|
-
if (confidence === 0) {
|
|
2683
|
-
return null;
|
|
2684
|
-
}
|
|
2685
|
-
return {
|
|
2686
|
-
id: 'rush',
|
|
2687
|
-
name: 'Rush',
|
|
2688
|
-
version,
|
|
2689
|
-
configPath,
|
|
2690
|
-
confidence: min(confidence, 100),
|
|
2691
|
-
detectedFrom: sources,
|
|
2692
|
-
};
|
|
2693
|
-
}
|
|
2694
|
-
|
|
2695
|
-
/**
|
|
2696
|
-
* Detect pnpm workspaces in project.
|
|
2697
|
-
*
|
|
2698
|
-
* @param workspacePath - Workspace directory path
|
|
2699
|
-
* @returns Detection result or null if not detected
|
|
2700
|
-
*/
|
|
2701
|
-
function pnpmWorkspacesDetector(workspacePath) {
|
|
2702
|
-
const sources = [];
|
|
2703
|
-
let confidence = 0;
|
|
2704
|
-
let configPath;
|
|
2705
|
-
const pnpmWorkspacePath = join$1(workspacePath, 'pnpm-workspace.yaml');
|
|
2706
|
-
if (exists(pnpmWorkspacePath)) {
|
|
2707
|
-
confidence += 90;
|
|
2708
|
-
configPath = 'pnpm-workspace.yaml';
|
|
2709
|
-
sources.push({ type: 'config-file', path: 'pnpm-workspace.yaml' });
|
|
2710
|
-
}
|
|
2711
|
-
if (exists(join$1(workspacePath, 'pnpm-lock.yaml'))) {
|
|
2620
|
+
if (deps['@microsoft/rush']) {
|
|
2712
2621
|
confidence += 10;
|
|
2713
|
-
|
|
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/' });
|
|
2714
2628
|
}
|
|
2715
2629
|
if (confidence === 0) {
|
|
2716
2630
|
return null;
|
|
2717
2631
|
}
|
|
2718
2632
|
return {
|
|
2719
|
-
id: '
|
|
2720
|
-
name: '
|
|
2633
|
+
id: 'rush',
|
|
2634
|
+
name: 'Rush',
|
|
2635
|
+
version,
|
|
2721
2636
|
configPath,
|
|
2722
2637
|
confidence: min(confidence, 100),
|
|
2723
2638
|
detectedFrom: sources,
|
|
@@ -2725,34 +2640,60 @@ function pnpmWorkspacesDetector(workspacePath) {
|
|
|
2725
2640
|
}
|
|
2726
2641
|
|
|
2727
2642
|
/**
|
|
2728
|
-
* Detect
|
|
2643
|
+
* Detect Turborepo in project.
|
|
2729
2644
|
*
|
|
2730
2645
|
* @param workspacePath - Workspace directory path
|
|
2731
2646
|
* @param packageJson - Optional pre-loaded package.json
|
|
2732
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
|
+
* ```
|
|
2733
2665
|
*/
|
|
2734
|
-
function
|
|
2666
|
+
function turborepoDetector(workspacePath, packageJson) {
|
|
2735
2667
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
2736
2668
|
const sources = [];
|
|
2737
2669
|
let confidence = 0;
|
|
2738
|
-
|
|
2670
|
+
let version;
|
|
2671
|
+
let configPath;
|
|
2672
|
+
const turboJsonPath = join$1(workspacePath, 'turbo.json');
|
|
2673
|
+
if (exists(turboJsonPath)) {
|
|
2739
2674
|
confidence += 80;
|
|
2740
|
-
|
|
2675
|
+
configPath = 'turbo.json';
|
|
2676
|
+
sources.push({ type: 'config-file', path: 'turbo.json' });
|
|
2741
2677
|
}
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
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' });
|
|
2745
2683
|
}
|
|
2746
|
-
|
|
2747
|
-
|
|
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)' });
|
|
2748
2688
|
}
|
|
2749
2689
|
if (confidence === 0) {
|
|
2750
2690
|
return null;
|
|
2751
2691
|
}
|
|
2752
2692
|
return {
|
|
2753
|
-
id: '
|
|
2754
|
-
name: '
|
|
2755
|
-
|
|
2693
|
+
id: 'turborepo',
|
|
2694
|
+
name: 'Turborepo',
|
|
2695
|
+
version,
|
|
2696
|
+
configPath,
|
|
2756
2697
|
confidence: min(confidence, 100),
|
|
2757
2698
|
detectedFrom: sources,
|
|
2758
2699
|
};
|
|
@@ -2764,6 +2705,23 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
|
|
|
2764
2705
|
* @param workspacePath - Workspace directory path
|
|
2765
2706
|
* @param packageJson - Optional pre-loaded package.json
|
|
2766
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
|
+
* ```
|
|
2767
2725
|
*/
|
|
2768
2726
|
function yarnWorkspacesDetector(workspacePath, packageJson) {
|
|
2769
2727
|
const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
|
|
@@ -2804,55 +2762,58 @@ const monorepoDetectors = [
|
|
|
2804
2762
|
{ id: 'yarn-workspaces', name: 'Yarn Workspaces', detect: yarnWorkspacesDetector },
|
|
2805
2763
|
];
|
|
2806
2764
|
|
|
2807
|
-
/** Config patterns for
|
|
2808
|
-
const
|
|
2765
|
+
/** Config patterns for Cypress */
|
|
2766
|
+
const CYPRESS_CONFIG_PATTERNS = ['cypress.config.js', 'cypress.config.ts', 'cypress.config.mjs', 'cypress.json'];
|
|
2809
2767
|
/**
|
|
2810
|
-
* Detect
|
|
2768
|
+
* Detect Cypress in project.
|
|
2811
2769
|
*
|
|
2812
2770
|
* @param projectPath - Project directory path
|
|
2813
2771
|
* @param packageJson - Optional pre-loaded package.json
|
|
2814
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
|
+
* ```
|
|
2815
2784
|
*/
|
|
2816
|
-
function
|
|
2785
|
+
function cypressDetector(projectPath, packageJson) {
|
|
2817
2786
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2818
2787
|
const sources = [];
|
|
2819
2788
|
let confidence = 0;
|
|
2820
2789
|
let version;
|
|
2821
2790
|
const deps = collectAllDependencies(pkg);
|
|
2822
|
-
if (deps['
|
|
2791
|
+
if (deps['cypress']) {
|
|
2823
2792
|
confidence += 60;
|
|
2824
|
-
version = parseVersionString(deps['
|
|
2825
|
-
sources.push({ type: 'package.json', field: 'dependencies.
|
|
2793
|
+
version = parseVersionString(deps['cypress']);
|
|
2794
|
+
sources.push({ type: 'package.json', field: 'dependencies.cypress' });
|
|
2826
2795
|
}
|
|
2827
|
-
const configPath = locateConfigFile(projectPath,
|
|
2796
|
+
const configPath = locateConfigFile(projectPath, CYPRESS_CONFIG_PATTERNS);
|
|
2828
2797
|
if (configPath) {
|
|
2829
2798
|
confidence += 30;
|
|
2830
2799
|
sources.push({ type: 'config-file', path: configPath });
|
|
2831
2800
|
}
|
|
2832
|
-
if (
|
|
2833
|
-
confidence += 20;
|
|
2834
|
-
sources.push({ type: 'package.json', field: 'jest' });
|
|
2835
|
-
}
|
|
2836
|
-
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
2837
|
-
if (testScript.includes('jest')) {
|
|
2801
|
+
if (exists(join$1(projectPath, 'cypress'))) {
|
|
2838
2802
|
confidence += 10;
|
|
2839
|
-
sources.push({ type: '
|
|
2840
|
-
}
|
|
2841
|
-
if (deps['@types/jest']) {
|
|
2842
|
-
confidence += 5;
|
|
2843
|
-
sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
|
|
2803
|
+
sources.push({ type: 'directory', path: 'cypress/' });
|
|
2844
2804
|
}
|
|
2845
|
-
|
|
2805
|
+
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
2806
|
+
if (e2eScript.includes('cypress')) {
|
|
2846
2807
|
confidence += 5;
|
|
2847
|
-
sources.push({ type: 'package.json', field: '
|
|
2808
|
+
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
2848
2809
|
}
|
|
2849
2810
|
if (confidence === 0) {
|
|
2850
2811
|
return null;
|
|
2851
2812
|
}
|
|
2852
2813
|
return {
|
|
2853
|
-
id: '
|
|
2854
|
-
name: '
|
|
2855
|
-
type: '
|
|
2814
|
+
id: 'cypress',
|
|
2815
|
+
name: 'Cypress',
|
|
2816
|
+
type: 'e2e',
|
|
2856
2817
|
version,
|
|
2857
2818
|
configPath,
|
|
2858
2819
|
confidence: min(confidence, 100),
|
|
@@ -2860,51 +2821,66 @@ function jestDetector(projectPath, packageJson) {
|
|
|
2860
2821
|
};
|
|
2861
2822
|
}
|
|
2862
2823
|
|
|
2863
|
-
/** Config patterns for
|
|
2864
|
-
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'];
|
|
2865
2826
|
/**
|
|
2866
|
-
* Detect
|
|
2827
|
+
* Detect Jest in project.
|
|
2867
2828
|
*
|
|
2868
2829
|
* @param projectPath - Project directory path
|
|
2869
2830
|
* @param packageJson - Optional pre-loaded package.json
|
|
2870
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
|
+
* ```
|
|
2871
2844
|
*/
|
|
2872
|
-
function
|
|
2845
|
+
function jestDetector(projectPath, packageJson) {
|
|
2873
2846
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2874
2847
|
const sources = [];
|
|
2875
2848
|
let confidence = 0;
|
|
2876
2849
|
let version;
|
|
2877
2850
|
const deps = collectAllDependencies(pkg);
|
|
2878
|
-
if (deps['
|
|
2879
|
-
confidence +=
|
|
2880
|
-
version = parseVersionString(deps['
|
|
2881
|
-
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' });
|
|
2882
2855
|
}
|
|
2883
|
-
const configPath = locateConfigFile(projectPath,
|
|
2856
|
+
const configPath = locateConfigFile(projectPath, JEST_CONFIG_PATTERNS);
|
|
2884
2857
|
if (configPath) {
|
|
2885
|
-
confidence +=
|
|
2858
|
+
confidence += 30;
|
|
2886
2859
|
sources.push({ type: 'config-file', path: configPath });
|
|
2887
2860
|
}
|
|
2888
|
-
if (
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
exists(join$1(projectPath, 'vite.config.mjs'));
|
|
2892
|
-
if (viteConfig && deps['vitest']) {
|
|
2893
|
-
confidence += 5;
|
|
2894
|
-
sources.push({ type: 'config-file', path: 'vite.config.*' });
|
|
2895
|
-
}
|
|
2861
|
+
if (pkg && 'jest' in pkg) {
|
|
2862
|
+
confidence += 20;
|
|
2863
|
+
sources.push({ type: 'package.json', field: 'jest' });
|
|
2896
2864
|
}
|
|
2897
2865
|
const testScript = pkg?.scripts?.['test'] ?? '';
|
|
2898
|
-
if (testScript.includes('
|
|
2866
|
+
if (testScript.includes('jest')) {
|
|
2899
2867
|
confidence += 10;
|
|
2900
2868
|
sources.push({ type: 'package.json', field: 'scripts.test' });
|
|
2901
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
|
+
}
|
|
2902
2878
|
if (confidence === 0) {
|
|
2903
2879
|
return null;
|
|
2904
2880
|
}
|
|
2905
2881
|
return {
|
|
2906
|
-
id: '
|
|
2907
|
-
name: '
|
|
2882
|
+
id: 'jest',
|
|
2883
|
+
name: 'Jest',
|
|
2908
2884
|
type: 'unit',
|
|
2909
2885
|
version,
|
|
2910
2886
|
configPath,
|
|
@@ -2921,6 +2897,17 @@ const MOCHA_CONFIG_PATTERNS = ['.mocharc.js', '.mocharc.json', '.mocharc.yaml',
|
|
|
2921
2897
|
* @param projectPath - Project directory path
|
|
2922
2898
|
* @param packageJson - Optional pre-loaded package.json
|
|
2923
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
|
+
* ```
|
|
2924
2911
|
*/
|
|
2925
2912
|
function mochaDetector(projectPath, packageJson) {
|
|
2926
2913
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -2965,37 +2952,53 @@ function mochaDetector(projectPath, packageJson) {
|
|
|
2965
2952
|
};
|
|
2966
2953
|
}
|
|
2967
2954
|
|
|
2968
|
-
/** Config patterns for
|
|
2969
|
-
const
|
|
2955
|
+
/** Config patterns for Playwright */
|
|
2956
|
+
const PLAYWRIGHT_CONFIG_PATTERNS = ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs'];
|
|
2970
2957
|
/**
|
|
2971
|
-
* Detect
|
|
2958
|
+
* Detect Playwright in project.
|
|
2972
2959
|
*
|
|
2973
2960
|
* @param projectPath - Project directory path
|
|
2974
2961
|
* @param packageJson - Optional pre-loaded package.json
|
|
2975
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
|
+
* ```
|
|
2976
2974
|
*/
|
|
2977
|
-
function
|
|
2975
|
+
function playwrightDetector(projectPath, packageJson) {
|
|
2978
2976
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
2979
2977
|
const sources = [];
|
|
2980
2978
|
let confidence = 0;
|
|
2981
2979
|
let version;
|
|
2982
2980
|
const deps = collectAllDependencies(pkg);
|
|
2983
|
-
if (deps['
|
|
2984
|
-
confidence +=
|
|
2985
|
-
version = parseVersionString(deps['
|
|
2986
|
-
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' });
|
|
2987
2985
|
}
|
|
2988
|
-
|
|
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);
|
|
2989
2992
|
if (configPath) {
|
|
2990
|
-
confidence +=
|
|
2993
|
+
confidence += 25;
|
|
2991
2994
|
sources.push({ type: 'config-file', path: configPath });
|
|
2992
2995
|
}
|
|
2993
|
-
if (exists(join$1(projectPath, '
|
|
2994
|
-
confidence +=
|
|
2995
|
-
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/' });
|
|
2996
2999
|
}
|
|
2997
3000
|
const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
|
|
2998
|
-
if (e2eScript.includes('
|
|
3001
|
+
if (e2eScript.includes('playwright')) {
|
|
2999
3002
|
confidence += 5;
|
|
3000
3003
|
sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
|
|
3001
3004
|
}
|
|
@@ -3003,8 +3006,8 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3003
3006
|
return null;
|
|
3004
3007
|
}
|
|
3005
3008
|
return {
|
|
3006
|
-
id: '
|
|
3007
|
-
name: '
|
|
3009
|
+
id: 'playwright',
|
|
3010
|
+
name: 'Playwright',
|
|
3008
3011
|
type: 'e2e',
|
|
3009
3012
|
version,
|
|
3010
3013
|
configPath,
|
|
@@ -3013,52 +3016,64 @@ function cypressDetector(projectPath, packageJson) {
|
|
|
3013
3016
|
};
|
|
3014
3017
|
}
|
|
3015
3018
|
|
|
3016
|
-
/** Config patterns for
|
|
3017
|
-
const
|
|
3019
|
+
/** Config patterns for Vitest */
|
|
3020
|
+
const VITEST_CONFIG_PATTERNS = ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'];
|
|
3018
3021
|
/**
|
|
3019
|
-
* Detect
|
|
3022
|
+
* Detect Vitest in project.
|
|
3020
3023
|
*
|
|
3021
3024
|
* @param projectPath - Project directory path
|
|
3022
3025
|
* @param packageJson - Optional pre-loaded package.json
|
|
3023
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
|
+
* ```
|
|
3024
3039
|
*/
|
|
3025
|
-
function
|
|
3040
|
+
function vitestDetector(projectPath, packageJson) {
|
|
3026
3041
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
3027
3042
|
const sources = [];
|
|
3028
3043
|
let confidence = 0;
|
|
3029
3044
|
let version;
|
|
3030
3045
|
const deps = collectAllDependencies(pkg);
|
|
3031
|
-
if (deps['
|
|
3046
|
+
if (deps['vitest']) {
|
|
3032
3047
|
confidence += 70;
|
|
3033
|
-
version = parseVersionString(deps['
|
|
3034
|
-
sources.push({ type: 'package.json', field: 'dependencies
|
|
3035
|
-
}
|
|
3036
|
-
if (deps['playwright']) {
|
|
3037
|
-
confidence += 50;
|
|
3038
|
-
version = version ?? parseVersionString(deps['playwright']);
|
|
3039
|
-
sources.push({ type: 'package.json', field: 'dependencies.playwright' });
|
|
3048
|
+
version = parseVersionString(deps['vitest']);
|
|
3049
|
+
sources.push({ type: 'package.json', field: 'dependencies.vitest' });
|
|
3040
3050
|
}
|
|
3041
|
-
const configPath = locateConfigFile(projectPath,
|
|
3051
|
+
const configPath = locateConfigFile(projectPath, VITEST_CONFIG_PATTERNS);
|
|
3042
3052
|
if (configPath) {
|
|
3043
3053
|
confidence += 25;
|
|
3044
3054
|
sources.push({ type: 'config-file', path: configPath });
|
|
3045
3055
|
}
|
|
3046
|
-
if (
|
|
3047
|
-
|
|
3048
|
-
|
|
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
|
+
}
|
|
3049
3064
|
}
|
|
3050
|
-
const
|
|
3051
|
-
if (
|
|
3052
|
-
confidence +=
|
|
3053
|
-
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' });
|
|
3054
3069
|
}
|
|
3055
3070
|
if (confidence === 0) {
|
|
3056
3071
|
return null;
|
|
3057
3072
|
}
|
|
3058
3073
|
return {
|
|
3059
|
-
id: '
|
|
3060
|
-
name: '
|
|
3061
|
-
type: '
|
|
3074
|
+
id: 'vitest',
|
|
3075
|
+
name: 'Vitest',
|
|
3076
|
+
type: 'unit',
|
|
3062
3077
|
version,
|
|
3063
3078
|
configPath,
|
|
3064
3079
|
confidence: min(confidence, 100),
|
|
@@ -3101,6 +3116,19 @@ function checkTsConfigStrict(projectPath) {
|
|
|
3101
3116
|
* @param projectPath - Project directory path
|
|
3102
3117
|
* @param packageJson - Optional pre-loaded package.json
|
|
3103
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
|
+
* ```
|
|
3104
3132
|
*/
|
|
3105
3133
|
function typescriptDetector(projectPath, packageJson) {
|
|
3106
3134
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3152,6 +3180,17 @@ function typescriptDetector(projectPath, packageJson) {
|
|
|
3152
3180
|
* @param projectPath - Project directory path
|
|
3153
3181
|
* @param packageJson - Optional pre-loaded package.json
|
|
3154
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
|
+
* ```
|
|
3155
3194
|
*/
|
|
3156
3195
|
function flowDetector(projectPath, packageJson) {
|
|
3157
3196
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3209,6 +3248,18 @@ function hasJsDocTypes(content) {
|
|
|
3209
3248
|
* @param projectPath - Project directory path
|
|
3210
3249
|
* @param packageJson - Optional pre-loaded package.json
|
|
3211
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
|
+
* ```
|
|
3212
3263
|
*/
|
|
3213
3264
|
function jsdocDetector(projectPath, packageJson) {
|
|
3214
3265
|
const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
|
|
@@ -3302,7 +3353,7 @@ function isDetectAllOptions(value) {
|
|
|
3302
3353
|
* @param packageJsonOrOptions - Optional pre-loaded package.json or options object
|
|
3303
3354
|
* @returns All detection results organized by category
|
|
3304
3355
|
*
|
|
3305
|
-
* @example
|
|
3356
|
+
* @example Running all tech detectors
|
|
3306
3357
|
* ```typescript
|
|
3307
3358
|
* import { detectAll } from '@hyperfrontend/project-scope'
|
|
3308
3359
|
*
|
|
@@ -3394,7 +3445,7 @@ const projectTypeLogger = createScopedLogger('project-scope:heuristics:project-t
|
|
|
3394
3445
|
* @param options - Detection options
|
|
3395
3446
|
* @returns Project type detection result with confidence score
|
|
3396
3447
|
*
|
|
3397
|
-
* @example
|
|
3448
|
+
* @example Detecting project type
|
|
3398
3449
|
* ```typescript
|
|
3399
3450
|
* import { detectProjectType } from '@hyperfrontend/project-scope'
|
|
3400
3451
|
*
|
|
@@ -3566,4 +3617,3 @@ function detectProjectType(projectPath, options) {
|
|
|
3566
3617
|
}
|
|
3567
3618
|
|
|
3568
3619
|
export { detectProjectType };
|
|
3569
|
-
//# sourceMappingURL=index.esm.js.map
|