mopub 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # mopub
2
+
3
+ Publish every package in a pnpm monorepo with one command. It builds, packs, diffs against what's on the registry, prompts for the new version(s), and publishes.
4
+
5
+ ## Use it
6
+
7
+ Dry-run first (packs everything into a temp folder so you can inspect):
8
+
9
+ ```
10
+ npx mopub
11
+ ```
12
+
13
+ It'll figure out when you last published, calculate a changelog based on git history in each sub-package, prompt you for version number(s) you'd like to publish, and write a ready-to-publish package + changelog to a staging folder under `/tmp`. It'll print out the command for actually publishing at your leisure:
14
+
15
+ ```
16
+ npx mopub prebuilt /tmp/mopub/your-repo-name-will-be-here/1777048359189
17
+ ```
18
+
19
+ Once the publish succeeds, it prints a command for drafting a GitHub release (opens the "new release" page with the changelog prefilled — no side effects until you click "Create release"):
20
+
21
+ ```
22
+ npx mopub release-notes --comparison 0.0.3-7...0.0.3-8
23
+ ```
24
+
25
+ Other commands:
26
+
27
+ - `npx mopub local` replaces workspace deps with `file:` paths and prints `pnpm add` commands so you can test installs in another project.
28
+ - `npx mopub --help` for the full option list.
29
+
30
+ ## Caveats
31
+
32
+ - pnpm only. It shells out to `pnpm list` and `pnpm recursive exec`, and looks for a `pnpm-workspace.yaml` or `pnpm-lock.yaml` at the workspace root.
33
+ - For monorepos. A single-package repo works, but there's no real reason to reach for this over `np`.
34
+ - Rough and ready. Expect to answer a few prompts and read some output before trusting `--publish`. The dry-run folder it prints (`/tmp/mopub/...`) is the source of truth for what will be shipped.
package/dist/publish.js CHANGED
@@ -17,7 +17,10 @@ export const PublishInput = z
17
17
  .boolean()
18
18
  .describe('actually publish packages - if not provided the tool will run in dry-run mode and create a directory containing the packages to be published.')
19
19
  .optional(),
20
- otp: z.string().describe('npm otp - needed with --publish. If not provided you will be prompted for it').optional(),
20
+ otp: z
21
+ .string()
22
+ .describe('npm OTP to pass through to `npm publish --otp`. Only needed for registries that still require OTP-based 2FA. Leave unset to use npm\'s default browser-based auth flow.')
23
+ .optional(),
21
24
  bump: z
22
25
  .enum(['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease', 'other', 'independent'])
23
26
  .describe('semver "bump" strategy - if not provided you will be prompted for it. Do not use with --version.')
@@ -62,7 +65,7 @@ export const setupContextTasks = [
62
65
  }
63
66
  if (!projectName)
64
67
  throw new Error(`Couldn't get package name from pnpm list output: ${list.stdout}`);
65
- ctx.tempDir = path.join('/tmp/npmono', projectName, Date.now().toString());
68
+ ctx.tempDir = path.join('/tmp/mopub', projectName, Date.now().toString());
66
69
  task.output = ctx.tempDir;
67
70
  fs.mkdirSync(ctx.tempDir, { recursive: true });
68
71
  },
