Skip to content

Commit 4fec336

Browse files
committed
fix
1 parent 6c1b744 commit 4fec336

6 files changed

Lines changed: 93 additions & 70 deletions

File tree

src/__e2e__/bump.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,11 @@ describe('bump command', () => {
447447
it('bumps dependents with workspace: deps', async () => {
448448
const monorepo: RepoFixture['folders'] = {
449449
packages: {
450-
'pkg-1': { version: '1.0.0' },
450+
// Include some external deps to make sure nothing weird happens there
451+
'pkg-1': { version: '1.0.0', dependencies: { extra: '~1.2.3' } },
451452
'pkg-2': { version: '1.0.0', dependencies: { 'pkg-1': 'workspace:~' } },
452453
// this workspace version will be updated
453-
'pkg-3': { version: '1.0.0', dependencies: { 'pkg-2': 'workspace:^1.0.0' } },
454+
'pkg-3': { version: '1.0.0', dependencies: { 'pkg-2': 'workspace:^1.0.0', other: 'npm:lodash' } },
454455
},
455456
};
456457
repositoryFactory = new RepositoryFactory({ folders: monorepo });
@@ -468,12 +469,15 @@ describe('bump command', () => {
468469
const packageInfos = getPackageInfos(parsedOptions);
469470

470471
// All the dependent packages are bumped despite the workspace: dep specs
471-
expect(packageInfos['pkg-1'].version).toBe('1.1.0');
472+
expect(packageInfos['pkg-1']).toEqual({ ...originalPackageInfos['pkg-1'], version: '1.1.0' });
472473
// workspace:~ range isn't changed
473474
expect(packageInfos['pkg-2']).toEqual({ ...originalPackageInfos['pkg-2'], version: '1.0.1' });
474-
expect(packageInfos['pkg-2'].version).toBe('1.0.1');
475475
// workspace: range with number is updated
476-
expect(packageInfos['pkg-3'].dependencies).toEqual({ 'pkg-2': 'workspace:^1.0.1' });
476+
expect(packageInfos['pkg-3']).toEqual({
477+
...originalPackageInfos['pkg-3'],
478+
version: '1.0.1',
479+
dependencies: { 'pkg-2': 'workspace:^1.0.1', other: 'npm:lodash' },
480+
});
477481

478482
expect(readChangelogJson(repo.pathTo('packages/pkg-1'))).not.toBeNull();
479483
const pkg3Changelog = readChangelogJson(repo.pathTo('packages/pkg-3'));

src/__e2e__/publishE2E.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,10 @@ describe('publish command (e2e)', () => {
339339
it('publishes packages with workspace: and catalog: deps and replaces versions', async () => {
340340
const monorepo: RepoFixture['folders'] = {
341341
packages: {
342-
'pkg-1': { version: '1.0.0' },
342+
// Include some external deps to make sure nothing weird happens there
343+
'pkg-1': { version: '1.0.0', dependencies: { extra: '~1.2.3' } },
343344
'pkg-2': { version: '1.0.0', dependencies: { 'pkg-1': 'workspace:~', react: 'catalog:react18' } },
344-
'pkg-3': { version: '1.0.0', dependencies: { 'pkg-2': 'workspace:^1.0.0' } },
345+
'pkg-3': { version: '1.0.0', dependencies: { 'pkg-2': 'workspace:^1.0.0', other: 'npm:lodash' } },
345346
'pkg-4': {
346347
version: '1.0.0',
347348
dependencies: { 'pkg-1': 'catalog:' },
@@ -372,12 +373,16 @@ describe('publish command (e2e)', () => {
372373
// All the dependent packages are bumped despite the workspace: dep specs.
373374
// The literal workspace: specs are preserved in git.
374375
const packageInfos = getPackageInfos(parsedOptions);
375-
expect(packageInfos['pkg-1'].version).toBe('1.1.0');
376+
expect(packageInfos['pkg-1']).toEqual({ ...originalPackageInfos['pkg-1'], version: '1.1.0' });
376377
// workspace:~ and catalog: ranges aren't changed
377378
expect(packageInfos['pkg-2']).toEqual({ ...originalPackageInfos['pkg-2'], version: '1.0.1' });
378379
expect(packageInfos['pkg-2'].version).toBe('1.0.1');
379380
// workspace: range with number is updated
380-
expect(packageInfos['pkg-3'].dependencies).toEqual({ 'pkg-2': 'workspace:^1.0.1' });
381+
expect(packageInfos['pkg-3']).toEqual({
382+
...originalPackageInfos['pkg-3'],
383+
version: '1.0.1',
384+
dependencies: { 'pkg-2': 'workspace:^1.0.1', other: 'npm:lodash' },
385+
});
381386
// catalog: range isn't changed
382387
expect(packageInfos['pkg-4']).toEqual({ ...originalPackageInfos['pkg-4'], version: '1.0.1' });
383388

@@ -391,7 +396,7 @@ describe('publish command (e2e)', () => {
391396
});
392397
expect(npmMock.getPublishedPackage('pkg-3')).toMatchObject({
393398
version: '1.0.1',
394-
dependencies: { 'pkg-2': '^1.0.1' },
399+
dependencies: { 'pkg-2': '^1.0.1', other: 'npm:lodash' },
395400
});
396401
expect(npmMock.getPublishedPackage('pkg-4')).toMatchObject({
397402
version: '1.0.1',

src/__tests__/bump/bumpInMemory.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,9 @@ describe('bumpInMemory', () => {
289289
const { bumpInfo, originalPackageInfos } = gatherBumpInfoWrapper({
290290
packageFolders: {
291291
'pkg-1': { version: '1.0.0' },
292-
'pkg-2': { version: '1.0.0', dependencies: { 'pkg-1': 'workspace:~' } },
292+
'pkg-2': { version: '1.0.0', dependencies: { 'pkg-1': 'workspace:~', extra: '~1.2.3' } },
293293
// this workspace version will be updated
294-
'pkg-3': { version: '1.0.0', dependencies: { 'pkg-2': 'workspace:^1.0.0' } },
294+
'pkg-3': { version: '1.0.0', dependencies: { 'pkg-2': 'workspace:^1.0.0', other: 'npm:lodash' } },
295295
},
296296
repoOptions: { bumpDeps: true },
297297
changes: ['pkg-1'],
@@ -313,7 +313,7 @@ describe('bumpInMemory', () => {
313313
// workspace:~ range isn't changed
314314
expect(packageInfos['pkg-2']).toEqual({ ...originalPackageInfos['pkg-2'], version: '1.0.1' });
315315
// workspace: range with number is updated
316-
expect(packageInfos['pkg-3'].dependencies).toEqual({ 'pkg-2': 'workspace:^1.0.1' });
316+
expect(packageInfos['pkg-3'].dependencies).toEqual({ 'pkg-2': 'workspace:^1.0.1', other: 'npm:lodash' });
317317
});
318318

319319
it('bumps dependents with catalog: deps', () => {

src/__tests__/packageManager/resolveSpecialVersion.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ describe('resolveSpecialVersion', () => {
2424
});
2525
expect(result).toBeUndefined();
2626
});
27+
28+
it('returns undefined for regular version of package not in repo', () => {
29+
const result = resolveSpecialVersion({
30+
depName: 'bar', // different package
31+
depVersion: '^1.0.0',
32+
catalogs: undefined,
33+
packageInfos: emptyPackageInfos,
34+
});
35+
expect(result).toBeUndefined();
36+
});
2737
});
2838

2939
describe('workspace protocol', () => {

src/__tests__/publish/performPublishOverrides.test.ts

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -228,40 +228,21 @@ describe('performPublishOverrides', () => {
228228
return cloneObject(packageJsons[pkg.name]);
229229
}
230230
}
231-
throw new Error(`not found: ${path}`);
231+
throw new Error(`Path not mocked for readJson: ${path}`);
232232
}) as typeof _readJson);
233233

234234
return { packageInfos, packageJsons };
235235
}
236236

237-
it('overrides accepted publishConfig keys and preserves values not specified', () => {
238-
const publishConfig: PublishConfig = {
239-
main: 'lib/index.js',
240-
types: 'lib/index.d.ts',
241-
};
242-
const { packageInfos, packageJsons } = createFullFixture({ foo: { publishConfig } });
243-
expect(packageJsons.foo).not.toMatchObject(publishConfig);
237+
it('does not write package.json if no overrides needed', () => {
238+
const { packageInfos } = createFullFixture({ foo: {} });
244239

245240
performPublishOverrides(['foo'], packageInfos, undefined);
246241

247-
expect(mockWriteJson).toHaveBeenCalledTimes(1);
248-
expect(publishConfig).toEqual({
249-
main: 'lib/index.js',
250-
types: 'lib/index.d.ts',
251-
});
252-
expect(mockWriteJson).toHaveBeenCalledWith(
253-
packageInfos.foo.packageJsonPath,
254-
// package.json data with publishConfig values promoted to root,
255-
// and any original values not specified in publishConfig preserved
256-
{
257-
...packageJsons.foo,
258-
...publishConfig,
259-
publishConfig: {},
260-
}
261-
);
242+
expect(mockWriteJson).not.toHaveBeenCalled();
262243
});
263244

264-
it('does not override non-accepted publishConfig keys', () => {
245+
it('does not write package.json if publishConfig has only non-accepted keys', () => {
265246
const publishConfig = { version: '1.2.3', extra: 'nope' } as unknown as PublishConfig;
266247
const { packageInfos, packageJsons } = createFullFixture({ foo: { publishConfig } });
267248
expect(packageJsons.foo).not.toMatchObject(publishConfig);
@@ -271,23 +252,27 @@ describe('performPublishOverrides', () => {
271252
expect(mockWriteJson).not.toHaveBeenCalled();
272253
});
273254

274-
it('performs overrides for multiple packages', () => {
255+
it('writes package.json for multiple packages with publishConfig overrides', () => {
256+
const unsupportedConfig = { version: '1.2.3', extra: 'nope' } as unknown as PublishConfig;
275257
const { packageInfos, packageJsons } = createFullFixture({
276-
foo: { publishConfig: { main: 'lib/index.js' } },
258+
foo: { bin: './bin.js', publishConfig: { main: 'lib/index.js', ...unsupportedConfig } },
277259
bar: { publishConfig: { types: 'lib/index.d.ts' } },
260+
baz: {},
278261
});
279-
const originalFoo = packageJsons.foo;
280-
const originalBar = packageJsons.bar;
262+
const { foo: originalFoo, bar: originalBar } = packageJsons;
281263
expect(originalFoo).not.toMatchObject(originalFoo.publishConfig!);
282264
expect(originalBar).not.toMatchObject(originalBar.publishConfig!);
283265

284-
performPublishOverrides(['foo', 'bar'], packageInfos, undefined);
266+
performPublishOverrides(['foo', 'bar', 'baz'], packageInfos, undefined);
285267

268+
// only called for packages that need updates, not baz
286269
expect(mockWriteJson).toHaveBeenCalledTimes(2);
287270
expect(mockWriteJson).toHaveBeenCalledWith(packageInfos.foo.packageJsonPath, {
271+
// package.json data with publishConfig values promoted to root,
272+
// and any original values not specified in publishConfig preserved
288273
...originalFoo,
289-
...originalFoo.publishConfig,
290-
publishConfig: {},
274+
main: 'lib/index.js',
275+
publishConfig: unsupportedConfig, // unsupported keys remain in publishConfig
291276
});
292277
expect(mockWriteJson).toHaveBeenCalledWith(packageInfos.bar.packageJsonPath, {
293278
...originalBar,
@@ -296,26 +281,44 @@ describe('performPublishOverrides', () => {
296281
});
297282
});
298283

299-
it.each([
284+
it.each<[string, string]>([
300285
['workspace:*', '1.0.0'],
301-
['workspace:~', '~1.0.0'],
302-
['workspace:^', '^1.0.0'],
303-
['workspace:~1.0.0', '~1.0.0'],
304286
['workspace:^1.0.0', '^1.0.0'],
305-
])('overrides %s dependency versions', (dependencyVersion, expectedPublishVersion) => {
287+
])('writes package.json with %s dependency version updates', (depVersion, expectedVersion) => {
306288
const { packageInfos, packageJsons } = createFullFixture({
307289
foo: { version: '1.0.0' },
308-
bar: { version: '2.0.0', dependencies: { foo: dependencyVersion } },
290+
bar: { version: '2.0.0', dependencies: { foo: depVersion } },
309291
});
310-
expect(packageJsons.bar.dependencies!.foo).toBe(dependencyVersion);
292+
expect(packageJsons.bar.dependencies!.foo).toBe(depVersion);
311293

312294
performPublishOverrides(['bar'], packageInfos, undefined);
313295

314296
expect(mockWriteJson).toHaveBeenCalledTimes(1);
315297
expect(mockWriteJson).toHaveBeenCalledWith(
316298
packageInfos.bar.packageJsonPath,
317299
expect.objectContaining({
318-
dependencies: { foo: expectedPublishVersion },
300+
dependencies: { foo: expectedVersion },
301+
})
302+
);
303+
});
304+
305+
it('writes package.json with catalog dependency version updates', () => {
306+
const { packageInfos, packageJsons } = createFullFixture({
307+
foo: { version: '1.0.0' },
308+
bar: { version: '2.0.0', dependencies: { foo: 'catalog:', react: 'catalog:', extra: '~1.2.3' } },
309+
});
310+
expect(packageJsons.bar.dependencies!.react).toBe('catalog:');
311+
const catalogs: Catalogs = {
312+
default: { foo: 'workspace:^', react: '^18.0.0' },
313+
};
314+
315+
performPublishOverrides(['bar'], packageInfos, catalogs);
316+
317+
expect(mockWriteJson).toHaveBeenCalledTimes(1);
318+
expect(mockWriteJson).toHaveBeenCalledWith(
319+
packageInfos.bar.packageJsonPath,
320+
expect.objectContaining({
321+
dependencies: { foo: '^1.0.0', react: '^18.0.0', extra: '~1.2.3' },
319322
})
320323
);
321324
});

src/packageManager/resolveSpecialVersion.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,25 @@ export function resolveSpecialVersion(params: {
2626
}
2727
}
2828

29-
// If the dependency comes from within the repo, check if the version is specified with workspace:
30-
const packageInfo = packageInfos[depName];
31-
if (packageInfo) {
32-
// Check for a workspace: version (there's a slight chance one could be nested inside a catalog)
33-
const workspaceRange =
34-
getWorkspaceRange(depVersion) || (versionFromCatalog && getWorkspaceRange(versionFromCatalog));
35-
if (workspaceRange) {
36-
// Resolve to actual version per specs
37-
// https://pnpm.io/workspaces#workspace-protocol-workspace
38-
// https://yarnpkg.com/features/workspaces#publishing-workspaces
39-
return workspaceRange === '*'
40-
? packageInfo.version
41-
: workspaceRange === '^' || workspaceRange === '~'
42-
? `${workspaceRange}${packageInfo.version}`
43-
: workspaceRange;
29+
// Check for a workspace: version (there's a slight chance one could be nested inside a catalog)
30+
const workspaceRange = getWorkspaceRange(depVersion) || (versionFromCatalog && getWorkspaceRange(versionFromCatalog));
31+
if (workspaceRange) {
32+
const packageInfo = packageInfos[depName];
33+
if (!packageInfo) {
34+
// workspace: version referenced a package that isn't in the repo
35+
const referenceVersion = versionFromCatalog ? `"${depVersion}" -> "${versionFromCatalog}"` : `"${depVersion}"`;
36+
throw new Error(
37+
`Package "${depName}" (referenced by version ${referenceVersion}) not found in workspace packages`
38+
);
4439
}
45-
} else {
46-
const referenceVersion = versionFromCatalog ? `"${depVersion}" -> "${versionFromCatalog}"` : `"${depVersion}"`;
47-
throw new Error(`Package "${depName}" (referenced by version ${referenceVersion}) not found in workspace packages`);
40+
41+
// Resolve to actual version per specs
42+
// https://pnpm.io/workspaces#workspace-protocol-workspace
43+
// https://yarnpkg.com/features/workspaces#publishing-workspaces
44+
return workspaceRange === '*'
45+
? packageInfo.version
46+
: workspaceRange === '^' || workspaceRange === '~'
47+
? `${workspaceRange}${packageInfo.version}`
48+
: workspaceRange;
4849
}
4950
}

0 commit comments

Comments
 (0)