Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .yarn/versions/0a4c10c5.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
releases:
"@yarnpkg/cli": minor
"@yarnpkg/core": minor
"@yarnpkg/plugin-npm": minor

declined:
- "@yarnpkg/plugin-catalog"
- "@yarnpkg/plugin-compat"
- "@yarnpkg/plugin-constraints"
- "@yarnpkg/plugin-dlx"
- "@yarnpkg/plugin-essentials"
- "@yarnpkg/plugin-exec"
- "@yarnpkg/plugin-file"
- "@yarnpkg/plugin-git"
- "@yarnpkg/plugin-github"
- "@yarnpkg/plugin-http"
- "@yarnpkg/plugin-init"
- "@yarnpkg/plugin-interactive-tools"
- "@yarnpkg/plugin-jsr"
- "@yarnpkg/plugin-link"
- "@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/doctor"
- "@yarnpkg/extensions"
- "@yarnpkg/nm"
- "@yarnpkg/pnpify"
- "@yarnpkg/sdks"
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
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,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`add`, `release-date`);
await expect(source(`require('release-date/package.json')`)).resolves.toMatchObject({
Expand All @@ -19,7 +17,7 @@ describe(`Features`, () => {
test(
`it should fail when trying to install exact version that is newer than the minimum release age`,
makeTemporaryEnv({}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run}) => {
await expect(run(`add`, `[email protected]`)).rejects.toThrowError(`No candidates found`);
}),
Expand All @@ -28,7 +26,7 @@ describe(`Features`, () => {
test(
`it should install older package versions when the minimum release age disallows the newest suitable version`,
makeTemporaryEnv({}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`add`, `release-date@^1.0.0`);

Expand All @@ -42,7 +40,7 @@ describe(`Features`, () => {
test(
`it should install new version when excluded by a descriptor; while transitive dependencies are not excluded`,
makeTemporaryEnv({}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`release-date@^1.0.0`],
}, async ({run, source}) => {
await run(`add`, `release-date@^1.0.0`);
Expand All @@ -63,7 +61,7 @@ describe(`Features`, () => {
test(
`it should install new version when excluded by package ident`,
makeTemporaryEnv({}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`release-date`],
}, async ({run, source}) => {
await run(`add`, `release-date@^1.0.0`);
Expand Down Expand Up @@ -92,7 +90,7 @@ describe(`Features`, () => {
test(
`it should work with scoped packages`,
makeTemporaryEnv({}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run}) => {
await expect(run(`add`, `@scoped/[email protected]`)).rejects.toThrowError(`No candidates found`);
}),
Expand All @@ -101,7 +99,7 @@ describe(`Features`, () => {
test(
`it should install scoped package when excluded`,
makeTemporaryEnv({}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`@scoped/release-date`],
}, async ({run, source}) => {
await run(`add`, `@scoped/release-date@^1.0.0`);
Expand All @@ -116,7 +114,7 @@ describe(`Features`, () => {
test(
`it should install scoped package when excluded by scoped glob pattern`,
makeTemporaryEnv({}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`@scoped/*`],
}, async ({run, source}) => {
await run(`add`, `@scoped/release-date@^1.0.0`);
Expand All @@ -132,7 +130,7 @@ describe(`Features`, () => {
`it should not install a version via add that is higher than the latest tag`,
makeTemporaryEnv({
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`add`, `@scoped/release-date`);

Expand All @@ -149,7 +147,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`release-date`]: `1.1.1`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run}) => {
await expect(run(`install`)).rejects.toThrowError(`No candidates found`);
}),
Expand All @@ -160,7 +158,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`install`);

Expand All @@ -176,7 +174,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`release-date@^1.0.0`],
}, async ({run, source}) => {
await run(`install`);
Expand All @@ -193,7 +191,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`release-*`],
}, async ({run, source}) => {
await run(`install`);
Expand All @@ -210,7 +208,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`release-date`],
}, async ({run, source}) => {
await run(`install`);
Expand Down Expand Up @@ -243,7 +241,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`@scoped/release-date`]: `1.1.1`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run}) => {
await expect(run(`install`)).rejects.toThrowError(`No candidates found`);
}),
Expand All @@ -254,7 +252,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`@scoped/release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`@scoped/release-date`],
}, async ({run, source}) => {
await run(`install`);
Expand All @@ -271,7 +269,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`@scoped/release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
npmPreapprovedPackages: [`@scoped/*`],
}, async ({run, source}) => {
await run(`install`);
Expand All @@ -288,7 +286,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`@scoped/release-date`]: `latest`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`install`);

Expand All @@ -305,7 +303,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`install`);
await run(`set`, `resolution`, `release-date@npm:^1.0.0`, `npm:1.0.0`);
Expand All @@ -330,7 +328,7 @@ describe(`Features`, () => {
// disabling these checks for the purpose of this test
pnpFallbackMode: `all`,
pnpMode: `loose`,
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`install`);
await run(`set`, `resolution`, `release-date@npm:^1.0.0`, `npm:1.0.0`);
Expand Down Expand Up @@ -358,7 +356,7 @@ describe(`Features`, () => {
makeTemporaryEnv({
dependencies: {[`@scoped/release-date`]: `^1.0.0`},
}, {
npmMinimalAgeGate: ONE_DAY_IN_MINUTES,
npmMinimalAgeGate: `1d`,
}, async ({run, source}) => {
await run(`set`, `resolution`, `@scoped/release-date@npm:^1.0.0`, `npm:1.0.0`);

Expand Down
30 changes: 21 additions & 9 deletions packages/docusaurus/static/configuration/yarnrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,13 @@
},
"httpTimeout": {
"_package": "@yarnpkg/core",
"title": "Amount of time to wait in milliseconds before cancelling pending HTTP requests.",
"type": "number",
"default": 60000
"title": "Amount of time to wait before cancelling pending HTTP requests.",
"type": "mixed",
"oneOf": [
{ "type": "number" },
{ "type": "string", "pattern": "^(\\d*\\.?\\d+)(ms|s|m|h|d|w)?$" }
],
"default": "1m"
},
"httpsCaFilePath": {
"_package": "@yarnpkg/core",
Expand Down Expand Up @@ -481,10 +485,14 @@
},
"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.",
"title": "Minimum age of a package version according to the publish date on the npm registry 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
"type": "mixed",
"oneOf": [
{ "type": "number" },
{ "type": "string", "pattern": "^(\\d*\\.?\\d+)(ms|s|m|h|d|w)?$" }
],
"default": "0m"
},
"npmPreapprovedPackages": {
"_package": "@yarnpkg/core",
Expand Down Expand Up @@ -851,10 +859,14 @@
},
"telemetryInterval": {
"_package": "@yarnpkg/core",
"title": "Define the minimal amount of time between two telemetry events, in days.",
"title": "Define the minimal amount of time between two telemetry events.",
"description": "By default we only send one request per week, making it impossible for us to track your usage with a lower granularity.",
"type": "number",
"default": 7
"type": "mixed",
"oneOf": [
{ "type": "number" },
{ "type": "string", "pattern": "^(\\d*\\.?\\d+)(ms|s|m|h|d|w)?$" }
],
"default": "7d"
},
"telemetryUserId": {
"_package": "@yarnpkg/core",
Expand Down
50 changes: 26 additions & 24 deletions packages/plugin-npm/sources/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {Plugin, SettingsType, miscUtils, Configuration, Ident} from '@yarnpkg/core';

import {NpmHttpFetcher} from './NpmHttpFetcher';
import {NpmRemapResolver} from './NpmRemapResolver';
import {NpmSemverFetcher} from './NpmSemverFetcher';
import {NpmSemverResolver} from './NpmSemverResolver';
import {NpmTagResolver} from './NpmTagResolver';
import * as npmConfigUtils from './npmConfigUtils';
import * as npmHttpUtils from './npmHttpUtils';
import * as npmPublishUtils from './npmPublishUtils';
import {Plugin, SettingsType, DurationUnit, miscUtils, Configuration, Ident} from '@yarnpkg/core';
import type {SettingsDefinition} from '@yarnpkg/core';

import {NpmHttpFetcher} from './NpmHttpFetcher';
import {NpmRemapResolver} from './NpmRemapResolver';
import {NpmSemverFetcher} from './NpmSemverFetcher';
import {NpmSemverResolver} from './NpmSemverResolver';
import {NpmTagResolver} from './NpmTagResolver';
import * as npmConfigUtils from './npmConfigUtils';
import * as npmHttpUtils from './npmHttpUtils';
import * as npmPublishUtils from './npmPublishUtils';

export {npmConfigUtils};
export {npmHttpUtils};
Expand All @@ -34,52 +35,53 @@ export interface Hooks {
const authSettings = {
npmAlwaysAuth: {
description: `URL of the selected npm registry (note: npm enterprise isn't supported)`,
type: SettingsType.BOOLEAN as const,
type: SettingsType.BOOLEAN,
default: false,
},
npmAuthIdent: {
description: `Authentication identity for the npm registry (_auth in npm and yarn v1)`,
type: SettingsType.SECRET as const,
type: SettingsType.SECRET,
default: null,
},
npmAuthToken: {
description: `Authentication token for the npm registry (_authToken in npm and yarn v1)`,
type: SettingsType.SECRET as const,
type: SettingsType.SECRET,
default: null,
},
};
} satisfies Record<string, SettingsDefinition>;

const registrySettings = {
npmAuditRegistry: {
description: `Registry to query for audit reports`,
type: SettingsType.STRING as const,
type: SettingsType.STRING,
default: null,
},
npmPublishRegistry: {
description: `Registry to push packages to`,
type: SettingsType.STRING as const,
type: SettingsType.STRING,
default: null,
},
npmRegistryServer: {
description: `URL of the selected npm registry (note: npm enterprise isn't supported)`,
type: SettingsType.STRING as const,
type: SettingsType.STRING,
default: `https://registry.yarnpkg.com`,
},
};
} satisfies Record<string, SettingsDefinition>;

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,
description: `Minimum age of a package version according to the publish date on the npm registry to be considered for installation`,
type: SettingsType.DURATION,
unit: DurationUnit.MINUTES,
default: `0m`,
},
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,
type: SettingsType.STRING,
isArray: true,
default: [],
},
};
} satisfies Record<string, SettingsDefinition>;

declare module '@yarnpkg/core' {
interface ConfigurationValueMap {
Expand Down
Loading
Loading