├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .npmrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── src ├── index.cjs ├── index.d.cts ├── index.d.ts ├── index.js └── sync.cjs ├── tests ├── deps │ ├── cjs-js-lib │ │ ├── index.js │ │ └── package.json │ ├── esm-js-lib │ │ ├── index.js │ │ └── package.json │ ├── framework │ │ ├── index.js │ │ ├── package.json │ │ └── utils.js │ ├── full-direct-framework-lib │ │ ├── index.framework │ │ └── package.json │ ├── full-framework-lib │ │ ├── index.framework │ │ ├── index.js │ │ └── package.json │ ├── implicit-entry-cjs-lib │ │ ├── index.js │ │ └── package.json │ ├── no-deep-optimize-lib │ │ ├── index.js │ │ └── package.json │ ├── no-entry-lib │ │ ├── index.d.ts │ │ └── package.json │ ├── proxy-framework-lib │ │ ├── index.js │ │ └── package.json │ ├── semi-framework-lib │ │ ├── index.js │ │ └── package.json │ └── should-no-external-lib │ │ ├── index.js │ │ └── package.json ├── projects │ ├── basic │ │ ├── basic.test.js │ │ └── package.json │ ├── package.json │ │ └── empty.js │ └── workspace │ │ ├── package.json │ │ ├── packages │ │ ├── package.json │ │ ├── workspace-app │ │ │ └── package.json │ │ ├── workspace-esm-js-lib │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── workspace-full-direct-framework-lib │ │ │ ├── index.framework │ │ │ └── package.json │ │ ├── workspace-full-framework-lib │ │ │ ├── index.framework │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── workspace-proxy-framework-lib │ │ │ ├── index.js │ │ │ └── package.json │ │ └── workspace-semi-framework-lib │ │ │ ├── index.js │ │ │ └── package.json │ │ └── workspace.test.js └── unit.test.js └── tsconfig.json /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | env: 4 | # configure corepack 5 | COREPACK_DEFAULT_TO_LATEST: 0 6 | COREPACK_ENABLE_AUTO_PIN: 0 7 | # https://github.com/nodejs/corepack/issues/612#issuecomment-2631462297 8 | # This sets the old and new integrity keys for corepack to download different 9 | # package managers signed with different keys. 10 | COREPACK_INTEGRITY_KEYS: '{"npm":[{"expires":"2025-01-29T00:00:00.000Z","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","key":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg=="},{"expires":null,"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","key":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY6Ya7W++7aUPzvMTrezH6Ycx3c+HOKYCcNGybJZSCJq/fd7Qa8uuAKtdIkUQtQiEKERhAmE5lMMJhP8OkDOa2g=="}]}' 11 | # configure yarn 12 | YARN_ENABLE_IMMUTABLE_INSTALLS: 'false' 13 | 14 | on: 15 | push: 16 | branches: 17 | - main 18 | paths-ignore: 19 | - '**.md' 20 | pull_request: 21 | branches: 22 | - main 23 | paths-ignore: 24 | - '**.md' 25 | 26 | jobs: 27 | test: 28 | name: Test 29 | timeout-minutes: 5 30 | runs-on: ${{ matrix.os }} 31 | strategy: 32 | fail-fast: false 33 | matrix: 34 | node: [20] 35 | os: [ubuntu-latest, macos-latest, windows-latest] 36 | pm: ["pnpm@10"] 37 | include: 38 | - node: 22 39 | os: ubuntu-latest 40 | pm: "pnpm@10" 41 | - node: 22 42 | os: ubuntu-latest 43 | pm: "yarn@4" 44 | - node: 22 45 | os: ubuntu-latest 46 | pm: "npm@10" 47 | steps: 48 | - uses: actions/checkout@v4 49 | - uses: actions/setup-node@v4 50 | with: 51 | node-version: ${{ matrix.node }} 52 | - run: corepack enable 53 | - name: Install dependencies 54 | run: corepack ${{matrix.pm}} install 55 | 56 | - name: Test 57 | run: corepack ${{matrix.pm}} test 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .yarn 3 | .pnp.* 4 | yarn.lock 5 | package-lock.json 6 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers=false 2 | link-workspace-packages=true 3 | dedupe-injected-deps=false # needed for file: references to work 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.1.1 (2025-07-04) 4 | 5 | - fix: ensure workspaceRoot option works on windows ([#26](https://github.com/svitejs/vitefu/pull/26)) 6 | 7 | ## 1.1.0 (2025-07-03) 8 | 9 | - Add workspaceRoot option to `crawlFrameworkPkgs` that enables crawling devDependencies of local workspace **private** packages ([#23](https://github.com/svitejs/vitefu/pull/23)) 10 | 11 | ## 1.0.7 (2025-06-20) 12 | 13 | - Allow Vite 7 peer dependency ([#21](https://github.com/svitejs/vitefu/pull/21)) 14 | 15 | ## 1.0.6 (2025-02-24) 16 | 17 | - Handle `ssr.external: true` Vite config when calling `crawlFrameworkPkgs` and `isDepExternaled` ([#19](https://github.com/svitejs/vitefu/pull/19)) 18 | 19 | ## 1.0.5 (2025-01-02) 20 | 21 | - Don't require `package.json` to exist for `crawlFrameworkPkgs` ([#16](https://github.com/svitejs/vitefu/pull/16)) 22 | 23 | ## 1.0.4 (2024-11-26) 24 | 25 | - Allow Vite 6 peer dependency (remove beta support) 26 | 27 | ## 1.0.3 (2024-10-14) 28 | 29 | - Allow Vite 6 beta peer dependency (experimental support) 30 | 31 | ## 1.0.2 (2024-09-02) 32 | 33 | - Duplicate CJS types to correct ESM types export 34 | 35 | ## 1.0.1 (2024-09-02) 36 | 37 | - Fix ESM types export 38 | 39 | ## 1.0.0 (2024-08-26) 40 | 41 | The library is now v1! This release is mostly ceremonial as the API has been stable for a while without any plans to change it. As such, there are no breaking changes. 42 | 43 | - Remove top-level await to allow future compatibility to `require` ESM code 44 | - Export proper ESM and CJS types 45 | 46 | ## 0.2.5 (2023-10-13) 47 | 48 | - Align `findDepPkgJsonPath` implementation with Vite 49 | - Allow Vite 5 peer dependency 50 | 51 | ## 0.2.4 (2022-12-17) 52 | 53 | - Fix `findDepPkgJsonPath` usage in Windows mapped network drives 54 | 55 | ## 0.2.3 (2022-12-09) 56 | 57 | - Allow Vite 4 peer dependency 58 | 59 | ## 0.2.2 (2022-11-23) 60 | 61 | - `findClosestPkgJsonPath` only returns `package.json` file, not directory 62 | - Support `predicate` parameter for `findClosestPkgJsonPath` to filter paths 63 | 64 | ## 0.2.1 (2022-11-12) 65 | 66 | - Don't throw error if `package.json` not found in Deno 67 | 68 | ## 0.2.0 (2022-11-10) 69 | 70 | - BREAKING: Rename `pkgJsonNeedsOptimization` to `pkgNeedsOptimization` with new parameters and async for correctness 71 | - Prevent deep optimize packages with no exports and `index.js` file 72 | - Correctly respect Vite user config for `crawlFrameworkPkgs` 73 | - Export new utilities to respect Vite user config 74 | 75 | ## 0.1.1 (2022-11-01) 76 | 77 | - Resolve packages without root entry ([#1](https://github.com/svitejs/vitefu/issues/1)) 78 | - Support yarn pnp ([#2](https://github.com/svitejs/vitefu/issues/2)) 79 | 80 | ## 0.1.0 (2022-10-27) 81 | 82 | - Fix Windows `package.json` import resolve 83 | - Remove `ssr.external` duplicates for `crawlFrameworkPkgs` 84 | 85 | ## 0.0.1 (2022-10-26) 86 | 87 | Initial release 88 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Bjorn and Dominik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vitefu 2 | 3 | Utilities for building frameworks with Vite. 4 | 5 | ## Usage 6 | 7 | See [src/index.d.ts](./src/index.d.ts). 8 | 9 | ## License 10 | 11 | MIT 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vitefu", 3 | "description": "Utilities for building frameworks with Vite", 4 | "version": "1.1.1", 5 | "license": "MIT", 6 | "type": "module", 7 | "types": "./src/index.d.ts", 8 | "exports": { 9 | ".": { 10 | "import": "./src/index.js", 11 | "require": "./src/index.cjs" 12 | } 13 | }, 14 | "files": [ 15 | "src" 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/svitejs/vitefu.git" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/svitejs/vitefu/issues" 23 | }, 24 | "keywords": [ 25 | "vite", 26 | "framework", 27 | "utilities" 28 | ], 29 | "scripts": { 30 | "test": "uvu tests \".*\\.test\\.js\"" 31 | }, 32 | "peerDependencies": { 33 | "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" 34 | }, 35 | "peerDependenciesMeta": { 36 | "vite": { 37 | "optional": true 38 | } 39 | }, 40 | "devDependencies": { 41 | "@types/node": "^14.18.63", 42 | "@types/pnpapi": "^0.0.5", 43 | "uvu": "^0.5.6", 44 | "vite": "^3.2.11" 45 | }, 46 | "workspaces": [ 47 | "tests/deps/*", 48 | "tests/projects/*", 49 | "tests/projects/workspace/packages/*" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: false 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | devDependencies: 11 | '@types/node': 12 | specifier: ^14.18.63 13 | version: 14.18.63 14 | '@types/pnpapi': 15 | specifier: ^0.0.5 16 | version: 0.0.5 17 | uvu: 18 | specifier: ^0.5.6 19 | version: 0.5.6 20 | vite: 21 | specifier: ^3.2.11 22 | version: 3.2.11(@types/node@14.18.63) 23 | 24 | tests/deps/cjs-js-lib: {} 25 | 26 | tests/deps/esm-js-lib: {} 27 | 28 | tests/deps/framework: {} 29 | 30 | tests/deps/full-direct-framework-lib: 31 | dependencies: 32 | '@vitefu/dep-cjs-js-lib': 33 | specifier: file:../cjs-js-lib 34 | version: file:tests/deps/cjs-js-lib 35 | 36 | tests/deps/full-framework-lib: 37 | dependencies: 38 | '@vitefu/dep-cjs-js-lib': 39 | specifier: file:../cjs-js-lib 40 | version: file:tests/deps/cjs-js-lib 41 | '@vitefu/dep-implicit-entry-cjs-lib': 42 | specifier: file:../implicit-entry-cjs-lib 43 | version: file:tests/deps/implicit-entry-cjs-lib 44 | '@vitefu/dep-no-deep-optimize-lib': 45 | specifier: file:../no-deep-optimize-lib 46 | version: file:tests/deps/no-deep-optimize-lib 47 | '@vitefu/dep-no-entry-lib': 48 | specifier: file:../no-entry-lib 49 | version: file:tests/deps/no-entry-lib 50 | '@vitefu/dep-should-no-external-lib': 51 | specifier: file:../should-no-external-lib 52 | version: '@vitefu/dep-sshould-no-external-lib@file:tests/deps/should-no-external-lib' 53 | 54 | tests/deps/implicit-entry-cjs-lib: {} 55 | 56 | tests/deps/no-deep-optimize-lib: {} 57 | 58 | tests/deps/no-entry-lib: {} 59 | 60 | tests/deps/proxy-framework-lib: 61 | dependencies: 62 | '@vitefu/dep-full-framework-lib': 63 | specifier: file:../full-framework-lib 64 | version: file:tests/deps/full-framework-lib(@vitefu/dep-framework@file:tests/deps/framework) 65 | devDependencies: 66 | '@vitefu/dep-framework': 67 | specifier: file:../framework 68 | version: file:tests/deps/framework 69 | 70 | tests/deps/semi-framework-lib: 71 | dependencies: 72 | '@vitefu/dep-framework': 73 | specifier: file:../framework 74 | version: file:tests/deps/framework 75 | 76 | tests/deps/should-no-external-lib: {} 77 | 78 | tests/projects/basic: 79 | dependencies: 80 | '@vitefu/dep-esm-js-lib': 81 | specifier: file:../../deps/esm-js-lib 82 | version: file:tests/deps/esm-js-lib 83 | '@vitefu/dep-framework': 84 | specifier: file:../../deps/framework 85 | version: file:tests/deps/framework 86 | '@vitefu/dep-full-direct-framework-lib': 87 | specifier: file:../../deps/full-direct-framework-lib 88 | version: file:tests/deps/full-direct-framework-lib(@vitefu/dep-framework@file:tests/deps/framework) 89 | '@vitefu/dep-full-framework-lib': 90 | specifier: file:../../deps/full-framework-lib 91 | version: file:tests/deps/full-framework-lib(@vitefu/dep-framework@file:tests/deps/framework) 92 | '@vitefu/dep-proxy-framework-lib': 93 | specifier: file:../../deps/proxy-framework-lib 94 | version: file:tests/deps/proxy-framework-lib(@vitefu/dep-framework@file:tests/deps/framework) 95 | '@vitefu/dep-semi-framework-lib': 96 | specifier: file:../../deps/semi-framework-lib 97 | version: file:tests/deps/semi-framework-lib 98 | devDependencies: 99 | uvu: 100 | specifier: ^0.5.6 101 | version: 0.5.6 102 | 103 | tests/projects/workspace: 104 | devDependencies: 105 | uvu: 106 | specifier: ^0.5.6 107 | version: 0.5.6 108 | 109 | tests/projects/workspace/packages/workspace-app: 110 | devDependencies: 111 | '@types/node': 112 | specifier: ^14.18.63 113 | version: 14.18.63 114 | '@vitefu/workspace-dep-esm-js-lib': 115 | specifier: ../workspace-esm-js-lib 116 | version: link:../workspace-esm-js-lib 117 | '@vitefu/workspace-dep-full-direct-framework-lib': 118 | specifier: ../workspace-full-direct-framework-lib 119 | version: link:../workspace-full-direct-framework-lib 120 | '@vitefu/workspace-dep-full-framework-lib': 121 | specifier: ../workspace-full-framework-lib 122 | version: link:../workspace-full-framework-lib 123 | '@vitefu/workspace-dep-proxy-framework-lib': 124 | specifier: ../workspace-proxy-framework-lib 125 | version: link:../workspace-proxy-framework-lib 126 | '@vitefu/workspace-dep-semi-framework-lib': 127 | specifier: ../workspace-semi-framework-lib 128 | version: link:../workspace-semi-framework-lib 129 | 130 | tests/projects/workspace/packages/workspace-esm-js-lib: 131 | devDependencies: 132 | '@types/node': 133 | specifier: ^14.18.63 134 | version: 14.18.63 135 | 136 | tests/projects/workspace/packages/workspace-full-direct-framework-lib: 137 | devDependencies: 138 | '@types/node': 139 | specifier: ^14.18.63 140 | version: 14.18.63 141 | '@vitefu/dep-cjs-js-lib': 142 | specifier: file:../../../../deps/cjs-js-lib 143 | version: file:tests/deps/cjs-js-lib 144 | '@vitefu/dep-implicit-entry-cjs-lib': 145 | specifier: file:../../../../deps/implicit-entry-cjs-lib 146 | version: file:tests/deps/implicit-entry-cjs-lib 147 | '@vitefu/dep-no-deep-optimize-lib': 148 | specifier: file:../../../../deps/no-deep-optimize-lib 149 | version: file:tests/deps/no-deep-optimize-lib 150 | '@vitefu/dep-no-entry-lib': 151 | specifier: file:../../../../deps/no-entry-lib 152 | version: file:tests/deps/no-entry-lib 153 | '@vitefu/dep-should-no-external-lib': 154 | specifier: file:../../../../deps/should-no-external-lib 155 | version: '@vitefu/dep-sshould-no-external-lib@file:tests/deps/should-no-external-lib' 156 | 157 | tests/projects/workspace/packages/workspace-full-framework-lib: 158 | devDependencies: 159 | '@types/node': 160 | specifier: ^14.18.63 161 | version: 14.18.63 162 | '@vitefu/dep-cjs-js-lib': 163 | specifier: file:../../../../deps/cjs-js-lib 164 | version: file:tests/deps/cjs-js-lib 165 | '@vitefu/dep-implicit-entry-cjs-lib': 166 | specifier: file:../../../../deps/implicit-entry-cjs-lib 167 | version: file:tests/deps/implicit-entry-cjs-lib 168 | '@vitefu/dep-no-deep-optimize-lib': 169 | specifier: file:../../../../deps/no-deep-optimize-lib 170 | version: file:tests/deps/no-deep-optimize-lib 171 | '@vitefu/dep-no-entry-lib': 172 | specifier: file:../../../../deps/no-entry-lib 173 | version: file:tests/deps/no-entry-lib 174 | '@vitefu/dep-should-no-external-lib': 175 | specifier: file:../../../../deps/should-no-external-lib 176 | version: '@vitefu/dep-sshould-no-external-lib@file:tests/deps/should-no-external-lib' 177 | 178 | tests/projects/workspace/packages/workspace-proxy-framework-lib: 179 | devDependencies: 180 | '@types/node': 181 | specifier: ^14.18.63 182 | version: 14.18.63 183 | '@vitefu/dep-framework': 184 | specifier: file:../../../../deps/framework 185 | version: file:tests/deps/framework 186 | '@vitefu/dep-full-framework-lib': 187 | specifier: file:../../../../deps/full-framework-lib 188 | version: file:tests/deps/full-framework-lib(@vitefu/dep-framework@file:tests/deps/framework) 189 | 190 | tests/projects/workspace/packages/workspace-semi-framework-lib: {} 191 | 192 | packages: 193 | 194 | '@esbuild/android-arm@0.15.18': 195 | resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} 196 | engines: {node: '>=12'} 197 | cpu: [arm] 198 | os: [android] 199 | 200 | '@esbuild/linux-loong64@0.15.18': 201 | resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} 202 | engines: {node: '>=12'} 203 | cpu: [loong64] 204 | os: [linux] 205 | 206 | '@types/node@14.18.63': 207 | resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} 208 | 209 | '@types/pnpapi@0.0.5': 210 | resolution: {integrity: sha512-tjymquatF9seZGE3GcN1barqNqpmyEpqIN0rBKTcoZWwgDC0SgBp5LFqCRJE6YhzXA7TjpXbpTdcL5A8cwyryw==} 211 | 212 | '@vitefu/dep-cjs-js-lib@file:tests/deps/cjs-js-lib': 213 | resolution: {directory: tests/deps/cjs-js-lib, type: directory} 214 | 215 | '@vitefu/dep-esm-js-lib@file:tests/deps/esm-js-lib': 216 | resolution: {directory: tests/deps/esm-js-lib, type: directory} 217 | 218 | '@vitefu/dep-framework@file:tests/deps/framework': 219 | resolution: {directory: tests/deps/framework, type: directory} 220 | 221 | '@vitefu/dep-full-direct-framework-lib@file:tests/deps/full-direct-framework-lib': 222 | resolution: {directory: tests/deps/full-direct-framework-lib, type: directory} 223 | peerDependencies: 224 | '@vitefu/dep-framework': ^0.0.1 225 | 226 | '@vitefu/dep-full-framework-lib@file:tests/deps/full-framework-lib': 227 | resolution: {directory: tests/deps/full-framework-lib, type: directory} 228 | peerDependencies: 229 | '@vitefu/dep-framework': ^0.0.1 230 | 231 | '@vitefu/dep-implicit-entry-cjs-lib@file:tests/deps/implicit-entry-cjs-lib': 232 | resolution: {directory: tests/deps/implicit-entry-cjs-lib, type: directory} 233 | 234 | '@vitefu/dep-no-deep-optimize-lib@file:tests/deps/no-deep-optimize-lib': 235 | resolution: {directory: tests/deps/no-deep-optimize-lib, type: directory} 236 | 237 | '@vitefu/dep-no-entry-lib@file:tests/deps/no-entry-lib': 238 | resolution: {directory: tests/deps/no-entry-lib, type: directory} 239 | 240 | '@vitefu/dep-proxy-framework-lib@file:tests/deps/proxy-framework-lib': 241 | resolution: {directory: tests/deps/proxy-framework-lib, type: directory} 242 | peerDependencies: 243 | '@vitefu/dep-framework': ^0.0.1 244 | 245 | '@vitefu/dep-semi-framework-lib@file:tests/deps/semi-framework-lib': 246 | resolution: {directory: tests/deps/semi-framework-lib, type: directory} 247 | 248 | '@vitefu/dep-sshould-no-external-lib@file:tests/deps/should-no-external-lib': 249 | resolution: {directory: tests/deps/should-no-external-lib, type: directory} 250 | 251 | dequal@2.0.3: 252 | resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} 253 | engines: {node: '>=6'} 254 | 255 | diff@5.2.0: 256 | resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} 257 | engines: {node: '>=0.3.1'} 258 | 259 | esbuild-android-64@0.15.18: 260 | resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} 261 | engines: {node: '>=12'} 262 | cpu: [x64] 263 | os: [android] 264 | 265 | esbuild-android-arm64@0.15.18: 266 | resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} 267 | engines: {node: '>=12'} 268 | cpu: [arm64] 269 | os: [android] 270 | 271 | esbuild-darwin-64@0.15.18: 272 | resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} 273 | engines: {node: '>=12'} 274 | cpu: [x64] 275 | os: [darwin] 276 | 277 | esbuild-darwin-arm64@0.15.18: 278 | resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} 279 | engines: {node: '>=12'} 280 | cpu: [arm64] 281 | os: [darwin] 282 | 283 | esbuild-freebsd-64@0.15.18: 284 | resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} 285 | engines: {node: '>=12'} 286 | cpu: [x64] 287 | os: [freebsd] 288 | 289 | esbuild-freebsd-arm64@0.15.18: 290 | resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} 291 | engines: {node: '>=12'} 292 | cpu: [arm64] 293 | os: [freebsd] 294 | 295 | esbuild-linux-32@0.15.18: 296 | resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} 297 | engines: {node: '>=12'} 298 | cpu: [ia32] 299 | os: [linux] 300 | 301 | esbuild-linux-64@0.15.18: 302 | resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} 303 | engines: {node: '>=12'} 304 | cpu: [x64] 305 | os: [linux] 306 | 307 | esbuild-linux-arm64@0.15.18: 308 | resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} 309 | engines: {node: '>=12'} 310 | cpu: [arm64] 311 | os: [linux] 312 | 313 | esbuild-linux-arm@0.15.18: 314 | resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} 315 | engines: {node: '>=12'} 316 | cpu: [arm] 317 | os: [linux] 318 | 319 | esbuild-linux-mips64le@0.15.18: 320 | resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} 321 | engines: {node: '>=12'} 322 | cpu: [mips64el] 323 | os: [linux] 324 | 325 | esbuild-linux-ppc64le@0.15.18: 326 | resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} 327 | engines: {node: '>=12'} 328 | cpu: [ppc64] 329 | os: [linux] 330 | 331 | esbuild-linux-riscv64@0.15.18: 332 | resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} 333 | engines: {node: '>=12'} 334 | cpu: [riscv64] 335 | os: [linux] 336 | 337 | esbuild-linux-s390x@0.15.18: 338 | resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} 339 | engines: {node: '>=12'} 340 | cpu: [s390x] 341 | os: [linux] 342 | 343 | esbuild-netbsd-64@0.15.18: 344 | resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} 345 | engines: {node: '>=12'} 346 | cpu: [x64] 347 | os: [netbsd] 348 | 349 | esbuild-openbsd-64@0.15.18: 350 | resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} 351 | engines: {node: '>=12'} 352 | cpu: [x64] 353 | os: [openbsd] 354 | 355 | esbuild-sunos-64@0.15.18: 356 | resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} 357 | engines: {node: '>=12'} 358 | cpu: [x64] 359 | os: [sunos] 360 | 361 | esbuild-windows-32@0.15.18: 362 | resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} 363 | engines: {node: '>=12'} 364 | cpu: [ia32] 365 | os: [win32] 366 | 367 | esbuild-windows-64@0.15.18: 368 | resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} 369 | engines: {node: '>=12'} 370 | cpu: [x64] 371 | os: [win32] 372 | 373 | esbuild-windows-arm64@0.15.18: 374 | resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} 375 | engines: {node: '>=12'} 376 | cpu: [arm64] 377 | os: [win32] 378 | 379 | esbuild@0.15.18: 380 | resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} 381 | engines: {node: '>=12'} 382 | hasBin: true 383 | 384 | fsevents@2.3.3: 385 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 386 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 387 | os: [darwin] 388 | 389 | function-bind@1.1.2: 390 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 391 | 392 | hasown@2.0.2: 393 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 394 | engines: {node: '>= 0.4'} 395 | 396 | is-core-module@2.15.1: 397 | resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 398 | engines: {node: '>= 0.4'} 399 | 400 | kleur@4.1.5: 401 | resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} 402 | engines: {node: '>=6'} 403 | 404 | mri@1.2.0: 405 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 406 | engines: {node: '>=4'} 407 | 408 | nanoid@3.3.7: 409 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 410 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 411 | hasBin: true 412 | 413 | path-parse@1.0.7: 414 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 415 | 416 | picocolors@1.1.0: 417 | resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} 418 | 419 | postcss@8.4.47: 420 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} 421 | engines: {node: ^10 || ^12 || >=14} 422 | 423 | resolve@1.22.8: 424 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 425 | hasBin: true 426 | 427 | rollup@2.79.2: 428 | resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} 429 | engines: {node: '>=10.0.0'} 430 | hasBin: true 431 | 432 | sade@1.8.1: 433 | resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} 434 | engines: {node: '>=6'} 435 | 436 | source-map-js@1.2.1: 437 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 438 | engines: {node: '>=0.10.0'} 439 | 440 | supports-preserve-symlinks-flag@1.0.0: 441 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 442 | engines: {node: '>= 0.4'} 443 | 444 | uvu@0.5.6: 445 | resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} 446 | engines: {node: '>=8'} 447 | hasBin: true 448 | 449 | vite@3.2.11: 450 | resolution: {integrity: sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==} 451 | engines: {node: ^14.18.0 || >=16.0.0} 452 | hasBin: true 453 | peerDependencies: 454 | '@types/node': '>= 14' 455 | less: '*' 456 | sass: '*' 457 | stylus: '*' 458 | sugarss: '*' 459 | terser: ^5.4.0 460 | peerDependenciesMeta: 461 | '@types/node': 462 | optional: true 463 | less: 464 | optional: true 465 | sass: 466 | optional: true 467 | stylus: 468 | optional: true 469 | sugarss: 470 | optional: true 471 | terser: 472 | optional: true 473 | 474 | snapshots: 475 | 476 | '@esbuild/android-arm@0.15.18': 477 | optional: true 478 | 479 | '@esbuild/linux-loong64@0.15.18': 480 | optional: true 481 | 482 | '@types/node@14.18.63': {} 483 | 484 | '@types/pnpapi@0.0.5': {} 485 | 486 | '@vitefu/dep-cjs-js-lib@file:tests/deps/cjs-js-lib': {} 487 | 488 | '@vitefu/dep-esm-js-lib@file:tests/deps/esm-js-lib': {} 489 | 490 | '@vitefu/dep-framework@file:tests/deps/framework': {} 491 | 492 | '@vitefu/dep-full-direct-framework-lib@file:tests/deps/full-direct-framework-lib(@vitefu/dep-framework@file:tests/deps/framework)': 493 | dependencies: 494 | '@vitefu/dep-cjs-js-lib': file:tests/deps/cjs-js-lib 495 | '@vitefu/dep-framework': file:tests/deps/framework 496 | 497 | '@vitefu/dep-full-framework-lib@file:tests/deps/full-framework-lib(@vitefu/dep-framework@file:tests/deps/framework)': 498 | dependencies: 499 | '@vitefu/dep-cjs-js-lib': file:tests/deps/cjs-js-lib 500 | '@vitefu/dep-framework': file:tests/deps/framework 501 | '@vitefu/dep-implicit-entry-cjs-lib': file:tests/deps/implicit-entry-cjs-lib 502 | '@vitefu/dep-no-deep-optimize-lib': file:tests/deps/no-deep-optimize-lib 503 | '@vitefu/dep-no-entry-lib': file:tests/deps/no-entry-lib 504 | '@vitefu/dep-should-no-external-lib': '@vitefu/dep-sshould-no-external-lib@file:tests/deps/should-no-external-lib' 505 | 506 | '@vitefu/dep-implicit-entry-cjs-lib@file:tests/deps/implicit-entry-cjs-lib': {} 507 | 508 | '@vitefu/dep-no-deep-optimize-lib@file:tests/deps/no-deep-optimize-lib': {} 509 | 510 | '@vitefu/dep-no-entry-lib@file:tests/deps/no-entry-lib': {} 511 | 512 | '@vitefu/dep-proxy-framework-lib@file:tests/deps/proxy-framework-lib(@vitefu/dep-framework@file:tests/deps/framework)': 513 | dependencies: 514 | '@vitefu/dep-framework': file:tests/deps/framework 515 | '@vitefu/dep-full-framework-lib': file:tests/deps/full-framework-lib(@vitefu/dep-framework@file:tests/deps/framework) 516 | 517 | '@vitefu/dep-semi-framework-lib@file:tests/deps/semi-framework-lib': 518 | dependencies: 519 | '@vitefu/dep-framework': file:tests/deps/framework 520 | 521 | '@vitefu/dep-sshould-no-external-lib@file:tests/deps/should-no-external-lib': {} 522 | 523 | dequal@2.0.3: {} 524 | 525 | diff@5.2.0: {} 526 | 527 | esbuild-android-64@0.15.18: 528 | optional: true 529 | 530 | esbuild-android-arm64@0.15.18: 531 | optional: true 532 | 533 | esbuild-darwin-64@0.15.18: 534 | optional: true 535 | 536 | esbuild-darwin-arm64@0.15.18: 537 | optional: true 538 | 539 | esbuild-freebsd-64@0.15.18: 540 | optional: true 541 | 542 | esbuild-freebsd-arm64@0.15.18: 543 | optional: true 544 | 545 | esbuild-linux-32@0.15.18: 546 | optional: true 547 | 548 | esbuild-linux-64@0.15.18: 549 | optional: true 550 | 551 | esbuild-linux-arm64@0.15.18: 552 | optional: true 553 | 554 | esbuild-linux-arm@0.15.18: 555 | optional: true 556 | 557 | esbuild-linux-mips64le@0.15.18: 558 | optional: true 559 | 560 | esbuild-linux-ppc64le@0.15.18: 561 | optional: true 562 | 563 | esbuild-linux-riscv64@0.15.18: 564 | optional: true 565 | 566 | esbuild-linux-s390x@0.15.18: 567 | optional: true 568 | 569 | esbuild-netbsd-64@0.15.18: 570 | optional: true 571 | 572 | esbuild-openbsd-64@0.15.18: 573 | optional: true 574 | 575 | esbuild-sunos-64@0.15.18: 576 | optional: true 577 | 578 | esbuild-windows-32@0.15.18: 579 | optional: true 580 | 581 | esbuild-windows-64@0.15.18: 582 | optional: true 583 | 584 | esbuild-windows-arm64@0.15.18: 585 | optional: true 586 | 587 | esbuild@0.15.18: 588 | optionalDependencies: 589 | '@esbuild/android-arm': 0.15.18 590 | '@esbuild/linux-loong64': 0.15.18 591 | esbuild-android-64: 0.15.18 592 | esbuild-android-arm64: 0.15.18 593 | esbuild-darwin-64: 0.15.18 594 | esbuild-darwin-arm64: 0.15.18 595 | esbuild-freebsd-64: 0.15.18 596 | esbuild-freebsd-arm64: 0.15.18 597 | esbuild-linux-32: 0.15.18 598 | esbuild-linux-64: 0.15.18 599 | esbuild-linux-arm: 0.15.18 600 | esbuild-linux-arm64: 0.15.18 601 | esbuild-linux-mips64le: 0.15.18 602 | esbuild-linux-ppc64le: 0.15.18 603 | esbuild-linux-riscv64: 0.15.18 604 | esbuild-linux-s390x: 0.15.18 605 | esbuild-netbsd-64: 0.15.18 606 | esbuild-openbsd-64: 0.15.18 607 | esbuild-sunos-64: 0.15.18 608 | esbuild-windows-32: 0.15.18 609 | esbuild-windows-64: 0.15.18 610 | esbuild-windows-arm64: 0.15.18 611 | 612 | fsevents@2.3.3: 613 | optional: true 614 | 615 | function-bind@1.1.2: {} 616 | 617 | hasown@2.0.2: 618 | dependencies: 619 | function-bind: 1.1.2 620 | 621 | is-core-module@2.15.1: 622 | dependencies: 623 | hasown: 2.0.2 624 | 625 | kleur@4.1.5: {} 626 | 627 | mri@1.2.0: {} 628 | 629 | nanoid@3.3.7: {} 630 | 631 | path-parse@1.0.7: {} 632 | 633 | picocolors@1.1.0: {} 634 | 635 | postcss@8.4.47: 636 | dependencies: 637 | nanoid: 3.3.7 638 | picocolors: 1.1.0 639 | source-map-js: 1.2.1 640 | 641 | resolve@1.22.8: 642 | dependencies: 643 | is-core-module: 2.15.1 644 | path-parse: 1.0.7 645 | supports-preserve-symlinks-flag: 1.0.0 646 | 647 | rollup@2.79.2: 648 | optionalDependencies: 649 | fsevents: 2.3.3 650 | 651 | sade@1.8.1: 652 | dependencies: 653 | mri: 1.2.0 654 | 655 | source-map-js@1.2.1: {} 656 | 657 | supports-preserve-symlinks-flag@1.0.0: {} 658 | 659 | uvu@0.5.6: 660 | dependencies: 661 | dequal: 2.0.3 662 | diff: 5.2.0 663 | kleur: 4.1.5 664 | sade: 1.8.1 665 | 666 | vite@3.2.11(@types/node@14.18.63): 667 | dependencies: 668 | esbuild: 0.15.18 669 | postcss: 8.4.47 670 | resolve: 1.22.8 671 | rollup: 2.79.2 672 | optionalDependencies: 673 | '@types/node': 14.18.63 674 | fsevents: 2.3.3 675 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - tests/deps/* 3 | - tests/projects/* 4 | - tests/projects/workspace/packages/* 5 | -------------------------------------------------------------------------------- /src/index.cjs: -------------------------------------------------------------------------------- 1 | // CJS -> ESM proxy file 2 | // Reference: https://github.com/vitejs/vite/blob/9f268dad2e82c0f1276b1098c0a28f1cf245aa50/packages/vite/index.cjs 3 | 4 | module.exports = require('./sync.cjs') 5 | 6 | // redirect async functions to ESM 7 | const asyncFunctions = [ 8 | 'crawlFrameworkPkgs', 9 | 'findDepPkgJsonPath', 10 | 'findClosestPkgJsonPath', 11 | 'pkgNeedsOptimization' 12 | ] 13 | 14 | for (const fn of asyncFunctions) { 15 | module.exports[fn] = function () { 16 | return import('./index.js').then((mod) => mod[fn].apply(this, arguments)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/index.d.cts: -------------------------------------------------------------------------------- 1 | // CJS types like `index.d.ts` but dumbed down and doesn't import from `vite`. Thanks TypeScript. 2 | 3 | export interface CrawlFrameworkPkgsOptions { 4 | root: string 5 | isBuild: boolean 6 | workspaceRoot?: string 7 | viteUserConfig?: any 8 | isFrameworkPkgByJson?: (pkgJson: Record) => boolean 9 | isFrameworkPkgByName?: (pkgName: string) => boolean | undefined 10 | isSemiFrameworkPkgByJson?: (pkgJson: Record) => boolean 11 | isSemiFrameworkPkgByName?: (pkgName: string) => boolean | undefined 12 | } 13 | 14 | export interface CrawlFrameworkPkgsResult { 15 | optimizeDeps: { 16 | include: string[] 17 | exclude: string[] 18 | } 19 | ssr: { 20 | noExternal: string[] 21 | external: string[] 22 | } 23 | } 24 | 25 | export declare function crawlFrameworkPkgs( 26 | options: CrawlFrameworkPkgsOptions 27 | ): Promise 28 | 29 | export declare function findDepPkgJsonPath( 30 | dep: string, 31 | parent: string 32 | ): Promise 33 | 34 | export declare function findClosestPkgJsonPath( 35 | dir: string, 36 | predicate?: (pkgJsonPath: string) => boolean | Promise 37 | ): Promise 38 | 39 | export declare function pkgNeedsOptimization( 40 | pkgJson: Record, 41 | pkgJsonPath: string 42 | ): Promise 43 | 44 | export declare function isDepExcluded( 45 | dep: string, 46 | optimizeDepsExclude: any 47 | ): boolean 48 | 49 | export declare function isDepIncluded( 50 | dep: string, 51 | optimizeDepsInclude: any 52 | ): boolean 53 | 54 | export declare function isDepNoExternaled( 55 | dep: string, 56 | ssrNoExternal: any 57 | ): boolean 58 | 59 | export declare function isDepExternaled(dep: string, ssrExternal: any): boolean 60 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | import type { DepOptimizationOptions, SSROptions, UserConfig } from 'vite' 2 | 3 | export interface CrawlFrameworkPkgsOptions { 4 | /** 5 | * Path to the root of the project that contains the `package.json` 6 | */ 7 | root: string 8 | /** 9 | * Whether we're currently in a Vite build 10 | */ 11 | isBuild: boolean 12 | 13 | /** 14 | * Path to workspace root of the project 15 | * 16 | * setting this enables crawling devDependencies of private packages inside the workspace 17 | * you can use `import {searchForWorkspaceRoot} from 'vite'` to find it. 18 | */ 19 | workspaceRoot?: string 20 | 21 | /** 22 | * Optional. If a Vite user config is passed, the output Vite config will respect the 23 | * set `optimizeDeps` and `ssr` options so it doesn't override it 24 | */ 25 | viteUserConfig?: UserConfig 26 | /** 27 | * Whether this is a framework package by checking it's `package.json`. 28 | * A framework package is one that exports special files that can't be processed 29 | * by esbuild natively. For example, exporting `.framework` files. 30 | * 31 | * @example 32 | * ```ts 33 | * return pkgJson.keywords?.includes('my-framework') 34 | * ``` 35 | */ 36 | isFrameworkPkgByJson?: (pkgJson: Record) => boolean 37 | /** 38 | * Whether this is a framework package by checking it's name. This is 39 | * usually used as a fast path. Return `true` or `false` if you know 100% 40 | * if it's a framework package or not. Return `undefined` to fallback to 41 | * `isFrameworkPkgByJson`. 42 | * 43 | * @example 44 | * ```ts 45 | * return SPECIAL_PACKAGES.includes(pkgName) || undefined 46 | * ``` 47 | */ 48 | isFrameworkPkgByName?: (pkgName: string) => boolean | undefined 49 | /** 50 | * Whether this is a semi-framework package by checking it's `package.json`. 51 | * A semi-framework package is one that **doesn't** export special files but 52 | * consumes other APIs of the framework. For example, it only does 53 | * `import { debounce } from 'my-framework/utils'`. 54 | * 55 | * @example 56 | * ```ts 57 | * return Object.keys(pkgJson.dependencies || {}).includes('my-framework') 58 | * ``` 59 | */ 60 | isSemiFrameworkPkgByJson?: (pkgJson: Record) => boolean 61 | /** 62 | * Whether this is a semi-framework package by checking it's name. This is 63 | * usually used as a fast path. Return `true` or `false` if you know 100% 64 | * if it's a semi-framework package or not. Return `undefined` to fallback to 65 | * `isSemiFrameworkPkgByJson`. 66 | * 67 | * @example 68 | * ```ts 69 | * return SPECIAL_SEMI_PACKAGES.includes(pkgName) || undefined 70 | * ``` 71 | */ 72 | isSemiFrameworkPkgByName?: (pkgName: string) => boolean | undefined 73 | } 74 | 75 | export interface CrawlFrameworkPkgsResult { 76 | optimizeDeps: { 77 | include: string[] 78 | exclude: string[] 79 | } 80 | ssr: { 81 | noExternal: string[] 82 | external: string[] 83 | } 84 | } 85 | 86 | /** 87 | * Crawls for framework packages starting from `/package.json` to build 88 | * out a partial Vite config. See the source code for details of how this is built. 89 | */ 90 | export declare function crawlFrameworkPkgs( 91 | options: CrawlFrameworkPkgsOptions 92 | ): Promise 93 | 94 | /** 95 | * Find the `package.json` of a dep, starting from the parent, e.g. `process.cwd()`. 96 | * A simplified implementation of https://nodejs.org/api/esm.html#resolver-algorithm-specification 97 | * (PACKAGE_RESOLVE) for `package.json` specifically. 98 | */ 99 | export declare function findDepPkgJsonPath( 100 | dep: string, 101 | parent: string, 102 | ): Promise 103 | 104 | /** 105 | * Find the closest `package.json` path by walking `dir` upwards. 106 | * 107 | * Pass a function to `predicate` to check if the current `package.json` is the 108 | * one you're looking for. For example, finding `package.json` that has the 109 | * `name` field only. Throwing inside the `predicate` is safe and acts the same 110 | * as returning false. 111 | */ 112 | export declare function findClosestPkgJsonPath( 113 | dir: string, 114 | predicate?: (pkgJsonPath: string) => boolean | Promise 115 | ): Promise 116 | 117 | /** 118 | * Check if a package needs to be optimized by Vite, aka if it's CJS-only 119 | */ 120 | export declare function pkgNeedsOptimization( 121 | pkgJson: Record, 122 | pkgJsonPath: string 123 | ): Promise 124 | 125 | /** 126 | * Check if a dependency is part of an existing `optimizeDeps.exclude` config 127 | * @param dep Dependency to be included 128 | * @param optimizeDepsExclude Existing `optimizeDeps.exclude` config 129 | * @example 130 | * ```ts 131 | * optimizeDeps: { 132 | * include: includesToAdd.filter((dep) => !isDepExcluded(dep, existingExclude)) 133 | * } 134 | * ``` 135 | */ 136 | export declare function isDepExcluded( 137 | dep: string, 138 | optimizeDepsExclude: NonNullable 139 | ): boolean 140 | 141 | /** 142 | * Check if a dependency is part of an existing `optimizeDeps.include` config 143 | * @param dep Dependency to be excluded 144 | * @param optimizeDepsInclude Existing `optimizeDeps.include` config 145 | * @example 146 | * ```ts 147 | * optimizeDeps: { 148 | * exclude: excludesToAdd.filter((dep) => !isDepIncluded(dep, existingInclude)) 149 | * } 150 | * ``` 151 | */ 152 | export declare function isDepIncluded( 153 | dep: string, 154 | optimizeDepsInclude: NonNullable 155 | ): boolean 156 | 157 | /** 158 | * Check if a dependency is part of an existing `ssr.noExternal` config 159 | * @param dep Dependency to be excluded 160 | * @param ssrNoExternal Existing `ssr.noExternal` config 161 | * @example 162 | * ```ts 163 | * ssr: { 164 | * external: externalsToAdd.filter((dep) => !isDepNoExternal(dep, existingNoExternal)) 165 | * } 166 | * ``` 167 | */ 168 | export declare function isDepNoExternaled( 169 | dep: string, 170 | ssrNoExternal: NonNullable 171 | ): boolean 172 | 173 | /** 174 | * Check if a dependency is part of an existing `ssr.external` config 175 | * @param dep Dependency to be noExternaled 176 | * @param ssrExternal Existing `ssr.external` config 177 | * @example 178 | * ```ts 179 | * ssr: { 180 | * noExternal: noExternalsToAdd.filter((dep) => !isDepExternal(dep, existingExternal)) 181 | * } 182 | * ``` 183 | */ 184 | export declare function isDepExternaled( 185 | dep: string, 186 | ssrExternal: NonNullable 187 | ): boolean 188 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises' 2 | import fsSync from 'node:fs' 3 | import { createRequire } from 'node:module' 4 | import path from 'node:path' 5 | import { 6 | isDepIncluded, 7 | isDepExcluded, 8 | isDepNoExternaled, 9 | isDepExternaled 10 | } from './sync.cjs' 11 | 12 | /** @type {import('pnpapi')} */ 13 | let pnp 14 | 15 | 16 | /** @type {Array<{ name: string; reference: string; }>} */ 17 | let pnpWorkspaceLocators; 18 | 19 | if (process.versions.pnp) { 20 | try { 21 | pnp = createRequire(import.meta.url)('pnpapi') 22 | // returns a set of physical locators https://yarnpkg.com/advanced/pnpapi#getdependencytreeroots 23 | // @ts-expect-error unfortunately doesn't exist in the `@types` package 24 | pnpWorkspaceLocators = pnp.getDependencyTreeRoots() 25 | } catch {} 26 | } 27 | 28 | export { isDepIncluded, isDepExcluded, isDepNoExternaled, isDepExternaled } 29 | 30 | /** @type {import('./index.d.ts').crawlFrameworkPkgs} */ 31 | export async function crawlFrameworkPkgs(options) { 32 | const pkgJsonPath = await findClosestPkgJsonPath(options.root) 33 | if (!pkgJsonPath) { 34 | // don't throw as package.json is not required 35 | return { 36 | optimizeDeps: { include: [], exclude: [] }, 37 | ssr: { noExternal: [], external: [] } 38 | } 39 | } 40 | const pkgJson = await readJson(pkgJsonPath).catch((e) => { 41 | throw new Error(`Unable to read ${pkgJsonPath}`, { cause: e }) 42 | }) 43 | 44 | /** @type {string[]} */ 45 | let optimizeDepsInclude = [] 46 | /** @type {string[]} */ 47 | let optimizeDepsExclude = [] 48 | /** @type {string[]} */ 49 | let ssrNoExternal = [] 50 | /** @type {string[]} */ 51 | let ssrExternal = [] 52 | 53 | await crawl(pkgJsonPath, pkgJson) 54 | 55 | // respect vite user config 56 | if (options.viteUserConfig) { 57 | // remove includes that are explicitly excluded in optimizeDeps 58 | const _optimizeDepsExclude = options.viteUserConfig?.optimizeDeps?.exclude 59 | if (_optimizeDepsExclude) { 60 | optimizeDepsInclude = optimizeDepsInclude.filter( 61 | (dep) => !isDepExcluded(dep, _optimizeDepsExclude) 62 | ) 63 | } 64 | // remove excludes that are explicitly included in optimizeDeps 65 | const _optimizeDepsInclude = options.viteUserConfig?.optimizeDeps?.include 66 | if (_optimizeDepsInclude) { 67 | optimizeDepsExclude = optimizeDepsExclude.filter( 68 | (dep) => !isDepIncluded(dep, _optimizeDepsInclude) 69 | ) 70 | } 71 | // remove noExternals that are explicitly externalized 72 | const _ssrExternal = options.viteUserConfig?.ssr?.external 73 | if (_ssrExternal) { 74 | ssrNoExternal = ssrNoExternal.filter( 75 | (dep) => !isDepExternaled(dep, _ssrExternal) 76 | ) 77 | } 78 | // remove externals that are explicitly noExternal 79 | const _ssrNoExternal = options.viteUserConfig?.ssr?.noExternal 80 | if (_ssrNoExternal) { 81 | ssrExternal = ssrExternal.filter( 82 | (dep) => !isDepNoExternaled(dep, _ssrNoExternal) 83 | ) 84 | } 85 | } 86 | 87 | return { 88 | optimizeDeps: { 89 | include: optimizeDepsInclude, 90 | exclude: optimizeDepsExclude 91 | }, 92 | ssr: { 93 | noExternal: ssrNoExternal, 94 | external: ssrExternal 95 | } 96 | } 97 | 98 | /** 99 | * crawl the package.json dependencies for framework packages. rules: 100 | * 1. a framework package should be `optimizeDeps.exclude` and `ssr.noExternal`. 101 | * 2. the deps of the framework package should be `optimizeDeps.include` and `ssr.external` 102 | * unless the dep is also a framework package, in which case do no1 & no2 recursively. 103 | * 3. any non-framework packages that aren't imported by a framework package can be skipped entirely. 104 | * 4. a semi-framework package is like a framework package, except it isn't `optimizeDeps.exclude`, 105 | * but only applies `ssr.noExternal`. 106 | * @param {string} pkgJsonPath 107 | * @param {Record} pkgJson 108 | * @param {string[]} [parentDepNames] 109 | */ 110 | async function crawl(pkgJsonPath, pkgJson, parentDepNames = []) { 111 | const isRoot = parentDepNames.length === 0 112 | const crawlDevDependencies = isRoot || isPrivateWorkspacePackage(pkgJsonPath,pkgJson,options.workspaceRoot) 113 | /** @type {string[]} */ 114 | let deps = [ 115 | ...Object.keys(pkgJson.dependencies || {}), 116 | ...((crawlDevDependencies) ? Object.keys(pkgJson.devDependencies || {}) : []) 117 | ] 118 | 119 | deps = deps.filter((dep) => { 120 | // skip circular deps 121 | if (parentDepNames.includes(dep)) { 122 | return false 123 | } 124 | 125 | const isFrameworkPkg = options.isFrameworkPkgByName?.(dep) 126 | const isSemiFrameworkPkg = options.isSemiFrameworkPkgByName?.(dep) 127 | if (isFrameworkPkg) { 128 | // framework packages should be excluded from optimization as esbuild can't handle them. 129 | // otherwise it'll cause https://github.com/vitejs/vite/issues/3910 130 | optimizeDepsExclude.push(dep) 131 | // framework packages should be noExternal so that they go through vite's transformation 132 | // pipeline, since nodejs can't support them. 133 | ssrNoExternal.push(dep) 134 | } else if (isSemiFrameworkPkg) { 135 | // semi-framework packages should do the same except for optimization exclude as they 136 | // aren't needed to work (they don't contain raw framework components) 137 | ssrNoExternal.push(dep) 138 | } 139 | 140 | // only those that are explictly false can skip crawling since we don't need to do anything 141 | // special for them 142 | if (isFrameworkPkg === false || isSemiFrameworkPkg === false) { 143 | return false 144 | } 145 | // if `true`, we need to crawl the nested deps to deep include and ssr externalize them in dev. 146 | // if `undefined`, it's the same as "i don't know". we need to crawl and find the package.json 147 | // to find out. 148 | else { 149 | return true 150 | } 151 | }) 152 | 153 | const promises = deps.map(async (dep) => { 154 | const depPkgJsonPath = await _findDepPkgJsonPath(dep, pkgJsonPath, !!options.workspaceRoot) 155 | if (!depPkgJsonPath) return 156 | const depPkgJson = await readJson(depPkgJsonPath).catch(() => {}) 157 | if (!depPkgJson) return 158 | 159 | // fast path if this dep is already a framework dep based on the filter condition above 160 | const cachedIsFrameworkPkg = ssrNoExternal.includes(dep) 161 | if (cachedIsFrameworkPkg) { 162 | return crawl(depPkgJsonPath, depPkgJson, parentDepNames.concat(dep)) 163 | } 164 | 165 | // check if this dep is a framework dep, if so, track and crawl it 166 | const isFrameworkPkg = options.isFrameworkPkgByJson?.(depPkgJson) 167 | const isSemiFrameworkPkg = options.isSemiFrameworkPkgByJson?.(depPkgJson) 168 | if (isFrameworkPkg || isSemiFrameworkPkg) { 169 | // see explanation in filter condition above 170 | if (isFrameworkPkg) { 171 | optimizeDepsExclude.push(dep) 172 | ssrNoExternal.push(dep) 173 | } else if (isSemiFrameworkPkg) { 174 | ssrNoExternal.push(dep) 175 | } 176 | return crawl(depPkgJsonPath, depPkgJson, parentDepNames.concat(dep)) 177 | } 178 | 179 | // if we're crawling in a non-root state, the parent is 100% a framework package 180 | // because of the above if block. in this case, if it's dep of a non-framework 181 | // package, handle special cases for them. 182 | if (!isRoot) { 183 | // deep include it if it's a CJS package, so it becomes ESM and vite is happy. 184 | if (await pkgNeedsOptimization(depPkgJson, depPkgJsonPath)) { 185 | optimizeDepsInclude.push(parentDepNames.concat(dep).join(' > ')) 186 | } 187 | // also externalize it in dev so it doesn't trip vite's SSR transformation. 188 | // we do in dev only as build cannot access deep external packages in strict 189 | // dependency installations, such as pnpm. 190 | if (!options.isBuild && !ssrExternal.includes(dep)) { 191 | ssrExternal.push(dep) 192 | } 193 | } 194 | }) 195 | 196 | await Promise.all(promises) 197 | } 198 | } 199 | /** @type {import('./index.d.ts').findDepPkgJsonPath} */ 200 | export async function findDepPkgJsonPath(dep, parent) { 201 | return _findDepPkgJsonPath(dep, parent, false); 202 | } 203 | 204 | /** 205 | * internal implementation to avoid exposing the usePnpWorkspaceLocators flag 206 | * 207 | * @param {string} dep 208 | * @param {string} parent 209 | * @param {boolean} usePnpWorkspaceLocators 210 | * @returns {Promise} 211 | * @private 212 | */ 213 | async function _findDepPkgJsonPath(dep, parent, usePnpWorkspaceLocators) { 214 | if (pnp) { 215 | if(usePnpWorkspaceLocators) { 216 | try { 217 | // if we're in a workspace and the dep is a workspace dep, 218 | // then we'll try to resolve to it's real location 219 | const locator = pnpWorkspaceLocators.find((root) => root.name === dep) 220 | if (locator) { 221 | const pkgPath = pnp.getPackageInformation(locator).packageLocation 222 | return path.resolve(pkgPath, 'package.json') 223 | } 224 | } catch {} 225 | } 226 | try { 227 | const depRoot = pnp.resolveToUnqualified(dep, parent) 228 | if (!depRoot) return undefined 229 | return path.join(depRoot, 'package.json') 230 | } catch { 231 | return undefined 232 | } 233 | } 234 | 235 | let root = parent 236 | while (root) { 237 | const pkg = path.join(root, 'node_modules', dep, 'package.json') 238 | try { 239 | await fs.access(pkg) 240 | // use 'node:fs' version to match 'vite:resolve' and avoid realpath.native quirk 241 | // https://github.com/sveltejs/vite-plugin-svelte/issues/525#issuecomment-1355551264 242 | return fsSync.realpathSync(pkg) 243 | } catch {} 244 | const nextRoot = path.dirname(root) 245 | if (nextRoot === root) break 246 | root = nextRoot 247 | } 248 | return undefined 249 | } 250 | 251 | /** @type {import('./index.d.ts').findClosestPkgJsonPath} */ 252 | export async function findClosestPkgJsonPath(dir, predicate = undefined) { 253 | if (dir.endsWith('package.json')) { 254 | dir = path.dirname(dir) 255 | } 256 | while (dir) { 257 | const pkg = path.join(dir, 'package.json') 258 | try { 259 | const stat = await fs.stat(pkg) 260 | if (stat.isFile() && (!predicate || (await predicate(pkg)))) { 261 | return pkg 262 | } 263 | } catch {} 264 | const nextDir = path.dirname(dir) 265 | if (nextDir === dir) break 266 | dir = nextDir 267 | } 268 | return undefined 269 | } 270 | 271 | /** @type {import('./index.d.ts').pkgNeedsOptimization} */ 272 | export async function pkgNeedsOptimization(pkgJson, pkgJsonPath) { 273 | // only optimize if is cjs, using the below as heuristic 274 | // see https://github.com/sveltejs/vite-plugin-svelte/issues/162 275 | if (pkgJson.module || pkgJson.exports) return false 276 | // if have main, ensure entry is js so vite can prebundle it 277 | // see https://github.com/sveltejs/vite-plugin-svelte/issues/233 278 | if (pkgJson.main) { 279 | const entryExt = path.extname(pkgJson.main) 280 | return !entryExt || entryExt === '.js' || entryExt === '.cjs' 281 | } 282 | // check if has implicit index.js entrypoint to prebundle 283 | // see https://github.com/sveltejs/vite-plugin-svelte/issues/281 284 | // see https://github.com/solidjs/vite-plugin-solid/issues/70#issuecomment-1306488154 285 | try { 286 | await fs.access(path.join(path.dirname(pkgJsonPath), 'index.js')) 287 | return true 288 | } catch { 289 | return false 290 | } 291 | } 292 | 293 | /** 294 | * @param {string} findDepPkgJsonPath 295 | * @returns {Promise>} 296 | */ 297 | async function readJson(findDepPkgJsonPath) { 298 | return JSON.parse(await fs.readFile(findDepPkgJsonPath, 'utf8')) 299 | } 300 | 301 | /** 302 | * 303 | * @param {string} pkgJsonPath 304 | * @param {Record} pkgJson 305 | * @param {string} [workspaceRoot] 306 | * @returns {boolean} 307 | */ 308 | function isPrivateWorkspacePackage(pkgJsonPath,pkgJson,workspaceRoot = undefined) { 309 | return !!( 310 | workspaceRoot && 311 | pkgJson.private && 312 | !pkgJsonPath.match(/[/\\]node_modules[/\\]/) && 313 | !path.relative(workspaceRoot,pkgJsonPath).startsWith('..') 314 | ) 315 | } 316 | -------------------------------------------------------------------------------- /src/sync.cjs: -------------------------------------------------------------------------------- 1 | // contains synchronous API only so it can be exported as CJS and ESM 2 | 3 | /** @type {import('./index.d.ts').isDepIncluded} */ 4 | function isDepIncluded(dep, optimizeDepsInclude) { 5 | return optimizeDepsInclude.some((id) => parseIncludeStr(id) === dep) 6 | } 7 | 8 | /** @type {import('./index.d.ts').isDepExcluded} */ 9 | function isDepExcluded(dep, optimizeDepsExclude) { 10 | dep = parseIncludeStr(dep) 11 | return optimizeDepsExclude.some( 12 | (id) => id === dep || dep.startsWith(`${id}/`) 13 | ) 14 | } 15 | 16 | /** @type {import('./index.d.ts').isDepNoExternaled} */ 17 | function isDepNoExternaled(dep, ssrNoExternal) { 18 | if (ssrNoExternal === true) { 19 | return true 20 | } else { 21 | return isMatch(dep, ssrNoExternal) 22 | } 23 | } 24 | 25 | /** @type {import('./index.d.ts').isDepExternaled} */ 26 | function isDepExternaled(dep, ssrExternal) { 27 | // If `ssrExternal` is `true`, it just means that all linked 28 | // dependencies should also be externalized by default. It doesn't 29 | // mean that a dependency is being explicitly externalized. So we 30 | // return `false` in this case. 31 | // @ts-expect-error can be true in Vite 6 32 | if (ssrExternal === true) { 33 | return false 34 | } else { 35 | return ssrExternal.includes(dep) 36 | } 37 | } 38 | 39 | /** 40 | * @param {string} raw could be "foo" or "foo > bar" etc 41 | */ 42 | function parseIncludeStr(raw) { 43 | const lastArrow = raw.lastIndexOf('>') 44 | return lastArrow === -1 ? raw : raw.slice(lastArrow + 1).trim() 45 | } 46 | 47 | /** 48 | * @param {string} target 49 | * @param {string | RegExp | (string | RegExp)[]} pattern 50 | */ 51 | function isMatch(target, pattern) { 52 | if (Array.isArray(pattern)) { 53 | return pattern.some((p) => isMatch(target, p)) 54 | } else if (typeof pattern === 'string') { 55 | return target === pattern 56 | } else if (pattern instanceof RegExp) { 57 | return pattern.test(target) 58 | } 59 | } 60 | 61 | module.exports = { 62 | isDepIncluded, 63 | isDepExcluded, 64 | isDepNoExternaled, 65 | isDepExternaled 66 | } 67 | -------------------------------------------------------------------------------- /tests/deps/cjs-js-lib/index.js: -------------------------------------------------------------------------------- 1 | module.exports.plus = function plus(a, b) { 2 | return a + b 3 | } 4 | -------------------------------------------------------------------------------- /tests/deps/cjs-js-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-cjs-js-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "main": "./index.js" 6 | } 7 | -------------------------------------------------------------------------------- /tests/deps/esm-js-lib/index.js: -------------------------------------------------------------------------------- 1 | export function plus(a, b) { 2 | return a + b 3 | } 4 | -------------------------------------------------------------------------------- /tests/deps/esm-js-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-esm-js-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "import": "./index.js" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/deps/framework/index.js: -------------------------------------------------------------------------------- 1 | export function compile(code) { 2 | return code.replace('', '').replace('', '') 3 | } 4 | -------------------------------------------------------------------------------- /tests/deps/framework/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-framework", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "import": "./index.js" 9 | }, 10 | "./utils": { 11 | "import": "./utils.js" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/deps/framework/utils.js: -------------------------------------------------------------------------------- 1 | export function trim(str) { 2 | return str.trim() 3 | } 4 | -------------------------------------------------------------------------------- /tests/deps/full-direct-framework-lib/index.framework: -------------------------------------------------------------------------------- 1 | 2 | export default function renderComponent() { 3 | return 'Hello World' 4 | } 5 | 6 | -------------------------------------------------------------------------------- /tests/deps/full-direct-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-full-direct-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "framework": "./index.js" 9 | }, 10 | "./package.json": "./package.json" 11 | }, 12 | "dependencies": { 13 | "@vitefu/dep-cjs-js-lib": "file:../cjs-js-lib" 14 | }, 15 | "peerDependencies": { 16 | "@vitefu/dep-framework": "^0.0.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/deps/full-framework-lib/index.framework: -------------------------------------------------------------------------------- 1 | 2 | export default function renderComponent() { 3 | return 'Hello World' 4 | } 5 | 6 | -------------------------------------------------------------------------------- /tests/deps/full-framework-lib/index.js: -------------------------------------------------------------------------------- 1 | export { default as default } from './index.framework' 2 | -------------------------------------------------------------------------------- /tests/deps/full-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-full-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "framework": "./index.js", 9 | "import": "./index.js" 10 | } 11 | }, 12 | "dependencies": { 13 | "@vitefu/dep-cjs-js-lib": "file:../cjs-js-lib", 14 | "@vitefu/dep-implicit-entry-cjs-lib": "file:../implicit-entry-cjs-lib", 15 | "@vitefu/dep-no-deep-optimize-lib": "file:../no-deep-optimize-lib", 16 | "@vitefu/dep-no-entry-lib": "file:../no-entry-lib", 17 | "@vitefu/dep-should-no-external-lib": "file:../should-no-external-lib" 18 | }, 19 | "peerDependencies": { 20 | "@vitefu/dep-framework": "^0.0.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/deps/implicit-entry-cjs-lib/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svitejs/vitefu/04f8198ad30ed02eea89bd313affc92a6f1c1cb9/tests/deps/implicit-entry-cjs-lib/index.js -------------------------------------------------------------------------------- /tests/deps/implicit-entry-cjs-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-implicit-entry-cjs-lib", 3 | "version": "0.0.1", 4 | "private": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/deps/no-deep-optimize-lib/index.js: -------------------------------------------------------------------------------- 1 | // note: this dep should be optimized, but we want to test explicitly opting out of it 2 | module.exports = 'foo' -------------------------------------------------------------------------------- /tests/deps/no-deep-optimize-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-no-deep-optimize-lib", 3 | "version": "0.0.1", 4 | "private": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/deps/no-entry-lib/index.d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svitejs/vitefu/04f8198ad30ed02eea89bd313affc92a6f1c1cb9/tests/deps/no-entry-lib/index.d.ts -------------------------------------------------------------------------------- /tests/deps/no-entry-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-no-entry-lib", 3 | "version": "0.0.1", 4 | "private": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/deps/proxy-framework-lib/index.js: -------------------------------------------------------------------------------- 1 | import FrameworkComponent from '@vitefu/dep-full-framework-lib' 2 | export default FrameworkComponent 3 | -------------------------------------------------------------------------------- /tests/deps/proxy-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-proxy-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "framework": "./index.js", 9 | "import": "./index.js" 10 | } 11 | }, 12 | "dependencies": { 13 | "@vitefu/dep-full-framework-lib": "file:../full-framework-lib" 14 | }, 15 | "peerDependencies": { 16 | "@vitefu/dep-framework": "^0.0.1" 17 | }, 18 | "devDependencies": { 19 | "@vitefu/dep-framework": "file:../framework" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/deps/semi-framework-lib/index.js: -------------------------------------------------------------------------------- 1 | import { trim } from '@vitefu/dep-framework' 2 | 3 | export function betterTrim(str) { 4 | return trim(str) 5 | } 6 | -------------------------------------------------------------------------------- /tests/deps/semi-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-semi-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "import": "./index.js" 9 | } 10 | }, 11 | "dependencies": { 12 | "@vitefu/dep-framework": "file:../framework" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/deps/should-no-external-lib/index.js: -------------------------------------------------------------------------------- 1 | export function hello() { 2 | return 'world' 3 | } 4 | -------------------------------------------------------------------------------- /tests/deps/should-no-external-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/dep-sshould-no-external-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "import": "./index.js" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/projects/basic/basic.test.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | import { test } from 'uvu' 3 | import * as assert from 'uvu/assert' 4 | import { crawlFrameworkPkgs } from '../../../src/index.js' 5 | 6 | const root = fileURLToPath(new URL('./', import.meta.url)) 7 | 8 | test('crawlFrameworkPkgs (dev)', async () => { 9 | const result = await callCrawlFrameworkPkgs(false) 10 | assert.equal(result, { 11 | optimizeDeps: { 12 | include: [ 13 | '@vitefu/dep-full-direct-framework-lib > @vitefu/dep-cjs-js-lib', 14 | '@vitefu/dep-full-framework-lib > @vitefu/dep-cjs-js-lib', 15 | '@vitefu/dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib', 16 | '@vitefu/dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-cjs-js-lib', 17 | '@vitefu/dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib' 18 | ], 19 | exclude: [ 20 | '@vitefu/dep-full-direct-framework-lib', 21 | '@vitefu/dep-full-framework-lib', 22 | '@vitefu/dep-proxy-framework-lib' 23 | ] 24 | }, 25 | ssr: { 26 | noExternal: [ 27 | '@vitefu/dep-full-direct-framework-lib', 28 | '@vitefu/dep-full-framework-lib', 29 | '@vitefu/dep-proxy-framework-lib', 30 | '@vitefu/dep-semi-framework-lib' 31 | ], 32 | external: [ 33 | '@vitefu/dep-cjs-js-lib', 34 | '@vitefu/dep-framework', 35 | '@vitefu/dep-implicit-entry-cjs-lib', 36 | '@vitefu/dep-no-deep-optimize-lib', 37 | '@vitefu/dep-no-entry-lib' 38 | ] 39 | } 40 | }) 41 | }) 42 | 43 | test('crawlFrameworkPkgs (build)', async () => { 44 | const result = await callCrawlFrameworkPkgs(true) 45 | assert.equal(result, { 46 | optimizeDeps: { 47 | include: [ 48 | '@vitefu/dep-full-direct-framework-lib > @vitefu/dep-cjs-js-lib', 49 | '@vitefu/dep-full-framework-lib > @vitefu/dep-cjs-js-lib', 50 | '@vitefu/dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib', 51 | '@vitefu/dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-cjs-js-lib', 52 | '@vitefu/dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib' 53 | ], 54 | exclude: [ 55 | '@vitefu/dep-full-direct-framework-lib', 56 | '@vitefu/dep-full-framework-lib', 57 | '@vitefu/dep-proxy-framework-lib' 58 | ] 59 | }, 60 | ssr: { 61 | noExternal: [ 62 | '@vitefu/dep-full-direct-framework-lib', 63 | '@vitefu/dep-full-framework-lib', 64 | '@vitefu/dep-proxy-framework-lib', 65 | '@vitefu/dep-semi-framework-lib' 66 | ], 67 | external: [] 68 | } 69 | }) 70 | }) 71 | 72 | test.run() 73 | 74 | /** 75 | * @param {boolean} isBuild 76 | */ 77 | async function callCrawlFrameworkPkgs(isBuild) { 78 | const result = await crawlFrameworkPkgs({ 79 | root, 80 | isBuild, 81 | viteUserConfig: { 82 | optimizeDeps: { 83 | exclude: ['@vitefu/dep-no-deep-optimize-lib'] 84 | }, 85 | ssr: { 86 | noExternal: [/@vitefu\/dep-should-no-external-lib/] 87 | } 88 | }, 89 | isFrameworkPkgByJson: (pkgJson) => { 90 | return exportsHasFrameworkField(pkgJson.exports || {}) 91 | }, 92 | isSemiFrameworkPkgByJson: (pkgJson) => { 93 | return !!( 94 | pkgJson.dependencies?.['@vitefu/dep-framework'] || 95 | pkgJson.peerDependencies?.['@vitefu/dep-framework'] 96 | ) 97 | } 98 | }) 99 | // sort for deep equal comparison 100 | result.optimizeDeps.include.sort() 101 | result.optimizeDeps.exclude.sort() 102 | result.ssr.noExternal.sort() 103 | result.ssr.external.sort() 104 | return result 105 | } 106 | 107 | /** 108 | * @param {Record} exports 109 | */ 110 | function exportsHasFrameworkField(exports) { 111 | for (const [key, value] of Object.entries(exports)) { 112 | if (key === 'framework') { 113 | return true 114 | } else if ( 115 | typeof value === 'object' && 116 | value != null && 117 | exportsHasFrameworkField(value) 118 | ) { 119 | return true 120 | } 121 | } 122 | return false 123 | } 124 | -------------------------------------------------------------------------------- /tests/projects/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/project-basic", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "dependencies": { 7 | "@vitefu/dep-esm-js-lib": "file:../../deps/esm-js-lib", 8 | "@vitefu/dep-framework": "file:../../deps/framework", 9 | "@vitefu/dep-full-direct-framework-lib": "file:../../deps/full-direct-framework-lib", 10 | "@vitefu/dep-full-framework-lib": "file:../../deps/full-framework-lib", 11 | "@vitefu/dep-proxy-framework-lib": "file:../../deps/proxy-framework-lib", 12 | "@vitefu/dep-semi-framework-lib": "file:../../deps/semi-framework-lib" 13 | }, 14 | "devDependencies": { 15 | "uvu": "^0.5.6" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/projects/package.json/empty.js: -------------------------------------------------------------------------------- 1 | // retain `package.json` directory for unit test 2 | -------------------------------------------------------------------------------- /tests/projects/workspace/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/project-workspace", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "devDependencies": { 7 | "uvu": "^0.5.6" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/project-basic", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "dependencies": { 7 | "@vitefu/dep-esm-js-lib": "file:../../deps/esm-js-lib", 8 | "@vitefu/dep-framework": "file:../../deps/framework", 9 | "@vitefu/dep-full-direct-framework-lib": "file:../../deps/full-direct-framework-lib", 10 | "@vitefu/dep-full-framework-lib": "file:../../deps/full-framework-lib", 11 | "@vitefu/dep-proxy-framework-lib": "file:../../deps/proxy-framework-lib", 12 | "@vitefu/dep-semi-framework-lib": "file:../../deps/semi-framework-lib" 13 | }, 14 | "devDependencies": { 15 | "uvu": "^0.5.6" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/project-workspace-app", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "devDependencies": { 7 | "@vitefu/workspace-dep-full-direct-framework-lib": "../workspace-full-direct-framework-lib", 8 | "@vitefu/workspace-dep-full-framework-lib": "../workspace-full-framework-lib", 9 | "@vitefu/workspace-dep-semi-framework-lib": "../workspace-semi-framework-lib", 10 | "@vitefu/workspace-dep-proxy-framework-lib": "../workspace-proxy-framework-lib", 11 | "@vitefu/workspace-dep-esm-js-lib": "../workspace-esm-js-lib", 12 | "@types/node": "^14.18.63" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-esm-js-lib/index.js: -------------------------------------------------------------------------------- 1 | export function plus(a, b) { 2 | return a + b 3 | } 4 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-esm-js-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/workspace-dep-esm-js-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "import": "./index.js" 9 | } 10 | }, 11 | "devDependencies": { 12 | "@types/node": "^14.18.63" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-full-direct-framework-lib/index.framework: -------------------------------------------------------------------------------- 1 | 2 | export default function renderComponent() { 3 | return 'Hello World' 4 | } 5 | 6 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-full-direct-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/workspace-dep-full-direct-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "framework": "./index.js" 9 | }, 10 | "./package.json": "./package.json" 11 | }, 12 | "devDependencies": { 13 | "@vitefu/dep-cjs-js-lib": "file:../../../../deps/cjs-js-lib", 14 | "@vitefu/dep-implicit-entry-cjs-lib": "file:../../../../deps/implicit-entry-cjs-lib", 15 | "@vitefu/dep-no-deep-optimize-lib": "file:../../../../deps/no-deep-optimize-lib", 16 | "@vitefu/dep-no-entry-lib": "file:../../../../deps/no-entry-lib", 17 | "@vitefu/dep-should-no-external-lib": "file:../../../../deps/should-no-external-lib", 18 | "@types/node": "^14.18.63" 19 | }, 20 | "peerDependencies": { 21 | "@vitefu/dep-framework": "^0.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-full-framework-lib/index.framework: -------------------------------------------------------------------------------- 1 | 2 | export default function renderComponent() { 3 | return 'Hello World' 4 | } 5 | 6 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-full-framework-lib/index.js: -------------------------------------------------------------------------------- 1 | export { default as default } from './index.framework' 2 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-full-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/workspace-dep-full-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "framework": "./index.js", 9 | "import": "./index.js" 10 | } 11 | }, 12 | "devDependencies": { 13 | "@vitefu/dep-cjs-js-lib": "file:../../../../deps/cjs-js-lib", 14 | "@vitefu/dep-implicit-entry-cjs-lib": "file:../../../../deps/implicit-entry-cjs-lib", 15 | "@vitefu/dep-no-deep-optimize-lib": "file:../../../../deps/no-deep-optimize-lib", 16 | "@vitefu/dep-no-entry-lib": "file:../../../../deps/no-entry-lib", 17 | "@vitefu/dep-should-no-external-lib": "file:../../../../deps/should-no-external-lib", 18 | "@types/node": "^14.18.63" 19 | }, 20 | "peerDependencies": { 21 | "@vitefu/dep-framework": "^0.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-proxy-framework-lib/index.js: -------------------------------------------------------------------------------- 1 | import FrameworkComponent from '@vitefu/dep-full-framework-lib' 2 | export default FrameworkComponent 3 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-proxy-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/workspace-dep-proxy-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "framework": "./index.js", 9 | "import": "./index.js" 10 | } 11 | }, 12 | "peerDependencies": { 13 | "@vitefu/dep-framework": "^0.0.1" 14 | }, 15 | "devDependencies": { 16 | "@vitefu/dep-full-framework-lib": "file:../../../../deps/full-framework-lib", 17 | "@vitefu/dep-framework": "file:../../../../deps/framework", 18 | "@types/node": "^14.18.63" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-semi-framework-lib/index.js: -------------------------------------------------------------------------------- 1 | import { trim } from '@vitefu/dep-framework' 2 | 3 | export function betterTrim(str) { 4 | return trim(str) 5 | } 6 | -------------------------------------------------------------------------------- /tests/projects/workspace/packages/workspace-semi-framework-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vitefu/workspace-dep-semi-framework-lib", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "import": "./index.js" 9 | } 10 | }, 11 | "devDdependencies": { 12 | "@vitefu/dep-framework": "file:../../../../deps/framework" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/projects/workspace/workspace.test.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | import { test } from 'uvu' 3 | import * as assert from 'uvu/assert' 4 | import {crawlFrameworkPkgs} from '../../../src/index.js' 5 | 6 | const workspaceRoot = fileURLToPath(new URL('../../../', import.meta.url)) 7 | .replace(/\\/g,'/') // vite's seachForWorkspaceRoot returns slashified string on windows do that here too 8 | .replace(/\/$/,'') 9 | const root = fileURLToPath(new URL('./packages/workspace-app', import.meta.url)).replace(/\/$/,'') 10 | 11 | test('crawlFrameworkPkgs (dev)', async () => { 12 | const result = await callCrawlFrameworkPkgs({isBuild: false}) 13 | assert.equal(result, { 14 | optimizeDeps: { 15 | include: [], 16 | exclude: [ 17 | "@vitefu/workspace-dep-full-direct-framework-lib", 18 | "@vitefu/workspace-dep-full-framework-lib", 19 | "@vitefu/workspace-dep-proxy-framework-lib" 20 | ] 21 | }, 22 | ssr: { 23 | noExternal: [ 24 | "@vitefu/workspace-dep-full-direct-framework-lib", 25 | "@vitefu/workspace-dep-full-framework-lib", 26 | "@vitefu/workspace-dep-proxy-framework-lib" 27 | ], 28 | external: [] 29 | } 30 | }) 31 | }) 32 | 33 | test('crawlFrameworkPkgs (build)', async () => { 34 | const result = await callCrawlFrameworkPkgs({isBuild: true}) 35 | assert.equal(result, { 36 | optimizeDeps: { 37 | include: [], 38 | exclude: [ 39 | "@vitefu/workspace-dep-full-direct-framework-lib", 40 | "@vitefu/workspace-dep-full-framework-lib", 41 | "@vitefu/workspace-dep-proxy-framework-lib" 42 | ] 43 | }, 44 | ssr: { 45 | noExternal: [ 46 | "@vitefu/workspace-dep-full-direct-framework-lib", 47 | "@vitefu/workspace-dep-full-framework-lib", 48 | "@vitefu/workspace-dep-proxy-framework-lib" 49 | ], 50 | external: [] 51 | } 52 | }) 53 | }) 54 | 55 | test('crawlFrameworkPkgs (dev + workspaceRoot)', async () => { 56 | const result = await callCrawlFrameworkPkgs({isBuild: false, workspaceRoot}) 57 | assert.equal(result, { 58 | optimizeDeps: { 59 | include: [ 60 | "@vitefu/workspace-dep-full-direct-framework-lib > @vitefu/dep-cjs-js-lib", 61 | "@vitefu/workspace-dep-full-direct-framework-lib > @vitefu/dep-implicit-entry-cjs-lib", 62 | "@vitefu/workspace-dep-full-framework-lib > @vitefu/dep-cjs-js-lib", 63 | "@vitefu/workspace-dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib", 64 | "@vitefu/workspace-dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-cjs-js-lib", 65 | "@vitefu/workspace-dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib" 66 | 67 | ], 68 | exclude: [ 69 | "@vitefu/dep-full-framework-lib", 70 | "@vitefu/workspace-dep-full-direct-framework-lib", 71 | "@vitefu/workspace-dep-full-framework-lib", 72 | "@vitefu/workspace-dep-proxy-framework-lib" 73 | ] 74 | }, 75 | ssr: { 76 | noExternal: [ 77 | "@vitefu/dep-full-framework-lib", 78 | "@vitefu/workspace-dep-full-direct-framework-lib", 79 | "@vitefu/workspace-dep-full-framework-lib", 80 | "@vitefu/workspace-dep-proxy-framework-lib" 81 | ], 82 | external: [ 83 | "@types/node", 84 | "@vitefu/dep-cjs-js-lib", 85 | "@vitefu/dep-framework", 86 | "@vitefu/dep-implicit-entry-cjs-lib", 87 | "@vitefu/dep-no-deep-optimize-lib", 88 | "@vitefu/dep-no-entry-lib" 89 | ] 90 | } 91 | }) 92 | }) 93 | 94 | test('crawlFrameworkPkgs (build + workspaceRoot)', async () => { 95 | const result = await callCrawlFrameworkPkgs({isBuild:true, workspaceRoot}) 96 | assert.equal(result, { 97 | optimizeDeps: { 98 | include: [ 99 | "@vitefu/workspace-dep-full-direct-framework-lib > @vitefu/dep-cjs-js-lib", 100 | "@vitefu/workspace-dep-full-direct-framework-lib > @vitefu/dep-implicit-entry-cjs-lib", 101 | "@vitefu/workspace-dep-full-framework-lib > @vitefu/dep-cjs-js-lib", 102 | "@vitefu/workspace-dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib", 103 | "@vitefu/workspace-dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-cjs-js-lib", 104 | "@vitefu/workspace-dep-proxy-framework-lib > @vitefu/dep-full-framework-lib > @vitefu/dep-implicit-entry-cjs-lib" 105 | 106 | ], 107 | exclude: [ 108 | "@vitefu/dep-full-framework-lib", 109 | "@vitefu/workspace-dep-full-direct-framework-lib", 110 | "@vitefu/workspace-dep-full-framework-lib", 111 | "@vitefu/workspace-dep-proxy-framework-lib" 112 | ] 113 | }, 114 | ssr: { 115 | noExternal: [ 116 | "@vitefu/dep-full-framework-lib", 117 | "@vitefu/workspace-dep-full-direct-framework-lib", 118 | "@vitefu/workspace-dep-full-framework-lib", 119 | "@vitefu/workspace-dep-proxy-framework-lib" 120 | ], 121 | external: [] 122 | } 123 | }) 124 | }) 125 | 126 | 127 | test.run() 128 | 129 | /** 130 | * 131 | * @param {Partial} options 132 | * @returns {ReturnType} 133 | */ 134 | async function callCrawlFrameworkPkgs(options) { 135 | const mergedOptions = { 136 | root, 137 | ...options, 138 | isBuild: options.isBuild ?? false, 139 | viteUserConfig: { 140 | optimizeDeps: { 141 | exclude: ['@vitefu/dep-no-deep-optimize-lib'] 142 | }, 143 | ssr: { 144 | noExternal: [/@vitefu\/dep-should-no-external-lib/] 145 | } 146 | }, 147 | isFrameworkPkgByJson: (pkgJson) => { 148 | return exportsHasFrameworkField(pkgJson.exports || {}) 149 | }, 150 | isSemiFrameworkPkgByJson: (pkgJson) => { 151 | return !!( 152 | pkgJson.dependencies?.['@vitefu/dep-framework'] || 153 | pkgJson.peerDependencies?.['@vitefu/dep-framework'] 154 | ) 155 | } 156 | }; 157 | const result = await crawlFrameworkPkgs(mergedOptions) 158 | // sort for deep equal comparison 159 | result.optimizeDeps.include.sort() 160 | result.optimizeDeps.exclude.sort() 161 | result.ssr.noExternal.sort() 162 | result.ssr.external.sort() 163 | return result 164 | } 165 | 166 | /** 167 | * @param {Record} exports 168 | */ 169 | function exportsHasFrameworkField(exports) { 170 | for (const [key, value] of Object.entries(exports)) { 171 | if (key === 'framework') { 172 | return true 173 | } else if ( 174 | typeof value === 'object' && 175 | value != null && 176 | exportsHasFrameworkField(value) 177 | ) { 178 | return true 179 | } 180 | } 181 | return false 182 | } 183 | -------------------------------------------------------------------------------- /tests/unit.test.js: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises' 2 | import { fileURLToPath } from 'node:url' 3 | import { suite } from 'uvu' 4 | import * as assert from 'uvu/assert' 5 | import { 6 | findClosestPkgJsonPath, 7 | isDepIncluded, 8 | isDepExcluded, 9 | isDepNoExternaled, 10 | isDepExternaled 11 | } from '../src/index.js' 12 | 13 | const test1 = suite('isDepIncluded') 14 | test1('return true if dep is included', () => { 15 | assert.ok(isDepIncluded('foo', ['foo'])) 16 | }) 17 | test1('return true if dep is deep included', () => { 18 | assert.ok(isDepIncluded('bar', ['foo > bar'])) 19 | }) 20 | test1('return false if dep is not included', () => { 21 | assert.not.ok(isDepIncluded('bar', ['foo'])) 22 | }) 23 | test1.run() 24 | 25 | const test2 = suite('isDepExcluded') 26 | test2('return true if dep is excluded', () => { 27 | assert.ok(isDepExcluded('foo', ['foo'])) 28 | }) 29 | test2('return false if dep is not excluded', () => { 30 | assert.not.ok(isDepExcluded('bar', ['foo'])) 31 | }) 32 | test2('return true if nested dep is excluded', () => { 33 | assert.ok(isDepExcluded('hello > foo', ['foo'])) 34 | assert.ok(isDepExcluded('hello > world > foo', ['foo'])) 35 | }) 36 | test2('return false if nested dep is not excluded', () => { 37 | assert.not.ok(isDepExcluded('hello > bar', ['foo'])) 38 | assert.not.ok(isDepExcluded('hello > world > bar', ['foo'])) 39 | }) 40 | test2.run() 41 | 42 | const test3 = suite('isDepNoExternaled') 43 | test3('return true if dep is noExternaled', () => { 44 | assert.ok(isDepNoExternaled('foo', ['foo'])) 45 | }) 46 | test3('return false if dep is not noExternaled', () => { 47 | assert.not.ok(isDepNoExternaled('bar', ['foo'])) 48 | }) 49 | test3('return true if dep is noExternaled is true', () => { 50 | assert.ok(isDepNoExternaled('foo', true)) 51 | }) 52 | test3('return true if dep is noExternaled with regex', () => { 53 | assert.ok(isDepNoExternaled('foo', 'foo')) 54 | }) 55 | test3('return true if dep is noExternaled with regex', () => { 56 | assert.ok(isDepNoExternaled('foo', /fo/)) 57 | }) 58 | test3('return true if dep is noExternaled with string and regex array', () => { 59 | assert.ok(isDepNoExternaled('foo', ['foo', /ba/])) 60 | assert.ok(isDepNoExternaled('bar', ['foo', /ba/])) 61 | }) 62 | test3.run() 63 | 64 | const test4 = suite('isDepExternaled') 65 | test4('return true if dep is externaled', () => { 66 | assert.ok(isDepExternaled('foo', ['foo'])) 67 | }) 68 | test4('return false if dep is not externaled', () => { 69 | assert.not.ok(isDepExternaled('bar', ['foo'])) 70 | }) 71 | test4.run() 72 | 73 | const test5 = suite('findClosestPkgJsonPath') 74 | test5('return package.json', async () => { 75 | const start = fileURLToPath(new URL('.', import.meta.url)) 76 | const actual = await findClosestPkgJsonPath(start) 77 | const expected = fileURLToPath(new URL('../package.json', import.meta.url)) 78 | assert.equal(actual, expected) 79 | }) 80 | test5('ignore package.json directory name', async () => { 81 | const start = fileURLToPath( 82 | new URL('./projects/package.json/empty.js', import.meta.url) 83 | ) 84 | const actual = await findClosestPkgJsonPath(start) 85 | const expected = fileURLToPath(new URL('../package.json', import.meta.url)) 86 | assert.equal(actual, expected) 87 | }) 88 | test5('respect predicate', async () => { 89 | const start = fileURLToPath( 90 | new URL('./projects/basic/package.json', import.meta.url) 91 | ) 92 | const actual = await findClosestPkgJsonPath(start, async (pkgJsonPath) => { 93 | const content = await fs.readFile(pkgJsonPath, 'utf8') 94 | const json = JSON.parse(content) 95 | return json.name === 'vitefu' 96 | }) 97 | const expected = fileURLToPath(new URL('../package.json', import.meta.url)) 98 | assert.equal(actual, expected) 99 | }) 100 | test5.run() 101 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "checkJs": true, 7 | "allowJs": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "strictNullChecks": true 11 | }, 12 | "include": ["src", "tests"], 13 | "exclude": ["tests/deps"] 14 | } 15 | --------------------------------------------------------------------------------