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