diff --git a/.pnp.cjs b/.pnp.cjs index 78020d5080dc..86001450ed3b 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -14872,6 +14872,7 @@ const RAW_RUNTIME_STATE = ["virtual:08fe6ad7a76ed00f8dc32e3b968ce66fd4db8ac47424db78612ce3633e63ecb46d41984611094facf53bbef7eae7fbf98bbfd729fb77f5ccde564684f4e3a829#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-62b5fdf575/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -14882,6 +14883,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:572569575af06858e5d7f4d0dbe6c0741e76db5e6c65708522a93857213495bf1c60f4e618b217daf88fc14605c64ad49f87b67a6007ad69373fb6d52190ee49#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -14897,6 +14899,7 @@ const RAW_RUNTIME_STATE = ["virtual:10635d85d43c1773f587c2d6565f7a30c3bff1c16e39550dcdd44b3745dd69317ced5e20de16484758df2d6dc9314da646bf356d1ef8485a0dcd939b71a3327c#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-9b5e15c7a8/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -14907,6 +14910,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:10635d85d43c1773f587c2d6565f7a30c3bff1c16e39550dcdd44b3745dd69317ced5e20de16484758df2d6dc9314da646bf356d1ef8485a0dcd939b71a3327c#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -14923,6 +14927,7 @@ const RAW_RUNTIME_STATE = ["virtual:16f564b30745199d7e07a913c371ce0c078051290c6e08b972f07b3f1bf057a6993fe67b7c6ee24931d0b1dd67e1274151612081733a79b961dd8336318fdfb9#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-b849f17967/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -14933,6 +14938,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:16f564b30745199d7e07a913c371ce0c078051290c6e08b972f07b3f1bf057a6993fe67b7c6ee24931d0b1dd67e1274151612081733a79b961dd8336318fdfb9#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -14949,6 +14955,7 @@ const RAW_RUNTIME_STATE = ["virtual:1c3d72c6b31a8950672985f8306a860ecc80c9a006aac95cf4a7ba13a6e7cc4e095e37186a53c9909e9efe97bc0f7f570a74b3879778e2a2356cdcf407120006#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-d10a34a30c/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -14959,6 +14966,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:1c3d72c6b31a8950672985f8306a860ecc80c9a006aac95cf4a7ba13a6e7cc4e095e37186a53c9909e9efe97bc0f7f570a74b3879778e2a2356cdcf407120006#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -14975,6 +14983,7 @@ const RAW_RUNTIME_STATE = ["virtual:2351fd5ac4f83ad35b714d8af9fdeea561ada341d529d0dba50742dd5735dc3750df6c56bd680e14833d5b987026a1eab6618211ea0ef1b34b727372b3c77bc9#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-5066cb1bc2/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -14985,6 +14994,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:2351fd5ac4f83ad35b714d8af9fdeea561ada341d529d0dba50742dd5735dc3750df6c56bd680e14833d5b987026a1eab6618211ea0ef1b34b727372b3c77bc9#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15001,6 +15011,7 @@ const RAW_RUNTIME_STATE = ["virtual:45a6746f11cef24d8db9429cc5650999571e6bb77a8cfb3904a0e832f542be35246ec490516049308ca15b8678eb03bcf394199e514a8145ec32731af7235c91#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-1d0f0cf8f5/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15011,6 +15022,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:45a6746f11cef24d8db9429cc5650999571e6bb77a8cfb3904a0e832f542be35246ec490516049308ca15b8678eb03bcf394199e514a8145ec32731af7235c91#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15027,6 +15039,7 @@ const RAW_RUNTIME_STATE = ["virtual:4864d30fc563f2fd1b72a5e3869493c5f50bf38f98ed3886173d80c044d981c3f68220dbf17f2b5fc5b4c5fba7d0af2e003926efe3487086484049f41c449852#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-ac09774f7e/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15037,6 +15050,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:4864d30fc563f2fd1b72a5e3869493c5f50bf38f98ed3886173d80c044d981c3f68220dbf17f2b5fc5b4c5fba7d0af2e003926efe3487086484049f41c449852#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15053,6 +15067,7 @@ const RAW_RUNTIME_STATE = ["virtual:4a733c8d9614e2148392368219d98ec1a70b4e8ce99164edd551241b22f6c5233e9d0ccf9f6d83265c8a5aafc617cfd3c4100b3efef1e092a42053c23770ed9a#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-fdb17b9327/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15063,6 +15078,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:4a733c8d9614e2148392368219d98ec1a70b4e8ce99164edd551241b22f6c5233e9d0ccf9f6d83265c8a5aafc617cfd3c4100b3efef1e092a42053c23770ed9a#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15079,6 +15095,7 @@ const RAW_RUNTIME_STATE = ["virtual:4ff153bc11101851444cc464184bde5e42ffd55b3939421c30a4c2b69483c3267c1680de4a4c00a49c98cbbe35e70111bb3c26f5ce8836b703c15cd5b753451a#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-3ea9bf04ef/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15089,6 +15106,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:4ff153bc11101851444cc464184bde5e42ffd55b3939421c30a4c2b69483c3267c1680de4a4c00a49c98cbbe35e70111bb3c26f5ce8836b703c15cd5b753451a#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15105,6 +15123,7 @@ const RAW_RUNTIME_STATE = ["virtual:54c8b951e743ea46368d98ac86d4c1ac7d1aa57c9d31cbf6424fa2d918257654f26f71d51dbfe63844c533e97635ff97de50fd37e6e4bf74f2603a98754d6d22#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-d0a5a66e87/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15115,6 +15134,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:54c8b951e743ea46368d98ac86d4c1ac7d1aa57c9d31cbf6424fa2d918257654f26f71d51dbfe63844c533e97635ff97de50fd37e6e4bf74f2603a98754d6d22#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15131,6 +15151,7 @@ const RAW_RUNTIME_STATE = ["virtual:6fc63e4d1a1b8c6564cfaaeabf378b05cdf49336a90189d76df005175060690d597b069801c0c39b9c60573a6fba29e7646274224b3007bd7f72c95871114cf2#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-347ff97d4b/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15141,6 +15162,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:27ebb8cf1fa70157f710b4926b6d25c44192e74dbac3a766c8dc6505a59ebc433221bfb4b5aabc8cca814bbe95fcb6e1ecffcf94ba96ee6112a57c89364571ac#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15157,6 +15179,7 @@ const RAW_RUNTIME_STATE = ["virtual:712d04b0098634bdb13868ff8f85b327022bd7d3880873ada8c0ae56847ed36cf9da1fd74a88519380129cec528fe2bd2201426bc28ac9d4a8cc6734ff25c538#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-572569575a/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15167,6 +15190,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:572569575af06858e5d7f4d0dbe6c0741e76db5e6c65708522a93857213495bf1c60f4e618b217daf88fc14605c64ad49f87b67a6007ad69373fb6d52190ee49#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15182,6 +15206,7 @@ const RAW_RUNTIME_STATE = ["virtual:8bb72793b532d34e63bbc26264dcbcfc4dc4faa0a42627635e997081722bf229d67b7a677d86a568dad949d756630e45b9d4da97ee14b1b4c506494f8a58ea91#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-badf9df693/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15192,6 +15217,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:8bb72793b532d34e63bbc26264dcbcfc4dc4faa0a42627635e997081722bf229d67b7a677d86a568dad949d756630e45b9d4da97ee14b1b4c506494f8a58ea91#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15208,6 +15234,7 @@ const RAW_RUNTIME_STATE = ["virtual:a4e201fc3c2d8b3ec5632082d407d554bbf8ea8b84182577dde1ce419148ae0981b382a0805280637d50e1132628fef8f78ee6a015164963130b1310a4cca910#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-d0a74e03b3/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15218,6 +15245,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:a4e201fc3c2d8b3ec5632082d407d554bbf8ea8b84182577dde1ce419148ae0981b382a0805280637d50e1132628fef8f78ee6a015164963130b1310a4cca910#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15234,6 +15262,7 @@ const RAW_RUNTIME_STATE = ["virtual:a7c38e9a420fd3b408ea245831c2c9f0e880eac64b268fab3219f5f0b1d6015f44b1f92d23aabfc6e980bbbbda00a23e9faa983fb98544fab94119ccd31f2440#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-2395b4e5d3/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15244,6 +15273,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:a7c38e9a420fd3b408ea245831c2c9f0e880eac64b268fab3219f5f0b1d6015f44b1f92d23aabfc6e980bbbbda00a23e9faa983fb98544fab94119ccd31f2440#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15260,6 +15290,7 @@ const RAW_RUNTIME_STATE = ["virtual:adaf1cec8728346f1bf6a263f1954625a52d60518b8d2084da8a926203282105d2b95fb9da84922062af8d4fc84b8a1c39f220238424024e56f55577bdbc7208#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-8792f06b17/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15270,6 +15301,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:adaf1cec8728346f1bf6a263f1954625a52d60518b8d2084da8a926203282105d2b95fb9da84922062af8d4fc84b8a1c39f220238424024e56f55577bdbc7208#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15286,6 +15318,7 @@ const RAW_RUNTIME_STATE = ["virtual:b4c0e602e8ac4e01a7b08db41bb5808da767dd1f6802758faa5125fb2423614bb0a8806ee1b30c3a0769f86da15ad37377f5118d93cd93fa48df0008a448fb35#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-708f4ba711/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15296,6 +15329,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:b4c0e602e8ac4e01a7b08db41bb5808da767dd1f6802758faa5125fb2423614bb0a8806ee1b30c3a0769f86da15ad37377f5118d93cd93fa48df0008a448fb35#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15312,6 +15346,7 @@ const RAW_RUNTIME_STATE = ["virtual:b63ad861025672af62aed0e7c80dca4cfce3194ca046161e54fc14c498c39e3b82004ea844489c7a58d2f1a31867f388bf25b8128f5ccce46f35305e1f91e9ab#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-8e76aa50aa/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15322,6 +15357,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:b63ad861025672af62aed0e7c80dca4cfce3194ca046161e54fc14c498c39e3b82004ea844489c7a58d2f1a31867f388bf25b8128f5ccce46f35305e1f91e9ab#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15338,6 +15374,7 @@ const RAW_RUNTIME_STATE = ["virtual:c4bd2716e35986fb2e70f5fba6e9570c69eceabc69282df5bcff5d22c6b7d0e696d0cfb4bcbd9a20675fe3e2eb6192b59d41b97baa8b27e1d474b94eeda3f778#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-d0252a53c5/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15348,6 +15385,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:c4bd2716e35986fb2e70f5fba6e9570c69eceabc69282df5bcff5d22c6b7d0e696d0cfb4bcbd9a20675fe3e2eb6192b59d41b97baa8b27e1d474b94eeda3f778#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15364,6 +15402,7 @@ const RAW_RUNTIME_STATE = ["virtual:ce4dc3135569e847b88addae1199f9468fb0b37867e1a86ba6725f71b9df587a8ae43356ae86c3bfe3b0cbbf07dcf8c1a4a95199810d9f20df387eec0a1e1965#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-bfcf790ec1/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15374,6 +15413,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:ce4dc3135569e847b88addae1199f9468fb0b37867e1a86ba6725f71b9df587a8ae43356ae86c3bfe3b0cbbf07dcf8c1a4a95199810d9f20df387eec0a1e1965#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15390,6 +15430,7 @@ const RAW_RUNTIME_STATE = ["virtual:d1d72d9e3903ca8b8d9c23a360395cc764db2689e5992ef9af91c79f03a839db10ec675af9e4c1c8f4842aff1a614eb5b115fcc0afe8256630151ef1252de94b#workspace:packages/plugin-npm", {\ "packageLocation": "./.yarn/__virtual__/@yarnpkg-plugin-npm-virtual-87450824e1/1/packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@types/yarnpkg__core", null],\ @@ -15400,6 +15441,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:d1d72d9e3903ca8b8d9c23a360395cc764db2689e5992ef9af91c79f03a839db10ec675af9e4c1c8f4842aff1a614eb5b115fcc0afe8256630151ef1252de94b#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ @@ -15416,6 +15458,7 @@ const RAW_RUNTIME_STATE = ["workspace:packages/plugin-npm", {\ "packageLocation": "./packages/plugin-npm/",\ "packageDependencies": [\ + ["@types/micromatch", "npm:4.0.1"],\ ["@types/semver", "npm:7.5.8"],\ ["@types/ssri", "npm:7.1.5"],\ ["@yarnpkg/core", "workspace:packages/yarnpkg-core"],\ @@ -15424,6 +15467,7 @@ const RAW_RUNTIME_STATE = ["@yarnpkg/plugin-pack", "virtual:572569575af06858e5d7f4d0dbe6c0741e76db5e6c65708522a93857213495bf1c60f4e618b217daf88fc14605c64ad49f87b67a6007ad69373fb6d52190ee49#workspace:packages/plugin-pack"],\ ["enquirer", "npm:2.3.6"],\ ["es-toolkit", "npm:1.39.7"],\ + ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.6.0"],\ ["sigstore", "npm:3.1.0"],\ ["ssri", "npm:12.0.0"],\ diff --git a/.yarn/versions/25eb93a2.yml b/.yarn/versions/25eb93a2.yml new file mode 100644 index 000000000000..b8af1f116800 --- /dev/null +++ b/.yarn/versions/25eb93a2.yml @@ -0,0 +1,24 @@ +releases: + "@yarnpkg/cli": minor + "@yarnpkg/plugin-npm": minor + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-nm" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-pnpm" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/core" + - "@yarnpkg/doctor" diff --git a/packages/acceptance-tests/pkg-tests-core/sources/utils/makeTemporaryEnv.ts b/packages/acceptance-tests/pkg-tests-core/sources/utils/makeTemporaryEnv.ts index 415b1ad18aa1..f7acc8cd7e34 100644 --- a/packages/acceptance-tests/pkg-tests-core/sources/utils/makeTemporaryEnv.ts +++ b/packages/acceptance-tests/pkg-tests-core/sources/utils/makeTemporaryEnv.ts @@ -18,7 +18,7 @@ const mte = generatePkgDriver({ ) { const rcEnv: Record = {}; for (const [key, value] of Object.entries(config)) - rcEnv[`YARN_${key.replace(/([A-Z])/g, `_$1`).toUpperCase()}`] = Array.isArray(value) ? value.join(`;`) : value; + rcEnv[`YARN_${key.replace(/([A-Z])/g, `_$1`).toUpperCase()}`] = Array.isArray(value) ? value.join(`,`) : value; const nativePath = npath.fromPortablePath(path); const nativeHomePath = npath.dirname(nativePath); diff --git a/packages/acceptance-tests/pkg-tests-core/sources/utils/tests.ts b/packages/acceptance-tests/pkg-tests-core/sources/utils/tests.ts index 40e4efc26647..49a68ae769d9 100644 --- a/packages/acceptance-tests/pkg-tests-core/sources/utils/tests.ts +++ b/packages/acceptance-tests/pkg-tests-core/sources/utils/tests.ts @@ -46,7 +46,7 @@ export const TEST_TIMEOUT = os.endianness() === `BE` ? 300000 : 75000; -export type PackageEntry = Map}>; +export type PackageEntry = Map, releaseDate: string | undefined}>; export type PackageRegistry = Map; interface RunDriverOptions extends Record { @@ -177,6 +177,25 @@ export const ADVISORIES = new Map>([ }]], ]); +const RELEASE_DATE_PACKAGES: Record> = { + "release-date": { + "1.0.0": new Date(new Date().getTime() - /* 10 days */ 1000 * 60 * 60 * 24 * 10).toISOString(), + "1.1.0": new Date(new Date().getTime() - /* 5 days */ 1000 * 60 * 60 * 24 * 5).toISOString(), + "1.1.1": new Date().toISOString(), + }, + "release-date-transitive": { + "1.0.0": new Date(new Date().getTime() - /* 10 days */ 1000 * 60 * 60 * 24 * 10).toISOString(), + "1.1.0": new Date(new Date().getTime() - /* 5 days */ 1000 * 60 * 60 * 24 * 5).toISOString(), + "1.1.1": new Date().toISOString(), + }, + "@scoped/release-date": { + "1.0.0": new Date(new Date().getTime() - /* 10 days */ 1000 * 60 * 60 * 24 * 10).toISOString(), + "1.1.0": new Date(new Date().getTime() - /* 5 days */ 1000 * 60 * 60 * 24 * 5).toISOString(), + "1.1.1": new Date().toISOString(), + "1.1.2": new Date(new Date().getTime() - /* 5 days */ 1000 * 60 * 60 * 24 * 5).toISOString(), + }, +}; + export const validLogins = { fooUser: new Login(`foo-user`), barUser: new Login(`bar-user`), @@ -233,7 +252,7 @@ export const getPackageRegistry = (): Promise => { const packageFile = ppath.join(packagesDir, packageName, Filename.manifest); const packageJson = await xfs.readJsonPromise(packageFile); - const {name, version} = packageJson; + const {name, version}: {name: string, version: string} = packageJson; if (name.startsWith(`git-`)) continue; @@ -422,6 +441,7 @@ export const startPackageServer = ({type}: {type: keyof typeof packageServerUrls }), )), ), + time: name in RELEASE_DATE_PACKAGES ? RELEASE_DATE_PACKAGES[name] : undefined, [`dist-tags`]: { latest: semver.maxSatisfying(versions, `*`), ...distTags, diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.0.0/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.0.0/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.0.0/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.0.0/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.0.0/package.json new file mode 100644 index 000000000000..ce451ff8ffe7 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.0.0/package.json @@ -0,0 +1,7 @@ +{ + "name": "@scoped/release-date", + "version": "1.0.0", + "dist-tags": { + "latest": "1.1.1" + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.0/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.0/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.0/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.0/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.0/package.json new file mode 100644 index 000000000000..cddbb810f4cd --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.0/package.json @@ -0,0 +1,7 @@ +{ + "name": "@scoped/release-date", + "version": "1.1.0", + "dist-tags": { + "latest": "1.1.1" + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.1/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.1/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.1/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.1/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.1/package.json new file mode 100644 index 000000000000..1f68e0fd8572 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.1/package.json @@ -0,0 +1,7 @@ +{ + "name": "@scoped/release-date", + "version": "1.1.1", + "dist-tags": { + "latest": "1.1.1" + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.2/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.2/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.2/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.2/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.2/package.json new file mode 100644 index 000000000000..a427cbd6e053 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/@scoped__release-date-1.1.2/package.json @@ -0,0 +1,7 @@ +{ + "name": "@scoped/release-date", + "version": "1.1.2", + "dist-tags": { + "latest": "1.1.1" + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.0.0/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.0.0/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.0.0/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.0.0/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.0.0/package.json new file mode 100644 index 000000000000..614d91d2f23b --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.0.0/package.json @@ -0,0 +1,7 @@ +{ + "name": "release-date", + "version": "1.0.0", + "dependencies": { + "release-date-transitive": "^1.0.0" + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.0/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.0/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.0/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.0/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.0/package.json new file mode 100644 index 000000000000..4b022847f964 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.0/package.json @@ -0,0 +1,7 @@ +{ + "name": "release-date", + "version": "1.1.0", + "dependencies": { + "release-date-transitive": "^1.0.0" + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.1/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.1/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.1/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.1/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.1/package.json new file mode 100644 index 000000000000..dad165c13ffa --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-1.1.1/package.json @@ -0,0 +1,7 @@ +{ + "name": "release-date", + "version": "1.1.1", + "dependencies": { + "release-date-transitive": "^1.0.0" + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.0.0/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.0.0/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.0.0/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.0.0/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.0.0/package.json new file mode 100644 index 000000000000..1bcdccc6631b --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.0.0/package.json @@ -0,0 +1,4 @@ +{ + "name": "release-date-transitive", + "version": "1.0.0" +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.0/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.0/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.0/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.0/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.0/package.json new file mode 100644 index 000000000000..059e4fc477f1 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.0/package.json @@ -0,0 +1,4 @@ +{ + "name": "release-date-transitive", + "version": "1.1.0" +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.1/index.js b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.1/index.js new file mode 100644 index 000000000000..bb9c6f687615 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.1/index.js @@ -0,0 +1,7 @@ +module.exports = require(`./package.json`); + +for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) { + for (const dep of Object.keys(module.exports[key] || {})) { + module.exports[key][dep] = require(dep); + } +} diff --git a/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.1/package.json b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.1/package.json new file mode 100644 index 000000000000..89d229c39d22 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-fixtures/packages/release-date-transitive-1.1.1/package.json @@ -0,0 +1,4 @@ +{ + "name": "release-date-transitive", + "version": "1.1.1" +} diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/npmMinimalAgeGate.test.ts b/packages/acceptance-tests/pkg-tests-specs/sources/features/npmMinimalAgeGate.test.ts new file mode 100644 index 000000000000..728183476cf6 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-specs/sources/features/npmMinimalAgeGate.test.ts @@ -0,0 +1,375 @@ +const ONE_DAY_IN_MINUTES = 24 * 60; + +describe(`Features`, () => { + describe(`npmMinimalAgeGate and npmPreapprovedPackages`, () => { + describe(`add`, () => { + test( + `add should install the latest version allowed by the minimum release age`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`add`, `release-date`); + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.0`, + }); + }), + ); + + test( + `it should fail when trying to install exact version that is newer than the minimum release age`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run}) => { + await expect(run(`add`, `release-date@1.1.1`)).rejects.toThrowError(`No candidates found`); + }), + ); + + test( + `it should install older package versions when the minimum release age disallows the newest suitable version`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`add`, `release-date@^1.0.0`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.0`, + }); + }), + ); + + test( + `it should install new version when excluded by a descriptor; while transitive dependencies are not excluded`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`release-date@^1.0.0`], + }, async ({run, source}) => { + await run(`add`, `release-date@^1.0.0`); + + await expect(source(`require('release-date')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + dependencies: { + [`release-date-transitive`]: { + name: `release-date-transitive`, + version: `1.1.0`, + }, + }, + }); + }), + ); + + test( + `it should install new version when excluded by package ident`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`release-date`], + }, async ({run, source}) => { + await run(`add`, `release-date@^1.0.0`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + }); + }), + ); + + test( + `it should not impact semver prioritization of newer versions when multiple versions meet the age requirement`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: 0, + }, async ({run, source}) => { + await run(`add`, `release-date@^1.0.0`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + }); + }), + ); + + test( + `it should work with scoped packages`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run}) => { + await expect(run(`add`, `@scoped/release-date@1.1.1`)).rejects.toThrowError(`No candidates found`); + }), + ); + + test( + `it should install scoped package when excluded`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`@scoped/release-date`], + }, async ({run, source}) => { + await run(`add`, `@scoped/release-date@^1.0.0`); + + await expect(source(`require('@scoped/release-date/package.json')`)).resolves.toMatchObject({ + name: `@scoped/release-date`, + version: `1.1.2`, + }); + }), + ); + + test( + `it should install scoped package when excluded by scoped glob pattern`, + makeTemporaryEnv({}, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`@scoped/*`], + }, async ({run, source}) => { + await run(`add`, `@scoped/release-date@^1.0.0`); + + await expect(source(`require('@scoped/release-date/package.json')`)).resolves.toMatchObject({ + name: `@scoped/release-date`, + version: `1.1.2`, + }); + }), + ); + + test( + `it should not install a version via add that is higher than the latest tag`, + makeTemporaryEnv({ + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`add`, `@scoped/release-date`); + + await expect(source(`require('@scoped/release-date/package.json')`)).resolves.toMatchObject({ + name: `@scoped/release-date`, + version: `1.1.0`, + }); + }), + ); + }); + describe(`install`, () => { + test( + `it should fail when trying to install exact version that is too new`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `1.1.1`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run}) => { + await expect(run(`install`)).rejects.toThrowError(`No candidates found`); + }), + ); + + test( + `it should install older package versions when the minimum release age disallows the newest suitable version`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.0`, + }); + }), + ); + + test( + `it should install new version when excluded by a descriptor`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`release-date@^1.0.0`], + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + }); + }), + ); + + test( + `it should install new version when excluded by package name glob pattern`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`release-*`], + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + }); + }), + ); + + test( + `it should install new version when excluded by package ident`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`release-date`], + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + }); + }), + ); + + test( + `it should not impact semver prioritization of newer versions when multiple versions meet the age requirement`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: 0, + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + }); + }), + ); + + test( + `it should work with scoped packages`, + makeTemporaryEnv({ + dependencies: {[`@scoped/release-date`]: `1.1.1`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run}) => { + await expect(run(`install`)).rejects.toThrowError(`No candidates found`); + }), + ); + + test( + `it should install scoped package when excluded`, + makeTemporaryEnv({ + dependencies: {[`@scoped/release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`@scoped/release-date`], + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('@scoped/release-date/package.json')`)).resolves.toMatchObject({ + name: `@scoped/release-date`, + version: `1.1.2`, + }); + }), + ); + + test( + `it should install scoped package when excluded by scoped glob pattern`, + makeTemporaryEnv({ + dependencies: {[`@scoped/release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + npmPreapprovedPackages: [`@scoped/*`], + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('@scoped/release-date/package.json')`)).resolves.toMatchObject({ + name: `@scoped/release-date`, + version: `1.1.2`, + }); + }), + ); + + test( + `it should not install a version that is higher than the latest tag`, + makeTemporaryEnv({ + dependencies: {[`@scoped/release-date`]: `latest`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`install`); + + await expect(source(`require('@scoped/release-date/package.json')`)).resolves.toMatchObject({ + name: `@scoped/release-date`, + version: `1.1.0`, + }); + }), + ); + }); + describe(`up`, () => { + test( + `it should update to the latest version allowed by the minimum release age`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`install`); + await run(`set`, `resolution`, `release-date@npm:^1.0.0`, `npm:1.0.0`); + + const preUpVersion = (await source(`require('release-date/package.json')`)).version; + if (preUpVersion !== `1.0.0`) + throw new Error(`Pre-up version is not 1.0.0`); + + await run(`up`, `release-date`); + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.0`, + }); + }), + ); + test( + `recursive should update to the latest version allowed by the minimum release age`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, { + // we are checking a transitive dependencies version, which the pnp will throw an error for + // disabling these checks for the purpose of this test + pnpFallbackMode: `all`, + pnpMode: `loose`, + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`install`); + await run(`set`, `resolution`, `release-date@npm:^1.0.0`, `npm:1.0.0`); + await run(`set`, `resolution`, `release-date-transitive@npm:^1.0.0`, `npm:1.0.0`); + + const preUpVersion = (await source(`require('release-date/package.json')`)).version; + const preUpVersionTransitive = (await source(`require('release-date/package.json')`)).version; + if (preUpVersion !== `1.0.0` || preUpVersionTransitive !== `1.0.0`) + throw new Error(`Pre-up version is not 1.0.0`); + + await run(`up`, `-R`, `*`); + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.0`, + }); + await expect(source(`require('release-date-transitive/package.json')`)).resolves.toMatchObject({ + name: `release-date-transitive`, + version: `1.1.0`, + }); + }), + ); + + test( + `it should not update to a version that is higher than the latest tag`, + makeTemporaryEnv({ + dependencies: {[`@scoped/release-date`]: `^1.0.0`}, + }, { + npmMinimalAgeGate: ONE_DAY_IN_MINUTES, + }, async ({run, source}) => { + await run(`set`, `resolution`, `@scoped/release-date@npm:^1.0.0`, `npm:1.0.0`); + + await run(`up`, `@scoped/release-date`); + + await expect(source(`require('@scoped/release-date/package.json')`)).resolves.toMatchObject({ + name: `@scoped/release-date`, + version: `1.1.0`, + }); + }), + ); + }); + }); +}); diff --git a/packages/docusaurus/static/configuration/yarnrc.json b/packages/docusaurus/static/configuration/yarnrc.json index 814dc030603a..d875cf4cc3e2 100644 --- a/packages/docusaurus/static/configuration/yarnrc.json +++ b/packages/docusaurus/static/configuration/yarnrc.json @@ -479,6 +479,24 @@ "type": "string", "default": "pnp" }, + "npmMinimalAgeGate": { + "_package": "@yarnpkg/core", + "title": "Minimum age of a package version according to the publish date on the npm registry in minutes to be considered for installation.", + "description": "If a package version is newer than the minimal age gate, it will not be considered for installation. This can be used to reduce the likelihood of installing compromised packages.", + "type": "number", + "default": 0 + }, + "npmPreapprovedPackages": { + "_package": "@yarnpkg/core", + "title": "Array of package descriptors or package name glob patterns to exclude from all of the package gates.", + "description": "If a package descriptor or name matches the specified pattern, it will not be considered when evaluating any of the package gates.", + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "examples": ["@scoped-package/*", "package", "package*", "package@^1.0.0", "package@1.0.0"] + }, "pnpmStoreFolder": { "_package": "@yarnpkg/plugin-pnpm", "title": "Path where the pnpm store will be stored", diff --git a/packages/plugin-npm/package.json b/packages/plugin-npm/package.json index 6979e9a8b768..22c9b9a9a0d1 100644 --- a/packages/plugin-npm/package.json +++ b/packages/plugin-npm/package.json @@ -11,6 +11,7 @@ "@yarnpkg/fslib": "workspace:^", "enquirer": "^2.3.6", "es-toolkit": "^1.39.7", + "micromatch": "^4.0.2", "semver": "^7.1.2", "sigstore": "^3.1.0", "ssri": "^12.0.0", @@ -21,6 +22,7 @@ "@yarnpkg/plugin-pack": "workspace:^" }, "devDependencies": { + "@types/micromatch": "^4.0.1", "@types/semver": "^7.1.0", "@types/ssri": "^7.1.5", "@yarnpkg/core": "workspace:^", diff --git a/packages/plugin-npm/sources/NpmSemverResolver.ts b/packages/plugin-npm/sources/NpmSemverResolver.ts index 34b545f01df6..7d03d762519e 100644 --- a/packages/plugin-npm/sources/NpmSemverResolver.ts +++ b/packages/plugin-npm/sources/NpmSemverResolver.ts @@ -6,6 +6,7 @@ import semver import {NpmSemverFetcher} from './NpmSemverFetcher'; import {PROTOCOL} from './constants'; +import {isPackageApproved} from './npmConfigUtils'; import * as npmHttpUtils from './npmHttpUtils'; const NODE_GYP_IDENT = structUtils.makeIdent(null, `node-gyp`); @@ -57,6 +58,9 @@ export class NpmSemverResolver implements Resolver { try { const candidate = new semverUtils.SemVer(version); if (range.test(candidate)) { + if (!isPackageApproved({configuration: opts.project.configuration, ident: descriptor, version, publishTimes: registryData.time})) + return miscUtils.mapAndFilter.skip; + return candidate; } } catch { } diff --git a/packages/plugin-npm/sources/NpmTagResolver.ts b/packages/plugin-npm/sources/NpmTagResolver.ts index 9ced3a9e0365..45eb84e70ca0 100644 --- a/packages/plugin-npm/sources/NpmTagResolver.ts +++ b/packages/plugin-npm/sources/NpmTagResolver.ts @@ -5,6 +5,7 @@ import semver import {NpmSemverFetcher} from './NpmSemverFetcher'; import {PROTOCOL} from './constants'; +import {isPackageApproved} from './npmConfigUtils'; import * as npmHttpUtils from './npmHttpUtils'; export class NpmTagResolver implements Resolver { @@ -52,7 +53,22 @@ export class NpmTagResolver implements Resolver { if (!Object.hasOwn(distTags, tag)) throw new ReportError(MessageName.REMOTE_NOT_FOUND, `Registry failed to return tag "${tag}"`); - const version = distTags[tag]; + const versions = Object.keys(registryData.versions); + const times = registryData.time; + + let version = distTags[tag]; + + if (tag === `latest` && !isPackageApproved({configuration: opts.project.configuration, ident: descriptor, version, publishTimes: times})) { + const nextVersion = semver.rsort(versions).find(candidateVersion => { + return semver.lt(candidateVersion, version) && isPackageApproved({configuration: opts.project.configuration, ident: descriptor, version: candidateVersion, publishTimes: times}); + }); + + if (!nextVersion) + throw new ReportError(MessageName.REMOTE_NOT_FOUND, `The version for tag "${tag}" is quarantined, and no lower version is available`); + + version = nextVersion; + } + const versionLocator = structUtils.makeLocator(descriptor, `${PROTOCOL}${version}`); const archiveUrl = registryData.versions[version].dist.tarball; diff --git a/packages/plugin-npm/sources/index.ts b/packages/plugin-npm/sources/index.ts index 8e2f27663935..3c1cf5b15827 100644 --- a/packages/plugin-npm/sources/index.ts +++ b/packages/plugin-npm/sources/index.ts @@ -67,6 +67,20 @@ const registrySettings = { }, }; +const packageGateSettings = { + npmMinimalAgeGate: { + description: `Minimum age of a package version according to the publish date on the npm registry in minutes to be considered for installation`, + type: SettingsType.NUMBER as const, + default: 0, + }, + npmPreapprovedPackages: { + description: `Array of package descriptors or package name glob patterns to exclude from the minimum release age check`, + type: SettingsType.STRING as const, + isArray: true as const, + default: [], + }, +}; + declare module '@yarnpkg/core' { interface ConfigurationValueMap { npmAlwaysAuth: boolean; @@ -77,6 +91,9 @@ declare module '@yarnpkg/core' { npmPublishRegistry: string | null; npmRegistryServer: string; + npmMinimalAgeGate: number; + npmPreapprovedPackages: Array; + npmScopes: Map; +}; + +function isPreapproved({configuration, ident, version}: IsPackageApprovedOptions) { + return configuration.get(`npmPreapprovedPackages`).some(entry => { + return checkIdent(ident, version, entry); + }); +} + +export function isPackageApproved(params: IsPackageApprovedOptions) { + return !shouldBeQuarantined(params) || isPreapproved(params); +} diff --git a/packages/plugin-npm/sources/npmHttpUtils.ts b/packages/plugin-npm/sources/npmHttpUtils.ts index d5543ec67d09..b932ddaa569a 100644 --- a/packages/plugin-npm/sources/npmHttpUtils.ts +++ b/packages/plugin-npm/sources/npmHttpUtils.ts @@ -286,6 +286,7 @@ export type PackageMetadata = { tarball: string; }; }>; + time: Record; }; function pickPackageMetadata(metadata: PackageMetadata): PackageMetadata { @@ -295,6 +296,7 @@ function pickPackageMetadata(metadata: PackageMetadata): PackageMetadata { key, pick(value, CACHED_FIELDS) as any, ])), + time: metadata.time, }; } diff --git a/yarn.lock b/yarn.lock index d1a620ef7391..73c062e9d1df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6440,6 +6440,7 @@ __metadata: version: 0.0.0-use.local resolution: "@yarnpkg/plugin-npm@workspace:packages/plugin-npm" dependencies: + "@types/micromatch": "npm:^4.0.1" "@types/semver": "npm:^7.1.0" "@types/ssri": "npm:^7.1.5" "@yarnpkg/core": "workspace:^" @@ -6447,6 +6448,7 @@ __metadata: "@yarnpkg/plugin-pack": "workspace:^" enquirer: "npm:^2.3.6" es-toolkit: "npm:^1.39.7" + micromatch: "npm:^4.0.2" semver: "npm:^7.1.2" sigstore: "npm:^3.1.0" ssri: "npm:^12.0.0"