1import semver from 'semver';
2
3import logger from '../../Logger';
4import { Task } from '../../TasksRunner';
5import { CommandOptions, Parcel, TaskArgs } from '../types';
6
7/**
8 * Finds packages whose local version is not tagged as the target tag provided as a command option (defaults to `latest`).
9 */
10export const findPackagesToPromote = new Task<TaskArgs>(
11  {
12    name: 'findPackagesToPromote',
13  },
14  async (parcels: Parcel[], options: CommandOptions): Promise<symbol | TaskArgs> => {
15    logger.info('\n�� Searching for packages to promote...');
16
17    const newParcels: Parcel[] = [];
18
19    await Promise.all(
20      parcels.map(async (parcel) => {
21        const { pkg, pkgView, state } = parcel;
22        const currentDistTags = await pkg.getDistTagsAsync();
23        const versionToReplace = pkgView?.['dist-tags']?.[options.tag] ?? null;
24        const canPromote = pkgView && !currentDistTags.includes(options.tag);
25
26        state.distTags = currentDistTags;
27        state.versionToReplace = versionToReplace;
28        state.isDemoting = !!versionToReplace && semver.lt(pkg.packageVersion, versionToReplace);
29
30        if (canPromote && (!state.isDemoting || options.list || options.demote)) {
31          newParcels.push(parcel);
32        }
33      })
34    );
35
36    if (newParcels.length === 0) {
37      logger.success('\n✅ No packages to promote.\n');
38      return Task.STOP;
39    }
40    return [newParcels, options];
41  }
42);
43