@formo/cli 1.0.0 → 1.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 CHANGED
@@ -26,6 +26,13 @@ export FORMO_API_KEY=formo_abc123
26
26
 
27
27
  Get your API key from `Settings → API Keys` in the [Formo dashboard](https://app.formo.so).
28
28
 
29
+ For local development or proxying, override API hosts with:
30
+
31
+ ```bash
32
+ export FORMO_API_BASE_URL=http://localhost:3001
33
+ export FORMO_EVENTS_BASE_URL=http://localhost:3002
34
+ ```
35
+
29
36
  ---
30
37
 
31
38
  ## Auth commands
@@ -114,6 +121,15 @@ formo profiles update vitalik.eth --properties '{"email":"alice@example.com"}'
114
121
 
115
122
  > Requires `profiles:write` scope.
116
123
 
124
+ ### `profiles properties batch`
125
+
126
+ Batch update first-party properties for up to 100 wallets.
127
+
128
+ ```bash
129
+ formo profiles properties batch \
130
+ --rows '[{"address":"0xd8dA...","display_name":"alice.eth","email":"alice@example.com"}]'
131
+ ```
132
+
117
133
  ### `profiles labels create <address>`
118
134
 
119
135
  Upsert one or more labels on a wallet profile. Provide either a single label via `--tag-id` or a batch via `--labels`.
@@ -123,12 +139,16 @@ Upsert one or more labels on a wallet profile. Provide either a single label via
123
139
  | `--tag-id` | Label identifier (e.g. `vip`, `airdrop_eligible`) |
124
140
  | `--value` | Optional label value (e.g. tier name, country code) |
125
141
  | `--chain-id` | Optional chain identifier the label applies to |
142
+ | `--timestamp` | Optional historical ISO-8601 timestamp |
143
+ | `--is-deleted` | Backfill a historical label removal tombstone |
126
144
  | `--labels` | JSON array of `UserLabelInput` objects for batch upsert |
127
145
 
128
146
  ```bash
129
147
  formo profiles labels create 0xd8dA... --tag-id vip
130
148
  formo profiles labels create 0xd8dA... --tag-id tier --value gold --chain-id 1
131
149
  formo profiles labels create 0xd8dA... --labels '[{"tag_id":"vip"},{"tag_id":"airdrop_eligible","chain_id":"1"}]'
150
+ formo profiles labels create 0xd8dA... --tag-id tier --timestamp 2024-03-15T00:00:00.000Z --is-deleted
151
+ formo profiles labels batch --labels '[{"address":"0xd8dA...","tag_id":"vip","value":"tier-1"}]'
132
152
  ```
133
153
 
134
154
  ### `profiles labels delete <address>`
@@ -164,7 +184,7 @@ Get a single alert by ID.
164
184
  | Option | Description |
165
185
  |---|---|
166
186
  | `--name` | Alert name |
167
- | `--trigger-type` | Trigger type (e.g. `event`, `threshold`) |
187
+ | `--trigger-type` | Trigger type: `event` or `user` |
168
188
  | `--trigger-filters` | JSON array of trigger filter objects |
169
189
  | `--recipient` | JSON array of recipient objects |
170
190
  | `--secret` | Webhook secret |
@@ -181,11 +201,18 @@ Same options as `create`. Replaces the alert configuration.
181
201
  ### `alerts delete <alertId>`
182
202
  Delete an alert.
183
203
 
184
- ### `alerts toggle <alertId> --status <active|paused>`
185
- Toggle an alert between `active` and `paused`.
204
+ ### `alerts toggle <alertId> --status <active|inactive>`
205
+ Toggle an alert between `active` and `inactive`.
206
+
207
+ ```bash
208
+ formo alerts toggle alert_abc123 --status inactive
209
+ ```
210
+
211
+ ### `alerts test <alertId>`
212
+ Send a test alert delivery with optional sample payloads.
186
213
 
187
214
  ```bash
188
- formo alerts toggle alert_abc123 --status paused
215
+ formo alerts test alert_abc123 --sample-event '{"event":"transaction","revenue":250}'
189
216
  ```
190
217
 
191
218
  ---
@@ -204,19 +231,21 @@ Get a single board by ID.
204
231
 
205
232
  | Option | Description |
206
233
  |---|---|
207
- | `--name` | Board name |
234
+ | `--title` | Board title |
208
235
  | `--description` | Optional board description |
236
+ | `--is-public` | Make the board publicly viewable |
209
237
 
210
238
  ```bash
211
- formo boards create --name "Revenue Metrics" --description "Weekly revenue tracking"
239
+ formo boards create --title "Revenue Metrics" --description "Weekly revenue tracking"
212
240
  ```
213
241
 
214
242
  ### `boards update <boardId>`
215
243
 
216
244
  | Option | Description |
217
245
  |---|---|
218
- | `--name` | New board name |
246
+ | `--title` | New board title |
219
247
  | `--description` | New board description |
248
+ | `--is-public` | Update public visibility |
220
249
 
221
250
  ### `boards delete <boardId>`
222
251
  Delete a board.
@@ -233,12 +262,30 @@ List all charts in a board.
233
262
  ### `charts get <chartId> --board-id <boardId>`
234
263
  Get a single chart by ID.
235
264
 
236
- ### `charts create --board-id <boardId> --body '<json>'`
237
- Create a chart from a JSON config string.
265
+ ### `charts meta --board-id <boardId>`
266
+ List lightweight chart metadata without executing chart queries.
267
+
268
+ ### `charts create --board-id <boardId> [options]`
269
+ Create a chart from typed flags or a raw JSON body.
270
+
271
+ ```bash
272
+ formo charts create --board-id brd_123 --title "Daily Active Users" \
273
+ --chart-type line \
274
+ --query "SELECT toDate(timestamp) AS date, countDistinct(address) AS users FROM events GROUP BY date ORDER BY date" \
275
+ --x-axis date --y-axis users
276
+
277
+ formo charts create --board-id brd_123 --body '{"title":"Recent Events","chart_type":"table","query":"SELECT * FROM events LIMIT 10"}'
278
+ ```
238
279
 
239
280
  ### `charts update <chartId> --board-id <boardId> --body '<json>'`
240
281
  Update a chart.
241
282
 
283
+ ### `charts query <chartId> --board-id <boardId> --date-from <YYYY-MM-DD> --date-to <YYYY-MM-DD>`
284
+ Execute a saved chart that uses `{{date_from}}` / `{{date_to}}` variables.
285
+
286
+ ### `charts move|duplicate|reorder`
287
+ Move a chart to another board, duplicate a chart, or reorder charts in a board.
288
+
242
289
  ### `charts delete <chartId> --board-id <boardId>`
243
290
  Delete a chart.
244
291
 
@@ -251,6 +298,12 @@ Smart contract commands. Requires `contracts:read` / `contracts:write`.
251
298
  ### `contracts list`
252
299
  List all tracked contracts. Returns `{ data: Contract[], deploy: { last_deployed_at, diff }, total, page, size, has_more }`.
253
300
 
301
+ ### `contracts get <chain> <address>`
302
+ Get a single tracked contract.
303
+
304
+ ### `contracts recommendations`
305
+ List contracts the project already interacts with but has not added yet.
306
+
254
307
  ### `contracts create`
255
308
 
256
309
  | Option | Description |
@@ -258,13 +311,15 @@ List all tracked contracts. Returns `{ data: Contract[], deploy: { last_deployed
258
311
  | `--address` | Contract address (`0x…`) |
259
312
  | `--chain` | Chain ID (e.g. `1`, `137`) |
260
313
  | `--name` | Human-readable contract name |
261
- | `--abi` | Contract ABI as a JSON string |
262
- | `--events` | Events configuration as a JSON string |
314
+ | `--abi` | Contract ABI as a JSON string; sent stringified to the API |
315
+ | `--events` | JSON array of ABI event objects to monitor |
316
+ | `--start-block` | Optional start block |
317
+ | `--include-in-pipeline` | Include this contract in the Goldsky events pipeline (`true` by default in the API) |
263
318
 
264
319
  ```bash
265
320
  formo contracts create --address 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 --chain 1 \
266
321
  --name "UNI Token" --abi '[{"type":"event","name":"Transfer","inputs":[]}]' \
267
- --events '{"Transfer":true}'
322
+ --events '[{"type":"event","name":"Transfer","inputs":[]}]'
268
323
  ```
269
324
 
270
325
  ### `contracts update <chain> <address>`
@@ -273,7 +328,12 @@ formo contracts create --address 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 --ch
273
328
  |---|---|
274
329
  | `--name` | Updated contract name |
275
330
  | `--abi` | Updated ABI |
276
- | `--events` | Updated events config |
331
+ | `--events` | Updated JSON array of ABI event objects |
332
+ | `--start-block` | Optional start block |
333
+ | `--include-in-pipeline` | Include or exclude this contract from the Goldsky events pipeline |
334
+
335
+ ### `contracts pipeline <chain> <address> --include-in-pipeline <true|false>`
336
+ Toggle pipeline inclusion without re-sending the full ABI/events payload.
277
337
 
278
338
  ### `contracts delete <chain> <address>`
279
339
  Remove a tracked contract.
@@ -348,10 +408,24 @@ Bulk-import wallet addresses into the project via the events API.
348
408
  | Option | Description |
349
409
  |---|---|
350
410
  | `--addresses` | JSON array of wallet address strings |
351
- | `--write-key` | Project write SDK key |
411
+ | `--rows` | JSON array of `{address,properties?}` objects |
412
+
413
+ ```bash
414
+ formo import wallets --addresses '["0xabc...","0xdef..."]'
415
+ formo import wallets --rows '[{"address":"0xabc...","properties":{"display_name":"Alice"}}]'
416
+ ```
417
+
418
+ ---
419
+
420
+ ## `formo events`
421
+
422
+ ### `events ingest`
423
+
424
+ Send raw analytics events to `events.formo.so`. This command uses a project SDK write key, not the workspace API key.
352
425
 
353
426
  ```bash
354
- formo import wallets --addresses '["0xabc...","0xdef..."]' --write-key write_key_xyz
427
+ export FORMO_WRITE_KEY=formo_write_key_xxx
428
+ formo events ingest --event '{"type":"track","channel":"cli","version":"1","anonymous_id":"anon_123","event":"CLI Test","context":{},"properties":{},"original_timestamp":"2026-04-27T23:05:38.000Z","sent_at":"2026-04-27T23:05:42.000Z","message_id":"cli-test-1"}'
355
429
  ```
356
430
 
357
431
  ---
@@ -1,23 +1,36 @@
1
1
  import { Cli } from 'incur';
2
2
  export declare const alerts: Cli.Cli<{}, undefined, undefined>;
3
- export declare function listAlertsRun(): Promise<import("axios").AxiosResponse<any, any, {}>>;
3
+ export interface PaginationOptions {
4
+ page?: number;
5
+ size?: number;
6
+ }
7
+ export declare function listAlertsRun(options?: PaginationOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
4
8
  export declare function getAlertRun(alertId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
5
9
  export interface CreateAlertOptions {
6
10
  name: string;
7
- triggerType: string;
11
+ triggerType: 'event' | 'user' | string;
8
12
  triggerFilters?: string;
9
13
  recipient?: string;
10
14
  secret?: string;
15
+ slackPropertyKeys?: string;
11
16
  }
12
17
  export declare function buildAlertBody(options: CreateAlertOptions | UpdateAlertOptions): Record<string, unknown>;
13
18
  export declare function createAlertRun(options: CreateAlertOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
14
19
  export interface UpdateAlertOptions {
15
20
  name: string;
16
- triggerType: string;
21
+ triggerType: 'event' | 'user' | string;
17
22
  triggerFilters?: string;
18
23
  recipient?: string;
19
24
  secret?: string;
25
+ slackPropertyKeys?: string;
20
26
  }
21
27
  export declare function updateAlertRun(alertId: string, options: UpdateAlertOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
22
28
  export declare function deleteAlertRun(alertId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
23
29
  export declare function toggleAlertRun(alertId: string, status: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
30
+ export interface TestAlertOptions {
31
+ sampleEvent?: string;
32
+ sampleUser?: string;
33
+ recipientOverrides?: string;
34
+ }
35
+ export declare function buildTestAlertBody(options: TestAlertOptions): Record<string, unknown> | undefined;
36
+ export declare function testAlertRun(alertId: string, options?: TestAlertOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
@@ -8,23 +8,37 @@ exports.createAlertRun = createAlertRun;
8
8
  exports.updateAlertRun = updateAlertRun;
9
9
  exports.deleteAlertRun = deleteAlertRun;
10
10
  exports.toggleAlertRun = toggleAlertRun;
11
+ exports.buildTestAlertBody = buildTestAlertBody;
12
+ exports.testAlertRun = testAlertRun;
11
13
  const incur_1 = require("incur");
12
14
  const client_1 = require("../lib/client");
15
+ const json_1 = require("../lib/json");
13
16
  exports.alerts = incur_1.Cli.create('alerts', {
14
17
  description: 'Project alert commands — create, list, update, and delete alerts',
15
18
  });
16
- // ── List alerts ──
17
- function listAlertsRun() {
19
+ function buildPaginationParams(options = {}) {
20
+ const params = {};
21
+ if (options.page !== undefined)
22
+ params.page = options.page;
23
+ if (options.size !== undefined)
24
+ params.size = options.size;
25
+ return params;
26
+ }
27
+ function listAlertsRun(options = {}) {
18
28
  (0, client_1.requireApiKey)();
19
29
  const client = (0, client_1.createClient)();
20
- return client.get('/v0/alerts/');
30
+ return client.get('/v0/alerts/', { params: buildPaginationParams(options) });
21
31
  }
22
32
  exports.alerts.command('list', {
23
33
  description: 'List all alerts for the project',
34
+ options: incur_1.z.object({
35
+ page: incur_1.z.coerce.number().optional().describe('Page number (1-indexed, default 1)'),
36
+ size: incur_1.z.coerce.number().optional().describe('Page size (default 100, max 200)'),
37
+ }),
24
38
  examples: [{ description: 'List all project alerts' }],
25
39
  hint: 'Requires alerts:read scope on your API key.',
26
- run() {
27
- return listAlertsRun();
40
+ run({ options }) {
41
+ return listAlertsRun(options);
28
42
  },
29
43
  });
30
44
  // ── Get a single alert ──
@@ -50,26 +64,20 @@ function buildAlertBody(options) {
50
64
  const body = {
51
65
  name: options.name,
52
66
  trigger_type: options.triggerType,
67
+ trigger_filters: [],
53
68
  };
54
69
  if (options.triggerFilters) {
55
- try {
56
- body.trigger_filters = JSON.parse(options.triggerFilters);
57
- }
58
- catch {
59
- throw new Error('--trigger-filters must be a valid JSON array');
60
- }
70
+ body.trigger_filters = (0, json_1.parseJsonArray)(options.triggerFilters, '--trigger-filters');
61
71
  }
62
72
  if (options.recipient) {
63
- try {
64
- body.recipient = JSON.parse(options.recipient);
65
- }
66
- catch {
67
- throw new Error('--recipient must be a valid JSON array');
68
- }
73
+ body.recipient = (0, json_1.parseJsonArray)(options.recipient, '--recipient');
69
74
  }
70
75
  if (options.secret !== undefined) {
71
76
  body.secret = options.secret;
72
77
  }
78
+ if (options.slackPropertyKeys !== undefined) {
79
+ body.slack_property_keys = (0, json_1.parseJsonArray)(options.slackPropertyKeys, '--slack-property-keys');
80
+ }
73
81
  return body;
74
82
  }
75
83
  function createAlertRun(options) {
@@ -81,7 +89,7 @@ exports.alerts.command('create', {
81
89
  description: 'Create a new project alert',
82
90
  options: incur_1.z.object({
83
91
  name: incur_1.z.string().describe('Alert name'),
84
- triggerType: incur_1.z.string().describe('Trigger type (e.g. "event", "threshold")'),
92
+ triggerType: incur_1.z.enum(['event', 'user']).describe('Trigger type'),
85
93
  triggerFilters: incur_1.z
86
94
  .string()
87
95
  .optional()
@@ -91,6 +99,10 @@ exports.alerts.command('create', {
91
99
  .optional()
92
100
  .describe('JSON array of recipient objects'),
93
101
  secret: incur_1.z.string().optional().describe('Webhook secret for the alert'),
102
+ slackPropertyKeys: incur_1.z
103
+ .string()
104
+ .optional()
105
+ .describe('JSON array of event/user property keys to include in Slack alerts'),
94
106
  }),
95
107
  examples: [
96
108
  {
@@ -115,7 +127,7 @@ exports.alerts.command('update', {
115
127
  }),
116
128
  options: incur_1.z.object({
117
129
  name: incur_1.z.string().describe('Alert name'),
118
- triggerType: incur_1.z.string().describe('Trigger type'),
130
+ triggerType: incur_1.z.enum(['event', 'user']).describe('Trigger type'),
119
131
  triggerFilters: incur_1.z
120
132
  .string()
121
133
  .optional()
@@ -125,6 +137,10 @@ exports.alerts.command('update', {
125
137
  .optional()
126
138
  .describe('JSON array of recipient objects'),
127
139
  secret: incur_1.z.string().optional().describe('Webhook secret for the alert'),
140
+ slackPropertyKeys: incur_1.z
141
+ .string()
142
+ .optional()
143
+ .describe('JSON array of event/user property keys to include in Slack alerts'),
128
144
  }),
129
145
  examples: [
130
146
  {
@@ -161,21 +177,24 @@ exports.alerts.command('delete', {
161
177
  function toggleAlertRun(alertId, status) {
162
178
  (0, client_1.requireApiKey)();
163
179
  const client = (0, client_1.createClient)();
164
- return client.patch(`/v0/alerts/${encodeURIComponent(alertId)}`, { status });
180
+ const normalizedStatus = status === 'paused' ? 'inactive' : status;
181
+ return client.patch(`/v0/alerts/${encodeURIComponent(alertId)}`, {
182
+ status: normalizedStatus,
183
+ });
165
184
  }
166
185
  exports.alerts.command('toggle', {
167
- description: 'Toggle an alert status (active/paused)',
186
+ description: 'Toggle an alert status (active/inactive)',
168
187
  args: incur_1.z.object({
169
188
  alertId: incur_1.z.string().describe('Alert ID to toggle'),
170
189
  }),
171
190
  options: incur_1.z.object({
172
- status: incur_1.z.enum(['active', 'paused']).describe('New status'),
191
+ status: incur_1.z.enum(['active', 'inactive', 'paused']).describe('New status. "paused" is accepted as a deprecated alias for "inactive".'),
173
192
  }),
174
193
  examples: [
175
194
  {
176
195
  args: { alertId: 'alert_abc123' },
177
- options: { status: 'paused' },
178
- description: 'Pause an alert',
196
+ options: { status: 'inactive' },
197
+ description: 'Deactivate an alert',
179
198
  },
180
199
  ],
181
200
  hint: 'Requires alerts:write scope on your API key.',
@@ -183,3 +202,54 @@ exports.alerts.command('toggle', {
183
202
  return toggleAlertRun(args.alertId, options.status);
184
203
  },
185
204
  });
205
+ function buildTestAlertBody(options) {
206
+ const body = {};
207
+ if (options.sampleEvent !== undefined) {
208
+ body.sampleEvent = (0, json_1.parseJsonObject)(options.sampleEvent, '--sample-event');
209
+ }
210
+ if (options.sampleUser !== undefined) {
211
+ body.sampleUser = (0, json_1.parseJsonObject)(options.sampleUser, '--sample-user');
212
+ }
213
+ if (options.recipientOverrides !== undefined) {
214
+ body.recipientOverrides = (0, json_1.parseJsonArray)(options.recipientOverrides, '--recipient-overrides');
215
+ }
216
+ return Object.keys(body).length > 0 ? body : undefined;
217
+ }
218
+ function testAlertRun(alertId, options = {}) {
219
+ (0, client_1.requireApiKey)();
220
+ const client = (0, client_1.createClient)();
221
+ return client.post(`/v0/alerts/${encodeURIComponent(alertId)}/test`, buildTestAlertBody(options));
222
+ }
223
+ exports.alerts.command('test', {
224
+ description: 'Send a test delivery for an alert',
225
+ args: incur_1.z.object({
226
+ alertId: incur_1.z.string().describe('Alert ID to test'),
227
+ }),
228
+ options: incur_1.z.object({
229
+ sampleEvent: incur_1.z
230
+ .string()
231
+ .optional()
232
+ .describe('Optional JSON object to use as the sample event'),
233
+ sampleUser: incur_1.z
234
+ .string()
235
+ .optional()
236
+ .describe('Optional JSON object to use as the sample user/profile'),
237
+ recipientOverrides: incur_1.z
238
+ .string()
239
+ .optional()
240
+ .describe('Optional JSON array of recipient objects to test instead of saved recipients'),
241
+ }),
242
+ examples: [
243
+ {
244
+ args: { alertId: 'alert_abc123' },
245
+ options: {
246
+ sampleEvent: '{"event":"transaction","revenue":250}',
247
+ },
248
+ description: 'Send a test alert with a sample event',
249
+ },
250
+ ],
251
+ hint: 'Requires alerts:write scope on your API key.',
252
+ run({ args, options }) {
253
+ return testAlertRun(args.alertId, options);
254
+ },
255
+ });
@@ -1,15 +1,24 @@
1
1
  import { Cli } from 'incur';
2
2
  export declare const boards: Cli.Cli<{}, undefined, undefined>;
3
- export declare function listBoardsRun(): Promise<import("axios").AxiosResponse<any, any, {}>>;
3
+ export interface PaginationOptions {
4
+ page?: number;
5
+ size?: number;
6
+ }
7
+ export declare function listBoardsRun(options?: PaginationOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
4
8
  export declare function getBoardRun(boardId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
5
9
  export interface CreateBoardOptions {
6
- name: string;
10
+ title?: string;
11
+ name?: string;
7
12
  description?: string;
13
+ isPublic?: boolean;
8
14
  }
15
+ export declare function buildBoardBody(options: CreateBoardOptions | UpdateBoardOptions): Record<string, unknown>;
9
16
  export declare function createBoardRun(options: CreateBoardOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
10
17
  export interface UpdateBoardOptions {
18
+ title?: string;
11
19
  name?: string;
12
20
  description?: string;
21
+ isPublic?: boolean;
13
22
  }
14
23
  export declare function updateBoardRun(boardId: string, options: UpdateBoardOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
15
24
  export declare function deleteBoardRun(boardId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.boards = void 0;
4
4
  exports.listBoardsRun = listBoardsRun;
5
5
  exports.getBoardRun = getBoardRun;
6
+ exports.buildBoardBody = buildBoardBody;
6
7
  exports.createBoardRun = createBoardRun;
7
8
  exports.updateBoardRun = updateBoardRun;
8
9
  exports.deleteBoardRun = deleteBoardRun;
@@ -11,18 +12,30 @@ const client_1 = require("../lib/client");
11
12
  exports.boards = incur_1.Cli.create('boards', {
12
13
  description: 'Dashboard board commands — create, list, update, and delete boards',
13
14
  });
15
+ function buildPaginationParams(options = {}) {
16
+ const params = {};
17
+ if (options.page !== undefined)
18
+ params.page = options.page;
19
+ if (options.size !== undefined)
20
+ params.size = options.size;
21
+ return params;
22
+ }
14
23
  // ── List boards ──
15
- function listBoardsRun() {
24
+ function listBoardsRun(options = {}) {
16
25
  (0, client_1.requireApiKey)();
17
26
  const client = (0, client_1.createClient)();
18
- return client.get('/v0/boards/');
27
+ return client.get('/v0/boards/', { params: buildPaginationParams(options) });
19
28
  }
20
29
  exports.boards.command('list', {
21
30
  description: 'List all boards for the project',
31
+ options: incur_1.z.object({
32
+ page: incur_1.z.coerce.number().optional().describe('Page number (1-indexed, default 1)'),
33
+ size: incur_1.z.coerce.number().optional().describe('Page size (default 100, max 200)'),
34
+ }),
22
35
  examples: [{ description: 'List all dashboard boards' }],
23
36
  hint: 'Requires boards:read scope on your API key.',
24
- run() {
25
- return listBoardsRun();
37
+ run({ options }) {
38
+ return listBoardsRun(options);
26
39
  },
27
40
  });
28
41
  // ── Get a single board ──
@@ -44,28 +57,46 @@ exports.boards.command('get', {
44
57
  return getBoardRun(args.boardId);
45
58
  },
46
59
  });
60
+ function buildBoardBody(options) {
61
+ const title = options.title ?? options.name;
62
+ const body = {};
63
+ if (title !== undefined) {
64
+ if (!title)
65
+ throw new Error('--title must not be empty');
66
+ body.title = title;
67
+ }
68
+ if (options.description !== undefined) {
69
+ body.description = options.description;
70
+ }
71
+ if (options.isPublic !== undefined) {
72
+ body.isPublic = options.isPublic;
73
+ }
74
+ return body;
75
+ }
47
76
  function createBoardRun(options) {
48
77
  (0, client_1.requireApiKey)();
49
78
  const client = (0, client_1.createClient)();
50
- const body = { name: options.name };
51
- if (options.description) {
52
- body.description = options.description;
79
+ const body = buildBoardBody(options);
80
+ if (!body.title) {
81
+ throw new Error('Provide --title for the board name');
53
82
  }
54
83
  return client.post('/v0/boards/', body);
55
84
  }
56
85
  exports.boards.command('create', {
57
86
  description: 'Create a new dashboard board',
58
87
  options: incur_1.z.object({
59
- name: incur_1.z.string().describe('Board name'),
88
+ title: incur_1.z.string().optional().describe('Board title'),
89
+ name: incur_1.z.string().optional().describe('Deprecated alias for --title').meta({ deprecated: true }),
60
90
  description: incur_1.z.string().optional().describe('Board description'),
91
+ isPublic: incur_1.z.boolean().optional().describe('Whether the board is publicly viewable'),
61
92
  }),
62
93
  examples: [
63
94
  {
64
- options: { name: 'KPI Dashboard' },
95
+ options: { title: 'KPI Dashboard' },
65
96
  description: 'Create a board',
66
97
  },
67
98
  {
68
- options: { name: 'Revenue Metrics', description: 'Weekly revenue tracking' },
99
+ options: { title: 'Revenue Metrics', description: 'Weekly revenue tracking' },
69
100
  description: 'Create a board with description',
70
101
  },
71
102
  ],
@@ -77,11 +108,10 @@ exports.boards.command('create', {
77
108
  function updateBoardRun(boardId, options) {
78
109
  (0, client_1.requireApiKey)();
79
110
  const client = (0, client_1.createClient)();
80
- const body = {};
81
- if (options.name !== undefined)
82
- body.name = options.name;
83
- if (options.description !== undefined)
84
- body.description = options.description;
111
+ const body = buildBoardBody(options);
112
+ if (Object.keys(body).length === 0) {
113
+ throw new Error('Provide at least one of --title, --description, or --is-public');
114
+ }
85
115
  return client.patch(`/v0/boards/${encodeURIComponent(boardId)}`, body);
86
116
  }
87
117
  exports.boards.command('update', {
@@ -90,13 +120,15 @@ exports.boards.command('update', {
90
120
  boardId: incur_1.z.string().describe('Board ID to update'),
91
121
  }),
92
122
  options: incur_1.z.object({
93
- name: incur_1.z.string().optional().describe('New board name'),
123
+ title: incur_1.z.string().optional().describe('New board title'),
124
+ name: incur_1.z.string().optional().describe('Deprecated alias for --title').meta({ deprecated: true }),
94
125
  description: incur_1.z.string().optional().describe('New board description'),
126
+ isPublic: incur_1.z.boolean().optional().describe('Whether the board is publicly viewable'),
95
127
  }),
96
128
  examples: [
97
129
  {
98
130
  args: { boardId: 'board_abc123' },
99
- options: { name: 'Renamed Board' },
131
+ options: { title: 'Renamed Board' },
100
132
  description: 'Rename a board',
101
133
  },
102
134
  ],
@@ -1,7 +1,34 @@
1
1
  import { Cli } from 'incur';
2
2
  export declare const charts: Cli.Cli<{}, undefined, undefined>;
3
- export declare function listChartsRun(boardId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
3
+ export interface PaginationOptions {
4
+ page?: number;
5
+ size?: number;
6
+ }
7
+ export interface ChartBodyOptions {
8
+ body?: string;
9
+ query?: string;
10
+ chartType?: string;
11
+ title?: string;
12
+ description?: string;
13
+ xAxis?: string;
14
+ yAxis?: string;
15
+ groupBy?: string;
16
+ steps?: string;
17
+ settings?: string;
18
+ }
19
+ export declare function buildChartBody(options: ChartBodyOptions): Record<string, unknown>;
20
+ export declare function listChartsRun(boardId: string, options?: PaginationOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
21
+ export declare function listChartSummariesRun(boardId: string, options?: PaginationOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
4
22
  export declare function getChartRun(boardId: string, chartId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
5
- export declare function createChartRun(boardId: string, body: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
6
- export declare function updateChartRun(boardId: string, chartId: string, body: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
23
+ export interface QueryChartOptions {
24
+ dateFrom: string;
25
+ dateTo: string;
26
+ }
27
+ export declare function queryChartRun(boardId: string, chartId: string, options: QueryChartOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
28
+ export declare function createChartRun(boardId: string, input: string | ChartBodyOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
29
+ export declare function updateChartRun(boardId: string, chartId: string, input: string | ChartBodyOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
30
+ export declare function moveChartRun(boardId: string, chartId: string, targetBoardId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
31
+ export declare function normalizeDuplicateChartResponse(result: unknown): unknown;
32
+ export declare function duplicateChartRun(boardId: string, chartId: string): Promise<unknown>;
33
+ export declare function reorderChartsRun(boardId: string, chartIds: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
7
34
  export declare function deleteChartRun(boardId: string, chartId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;