Skip to content

Commit 0902df4

Browse files
committed
Revert "Temporarily revert npm-registry-fetch usage (#1145)"
This reverts commit f666c1e.
1 parent c790eca commit 0902df4

18 files changed

Lines changed: 766 additions & 493 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ beachball publish -r http://localhost:4873 -t beta
108108

109109
### Overriding concurrency
110110

111-
In large monorepos, the process of fetching versions for sync or before publishing can be time-consuming due to the high number of packages. To optimize performance, you can override the concurrency for fetching from the registry by setting `options.npmReadConcurrency` (default: 5). You can also increase concurrency for hook calls and publish operations via `options.concurrency` (default: 1; respects topological order).
111+
In large monorepos, the process of fetching versions for sync or before publishing can be time-consuming due to the high number of packages. To optimize performance, you can override the concurrency for fetching from the registry by setting `options.npmReadConcurrency` (default: 10). You can also increase concurrency for hook calls and publish operations via `options.concurrency` (default: 1; respects topological order).
112112

113113
### API surface
114114

docs/overview/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ For the latest full list of supported options, see `RepoOptions` [in this file](
9191
| `groupChanges` | `boolean` | `false` | repo | Write multiple changes to a single change file |
9292
| `hooks` | [`HooksOptions`][4] | | repo | Hooks for custom pre/post publish actions |
9393
| `ignorePatterns` | `string[]` | | repo | Ignore changes in files matching these glob patterns ([see notes][6]) |
94-
| `npmReadConcurrency` | number | 5 | repo | Maximum concurrency for fetching package versions from the registry (see `concurrency` for write operations) |
94+
| `npmReadConcurrency` | number | 10 | repo | Maximum concurrency for fetching package versions from the registry (see `concurrency` for write operations) |
9595
| `package` | `string` | | repo | Specifies which package the command relates to (overrides change detection based on `git diff`) |
9696
| `prereleasePrefix` | `string` | | repo | Prerelease prefix, e.g. `"beta"`. Note that if this is specified, packages with change type major/minor/patch will be bumped as prerelease instead. |
9797
| `packStyle` | `'sequential' \| 'layer'` | `'sequential'` | repo | With `packToPath`, how to organize the tgz files. `'sequential'` uses numeric prefixes to ensure topological ordering. `'layer'` groups the packages into numbered subfolders based on dependency tree layers. |

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"cosmiconfig": "^9.0.1",
5656
"execa": "^5.1.1",
5757
"minimatch": "^3.1.5",
58+
"npm-registry-fetch": "^14.0.0",
5859
"p-graph": "^1.3.0",
5960
"p-limit": "^3.1.0",
6061
"prompts": "^2.4.2",
@@ -66,6 +67,7 @@
6667
"@jest/globals": "^29.0.0",
6768
"@types/minimatch": "^3.0.0",
6869
"@types/node": "^22.0.0",
70+
"@types/npm-registry-fetch": "^8.0.9",
6971
"@types/prompts": "^2.4.2",
7072
"@types/semver": "^7.3.13",
7173
"@types/tmp": "^0.2.3",

src/__e2e__/publishE2E.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { validate } from '../validation/validate';
2828
// If an issue is found in the future that could only be caught by this test using real npm,
2929
// a new test file with a real registry should be created to cover that specific scenario.
3030
jest.mock('../packageManager/npm');
31-
// jest.mock('npm-registry-fetch');
31+
jest.mock('npm-registry-fetch');
3232

3333
describe('publish command (e2e)', () => {
3434
const npmMock = initNpmMock();

src/__e2e__/publishRegistry.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { validate } from '../validation/validate';
2323
// If an issue is found in the future that could only be caught by this test using real npm,
2424
// a new test file with a real registry should be created to cover that specific scenario.
2525
jest.mock('../packageManager/npm');
26-
// jest.mock('npm-registry-fetch');
26+
jest.mock('npm-registry-fetch');
2727

2828
describe('publish command (registry)', () => {
2929
const npmMock = initNpmMock();
@@ -193,8 +193,7 @@ describe('publish command (registry)', () => {
193193

194194
expect(npmMock.getPublishedPackage('foo')!.version).toEqual('1.1.0');
195195
expect(npmMock.getPublishedPackage('bar')!.version).toEqual('1.4.0');
196-
expect(npmMock.mock).toHaveBeenCalledTimes(4);
197-
// expect(npmMock.mock).toHaveBeenCalledTimes(2);
196+
expect(npmMock.mock).toHaveBeenCalledTimes(2);
198197
expect(logs.mocks.error).not.toHaveBeenCalled();
199198
});
200199

src/__e2e__/syncE2E.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { getScopedPackages } from '../monorepo/getScopedPackages';
1818
// If an issue is found in the future that could only be caught by this test using real npm,
1919
// a new test file with a real registry should be created to cover that specific scenario.
2020
jest.mock('../packageManager/npm');
21-
// jest.mock('npm-registry-fetch');
21+
jest.mock('npm-registry-fetch');
2222

2323
describe('sync command (e2e)', () => {
2424
const mockNpm = initNpmMock();

src/__fixtures__/mockNpm.test.ts

Lines changed: 34 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,16 @@
22
// But this added complexity greatly speeds up the other npm-related tests by removing the
33
// dependency on actual npm CLI calls and a fake registry (which are very slow).
44

5-
import { afterEach, beforeAll, describe, expect, it, jest } from '@jest/globals';
5+
import { afterAll, afterEach, beforeAll, describe, expect, it, jest } from '@jest/globals';
66
import fs from 'fs';
7-
// import fetch from 'npm-registry-fetch';
7+
import fetch from 'npm-registry-fetch';
88
import { type NpmResult, npm } from '../packageManager/npm';
99
import type { PackageJson } from '../types/PackageInfo';
10-
import {
11-
initNpmMock,
12-
_makeRegistryData,
13-
_mockNpmPack,
14-
_mockNpmPublish,
15-
_mockNpmShow,
16-
type MockNpmResult,
17-
} from './mockNpm';
10+
import { initNpmMock, _makeRegistryData, _mockNpmPack, _mockNpmPublish, type MockNpmResult } from './mockNpm';
1811
import * as readJsonModule from '../object/readJson';
1912

2013
jest.mock('fs');
21-
// jest.mock('npm-registry-fetch');
14+
jest.mock('npm-registry-fetch');
2215
jest.mock('../object/readJson');
2316
jest.mock('../packageManager/npm');
2417

@@ -93,94 +86,6 @@ describe('_makeRegistryData', () => {
9386
});
9487
});
9588

96-
describe('_mockNpmShow', () => {
97-
function getErrorResult(errorMessage: string) {
98-
return {
99-
stdout: '',
100-
stderr: errorMessage,
101-
all: errorMessage,
102-
success: false,
103-
failed: true,
104-
} as NpmResult;
105-
}
106-
107-
function getShowResult(params: { name: string; version: string }) {
108-
const { name, version } = params;
109-
const output = JSON.stringify({
110-
...data[name].versions[version],
111-
'dist-tags': data[name]['dist-tags'],
112-
versions: Object.keys(data[name].versions),
113-
});
114-
115-
return {
116-
stdout: output,
117-
stderr: '',
118-
all: output,
119-
success: true,
120-
failed: false,
121-
} as NpmResult;
122-
}
123-
124-
const data = _makeRegistryData({
125-
foo: {
126-
versions: ['1.0.0-beta', '1.0.0', '1.0.1'],
127-
'dist-tags': { latest: '1.0.1', beta: '1.0.0-beta' },
128-
},
129-
'@foo/bar': {
130-
versions: ['2.0.0-beta', '2.0.0', '2.0.1'],
131-
'dist-tags': { latest: '2.0.1', beta: '2.0.0-beta' },
132-
},
133-
});
134-
135-
it("errors if package doesn't exist", async () => {
136-
const emptyData = _makeRegistryData({});
137-
const result = await _mockNpmShow(emptyData, ['foo'], { cwd: undefined });
138-
expect(result).toEqual(getErrorResult('[fake] code E404 - foo - not found'));
139-
});
140-
141-
it('returns requested version plus dist-tags and version list', async () => {
142-
const result = await _mockNpmShow(data, ['foo@1.0.0'], { cwd: undefined });
143-
expect(result).toEqual(getShowResult({ name: 'foo', version: '1.0.0' }));
144-
});
145-
146-
it('returns requested version of scoped package', async () => {
147-
const result = await _mockNpmShow(data, ['@foo/bar@2.0.0'], { cwd: undefined });
148-
expect(result).toEqual(getShowResult({ name: '@foo/bar', version: '2.0.0' }));
149-
});
150-
151-
it('returns requested tag', async () => {
152-
const result = await _mockNpmShow(data, ['foo@beta'], { cwd: undefined });
153-
expect(result).toEqual(getShowResult({ name: 'foo', version: '1.0.0-beta' }));
154-
});
155-
156-
it('returns requested tag of scoped package', async () => {
157-
const result = await _mockNpmShow(data, ['@foo/bar@beta'], { cwd: undefined });
158-
expect(result).toEqual(getShowResult({ name: '@foo/bar', version: '2.0.0-beta' }));
159-
});
160-
161-
it('returns latest version if no version requested', async () => {
162-
const result = await _mockNpmShow(data, ['foo'], { cwd: undefined });
163-
expect(result).toEqual(getShowResult({ name: 'foo', version: '1.0.1' }));
164-
});
165-
166-
it('returns latest version of scoped package if no version requested', async () => {
167-
const result = await _mockNpmShow(data, ['@foo/bar'], { cwd: undefined });
168-
expect(result).toEqual(getShowResult({ name: '@foo/bar', version: '2.0.1' }));
169-
});
170-
171-
it("errors if requested version doesn't exist", async () => {
172-
const result = await _mockNpmShow(data, ['foo@2.0.0'], { cwd: undefined });
173-
expect(result).toEqual(getErrorResult('[fake] code E404 - foo@2.0.0 - not found'));
174-
});
175-
176-
// support for this could be added later
177-
it('currently throws if requested version is a range', async () => {
178-
await expect(() => _mockNpmShow(data, ['foo@^1.0.0'], { cwd: undefined })).rejects.toThrow(
179-
/not currently supported/
180-
);
181-
});
182-
});
183-
18489
describe('_mockNpmPublish', () => {
18590
function getPublishResult(params: { error?: string; tag?: string }) {
18691
const { error, tag } = params;
@@ -362,25 +267,29 @@ describe('mockNpm', () => {
362267
packageJson = undefined;
363268
});
364269

365-
// describe('mockFetchJson', () => {
366-
// it('mocks registry fetch', async () => {
367-
// npmMock.setRegistryData({ foo: { versions: ['1.0.0'] } });
368-
// expect(fetch.json).toHaveProperty('mock');
369-
// const result = await fetch.json('/foo');
370-
// expect(result).toEqual({
371-
// name: 'foo',
372-
// modified: expect.any(String),
373-
// versions: { '1.0.0': { name: 'foo', version: '1.0.0' } },
374-
// 'dist-tags': { latest: '1.0.0' },
375-
// });
376-
// });
377-
378-
// it('resets calls and registry after each test', () => {
379-
// expect(npmMock.mockFetchJson).not.toHaveBeenCalled();
380-
// // registry data for foo was set in the previous test but should have been cleared
381-
// expect(() => fetch.json('/foo')).toThrow('404 Not Found');
382-
// });
383-
// });
270+
afterAll(() => {
271+
jest.restoreAllMocks();
272+
});
273+
274+
describe('mockFetchJson', () => {
275+
it('mocks registry fetch', async () => {
276+
npmMock.setRegistryData({ foo: { versions: ['1.0.0'] } });
277+
expect(fetch.json).toHaveProperty('mock');
278+
const result = await fetch.json('/foo');
279+
expect(result).toEqual({
280+
name: 'foo',
281+
modified: expect.any(String),
282+
versions: { '1.0.0': { name: 'foo', version: '1.0.0' } },
283+
'dist-tags': { latest: '1.0.0' },
284+
});
285+
});
286+
287+
it('resets calls and registry after each test', () => {
288+
expect(npmMock.mockFetchJson).not.toHaveBeenCalled();
289+
// registry data for foo was set in the previous test but should have been cleared
290+
expect(() => fetch.json('/foo')).toThrow('404 Not Found');
291+
});
292+
});
384293

385294
describe('getPublishedVersions', () => {
386295
it('gets data for a package', () => {
@@ -433,23 +342,14 @@ describe('mockNpm', () => {
433342
versions: ['1.0.0'],
434343
'dist-tags': { latest: '1.0.0' },
435344
});
436-
expect(await npm(['show', 'foo'], { cwd: undefined })).toMatchObject({
437-
success: true,
438-
stdout: JSON.stringify({
439-
name: 'foo',
440-
version: '1.0.0',
441-
'dist-tags': { latest: '1.0.0' },
442-
versions: ['1.0.0'],
443-
}),
345+
expect(await fetch.json('/foo')).toEqual({
346+
name: 'foo',
347+
modified: expect.any(String),
348+
versions: {
349+
'1.0.0': { name: 'foo', version: '1.0.0' },
350+
},
351+
'dist-tags': { latest: '1.0.0' },
444352
});
445-
// expect(await fetch.json('/foo')).toEqual({
446-
// name: 'foo',
447-
// modified: expect.any(String),
448-
// versions: {
449-
// '1.0.0': { name: 'foo', version: '1.0.0' },
450-
// },
451-
// 'dist-tags': { latest: '1.0.0' },
452-
// });
453353
});
454354
});
455355

@@ -494,15 +394,6 @@ describe('mockNpm', () => {
494394
expect(npmMock.mock).toHaveBeenCalledTimes(1);
495395
expect(npmMock.mock).toHaveBeenCalledWith(['foo'], expect.objectContaining({ cwd: undefined }));
496396
});
497-
498-
it('TEMP mocks npm show command', async () => {
499-
npmMock.setRegistryData({ foo: { versions: ['1.0.0'] } });
500-
const result = await npm(['show', 'foo'], { cwd: undefined });
501-
expect(result).toMatchObject({
502-
success: true,
503-
stdout: expect.stringContaining('"name":"foo"'),
504-
});
505-
});
506397
});
507398

508399
describe('setCommandOverride', () => {

0 commit comments

Comments
 (0)