@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 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. When it finishes it prints the address
35
- your publication will live at.
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 the Markdown file and tells you the address the post will appear at. Write below the
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rathnasgala/cli",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
@@ -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
+ }
@@ -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', 'gala auth');
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', 'gala init')
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`, 'gala publish');
57
- if (ahead !== '' && ahead !== '0') return wrong(`${ahead} commit(s) not sent`, 'gala publish');
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
 
@@ -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('Use: gala domain [status|set <hostname>|check|cancel|remove]');
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('Verify it in the repository owner’s GitHub account, then run: gala domain check');
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('After DNS propagates, run: gala domain check');
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('Next: verify ownership, then run gala domain check.');
123
- else terminal.note('Next: configure DNS, then run gala domain check.');
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
  }
@@ -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 reporting the address.
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
- terminal.blank();
111
- terminal.note('gala new "Your first post"');
112
- if (domainChange) terminal.note('gala domain check');
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 publicationUrl(registration, created) {
287
- const base = registration?.canonicalBaseUrl ?? `https://${created.owner.toLowerCase()}.github.io`;
288
- const prefix = registration?.pathPrefix ?? `/${created.name}`;
289
- return `${base}${prefix === '/' ? '' : prefix}/`;
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) {
@@ -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('write below the second --- line, then: gala preview');
58
+ terminal.note(`write below the second --- line, then: ${cliCommand('preview')}`);
58
59
  return { file, metadata };
59
60
  }
60
61
 
@@ -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, 'gala prism status');
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, 'gala prism mode <off|presentation-only|manual|assisted>');
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, 'gala prism link-policy site <nofollow|follow>');
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, 'gala prism link-policy work <slug> <inherit|nofollow|follow>');
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('Use: gala prism link-policy site <nofollow|follow> or work <slug> <inherit|nofollow|follow>');
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, 'gala prism list <slug> [--language en]');
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, 'gala prism create <slug> --language en --depth brief --intent orientation');
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('Unknown Prism action. Run gala prism --help.');
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, 'gala prism edit <configuration-id> --file proposal.md');
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, 'gala prism generate <configuration-id>');
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('Use: gala prism submit <configuration-id> [revision-id]');
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('Use: gala prism approve <configuration-id> [revision-id] [--yes]');
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('Repository update did not finish before the 31-minute tracking deadline. Check gala prism status before retrying.');
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.');
@@ -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 gala doctor before upgrading`);
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('Run gala preview, then gala publish when the result is approved.');
173
+ terminal.note(`Run ${cliCommand('preview')}, then ${cliCommand('publish')} when the result is approved.`);
172
174
  return { changed: true, version: release.version };
173
175
  }
@@ -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: 'gala init [directory] [--name my-notes] [--domain blog.example.com]',
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: 'gala domain [status|set <hostname>|check|cancel|remove] [--root path]',
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: 'gala new "A durable idea" [--language en]',
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: 'gala prism <status|mode|link-policy|list|create|edit|generate|submit|approve|reject|revoke> [arguments]',
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: 'gala upgrade [--channel latest|next] [--yes]',
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 ?? `gala ${name}`}\n ${command.summary}\n\n`);
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 gala <command>\n\n${lines}\n\n Run any command with --help.\n\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
  }