From 306e7ca752b0cd8594fd42eed7f8699a9f2ef64d Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Tue, 14 Apr 2026 11:07:10 -0700 Subject: [PATCH 1/2] feat!: omit license field by default when initializing package.json BREAKING CHANGE: The license field is no longer included by default when running `npm init` or `npm init --yes`. If you want to include a license, you can either set it in your npm config (`npm set init-license=MIT`) or provide it interactively when running `npm init`. --- lib/default-input.js | 26 ++++++++++++++++++++------ lib/init-package-json.js | 5 +++++ test/dependencies.js | 1 - test/license.js | 40 ++++++++++++++++++++++++++++++++++++++-- test/name-spaces.js | 2 -- test/name-uppercase.js | 1 - test/scope-in-config.js | 1 - test/yes-defaults.js | 2 +- 8 files changed, 64 insertions(+), 14 deletions(-) diff --git a/lib/default-input.js b/lib/default-input.js index 7b9c8f44..8d835d2c 100644 --- a/lib/default-input.js +++ b/lib/default-input.js @@ -262,13 +262,27 @@ if (!package.author) { : yes ? '' : prompt('author') } -const license = package.license || getConfig('license') || 'ISC' -exports.license = yes ? license : prompt('license', license, (data) => { - if (validateLicense(data)) { - return data +const configLicense = getConfig('license') +const license = package.license || configLicense || undefined + +if (yes) { + // Only include license if explicitly set in config or already in package.json + if (license) { + exports.license = license } - return invalid('Sorry, license should be a valid SPDX license expression') -}) +} else { + exports.license = prompt('license', license || undefined, (data) => { + if (!data) { + return undefined + } + if (validateLicense(data)) { + return data + } + return invalid( + 'License should be a valid SPDX license expression' + ) + }) +} const type = package.type || getConfig('type') || 'commonjs' exports.type = yes ? type : prompt('type', type, (data) => { diff --git a/lib/init-package-json.js b/lib/init-package-json.js index b67ae418..a560ae30 100644 --- a/lib/init-package-json.js +++ b/lib/init-package-json.js @@ -100,6 +100,11 @@ async function init (dir, delete pkg.content.repository } + // if no license was explicitly provided, don't include one + if (!pzData.license) { + delete pkg.content.license + } + // readJson filters out empty descriptions, but init-package-json // traditionally leaves them alone if (!pkg.content.description) { diff --git a/test/dependencies.js b/test/dependencies.js index 55ee86cb..393a5c16 100644 --- a/test/dependencies.js +++ b/test/dependencies.js @@ -42,7 +42,6 @@ t.test('read in dependencies and dev deps', async (t) => { scripts: { test: 'mocha' }, main: 'index.js', keywords: [], - license: 'ISC', dependencies: { tap: '*', }, diff --git a/test/license.js b/test/license.js index ab100333..8abaa9d1 100644 --- a/test/license.js +++ b/test/license.js @@ -10,8 +10,8 @@ t.test('license', async (t) => { inputs: { name: 'the-name', licence: [ - [/license: \(.*\) $/, 'Apache'], // invalid license - [/license: \(.*\) $/, 'Apache-2.0'], // license + [/license: $/, 'Apache'], // invalid license + [/license: $/, 'Apache-2.0'], // license ], }, }) @@ -27,3 +27,39 @@ t.test('license', async (t) => { } t.has(data, wanted) }) + +t.test('license omitted when left blank', async (t) => { + const { data } = await setup(t, __filename, { + inputs: { + name: 'the-name', + licence: [ + [/license: $/, ''], // leave blank + ], + }, + }) + + t.equal(data.license, undefined, 'license is omitted when left blank') +}) + +t.test('license from config', async (t) => { + const { data } = await setup(t, __filename, { + config: { yes: 'yes', 'init-license': 'MIT' }, + }) + + t.equal(data.license, 'MIT', 'uses configured license') +}) + +t.test('license preserved from existing package.json', async (t) => { + const { data } = await setup(t, __filename, { + testdir: { + 'package.json': JSON.stringify({ + name: 'existing-package', + version: '1.0.0', + license: 'BSD-3-Clause', + }), + }, + config: { yes: 'yes' }, + }) + + t.equal(data.license, 'BSD-3-Clause', 'preserves existing license') +}) diff --git a/test/name-spaces.js b/test/name-spaces.js index 3c8b926a..c5f6cff0 100644 --- a/test/name-spaces.js +++ b/test/name-spaces.js @@ -20,7 +20,6 @@ t.test('single space', async t => { version: '1.0.0', description: '', scripts: { test: 'echo "Error: no test specified" && exit 1' }, - license: 'ISC', author: '', main: 'index.js', } @@ -42,7 +41,6 @@ t.test('multiple spaces', async t => { version: '1.0.0', description: '', scripts: { test: 'echo "Error: no test specified" && exit 1' }, - license: 'ISC', author: '', main: 'index.js', } diff --git a/test/name-uppercase.js b/test/name-uppercase.js index a8529c43..170474a4 100644 --- a/test/name-uppercase.js +++ b/test/name-uppercase.js @@ -20,7 +20,6 @@ t.test('uppercase', async (t) => { version: '1.0.0', description: '', scripts: { test: 'echo "Error: no test specified" && exit 1' }, - license: 'ISC', author: '', main: 'index.js', } diff --git a/test/scope-in-config.js b/test/scope-in-config.js index 9927aad0..cf244dad 100644 --- a/test/scope-in-config.js +++ b/test/scope-in-config.js @@ -14,7 +14,6 @@ t.test('--yes with scope', async (t) => { scripts: { test: 'echo "Error: no test specified" && exit 1' }, main: 'index.js', keywords: [], - license: 'ISC', } const { data } = await setup(t, __filename, { diff --git a/test/yes-defaults.js b/test/yes-defaults.js index 3799c350..add71773 100644 --- a/test/yes-defaults.js +++ b/test/yes-defaults.js @@ -14,7 +14,6 @@ t.test('--yes defaults', async (t) => { scripts: { test: 'echo "Error: no test specified" && exit 1' }, main: 'index.js', keywords: [], - license: 'ISC', } const { data } = await setup(t, __filename, { @@ -22,4 +21,5 @@ t.test('--yes defaults', async (t) => { }) t.has(data, EXPECT, 'used the default data') + t.equal(data.license, undefined, 'license is omitted by default') }) From d15c2f85478c36ae51deeb1e7cd79d87275d1f5a Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Tue, 14 Apr 2026 11:09:37 -0700 Subject: [PATCH 2/2] chore: template-oss-apply --- .github/workflows/audit.yml | 4 ---- .github/workflows/ci-release.yml | 8 -------- .github/workflows/ci.yml | 8 -------- .github/workflows/post-dependabot.yml | 4 ---- .github/workflows/pull-request.yml | 4 ---- .github/workflows/release-integration.yml | 4 ---- .github/workflows/release.yml | 8 -------- package.json | 3 ++- 8 files changed, 2 insertions(+), 41 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 85282bdf..628ed3b4 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -32,10 +32,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund --package-lock - name: Run Production Audit diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index 3f01e204..1284dd6a 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -53,10 +53,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Lint @@ -131,10 +127,6 @@ jobs: with: node-version: ${{ matrix.node-version }} check-latest: contains(matrix.node-version, '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Add Problem Matcher diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07a869f2..bd4e34df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,10 +36,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Lint @@ -97,10 +93,6 @@ jobs: with: node-version: ${{ matrix.node-version }} check-latest: contains(matrix.node-version, '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Add Problem Matcher diff --git a/.github/workflows/post-dependabot.yml b/.github/workflows/post-dependabot.yml index 3a919116..8439f848 100644 --- a/.github/workflows/post-dependabot.yml +++ b/.github/workflows/post-dependabot.yml @@ -30,10 +30,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Fetch Dependabot Metadata diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index c69932da..bb7672cd 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -36,10 +36,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Run Commitlint on Commits diff --git a/.github/workflows/release-integration.yml b/.github/workflows/release-integration.yml index 9ca9a2b8..6d7fc3e8 100644 --- a/.github/workflows/release-integration.yml +++ b/.github/workflows/release-integration.yml @@ -47,10 +47,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Set npm authToken diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53ff3c24..15a528d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,10 +41,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Release Please @@ -121,10 +117,6 @@ jobs: with: node-version: 22.x check-latest: contains('22.x', '.x') - - name: Install Latest npm - uses: ./.github/actions/install-latest-npm - with: - node: ${{ steps.node.outputs.node-version }} - name: Install Dependencies run: npm i --ignore-scripts --no-audit --no-fund - name: Create Release Manager Checklist Text diff --git a/package.json b/package.json index 0654d193..f05fb9ba 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", "version": "4.30.0", - "publish": true + "publish": true, + "updateNpm": false } }