@rathnasgala/cli 1.1.7 → 1.1.9
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 +12 -4
- package/package.json +1 -1
- package/src/cli/invocation.js +9 -0
- package/src/commands/doctor.js +5 -4
- package/src/commands/domain.js +6 -5
- package/src/commands/init.js +37 -12
- package/src/commands/new.js +2 -1
- package/src/commands/prism.js +17 -13
- package/src/commands/upgrade.js +4 -2
- package/src/commands-manifest.js +6 -5
- package/src/index.js +4 -2
package/README.md
CHANGED
|
@@ -31,8 +31,9 @@ accepted and its `.git` directory is preserved. To reserve a custom domain durin
|
|
|
31
31
|
before activating it.
|
|
32
32
|
|
|
33
33
|
It signs you in to Gala and to GitHub if you are not already, creates the repository, registers the
|
|
34
|
-
publication, and leaves a working checkout in the folder.
|
|
35
|
-
|
|
34
|
+
publication, and leaves a working checkout in the folder. GitHub starts the first deployment in the
|
|
35
|
+
background. The command links to that deployment rather than presenting the public address as live
|
|
36
|
+
before GitHub has finished.
|
|
36
37
|
|
|
37
38
|
On the first run, it opens GitHub's Gala App installation page. Choose the account Gala may use,
|
|
38
39
|
finish the installation, and return to the terminal; the same command resumes automatically.
|
|
@@ -43,12 +44,19 @@ unavoidable. Everything else is automatic.
|
|
|
43
44
|
|
|
44
45
|
## Write
|
|
45
46
|
|
|
47
|
+
Every command continues to run through `npx`; `init` does not install a global `gala` executable.
|
|
48
|
+
To see every command, run:
|
|
49
|
+
|
|
50
|
+
```console
|
|
51
|
+
npx --yes @rathnasgala/cli@latest --help
|
|
52
|
+
```
|
|
53
|
+
|
|
46
54
|
```console
|
|
47
55
|
npx --yes @rathnasgala/cli@latest new "The places we return to"
|
|
48
56
|
```
|
|
49
57
|
|
|
50
|
-
This creates
|
|
51
|
-
second `---` line.
|
|
58
|
+
This creates a local Markdown draft; it does not publish anything. It also tells you the address the
|
|
59
|
+
post will use after a successful publication. Write below the second `---` line.
|
|
52
60
|
|
|
53
61
|
```console
|
|
54
62
|
npx --yes @rathnasgala/cli@latest preview
|
package/package.json
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const CLI_INVOCATION = 'npx --yes @rathnasgala/cli@latest';
|
|
2
|
+
|
|
3
|
+
export function cliCommand(argumentsText = '') {
|
|
4
|
+
return argumentsText === '' ? CLI_INVOCATION : `${CLI_INVOCATION} ${argumentsText}`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function shellArgument(value) {
|
|
8
|
+
return /^[A-Za-z0-9_./-]+$/.test(value) ? value : `'${value.replaceAll("'", "'\\''")}'`;
|
|
9
|
+
}
|
package/src/commands/doctor.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { galaApi } from '../api/gala.js';
|
|
5
5
|
import { galaCredential } from '../auth/gala.js';
|
|
6
6
|
import { githubCredential } from '../auth/github.js';
|
|
7
|
+
import { cliCommand } from '../cli/invocation.js';
|
|
7
8
|
import { createGit } from '../git.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -23,7 +24,7 @@ export async function doctor({ terminal, options, cwd = process.cwd() }) {
|
|
|
23
24
|
const accepted = await galaApi({ baseUrl: gala.apiBaseUrl, token: gala.accessToken }).accepted();
|
|
24
25
|
return accepted
|
|
25
26
|
? ok(`valid until ${new Date(gala.expiresAt).toLocaleString()}`)
|
|
26
|
-
: wrong('the API no longer accepts it', '
|
|
27
|
+
: wrong('the API no longer accepts it', cliCommand('auth'));
|
|
27
28
|
}));
|
|
28
29
|
|
|
29
30
|
checks.push(await checkCredential('GitHub sign-in', async () => {
|
|
@@ -45,7 +46,7 @@ export async function doctor({ terminal, options, cwd = process.cwd() }) {
|
|
|
45
46
|
const source = await readFile(workflow, 'utf8');
|
|
46
47
|
const siteId = /site-id:\s*([0-9A-Z]{26})/.exec(source)?.[1];
|
|
47
48
|
return siteId == null
|
|
48
|
-
? wrong('no site id — this publication may not be registered', '
|
|
49
|
+
? wrong('no site id — this publication may not be registered', cliCommand('init'))
|
|
49
50
|
: ok(siteId);
|
|
50
51
|
}, 'the workflow is missing; registration writes it'));
|
|
51
52
|
|
|
@@ -53,8 +54,8 @@ export async function doctor({ terminal, options, cwd = process.cwd() }) {
|
|
|
53
54
|
const git = createGit({ root });
|
|
54
55
|
const dirty = await git.run(['status', '--porcelain'], { capture: true });
|
|
55
56
|
const ahead = await git.run(['rev-list', '--count', '@{upstream}..HEAD'], { capture: true, allow: [0, 128] });
|
|
56
|
-
if (dirty !== '') return wrong(`${dirty.split('\n').length} file(s) not recorded`, '
|
|
57
|
-
if (ahead !== '' && ahead !== '0') return wrong(`${ahead} commit(s) not sent`, '
|
|
57
|
+
if (dirty !== '') return wrong(`${dirty.split('\n').length} file(s) not recorded`, cliCommand('publish'));
|
|
58
|
+
if (ahead !== '' && ahead !== '0') return wrong(`${ahead} commit(s) not sent`, cliCommand('publish'));
|
|
58
59
|
return ok('everything is on GitHub');
|
|
59
60
|
}, 'this folder is not a git checkout'));
|
|
60
61
|
|
package/src/commands/domain.js
CHANGED
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { galaApi } from '../api/gala.js';
|
|
4
4
|
import { galaCredential } from '../auth/gala.js';
|
|
5
5
|
import { UsageError } from '../cli/args.js';
|
|
6
|
+
import { cliCommand } from '../cli/invocation.js';
|
|
6
7
|
import { customDomain } from '../domain.js';
|
|
7
8
|
import { readPublication } from '../publication.js';
|
|
8
9
|
|
|
@@ -16,7 +17,7 @@ export async function domain({ terminal, options, cwd = process.cwd() }) {
|
|
|
16
17
|
}
|
|
17
18
|
const [action = 'status', value, ...extra] = options.positional;
|
|
18
19
|
if (extra.length > 0 || !['status', 'set', 'check', 'cancel', 'remove'].includes(action)) {
|
|
19
|
-
throw new UsageError(
|
|
20
|
+
throw new UsageError(`Use: ${cliCommand('domain [status|set <hostname>|check|cancel|remove]')}`);
|
|
20
21
|
}
|
|
21
22
|
if (action === 'set' && value == null) throw new UsageError('domain set needs a hostname');
|
|
22
23
|
if (action !== 'set' && value != null) throw new UsageError(`domain ${action} takes no hostname`);
|
|
@@ -45,7 +46,7 @@ export async function domain({ terminal, options, cwd = process.cwd() }) {
|
|
|
45
46
|
pathPrefix: '/',
|
|
46
47
|
});
|
|
47
48
|
terminal.done(`Reserved ${checked.host}`);
|
|
48
|
-
terminal.note(
|
|
49
|
+
terminal.note(`Verify it in the repository owner’s GitHub account, then run: ${cliCommand('domain check')}`);
|
|
49
50
|
terminal.openUrl('https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/verifying-your-custom-domain-for-github-pages');
|
|
50
51
|
return change;
|
|
51
52
|
}
|
|
@@ -83,7 +84,7 @@ export async function domain({ terminal, options, cwd = process.cwd() }) {
|
|
|
83
84
|
const configured = await api.configureTopologyChange(publication.siteId, pending.changeId);
|
|
84
85
|
terminal.done(`GitHub verified ${configured.cname}`);
|
|
85
86
|
terminal.note(dnsInstruction(configured.cname, await providerHost(api, publication.siteId)));
|
|
86
|
-
terminal.note(
|
|
87
|
+
terminal.note(`After DNS propagates, run: ${cliCommand('domain check')}`);
|
|
87
88
|
return configured;
|
|
88
89
|
}
|
|
89
90
|
const committed = await api.commitTopologyChange(publication.siteId, pending.changeId);
|
|
@@ -119,6 +120,6 @@ function dnsInstruction(host, target) {
|
|
|
119
120
|
function showPending(terminal, pending) {
|
|
120
121
|
terminal.result(`${pending.canonicalBaseUrl}${pending.pathPrefix}`);
|
|
121
122
|
terminal.note(`State: ${pending.state}`);
|
|
122
|
-
if (pending.state === 'PREPARED') terminal.note(
|
|
123
|
-
else terminal.note(
|
|
123
|
+
if (pending.state === 'PREPARED') terminal.note(`Next: verify ownership, then run ${cliCommand('domain check')}.`);
|
|
124
|
+
else terminal.note(`Next: configure DNS, then run ${cliCommand('domain check')}.`);
|
|
124
125
|
}
|
package/src/commands/init.js
CHANGED
|
@@ -7,6 +7,7 @@ import { galaCredential } from '../auth/gala.js';
|
|
|
7
7
|
import { githubCredential } from '../auth/github.js';
|
|
8
8
|
import { cloneRepository, createGit, populateEmptyRepository } from '../git.js';
|
|
9
9
|
import { UsageError } from '../cli/args.js';
|
|
10
|
+
import { CLI_INVOCATION, shellArgument } from '../cli/invocation.js';
|
|
10
11
|
import { customDomain } from '../domain.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -26,7 +27,8 @@ import { customDomain } from '../domain.js';
|
|
|
26
27
|
* - **GitHub** turns on Pages by itself once publishing creates a `gh-pages` branch. The CLI used
|
|
27
28
|
* to poll ten minutes for a run it had caused, then call an API that changed nothing.
|
|
28
29
|
*
|
|
29
|
-
* What is left is genuinely the CLI's: asking what to call it, cloning, and
|
|
30
|
+
* What is left is genuinely the CLI's: asking what to call it, cloning, and explaining the next
|
|
31
|
+
* steps without presenting a deployment as live before GitHub has finished it.
|
|
30
32
|
*/
|
|
31
33
|
const NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
32
34
|
const GITHUB_APP_INSTALLATION_URL = 'https://github.com/apps/gala67-app/installations/new';
|
|
@@ -87,10 +89,6 @@ export async function init({ terminal, options, cwd = process.cwd() }) {
|
|
|
87
89
|
// writer's copy is the publication as it actually exists.
|
|
88
90
|
await git.takeRemote();
|
|
89
91
|
|
|
90
|
-
terminal.done(`Created ${created.owner}/${created.name}`);
|
|
91
|
-
terminal.result(publicationUrl(registration, created));
|
|
92
|
-
terminal.note(path.relative(cwd, directory) || '.');
|
|
93
|
-
|
|
94
92
|
let domainChange;
|
|
95
93
|
if (checkedDomain?.host) {
|
|
96
94
|
terminal.step(`Reserving ${checkedDomain.host}`);
|
|
@@ -107,9 +105,13 @@ export async function init({ terminal, options, cwd = process.cwd() }) {
|
|
|
107
105
|
}
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
reportCreatedPublication({
|
|
109
|
+
terminal,
|
|
110
|
+
owner: created.owner,
|
|
111
|
+
name: created.name,
|
|
112
|
+
directoryLabel: path.relative(cwd, directory) || '.',
|
|
113
|
+
hasDomainChange: domainChange != null
|
|
114
|
+
});
|
|
113
115
|
|
|
114
116
|
return { owner: created.owner, name: created.name, siteId: registration.siteId, root: directory };
|
|
115
117
|
}
|
|
@@ -283,10 +285,33 @@ async function hasReference(directory) {
|
|
|
283
285
|
return false;
|
|
284
286
|
}
|
|
285
287
|
|
|
286
|
-
function
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
288
|
+
export function reportCreatedPublication({
|
|
289
|
+
terminal,
|
|
290
|
+
owner,
|
|
291
|
+
name,
|
|
292
|
+
directoryLabel,
|
|
293
|
+
hasDomainChange = false
|
|
294
|
+
}) {
|
|
295
|
+
const run = CLI_INVOCATION;
|
|
296
|
+
terminal.done(`Created ${owner}/${name}`);
|
|
297
|
+
terminal.note('The first deployment is running in GitHub Actions. The public site is not live yet.');
|
|
298
|
+
terminal.note(`track it at https://github.com/${owner}/${name}/actions`);
|
|
299
|
+
|
|
300
|
+
terminal.blank();
|
|
301
|
+
terminal.result('Next steps');
|
|
302
|
+
if (directoryLabel !== '.') terminal.note(`cd ${shellArgument(directoryLabel)}`);
|
|
303
|
+
terminal.note(`${run} new "Your first post"`);
|
|
304
|
+
terminal.note('creates a local Markdown draft; it does not publish');
|
|
305
|
+
terminal.note(`${run} preview`);
|
|
306
|
+
terminal.note('builds and serves the publication locally');
|
|
307
|
+
terminal.note(`${run} publish`);
|
|
308
|
+
terminal.note('checks and sends the work to GitHub');
|
|
309
|
+
if (hasDomainChange) {
|
|
310
|
+
terminal.note(`${run} domain check`);
|
|
311
|
+
terminal.note('checks whether the custom domain is ready');
|
|
312
|
+
}
|
|
313
|
+
terminal.note(`${run} --help`);
|
|
314
|
+
terminal.note('lists every available command');
|
|
290
315
|
}
|
|
291
316
|
|
|
292
317
|
function idempotencyKey(owner, name) {
|
package/src/commands/new.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { stringify } from 'yaml';
|
|
12
12
|
|
|
13
13
|
import { UsageError } from '../cli/args.js';
|
|
14
|
+
import { cliCommand } from '../cli/invocation.js';
|
|
14
15
|
import { postUrl, readPublication } from '../publication.js';
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -54,7 +55,7 @@ export async function createPost({ terminal, options, cwd = process.cwd(), now =
|
|
|
54
55
|
if (address != null) terminal.note(`will appear at ${address}`);
|
|
55
56
|
|
|
56
57
|
terminal.blank();
|
|
57
|
-
terminal.note(
|
|
58
|
+
terminal.note(`write below the second --- line, then: ${cliCommand('preview')}`);
|
|
58
59
|
return { file, metadata };
|
|
59
60
|
}
|
|
60
61
|
|
package/src/commands/prism.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { galaApi } from '../api/gala.js';
|
|
5
5
|
import { galaCredential } from '../auth/gala.js';
|
|
6
6
|
import { UsageError } from '../cli/args.js';
|
|
7
|
+
import { cliCommand } from '../cli/invocation.js';
|
|
7
8
|
import { createGit } from '../git.js';
|
|
8
9
|
import { readPublication } from '../publication.js';
|
|
9
10
|
|
|
@@ -25,7 +26,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
25
26
|
const [action = 'status', ...args] = options.positional;
|
|
26
27
|
|
|
27
28
|
if (action === 'status') {
|
|
28
|
-
requireArgs(args, 0, '
|
|
29
|
+
requireArgs(args, 0, cliCommand('prism status'));
|
|
29
30
|
const state = await api.json(`/v1/sites/${publication.siteId}/prism`, { action: 'Prism status' });
|
|
30
31
|
terminal.result(`Prism ${state.publishedMode}`);
|
|
31
32
|
terminal.note(`Mode: requested ${state.requestedMode}; published ${state.publishedMode}`);
|
|
@@ -39,7 +40,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
39
40
|
const expectedRepositoryHeadSha = inventory.headSha;
|
|
40
41
|
|
|
41
42
|
if (action === 'mode') {
|
|
42
|
-
requireArgs(args, 1, '
|
|
43
|
+
requireArgs(args, 1, cliCommand('prism mode <off|presentation-only|manual|assisted>'));
|
|
43
44
|
const mode = MODES.get(args[0]);
|
|
44
45
|
if (!mode) throw new UsageError('Prism mode must be off, presentation-only, manual, or assisted.');
|
|
45
46
|
if (mode === 'OFF' || mode === 'PRESENTATION_ONLY') await confirm(terminal, options, `Change Prism mode to ${args[0]}?`);
|
|
@@ -52,7 +53,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
52
53
|
if (action === 'link-policy') {
|
|
53
54
|
const [scope, target, value] = args;
|
|
54
55
|
if (scope === 'site') {
|
|
55
|
-
requireArgs(args, 2, '
|
|
56
|
+
requireArgs(args, 2, cliCommand('prism link-policy site <nofollow|follow>'));
|
|
56
57
|
const policy = policyValue(target);
|
|
57
58
|
const result = await mutate(api, `/v1/sites/${publication.siteId}/prism`, 'PUT', {
|
|
58
59
|
configurationLinkPolicy: policy, expectedRepositoryHeadSha,
|
|
@@ -60,7 +61,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
60
61
|
return settleMutation(api, terminal, publication, result);
|
|
61
62
|
}
|
|
62
63
|
if (scope === 'work') {
|
|
63
|
-
requireArgs(args, 3, '
|
|
64
|
+
requireArgs(args, 3, cliCommand('prism link-policy work <slug> <inherit|nofollow|follow>'));
|
|
64
65
|
const post = resolvePost(inventory, target, options.value('language'), publication.defaultLanguage);
|
|
65
66
|
if (value === 'inherit') {
|
|
66
67
|
const result = await mutate(api,
|
|
@@ -76,11 +77,14 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
76
77
|
}, 'Prism work link policy');
|
|
77
78
|
return settleMutation(api, terminal, publication, result);
|
|
78
79
|
}
|
|
79
|
-
throw new UsageError(
|
|
80
|
+
throw new UsageError(
|
|
81
|
+
`Use: ${cliCommand('prism link-policy site <nofollow|follow>')} or `
|
|
82
|
+
+ cliCommand('prism link-policy work <slug> <inherit|nofollow|follow>')
|
|
83
|
+
);
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
if (action === 'list') {
|
|
83
|
-
requireArgs(args, 1, '
|
|
87
|
+
requireArgs(args, 1, cliCommand('prism list <slug> [--language en]'));
|
|
84
88
|
const post = resolvePost(inventory, args[0], options.value('language'), publication.defaultLanguage);
|
|
85
89
|
const result = await configurations(api, publication.siteId, post);
|
|
86
90
|
terminal.result(`${result.configurations.length} configuration${result.configurations.length === 1 ? '' : 's'}`);
|
|
@@ -91,7 +95,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
if (action === 'create') {
|
|
94
|
-
requireArgs(args, 1, '
|
|
98
|
+
requireArgs(args, 1, cliCommand('prism create <slug> --language en --depth brief --intent orientation'));
|
|
95
99
|
const post = resolvePost(inventory, args[0], options.value('language'), publication.defaultLanguage);
|
|
96
100
|
const current = await configurations(api, publication.siteId, post);
|
|
97
101
|
const result = await mutate(api,
|
|
@@ -108,7 +112,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
if (!['edit', 'generate', 'submit', 'approve', 'reject', 'revoke'].includes(action)) {
|
|
111
|
-
throw new UsageError(
|
|
115
|
+
throw new UsageError(`Unknown Prism action. Run ${cliCommand('prism --help')}.`);
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
const configurationId = args[0];
|
|
@@ -119,7 +123,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
119
123
|
const base = `/v1/sites/${publication.siteId}/articles/${post.articleId}/configurations/${configurationId}`;
|
|
120
124
|
|
|
121
125
|
if (action === 'edit') {
|
|
122
|
-
requireArgs(args, 1, '
|
|
126
|
+
requireArgs(args, 1, cliCommand('prism edit <configuration-id> --file proposal.md'));
|
|
123
127
|
const filename = options.value('file');
|
|
124
128
|
if (!filename) throw new UsageError('Prism edit needs --file proposal.md.');
|
|
125
129
|
const markdown = await readFile(path.resolve(root, filename), 'utf8');
|
|
@@ -132,7 +136,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
if (action === 'generate') {
|
|
135
|
-
requireArgs(args, 1, '
|
|
139
|
+
requireArgs(args, 1, cliCommand('prism generate <configuration-id>'));
|
|
136
140
|
const result = await mutate(api, `${base}/generation-jobs`, 'POST', {
|
|
137
141
|
expectedSourceContentHash: collection.sourceRevisionHash,
|
|
138
142
|
hashContract: collection.hashContract,
|
|
@@ -146,7 +150,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
146
150
|
throw new UsageError(`${action} needs a revision ID when there is no working revision.`);
|
|
147
151
|
}
|
|
148
152
|
if (action === 'submit') {
|
|
149
|
-
if (args.length > 2) throw new UsageError(
|
|
153
|
+
if (args.length > 2) throw new UsageError(`Use: ${cliCommand('prism submit <configuration-id> [revision-id]')}`);
|
|
150
154
|
if (revisionId !== configuration.workingRevision?.revisionId) {
|
|
151
155
|
throw new UsageError('Only the current working revision can be submitted. Refresh the configuration and try again.');
|
|
152
156
|
}
|
|
@@ -165,7 +169,7 @@ export async function prism({ terminal, options, cwd = process.cwd() }) {
|
|
|
165
169
|
|
|
166
170
|
const reason = options.value('reason');
|
|
167
171
|
if (action === 'approve') {
|
|
168
|
-
if (args.length > 2) throw new UsageError(
|
|
172
|
+
if (args.length > 2) throw new UsageError(`Use: ${cliCommand('prism approve <configuration-id> [revision-id] [--yes]')}`);
|
|
169
173
|
if (revisionId !== configuration.workingRevision?.revisionId) {
|
|
170
174
|
throw new UsageError('Only the current working revision can be approved. Refresh the configuration and try again.');
|
|
171
175
|
}
|
|
@@ -292,7 +296,7 @@ async function settleMutation(api, terminal, publication, result) {
|
|
|
292
296
|
throw new UsageError(`Repository update failed (${state.errorCode ?? 'unknown error'}). Run the command again after correcting the cause.`);
|
|
293
297
|
}
|
|
294
298
|
if (state.status !== 'COMMITTED') {
|
|
295
|
-
throw new UsageError(
|
|
299
|
+
throw new UsageError(`Repository update did not finish before the 31-minute tracking deadline. Check ${cliCommand('prism status')} before retrying.`);
|
|
296
300
|
}
|
|
297
301
|
if (!state.publicationAttemptSha) {
|
|
298
302
|
terminal.result('Repository updated. No publication attempt was returned.');
|
package/src/commands/upgrade.js
CHANGED
|
@@ -4,6 +4,8 @@ import { tmpdir } from 'node:os';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { x as extractTar } from 'tar';
|
|
6
6
|
|
|
7
|
+
import { cliCommand } from '../cli/invocation.js';
|
|
8
|
+
|
|
7
9
|
const PACKAGE = '@rathnasgala/theme';
|
|
8
10
|
const REGISTRY = 'https://registry.npmjs.org';
|
|
9
11
|
const PROTECTED = ['.git/', 'content/', 'custom.css', 'site.config.yml'];
|
|
@@ -81,7 +83,7 @@ async function assertNoManagedDrift(root, installed) {
|
|
|
81
83
|
for (const [managed, expected] of Object.entries(installed.files)) {
|
|
82
84
|
const file = path.join(root, managed);
|
|
83
85
|
if (!await exists(file) || (await lstat(file)).isSymbolicLink() || sha256(await readFile(file)) !== expected) {
|
|
84
|
-
throw new Error(`${managed} has local changes; restore it with
|
|
86
|
+
throw new Error(`${managed} has local changes; restore it with ${cliCommand('doctor')} before upgrading`);
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
}
|
|
@@ -168,6 +170,6 @@ export async function upgrade({ terminal, options, cwd = process.cwd(), fetchImp
|
|
|
168
170
|
await rm(unpacked.temporary, { recursive: true, force: true });
|
|
169
171
|
}
|
|
170
172
|
terminal.done(`Upgraded managed theme to ${release.version}`);
|
|
171
|
-
terminal.note(
|
|
173
|
+
terminal.note(`Run ${cliCommand('preview')}, then ${cliCommand('publish')} when the result is approved.`);
|
|
172
174
|
return { changed: true, version: release.version };
|
|
173
175
|
}
|
package/src/commands-manifest.js
CHANGED
|
@@ -7,6 +7,7 @@ import { preview } from './commands/preview.js';
|
|
|
7
7
|
import { publish } from './commands/publish.js';
|
|
8
8
|
import { prism } from './commands/prism.js';
|
|
9
9
|
import { upgrade } from './commands/upgrade.js';
|
|
10
|
+
import { cliCommand } from './cli/invocation.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Commands in the order a writer meets them.
|
|
@@ -31,19 +32,19 @@ export const COMMANDS = {
|
|
|
31
32
|
},
|
|
32
33
|
init: {
|
|
33
34
|
summary: 'Create a publication in an empty directory',
|
|
34
|
-
usage: '
|
|
35
|
+
usage: cliCommand('init [directory] [--name my-notes] [--domain blog.example.com]'),
|
|
35
36
|
flags: ['name', 'domain', 'api-base-url'],
|
|
36
37
|
run: init
|
|
37
38
|
},
|
|
38
39
|
domain: {
|
|
39
40
|
summary: 'Inspect or change this publication’s custom domain',
|
|
40
|
-
usage: '
|
|
41
|
+
usage: cliCommand('domain [status|set <hostname>|check|cancel|remove] [--root path]'),
|
|
41
42
|
flags: ['root', 'api-base-url'],
|
|
42
43
|
run: domain
|
|
43
44
|
},
|
|
44
45
|
new: {
|
|
45
46
|
summary: 'Start a post',
|
|
46
|
-
usage: '
|
|
47
|
+
usage: cliCommand('new "A durable idea" [--language en]'),
|
|
47
48
|
flags: ['root', 'language', 'today'],
|
|
48
49
|
run: createPost
|
|
49
50
|
},
|
|
@@ -60,14 +61,14 @@ export const COMMANDS = {
|
|
|
60
61
|
},
|
|
61
62
|
prism: {
|
|
62
63
|
summary: 'Manage author-approved Prism configurations',
|
|
63
|
-
usage: '
|
|
64
|
+
usage: cliCommand('prism <status|mode|link-policy|list|create|edit|generate|submit|approve|reject|revoke> [arguments]'),
|
|
64
65
|
flags: ['root', 'api-base-url', 'language', 'depth', 'intent', 'modality', 'file', 'reason'],
|
|
65
66
|
switches: ['yes'],
|
|
66
67
|
run: prism
|
|
67
68
|
},
|
|
68
69
|
upgrade: {
|
|
69
70
|
summary: 'Inspect and apply a verified managed-theme update',
|
|
70
|
-
usage: '
|
|
71
|
+
usage: cliCommand('upgrade [--channel latest|next] [--yes]'),
|
|
71
72
|
flags: ['root', 'channel'],
|
|
72
73
|
switches: ['yes'],
|
|
73
74
|
run: upgrade
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { UsageError, parseArguments } from './cli/args.js';
|
|
3
|
+
import { CLI_INVOCATION, cliCommand } from './cli/invocation.js';
|
|
3
4
|
import { createTerminal } from './cli/terminal.js';
|
|
4
5
|
import { COMMANDS } from './commands-manifest.js';
|
|
5
6
|
|
|
@@ -20,7 +21,7 @@ if (command == null) {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
if (argv.includes('--help') || argv.includes('-h')) {
|
|
23
|
-
process.stdout.write(`\n ${command.usage ??
|
|
24
|
+
process.stdout.write(`\n ${command.usage ?? cliCommand(name)}\n ${command.summary}\n\n`);
|
|
24
25
|
process.exit(0);
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -56,5 +57,6 @@ function usage() {
|
|
|
56
57
|
const lines = Object.entries(COMMANDS)
|
|
57
58
|
.map(([key, { summary }]) => ` ${key.padEnd(9)} ${summary}`)
|
|
58
59
|
.join('\n');
|
|
59
|
-
process.stdout.write(`\n
|
|
60
|
+
process.stdout.write(`\n ${CLI_INVOCATION} <command>\n\n${lines}\n\n`
|
|
61
|
+
+ ` Run ${CLI_INVOCATION} <command> --help for details.\n\n`);
|
|
60
62
|
}
|