All files / create-package/src commands.ts

100% Statements 20/20
100% Branches 10/10
100% Functions 4/4
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104                                            3x       6x                                           5x 1x   4x 1x     3x 2x     3x     6x     2x     3x 3x                           3x   3x 3x             3x     3x 3x 3x          
import type {
  Argv,
  CommandModule as YargsCommandModule,
  Arguments,
} from 'yargs';
 
import type { PackageData } from './utils.ts';
import { finalizeAndWriteData, readMonorepoFiles } from './utils.ts';
 
export type CreatePackageOptions = {
  name: string;
  description: string;
};
 
export type CommandModule = YargsCommandModule<object, CreatePackageOptions> & {
  command: string;
  handler: (args: Arguments<CreatePackageOptions>) => Promise<void>;
};
 
/**
 * The yargs command for creating a new monorepo package.
 */
const defaultCommand: CommandModule = {
  command: '$0',
  describe: 'Create a new monorepo package.',
  builder: (argv: Argv<object>) => {
    argv
      .options({
        name: {
          alias: 'n',
          describe: 'The package name. Will be prefixed with "@ocap/".',
          type: 'string',
          requiresArg: true,
        },
 
        description: {
          alias: 'd',
          describe:
            'A short description of the package, as used in package.json.',
          type: 'string',
          requiresArg: true,
        },
      })
      .example(
        '$0 --name fabulous-package --description "A fabulous package."',
        'Create a new package with the given name and description.',
      )
      .check((args) => {
        if (!args.name || typeof args.name !== 'string') {
          throw new Error('Missing required argument: "name"');
        }
        if (!args.description || typeof args.description !== 'string') {
          throw new Error('Missing required argument: "description"');
        }
 
        if (!args.name.startsWith('@ocap/')) {
          args.name = `@ocap/${args.name}`;
        }
 
        return true;
      });
 
    return argv as Argv<CreatePackageOptions>;
  },
  handler: async (args: Arguments<CreatePackageOptions>) =>
    await createPackageHandler(args),
};
 
export const commands = [defaultCommand];
export const commandMap = {
  $0: defaultCommand,
};
 
/**
 * Creates a new monorepo package.
 *
 * @param args - The yargs arguments.
 */
export async function createPackageHandler(
  args: Arguments<CreatePackageOptions>,
): Promise<void> {
  // TODO(#562): Use logger instead or change lint rule.
  // eslint-disable-next-line no-console
  console.log(`Attempting to create package "${args.name}"...`);
 
  const monorepoFileData = await readMonorepoFiles();
  const packageData: PackageData = {
    name: args.name,
    description: args.description,
    directoryName: args.name.slice('@ocap/'.length),
    currentYear: new Date().getFullYear().toString(),
  };
 
  await finalizeAndWriteData(packageData, monorepoFileData);
  // TODO(#562): Use logger instead or change lint rule.
  /* eslint-disable no-console */
  console.log(`Created package "${packageData.name}"!`);
  console.log();
  console.log(
    '\x1b[33mNote:\x1b[0m \x1b[1mRemember to add coverage thresholds to the root vitest.config.ts file!\x1b[0m',
  );
  /* eslint-enable no-console */
}