From c41c79b7773aa561a2bc41f8258a3df13529add1 Mon Sep 17 00:00:00 2001 From: Hamidreza Hanafi Date: Sat, 14 Feb 2026 10:56:17 -0500 Subject: [PATCH 1/2] zpm-config: accept numeric scalar values for interpolated settings Allow interpolated configuration fields to deserialize numeric YAML scalars by converting them to strings before parsing. This preserves existing string interpolation behavior while fixing configs like npmMinimalAgeGate: 0. Co-authored-by: Cursor --- packages/zpm-config/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/zpm-config/src/lib.rs b/packages/zpm-config/src/lib.rs index b4b361d3..f0c37709 100644 --- a/packages/zpm-config/src/lib.rs +++ b/packages/zpm-config/src/lib.rs @@ -119,6 +119,8 @@ impl<'de, T: FromFileString + Deserialize<'de>> Deserialize<'de> for Interpolate #[serde(untagged)] enum StringOrAnything { String(String), + Integer(i64), + Float(f64), Anything(T), } @@ -135,6 +137,22 @@ impl<'de, T: FromFileString + Deserialize<'de>> Deserialize<'de> for Interpolate Ok(Interpolated::new(hydrated)) }, + StringOrAnything::Integer(value) => { + let hydrated + = T::from_file_string(&value.to_string()) + .map_err(de::Error::custom)?; + + Ok(Interpolated::new(hydrated)) + }, + + StringOrAnything::Float(value) => { + let hydrated + = T::from_file_string(&value.to_string()) + .map_err(de::Error::custom)?; + + Ok(Interpolated::new(hydrated)) + }, + StringOrAnything::Anything(anything) => { Ok(Interpolated::new(anything)) }, From 7853d62f0e6efb521de33f7f477bb390d01ebaef Mon Sep 17 00:00:00 2001 From: Hamidreza Hanafi Date: Tue, 17 Feb 2026 16:32:53 -0500 Subject: [PATCH 2/2] tests: cover numeric npmMinimalAgeGate from .yarnrc.yml Add an acceptance test that writes npmMinimalAgeGate as a numeric YAML scalar in .yarnrc.yml and verifies install succeeds. This exercises file-based config parsing rather than env-based overrides. Co-authored-by: Cursor --- .../features/npmMinimalAgeGate.test.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/acceptance-tests/pkg-tests-specs/sources/features/npmMinimalAgeGate.test.ts b/tests/acceptance-tests/pkg-tests-specs/sources/features/npmMinimalAgeGate.test.ts index 34d1c080..e1ead87a 100644 --- a/tests/acceptance-tests/pkg-tests-specs/sources/features/npmMinimalAgeGate.test.ts +++ b/tests/acceptance-tests/pkg-tests-specs/sources/features/npmMinimalAgeGate.test.ts @@ -1,3 +1,7 @@ +const { + fs: {writeFile}, +} = require(`pkg-tests-core`); + describe(`Features`, () => { describe(`npmMinimalAgeGate and npmPreapprovedPackages`, () => { describe(`add`, () => { @@ -142,6 +146,22 @@ describe(`Features`, () => { ); }); describe(`install`, () => { + test( + `it should parse numeric npmMinimalAgeGate from .yarnrc.yml`, + makeTemporaryEnv({ + dependencies: {[`release-date`]: `^1.0.0`}, + }, async ({path, run, source}) => { + await writeFile(`${path}/.yarnrc.yml`, `npmMinimalAgeGate: 0\n`); + + await run(`install`); + + await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({ + name: `release-date`, + version: `1.1.1`, + }); + }), + ); + test( `it should fail when trying to install exact version that is too new`, makeTemporaryEnv({