@pitcher/cli-scripts 2.4.0 → 2.5.0

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
@@ -270,6 +270,23 @@ p announcements scaffold --out ./announcement.json --api-key myapikey
270
270
 
271
271
  `scaffold` returns the starter JSON in the envelope `data`; pass `--out <path>` to write it to a file instead.
272
272
 
273
+ ## To run the `themes` command:
274
+
275
+ Read canvas/branding themes (colors via `settings`, fonts via `typography`, plus `assets`/`logo`) to reference when authoring email/DSR/canvas content. Read-only.
276
+
277
+ ```bash
278
+ # List all themes in the org (returns full theme objects)
279
+ p themes list --api-key myapikey
280
+
281
+ # Narrow to one instance; add per-theme canvas usage and canvas ids
282
+ p themes list --instance-id 01... --with-usage --with-canvas-ids --api-key myapikey
283
+
284
+ # Get one theme by id
285
+ p themes get --id 01THEMEID... --api-key myapikey
286
+ ```
287
+
288
+ `list` is server-capped (newest-first) with no `--limit`/`--page`; when the cap is hit the envelope carries a truncation warning. `--instance-id` narrows to themes bound to that instance and **excludes** org-level (default) themes, so omit it to see everything usable in the org.
289
+
273
290
  ## To run the `org` command:
274
291
 
275
292
  Read the organization the API key belongs to.
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ import { createAnalyticsCommand } from './src/commands/analytics.js';
17
17
  import { createAnnouncementsCommand } from './src/commands/announcements.js';
18
18
  import { createDsrLandingCommand } from './src/commands/dsrLanding.js';
19
19
  import { createEmailTemplateCommand } from './src/commands/emailTemplate.js';
20
+ import { createThemesCommand } from './src/commands/themes.js';
20
21
  const __filename = fileURLToPath(import.meta.url);
21
22
  const __dirname = dirname(__filename);
22
23
  const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
@@ -39,6 +40,7 @@ program.addCommand(createTagsCommand());
39
40
  program.addCommand(createAnnouncementsCommand());
40
41
  program.addCommand(createDsrLandingCommand());
41
42
  program.addCommand(createEmailTemplateCommand());
43
+ program.addCommand(createThemesCommand());
42
44
  program.addCommand(createOrgCommand());
43
45
  program.addCommand(createAnalyticsCommand());
44
46
  program.parseAsync(process.argv);
