mopub 0.0.1 → 0.0.3
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 +34 -0
- package/dist/publish.js +27 -41
- package/package.json +2 -2
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,14 @@ 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
|
|
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(),
|
|
24
|
+
tag: z
|
|
25
|
+
.string()
|
|
26
|
+
.describe('tag to publish to. Leave unset to use the last tag from the registry.')
|
|
27
|
+
.optional(),
|
|
21
28
|
bump: z
|
|
22
29
|
.enum(['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease', 'other', 'independent'])
|
|
23
30
|
.describe('semver "bump" strategy - if not provided you will be prompted for it. Do not use with --version.')
|
|
@@ -62,7 +69,7 @@ export const setupContextTasks = [
|
|
|
62
69
|
}
|
|
63
70
|
if (!projectName)
|
|
64
71
|
throw new Error(`Couldn't get package name from pnpm list output: ${list.stdout}`);
|
|
65
|
-
ctx.tempDir = path.join('/tmp/
|
|
72
|
+
ctx.tempDir = path.join('/tmp/mopub', projectName, Date.now().toString());
|
|
66
73
|
task.output = ctx.tempDir;
|
|
67
74
|
fs.mkdirSync(ctx.tempDir, { recursive: true });
|
|
68
75
|
},
|
|
@@ -437,18 +444,7 @@ export const publish = async (input) => {
|
|
|
437
444
|
rendererOptions: { persistentOutput: true },
|
|
438
445
|
task: async (ctx, task) => {
|
|
439
446
|
const shouldActuallyPublish = input.publish;
|
|
440
|
-
|
|
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 });
|
|
447
|
+
const publishTasks = createPublishTasks(ctx, { otp: input.otp, tag: input.tag });
|
|
452
448
|
if (!shouldActuallyPublish)
|
|
453
449
|
publishTasks.forEach(t => (t.skip = true));
|
|
454
450
|
return task.newListr(publishTasks, { rendererOptions: { collapseSubtasks: false } });
|
|
@@ -461,7 +457,7 @@ export const publish = async (input) => {
|
|
|
461
457
|
task: async (ctx, task) => {
|
|
462
458
|
task.output = `To publish, run the following command:`;
|
|
463
459
|
task.output += `\n\n`;
|
|
464
|
-
task.output += `
|
|
460
|
+
task.output += `npx mopub prebuilt ${ctx.tempDir}`;
|
|
465
461
|
},
|
|
466
462
|
},
|
|
467
463
|
], { ctx: {} });
|
|
@@ -483,7 +479,14 @@ function loadContext(folderPath) {
|
|
|
483
479
|
export const PrebuiltInput = z.tuple([
|
|
484
480
|
z.string().describe('Path to the prebuilt publishable folder'),
|
|
485
481
|
z.object({
|
|
486
|
-
otp: z
|
|
482
|
+
otp: z
|
|
483
|
+
.string()
|
|
484
|
+
.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.')
|
|
485
|
+
.optional(),
|
|
486
|
+
tag: z
|
|
487
|
+
.string()
|
|
488
|
+
.describe('tag to publish to. Leave unset to use the last tag from the registry.')
|
|
489
|
+
.optional(),
|
|
487
490
|
}),
|
|
488
491
|
]);
|
|
489
492
|
export async function publishPrebuilt([folder, options]) {
|
|
@@ -492,29 +495,7 @@ export async function publishPrebuilt([folder, options]) {
|
|
|
492
495
|
throw new Error(`Failed to get npm username: ${me.stderr}`);
|
|
493
496
|
console.log(me.stdout, '<<<<<<< npm whoami');
|
|
494
497
|
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 });
|
|
498
|
+
const tasks = new Listr(createPublishTasks(ctx, options), { ctx });
|
|
518
499
|
await tasks.run();
|
|
519
500
|
}
|
|
520
501
|
function createPublishTasks(ctx, options) {
|
|
@@ -531,7 +512,8 @@ function createPublishTasks(ctx, options) {
|
|
|
531
512
|
publishArgs.push('--otp', options.otp);
|
|
532
513
|
if (rhsPackageJson && semver.prerelease(rhsPackageJson.version)) {
|
|
533
514
|
const first = semver.prerelease(rhsPackageJson.version)?.[0];
|
|
534
|
-
|
|
515
|
+
let tag = options.tag;
|
|
516
|
+
tag ||= typeof first === 'string' ? first : 'next';
|
|
535
517
|
publishArgs.push('--tag', tag);
|
|
536
518
|
}
|
|
537
519
|
await pipeExeca(subtask, 'pnpm', ['publish', ...publishArgs], {
|
|
@@ -548,9 +530,13 @@ function createPublishTasks(ctx, options) {
|
|
|
548
530
|
title: 'Publish complete',
|
|
549
531
|
rendererOptions: { persistentOutput: true },
|
|
550
532
|
task: async (_ctx, task) => {
|
|
533
|
+
const firstPkg = ctx.packages[0];
|
|
534
|
+
const left = loadLHSPackageJson(firstPkg)?.version || firstPkg?.shas?.left;
|
|
535
|
+
const right = firstPkg?.targetVersion || firstPkg?.shas?.right;
|
|
536
|
+
const comparison = left && right ? ` --comparison ${left}...${right}` : '';
|
|
551
537
|
task.output = `To open a release draft, run the following command:`;
|
|
552
538
|
task.output += `\n\n`;
|
|
553
|
-
task.output += `
|
|
539
|
+
task.output += `npx mopub release-notes${comparison}`;
|
|
554
540
|
},
|
|
555
541
|
},
|
|
556
542
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mopub",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Publish packages in a pnpm monorepo",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"typescript": "^6.0.3"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"
|
|
35
|
+
"clean": "rm -rf dist",
|
|
36
36
|
"build": "tsc --noEmit false --outDir dist",
|
|
37
37
|
"lint": "eslint .",
|
|
38
38
|
"test": "echo maybe later"
|