Keep npm lockfiles portable and preserve inherited package sources (#871)

Co-authored-by: Stefan Broenner <stbrnner@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Stefan Broenner
2026-09-11 09:07:01 -07:00
committed by GitHub
parent a5ab24768d
commit 5eafcbfc8f
14 changed files with 320 additions and 456 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
node-version: '22'
- name: Install changesets CLI
run: npm install --no-save --registry https://registry.npmjs.org/
run: npm install --no-save
- name: Check for a changeset
run: |
+10
View File
@@ -82,6 +82,16 @@ jobs:
- name: Checkout
uses: actions/checkout@v7
- name: Npm lockfile portability regression tests
timeout-minutes: 2
shell: pwsh
run: ./scripts/Test-NpmLockfiles.ps1
- name: Npm lockfile portability
timeout-minutes: 2
shell: pwsh
run: ./scripts/check-npm-lockfiles.ps1
- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
+2 -2
View File
@@ -127,7 +127,7 @@ jobs:
node-version: ${{ env.NODE_VERSION }}
- name: Install changesets CLI
run: npm ci --registry https://registry.npmjs.org/
run: npm ci
- name: Compile changesets into CHANGELOG.md
shell: pwsh
@@ -575,7 +575,7 @@ jobs:
node-version: ${{ env.NODE_VERSION }}
- name: Install changesets CLI
run: npm ci --registry https://registry.npmjs.org/
run: npm ci
- name: Download Prepared Changelog
uses: actions/download-artifact@v8
+1
View File
@@ -0,0 +1 @@
omit-lockfile-registry-resolved=true
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
+52
View File
@@ -59,6 +59,58 @@ ExcelMcp aims to be the go-to command-line tool for coding agents to interact wi
## 📋 Development Guidelines
### Portable npm lockfiles
Every npm project with a tracked lockfile needs its own `.npmrc` containing:
```ini
omit-lockfile-registry-resolved=true
```
This applies to the repository root, `vscode-extension`, and
`videos/excel-mcp-intro`, as well as any new nested npm project. npm does not
inherit the root project's configuration in nested projects. Preserve any
other existing project settings; do not change registry, proxy, credentials,
or user/global npm configuration to clean up a lockfile.
Run this command **inside each affected project**:
```powershell
npm install --package-lock-only --ignore-scripts
```
Use npm to regenerate lockfiles, not search-and-replace. For portability-only
changes, keep dependency versions and integrity hashes unchanged; do not run
`npm update` or `npm audit fix`. Downloads then use the developer's or CI
environment's configured registry rather than a URL saved by another machine.
Direct URL dependencies are not portable under this policy and must use
registry versions or local dependencies instead.
Run the focused checks from the repository root (no Excel required):
```powershell
pwsh -NoProfile -File scripts\Test-NpmLockfiles.ps1
pwsh -NoProfile -File scripts\check-npm-lockfiles.ps1
```
The required CI Gate runs both checks with two-minute limits. The pre-commit
hook checks the staged contents with `-Staged`. The guard discovers tracked
`package-lock.json` and `npm-shrinkwrap.json` files at any depth, excludes
`node_modules`, and reports offending filenames without exposing URLs or
credentials. New lockfiles must be staged before the guard can discover them.
### Respect local package sources
npm installs and .NET restores use the package manager's normal configuration
hierarchy. The repository does not clear NuGet package sources or force a
registry/source/configuration file for restores. Keep local feeds, credentials,
proxy settings, caches, and environment settings under the developer's or CI
environment's control; do not overwrite them to work around a restore failure.
Report an unavailable configured feed instead.
NuGet publishing commands intentionally name the public publishing destination.
That `dotnet nuget push --source` setting is not a restore-source override.
### Code Style
- **C# version** follows `Directory.Build.props` and the SDK selected by `global.json`
-109
View File
@@ -14,7 +14,6 @@
},
"node_modules/@babel/runtime": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
"integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
"dev": true,
"license": "MIT",
@@ -24,7 +23,6 @@
},
"node_modules/@changesets/apply-release-plan": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.1.1.tgz",
"integrity": "sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==",
"dev": true,
"license": "MIT",
@@ -46,7 +44,6 @@
},
"node_modules/@changesets/assemble-release-plan": {
"version": "6.0.10",
"resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.10.tgz",
"integrity": "sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==",
"dev": true,
"license": "MIT",
@@ -61,7 +58,6 @@
},
"node_modules/@changesets/changelog-git": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz",
"integrity": "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==",
"dev": true,
"license": "MIT",
@@ -71,7 +67,6 @@
},
"node_modules/@changesets/changelog-github": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@changesets/changelog-github/-/changelog-github-0.7.0.tgz",
"integrity": "sha512-rBsbRvc4TVn+FvFnOVM3LxlFJfTXXCp8gfVJ+0BubxWNSVnLuAzowi5j+IEraLLP52w8AAs9QfKbPS3MMiXQJA==",
"dev": true,
"license": "MIT",
@@ -83,7 +78,6 @@
},
"node_modules/@changesets/cli": {
"version": "2.31.1",
"resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.31.1.tgz",
"integrity": "sha512-uO05WTcRBwuVOJVSW8Cmpqw6q0WDL53ajGCMyszutvOe5toOnunbpM4jZzf+qxBOz7i0AzopZ8diBuewjmF40w==",
"dev": true,
"license": "MIT",
@@ -121,7 +115,6 @@
},
"node_modules/@changesets/config": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.4.tgz",
"integrity": "sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==",
"dev": true,
"license": "MIT",
@@ -138,7 +131,6 @@
},
"node_modules/@changesets/errors": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz",
"integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==",
"dev": true,
"license": "MIT",
@@ -148,7 +140,6 @@
},
"node_modules/@changesets/get-dependents-graph": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.4.tgz",
"integrity": "sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==",
"dev": true,
"license": "MIT",
@@ -161,7 +152,6 @@
},
"node_modules/@changesets/get-github-info": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@changesets/get-github-info/-/get-github-info-0.8.0.tgz",
"integrity": "sha512-cRnC+xdF0JIik7coko3iUP9qbnfi1iJQ3sAa6dE+Tx3+ET8bjFEm63PA4WEohgjYcmsOikPHWzPsMWWiZmntOQ==",
"dev": true,
"license": "MIT",
@@ -172,7 +162,6 @@
},
"node_modules/@changesets/get-release-plan": {
"version": "4.0.16",
"resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.16.tgz",
"integrity": "sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==",
"dev": true,
"license": "MIT",
@@ -187,14 +176,12 @@
},
"node_modules/@changesets/get-version-range-type": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz",
"integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@changesets/git": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz",
"integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==",
"dev": true,
"license": "MIT",
@@ -208,7 +195,6 @@
},
"node_modules/@changesets/logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz",
"integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==",
"dev": true,
"license": "MIT",
@@ -218,7 +204,6 @@
},
"node_modules/@changesets/parse": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.3.tgz",
"integrity": "sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==",
"dev": true,
"license": "MIT",
@@ -229,7 +214,6 @@
},
"node_modules/@changesets/pre": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.2.tgz",
"integrity": "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==",
"dev": true,
"license": "MIT",
@@ -242,7 +226,6 @@
},
"node_modules/@changesets/read": {
"version": "0.6.7",
"resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.7.tgz",
"integrity": "sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==",
"dev": true,
"license": "MIT",
@@ -258,7 +241,6 @@
},
"node_modules/@changesets/should-skip-package": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.2.tgz",
"integrity": "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==",
"dev": true,
"license": "MIT",
@@ -269,14 +251,12 @@
},
"node_modules/@changesets/types": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.1.0.tgz",
"integrity": "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==",
"dev": true,
"license": "MIT"
},
"node_modules/@changesets/write": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.4.0.tgz",
"integrity": "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==",
"dev": true,
"license": "MIT",
@@ -289,7 +269,6 @@
},
"node_modules/@inquirer/external-editor": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz",
"integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==",
"dev": true,
"license": "MIT",
@@ -311,7 +290,6 @@
},
"node_modules/@manypkg/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==",
"dev": true,
"license": "MIT",
@@ -324,14 +302,12 @@
},
"node_modules/@manypkg/find-root/node_modules/@types/node": {
"version": "12.20.55",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@manypkg/find-root/node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"dev": true,
"license": "MIT",
@@ -346,7 +322,6 @@
},
"node_modules/@manypkg/get-packages": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz",
"integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==",
"dev": true,
"license": "MIT",
@@ -361,14 +336,12 @@
},
"node_modules/@manypkg/get-packages/node_modules/@changesets/types": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz",
"integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==",
"dev": true,
"license": "MIT"
},
"node_modules/@manypkg/get-packages/node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"dev": true,
"license": "MIT",
@@ -383,7 +356,6 @@
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"license": "MIT",
@@ -397,7 +369,6 @@
},
"node_modules/@nodelib/fs.stat": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"license": "MIT",
@@ -407,7 +378,6 @@
},
"node_modules/@nodelib/fs.walk": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"license": "MIT",
@@ -421,7 +391,6 @@
},
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
"dev": true,
"license": "MIT",
@@ -431,7 +400,6 @@
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"license": "MIT",
@@ -441,14 +409,12 @@
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true,
"license": "MIT",
@@ -458,7 +424,6 @@
},
"node_modules/better-path-resolve": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz",
"integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==",
"dev": true,
"license": "MIT",
@@ -471,7 +436,6 @@
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
@@ -484,14 +448,12 @@
},
"node_modules/chardet": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz",
"integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==",
"dev": true,
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
@@ -506,14 +468,12 @@
},
"node_modules/dataloader": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz",
"integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/detect-indent": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
"integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
"dev": true,
"license": "MIT",
@@ -523,7 +483,6 @@
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"dev": true,
"license": "MIT",
@@ -536,7 +495,6 @@
},
"node_modules/dotenv": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
"integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
"dev": true,
"license": "BSD-2-Clause",
@@ -546,7 +504,6 @@
},
"node_modules/enquirer": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
"integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
"dev": true,
"license": "MIT",
@@ -560,7 +517,6 @@
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
"license": "BSD-2-Clause",
@@ -574,14 +530,12 @@
},
"node_modules/extendable-error": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz",
"integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==",
"dev": true,
"license": "MIT"
},
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"license": "MIT",
@@ -598,7 +552,6 @@
},
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
"dev": true,
"license": "ISC",
@@ -608,7 +561,6 @@
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
@@ -621,7 +573,6 @@
},
"node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"license": "MIT",
@@ -635,7 +586,6 @@
},
"node_modules/fs-extra": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"license": "MIT",
@@ -650,7 +600,6 @@
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
@@ -663,7 +612,6 @@
},
"node_modules/globby": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
"license": "MIT",
@@ -684,14 +632,12 @@
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true,
"license": "ISC"
},
"node_modules/human-id": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/human-id/-/human-id-4.2.0.tgz",
"integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==",
"dev": true,
"license": "MIT",
@@ -701,7 +647,6 @@
},
"node_modules/iconv-lite": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz",
"integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==",
"dev": true,
"license": "MIT",
@@ -718,7 +663,6 @@
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
"license": "MIT",
@@ -728,7 +672,6 @@
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
@@ -738,7 +681,6 @@
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
@@ -751,7 +693,6 @@
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
@@ -761,7 +702,6 @@
},
"node_modules/is-subdir": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz",
"integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==",
"dev": true,
"license": "MIT",
@@ -774,7 +714,6 @@
},
"node_modules/is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true,
"license": "MIT",
@@ -784,14 +723,12 @@
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true,
"license": "ISC"
},
"node_modules/js-yaml": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
"integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
"dev": true,
"funding": [
@@ -814,7 +751,6 @@
},
"node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"license": "MIT",
@@ -824,7 +760,6 @@
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"license": "MIT",
@@ -837,14 +772,12 @@
},
"node_modules/lodash.startcase": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
"integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
"dev": true,
"license": "MIT"
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"license": "MIT",
@@ -854,7 +787,6 @@
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
@@ -868,7 +800,6 @@
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true,
"license": "MIT",
@@ -878,7 +809,6 @@
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dev": true,
"license": "MIT",
@@ -899,14 +829,12 @@
},
"node_modules/outdent": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz",
"integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==",
"dev": true,
"license": "MIT"
},
"node_modules/p-filter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz",
"integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==",
"dev": true,
"license": "MIT",
@@ -919,7 +847,6 @@
},
"node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"license": "MIT",
@@ -935,7 +862,6 @@
},
"node_modules/p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"license": "MIT",
@@ -948,7 +874,6 @@
},
"node_modules/p-map": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
"integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
"dev": true,
"license": "MIT",
@@ -958,7 +883,6 @@
},
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"license": "MIT",
@@ -968,7 +892,6 @@
},
"node_modules/package-manager-detector": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz",
"integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==",
"dev": true,
"license": "MIT",
@@ -978,7 +901,6 @@
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"license": "MIT",
@@ -988,7 +910,6 @@
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT",
@@ -998,7 +919,6 @@
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"license": "MIT",
@@ -1008,14 +928,12 @@
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
@@ -1028,7 +946,6 @@
},
"node_modules/pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true,
"license": "MIT",
@@ -1038,7 +955,6 @@
},
"node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"license": "MIT",
@@ -1054,7 +970,6 @@
},
"node_modules/quansync": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
"integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
"dev": true,
"funding": [
@@ -1071,7 +986,6 @@
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true,
"funding": [
@@ -1092,7 +1006,6 @@
},
"node_modules/read-yaml-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz",
"integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==",
"dev": true,
"license": "MIT",
@@ -1108,7 +1021,6 @@
},
"node_modules/read-yaml-file/node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"license": "MIT",
@@ -1118,7 +1030,6 @@
},
"node_modules/read-yaml-file/node_modules/js-yaml": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz",
"integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==",
"dev": true,
"license": "MIT",
@@ -1132,7 +1043,6 @@
},
"node_modules/resolve-from": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
"license": "MIT",
@@ -1142,7 +1052,6 @@
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"license": "MIT",
@@ -1153,7 +1062,6 @@
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
"funding": [
@@ -1177,14 +1085,12 @@
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true,
"license": "MIT"
},
"node_modules/semver": {
"version": "7.8.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"dev": true,
"license": "ISC",
@@ -1197,7 +1103,6 @@
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT",
@@ -1210,7 +1115,6 @@
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT",
@@ -1220,7 +1124,6 @@
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"license": "ISC",
@@ -1233,7 +1136,6 @@
},
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true,
"license": "MIT",
@@ -1243,7 +1145,6 @@
},
"node_modules/spawndamnit": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-3.0.1.tgz",
"integrity": "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==",
"dev": true,
"license": "SEE LICENSE IN LICENSE",
@@ -1254,14 +1155,12 @@
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT",
@@ -1274,7 +1173,6 @@
},
"node_modules/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"dev": true,
"license": "MIT",
@@ -1284,7 +1182,6 @@
},
"node_modules/term-size": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
"integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==",
"dev": true,
"license": "MIT",
@@ -1297,7 +1194,6 @@
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
@@ -1310,14 +1206,12 @@
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"dev": true,
"license": "MIT"
},
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true,
"license": "MIT",
@@ -1327,14 +1221,12 @@
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"dev": true,
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dev": true,
"license": "MIT",
@@ -1345,7 +1237,6 @@
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"license": "ISC",
+117
View File
@@ -0,0 +1,117 @@
<#
.SYNOPSIS
Tests portable npm lockfile validation without installing dependencies.
#>
$ErrorActionPreference = "Stop"
$guard = Join-Path $PSScriptRoot "check-npm-lockfiles.ps1"
$testRoot = Join-Path ([IO.Path]::GetTempPath()) "excelmcp-npm-tests-$([Guid]::NewGuid().ToString('N'))"
$testsRun = 0
function Invoke-TestProcess {
param([string]$Command, [string[]]$Arguments)
$info = [Diagnostics.ProcessStartInfo]::new($Command)
$info.WorkingDirectory = $testRoot
$info.UseShellExecute = $false
$info.RedirectStandardOutput = $true
$info.RedirectStandardError = $true
foreach ($argument in $Arguments) { $info.ArgumentList.Add($argument) }
$process = [Diagnostics.Process]::Start($info)
try {
$stdout = $process.StandardOutput.ReadToEndAsync()
$stderr = $process.StandardError.ReadToEndAsync()
if (-not $process.WaitForExit(30000)) {
$process.Kill($true)
throw "Test process exceeded 30 seconds."
}
return @{
ExitCode = $process.ExitCode
Output = $stdout.GetAwaiter().GetResult() + $stderr.GetAwaiter().GetResult()
}
}
finally { $process.Dispose() }
}
function Invoke-TestGit {
param([string[]]$GitArguments)
$result = Invoke-TestProcess "git" $GitArguments
if ($result.ExitCode -ne 0) { throw "Test Git command failed." }
}
function Set-Fixture {
param([string]$Path, [string]$Content)
$fullPath = Join-Path $testRoot $Path
[IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($fullPath)) | Out-Null
[IO.File]::WriteAllText($fullPath, $Content)
}
function Assert-Guard {
param([bool]$Success, [string]$ExpectedText, [switch]$Staged)
$arguments = @("-NoProfile", "-File", $guard, "-RepositoryRoot", $testRoot)
if ($Staged) { $arguments += "-Staged" }
$result = Invoke-TestProcess "pwsh" $arguments
if (($result.ExitCode -eq 0) -ne $Success -or $result.Output -notlike "*$ExpectedText*") {
throw "Guard assertion failed: expected success=$Success and diagnostic '$ExpectedText'."
}
if ($result.Output -match "private-mirror|secret-token|secret-password") {
throw "Guard exposed a download URL or credential."
}
$script:testsRun++
}
$portable = '{"lockfileVersion":3,"packages":{"":{"name":"fixture"},"node_modules/example":{"version":"1.2.3","integrity":"sha512-example","funding":{"url":"https://example.org/support"}},"node_modules/local":{"resolved":"file:../local","link":true}}}'
$unsafe = '{"lockfileVersion":3,"packages":{"node_modules/example":{"version":"1.2.3","resolved":"https://user:secret-password@private-mirror.invalid/example.tgz?secret-token","integrity":"sha512-example"}}}'
[IO.Directory]::CreateDirectory($testRoot) | Out-Null
try {
Invoke-TestGit @("init", "--quiet")
Set-Fixture "package-lock.json" $portable
Invoke-TestGit @("add", "--", "package-lock.json")
Assert-Guard $true "1 tracked npm lockfile"
Set-Fixture "package-lock.json" $unsafe
Assert-Guard $false "fixed download URL"
Assert-Guard $true "1 tracked npm lockfile" -Staged
Invoke-TestGit @("add", "--", "package-lock.json")
Set-Fixture "package-lock.json" $portable
Assert-Guard $false "fixed download URL" -Staged
Invoke-TestGit @("add", "--", "package-lock.json")
Set-Fixture "new nested/project/package-lock.json" $unsafe
Assert-Guard $true "1 tracked npm lockfile"
Invoke-TestGit @("add", "--", "new nested/project/package-lock.json")
Assert-Guard $false "new nested/project/package-lock.json"
Set-Fixture "new nested/project/package-lock.json" $portable
Assert-Guard $true "2 tracked npm lockfile"
Set-Fixture "node_modules/vendor/package-lock.json" $unsafe
Invoke-TestGit @("add", "--", "node_modules/vendor/package-lock.json")
Assert-Guard $true "2 tracked npm lockfile"
foreach ($url in @("https://registry.npmjs.org/example.tgz", "http://private-mirror.invalid/example.tgz", "//private-mirror.invalid/example.tgz", "git+https://private-mirror.invalid/repo.git", "ftp://private-mirror.invalid/example.tgz")) {
Set-Fixture "package-lock.json" (@{ lockfileVersion = 1; dependencies = @{ example = @{ version = "1.2.3"; resolved = $url } } } | ConvertTo-Json -Depth 10)
Assert-Guard $false "fixed download URL"
}
Set-Fixture "package-lock.json" '{"lockfileVersion":1,"dependencies":{"example":{"version":"https://private-mirror.invalid/example.tgz"}}}'
Assert-Guard $false "fixed download URL"
Set-Fixture "package-lock.json" '{"lockfileVersion":2,"packages":{},"dependencies":{"example":{"version":"1.2.3","dependencies":{"nested":{"resolved":"https://private-mirror.invalid/nested.tgz"}}}}}'
Assert-Guard $false "fixed download URL"
Set-Fixture "package-lock.json" '{"private-mirror secret-password":'
Assert-Guard $false "invalid JSON"
Set-Fixture "package-lock.json" "null"
Assert-Guard $false "JSON object"
Set-Fixture "package-lock.json" $portable
Set-Fixture "nested/npm-shrinkwrap.json" $unsafe
Invoke-TestGit @("add", "--", "nested/npm-shrinkwrap.json")
Assert-Guard $false "nested/npm-shrinkwrap.json"
Set-Fixture "nested/npm-shrinkwrap.json" $portable
Assert-Guard $true "3 tracked npm lockfile"
Write-Host "Passed $testsRun npm lockfile regression checks."
}
finally {
Remove-Item -LiteralPath $testRoot -Recurse -Force
}
+101
View File
@@ -0,0 +1,101 @@
<#
.SYNOPSIS
Rejects fixed download URLs in all tracked npm lockfiles.
.DESCRIPTION
Checks package-lock.json and npm-shrinkwrap.json, including nested projects,
but not node_modules. Diagnostics never include dependency values or URLs.
Use -Staged in commit hooks to check index contents rather than working files.
#>
[CmdletBinding()]
param(
[string]$RepositoryRoot = (Split-Path -Parent $PSScriptRoot),
[switch]$Staged
)
$ErrorActionPreference = "Stop"
function Invoke-LockfileGit {
param([string[]]$GitArguments)
$info = [Diagnostics.ProcessStartInfo]::new("git")
$info.WorkingDirectory = $RepositoryRoot
$info.UseShellExecute = $false
$info.RedirectStandardOutput = $true
$info.RedirectStandardError = $true
foreach ($argument in $GitArguments) { $info.ArgumentList.Add($argument) }
$process = [Diagnostics.Process]::Start($info)
try {
$stdout = $process.StandardOutput.ReadToEndAsync()
$stderr = $process.StandardError.ReadToEndAsync()
if (-not $process.WaitForExit(15000)) {
$process.Kill($true)
throw "Git lockfile inspection exceeded 15 seconds."
}
$output = $stdout.GetAwaiter().GetResult()
$null = $stderr.GetAwaiter().GetResult()
if ($process.ExitCode -ne 0) { throw "Git could not read tracked npm lockfiles." }
return $output
}
finally { $process.Dispose() }
}
function Test-FixedDownloadUrl {
param($Value)
if ($Value -is [System.Collections.IDictionary]) {
foreach ($key in $Value.Keys) {
$child = $Value[$key]
if ($key -in @("resolved", "version") -and $child -is [string] -and
$child -match '^(?:[a-z][a-z0-9+.-]*:)?//') {
return $true
}
if (Test-FixedDownloadUrl $child) { return $true }
}
}
elseif ($Value -is [array]) {
foreach ($child in $Value) {
if (Test-FixedDownloadUrl $child) { return $true }
}
}
return $false
}
try {
$tracked = (Invoke-LockfileGit @("ls-files", "--cached", "-z")) -split "`0"
$lockfiles = @($tracked | Where-Object {
$_ -match '(^|/)(package-lock\.json|npm-shrinkwrap\.json)$' -and
$_ -notmatch '(^|/)node_modules/'
} | Sort-Object -Unique)
$failed = $false
foreach ($path in $lockfiles) {
if ($Staged) {
$content = Invoke-LockfileGit @("show", ":$path")
}
else {
$fullPath = Join-Path $RepositoryRoot $path
if (-not (Test-Path -LiteralPath $fullPath -PathType Leaf)) {
throw "A tracked npm lockfile is missing: $path"
}
$content = [IO.File]::ReadAllText($fullPath)
}
try { $lockfile = ConvertFrom-Json -InputObject $content -AsHashtable }
catch { throw "Npm lockfile has invalid JSON: $path" }
if ($lockfile -isnot [System.Collections.IDictionary]) {
throw "Npm lockfile must contain a JSON object: $path"
}
if (Test-FixedDownloadUrl $lockfile) {
Write-Host "Fixed download URL found in $path (URL omitted)." -ForegroundColor Red
$failed = $true
}
}
if ($failed) {
Write-Host "Set omit-lockfile-registry-resolved=true in each project's .npmrc, then run npm install --package-lock-only --ignore-scripts there. Direct URL dependencies must be replaced with portable dependencies."
exit 1
}
Write-Host "Checked $($lockfiles.Count) tracked npm lockfile(s): no fixed download URLs."
exit 0
}
catch {
Write-Host "Npm lockfile check failed: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
+10 -2
View File
@@ -21,6 +21,7 @@
12. Agent skills packaging - validates the ZIP deliverable (skipped for docs/validation-only commits)
13. Plugin README validation - ensures overlays are complete and not stub content
14. Dynamic cast audit - ensures ((dynamic)) casts are documented
15. Npm lockfile portability - rejects fixed download URLs in staged lockfiles
Ensures code quality and prevents regression.
@@ -35,7 +36,6 @@
$ErrorActionPreference = "Stop"
$rootDir = Split-Path -Parent $PSScriptRoot
$preCommitArtifactsDir = Join-Path $rootDir "artifacts\pre-commit"
$nugetConfigPath = Join-Path $rootDir "NuGet.Config"
$version = $null
function Invoke-ValidationStep {
@@ -140,6 +140,14 @@ if ($currentBranch -eq "main") {
Write-Host "Branch check passed - on '$currentBranch' (not main)" -ForegroundColor Green
Write-Host ""
Invoke-ValidationStep `
-Heading "Checking staged npm lockfile portability..." `
-FailureSummary "Npm lockfiles contain fixed download URLs or could not be checked." `
-SuccessSummary "Staged npm lockfile portability check passed" `
-Action {
& (Join-Path $PSScriptRoot "check-npm-lockfiles.ps1") -Staged
}
# Stop only processes owned by the selected CLI pipe before touching Release binaries.
Write-Host "Stopping pipe-owned ExcelMCP processes..." -ForegroundColor Cyan
$ownedCleanupScript = Join-Path $PSScriptRoot "Stop-ExcelMcpProcesses.ps1"
@@ -280,7 +288,7 @@ Invoke-ValidationStep `
-Action {
Push-Location $rootDir
try {
dotnet build Sbroenne.ExcelMcp.sln --configuration Release --configfile $nugetConfigPath -p:NuGetAudit=false --verbosity minimal
dotnet build Sbroenne.ExcelMcp.sln --configuration Release -p:NuGetAudit=false --verbosity minimal
}
finally {
Pop-Location
@@ -90,9 +90,23 @@ public sealed class PreCommitScriptTests
Assert.Contains("comparison-base=merge-parent", result.CombinedOutput, StringComparison.Ordinal);
}
[Fact]
[Trait("Category", "Integration")]
[Trait("Feature", "PreCommit")]
public async Task NpmLockfileFailure_BlocksEvenDocumentationOnlyCommitsBeforeCleanup()
{
var result = await RunHookAsync("FEATURES.md", npmLockfileFailure: true);
Assert.NotEqual(0, result.ExitCode);
Assert.Contains("npm-staged=True", result.CombinedOutput, StringComparison.Ordinal);
Assert.Contains("Npm lockfiles contain fixed download URLs", result.CombinedOutput, StringComparison.Ordinal);
Assert.DoesNotContain("Stopping pipe-owned", result.CombinedOutput, StringComparison.Ordinal);
}
private static async Task<ScriptResult> RunHookAsync(
string paths, int failureExitCode = 23, bool merging = false,
string failureCommand = "publish", string failureProject = "CLI", bool createArtifacts = true)
string failureCommand = "publish", string failureProject = "CLI", bool createArtifacts = true,
bool npmLockfileFailure = false)
{
var sandbox = Path.Combine(Path.GetTempPath(), $"ExcelMcpPreCommit-{Guid.NewGuid():N}");
var scripts = Path.Combine(sandbox, "scripts");
@@ -113,6 +127,11 @@ public sealed class PreCommitScriptTests
{
await File.WriteAllTextAsync(Path.Combine(scripts, $"{name}.ps1"), "$global:LASTEXITCODE = 0");
}
await File.WriteAllTextAsync(Path.Combine(scripts, "check-npm-lockfiles.ps1"), $$"""
param([switch]$Staged)
Write-Output "npm-staged=$Staged"
$global:LASTEXITCODE = {{(npmLockfileFailure ? 1 : 0)}}
""");
// Exercise the real hook in isolation: no builds, Excel processes, or real Git state.
var harness = $$"""
@@ -134,6 +153,10 @@ public sealed class PreCommitScriptTests
}
function global:dotnet {
$global:LASTEXITCODE = 0
if ($args[0] -eq 'build' -and
($args -contains '--configfile' -or $args -contains '--source')) {
throw 'Build must preserve inherited package sources.'
}
if ($args[0] -eq '{{failureCommand}}' -and $args[1] -like '*ExcelMcp.{{failureProject}}\*') {
Write-Output '{{failureCommand}}-root-cause'
Write-Error '{{failureCommand}}-stderr-cause' -ErrorAction Continue
+1
View File
@@ -0,0 +1 @@
omit-lockfile-registry-resolved=true
+1
View File
@@ -0,0 +1 @@
omit-lockfile-registry-resolved=true
-334
View File
File diff suppressed because it is too large Load Diff