@@ -437,18 +440,7 @@ export const publish = async (input) => {
437
440
  rendererOptions: { persistentOutput: true },
438
441
  task: async (ctx, task) => {
439
442
  const shouldActuallyPublish = input.publish;
440
- let otp = input.otp;
441
- if (shouldActuallyPublish) {
442
- otp ||= await task.prompt(ListrEnquirerPromptAdapter).run({
443
- message: 'Enter npm OTP (press enter to try publishing without MFA)',
444
- type: 'Input',
445
- validate: v => v === '' || (typeof v === 'string' && /^\d{6}$/.test(v)),
446
- });
447
- if (otp.length === 0) {
448
- task.output = 'No OTP provided - publish will likely error unless you have disabled MFA.';
449
- }
450
- }
451
- const publishTasks = createPublishTasks(ctx, { otp });
443
+ const publishTasks = createPublishTasks(ctx, { otp: input.otp });
452
444
  if (!shouldActuallyPublish)
453
445
  publishTasks.forEach(t => (t.skip = true));
454
446
  return task.newListr(publishTasks, { rendererOptions: { collapseSubtasks: false } });
@@ -461,7 +453,7 @@ export const publish = async (input) => {
461
453
  task: async (ctx, task) => {
462
454
  task.output = `To publish, run the following command:`;
463
455
  task.output += `\n\n`;
464
- task.output += `pnpm npmono prebuilt ${ctx.tempDir}`;
456
+ task.output += `npx mopub prebuilt ${ctx.tempDir}`;
465
457
  },
466
458
  },
467
459
  ], { ctx: {} });
@@ -483,7 +475,10 @@ function loadContext(folderPath) {
483
475
  export const PrebuiltInput = z.tuple([
484
476
  z.string().describe('Path to the prebuilt publishable folder'),
485
477
  z.object({
486
- otp: z.string().describe('OTP for publishing. If not provided, you will be prompted for it.').optional(),
478
+ otp: z
479
+ .string()
480
+ .describe('npm OTP to pass through to `npm publish --otp`. Only needed for registries that still require OTP-based 2FA. Leave unset to use npm\'s default browser-based auth flow.')
481
+ .optional(),
487
482
  }),
488
483
  ]);
489
484
  export async function publishPrebuilt([folder, options]) {
@@ -492,29 +487,7 @@ export async function publishPrebuilt([folder, options]) {
492
487
  throw new Error(`Failed to get npm username: ${me.stderr}`);
493
488
  console.log(me.stdout, '<<<<<<< npm whoami');
494
489
  const ctx = loadContext(folder);
495
- const tasks = new Listr([
496
- {
497
- title: 'Get OTP',
498
- enabled: !options.otp,
499
- task: async (_ctx, task) => {
500
- options.otp = await task.prompt(ListrEnquirerPromptAdapter).run({
501
- message: 'Enter npm OTP',
502
- type: 'Input',
503
- validate: v => v === '' || (typeof v === 'string' && /^\d{6}$/.test(v)),
504
- });
505
- if (options.otp === '') {
506
- const confirmed = await task.prompt(ListrEnquirerPromptAdapter).run({
507
- message: 'This will fail unless you have disabled MFA, which is not recommended.',
508
- type: 'confirm',
509
- });
510
- if (!confirmed) {
511
- throw new Error('OTP not provided');
512
- }
513
- }
514
- },
515
- },
516
- ...createPublishTasks(ctx, options),
517
- ], { ctx });
490
+ const tasks = new Listr(createPublishTasks(ctx, options), { ctx });
518
491
  await tasks.run();
519
492
  }
520
493
  function createPublishTasks(ctx, options) {
@@ -548,9 +521,13 @@ function createPublishTasks(ctx, options) {
548
521
  title: 'Publish complete',
549
522
  rendererOptions: { persistentOutput: true },
550
523
  task: async (_ctx, task) => {
524
+ const firstPkg = ctx.packages[0];
525
+ const left = loadLHSPackageJson(firstPkg)?.version || firstPkg?.shas?.left;
526
+ const right = firstPkg?.targetVersion || firstPkg?.shas?.right;
527
+ const comparison = left && right ? ` --comparison ${left}...${right}` : '';
551
528
  task.output = `To open a release draft, run the following command:`;
552
529
  task.output += `\n\n`;
553
- task.output += `pnpm npmono release-notes`;
530
+ task.output += `npx mopub release-notes${comparison}`;
554
531
  },
555
532
  },
556
533
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mopub",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Publish packages in a pnpm monorepo",
5
5
  "type": "module",
6
6
  "bin": {