├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── action.yml ├── dist ├── cleanup │ └── index.js └── setup │ └── index.js ├── eslint.config.mjs ├── lib └── .gitignore ├── package-lock.json ├── package.json ├── src ├── cleanup-dev-drive.ts ├── cleanup-impl.ts ├── constants.ts ├── env-mapping.ts ├── setup-dev-drive.ts ├── setup-impl.ts └── vhd-commands.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.ts] 10 | indent_style = space 11 | indent_size = 2 12 | max_line_length = 88 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | permissions: 10 | contents: read 11 | 12 | concurrency: 13 | group: main-${{ github.head_ref || github.ref }} 14 | cancel-in-progress: ${{ github.event_name == 'pull_request' }} 15 | 16 | env: 17 | NPM_CONFIG_AUDIT: "false" 18 | NPM_CONFIG_FUND: "false" 19 | 20 | jobs: 21 | 22 | checks: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - name: Check out source code 26 | uses: actions/checkout@v4 27 | - name: Install Dependencies 28 | run: npm install 29 | - name: Run tsc 30 | run: npm run build 31 | - name: Run fmt check 32 | run: npm run fmt-check 33 | - name: Run lint check 34 | run: npm run lint 35 | - name: Run bundle 36 | run: npm run bundle 37 | - name: Compare the expected and actual dist/ directories 38 | run: | 39 | if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then 40 | echo "Detected uncommitted changes after build. See status below:" 41 | git diff --text -v 42 | exit 1 43 | fi 44 | 45 | audit: 46 | runs-on: ubuntu-latest 47 | steps: 48 | - name: Check out source code 49 | uses: actions/checkout@v4 50 | - run: npm install 51 | - run: npm audit --audit-level moderate --omit dev 52 | 53 | test-defaults: 54 | strategy: 55 | fail-fast: false 56 | matrix: 57 | runner: [ windows-2022, windows-2025 ] 58 | runs-on: ${{ matrix.runner }} 59 | steps: 60 | - name: Check out source code 61 | uses: actions/checkout@v4 62 | - name: Setup Dev Drive 63 | uses: ./ 64 | 65 | test-declare-inputs: 66 | strategy: 67 | fail-fast: false 68 | matrix: 69 | runner: [ windows-2022, windows-2025 ] 70 | runs-on: ${{ matrix.runner }} 71 | steps: 72 | - name: Check out source code 73 | uses: actions/checkout@v4 74 | - name: Setup Dev Drive 75 | uses: ./ 76 | with: 77 | drive-size: 2GB 78 | drive-format: NTFS 79 | drive-type: Fixed 80 | drive-path: "my_awesome_drive.vhdx" 81 | mount-path: "" 82 | mount-if-exists: false 83 | workspace-copy: true 84 | native-dev-drive: false 85 | trusted-dev-drive: false 86 | env-mapping: '' 87 | 88 | test-formats: 89 | strategy: 90 | fail-fast: false 91 | matrix: 92 | runner: [ windows-2022, windows-2025 ] 93 | drive-format: [ FAT, FAT32, exFAT, NTFS, ReFS ] 94 | with-mount-path: [ true, false ] 95 | runs-on: ${{ matrix.runner }} 96 | steps: 97 | - name: Check out source code 98 | uses: actions/checkout@v4 99 | - name: Setup Dev Drive 100 | uses: ./ 101 | with: 102 | drive-format: ${{ matrix.drive-format }} 103 | # This should fall back to Drive Letter on unsupported drive formats. 104 | mount-path: ${{ matrix.with-mount-path && 'mount' || '' }} 105 | # Ensure we test FS directly 106 | native-dev-drive: false 107 | 108 | test-large-size: 109 | strategy: 110 | fail-fast: false 111 | matrix: 112 | runner: [ windows-2022, windows-2025 ] 113 | drive-type: [ Fixed, Dynamic ] 114 | with-mount-path: [ true, false ] 115 | runs-on: ${{ matrix.runner }} 116 | steps: 117 | - name: Check out source code 118 | uses: actions/checkout@v4 119 | - name: Setup Dev Drive 120 | id: setup-drive 121 | uses: ./ 122 | with: 123 | drive-size: 10GB 124 | drive-type: ${{ matrix.drive-type }} 125 | mount-path: ${{ matrix.with-mount-path && 'mount' || '' }} 126 | 127 | test-paths-with-spaces: 128 | strategy: 129 | fail-fast: false 130 | matrix: 131 | runner: [ windows-2022, windows-2025 ] 132 | with-mount-path: [ true, false ] 133 | runs-on: ${{ matrix.runner }} 134 | steps: 135 | - name: Check out source code 136 | uses: actions/checkout@v4 137 | - name: Setup Dev Drive 138 | uses: ./ 139 | with: 140 | drive-size: 50MB 141 | drive-format: NTFS 142 | drive-path: "path/to/my/dev drive with spaces.vhdx" 143 | mount-path: ${{ matrix.with-mount-path && 'my mount/location/with spaces' || '' }} 144 | - name: Write File to Dev Drive 145 | working-directory: ${{ env.DEV_DRIVE }} 146 | run: New-Item test.txt 147 | 148 | 149 | test-trusted-mode: 150 | strategy: 151 | fail-fast: false 152 | matrix: 153 | runner: [ windows-2022, windows-2025 ] 154 | with-mount-path: [ true, false ] 155 | runs-on: ${{ matrix.runner }} 156 | steps: 157 | - name: Check out source code 158 | uses: actions/checkout@v4 159 | - name: Setup Dev Drive 160 | uses: ./ 161 | with: 162 | native-dev-drive: true 163 | trusted-dev-drive: true 164 | mount-path: ${{ matrix.with-mount-path && 'mount' || '' }} 165 | 166 | test-mount-path: 167 | strategy: 168 | fail-fast: false 169 | matrix: 170 | runner: [ windows-2022, windows-2025 ] 171 | is-relative: [ true, false ] 172 | drive-format: [ ReFS, NTFS ] 173 | runs-on: ${{ matrix.runner }} 174 | steps: 175 | - name: Check out source code 176 | uses: actions/checkout@v4 177 | - name: Setup Dev Drive 178 | uses: ./ 179 | with: 180 | drive-format: ${{ matrix.drive-format }} 181 | mount-path: ${{ matrix.is-relative && 'mount' || format('{0}/mount', github.workspace) }} 182 | - name: Write File to Dev Drive 183 | working-directory: ${{ env.DEV_DRIVE }} 184 | run: | 185 | New-Item test.txt 186 | 187 | test-workspace-copy: 188 | strategy: 189 | fail-fast: false 190 | matrix: 191 | runner: [ windows-2022, windows-2025 ] 192 | with-mount-path: [ true, false ] 193 | workspace-copy: [ true ] 194 | runs-on: ${{ matrix.runner }} 195 | steps: 196 | - name: Check out source code 197 | uses: actions/checkout@v4 198 | - name: Setup Dev Drive 199 | id: setup-drive 200 | uses: ./ 201 | with: 202 | mount-path: ${{ matrix.with-mount-path && format('{0}/../mount', github.workspace) || '' }} 203 | workspace-copy: ${{ matrix.workspace-copy }} 204 | - name: Check workspace was copied 205 | working-directory: ${{ env.DEV_DRIVE_WORKSPACE }} 206 | run: | 207 | Get-ChildItem -Force 208 | if (-not $env:DEV_DRIVE_WORKSPACE) { 209 | exit 1 210 | } 211 | if (-not (Test-Path -Path action.yml -PathType Leaf)) { 212 | exit 1 213 | } 214 | 215 | test-workspace-copy-edge-cases: 216 | strategy: 217 | fail-fast: false 218 | matrix: 219 | runner: [ windows-2022, windows-2025 ] 220 | with-mount-path: [ true, false ] 221 | workspace-copy: [ true, false ] 222 | runs-on: ${{ matrix.runner }} 223 | steps: 224 | - name: Check out source code 225 | uses: actions/checkout@v4 226 | - name: Setup Dev Drive 227 | id: setup-drive 228 | continue-on-error: true 229 | uses: ./ 230 | with: 231 | drive-path: "${{ github.workspace }}/dev_drive.vhdx" 232 | mount-path: ${{ matrix.with-mount-path && format('{0}/mount', github.workspace) || '' }} 233 | workspace-copy: ${{ matrix.workspace-copy }} 234 | # Dev Drive Location 235 | - name: Check dev drive is inside GitHub workspace 236 | run: | 237 | Get-ChildItem -Force 238 | if (-not (Test-Path -Path dev_drive.vhdx -PathType Leaf)) { 239 | exit 1 240 | } 241 | - name: Check workspace was copied, filtering the dev drive 242 | if: ${{ !matrix.with-mount-path && matrix.workspace-copy }} 243 | working-directory: ${{ env.DEV_DRIVE_WORKSPACE }} 244 | run: | 245 | Get-ChildItem -Force 246 | if (-not $env:DEV_DRIVE_WORKSPACE) { 247 | exit 1 248 | } 249 | if (Test-Path -Path dev_drive.vhdx -PathType Leaf) { 250 | exit 1 251 | } 252 | if (-not (Test-Path -Path action.yml -PathType Leaf)) { 253 | exit 1 254 | } 255 | # Drive Letter (with Dev Drive inside workspace) 256 | - name: Fail when `workspace-copy` and success is not the outcome when drive letter is being used 257 | if: ${{ !matrix.with-mount-path && matrix.workspace-copy && steps.setup-drive.outcome != 'success' }} 258 | run: exit 1 259 | - name: Fail when not `workspace-copy` and success is not the outcome when drive letter is being used 260 | if: ${{ !matrix.with-mount-path && !matrix.workspace-copy && steps.setup-drive.outcome != 'success' }} 261 | run: exit 1 262 | # Mount Path (with mount inside workspace) 263 | - name: Fail when `workspace-copy` and failure is not the outcome when mount path is inside workspace 264 | if: ${{ matrix.with-mount-path && matrix.workspace-copy && steps.setup-drive.outcome != 'failure' }} 265 | run: exit 1 266 | - name: Fail when not `workspace-copy` and success is not the outcome when mount path inside workspace 267 | if: ${{ matrix.with-mount-path && !matrix.workspace-copy && steps.setup-drive.outcome != 'success' }} 268 | run: exit 1 269 | 270 | test-unsupported-os: 271 | runs-on: ubuntu-latest 272 | steps: 273 | - name: Check out source code 274 | uses: actions/checkout@v4 275 | - name: Setup Dev Drive 276 | uses: ./ 277 | 278 | test-legacy-runners: 279 | runs-on: windows-2019 280 | steps: 281 | - name: Check out source code 282 | uses: actions/checkout@v4 283 | - name: Setup Dev Drive 284 | id: setup-drive 285 | continue-on-error: true 286 | uses: ./ 287 | - name: Fail when failure is not the outcome 288 | if: steps.setup-drive.outcome != 'failure' 289 | run: exit 1 290 | 291 | test-cache-storage: 292 | strategy: 293 | fail-fast: false 294 | matrix: 295 | runner: [ windows-2022, windows-2025 ] 296 | with-mount-path: [ true, false ] 297 | runs-on: ${{ matrix.runner }} 298 | steps: 299 | - name: Check out source code 300 | uses: actions/checkout@v4 301 | - name: Setup Dev Drive 302 | uses: ./ 303 | with: 304 | drive-size: 50MB 305 | drive-format: NTFS 306 | drive-path: "my_cached_drive.vhdx" 307 | mount-path: ${{ matrix.with-mount-path && format('{0}/mount', github.workspace) || '' }} 308 | mount-if-exists: true 309 | - name: Write File to Dev Drive 310 | working-directory: ${{ env.DEV_DRIVE }} 311 | # Dismount so we can always force-cache the disk via actions/cache/save 312 | run: | 313 | New-Item test.txt 314 | Dismount-VHD -Path ${{ env.DEV_DRIVE_PATH }} 315 | - name: Cache Dev Drive 316 | uses: actions/cache/save@v4 317 | with: 318 | path: ${{ env.DEV_DRIVE_PATH }} 319 | key: ${{ matrix.with-mount-path && format('test-cache-mount-path-{0}', github.run_id) || format('test-cache-drive-letter-{0}', github.run_id) }} 320 | outputs: 321 | dev-drive-path: ${{ env.DEV_DRIVE_PATH }} 322 | 323 | test-cache-retrieval: 324 | strategy: 325 | fail-fast: false 326 | matrix: 327 | runner: [ windows-2022, windows-2025 ] 328 | with-mount-path: [ true, false ] 329 | runs-on: ${{ matrix.runner }} 330 | needs: [test-cache-storage] 331 | steps: 332 | - name: Check out source code 333 | uses: actions/checkout@v4 334 | - name: Retrieve Cached Dev Drive 335 | uses: actions/cache/restore@v4 336 | with: 337 | path: ${{ needs.test-cache-storage.outputs.dev-drive-path }} 338 | key: ${{ matrix.with-mount-path && format('test-cache-mount-path-{0}', github.run_id) || format('test-cache-drive-letter-{0}', github.run_id) }} 339 | fail-on-cache-miss: true 340 | - name: Setup Dev Drive 341 | uses: ./ 342 | with: 343 | drive-path: "my_cached_drive.vhdx" 344 | mount-path: ${{ matrix.with-mount-path && format('{0}/mount', github.workspace) || '' }} 345 | mount-if-exists: true 346 | - name: Check File in Dev Drive 347 | working-directory: ${{ env.DEV_DRIVE }} 348 | run: | 349 | Get-ChildItem -Force 350 | if (-not (Test-Path -Path test.txt -PathType Leaf)) { 351 | exit 1 352 | } 353 | 354 | test-env-mapping: 355 | strategy: 356 | fail-fast: false 357 | matrix: 358 | runner: [ windows-2022, windows-2025 ] 359 | runs-on: ${{ matrix.runner }} 360 | steps: 361 | - name: Check out source code 362 | uses: actions/checkout@v4 363 | - name: Setup Dev Drive 364 | uses: ./ 365 | with: 366 | workspace-copy: true 367 | env-mapping: | 368 | CARGO_HOME,{{ DEV_DRIVE }}/.cargo 369 | RUSTUP_HOME,{{ DEV_DRIVE }}/.rustup 370 | MY_ENV_VAR , {{ DEV_DRIVE_PATH }} 371 | MY_OTHER_ENV_VAR,{{ DEV_DRIVE_WORKSPACE }}\other\path 372 | SHOULD_WARN, 373 | should_also_warn,about_template 374 | invalid-env-var,??? 375 | invalid.env.var,!!! 376 | ENV_VAR_VALUE_INCLUDES_COMMAS,{{ DEV_DRIVE}}/my file name, with commas.txt 377 | a 378 | , 379 | 42,{{ DEV_DRIVE }}/42 380 | does_it_substitute_1137,{{ DEV_DRIVE }}/$DEV_DRIVE 381 | - name: Verify Env Mapping 382 | run: | 383 | if ($Env:CARGO_HOME -ne '${{ env.DEV_DRIVE }}/.cargo') { Write-Error 'Failed CARGO_HOME'; exit 1 } 384 | if ($Env:RUSTUP_HOME -ne '${{ env.DEV_DRIVE }}/.rustup') { Write-Error 'Failed RUSTUP_HOME'; exit 1 } 385 | if ($Env:MY_ENV_VAR -ne '${{ env.DEV_DRIVE_PATH }}') { Write-Error 'Failed MY_ENV_VAR'; exit 1 } 386 | if ($Env:MY_OTHER_ENV_VAR -ne '${{ env.DEV_DRIVE_WORKSPACE }}\other\path') { Write-Error 'Failed MY_OTHER_ENV_VAR'; exit 1 } 387 | if ($Env:SHOULD_WARN -ne $null) { Write-Error 'Failed SHOULD_WARN'; exit 1 } 388 | if ($Env:should_also_warn -ne $null) { Write-Error 'Failed should_also_warn'; exit 1 } 389 | if (${Env:invalid-env-var} -ne $null) { Write-Error 'Failed invalid-env-var'; exit 1 } 390 | if (${Env:invalid.env.var} -ne $null) { Write-Error 'Failed invalid.env.var'; exit 1 } 391 | if ($Env:ENV_VAR_VALUE_INCLUDES_COMMAS -ne '${{ env.DEV_DRIVE }}/my file name, with commas.txt') { Write-Error 'Failed ENV_VAR_VALUE_INCLUDES_COMMAS'; exit 1 } 392 | if ($Env:a -ne $null) { Write-Error 'Failed a'; exit 1 } 393 | if (${Env:,} -ne $null) { Write-Error 'Failed ,'; exit 1 } 394 | if (${Env:42} -ne $null) { Write-Error 'Failed 42'; exit 1 } 395 | if ($Env:does_it_substitute_1137 -ne '${{ env.DEV_DRIVE }}/$DEV_DRIVE') { Write-Error 'Failed does_it_substitute_1137'; exit 1 } 396 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/node,linux,windows,osx,visualstudiocode,intellij+all 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=node,linux,windows,osx,visualstudiocode,intellij+all 3 | 4 | ### Intellij+all ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/**/usage.statistics.xml 12 | .idea/**/dictionaries 13 | .idea/**/shelf 14 | 15 | # AWS User-specific 16 | .idea/**/aws.xml 17 | 18 | # Generated files 19 | .idea/**/contentModel.xml 20 | 21 | # Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | .idea/**/dbnavigator.xml 29 | 30 | # Gradle 31 | .idea/**/gradle.xml 32 | .idea/**/libraries 33 | 34 | # Gradle and Maven with auto-import 35 | # When using Gradle or Maven with auto-import, you should exclude module files, 36 | # since they will be recreated, and may cause churn. Uncomment if using 37 | # auto-import. 38 | # .idea/artifacts 39 | # .idea/compiler.xml 40 | # .idea/jarRepositories.xml 41 | # .idea/modules.xml 42 | # .idea/*.iml 43 | # .idea/modules 44 | # *.iml 45 | # *.ipr 46 | 47 | # CMake 48 | cmake-build-*/ 49 | 50 | # Mongo Explorer plugin 51 | .idea/**/mongoSettings.xml 52 | 53 | # File-based project format 54 | *.iws 55 | 56 | # IntelliJ 57 | out/ 58 | 59 | # mpeltonen/sbt-idea plugin 60 | .idea_modules/ 61 | 62 | # JIRA plugin 63 | atlassian-ide-plugin.xml 64 | 65 | # Cursive Clojure plugin 66 | .idea/replstate.xml 67 | 68 | # SonarLint plugin 69 | .idea/sonarlint/ 70 | 71 | # Crashlytics plugin (for Android Studio and IntelliJ) 72 | com_crashlytics_export_strings.xml 73 | crashlytics.properties 74 | crashlytics-build.properties 75 | fabric.properties 76 | 77 | # Editor-based Rest Client 78 | .idea/httpRequests 79 | 80 | # Android studio 3.1+ serialized cache file 81 | .idea/caches/build_file_checksums.ser 82 | 83 | ### Intellij+all Patch ### 84 | # Ignore everything but code style settings and run configurations 85 | # that are supposed to be shared within teams. 86 | 87 | .idea/* 88 | 89 | !.idea/codeStyles 90 | !.idea/runConfigurations 91 | 92 | ### Linux ### 93 | *~ 94 | 95 | # temporary files which can be created if a process still has a handle open of a deleted file 96 | .fuse_hidden* 97 | 98 | # KDE directory preferences 99 | .directory 100 | 101 | # Linux trash folder which might appear on any partition or disk 102 | .Trash-* 103 | 104 | # .nfs files are created when an open file is removed but is still being accessed 105 | .nfs* 106 | 107 | ### Node ### 108 | # Logs 109 | logs 110 | *.log 111 | npm-debug.log* 112 | yarn-debug.log* 113 | yarn-error.log* 114 | lerna-debug.log* 115 | .pnpm-debug.log* 116 | 117 | # Diagnostic reports (https://nodejs.org/api/report.html) 118 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 119 | 120 | # Runtime data 121 | pids 122 | *.pid 123 | *.seed 124 | *.pid.lock 125 | 126 | # Directory for instrumented libs generated by jscoverage/JSCover 127 | lib-cov 128 | 129 | # Coverage directory used by tools like istanbul 130 | coverage 131 | *.lcov 132 | 133 | # nyc test coverage 134 | .nyc_output 135 | 136 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 137 | .grunt 138 | 139 | # Bower dependency directory (https://bower.io/) 140 | bower_components 141 | 142 | # node-waf configuration 143 | .lock-wscript 144 | 145 | # Compiled binary addons (https://nodejs.org/api/addons.html) 146 | build/Release 147 | 148 | # Dependency directories 149 | node_modules/ 150 | jspm_packages/ 151 | 152 | # Snowpack dependency directory (https://snowpack.dev/) 153 | web_modules/ 154 | 155 | # TypeScript cache 156 | *.tsbuildinfo 157 | 158 | # Optional npm cache directory 159 | .npm 160 | 161 | # Optional eslint cache 162 | .eslintcache 163 | 164 | # Optional stylelint cache 165 | .stylelintcache 166 | 167 | # Microbundle cache 168 | .rpt2_cache/ 169 | .rts2_cache_cjs/ 170 | .rts2_cache_es/ 171 | .rts2_cache_umd/ 172 | 173 | # Optional REPL history 174 | .node_repl_history 175 | 176 | # Output of 'npm pack' 177 | *.tgz 178 | 179 | # Yarn Integrity file 180 | .yarn-integrity 181 | 182 | # dotenv environment variable files 183 | .env 184 | .env.development.local 185 | .env.test.local 186 | .env.production.local 187 | .env.local 188 | 189 | # parcel-bundler cache (https://parceljs.org/) 190 | .cache 191 | .parcel-cache 192 | 193 | # Next.js build output 194 | .next 195 | out 196 | 197 | # Nuxt.js build / generate output 198 | .nuxt 199 | dist 200 | 201 | # Gatsby files 202 | .cache/ 203 | # Comment in the public line in if your project uses Gatsby and not Next.js 204 | # https://nextjs.org/blog/next-9-1#public-directory-support 205 | # public 206 | 207 | # vuepress build output 208 | .vuepress/dist 209 | 210 | # vuepress v2.x temp and cache directory 211 | .temp 212 | 213 | # Docusaurus cache and generated files 214 | .docusaurus 215 | 216 | # Serverless directories 217 | .serverless/ 218 | 219 | # FuseBox cache 220 | .fusebox/ 221 | 222 | # DynamoDB Local files 223 | .dynamodb/ 224 | 225 | # TernJS port file 226 | .tern-port 227 | 228 | # Stores VSCode versions used for testing VSCode extensions 229 | .vscode-test 230 | 231 | # yarn v2 232 | .yarn/cache 233 | .yarn/unplugged 234 | .yarn/build-state.yml 235 | .yarn/install-state.gz 236 | .pnp.* 237 | 238 | ### Node Patch ### 239 | # Serverless Webpack directories 240 | .webpack/ 241 | 242 | # Optional stylelint cache 243 | 244 | # SvelteKit build / generate output 245 | .svelte-kit 246 | 247 | ### OSX ### 248 | # General 249 | .DS_Store 250 | .AppleDouble 251 | .LSOverride 252 | 253 | # Icon must end with two \r 254 | Icon 255 | 256 | 257 | # Thumbnails 258 | ._* 259 | 260 | # Files that might appear in the root of a volume 261 | .DocumentRevisions-V100 262 | .fseventsd 263 | .Spotlight-V100 264 | .TemporaryItems 265 | .Trashes 266 | .VolumeIcon.icns 267 | .com.apple.timemachine.donotpresent 268 | 269 | # Directories potentially created on remote AFP share 270 | .AppleDB 271 | .AppleDesktop 272 | Network Trash Folder 273 | Temporary Items 274 | .apdisk 275 | 276 | ### VisualStudioCode ### 277 | .vscode/* 278 | !.vscode/settings.json 279 | !.vscode/tasks.json 280 | !.vscode/launch.json 281 | !.vscode/extensions.json 282 | !.vscode/*.code-snippets 283 | 284 | # Local History for Visual Studio Code 285 | .history/ 286 | 287 | # Built Visual Studio Code Extensions 288 | *.vsix 289 | 290 | ### VisualStudioCode Patch ### 291 | # Ignore all local history of files 292 | .history 293 | .ionide 294 | 295 | ### Windows ### 296 | # Windows thumbnail cache files 297 | Thumbs.db 298 | Thumbs.db:encryptable 299 | ehthumbs.db 300 | ehthumbs_vista.db 301 | 302 | # Dump file 303 | *.stackdump 304 | 305 | # Folder config file 306 | [Dd]esktop.ini 307 | 308 | # Recycle Bin used on file shares 309 | $RECYCLE.BIN/ 310 | 311 | # Windows Installer files 312 | *.cab 313 | *.msi 314 | *.msix 315 | *.msm 316 | *.msp 317 | 318 | # Windows shortcuts 319 | *.lnk 320 | 321 | # End of https://www.toptal.com/developers/gitignore/api/node,linux,windows,osx,visualstudiocode,intellij+all 322 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | dist/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSameLine": false, 4 | "bracketSpacing": true, 5 | "endOfLine": "lf", 6 | "htmlWhitespaceSensitivity": "css", 7 | "jsxSingleQuote": false, 8 | "printWidth": 88, 9 | "proseWrap": "always", 10 | "quoteProps": "as-needed", 11 | "semi": false, 12 | "singleQuote": true, 13 | "tabWidth": 2, 14 | "trailingComma": "all", 15 | "useTabs": false 16 | } 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 3.4.1 2 | 3 | * Improve logging when marking dev drive as trusted. 4 | 5 | # 3.4.0 6 | 7 | * Add ability to mark dev drive as trusted. 8 | 9 | # 3.3.0 10 | 11 | * Add `windows-2025` runner support. 12 | * Change default VHDX size to 2GB. 13 | 14 | # 3.2.0 15 | 16 | * Add `env-mapping` option to support improved environment variables configuration. 17 | 18 | # 3.1.0 19 | 20 | * Expose `native-dev-drive` as an option to turn off automatic native Dev Drive usage. 21 | * Documentation improvements. 22 | * Align package.json version. 23 | 24 | # 3.0.0 25 | 26 | * Allow mounting dev drive in specified mount path (ReFS, NTFS only). 27 | * Workspace copying is no longer restricted by the Dev Drive location. 28 | * Paths in output env vars are no longer escaped `\\`. 29 | * Cleaner error messages. 30 | 31 | # 2.2.0 32 | 33 | * Improved error handling feedback. 34 | * Additional CI tests. 35 | * More Badges. 36 | 37 | # 2.1.2 38 | 39 | * Documentation improvements. 40 | 41 | # 2.1.1 42 | 43 | * Added error check when Dev Drive is located inside `${{ github.workspace }}` when `workspace-copy` is set. 44 | 45 | # 2.1.0 46 | 47 | * Added input option `mount-if-exists` to allow mounting pre-existing VHDX drives (e.g. from `actions/cache`). 48 | 49 | # 2.0.0 50 | 51 | * The default `drive-type` is now `Dynamic` instead of `Fixed`. 52 | 53 | # 1.1.0 54 | 55 | * Support `drive-type` input allowing to set the drive allocation to `Fixed` or `Dynamic`. 56 | 57 | # 1.0.0 58 | 59 | * Initial Release. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 samypr100 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 | [![GitHub Actions][github-actions-badge]](https://github.com/samypr100/setup-dev-drive/actions/workflows/main.yml) 2 | [![Release][release-badge]](https://github.com/samypr100/setup-dev-drive/releases) 3 | [![Marketplace][marketplace-badge]](https://github.com/marketplace/actions/setup-dev-drive) 4 | [![License][license-badge]](https://github.com/samypr100/setup-dev-drive/blob/main/LICENSE) 5 | [![Language][typescript-badge]](https://www.typescriptlang.org) 6 | [![OS][windows-badge]](https://learn.microsoft.com/en-us/windows/dev-drive) 7 | 8 | [github-actions-badge]: https://github.com/samypr100/setup-dev-drive/actions/workflows/main.yml/badge.svg 9 | [release-badge]: https://img.shields.io/github/release/samypr100/setup-dev-drive.svg 10 | [marketplace-badge]: https://img.shields.io/badge/setup--dev--drive-100000?&label=Marketplace&logo=github 11 | [license-badge]: https://img.shields.io/github/license/samypr100/setup-dev-drive.svg 12 | [typescript-badge]: https://img.shields.io/badge/TypeScript-3178c6?&logo=typescript&logoColor=white 13 | [windows-badge]: https://img.shields.io/badge/Windows%20Only-08a1f7?&logo=windows 14 | 15 | This action primary aim is to create a [Windows Dev Drive](https://learn.microsoft.com/en-us/windows/dev-drive/) 16 | on your behalf and expose its location via GitHub Environment Variables. 17 | 18 | Dev Drives use `ReFS` under the hood to provide optimizations that are targeted for developer workflows. 19 | By using a dev drive, you can increase performance significantly on a variety of developer workloads. 20 | 21 | Workloads that involve high IO, such as building and testing will see an **improvement of about 25% 22 | or more on average**, which can translate to substantial speed, quota, and cost savings. 23 | See [related blog post](https://devblogs.microsoft.com/visualstudio/devdrive/). 24 | 25 | You can still decide to use something else than `ReFS` and get speed benefits of 26 | a [Virtual Hard Disk](https://en.wikipedia.org/wiki/VHD_(file_format)) (VHDX) that 27 | this action creates for you. 28 | 29 | ## Usage 30 | 31 | Just add the following line to the `steps:` list in your GitHub Actions yaml: 32 | 33 | ```yaml 34 | - uses: samypr100/setup-dev-drive@v3 35 | ``` 36 | 37 | You can optionally pass parameters to the action as follows: 38 | 39 | ```yaml 40 | - uses: samypr100/setup-dev-drive@v3 41 | with: 42 | # Drive size in bytes (or as a PowerShell numeric literal). Defaults to 2GB. 43 | drive-size: 2GB 44 | # Drive file system (ReFS, NTFS, etc.). Defaults to ReFS. 45 | drive-format: ReFS 46 | # Drive allocation (Dynamic or Fixed). Defaults to Dynamic. 47 | drive-type: Dynamic 48 | # Path to VHDX file. Defaults to `/dev_drive.vhdx` 49 | drive-path: "dev_drive.vhdx" 50 | # Path to mount the drive. Defaults to creating a new arbitrary drive letter such as "E:". 51 | mount-path: "my_mount_path" 52 | # Mounts (rather than create) an existing VHDX in drive-path. Defaults to false. 53 | mount-if-exists: false 54 | # Copies ${{ github.workspace }} to your dev drive. Defaults to false. 55 | workspace-copy: false 56 | # Use native dev drive support when available. Defaults to true. 57 | native-dev-drive: true 58 | # Used to mark the native dev drive as trusted. Defaults to false. 59 | trusted-dev-drive: false 60 | # Custom mappings of output environment variables. Defaults to no mapping. 61 | env-mapping: | 62 | MY_PROJECT_BIN,{{ DEV_DRIVE }}/path/to/bin 63 | ``` 64 | 65 | This action is [compatible](#runner-compatibility) with `windows-2022` runners or above. 66 | 67 | For more examples, take a look in the dedicated [examples section](#examples). 68 | 69 | ## Configuration 70 | 71 | ### *drive-size* 72 | 73 | By default, this option is set to `2GB`. 74 | 75 | Allows you to configure the dev drive size in bytes. This is subject to the limit of space 76 | available on your runner. The default public runners roughly hold about 15GB of 77 | [space](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories), 78 | so it's suggested you keep your drive size below that limit, or you may encounter errors. 79 | 80 | You can use PowerShell built in [Numeric Literals](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_numeric_literals) 81 | functionality to automatically expand expressions like `2GB` to mean `2147483648`. 82 | 83 | ### *drive-format* 84 | 85 | The format of the drive, by default `ReFS` but it can be any of `FAT`, `FAT32`, `exFAT`, `NTFS`, `ReFS` 86 | as provided by [Format-Volume](https://learn.microsoft.com/en-us/powershell/module/storage/format-volume). 87 | 88 | ### *drive-path* 89 | 90 | The path to the dev drive VHDX file, defaults to the relative path `dev_drive.vhdx` under the 91 | current system root. 92 | 93 | When a relative path is provided, it will be relative to `C:\`, `D:\` or the default 94 | workspace drive letter on the runner. Hence, `dev_drive.vhdx` will likely resolve to 95 | `C:\dev_drive.vhdx` or `D:\dev_drive.vhdx`. 96 | 97 | When an absolute path is provided, make sure it's located outside `${{ github.workspace }}` 98 | otherwise `workspace-copy` will issue a warning. This action will ignore copying the dev drive 99 | in such scenarios. 100 | 101 | ### *drive-type* 102 | 103 | By default, this option is set to `Dynamic`. 104 | 105 | Determines the type of drive, `Fixed` or `Dynamic`. There are performance tradeoffs between 106 | both. For the purposes of this action `Dynamic` is used by default for flexibility. 107 | 108 | `Dynamic` is useful when you want to cache the disk across job runs as it yields a smaller 109 | payload to cache when the job ends. 110 | 111 | `Fixed` gives you a notable performance boost, but there's a small creation overhead. 112 | 113 | ### *mount-path* 114 | 115 | By default, this option is not set and defaults to a new arbitrary drive letter such as `E:`. 116 | 117 | Mounts the dev drive at the specified `mount-path` location. This option can be 118 | useful when you want to mount your dev drive inside the GitHub workspace via 119 | `${{ github.workspace }}/my_mount_path`, `my_mount_path`, or equivalent. 120 | 121 | This option is only supported when using the `NTFS` or `ReFS` drive formats, otherwise 122 | it will fall back to a drive letter instead. Furthermore, when a relative path is specified 123 | it the mount path will end up being relative to your current working directory. 124 | 125 | **Warning**: Setting `mount-path` to exactly `${{ github.workspace }}` and then running 126 | `actions/checkout` will try to wipe your mount folder, causing an error that looks like 127 | `File was unable to be removed Error: EPERM: operation not permitted, lstat '${{ github.workspace }}\System Volume Information'` 128 | See [actions/checkout#430](https://github.com/actions/checkout/issues/430) for more details 129 | on this non-configurable behavior by `actions/checkout`. 130 | 131 | In such cases, it is recommended you run `actions/checkout` before this action. 132 | You can also leverage `workspace-copy: true` to copy your contents as long as 133 | your mount path is outside `${{ github.workspace }}`. 134 | 135 | ### *mount-if-exists* 136 | 137 | By default, this option is set to `false`. 138 | 139 | Mounts the dev drive if it already exists at `drive-path` location. When it does not exist, 140 | it will fall back to creating one at that location instead. This is useful when your workflow 141 | caches the dev drive for further use in other jobs via `actions/cache`. 142 | 143 | ### *workspace-copy* 144 | 145 | By default, this option is set to `false`. 146 | 147 | This copies `${{ github.workspace }}` to your dev drive. Usually when you use `actions/checkout` 148 | it creates a shallow copy of your commit to `${{ github.workspace }}`. When `workspace-copy` 149 | is set to `true`, this action will copy your workspace into your dev drive allowing you move 150 | your workload to be purely on the dev drive. 151 | 152 | This option was needed since `actions/checkout` does not allow cloning outside `${{ github.workspace }}`. 153 | See [actions/checkout#197](https://github.com/actions/checkout/issues/197). 154 | 155 | This option is compatible with `mount-path` as long as the mount path is not directly located inside your 156 | GitHub workspace (e.g. `${{ github.workspace }}/../my_mount_path`). 157 | 158 | ### *native-dev-drive* 159 | 160 | By default, this option is set to `true`. 161 | 162 | This action will automatically use the built-in [Windows Dev Drive](https://learn.microsoft.com/en-us/windows/dev-drive/) 163 | on your behalf when it's available on your Windows runner and `ReFS` is used. 164 | You can use this option to turn this automatic usage off. 165 | 166 | ### *trusted-dev-drive* 167 | 168 | By default, this option is set to `false`. 169 | 170 | This action will not mark the dev drive as trusted and will leave it to default settings. 171 | When an additional degree of performance is desired, marking a native dev drive as trusted may help. 172 | 173 | Consult [official documentation](https://learn.microsoft.com/en-us/windows/dev-drive/#understanding-security-risks-and-trust-in-relation-to-dev-drive) 174 | before considering enabling this functionality. 175 | 176 | ### *env-mapping* 177 | 178 | By default, this option is not set. 179 | 180 | This option provides syntactic sugar to manage the environment variables exposed by this action. 181 | 182 | On a particular job, it can be repetitive having to re-declare the environment variables like below. 183 | 184 | ```yaml 185 | - uses: samypr100/setup-dev-drive@v3 186 | - name: Step A 187 | env: 188 | CARGO_HOME: ${{ env.DEV_DRIVE }}/.cargo 189 | RUSTUP_HOME: ${{ env.DEV_DRIVE }}/.rustup 190 | run: ... 191 | - name: Step B 192 | env: 193 | CARGO_HOME: ${{ env.DEV_DRIVE }}/.cargo 194 | RUSTUP_HOME: ${{ env.DEV_DRIVE }}/.rustup 195 | run: ... 196 | - name: Step C 197 | env: 198 | CARGO_HOME: ${{ env.DEV_DRIVE }}/.cargo 199 | RUSTUP_HOME: ${{ env.DEV_DRIVE }}/.rustup 200 | run: ... 201 | # ... 202 | ``` 203 | 204 | This option allows you to define them once per job as shown in the example below. 205 | 206 | It leverages [handlebars](https://handlebarsjs.com/) syntax under the hood to expose the supported 207 | [environment variables](#environment-variables), giving you the ability to create new ones with 208 | their contents after the action runs, so they can be automatically set in subsequent steps. 209 | 210 | **Warning**: No canonicalization is performed on the input. The template is substituted as-is with the 211 | typical values of the environment variables and the rest of the input is then appended as-is. 212 | 213 | ```yaml 214 | - uses: samypr100/setup-dev-drive@v3 215 | with: 216 | env-mapping: | 217 | CARGO_HOME,{{ DEV_DRIVE }}/.cargo 218 | RUSTUP_HOME,{{ DEV_DRIVE }}/.rustup 219 | - name: Step A 220 | run: ... 221 | - name: Step B 222 | run: ... 223 | - name: Step C 224 | run: ... 225 | # ... 226 | ``` 227 | 228 | ## Exported Environment Variables 229 | 230 | These environment variables are meant to be used along `working-directory` to make sure 231 | your workflow commands are executing relative to your dev drive. 232 | 233 | #### *DEV_DRIVE* 234 | 235 | Contains the path to your dev drive of the form `:` or the canonical `mount-path`. 236 | For example, if the dev drive assigned letter is `E`, `${{ env.DEV_DRIVE }}` will contain `E:`. 237 | 238 | When `mount-path` is set, the value will be the resolved canonical path of the mount path. 239 | For example if your specified mount path is `my_mount_path`, the value will look like 240 | `D:\a\path\to\my_mount_path`. 241 | 242 | This env var is always set. 243 | 244 | #### *DEV_DRIVE_WORKSPACE* 245 | 246 | When `workspace-copy` is set to true, this contains the workspace location as represented 247 | by the dev drive location. For example if your GitHub workspace is `D:\a\\` 248 | your dev drive workspace will be `E:\` by default assuming the drive letter is `E`. 249 | 250 | When `mount-path` is set, this behaves the same as described above with the caveat that the `mount-path` 251 | location must be outside your GitHub workspace (e.g. `${{ github.workspace }}/../my_mount_path`). 252 | 253 | This env var is only set **if-only-if** `workspace-copy` option is set. Otherwise, it's expected that 254 | you'd use `DEV_DRIVE` env var instead. 255 | 256 | #### *DEV_DRIVE_PATH* 257 | 258 | The canonical location of the VHDX file. 259 | 260 | When `drive-path` is set to a relative path like `my_drive.vhdx` 261 | the location in this variable will likely be `D:\my_drive.vhdx`. 262 | 263 | When `drive-path` is set to an absolute path like `D:\path\to\my_drive.vhdx` 264 | the location in this variable will be the same but normalized as given by 265 | [path.normalize](https://nodejs.org/api/path.html#pathnormalizepath). 266 | 267 | This env var is always set. 268 | 269 | ## Examples 270 | 271 | ### Setting working directory to use Dev Drive workspace 272 | 273 | ```yaml 274 | - uses: actions/checkout@v4 275 | - uses: samypr100/setup-dev-drive@v3 276 | with: 277 | workspace-copy: true 278 | - name: Install dependencies in dev drive 279 | working-directory: ${{ env.DEV_DRIVE_WORKSPACE }} 280 | run: npm install 281 | ``` 282 | 283 | ### Installing software inside Dev Drive root 284 | 285 | ```yaml 286 | - uses: samypr100/setup-dev-drive@v3 287 | - name: Install rust toolchain in dev drive 288 | env: 289 | CARGO_HOME: ${{ env.DEV_DRIVE }}/.cargo 290 | RUSTUP_HOME: ${{ env.DEV_DRIVE }}/.rustup 291 | run: rustup show 292 | ``` 293 | 294 | ### Caching the Dev Drive 295 | 296 | Inspired by [actions/cache#752 (comment)](https://github.com/actions/cache/issues/752#issuecomment-1847036770) 297 | 298 | ```yaml 299 | - uses: actions/checkout@v4 300 | - uses: actions/cache@v4 301 | with: 302 | path: "C:\\bazel_cache.vhdx" 303 | key: bazel-cache-windows 304 | - uses: samypr100/setup-dev-drive@v3 305 | with: 306 | drive-path: "C:\\bazel_cache.vhdx" 307 | drive-format: NTFS 308 | mount-if-exists: true 309 | - name: Build and test 310 | run: bazelisk --output_base=$env:DEV_DRIVE test --config=windows //... 311 | # ... 312 | ``` 313 | 314 | ## Runner Compatibility 315 | 316 | This action currently only works on windows runners. In particular, this 317 | action will only work with `windows-2022` or `windows-latest` runners. 318 | 319 | For native dev drive support, `10.0.22621` build or later of windows is required. 320 | This action will gracefully still work even if native dev drive is not available. 321 | 322 | On cases where runners may still not be updated to meet the minimum version, you can 323 | still get speed gains by using this action due to `ReFS` and `VHDX` usage. 324 | 325 | 326 | ## Credits 327 | 328 | Thanks to Paco Sevilla for the idea to use a VHDX within a GitHub Workflow. 329 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "Setup Dev Drive" 2 | description: "A GitHub Action to setup a Windows Dev Drive." 3 | author: "samypr100" 4 | branding: 5 | icon: hard-drive 6 | color: purple 7 | inputs: 8 | drive-size: 9 | description: "Drive Size. Examples: 1GB, 3GB, 10GB." 10 | default: "2GB" 11 | drive-format: 12 | description: "Drive Format. Examples: FAT, FAT32, exFAT, NTFS, ReFS." 13 | default: "ReFS" 14 | drive-path: 15 | description: "Absolute or relative path to the Dev Drive storage location. Example: C:/path/to/my/dev_drive.vhdx" 16 | default: "dev_drive.vhdx" 17 | drive-type: 18 | description: "Determines whether all space is allocated initially or over time. Example: Fixed or Dynamic." 19 | default: "Dynamic" 20 | mount-path: 21 | description: "Specific mount location for the Dev Drive. Only compatible with NTFS or ReFS." 22 | required: false 23 | mount-if-exists: 24 | description: "Supports mounting an existing VHDX located in `drive-path`, avoiding creation overhead." 25 | default: "false" 26 | workspace-copy: 27 | description: "Copy your GITHUB_WORKSPACE checkout to your Dev Drive. Examples: true, false." 28 | default: "false" 29 | native-dev-drive: 30 | description: "Use native dev drive support when available." 31 | default: "true" 32 | trusted-dev-drive: 33 | description: "Use to mark a native dev drive as trusted." 34 | default: "false" 35 | env-mapping: 36 | description: "Allows mapping environment variables generated by this action to new user-defined ones." 37 | required: false 38 | runs: 39 | using: "node20" 40 | main: "dist/setup/index.js" 41 | post: "dist/cleanup/index.js" 42 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import eslint from '@eslint/js' 4 | import tseslint from 'typescript-eslint' 5 | 6 | export default tseslint.config( 7 | eslint.configs.recommended, 8 | tseslint.configs.recommended, 9 | { 10 | ignores: ['lib/', 'dist/', 'node_modules/'], 11 | }, 12 | ) 13 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-dev-drive", 3 | "version": "3.4.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "setup-dev-drive", 9 | "version": "3.4.1", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@actions/core": "^1.11.1", 13 | "@actions/exec": "^1.1.1", 14 | "@actions/github": "^6.0.0", 15 | "compare-versions": "^6.1.1", 16 | "fs-extra": "^11.3.0", 17 | "handlebars": "^4.7.8", 18 | "shell-quote": "^1.8.2" 19 | }, 20 | "devDependencies": { 21 | "@eslint/js": "^9.19.0", 22 | "@tsconfig/node20": "^20.1.4", 23 | "@types/fs-extra": "^11.0.4", 24 | "@types/node": "^20.17.16", 25 | "@types/shell-quote": "^1.7.5", 26 | "@vercel/ncc": "^0.38.3", 27 | "eslint": "^9.19.0", 28 | "eslint-plugin-prettier": "^5.2.3", 29 | "prettier": "^3.4.2", 30 | "typescript": "^5.7.3", 31 | "typescript-eslint": "^8.22.0" 32 | } 33 | }, 34 | "node_modules/@actions/core": { 35 | "version": "1.11.1", 36 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", 37 | "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", 38 | "license": "MIT", 39 | "dependencies": { 40 | "@actions/exec": "^1.1.1", 41 | "@actions/http-client": "^2.0.1" 42 | } 43 | }, 44 | "node_modules/@actions/exec": { 45 | "version": "1.1.1", 46 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", 47 | "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", 48 | "license": "MIT", 49 | "dependencies": { 50 | "@actions/io": "^1.0.1" 51 | } 52 | }, 53 | "node_modules/@actions/github": { 54 | "version": "6.0.0", 55 | "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", 56 | "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", 57 | "license": "MIT", 58 | "dependencies": { 59 | "@actions/http-client": "^2.2.0", 60 | "@octokit/core": "^5.0.1", 61 | "@octokit/plugin-paginate-rest": "^9.0.0", 62 | "@octokit/plugin-rest-endpoint-methods": "^10.0.0" 63 | } 64 | }, 65 | "node_modules/@actions/http-client": { 66 | "version": "2.2.3", 67 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", 68 | "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", 69 | "license": "MIT", 70 | "dependencies": { 71 | "tunnel": "^0.0.6", 72 | "undici": "^5.25.4" 73 | } 74 | }, 75 | "node_modules/@actions/io": { 76 | "version": "1.1.3", 77 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", 78 | "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", 79 | "license": "MIT" 80 | }, 81 | "node_modules/@eslint-community/eslint-utils": { 82 | "version": "4.4.1", 83 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", 84 | "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", 85 | "dev": true, 86 | "license": "MIT", 87 | "dependencies": { 88 | "eslint-visitor-keys": "^3.4.3" 89 | }, 90 | "engines": { 91 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 92 | }, 93 | "funding": { 94 | "url": "https://opencollective.com/eslint" 95 | }, 96 | "peerDependencies": { 97 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 98 | } 99 | }, 100 | "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { 101 | "version": "3.4.3", 102 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 103 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 104 | "dev": true, 105 | "license": "Apache-2.0", 106 | "engines": { 107 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 108 | }, 109 | "funding": { 110 | "url": "https://opencollective.com/eslint" 111 | } 112 | }, 113 | "node_modules/@eslint-community/regexpp": { 114 | "version": "4.12.1", 115 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", 116 | "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", 117 | "dev": true, 118 | "license": "MIT", 119 | "engines": { 120 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 121 | } 122 | }, 123 | "node_modules/@eslint/config-array": { 124 | "version": "0.19.2", 125 | "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", 126 | "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", 127 | "dev": true, 128 | "license": "Apache-2.0", 129 | "dependencies": { 130 | "@eslint/object-schema": "^2.1.6", 131 | "debug": "^4.3.1", 132 | "minimatch": "^3.1.2" 133 | }, 134 | "engines": { 135 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 136 | } 137 | }, 138 | "node_modules/@eslint/core": { 139 | "version": "0.10.0", 140 | "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", 141 | "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", 142 | "dev": true, 143 | "license": "Apache-2.0", 144 | "dependencies": { 145 | "@types/json-schema": "^7.0.15" 146 | }, 147 | "engines": { 148 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 149 | } 150 | }, 151 | "node_modules/@eslint/eslintrc": { 152 | "version": "3.2.0", 153 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", 154 | "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", 155 | "dev": true, 156 | "license": "MIT", 157 | "dependencies": { 158 | "ajv": "^6.12.4", 159 | "debug": "^4.3.2", 160 | "espree": "^10.0.1", 161 | "globals": "^14.0.0", 162 | "ignore": "^5.2.0", 163 | "import-fresh": "^3.2.1", 164 | "js-yaml": "^4.1.0", 165 | "minimatch": "^3.1.2", 166 | "strip-json-comments": "^3.1.1" 167 | }, 168 | "engines": { 169 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 170 | }, 171 | "funding": { 172 | "url": "https://opencollective.com/eslint" 173 | } 174 | }, 175 | "node_modules/@eslint/js": { 176 | "version": "9.19.0", 177 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", 178 | "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", 179 | "dev": true, 180 | "license": "MIT", 181 | "engines": { 182 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 183 | } 184 | }, 185 | "node_modules/@eslint/object-schema": { 186 | "version": "2.1.6", 187 | "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", 188 | "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", 189 | "dev": true, 190 | "license": "Apache-2.0", 191 | "engines": { 192 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 193 | } 194 | }, 195 | "node_modules/@eslint/plugin-kit": { 196 | "version": "0.2.5", 197 | "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", 198 | "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", 199 | "dev": true, 200 | "license": "Apache-2.0", 201 | "dependencies": { 202 | "@eslint/core": "^0.10.0", 203 | "levn": "^0.4.1" 204 | }, 205 | "engines": { 206 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 207 | } 208 | }, 209 | "node_modules/@fastify/busboy": { 210 | "version": "2.1.1", 211 | "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 212 | "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 213 | "license": "MIT", 214 | "engines": { 215 | "node": ">=14" 216 | } 217 | }, 218 | "node_modules/@humanfs/core": { 219 | "version": "0.19.1", 220 | "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", 221 | "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", 222 | "dev": true, 223 | "license": "Apache-2.0", 224 | "engines": { 225 | "node": ">=18.18.0" 226 | } 227 | }, 228 | "node_modules/@humanfs/node": { 229 | "version": "0.16.6", 230 | "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", 231 | "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", 232 | "dev": true, 233 | "license": "Apache-2.0", 234 | "dependencies": { 235 | "@humanfs/core": "^0.19.1", 236 | "@humanwhocodes/retry": "^0.3.0" 237 | }, 238 | "engines": { 239 | "node": ">=18.18.0" 240 | } 241 | }, 242 | "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { 243 | "version": "0.3.1", 244 | "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", 245 | "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", 246 | "dev": true, 247 | "license": "Apache-2.0", 248 | "engines": { 249 | "node": ">=18.18" 250 | }, 251 | "funding": { 252 | "type": "github", 253 | "url": "https://github.com/sponsors/nzakas" 254 | } 255 | }, 256 | "node_modules/@humanwhocodes/module-importer": { 257 | "version": "1.0.1", 258 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 259 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 260 | "dev": true, 261 | "license": "Apache-2.0", 262 | "engines": { 263 | "node": ">=12.22" 264 | }, 265 | "funding": { 266 | "type": "github", 267 | "url": "https://github.com/sponsors/nzakas" 268 | } 269 | }, 270 | "node_modules/@humanwhocodes/retry": { 271 | "version": "0.4.1", 272 | "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", 273 | "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", 274 | "dev": true, 275 | "license": "Apache-2.0", 276 | "engines": { 277 | "node": ">=18.18" 278 | }, 279 | "funding": { 280 | "type": "github", 281 | "url": "https://github.com/sponsors/nzakas" 282 | } 283 | }, 284 | "node_modules/@nodelib/fs.scandir": { 285 | "version": "2.1.5", 286 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 287 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 288 | "dev": true, 289 | "license": "MIT", 290 | "dependencies": { 291 | "@nodelib/fs.stat": "2.0.5", 292 | "run-parallel": "^1.1.9" 293 | }, 294 | "engines": { 295 | "node": ">= 8" 296 | } 297 | }, 298 | "node_modules/@nodelib/fs.stat": { 299 | "version": "2.0.5", 300 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 301 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 302 | "dev": true, 303 | "license": "MIT", 304 | "engines": { 305 | "node": ">= 8" 306 | } 307 | }, 308 | "node_modules/@nodelib/fs.walk": { 309 | "version": "1.2.8", 310 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 311 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 312 | "dev": true, 313 | "license": "MIT", 314 | "dependencies": { 315 | "@nodelib/fs.scandir": "2.1.5", 316 | "fastq": "^1.6.0" 317 | }, 318 | "engines": { 319 | "node": ">= 8" 320 | } 321 | }, 322 | "node_modules/@octokit/auth-token": { 323 | "version": "4.0.0", 324 | "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", 325 | "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", 326 | "license": "MIT", 327 | "engines": { 328 | "node": ">= 18" 329 | } 330 | }, 331 | "node_modules/@octokit/core": { 332 | "version": "5.2.0", 333 | "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", 334 | "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", 335 | "license": "MIT", 336 | "dependencies": { 337 | "@octokit/auth-token": "^4.0.0", 338 | "@octokit/graphql": "^7.1.0", 339 | "@octokit/request": "^8.3.1", 340 | "@octokit/request-error": "^5.1.0", 341 | "@octokit/types": "^13.0.0", 342 | "before-after-hook": "^2.2.0", 343 | "universal-user-agent": "^6.0.0" 344 | }, 345 | "engines": { 346 | "node": ">= 18" 347 | } 348 | }, 349 | "node_modules/@octokit/endpoint": { 350 | "version": "9.0.5", 351 | "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", 352 | "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", 353 | "license": "MIT", 354 | "dependencies": { 355 | "@octokit/types": "^13.1.0", 356 | "universal-user-agent": "^6.0.0" 357 | }, 358 | "engines": { 359 | "node": ">= 18" 360 | } 361 | }, 362 | "node_modules/@octokit/graphql": { 363 | "version": "7.1.0", 364 | "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", 365 | "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", 366 | "license": "MIT", 367 | "dependencies": { 368 | "@octokit/request": "^8.3.0", 369 | "@octokit/types": "^13.0.0", 370 | "universal-user-agent": "^6.0.0" 371 | }, 372 | "engines": { 373 | "node": ">= 18" 374 | } 375 | }, 376 | "node_modules/@octokit/openapi-types": { 377 | "version": "23.0.1", 378 | "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", 379 | "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", 380 | "license": "MIT" 381 | }, 382 | "node_modules/@octokit/plugin-paginate-rest": { 383 | "version": "9.2.1", 384 | "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", 385 | "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", 386 | "license": "MIT", 387 | "dependencies": { 388 | "@octokit/types": "^12.6.0" 389 | }, 390 | "engines": { 391 | "node": ">= 18" 392 | }, 393 | "peerDependencies": { 394 | "@octokit/core": "5" 395 | } 396 | }, 397 | "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { 398 | "version": "20.0.0", 399 | "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", 400 | "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", 401 | "license": "MIT" 402 | }, 403 | "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { 404 | "version": "12.6.0", 405 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", 406 | "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", 407 | "license": "MIT", 408 | "dependencies": { 409 | "@octokit/openapi-types": "^20.0.0" 410 | } 411 | }, 412 | "node_modules/@octokit/plugin-rest-endpoint-methods": { 413 | "version": "10.4.1", 414 | "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", 415 | "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", 416 | "license": "MIT", 417 | "dependencies": { 418 | "@octokit/types": "^12.6.0" 419 | }, 420 | "engines": { 421 | "node": ">= 18" 422 | }, 423 | "peerDependencies": { 424 | "@octokit/core": "5" 425 | } 426 | }, 427 | "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { 428 | "version": "20.0.0", 429 | "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", 430 | "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", 431 | "license": "MIT" 432 | }, 433 | "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { 434 | "version": "12.6.0", 435 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", 436 | "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", 437 | "license": "MIT", 438 | "dependencies": { 439 | "@octokit/openapi-types": "^20.0.0" 440 | } 441 | }, 442 | "node_modules/@octokit/request": { 443 | "version": "8.4.0", 444 | "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz", 445 | "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==", 446 | "license": "MIT", 447 | "dependencies": { 448 | "@octokit/endpoint": "^9.0.1", 449 | "@octokit/request-error": "^5.1.0", 450 | "@octokit/types": "^13.1.0", 451 | "universal-user-agent": "^6.0.0" 452 | }, 453 | "engines": { 454 | "node": ">= 18" 455 | } 456 | }, 457 | "node_modules/@octokit/request-error": { 458 | "version": "5.1.0", 459 | "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", 460 | "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", 461 | "license": "MIT", 462 | "dependencies": { 463 | "@octokit/types": "^13.1.0", 464 | "deprecation": "^2.0.0", 465 | "once": "^1.4.0" 466 | }, 467 | "engines": { 468 | "node": ">= 18" 469 | } 470 | }, 471 | "node_modules/@octokit/types": { 472 | "version": "13.8.0", 473 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", 474 | "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", 475 | "license": "MIT", 476 | "dependencies": { 477 | "@octokit/openapi-types": "^23.0.1" 478 | } 479 | }, 480 | "node_modules/@pkgr/core": { 481 | "version": "0.1.1", 482 | "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", 483 | "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", 484 | "dev": true, 485 | "license": "MIT", 486 | "engines": { 487 | "node": "^12.20.0 || ^14.18.0 || >=16.0.0" 488 | }, 489 | "funding": { 490 | "url": "https://opencollective.com/unts" 491 | } 492 | }, 493 | "node_modules/@tsconfig/node20": { 494 | "version": "20.1.4", 495 | "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz", 496 | "integrity": "sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==", 497 | "dev": true, 498 | "license": "MIT" 499 | }, 500 | "node_modules/@types/estree": { 501 | "version": "1.0.6", 502 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 503 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 504 | "dev": true, 505 | "license": "MIT" 506 | }, 507 | "node_modules/@types/fs-extra": { 508 | "version": "11.0.4", 509 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", 510 | "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", 511 | "dev": true, 512 | "license": "MIT", 513 | "dependencies": { 514 | "@types/jsonfile": "*", 515 | "@types/node": "*" 516 | } 517 | }, 518 | "node_modules/@types/json-schema": { 519 | "version": "7.0.15", 520 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", 521 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", 522 | "dev": true, 523 | "license": "MIT" 524 | }, 525 | "node_modules/@types/jsonfile": { 526 | "version": "6.1.4", 527 | "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", 528 | "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", 529 | "dev": true, 530 | "license": "MIT", 531 | "dependencies": { 532 | "@types/node": "*" 533 | } 534 | }, 535 | "node_modules/@types/node": { 536 | "version": "20.17.16", 537 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.16.tgz", 538 | "integrity": "sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw==", 539 | "dev": true, 540 | "license": "MIT", 541 | "dependencies": { 542 | "undici-types": "~6.19.2" 543 | } 544 | }, 545 | "node_modules/@types/shell-quote": { 546 | "version": "1.7.5", 547 | "resolved": "https://registry.npmjs.org/@types/shell-quote/-/shell-quote-1.7.5.tgz", 548 | "integrity": "sha512-+UE8GAGRPbJVQDdxi16dgadcBfQ+KG2vgZhV1+3A1XmHbmwcdwhCUwIdy+d3pAGrbvgRoVSjeI9vOWyq376Yzw==", 549 | "dev": true, 550 | "license": "MIT" 551 | }, 552 | "node_modules/@typescript-eslint/eslint-plugin": { 553 | "version": "8.22.0", 554 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", 555 | "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", 556 | "dev": true, 557 | "license": "MIT", 558 | "dependencies": { 559 | "@eslint-community/regexpp": "^4.10.0", 560 | "@typescript-eslint/scope-manager": "8.22.0", 561 | "@typescript-eslint/type-utils": "8.22.0", 562 | "@typescript-eslint/utils": "8.22.0", 563 | "@typescript-eslint/visitor-keys": "8.22.0", 564 | "graphemer": "^1.4.0", 565 | "ignore": "^5.3.1", 566 | "natural-compare": "^1.4.0", 567 | "ts-api-utils": "^2.0.0" 568 | }, 569 | "engines": { 570 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 571 | }, 572 | "funding": { 573 | "type": "opencollective", 574 | "url": "https://opencollective.com/typescript-eslint" 575 | }, 576 | "peerDependencies": { 577 | "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", 578 | "eslint": "^8.57.0 || ^9.0.0", 579 | "typescript": ">=4.8.4 <5.8.0" 580 | } 581 | }, 582 | "node_modules/@typescript-eslint/parser": { 583 | "version": "8.22.0", 584 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", 585 | "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", 586 | "dev": true, 587 | "license": "MIT", 588 | "dependencies": { 589 | "@typescript-eslint/scope-manager": "8.22.0", 590 | "@typescript-eslint/types": "8.22.0", 591 | "@typescript-eslint/typescript-estree": "8.22.0", 592 | "@typescript-eslint/visitor-keys": "8.22.0", 593 | "debug": "^4.3.4" 594 | }, 595 | "engines": { 596 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 597 | }, 598 | "funding": { 599 | "type": "opencollective", 600 | "url": "https://opencollective.com/typescript-eslint" 601 | }, 602 | "peerDependencies": { 603 | "eslint": "^8.57.0 || ^9.0.0", 604 | "typescript": ">=4.8.4 <5.8.0" 605 | } 606 | }, 607 | "node_modules/@typescript-eslint/scope-manager": { 608 | "version": "8.22.0", 609 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", 610 | "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", 611 | "dev": true, 612 | "license": "MIT", 613 | "dependencies": { 614 | "@typescript-eslint/types": "8.22.0", 615 | "@typescript-eslint/visitor-keys": "8.22.0" 616 | }, 617 | "engines": { 618 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 619 | }, 620 | "funding": { 621 | "type": "opencollective", 622 | "url": "https://opencollective.com/typescript-eslint" 623 | } 624 | }, 625 | "node_modules/@typescript-eslint/type-utils": { 626 | "version": "8.22.0", 627 | "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", 628 | "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", 629 | "dev": true, 630 | "license": "MIT", 631 | "dependencies": { 632 | "@typescript-eslint/typescript-estree": "8.22.0", 633 | "@typescript-eslint/utils": "8.22.0", 634 | "debug": "^4.3.4", 635 | "ts-api-utils": "^2.0.0" 636 | }, 637 | "engines": { 638 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 639 | }, 640 | "funding": { 641 | "type": "opencollective", 642 | "url": "https://opencollective.com/typescript-eslint" 643 | }, 644 | "peerDependencies": { 645 | "eslint": "^8.57.0 || ^9.0.0", 646 | "typescript": ">=4.8.4 <5.8.0" 647 | } 648 | }, 649 | "node_modules/@typescript-eslint/types": { 650 | "version": "8.22.0", 651 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", 652 | "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", 653 | "dev": true, 654 | "license": "MIT", 655 | "engines": { 656 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 657 | }, 658 | "funding": { 659 | "type": "opencollective", 660 | "url": "https://opencollective.com/typescript-eslint" 661 | } 662 | }, 663 | "node_modules/@typescript-eslint/typescript-estree": { 664 | "version": "8.22.0", 665 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", 666 | "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", 667 | "dev": true, 668 | "license": "MIT", 669 | "dependencies": { 670 | "@typescript-eslint/types": "8.22.0", 671 | "@typescript-eslint/visitor-keys": "8.22.0", 672 | "debug": "^4.3.4", 673 | "fast-glob": "^3.3.2", 674 | "is-glob": "^4.0.3", 675 | "minimatch": "^9.0.4", 676 | "semver": "^7.6.0", 677 | "ts-api-utils": "^2.0.0" 678 | }, 679 | "engines": { 680 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 681 | }, 682 | "funding": { 683 | "type": "opencollective", 684 | "url": "https://opencollective.com/typescript-eslint" 685 | }, 686 | "peerDependencies": { 687 | "typescript": ">=4.8.4 <5.8.0" 688 | } 689 | }, 690 | "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { 691 | "version": "2.0.1", 692 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 693 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 694 | "dev": true, 695 | "license": "MIT", 696 | "dependencies": { 697 | "balanced-match": "^1.0.0" 698 | } 699 | }, 700 | "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { 701 | "version": "9.0.5", 702 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", 703 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 704 | "dev": true, 705 | "license": "ISC", 706 | "dependencies": { 707 | "brace-expansion": "^2.0.1" 708 | }, 709 | "engines": { 710 | "node": ">=16 || 14 >=14.17" 711 | }, 712 | "funding": { 713 | "url": "https://github.com/sponsors/isaacs" 714 | } 715 | }, 716 | "node_modules/@typescript-eslint/utils": { 717 | "version": "8.22.0", 718 | "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", 719 | "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", 720 | "dev": true, 721 | "license": "MIT", 722 | "dependencies": { 723 | "@eslint-community/eslint-utils": "^4.4.0", 724 | "@typescript-eslint/scope-manager": "8.22.0", 725 | "@typescript-eslint/types": "8.22.0", 726 | "@typescript-eslint/typescript-estree": "8.22.0" 727 | }, 728 | "engines": { 729 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 730 | }, 731 | "funding": { 732 | "type": "opencollective", 733 | "url": "https://opencollective.com/typescript-eslint" 734 | }, 735 | "peerDependencies": { 736 | "eslint": "^8.57.0 || ^9.0.0", 737 | "typescript": ">=4.8.4 <5.8.0" 738 | } 739 | }, 740 | "node_modules/@typescript-eslint/visitor-keys": { 741 | "version": "8.22.0", 742 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", 743 | "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", 744 | "dev": true, 745 | "license": "MIT", 746 | "dependencies": { 747 | "@typescript-eslint/types": "8.22.0", 748 | "eslint-visitor-keys": "^4.2.0" 749 | }, 750 | "engines": { 751 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 752 | }, 753 | "funding": { 754 | "type": "opencollective", 755 | "url": "https://opencollective.com/typescript-eslint" 756 | } 757 | }, 758 | "node_modules/@vercel/ncc": { 759 | "version": "0.38.3", 760 | "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.3.tgz", 761 | "integrity": "sha512-rnK6hJBS6mwc+Bkab+PGPs9OiS0i/3kdTO+CkI8V0/VrW3vmz7O2Pxjw/owOlmo6PKEIxRSeZKv/kuL9itnpYA==", 762 | "dev": true, 763 | "license": "MIT", 764 | "bin": { 765 | "ncc": "dist/ncc/cli.js" 766 | } 767 | }, 768 | "node_modules/acorn": { 769 | "version": "8.14.0", 770 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 771 | "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 772 | "dev": true, 773 | "license": "MIT", 774 | "bin": { 775 | "acorn": "bin/acorn" 776 | }, 777 | "engines": { 778 | "node": ">=0.4.0" 779 | } 780 | }, 781 | "node_modules/acorn-jsx": { 782 | "version": "5.3.2", 783 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 784 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 785 | "dev": true, 786 | "license": "MIT", 787 | "peerDependencies": { 788 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 789 | } 790 | }, 791 | "node_modules/ajv": { 792 | "version": "6.12.6", 793 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 794 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 795 | "dev": true, 796 | "license": "MIT", 797 | "dependencies": { 798 | "fast-deep-equal": "^3.1.1", 799 | "fast-json-stable-stringify": "^2.0.0", 800 | "json-schema-traverse": "^0.4.1", 801 | "uri-js": "^4.2.2" 802 | }, 803 | "funding": { 804 | "type": "github", 805 | "url": "https://github.com/sponsors/epoberezkin" 806 | } 807 | }, 808 | "node_modules/ansi-styles": { 809 | "version": "4.3.0", 810 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 811 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 812 | "dev": true, 813 | "license": "MIT", 814 | "dependencies": { 815 | "color-convert": "^2.0.1" 816 | }, 817 | "engines": { 818 | "node": ">=8" 819 | }, 820 | "funding": { 821 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 822 | } 823 | }, 824 | "node_modules/argparse": { 825 | "version": "2.0.1", 826 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 827 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 828 | "dev": true, 829 | "license": "Python-2.0" 830 | }, 831 | "node_modules/balanced-match": { 832 | "version": "1.0.2", 833 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 834 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 835 | "dev": true, 836 | "license": "MIT" 837 | }, 838 | "node_modules/before-after-hook": { 839 | "version": "2.2.3", 840 | "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", 841 | "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", 842 | "license": "Apache-2.0" 843 | }, 844 | "node_modules/brace-expansion": { 845 | "version": "1.1.11", 846 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 847 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 848 | "dev": true, 849 | "license": "MIT", 850 | "dependencies": { 851 | "balanced-match": "^1.0.0", 852 | "concat-map": "0.0.1" 853 | } 854 | }, 855 | "node_modules/braces": { 856 | "version": "3.0.3", 857 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 858 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 859 | "dev": true, 860 | "license": "MIT", 861 | "dependencies": { 862 | "fill-range": "^7.1.1" 863 | }, 864 | "engines": { 865 | "node": ">=8" 866 | } 867 | }, 868 | "node_modules/callsites": { 869 | "version": "3.1.0", 870 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 871 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 872 | "dev": true, 873 | "license": "MIT", 874 | "engines": { 875 | "node": ">=6" 876 | } 877 | }, 878 | "node_modules/chalk": { 879 | "version": "4.1.2", 880 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 881 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 882 | "dev": true, 883 | "license": "MIT", 884 | "dependencies": { 885 | "ansi-styles": "^4.1.0", 886 | "supports-color": "^7.1.0" 887 | }, 888 | "engines": { 889 | "node": ">=10" 890 | }, 891 | "funding": { 892 | "url": "https://github.com/chalk/chalk?sponsor=1" 893 | } 894 | }, 895 | "node_modules/color-convert": { 896 | "version": "2.0.1", 897 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 898 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 899 | "dev": true, 900 | "license": "MIT", 901 | "dependencies": { 902 | "color-name": "~1.1.4" 903 | }, 904 | "engines": { 905 | "node": ">=7.0.0" 906 | } 907 | }, 908 | "node_modules/color-name": { 909 | "version": "1.1.4", 910 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 911 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 912 | "dev": true, 913 | "license": "MIT" 914 | }, 915 | "node_modules/compare-versions": { 916 | "version": "6.1.1", 917 | "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", 918 | "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", 919 | "license": "MIT" 920 | }, 921 | "node_modules/concat-map": { 922 | "version": "0.0.1", 923 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 924 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 925 | "dev": true, 926 | "license": "MIT" 927 | }, 928 | "node_modules/cross-spawn": { 929 | "version": "7.0.6", 930 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 931 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 932 | "dev": true, 933 | "license": "MIT", 934 | "dependencies": { 935 | "path-key": "^3.1.0", 936 | "shebang-command": "^2.0.0", 937 | "which": "^2.0.1" 938 | }, 939 | "engines": { 940 | "node": ">= 8" 941 | } 942 | }, 943 | "node_modules/debug": { 944 | "version": "4.4.0", 945 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 946 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 947 | "dev": true, 948 | "license": "MIT", 949 | "dependencies": { 950 | "ms": "^2.1.3" 951 | }, 952 | "engines": { 953 | "node": ">=6.0" 954 | }, 955 | "peerDependenciesMeta": { 956 | "supports-color": { 957 | "optional": true 958 | } 959 | } 960 | }, 961 | "node_modules/deep-is": { 962 | "version": "0.1.4", 963 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 964 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 965 | "dev": true, 966 | "license": "MIT" 967 | }, 968 | "node_modules/deprecation": { 969 | "version": "2.3.1", 970 | "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", 971 | "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", 972 | "license": "ISC" 973 | }, 974 | "node_modules/escape-string-regexp": { 975 | "version": "4.0.0", 976 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 977 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 978 | "dev": true, 979 | "license": "MIT", 980 | "engines": { 981 | "node": ">=10" 982 | }, 983 | "funding": { 984 | "url": "https://github.com/sponsors/sindresorhus" 985 | } 986 | }, 987 | "node_modules/eslint": { 988 | "version": "9.19.0", 989 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", 990 | "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", 991 | "dev": true, 992 | "license": "MIT", 993 | "dependencies": { 994 | "@eslint-community/eslint-utils": "^4.2.0", 995 | "@eslint-community/regexpp": "^4.12.1", 996 | "@eslint/config-array": "^0.19.0", 997 | "@eslint/core": "^0.10.0", 998 | "@eslint/eslintrc": "^3.2.0", 999 | "@eslint/js": "9.19.0", 1000 | "@eslint/plugin-kit": "^0.2.5", 1001 | "@humanfs/node": "^0.16.6", 1002 | "@humanwhocodes/module-importer": "^1.0.1", 1003 | "@humanwhocodes/retry": "^0.4.1", 1004 | "@types/estree": "^1.0.6", 1005 | "@types/json-schema": "^7.0.15", 1006 | "ajv": "^6.12.4", 1007 | "chalk": "^4.0.0", 1008 | "cross-spawn": "^7.0.6", 1009 | "debug": "^4.3.2", 1010 | "escape-string-regexp": "^4.0.0", 1011 | "eslint-scope": "^8.2.0", 1012 | "eslint-visitor-keys": "^4.2.0", 1013 | "espree": "^10.3.0", 1014 | "esquery": "^1.5.0", 1015 | "esutils": "^2.0.2", 1016 | "fast-deep-equal": "^3.1.3", 1017 | "file-entry-cache": "^8.0.0", 1018 | "find-up": "^5.0.0", 1019 | "glob-parent": "^6.0.2", 1020 | "ignore": "^5.2.0", 1021 | "imurmurhash": "^0.1.4", 1022 | "is-glob": "^4.0.0", 1023 | "json-stable-stringify-without-jsonify": "^1.0.1", 1024 | "lodash.merge": "^4.6.2", 1025 | "minimatch": "^3.1.2", 1026 | "natural-compare": "^1.4.0", 1027 | "optionator": "^0.9.3" 1028 | }, 1029 | "bin": { 1030 | "eslint": "bin/eslint.js" 1031 | }, 1032 | "engines": { 1033 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1034 | }, 1035 | "funding": { 1036 | "url": "https://eslint.org/donate" 1037 | }, 1038 | "peerDependencies": { 1039 | "jiti": "*" 1040 | }, 1041 | "peerDependenciesMeta": { 1042 | "jiti": { 1043 | "optional": true 1044 | } 1045 | } 1046 | }, 1047 | "node_modules/eslint-plugin-prettier": { 1048 | "version": "5.2.3", 1049 | "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", 1050 | "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", 1051 | "dev": true, 1052 | "license": "MIT", 1053 | "dependencies": { 1054 | "prettier-linter-helpers": "^1.0.0", 1055 | "synckit": "^0.9.1" 1056 | }, 1057 | "engines": { 1058 | "node": "^14.18.0 || >=16.0.0" 1059 | }, 1060 | "funding": { 1061 | "url": "https://opencollective.com/eslint-plugin-prettier" 1062 | }, 1063 | "peerDependencies": { 1064 | "@types/eslint": ">=8.0.0", 1065 | "eslint": ">=8.0.0", 1066 | "eslint-config-prettier": "*", 1067 | "prettier": ">=3.0.0" 1068 | }, 1069 | "peerDependenciesMeta": { 1070 | "@types/eslint": { 1071 | "optional": true 1072 | }, 1073 | "eslint-config-prettier": { 1074 | "optional": true 1075 | } 1076 | } 1077 | }, 1078 | "node_modules/eslint-scope": { 1079 | "version": "8.2.0", 1080 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", 1081 | "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", 1082 | "dev": true, 1083 | "license": "BSD-2-Clause", 1084 | "dependencies": { 1085 | "esrecurse": "^4.3.0", 1086 | "estraverse": "^5.2.0" 1087 | }, 1088 | "engines": { 1089 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1090 | }, 1091 | "funding": { 1092 | "url": "https://opencollective.com/eslint" 1093 | } 1094 | }, 1095 | "node_modules/eslint-visitor-keys": { 1096 | "version": "4.2.0", 1097 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", 1098 | "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", 1099 | "dev": true, 1100 | "license": "Apache-2.0", 1101 | "engines": { 1102 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1103 | }, 1104 | "funding": { 1105 | "url": "https://opencollective.com/eslint" 1106 | } 1107 | }, 1108 | "node_modules/espree": { 1109 | "version": "10.3.0", 1110 | "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", 1111 | "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", 1112 | "dev": true, 1113 | "license": "BSD-2-Clause", 1114 | "dependencies": { 1115 | "acorn": "^8.14.0", 1116 | "acorn-jsx": "^5.3.2", 1117 | "eslint-visitor-keys": "^4.2.0" 1118 | }, 1119 | "engines": { 1120 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1121 | }, 1122 | "funding": { 1123 | "url": "https://opencollective.com/eslint" 1124 | } 1125 | }, 1126 | "node_modules/esquery": { 1127 | "version": "1.6.0", 1128 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", 1129 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", 1130 | "dev": true, 1131 | "license": "BSD-3-Clause", 1132 | "dependencies": { 1133 | "estraverse": "^5.1.0" 1134 | }, 1135 | "engines": { 1136 | "node": ">=0.10" 1137 | } 1138 | }, 1139 | "node_modules/esrecurse": { 1140 | "version": "4.3.0", 1141 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1142 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1143 | "dev": true, 1144 | "license": "BSD-2-Clause", 1145 | "dependencies": { 1146 | "estraverse": "^5.2.0" 1147 | }, 1148 | "engines": { 1149 | "node": ">=4.0" 1150 | } 1151 | }, 1152 | "node_modules/estraverse": { 1153 | "version": "5.3.0", 1154 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1155 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1156 | "dev": true, 1157 | "license": "BSD-2-Clause", 1158 | "engines": { 1159 | "node": ">=4.0" 1160 | } 1161 | }, 1162 | "node_modules/esutils": { 1163 | "version": "2.0.3", 1164 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1165 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1166 | "dev": true, 1167 | "license": "BSD-2-Clause", 1168 | "engines": { 1169 | "node": ">=0.10.0" 1170 | } 1171 | }, 1172 | "node_modules/fast-deep-equal": { 1173 | "version": "3.1.3", 1174 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1175 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1176 | "dev": true, 1177 | "license": "MIT" 1178 | }, 1179 | "node_modules/fast-diff": { 1180 | "version": "1.3.0", 1181 | "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", 1182 | "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", 1183 | "dev": true, 1184 | "license": "Apache-2.0" 1185 | }, 1186 | "node_modules/fast-glob": { 1187 | "version": "3.3.3", 1188 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", 1189 | "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", 1190 | "dev": true, 1191 | "license": "MIT", 1192 | "dependencies": { 1193 | "@nodelib/fs.stat": "^2.0.2", 1194 | "@nodelib/fs.walk": "^1.2.3", 1195 | "glob-parent": "^5.1.2", 1196 | "merge2": "^1.3.0", 1197 | "micromatch": "^4.0.8" 1198 | }, 1199 | "engines": { 1200 | "node": ">=8.6.0" 1201 | } 1202 | }, 1203 | "node_modules/fast-glob/node_modules/glob-parent": { 1204 | "version": "5.1.2", 1205 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1206 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1207 | "dev": true, 1208 | "license": "ISC", 1209 | "dependencies": { 1210 | "is-glob": "^4.0.1" 1211 | }, 1212 | "engines": { 1213 | "node": ">= 6" 1214 | } 1215 | }, 1216 | "node_modules/fast-json-stable-stringify": { 1217 | "version": "2.1.0", 1218 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1219 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1220 | "dev": true, 1221 | "license": "MIT" 1222 | }, 1223 | "node_modules/fast-levenshtein": { 1224 | "version": "2.0.6", 1225 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1226 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 1227 | "dev": true, 1228 | "license": "MIT" 1229 | }, 1230 | "node_modules/fastq": { 1231 | "version": "1.19.0", 1232 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", 1233 | "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", 1234 | "dev": true, 1235 | "license": "ISC", 1236 | "dependencies": { 1237 | "reusify": "^1.0.4" 1238 | } 1239 | }, 1240 | "node_modules/file-entry-cache": { 1241 | "version": "8.0.0", 1242 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", 1243 | "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", 1244 | "dev": true, 1245 | "license": "MIT", 1246 | "dependencies": { 1247 | "flat-cache": "^4.0.0" 1248 | }, 1249 | "engines": { 1250 | "node": ">=16.0.0" 1251 | } 1252 | }, 1253 | "node_modules/fill-range": { 1254 | "version": "7.1.1", 1255 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1256 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1257 | "dev": true, 1258 | "license": "MIT", 1259 | "dependencies": { 1260 | "to-regex-range": "^5.0.1" 1261 | }, 1262 | "engines": { 1263 | "node": ">=8" 1264 | } 1265 | }, 1266 | "node_modules/find-up": { 1267 | "version": "5.0.0", 1268 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1269 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1270 | "dev": true, 1271 | "license": "MIT", 1272 | "dependencies": { 1273 | "locate-path": "^6.0.0", 1274 | "path-exists": "^4.0.0" 1275 | }, 1276 | "engines": { 1277 | "node": ">=10" 1278 | }, 1279 | "funding": { 1280 | "url": "https://github.com/sponsors/sindresorhus" 1281 | } 1282 | }, 1283 | "node_modules/flat-cache": { 1284 | "version": "4.0.1", 1285 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", 1286 | "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", 1287 | "dev": true, 1288 | "license": "MIT", 1289 | "dependencies": { 1290 | "flatted": "^3.2.9", 1291 | "keyv": "^4.5.4" 1292 | }, 1293 | "engines": { 1294 | "node": ">=16" 1295 | } 1296 | }, 1297 | "node_modules/flatted": { 1298 | "version": "3.3.2", 1299 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", 1300 | "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", 1301 | "dev": true, 1302 | "license": "ISC" 1303 | }, 1304 | "node_modules/fs-extra": { 1305 | "version": "11.3.0", 1306 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", 1307 | "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", 1308 | "license": "MIT", 1309 | "dependencies": { 1310 | "graceful-fs": "^4.2.0", 1311 | "jsonfile": "^6.0.1", 1312 | "universalify": "^2.0.0" 1313 | }, 1314 | "engines": { 1315 | "node": ">=14.14" 1316 | } 1317 | }, 1318 | "node_modules/glob-parent": { 1319 | "version": "6.0.2", 1320 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 1321 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1322 | "dev": true, 1323 | "license": "ISC", 1324 | "dependencies": { 1325 | "is-glob": "^4.0.3" 1326 | }, 1327 | "engines": { 1328 | "node": ">=10.13.0" 1329 | } 1330 | }, 1331 | "node_modules/globals": { 1332 | "version": "14.0.0", 1333 | "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", 1334 | "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", 1335 | "dev": true, 1336 | "license": "MIT", 1337 | "engines": { 1338 | "node": ">=18" 1339 | }, 1340 | "funding": { 1341 | "url": "https://github.com/sponsors/sindresorhus" 1342 | } 1343 | }, 1344 | "node_modules/graceful-fs": { 1345 | "version": "4.2.11", 1346 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1347 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1348 | "license": "ISC" 1349 | }, 1350 | "node_modules/graphemer": { 1351 | "version": "1.4.0", 1352 | "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", 1353 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", 1354 | "dev": true, 1355 | "license": "MIT" 1356 | }, 1357 | "node_modules/handlebars": { 1358 | "version": "4.7.8", 1359 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", 1360 | "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", 1361 | "license": "MIT", 1362 | "dependencies": { 1363 | "minimist": "^1.2.5", 1364 | "neo-async": "^2.6.2", 1365 | "source-map": "^0.6.1", 1366 | "wordwrap": "^1.0.0" 1367 | }, 1368 | "bin": { 1369 | "handlebars": "bin/handlebars" 1370 | }, 1371 | "engines": { 1372 | "node": ">=0.4.7" 1373 | }, 1374 | "optionalDependencies": { 1375 | "uglify-js": "^3.1.4" 1376 | } 1377 | }, 1378 | "node_modules/has-flag": { 1379 | "version": "4.0.0", 1380 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1381 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1382 | "dev": true, 1383 | "license": "MIT", 1384 | "engines": { 1385 | "node": ">=8" 1386 | } 1387 | }, 1388 | "node_modules/ignore": { 1389 | "version": "5.3.2", 1390 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 1391 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 1392 | "dev": true, 1393 | "license": "MIT", 1394 | "engines": { 1395 | "node": ">= 4" 1396 | } 1397 | }, 1398 | "node_modules/import-fresh": { 1399 | "version": "3.3.0", 1400 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1401 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1402 | "dev": true, 1403 | "license": "MIT", 1404 | "dependencies": { 1405 | "parent-module": "^1.0.0", 1406 | "resolve-from": "^4.0.0" 1407 | }, 1408 | "engines": { 1409 | "node": ">=6" 1410 | }, 1411 | "funding": { 1412 | "url": "https://github.com/sponsors/sindresorhus" 1413 | } 1414 | }, 1415 | "node_modules/imurmurhash": { 1416 | "version": "0.1.4", 1417 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1418 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 1419 | "dev": true, 1420 | "license": "MIT", 1421 | "engines": { 1422 | "node": ">=0.8.19" 1423 | } 1424 | }, 1425 | "node_modules/is-extglob": { 1426 | "version": "2.1.1", 1427 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1428 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1429 | "dev": true, 1430 | "license": "MIT", 1431 | "engines": { 1432 | "node": ">=0.10.0" 1433 | } 1434 | }, 1435 | "node_modules/is-glob": { 1436 | "version": "4.0.3", 1437 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1438 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1439 | "dev": true, 1440 | "license": "MIT", 1441 | "dependencies": { 1442 | "is-extglob": "^2.1.1" 1443 | }, 1444 | "engines": { 1445 | "node": ">=0.10.0" 1446 | } 1447 | }, 1448 | "node_modules/is-number": { 1449 | "version": "7.0.0", 1450 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1451 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1452 | "dev": true, 1453 | "license": "MIT", 1454 | "engines": { 1455 | "node": ">=0.12.0" 1456 | } 1457 | }, 1458 | "node_modules/isexe": { 1459 | "version": "2.0.0", 1460 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1461 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1462 | "dev": true, 1463 | "license": "ISC" 1464 | }, 1465 | "node_modules/js-yaml": { 1466 | "version": "4.1.0", 1467 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1468 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1469 | "dev": true, 1470 | "license": "MIT", 1471 | "dependencies": { 1472 | "argparse": "^2.0.1" 1473 | }, 1474 | "bin": { 1475 | "js-yaml": "bin/js-yaml.js" 1476 | } 1477 | }, 1478 | "node_modules/json-buffer": { 1479 | "version": "3.0.1", 1480 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 1481 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 1482 | "dev": true, 1483 | "license": "MIT" 1484 | }, 1485 | "node_modules/json-schema-traverse": { 1486 | "version": "0.4.1", 1487 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1488 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1489 | "dev": true, 1490 | "license": "MIT" 1491 | }, 1492 | "node_modules/json-stable-stringify-without-jsonify": { 1493 | "version": "1.0.1", 1494 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1495 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 1496 | "dev": true, 1497 | "license": "MIT" 1498 | }, 1499 | "node_modules/jsonfile": { 1500 | "version": "6.1.0", 1501 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 1502 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 1503 | "license": "MIT", 1504 | "dependencies": { 1505 | "universalify": "^2.0.0" 1506 | }, 1507 | "optionalDependencies": { 1508 | "graceful-fs": "^4.1.6" 1509 | } 1510 | }, 1511 | "node_modules/keyv": { 1512 | "version": "4.5.4", 1513 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", 1514 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", 1515 | "dev": true, 1516 | "license": "MIT", 1517 | "dependencies": { 1518 | "json-buffer": "3.0.1" 1519 | } 1520 | }, 1521 | "node_modules/levn": { 1522 | "version": "0.4.1", 1523 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1524 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1525 | "dev": true, 1526 | "license": "MIT", 1527 | "dependencies": { 1528 | "prelude-ls": "^1.2.1", 1529 | "type-check": "~0.4.0" 1530 | }, 1531 | "engines": { 1532 | "node": ">= 0.8.0" 1533 | } 1534 | }, 1535 | "node_modules/locate-path": { 1536 | "version": "6.0.0", 1537 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1538 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1539 | "dev": true, 1540 | "license": "MIT", 1541 | "dependencies": { 1542 | "p-locate": "^5.0.0" 1543 | }, 1544 | "engines": { 1545 | "node": ">=10" 1546 | }, 1547 | "funding": { 1548 | "url": "https://github.com/sponsors/sindresorhus" 1549 | } 1550 | }, 1551 | "node_modules/lodash.merge": { 1552 | "version": "4.6.2", 1553 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1554 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1555 | "dev": true, 1556 | "license": "MIT" 1557 | }, 1558 | "node_modules/merge2": { 1559 | "version": "1.4.1", 1560 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1561 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1562 | "dev": true, 1563 | "license": "MIT", 1564 | "engines": { 1565 | "node": ">= 8" 1566 | } 1567 | }, 1568 | "node_modules/micromatch": { 1569 | "version": "4.0.8", 1570 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 1571 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 1572 | "dev": true, 1573 | "license": "MIT", 1574 | "dependencies": { 1575 | "braces": "^3.0.3", 1576 | "picomatch": "^2.3.1" 1577 | }, 1578 | "engines": { 1579 | "node": ">=8.6" 1580 | } 1581 | }, 1582 | "node_modules/minimatch": { 1583 | "version": "3.1.2", 1584 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1585 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1586 | "dev": true, 1587 | "license": "ISC", 1588 | "dependencies": { 1589 | "brace-expansion": "^1.1.7" 1590 | }, 1591 | "engines": { 1592 | "node": "*" 1593 | } 1594 | }, 1595 | "node_modules/minimist": { 1596 | "version": "1.2.8", 1597 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1598 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1599 | "license": "MIT", 1600 | "funding": { 1601 | "url": "https://github.com/sponsors/ljharb" 1602 | } 1603 | }, 1604 | "node_modules/ms": { 1605 | "version": "2.1.3", 1606 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1607 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1608 | "dev": true, 1609 | "license": "MIT" 1610 | }, 1611 | "node_modules/natural-compare": { 1612 | "version": "1.4.0", 1613 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1614 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 1615 | "dev": true, 1616 | "license": "MIT" 1617 | }, 1618 | "node_modules/neo-async": { 1619 | "version": "2.6.2", 1620 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 1621 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", 1622 | "license": "MIT" 1623 | }, 1624 | "node_modules/once": { 1625 | "version": "1.4.0", 1626 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1627 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1628 | "license": "ISC", 1629 | "dependencies": { 1630 | "wrappy": "1" 1631 | } 1632 | }, 1633 | "node_modules/optionator": { 1634 | "version": "0.9.4", 1635 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", 1636 | "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", 1637 | "dev": true, 1638 | "license": "MIT", 1639 | "dependencies": { 1640 | "deep-is": "^0.1.3", 1641 | "fast-levenshtein": "^2.0.6", 1642 | "levn": "^0.4.1", 1643 | "prelude-ls": "^1.2.1", 1644 | "type-check": "^0.4.0", 1645 | "word-wrap": "^1.2.5" 1646 | }, 1647 | "engines": { 1648 | "node": ">= 0.8.0" 1649 | } 1650 | }, 1651 | "node_modules/p-limit": { 1652 | "version": "3.1.0", 1653 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1654 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1655 | "dev": true, 1656 | "license": "MIT", 1657 | "dependencies": { 1658 | "yocto-queue": "^0.1.0" 1659 | }, 1660 | "engines": { 1661 | "node": ">=10" 1662 | }, 1663 | "funding": { 1664 | "url": "https://github.com/sponsors/sindresorhus" 1665 | } 1666 | }, 1667 | "node_modules/p-locate": { 1668 | "version": "5.0.0", 1669 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1670 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1671 | "dev": true, 1672 | "license": "MIT", 1673 | "dependencies": { 1674 | "p-limit": "^3.0.2" 1675 | }, 1676 | "engines": { 1677 | "node": ">=10" 1678 | }, 1679 | "funding": { 1680 | "url": "https://github.com/sponsors/sindresorhus" 1681 | } 1682 | }, 1683 | "node_modules/parent-module": { 1684 | "version": "1.0.1", 1685 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1686 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1687 | "dev": true, 1688 | "license": "MIT", 1689 | "dependencies": { 1690 | "callsites": "^3.0.0" 1691 | }, 1692 | "engines": { 1693 | "node": ">=6" 1694 | } 1695 | }, 1696 | "node_modules/path-exists": { 1697 | "version": "4.0.0", 1698 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1699 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1700 | "dev": true, 1701 | "license": "MIT", 1702 | "engines": { 1703 | "node": ">=8" 1704 | } 1705 | }, 1706 | "node_modules/path-key": { 1707 | "version": "3.1.1", 1708 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1709 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1710 | "dev": true, 1711 | "license": "MIT", 1712 | "engines": { 1713 | "node": ">=8" 1714 | } 1715 | }, 1716 | "node_modules/picomatch": { 1717 | "version": "2.3.1", 1718 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1719 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1720 | "dev": true, 1721 | "license": "MIT", 1722 | "engines": { 1723 | "node": ">=8.6" 1724 | }, 1725 | "funding": { 1726 | "url": "https://github.com/sponsors/jonschlinkert" 1727 | } 1728 | }, 1729 | "node_modules/prelude-ls": { 1730 | "version": "1.2.1", 1731 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1732 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1733 | "dev": true, 1734 | "license": "MIT", 1735 | "engines": { 1736 | "node": ">= 0.8.0" 1737 | } 1738 | }, 1739 | "node_modules/prettier": { 1740 | "version": "3.4.2", 1741 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", 1742 | "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", 1743 | "dev": true, 1744 | "license": "MIT", 1745 | "bin": { 1746 | "prettier": "bin/prettier.cjs" 1747 | }, 1748 | "engines": { 1749 | "node": ">=14" 1750 | }, 1751 | "funding": { 1752 | "url": "https://github.com/prettier/prettier?sponsor=1" 1753 | } 1754 | }, 1755 | "node_modules/prettier-linter-helpers": { 1756 | "version": "1.0.0", 1757 | "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", 1758 | "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", 1759 | "dev": true, 1760 | "license": "MIT", 1761 | "dependencies": { 1762 | "fast-diff": "^1.1.2" 1763 | }, 1764 | "engines": { 1765 | "node": ">=6.0.0" 1766 | } 1767 | }, 1768 | "node_modules/punycode": { 1769 | "version": "2.3.1", 1770 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 1771 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 1772 | "dev": true, 1773 | "license": "MIT", 1774 | "engines": { 1775 | "node": ">=6" 1776 | } 1777 | }, 1778 | "node_modules/queue-microtask": { 1779 | "version": "1.2.3", 1780 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1781 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1782 | "dev": true, 1783 | "funding": [ 1784 | { 1785 | "type": "github", 1786 | "url": "https://github.com/sponsors/feross" 1787 | }, 1788 | { 1789 | "type": "patreon", 1790 | "url": "https://www.patreon.com/feross" 1791 | }, 1792 | { 1793 | "type": "consulting", 1794 | "url": "https://feross.org/support" 1795 | } 1796 | ], 1797 | "license": "MIT" 1798 | }, 1799 | "node_modules/resolve-from": { 1800 | "version": "4.0.0", 1801 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1802 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1803 | "dev": true, 1804 | "license": "MIT", 1805 | "engines": { 1806 | "node": ">=4" 1807 | } 1808 | }, 1809 | "node_modules/reusify": { 1810 | "version": "1.0.4", 1811 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1812 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1813 | "dev": true, 1814 | "license": "MIT", 1815 | "engines": { 1816 | "iojs": ">=1.0.0", 1817 | "node": ">=0.10.0" 1818 | } 1819 | }, 1820 | "node_modules/run-parallel": { 1821 | "version": "1.2.0", 1822 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1823 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1824 | "dev": true, 1825 | "funding": [ 1826 | { 1827 | "type": "github", 1828 | "url": "https://github.com/sponsors/feross" 1829 | }, 1830 | { 1831 | "type": "patreon", 1832 | "url": "https://www.patreon.com/feross" 1833 | }, 1834 | { 1835 | "type": "consulting", 1836 | "url": "https://feross.org/support" 1837 | } 1838 | ], 1839 | "license": "MIT", 1840 | "dependencies": { 1841 | "queue-microtask": "^1.2.2" 1842 | } 1843 | }, 1844 | "node_modules/semver": { 1845 | "version": "7.7.0", 1846 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", 1847 | "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", 1848 | "dev": true, 1849 | "license": "ISC", 1850 | "bin": { 1851 | "semver": "bin/semver.js" 1852 | }, 1853 | "engines": { 1854 | "node": ">=10" 1855 | } 1856 | }, 1857 | "node_modules/shebang-command": { 1858 | "version": "2.0.0", 1859 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1860 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1861 | "dev": true, 1862 | "license": "MIT", 1863 | "dependencies": { 1864 | "shebang-regex": "^3.0.0" 1865 | }, 1866 | "engines": { 1867 | "node": ">=8" 1868 | } 1869 | }, 1870 | "node_modules/shebang-regex": { 1871 | "version": "3.0.0", 1872 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1873 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1874 | "dev": true, 1875 | "license": "MIT", 1876 | "engines": { 1877 | "node": ">=8" 1878 | } 1879 | }, 1880 | "node_modules/shell-quote": { 1881 | "version": "1.8.2", 1882 | "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", 1883 | "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", 1884 | "license": "MIT", 1885 | "engines": { 1886 | "node": ">= 0.4" 1887 | }, 1888 | "funding": { 1889 | "url": "https://github.com/sponsors/ljharb" 1890 | } 1891 | }, 1892 | "node_modules/source-map": { 1893 | "version": "0.6.1", 1894 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1895 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1896 | "license": "BSD-3-Clause", 1897 | "engines": { 1898 | "node": ">=0.10.0" 1899 | } 1900 | }, 1901 | "node_modules/strip-json-comments": { 1902 | "version": "3.1.1", 1903 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1904 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1905 | "dev": true, 1906 | "license": "MIT", 1907 | "engines": { 1908 | "node": ">=8" 1909 | }, 1910 | "funding": { 1911 | "url": "https://github.com/sponsors/sindresorhus" 1912 | } 1913 | }, 1914 | "node_modules/supports-color": { 1915 | "version": "7.2.0", 1916 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1917 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1918 | "dev": true, 1919 | "license": "MIT", 1920 | "dependencies": { 1921 | "has-flag": "^4.0.0" 1922 | }, 1923 | "engines": { 1924 | "node": ">=8" 1925 | } 1926 | }, 1927 | "node_modules/synckit": { 1928 | "version": "0.9.2", 1929 | "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", 1930 | "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", 1931 | "dev": true, 1932 | "license": "MIT", 1933 | "dependencies": { 1934 | "@pkgr/core": "^0.1.0", 1935 | "tslib": "^2.6.2" 1936 | }, 1937 | "engines": { 1938 | "node": "^14.18.0 || >=16.0.0" 1939 | }, 1940 | "funding": { 1941 | "url": "https://opencollective.com/unts" 1942 | } 1943 | }, 1944 | "node_modules/to-regex-range": { 1945 | "version": "5.0.1", 1946 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1947 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1948 | "dev": true, 1949 | "license": "MIT", 1950 | "dependencies": { 1951 | "is-number": "^7.0.0" 1952 | }, 1953 | "engines": { 1954 | "node": ">=8.0" 1955 | } 1956 | }, 1957 | "node_modules/ts-api-utils": { 1958 | "version": "2.0.1", 1959 | "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", 1960 | "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", 1961 | "dev": true, 1962 | "license": "MIT", 1963 | "engines": { 1964 | "node": ">=18.12" 1965 | }, 1966 | "peerDependencies": { 1967 | "typescript": ">=4.8.4" 1968 | } 1969 | }, 1970 | "node_modules/tslib": { 1971 | "version": "2.8.1", 1972 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 1973 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 1974 | "dev": true, 1975 | "license": "0BSD" 1976 | }, 1977 | "node_modules/tunnel": { 1978 | "version": "0.0.6", 1979 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 1980 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 1981 | "license": "MIT", 1982 | "engines": { 1983 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3" 1984 | } 1985 | }, 1986 | "node_modules/type-check": { 1987 | "version": "0.4.0", 1988 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1989 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1990 | "dev": true, 1991 | "license": "MIT", 1992 | "dependencies": { 1993 | "prelude-ls": "^1.2.1" 1994 | }, 1995 | "engines": { 1996 | "node": ">= 0.8.0" 1997 | } 1998 | }, 1999 | "node_modules/typescript": { 2000 | "version": "5.7.3", 2001 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", 2002 | "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", 2003 | "dev": true, 2004 | "license": "Apache-2.0", 2005 | "bin": { 2006 | "tsc": "bin/tsc", 2007 | "tsserver": "bin/tsserver" 2008 | }, 2009 | "engines": { 2010 | "node": ">=14.17" 2011 | } 2012 | }, 2013 | "node_modules/typescript-eslint": { 2014 | "version": "8.22.0", 2015 | "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.22.0.tgz", 2016 | "integrity": "sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==", 2017 | "dev": true, 2018 | "license": "MIT", 2019 | "dependencies": { 2020 | "@typescript-eslint/eslint-plugin": "8.22.0", 2021 | "@typescript-eslint/parser": "8.22.0", 2022 | "@typescript-eslint/utils": "8.22.0" 2023 | }, 2024 | "engines": { 2025 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 2026 | }, 2027 | "funding": { 2028 | "type": "opencollective", 2029 | "url": "https://opencollective.com/typescript-eslint" 2030 | }, 2031 | "peerDependencies": { 2032 | "eslint": "^8.57.0 || ^9.0.0", 2033 | "typescript": ">=4.8.4 <5.8.0" 2034 | } 2035 | }, 2036 | "node_modules/uglify-js": { 2037 | "version": "3.19.3", 2038 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", 2039 | "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", 2040 | "license": "BSD-2-Clause", 2041 | "optional": true, 2042 | "bin": { 2043 | "uglifyjs": "bin/uglifyjs" 2044 | }, 2045 | "engines": { 2046 | "node": ">=0.8.0" 2047 | } 2048 | }, 2049 | "node_modules/undici": { 2050 | "version": "5.28.5", 2051 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", 2052 | "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", 2053 | "license": "MIT", 2054 | "dependencies": { 2055 | "@fastify/busboy": "^2.0.0" 2056 | }, 2057 | "engines": { 2058 | "node": ">=14.0" 2059 | } 2060 | }, 2061 | "node_modules/undici-types": { 2062 | "version": "6.19.8", 2063 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", 2064 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", 2065 | "dev": true, 2066 | "license": "MIT" 2067 | }, 2068 | "node_modules/universal-user-agent": { 2069 | "version": "6.0.1", 2070 | "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", 2071 | "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", 2072 | "license": "ISC" 2073 | }, 2074 | "node_modules/universalify": { 2075 | "version": "2.0.1", 2076 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", 2077 | "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", 2078 | "license": "MIT", 2079 | "engines": { 2080 | "node": ">= 10.0.0" 2081 | } 2082 | }, 2083 | "node_modules/uri-js": { 2084 | "version": "4.4.1", 2085 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2086 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2087 | "dev": true, 2088 | "license": "BSD-2-Clause", 2089 | "dependencies": { 2090 | "punycode": "^2.1.0" 2091 | } 2092 | }, 2093 | "node_modules/which": { 2094 | "version": "2.0.2", 2095 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2096 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2097 | "dev": true, 2098 | "license": "ISC", 2099 | "dependencies": { 2100 | "isexe": "^2.0.0" 2101 | }, 2102 | "bin": { 2103 | "node-which": "bin/node-which" 2104 | }, 2105 | "engines": { 2106 | "node": ">= 8" 2107 | } 2108 | }, 2109 | "node_modules/word-wrap": { 2110 | "version": "1.2.5", 2111 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", 2112 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 2113 | "dev": true, 2114 | "license": "MIT", 2115 | "engines": { 2116 | "node": ">=0.10.0" 2117 | } 2118 | }, 2119 | "node_modules/wordwrap": { 2120 | "version": "1.0.0", 2121 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 2122 | "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", 2123 | "license": "MIT" 2124 | }, 2125 | "node_modules/wrappy": { 2126 | "version": "1.0.2", 2127 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2128 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2129 | "license": "ISC" 2130 | }, 2131 | "node_modules/yocto-queue": { 2132 | "version": "0.1.0", 2133 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2134 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2135 | "dev": true, 2136 | "license": "MIT", 2137 | "engines": { 2138 | "node": ">=10" 2139 | }, 2140 | "funding": { 2141 | "url": "https://github.com/sponsors/sindresorhus" 2142 | } 2143 | } 2144 | } 2145 | } 2146 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-dev-drive", 3 | "version": "3.4.1", 4 | "private": true, 5 | "description": "Setup Dev Drive Action", 6 | "main": "lib/setup-dev-drive.js", 7 | "scripts": { 8 | "build": "tsc", 9 | "bundle": "npm run bundle:setup && npm run bundle:cleanup", 10 | "bundle:setup": "ncc build -m -o dist/setup lib/setup-dev-drive.js", 11 | "bundle:cleanup": "ncc build -m -o dist/cleanup lib/cleanup-dev-drive.js", 12 | "lint": "eslint .", 13 | "fmt": "prettier --write src/**/*.ts", 14 | "fmt-check": "prettier --check src/**/*.ts", 15 | "package": "npm run fmt && npm run lint && npm run build && npm run bundle" 16 | }, 17 | "keywords": [ 18 | "GitHub", 19 | "Actions", 20 | "Dev Drive", 21 | "Setup Dev Drive", 22 | "Windows Dev Drive", 23 | "Microsoft ReFS", 24 | "Microsoft VHDX", 25 | "Microsoft Virtual Drive" 26 | ], 27 | "author": "samypr100", 28 | "license": "MIT", 29 | "dependencies": { 30 | "@actions/core": "^1.11.1", 31 | "@actions/exec": "^1.1.1", 32 | "@actions/github": "^6.0.0", 33 | "compare-versions": "^6.1.1", 34 | "fs-extra": "^11.3.0", 35 | "handlebars": "^4.7.8", 36 | "shell-quote": "^1.8.2" 37 | }, 38 | "devDependencies": { 39 | "@eslint/js": "^9.19.0", 40 | "@tsconfig/node20": "^20.1.4", 41 | "@types/fs-extra": "^11.0.4", 42 | "@types/node": "^20.17.16", 43 | "@types/shell-quote": "^1.7.5", 44 | "@vercel/ncc": "^0.38.3", 45 | "eslint": "^9.19.0", 46 | "eslint-plugin-prettier": "^5.2.3", 47 | "prettier": "^3.4.2", 48 | "typescript": "^5.7.3", 49 | "typescript-eslint": "^8.22.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/cleanup-dev-drive.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import { cleanup } from './cleanup-impl' 3 | 4 | async function main() { 5 | await cleanup() 6 | } 7 | 8 | main().catch(err => core.setFailed(err.message)) 9 | -------------------------------------------------------------------------------- /src/cleanup-impl.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import { StateVariables, WIN_PLATFORM } from './constants' 3 | import { dismount } from './vhd-commands' 4 | 5 | export async function cleanup(): Promise { 6 | if (process.platform !== WIN_PLATFORM) { 7 | core.info('This action can only run on Windows.') 8 | return 9 | } 10 | 11 | core.info('Attempting to remove Dev Drive.') 12 | 13 | const mountedPath = core.getState(StateVariables.DevDrive) 14 | core.debug(`Retrieved State ${StateVariables.DevDrive}=${mountedPath}`) 15 | 16 | const drivePath = core.getState(StateVariables.DevDrivePath) 17 | core.debug(`Retrieved State ${StateVariables.DevDrivePath}=${drivePath}`) 18 | 19 | const ret = await dismount(drivePath, mountedPath) 20 | core.info(`Removal finished with exit code ${ret}.`) 21 | } 22 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | export enum ExternalInputs { 2 | DriveSize = 'drive-size', 3 | DriveFormat = 'drive-format', 4 | DrivePath = 'drive-path', 5 | DriveType = 'drive-type', 6 | MountPath = 'mount-path', 7 | MountIfExists = 'mount-if-exists', 8 | WorkspaceCopy = 'workspace-copy', 9 | NativeDevDrive = 'native-dev-drive', 10 | TrustedDevDrive = 'trusted-dev-drive', 11 | EnvMapping = 'env-mapping', 12 | } 13 | 14 | export enum Cmdlets { 15 | GetVHD = 'Get-VHD', 16 | NewVHD = 'New-VHD', 17 | MountVHD = 'Mount-VHD', 18 | DismountVHD = 'Dismount-VHD', 19 | } 20 | 21 | export enum EnvVariables { 22 | DevDrive = 'DEV_DRIVE', 23 | DevDriveWorkspace = 'DEV_DRIVE_WORKSPACE', 24 | DevDrivePath = 'DEV_DRIVE_PATH', 25 | } 26 | 27 | export enum StateVariables { 28 | DevDrive = EnvVariables.DevDrive, 29 | DevDrivePath = EnvVariables.DevDrivePath, 30 | } 31 | 32 | export enum GithubVariables { 33 | GithubWorkspace = 'GITHUB_WORKSPACE', 34 | } 35 | 36 | export const MountPathDriveFormats = new Set(['ReFS', 'NTFS']) 37 | 38 | export const VHDDriveTypes = new Set(['Fixed', 'Dynamic']) 39 | 40 | export const NATIVE_DEV_DRIVE_WIN_VERSION = '10.0.22621' 41 | 42 | export const POWERSHELL_BIN = 'pwsh.exe' 43 | 44 | export const WIN_PLATFORM = 'win32' 45 | 46 | export const VHDX_EXTENSION = '.vhdx' 47 | 48 | export const DRIVE_LETTER_RE = /^[A-Za-z]:$/ 49 | -------------------------------------------------------------------------------- /src/env-mapping.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import Handlebars from 'handlebars' 3 | import { EnvVariables } from './constants' 4 | 5 | const envVarPattern = /^[a-zA-Z_]+[a-zA-Z0-9_]*$/ 6 | const envPossibleValues = Object.values(EnvVariables) 7 | const envAllowedValuesPattern = new RegExp( 8 | `^{{\\s*(${envPossibleValues.join('|')})\\s*}}`, 9 | ) 10 | 11 | /** 12 | * Like .split, but keeps the rest of the data when a limit is given. 13 | */ 14 | function splitKeep(input: string, separator: string, limit: number): string[] { 15 | if (limit === 0) { 16 | return [] 17 | } 18 | const parts = input.split(separator) 19 | if (parts.length > limit) { 20 | return [...parts.slice(0, limit - 1), parts.slice(limit - 1).join(separator)] 21 | } 22 | return parts.concat(Array(limit - parts.length).fill('')) 23 | } 24 | 25 | export async function processEnvMapping( 26 | envMapping: string[], 27 | ...varsToMap: EnvVariables[] 28 | ) { 29 | envMapping.forEach((entry, index) => { 30 | const entryNumber = index + 1 31 | const [rawEnvVar, rawTemplate] = splitKeep(entry, ',', 2) 32 | 33 | // core.getMultilineInput trims the input, hence we only trim the split edges 34 | const [envVar, template] = [rawEnvVar.trimEnd(), rawTemplate.trimStart()] 35 | 36 | if (!envVar || !template) { 37 | core.warning(`Invalid env mapping at entry ${entryNumber}, is it missing ','?`) 38 | return 39 | } 40 | 41 | if (!envVarPattern.test(envVar)) { 42 | core.warning( 43 | `Invalid environment variable \`${rawEnvVar}\` at entry ${entryNumber}, expected it to follow the pattern \`${envVarPattern.source}\`.`, 44 | ) 45 | return 46 | } 47 | 48 | if (!envAllowedValuesPattern.test(template)) { 49 | core.warning( 50 | `Invalid template \`${rawTemplate}\` at entry ${entryNumber}, expected it to start with \`{{ ${envPossibleValues.join(' or ')} }}\`.`, 51 | ) 52 | return 53 | } 54 | 55 | const templateFunction = Handlebars.compile(template, { 56 | data: false, 57 | noEscape: true, 58 | knownHelpersOnly: true, 59 | preventIndent: true, 60 | ignoreStandalone: true, 61 | strict: true, 62 | }) 63 | 64 | // Dynamically create the context from specific members 65 | const context = varsToMap.reduce( 66 | (acc, key) => { 67 | if (key in process.env) { 68 | acc[key] = process.env[key]! 69 | } else { 70 | core.debug( 71 | `Skipping processing \`${key}\` as it was not found in the environment.`, 72 | ) 73 | } 74 | return acc 75 | }, 76 | {} as Record, 77 | ) 78 | 79 | let result 80 | try { 81 | result = templateFunction(context) 82 | } catch (e) { 83 | core.debug((e as Error).message) 84 | core.warning( 85 | `Unable to render dynamic value at entry ${entryNumber} for \`${rawTemplate}\`. Was an option missing?`, 86 | ) 87 | return 88 | } 89 | 90 | // Expose the result to the job using the new env variable 91 | core.exportVariable(envVar, result) 92 | core.debug( 93 | `Exported new dynamic environment variable from entry ${entryNumber}: \`${envVar}=${result}\`.`, 94 | ) 95 | }) 96 | } 97 | -------------------------------------------------------------------------------- /src/setup-dev-drive.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import { setup } from './setup-impl' 3 | import { ExternalInputs } from './constants' 4 | 5 | async function main() { 6 | const driveSize = core.getInput(ExternalInputs.DriveSize) 7 | const driveFormat = core.getInput(ExternalInputs.DriveFormat) 8 | const drivePath = core.getInput(ExternalInputs.DrivePath) 9 | const driveType = core.getInput(ExternalInputs.DriveType) 10 | const mountPath = core.getInput(ExternalInputs.MountPath) 11 | const mountIfExists = core.getBooleanInput(ExternalInputs.MountIfExists) 12 | const copyWorkspace = core.getBooleanInput(ExternalInputs.WorkspaceCopy) 13 | const nativeDevDrive = core.getBooleanInput(ExternalInputs.NativeDevDrive) 14 | const trustedDevDrive = core.getBooleanInput(ExternalInputs.TrustedDevDrive) 15 | const envMapping = core.getMultilineInput(ExternalInputs.EnvMapping) 16 | await setup( 17 | driveSize, 18 | driveFormat, 19 | drivePath, 20 | driveType, 21 | mountPath, 22 | mountIfExists, 23 | copyWorkspace, 24 | nativeDevDrive, 25 | trustedDevDrive, 26 | envMapping, 27 | ) 28 | } 29 | 30 | main().catch(err => core.setFailed(err.message)) 31 | -------------------------------------------------------------------------------- /src/setup-impl.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import { toPlatformPath } from '@actions/core' 3 | import fs from 'fs-extra' 4 | import path from 'node:path' 5 | import { 6 | EnvVariables, 7 | ExternalInputs, 8 | GithubVariables, 9 | MountPathDriveFormats, 10 | StateVariables, 11 | VHDDriveTypes, 12 | VHDX_EXTENSION, 13 | WIN_PLATFORM, 14 | } from './constants' 15 | import { create, mount } from './vhd-commands' 16 | import { processEnvMapping } from './env-mapping.js' 17 | 18 | async function doDevDriveCommand( 19 | driveSize: string, 20 | driveFormat: string, 21 | drivePath: string, 22 | driveType: string, 23 | mountPath: string, 24 | mountIfExists: boolean, 25 | nativeDevDrive: boolean, 26 | trustedDevDrive: boolean, 27 | ): Promise { 28 | if (mountIfExists) { 29 | try { 30 | // Do a check on the Dev Drive 31 | await fs.access(drivePath, fs.constants.F_OK | fs.constants.R_OK) 32 | } catch (e) { 33 | core.debug((e as NodeJS.ErrnoException).message) 34 | // Fallback to creation... 35 | mountIfExists = false 36 | core.warning('Dev Drive did not exist, will create instead.') 37 | } 38 | } 39 | 40 | let mountedPath 41 | if (!mountIfExists) { 42 | core.info('Creating Dev Drive.') 43 | mountedPath = await create( 44 | driveSize, 45 | driveFormat, 46 | drivePath, 47 | driveType, 48 | mountPath, 49 | nativeDevDrive, 50 | trustedDevDrive, 51 | ) 52 | core.info('Successfully created Dev Drive.') 53 | } else { 54 | core.info('Mounting Dev Drive.') 55 | mountedPath = await mount(drivePath, mountPath) 56 | core.info('Successfully mounted Dev Drive.') 57 | } 58 | 59 | core.debug(`Exporting EnvVar ${EnvVariables.DevDrive}=${mountedPath}`) 60 | core.exportVariable(EnvVariables.DevDrive, mountedPath) 61 | 62 | core.debug(`Saving State ${StateVariables.DevDrive}=${mountedPath}`) 63 | core.saveState(StateVariables.DevDrive, mountedPath) 64 | 65 | core.debug(`Exporting EnvVar ${EnvVariables.DevDrivePath}=${drivePath}`) 66 | core.exportVariable(EnvVariables.DevDrivePath, drivePath) 67 | 68 | core.debug(`Saving State ${StateVariables.DevDrivePath}=${drivePath}`) 69 | core.saveState(StateVariables.DevDrivePath, drivePath) 70 | 71 | return mountedPath 72 | } 73 | 74 | async function doCopyWorkspace(mountedPath: string, drivePath: string) { 75 | const githubWorkspace = process.env[GithubVariables.GithubWorkspace] 76 | if (!githubWorkspace) { 77 | throw new Error('Github Workspace does not exist!') 78 | } 79 | 80 | const copyFrom = path.resolve(githubWorkspace) 81 | const copyTo = path.resolve(mountedPath, path.basename(copyFrom)) 82 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 83 | const filterFunc = (src: string, dst: string) => src !== drivePath 84 | 85 | // Check whether Copy-To is a child of Copy-From 86 | const relativePath = path.relative(copyFrom, copyTo) 87 | const isValidDest = relativePath.startsWith('..') || path.isAbsolute(relativePath) 88 | if (!isValidDest) { 89 | throw new Error( 90 | `Cannot copy '${copyFrom}' to a (sub)directory of itself, '${copyTo}'.`, 91 | ) 92 | } 93 | 94 | // Check Dev Drive is inside the directory we're about to copy 95 | const isDevDriveInWorkspace = drivePath.startsWith(copyFrom) 96 | if (isDevDriveInWorkspace) { 97 | core.warning( 98 | `Your dev drive '${drivePath}' is located inside the Github Workspace when ${ExternalInputs.WorkspaceCopy} is enabled! Your drive will be filtered out during copying.`, 99 | ) 100 | } 101 | 102 | core.info(`Copying workspace from '${copyFrom}' to '${copyTo}'.`) 103 | await fs.copy(copyFrom, copyTo, { filter: filterFunc }) 104 | 105 | core.debug(`Exporting EnvVar ${EnvVariables.DevDriveWorkspace}=${copyTo}`) 106 | core.exportVariable(EnvVariables.DevDriveWorkspace, copyTo) 107 | 108 | core.info('Finished copying workspace.') 109 | } 110 | 111 | export async function setup( 112 | driveSize: string, 113 | driveFormat: string, 114 | drivePath: string, 115 | driveType: string, 116 | mountPath: string, 117 | mountIfExists: boolean, 118 | copyWorkspace: boolean, 119 | nativeDevDrive: boolean, 120 | trustedDevDrive: boolean, 121 | envMapping: string[], 122 | ): Promise { 123 | if (process.platform !== WIN_PLATFORM) { 124 | core.info('This action can only run on Windows.') 125 | return 126 | } 127 | 128 | // Normalize Drive Path Input 129 | let normalizedDrivePath = toPlatformPath(drivePath) 130 | if (!path.isAbsolute(drivePath)) { 131 | // Default is relative to CWD root 132 | normalizedDrivePath = path.resolve('/', normalizedDrivePath) 133 | } 134 | if (path.extname(normalizedDrivePath) !== VHDX_EXTENSION) { 135 | throw new Error(`Make sure ${ExternalInputs.DrivePath} ends with ${VHDX_EXTENSION}`) 136 | } 137 | 138 | // Normalize Mount Path Input 139 | let normalizedMountPath = toPlatformPath(mountPath) 140 | if (mountPath) { 141 | // Check Drive Type 142 | if (MountPathDriveFormats.has(driveFormat)) { 143 | // Default is relative to CWD (when it's not absolute) 144 | normalizedMountPath = path.resolve(normalizedMountPath) 145 | } else { 146 | normalizedMountPath = '' 147 | const allowedMsg = [...MountPathDriveFormats].join(' or ') 148 | core.warning( 149 | `${ExternalInputs.DriveFormat}=${driveFormat} must be either ${allowedMsg} when ${ExternalInputs.MountPath} is specified. Using Drive Letter instead.`, 150 | ) 151 | } 152 | } 153 | if (normalizedMountPath) { 154 | try { 155 | // Make sure the directory exists 156 | await fs.mkdir(normalizedMountPath, { recursive: true }) 157 | } catch (e) { 158 | const errMsg = (e as NodeJS.ErrnoException).message 159 | throw new Error( 160 | `Failed to create specified mount path '${normalizedMountPath}' due to ${errMsg}.`, 161 | ) 162 | } 163 | } 164 | 165 | // Check Drive Type 166 | if (!VHDDriveTypes.has(driveType)) { 167 | const allowedMsg = [...VHDDriveTypes].join(' or ') 168 | throw new Error(`Make sure ${ExternalInputs.DriveType} is either ${allowedMsg}`) 169 | } 170 | 171 | const mountedPath = await doDevDriveCommand( 172 | driveSize, 173 | driveFormat, 174 | normalizedDrivePath, 175 | driveType, 176 | normalizedMountPath, 177 | mountIfExists, 178 | nativeDevDrive, 179 | trustedDevDrive, 180 | ) 181 | 182 | if (copyWorkspace) { 183 | await doCopyWorkspace(mountedPath, normalizedDrivePath) 184 | } 185 | 186 | await processEnvMapping( 187 | envMapping, 188 | EnvVariables.DevDrive, 189 | EnvVariables.DevDrivePath, 190 | EnvVariables.DevDriveWorkspace, 191 | ) 192 | } 193 | -------------------------------------------------------------------------------- /src/vhd-commands.ts: -------------------------------------------------------------------------------- 1 | import { quote } from 'shell-quote' 2 | import { exec, ExecOptions } from '@actions/exec' 3 | import { 4 | Cmdlets, 5 | DRIVE_LETTER_RE, 6 | NATIVE_DEV_DRIVE_WIN_VERSION, 7 | POWERSHELL_BIN, 8 | } from './constants' 9 | import os from 'node:os' 10 | import { compare } from 'compare-versions' 11 | import * as core from '@actions/core' 12 | import fs from 'fs-extra' 13 | import path from 'node:path' 14 | 15 | const VHDCommandNotFound = (name: string) => 16 | new Error( 17 | `Failed to detect ${name} command. Hyper-V may not be enabled or you're running an unsupported Windows version.`, 18 | ) 19 | 20 | // Basic helper to prevents shell-quote.quote default behavior of escaping `\` in windows. 21 | const winQuote = (str: string) => quote([str]).replaceAll('\\\\', '\\') 22 | 23 | class PowerShellCommandExecutor { 24 | private readonly command: string 25 | private readonly args: string[] = [] 26 | private options: ExecOptions = { 27 | silent: true, 28 | failOnStdErr: false, 29 | ignoreReturnCode: true, 30 | listeners: { 31 | stdout: (data: Buffer) => { 32 | this.outStr += data.toString() 33 | }, 34 | stderr: (data: Buffer) => { 35 | this.errStr += data.toString() 36 | }, 37 | }, 38 | } 39 | private outStr: string = '' 40 | private errStr: string = '' 41 | 42 | constructor(commands: string[]) { 43 | this.command = commands.join(' ') 44 | this.args = ['-NoProfile', '-Command', `. { ${this.command} }`] 45 | } 46 | 47 | public setOptions(customOptions: Partial): PowerShellCommandExecutor { 48 | this.options = { ...this.options, ...customOptions } 49 | return this 50 | } 51 | 52 | public getStdOut(): string { 53 | // Trim because Buffers tend to have newlines. 54 | return this.outStr.trim() 55 | } 56 | 57 | public getStdErr(): string { 58 | // Trim because Buffers tend to have newlines. 59 | return this.errStr.trim() 60 | } 61 | 62 | public async execute(): Promise { 63 | core.debug(`Executing the following command:\n${this.command}`) 64 | const cmdStatus = await exec(POWERSHELL_BIN, this.args, this.options) 65 | core.debug(`Command finished with exit code ${cmdStatus}.`) 66 | core.debug(`Command stdout:\n${this.getStdOut()}`) 67 | core.debug(`Command stderr:\n${this.getStdErr()}`) 68 | return cmdStatus 69 | } 70 | } 71 | 72 | export async function dismount(drivePath: string, mountPath: string) { 73 | const pathArg = winQuote(drivePath) 74 | const mountArg = winQuote(mountPath) 75 | 76 | // When running inside `-Command`, `-ErrorAction Stop` will retain the proper exit code 77 | const dismountDiskArgs = [`Dismount-VHD -Path ${pathArg} -ErrorAction Stop`] 78 | const dismountDiskExecutor = new PowerShellCommandExecutor(dismountDiskArgs) 79 | 80 | const dismountDiskCmdExists = await execCommandExists(Cmdlets.DismountVHD) 81 | if (dismountDiskCmdExists != 0) { 82 | throw VHDCommandNotFound(Cmdlets.DismountVHD) 83 | } 84 | 85 | const removePartArgs = [ 86 | `$ErrorActionPreference = 'Stop' ;`, 87 | // Get partitions for VHD 88 | `Get-VHD -Path ${pathArg} |`, 89 | 'Get-Disk |', 90 | 'Get-Partition |', 91 | // Filter out reserved partitions (if any) 92 | 'where { ($_ | Get-Volume) -ne $Null } |', 93 | `Remove-PartitionAccessPath -AccessPath ${mountArg}`, 94 | ] 95 | const removePartExecutor = new PowerShellCommandExecutor(removePartArgs) 96 | 97 | const dismountPartCmdExists = await execCommandExists(Cmdlets.GetVHD) 98 | if (dismountPartCmdExists != 0) { 99 | throw VHDCommandNotFound(Cmdlets.GetVHD) 100 | } 101 | 102 | // Assume mounted path of just two characters is a Drive Letter 103 | let cmdStatus 104 | const isMountedFolder = !DRIVE_LETTER_RE.test(mountPath) 105 | if (isMountedFolder) { 106 | // Remove Partition First 107 | core.info(`Removing partition at '${mountPath}'.`) 108 | cmdStatus = await removePartExecutor.execute() 109 | if (cmdStatus != 0) { 110 | core.warning( 111 | `Removal of partition at '${mountPath}' failed with exit code ${cmdStatus}.`, 112 | ) 113 | } 114 | } 115 | 116 | // Dismount VHD Last 117 | core.info(`Dismounting disk at '${drivePath}'.`) 118 | cmdStatus = await dismountDiskExecutor.execute() 119 | if (cmdStatus != 0) { 120 | core.warning( 121 | `Dismounting disk at '${drivePath}' failed with exit code ${cmdStatus}.`, 122 | ) 123 | } 124 | 125 | return cmdStatus 126 | } 127 | 128 | export async function create( 129 | driveSize: string, 130 | driveFormat: string, 131 | drivePath: string, 132 | driveType: string, 133 | mountPath: string, 134 | nativeDevDrive: boolean, 135 | trustedDevDrive: boolean, 136 | ): Promise { 137 | const sizeArg = winQuote(driveSize) 138 | const formatArg = winQuote(driveFormat) 139 | const pathArg = winQuote(drivePath) 140 | const mountArg = winQuote(mountPath) 141 | 142 | const osVersion = os.release() 143 | const supportsDevDrive = compare(os.release(), NATIVE_DEV_DRIVE_WIN_VERSION, '>=') 144 | core.debug(`Windows Version ${osVersion}. Native Dev Drive? ${supportsDevDrive}`) 145 | 146 | let markAsTrusted = false 147 | let formatCmd = `Format-Volume -FileSystem ${formatArg} -Confirm:$false -Force` 148 | if (nativeDevDrive && supportsDevDrive && formatArg === 'ReFS') { 149 | formatCmd = `Format-Volume -DevDrive -Confirm:$false -Force` 150 | // trust mode is compatible with native dev drives only 151 | markAsTrusted = trustedDevDrive 152 | } 153 | 154 | const commandExists = await execCommandExists(Cmdlets.NewVHD) 155 | if (commandExists != 0) { 156 | throw VHDCommandNotFound(Cmdlets.NewVHD) 157 | } 158 | 159 | // Use drive letter mounting when there's no specified mount path 160 | let withDriveLetter = true 161 | try { 162 | await fs.access(mountPath, fs.constants.F_OK | fs.constants.W_OK) 163 | withDriveLetter = false 164 | } catch (e) { 165 | if (mountPath) { 166 | core.warning((e as NodeJS.ErrnoException).message) 167 | core.info( 168 | `Mount path '${mountPath}' is not writable, using Drive Letter instead.`, 169 | ) 170 | } 171 | } 172 | 173 | const createDevDriveArgs = [ 174 | `$ErrorActionPreference = 'Stop' ;`, 175 | '$DevDrive =', 176 | // Create VHD 177 | `New-VHD -Path ${pathArg} -SizeBytes ${sizeArg} -${driveType} |`, 178 | // Mount VHD 179 | withDriveLetter ? 'Mount-VHD -PassThru |' : 'Mount-VHD -NoDriveLetter -PassThru |', 180 | // Init Disk 181 | 'Initialize-Disk -PassThru |', 182 | // Init Partitions 183 | withDriveLetter 184 | ? 'New-Partition -AssignDriveLetter -UseMaximumSize ;' 185 | : 'New-Partition -UseMaximumSize ;', 186 | // Format Partition 187 | `$DevDrive | ${formatCmd} | Out-Null;`, 188 | // Output Mount Path 189 | withDriveLetter 190 | ? `Write-Output ($DevDrive.DriveLetter + ':')` 191 | : `$DevDrive | Add-PartitionAccessPath -AccessPath ${mountArg} | Out-Null ; Write-Output ${mountArg}`, 192 | ] 193 | 194 | if (markAsTrusted) { 195 | core.info('Disabling AV filters for dev drives.') 196 | await execDisableAVFilter() 197 | } 198 | 199 | const mountedPath = await execMountOrCreate(createDevDriveArgs) 200 | 201 | if (markAsTrusted) { 202 | core.info(`Marking dev drive at ${mountedPath} as trusted.`) 203 | await execMarkAsTrusted(mountedPath) 204 | } 205 | 206 | return mountedPath 207 | } 208 | 209 | export async function mount(drivePath: string, mountPath: string): Promise { 210 | const pathArg = winQuote(drivePath) 211 | const mountArg = winQuote(mountPath) 212 | 213 | const commandExists = await execCommandExists(Cmdlets.MountVHD) 214 | if (commandExists != 0) { 215 | throw VHDCommandNotFound(Cmdlets.MountVHD) 216 | } 217 | 218 | // Use drive letter mounting when there's no specified mount path 219 | let withDriveLetter = true 220 | try { 221 | await fs.access(mountPath, fs.constants.F_OK | fs.constants.W_OK) 222 | withDriveLetter = false 223 | } catch (e) { 224 | if (mountPath) { 225 | core.warning((e as NodeJS.ErrnoException).message) 226 | core.info( 227 | `Mount path '${mountPath}' is not writable, using Drive Letter instead.`, 228 | ) 229 | } 230 | } 231 | 232 | const mountCmdArgs = [ 233 | `$ErrorActionPreference = 'Stop' ;`, 234 | '$DevDrive =', 235 | // Mount VHD 236 | withDriveLetter 237 | ? `Mount-VHD -Path ${pathArg} -PassThru |` 238 | : `Mount-VHD -Path ${pathArg} -NoDriveLetter -PassThru |`, 239 | 'Get-Disk |', 240 | 'Get-Partition |', 241 | // Filter out reserved partitions (if any) 242 | 'where { ($_ | Get-Volume) -ne $Null } ;', 243 | // Get Mount Path 244 | withDriveLetter 245 | ? `$DevDrive = $DevDrive | Get-Volume ; Write-Output ($DevDrive.DriveLetter + ':')` 246 | : `$DevDrive | Add-PartitionAccessPath -AccessPath ${mountArg} | Out-Null ; Write-Output ${mountArg}`, 247 | ] 248 | 249 | return await execMountOrCreate(mountCmdArgs) 250 | } 251 | 252 | async function execMountOrCreate(pwshCommandArgs: string[]): Promise { 253 | const commandExecutor = new PowerShellCommandExecutor(pwshCommandArgs) 254 | const cmdStatus = await commandExecutor.execute() 255 | 256 | const cleanedErr = commandExecutor.getStdErr() 257 | if (cleanedErr.length > 0 || cmdStatus !== 0) { 258 | core.error(`Failed to setup Dev Drive with exit code ${cmdStatus}.`) 259 | throw new Error(cleanedErr) 260 | } 261 | 262 | // Assume mounted path of just two characters is a Drive Letter 263 | let mountedPath = commandExecutor.getStdOut() 264 | if (!DRIVE_LETTER_RE.test(mountedPath)) { 265 | mountedPath = path.resolve(mountedPath) 266 | } 267 | 268 | // Do a basic check on the Dev Drive 269 | // If it fails, this will raise an error and the generic handler will take care of it. 270 | await fs.access(mountedPath, fs.constants.F_OK | fs.constants.W_OK) 271 | 272 | return mountedPath 273 | } 274 | 275 | async function execCommandExists(name: string): Promise { 276 | // When running inside `-Command`, `-ErrorAction Stop` will retain the proper exit code 277 | const checkCommandArgs = [ 278 | `Get-Command -Name ${name} -CommandType Cmdlet -ErrorAction Stop`, 279 | ] 280 | const checkCommandExecutor = new PowerShellCommandExecutor(checkCommandArgs) 281 | return await checkCommandExecutor.execute() 282 | } 283 | 284 | async function execDisableAVFilter(): Promise { 285 | const disableAVFilterArgs = [ 286 | `$ErrorActionPreference = 'Stop' ;`, 287 | // Disable AV on dev drive 288 | // See https://learn.microsoft.com/en-us/windows/dev-drive/#how-do-i-configure-additional-filters-on-dev-drive 289 | 'fsutil devdrv enable /disallowAv ;', 290 | // Shows enablement logs 291 | 'fsutil devdrv query', 292 | ] 293 | const disableAVFilterExecutor = new PowerShellCommandExecutor(disableAVFilterArgs) 294 | return await disableAVFilterExecutor.execute() 295 | } 296 | 297 | async function execMarkAsTrusted(mountPath: string): Promise { 298 | // Note: This function assumes mountPath is escaped already. 299 | const markAsTrustedArgs = [ 300 | `$ErrorActionPreference = 'Stop' ;`, 301 | // Mark dev drive as trusted 302 | // See https://learn.microsoft.com/en-us/windows/dev-drive/#how-do-i-designate-a-dev-drive-as-trusted 303 | `fsutil devdrv clearFiltersAllowed ${mountPath} ;`, 304 | `fsutil devdrv trust /f ${mountPath} ;`, 305 | // Shows enablement logs 306 | `fsutil devdrv query ${mountPath}`, 307 | ] 308 | const markAsTrustedExecutor = new PowerShellCommandExecutor(markAsTrustedArgs) 309 | return await markAsTrustedExecutor.execute() 310 | } 311 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./lib", 6 | "forceConsistentCasingInFileNames": true, 7 | "newLine": "lf", 8 | "noImplicitAny": true, 9 | "sourceMap": true 10 | }, 11 | "exclude": [ 12 | "./lib", 13 | "./dist", 14 | "./node_modules" 15 | ] 16 | } 17 | --------------------------------------------------------------------------------