@@ -0,0 +1,17 @@
1
+ import { Command } from 'commander';
2
+ import type { AxiosInstance } from 'axios';
3
+ import { type CommonOpts } from '../core/http.js';
4
+ import { type Envelope } from '../core/envelope.js';
5
+ export declare const THEME_RETRIEVE_LIMIT = 1000;
6
+ export interface ThemesDeps {
7
+ client?: AxiosInstance;
8
+ }
9
+ export declare function runThemesList(opts: CommonOpts & {
10
+ instanceId?: string;
11
+ withUsage?: boolean;
12
+ withCanvasIds?: boolean;
13
+ }, deps?: ThemesDeps): Promise<Envelope<unknown>>;
14
+ export declare function runThemesGet(opts: CommonOpts & {
15
+ id?: string;
16
+ }, deps?: ThemesDeps): Promise<Envelope<unknown>>;
17
+ export declare function createThemesCommand(): Command;
@@ -0,0 +1,82 @@
1
+ import { Command } from 'commander';
2
+ import { clientFor, toCliError } from '../core/http.js';
3
+ import { ok, fail } from '../core/envelope.js';
4
+ import { createCliError } from '../core/errors.js';
5
+ import { emitEnvelope } from '../core/output.js';
6
+ import { withAuthFlags } from './withAuth.js';
7
+ const THEMES_ENDPOINT = '/core/api/protected/themes';
8
+ // Mirror of next-core THEME_RETRIEVE_LIMIT (themes/limits.ts). The list route
9
+ // caps at this many rows (newest-first) with no total/hasMore, so a full page
10
+ // may be silently truncated — we warn when the count equals the cap. Keep this
11
+ // in sync with the server constant: if the server cap changes and this does not,
12
+ // the truncation warning stops firing.
13
+ export const THEME_RETRIEVE_LIMIT = 1000;
14
+ export async function runThemesList(opts, deps = {}) {
15
+ try {
16
+ const client = clientFor(opts, deps);
17
+ const params = {};
18
+ if (opts.instanceId)
19
+ params.instance_id = opts.instanceId;
20
+ // The route compares === 'true' (string); send the literal only when set.
21
+ if (opts.withUsage)
22
+ params.used_in_canvases_count = 'true';
23
+ if (opts.withCanvasIds)
24
+ params.include_canvas_ids = 'true';
25
+ const res = await client.get(THEMES_ENDPOINT, { params });
26
+ const data = res.data;
27
+ if (Array.isArray(data) && data.length === THEME_RETRIEVE_LIMIT) {
28
+ const base = `results may be truncated at the server cap of ${THEME_RETRIEVE_LIMIT}`;
29
+ // Only advise --instance-id when it isn't already narrowing the scope.
30
+ return ok(data, [opts.instanceId ? base : `${base}; narrow with --instance-id`]);
31
+ }
32
+ return ok(data);
33
+ }
34
+ catch (e) {
35
+ return fail(toCliError(e));
36
+ }
37
+ }
38
+ export async function runThemesGet(opts, deps = {}) {
39
+ try {
40
+ if (!opts.id)
41
+ throw createCliError('VALIDATION', '--id is required for themes get');
42
+ const client = clientFor(opts, deps);
43
+ const res = await client.get(`${THEMES_ENDPOINT}/${encodeURIComponent(opts.id)}`);
44
+ return ok(res.data);
45
+ }
46
+ catch (e) {
47
+ return fail(toCliError(e));
48
+ }
49
+ }
50
+ const LIST_HELP = `
51
+ Themes carry the instance branding you reference when authoring:
52
+ settings colors
53
+ typography fonts
54
+ assets, logo branding assets
55
+
56
+ Notes:
57
+ - Results are server-capped (newest-first); there is no --limit/--page.
58
+ - --instance-id narrows to themes bound to that instance and EXCLUDES
59
+ org-level (default) themes; omit it to see all themes in the org.`;
60
+ export function createThemesCommand() {
61
+ const cmd = new Command('themes').description('read canvas/branding themes (colors, fonts, assets) for authoring');
62
+ withAuthFlags(cmd.command('list'))
63
+ .option('--instance-id <id>', 'Filter to themes bound to this instance (excludes org-level themes)')
64
+ .option('--with-usage', 'Include a per-theme count of canvases using it')
65
+ .option('--with-canvas-ids', 'Include the canvas ids using each theme')
66
+ .addHelpText('after', LIST_HELP)
67
+ .action(async (options, command) => {
68
+ const globals = command.optsWithGlobals();
69
+ emitEnvelope(await runThemesList({ ...options, quiet: globals.quiet }), globals);
70
+ });
71
+ withAuthFlags(cmd.command('get'))
72
+ // --id via .option (not .requiredOption) so a missing id flows through the
73
+ // in-run guard in runThemesGet and returns a VALIDATION envelope (the agent
74
+ // contract: envelope + exit code on stdout), rather than commander's plain
75
+ // parse error + exit 1.
76
+ .option('--id <id>', 'Theme ID')
77
+ .action(async (options, command) => {
78
+ const globals = command.optsWithGlobals();
79
+ emitEnvelope(await runThemesGet({ ...options, quiet: globals.quiet }), globals);
80
+ });
81
+ return cmd;
82
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pitcher/cli-scripts",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "The Pitcher CLI for various tasks in its ecosystem.",
5
5
  "author": "Pitcher AG",
6
6
  "license": "MIT",