@burdenoff/bigconsole-cli 2026.1029.1 → 2026.1110.1
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 +96 -212
- package/dist/auth/store.d.ts +0 -4
- package/dist/cli.js +2959 -103
- package/dist/commands/base.d.ts +0 -4
- package/dist/graphql/operations.d.ts +1 -1
- package/dist/index.js +2895 -6
- package/dist/utils/parse.d.ts +5 -0
- package/package.json +42 -41
- package/dist/auth/device-code.js +0 -244
- package/dist/auth/store.js +0 -90
- package/dist/commands/auth.js +0 -353
- package/dist/commands/base.js +0 -120
- package/dist/commands/cli-config.js +0 -79
- package/dist/commands/dashboard.js +0 -223
- package/dist/commands/datasink.js +0 -175
- package/dist/commands/drilldown.js +0 -55
- package/dist/commands/index.js +0 -13
- package/dist/commands/parser.js +0 -181
- package/dist/commands/pipeline.js +0 -142
- package/dist/commands/prompt.js +0 -84
- package/dist/commands/share.js +0 -50
- package/dist/commands/template.js +0 -62
- package/dist/commands/widget.js +0 -164
- package/dist/commands/workflow.js +0 -54
- package/dist/commands/workspace.js +0 -95
- package/dist/config/index.js +0 -151
- package/dist/graphql/client.js +0 -254
- package/dist/graphql/operations.js +0 -680
- package/dist/types/index.d.ts +0 -30
- package/dist/types/index.js +0 -7
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.js +0 -2
- package/dist/utils/output.js +0 -237
- package/dist/utils/sanitize.js +0 -347
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dashboard commands — list, get, archive, delete.
|
|
3
|
-
*/
|
|
4
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
5
|
-
import * as ops from '../graphql/operations.js';
|
|
6
|
-
import { execWorkspace, formatAndOutput, handleCommandError, loadJsonInput } from './base.js';
|
|
7
|
-
import { printSuccess, printError, formatDate, formatStatus, truncate } from '../utils/output.js';
|
|
8
|
-
import { sanitizeForTerminal } from '../utils/sanitize.js';
|
|
9
|
-
export function registerDashboardCommands(program) {
|
|
10
|
-
const dash = program.command('dashboard').description('Dashboard operations');
|
|
11
|
-
dash
|
|
12
|
-
.command('list')
|
|
13
|
-
.description('List dashboards in the current workspace')
|
|
14
|
-
.option('--search <term>', 'Search by name')
|
|
15
|
-
.option('--category <c>', 'Filter by category')
|
|
16
|
-
.option('--visibility <v>', 'PRIVATE | WORKSPACE | PUBLIC')
|
|
17
|
-
.option('--include-archived', 'Include archived dashboards')
|
|
18
|
-
.option('--first <n>', 'Page size', (v) => parseInt(v, 10), 25)
|
|
19
|
-
.option('--after <cursor>', 'Cursor for next page')
|
|
20
|
-
.option('-f, --format <format>', 'Output format')
|
|
21
|
-
.action(async (o) => {
|
|
22
|
-
try {
|
|
23
|
-
const d = await execWorkspace(ops.LIST_DASHBOARDS, {
|
|
24
|
-
first: o.first ?? 25,
|
|
25
|
-
after: o.after,
|
|
26
|
-
search: o.search,
|
|
27
|
-
category: o.category ? o.category.toUpperCase() : undefined,
|
|
28
|
-
visibility: o.visibility ? o.visibility.toUpperCase() : undefined,
|
|
29
|
-
includeArchived: o.includeArchived ?? false,
|
|
30
|
-
});
|
|
31
|
-
const items = d.listDashboards.edges.map((e) => e.node);
|
|
32
|
-
formatAndOutput(o, items, {
|
|
33
|
-
headers: ['ID', 'Name', 'Status', 'Visibility', 'Category', 'Updated'],
|
|
34
|
-
rows: items.map((x) => [
|
|
35
|
-
truncate(x.id, 14),
|
|
36
|
-
truncate(x.name, 30),
|
|
37
|
-
formatStatus(x.status),
|
|
38
|
-
x.visibility,
|
|
39
|
-
x.category,
|
|
40
|
-
formatDate(x.updatedAt),
|
|
41
|
-
]),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
catch (e) {
|
|
45
|
-
handleCommandError(e);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
dash
|
|
49
|
-
.command('get')
|
|
50
|
-
.description('Get a dashboard by ID')
|
|
51
|
-
.argument('<id>')
|
|
52
|
-
.option('-f, --format <format>', 'Output format')
|
|
53
|
-
.action(async (id, o) => {
|
|
54
|
-
try {
|
|
55
|
-
const d = await execWorkspace(ops.GET_DASHBOARD, {
|
|
56
|
-
id,
|
|
57
|
-
});
|
|
58
|
-
if (!d.getDashboard) {
|
|
59
|
-
printError('Dashboard not found');
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
formatAndOutput(o, d.getDashboard);
|
|
63
|
-
}
|
|
64
|
-
catch (e) {
|
|
65
|
-
handleCommandError(e);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
dash
|
|
69
|
-
.command('archive')
|
|
70
|
-
.description('Archive a dashboard (soft-delete, can be restored)')
|
|
71
|
-
.argument('<id>')
|
|
72
|
-
.action(async (id) => {
|
|
73
|
-
try {
|
|
74
|
-
const d = await execWorkspace(ops.ARCHIVE_DASHBOARD, {
|
|
75
|
-
id,
|
|
76
|
-
});
|
|
77
|
-
printSuccess(`Archived: ${d.archiveDashboard.name} (${d.archiveDashboard.id})`);
|
|
78
|
-
}
|
|
79
|
-
catch (e) {
|
|
80
|
-
handleCommandError(e);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
dash
|
|
84
|
-
.command('delete')
|
|
85
|
-
.description('Permanently delete a dashboard')
|
|
86
|
-
.argument('<id>')
|
|
87
|
-
.action(async (id) => {
|
|
88
|
-
try {
|
|
89
|
-
await execWorkspace(ops.DELETE_DASHBOARD, { id });
|
|
90
|
-
printSuccess(`Deleted dashboard ${id}`);
|
|
91
|
-
}
|
|
92
|
-
catch (e) {
|
|
93
|
-
handleCommandError(e);
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
dash
|
|
97
|
-
.command('create')
|
|
98
|
-
.description('Create a dashboard')
|
|
99
|
-
.requiredOption('--name <name>', 'Dashboard name')
|
|
100
|
-
.requiredOption('--category <cat>', 'Category (e.g. ANALYTICS, OPERATIONS)')
|
|
101
|
-
.option('--description <d>', 'Description')
|
|
102
|
-
.option('--visibility <v>', 'PRIVATE | WORKSPACE | PUBLIC', 'PRIVATE')
|
|
103
|
-
.option('--layout <l>', 'GRID | FREEFORM', 'GRID')
|
|
104
|
-
.option('--no-default-page', 'Skip creating the default page')
|
|
105
|
-
.option('--metadata-file <path>', 'JSON file with custom metadata')
|
|
106
|
-
.option('--metadata-json <json>', 'Inline JSON for custom metadata')
|
|
107
|
-
.option('-f, --format <format>', 'Output format')
|
|
108
|
-
.action(async (o) => {
|
|
109
|
-
try {
|
|
110
|
-
const metadata = loadJsonInput(o.metadataFile, o.metadataJson);
|
|
111
|
-
const input = {
|
|
112
|
-
name: o.name,
|
|
113
|
-
category: o.category.toUpperCase(),
|
|
114
|
-
description: o.description,
|
|
115
|
-
visibility: (o.visibility ?? 'PRIVATE').toUpperCase(),
|
|
116
|
-
layout: (o.layout ?? 'GRID').toUpperCase(),
|
|
117
|
-
createDefaultPage: o.defaultPage !== false,
|
|
118
|
-
metadata,
|
|
119
|
-
};
|
|
120
|
-
const d = await execWorkspace(ops.CREATE_DASHBOARD, { input });
|
|
121
|
-
printSuccess(`Created dashboard: ${d.createBigConsoleDashboard.name} (${d.createBigConsoleDashboard.id})`);
|
|
122
|
-
formatAndOutput(o, d.createBigConsoleDashboard);
|
|
123
|
-
}
|
|
124
|
-
catch (e) {
|
|
125
|
-
handleCommandError(e);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
dash
|
|
129
|
-
.command('update')
|
|
130
|
-
.description('Update a dashboard')
|
|
131
|
-
.argument('<id>')
|
|
132
|
-
.option('--name <name>')
|
|
133
|
-
.option('--description <d>')
|
|
134
|
-
.option('--category <cat>')
|
|
135
|
-
.option('--visibility <v>', 'PRIVATE | WORKSPACE | PUBLIC')
|
|
136
|
-
.option('--layout <l>', 'GRID | FREEFORM')
|
|
137
|
-
.option('-f, --format <format>', 'Output format')
|
|
138
|
-
.action(async (id, o) => {
|
|
139
|
-
try {
|
|
140
|
-
const input = { id };
|
|
141
|
-
if (o.name)
|
|
142
|
-
input.name = o.name;
|
|
143
|
-
if (o.description !== undefined)
|
|
144
|
-
input.description = o.description;
|
|
145
|
-
if (o.category)
|
|
146
|
-
input.category = o.category.toUpperCase();
|
|
147
|
-
if (o.visibility)
|
|
148
|
-
input.visibility = o.visibility.toUpperCase();
|
|
149
|
-
if (o.layout)
|
|
150
|
-
input.layout = o.layout.toUpperCase();
|
|
151
|
-
const d = await execWorkspace(ops.UPDATE_DASHBOARD, { input });
|
|
152
|
-
printSuccess(`Updated dashboard ${id}`);
|
|
153
|
-
formatAndOutput(o, d.updateBigConsoleDashboard);
|
|
154
|
-
}
|
|
155
|
-
catch (e) {
|
|
156
|
-
handleCommandError(e);
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
dash
|
|
160
|
-
.command('import')
|
|
161
|
-
.description('Import a dashboard from a JSON file (dashboard definition)')
|
|
162
|
-
.requiredOption('--file <path>', 'Dashboard JSON file produced by `dashboard export`')
|
|
163
|
-
.option('--name <name>', 'Override dashboard name')
|
|
164
|
-
.option('--visibility <v>', 'Override visibility: PRIVATE | WORKSPACE | PUBLIC')
|
|
165
|
-
.option('--conflict <strategy>', 'Conflict resolution: RENAME | REPLACE | FAIL', 'RENAME')
|
|
166
|
-
.action(async (o) => {
|
|
167
|
-
try {
|
|
168
|
-
const json = readFileSync(o.file, 'utf8');
|
|
169
|
-
const input = {
|
|
170
|
-
json,
|
|
171
|
-
conflictResolution: (o.conflict ?? 'RENAME').toUpperCase(),
|
|
172
|
-
};
|
|
173
|
-
if (o.name)
|
|
174
|
-
input.name = o.name;
|
|
175
|
-
if (o.visibility)
|
|
176
|
-
input.visibility = o.visibility.toUpperCase();
|
|
177
|
-
const d = await execWorkspace(ops.IMPORT_DASHBOARD, {
|
|
178
|
-
input,
|
|
179
|
-
});
|
|
180
|
-
printSuccess(`Imported dashboard: ${d.importDashboard.name} (${d.importDashboard.id})`);
|
|
181
|
-
}
|
|
182
|
-
catch (e) {
|
|
183
|
-
handleCommandError(e);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
dash
|
|
187
|
-
.command('export')
|
|
188
|
-
.description('Export a dashboard definition as JSON (stdout or --out file)')
|
|
189
|
-
.argument('<id>')
|
|
190
|
-
.option('--out <path>', 'Write JSON to file instead of stdout')
|
|
191
|
-
.option('--include-data-refs', 'Include data source references', true)
|
|
192
|
-
.option('--include-webhook-mappings', 'Include webhook mappings')
|
|
193
|
-
.option('--pretty', 'Pretty-print JSON', true)
|
|
194
|
-
.action(async (id, o) => {
|
|
195
|
-
try {
|
|
196
|
-
const options = {
|
|
197
|
-
includeDataSourceRefs: o.includeDataRefs !== false,
|
|
198
|
-
includeWebhookMappings: o.includeWebhookMappings ?? false,
|
|
199
|
-
prettyPrint: o.pretty !== false,
|
|
200
|
-
};
|
|
201
|
-
const d = await execWorkspace(ops.EXPORT_DASHBOARD, {
|
|
202
|
-
id,
|
|
203
|
-
options,
|
|
204
|
-
});
|
|
205
|
-
if (o.out) {
|
|
206
|
-
writeFileSync(o.out, d.exportDashboard, 'utf8');
|
|
207
|
-
printSuccess(`Exported to ${o.out}`);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
// Byte-exact when piped or redirected; made inert for a terminal.
|
|
211
|
-
const body = process.stdout.isTTY
|
|
212
|
-
? sanitizeForTerminal(d.exportDashboard, { preserveNewlines: true })
|
|
213
|
-
: d.exportDashboard;
|
|
214
|
-
process.stdout.write(body);
|
|
215
|
-
if (!body.endsWith('\n'))
|
|
216
|
-
process.stdout.write('\n');
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
catch (e) {
|
|
220
|
-
handleCommandError(e);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* datasink commands — list, get (by id OR key), fetch data, delete.
|
|
3
|
-
*/
|
|
4
|
-
import * as ops from '../graphql/operations.js';
|
|
5
|
-
import { execWorkspace, formatAndOutput, handleCommandError, loadJsonInput } from './base.js';
|
|
6
|
-
import { printSuccess, printError, formatDate, formatStatus, truncate } from '../utils/output.js';
|
|
7
|
-
export function registerDataSinkCommands(program) {
|
|
8
|
-
const ds = program.command('datasink').description('DataSink operations');
|
|
9
|
-
ds.command('list')
|
|
10
|
-
.description('List DataSinks in the current workspace')
|
|
11
|
-
.option('--search <term>', 'Search by name')
|
|
12
|
-
.option('--status <s>', 'Filter by status')
|
|
13
|
-
.option('--setup-state <s>', 'Filter by setup state')
|
|
14
|
-
.option('--active <bool>', 'Filter by isActive (true/false)')
|
|
15
|
-
.option('--first <n>', 'Page size', (v) => parseInt(v, 10), 25)
|
|
16
|
-
.option('--after <cursor>', 'Cursor for next page')
|
|
17
|
-
.option('-f, --format <format>', 'Output format')
|
|
18
|
-
.action(async (o) => {
|
|
19
|
-
try {
|
|
20
|
-
const d = await execWorkspace(ops.LIST_DATASINKS, {
|
|
21
|
-
first: o.first ?? 25,
|
|
22
|
-
after: o.after,
|
|
23
|
-
search: o.search,
|
|
24
|
-
status: o.status ? o.status.toUpperCase() : undefined,
|
|
25
|
-
setupState: o.setupState ? o.setupState.toUpperCase() : undefined,
|
|
26
|
-
isActive: o.active === undefined
|
|
27
|
-
? undefined
|
|
28
|
-
: o.active.toLowerCase() === 'true' || o.active === '1',
|
|
29
|
-
});
|
|
30
|
-
const items = d.listDataSinks.edges.map((e) => e.node);
|
|
31
|
-
formatAndOutput(o, items, {
|
|
32
|
-
headers: ['ID', 'Name', 'Key', 'Status', 'Setup', 'Active', 'Updated'],
|
|
33
|
-
rows: items.map((x) => [
|
|
34
|
-
truncate(x.id, 14),
|
|
35
|
-
truncate(x.name ?? '-', 24),
|
|
36
|
-
truncate(x.key, 20),
|
|
37
|
-
formatStatus(x.status),
|
|
38
|
-
x.setupState,
|
|
39
|
-
x.isActive ? 'yes' : 'no',
|
|
40
|
-
formatDate(x.updatedAt),
|
|
41
|
-
]),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
catch (e) {
|
|
45
|
-
handleCommandError(e);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
ds.command('get')
|
|
49
|
-
.description('Get a DataSink by ID or key')
|
|
50
|
-
.option('--id <id>', 'DataSink ID')
|
|
51
|
-
.option('--key <key>', 'DataSink key')
|
|
52
|
-
.option('-f, --format <format>', 'Output format')
|
|
53
|
-
.action(async (o) => {
|
|
54
|
-
try {
|
|
55
|
-
if (!o.id && !o.key) {
|
|
56
|
-
printError('Provide --id or --key');
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
const d = await execWorkspace(ops.GET_DATASINK, {
|
|
60
|
-
id: o.id,
|
|
61
|
-
key: o.key,
|
|
62
|
-
});
|
|
63
|
-
if (!d.getDataSink) {
|
|
64
|
-
printError('DataSink not found');
|
|
65
|
-
process.exit(1);
|
|
66
|
-
}
|
|
67
|
-
formatAndOutput(o, d.getDataSink);
|
|
68
|
-
}
|
|
69
|
-
catch (e) {
|
|
70
|
-
handleCommandError(e);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
ds.command('data')
|
|
74
|
-
.description('Fetch the current data payload of a DataSink')
|
|
75
|
-
.option('--id <id>', 'DataSink ID')
|
|
76
|
-
.option('--key <key>', 'DataSink key')
|
|
77
|
-
.option('--path <p>', 'JSONPath-like filter (e.g. items[0].value)')
|
|
78
|
-
.option('--force-refresh', 'Bypass cache')
|
|
79
|
-
.option('-f, --format <format>', 'Output format (json recommended)')
|
|
80
|
-
.action(async (o) => {
|
|
81
|
-
try {
|
|
82
|
-
if (!o.id && !o.key) {
|
|
83
|
-
printError('Provide --id or --key');
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
const d = await execWorkspace(ops.GET_DATASINK_DATA, {
|
|
87
|
-
id: o.id,
|
|
88
|
-
key: o.key,
|
|
89
|
-
dataPath: o.path,
|
|
90
|
-
forceRefresh: o.forceRefresh ?? false,
|
|
91
|
-
});
|
|
92
|
-
formatAndOutput({ format: o.format ?? 'json' }, d.getDataSinkData);
|
|
93
|
-
}
|
|
94
|
-
catch (e) {
|
|
95
|
-
handleCommandError(e);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
ds.command('delete')
|
|
99
|
-
.description('Delete a DataSink')
|
|
100
|
-
.argument('<id>')
|
|
101
|
-
.action(async (id) => {
|
|
102
|
-
try {
|
|
103
|
-
await execWorkspace(ops.DELETE_DATASINK, { id });
|
|
104
|
-
printSuccess(`Deleted DataSink ${id}`);
|
|
105
|
-
}
|
|
106
|
-
catch (e) {
|
|
107
|
-
handleCommandError(e);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
ds.command('create')
|
|
111
|
-
.description('Create a DataSink')
|
|
112
|
-
.requiredOption('--key <key>', 'Unique key within workspace (e.g. sales_metrics_q4)')
|
|
113
|
-
.option('--name <name>', 'Display name')
|
|
114
|
-
.option('--description <d>', 'Description')
|
|
115
|
-
.option('--data-file <path>', 'JSON file with initial payload')
|
|
116
|
-
.option('--data-json <json>', 'Inline JSON for initial payload')
|
|
117
|
-
.option('--config-file <path>', 'JSON file with DataSink config')
|
|
118
|
-
.option('--config-json <json>', 'Inline JSON for DataSink config')
|
|
119
|
-
.option('-f, --format <format>', 'Output format')
|
|
120
|
-
.action(async (o) => {
|
|
121
|
-
try {
|
|
122
|
-
const data = loadJsonInput(o.dataFile, o.dataJson);
|
|
123
|
-
const config = loadJsonInput(o.configFile, o.configJson);
|
|
124
|
-
const input = { key: o.key };
|
|
125
|
-
if (o.name)
|
|
126
|
-
input.name = o.name;
|
|
127
|
-
if (o.description)
|
|
128
|
-
input.description = o.description;
|
|
129
|
-
if (data !== undefined)
|
|
130
|
-
input.data = data;
|
|
131
|
-
if (config !== undefined)
|
|
132
|
-
input.config = config;
|
|
133
|
-
const d = await execWorkspace(ops.CREATE_DATASINK, {
|
|
134
|
-
input,
|
|
135
|
-
});
|
|
136
|
-
printSuccess(`Created DataSink: ${d.createDataSink.key} (${d.createDataSink.id})`);
|
|
137
|
-
formatAndOutput(o, d.createDataSink);
|
|
138
|
-
}
|
|
139
|
-
catch (e) {
|
|
140
|
-
handleCommandError(e);
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
ds.command('update')
|
|
144
|
-
.description('Update a DataSink')
|
|
145
|
-
.argument('<id>')
|
|
146
|
-
.option('--name <name>')
|
|
147
|
-
.option('--description <d>')
|
|
148
|
-
.option('--active <bool>', 'true / false')
|
|
149
|
-
.option('--data-file <path>', 'JSON file to replace data payload')
|
|
150
|
-
.option('--data-json <json>', 'Inline JSON to replace data payload')
|
|
151
|
-
.option('-f, --format <format>', 'Output format')
|
|
152
|
-
.action(async (id, o) => {
|
|
153
|
-
try {
|
|
154
|
-
const data = loadJsonInput(o.dataFile, o.dataJson);
|
|
155
|
-
const input = { id };
|
|
156
|
-
if (o.name)
|
|
157
|
-
input.name = o.name;
|
|
158
|
-
if (o.description !== undefined)
|
|
159
|
-
input.description = o.description;
|
|
160
|
-
if (o.active !== undefined) {
|
|
161
|
-
input.isActive = o.active.toLowerCase() === 'true' || o.active === '1';
|
|
162
|
-
}
|
|
163
|
-
if (data !== undefined)
|
|
164
|
-
input.data = data;
|
|
165
|
-
const d = await execWorkspace(ops.UPDATE_DATASINK, {
|
|
166
|
-
input,
|
|
167
|
-
});
|
|
168
|
-
printSuccess(`Updated DataSink ${id}`);
|
|
169
|
-
formatAndOutput(o, d.updateDataSink);
|
|
170
|
-
}
|
|
171
|
-
catch (e) {
|
|
172
|
-
handleCommandError(e);
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* drilldown commands — list actions on a widget, delete drilldown config.
|
|
3
|
-
*
|
|
4
|
-
* Drilldown creation is JSON-heavy (parameter mappings, target routes,
|
|
5
|
-
* modal/push/replace navigation). It's deferred to a future pass where we
|
|
6
|
-
* can offer a generator-style UX rather than a flag firehose.
|
|
7
|
-
*/
|
|
8
|
-
import * as ops from '../graphql/operations.js';
|
|
9
|
-
import { execWorkspace, formatAndOutput, handleCommandError } from './base.js';
|
|
10
|
-
import { printSuccess, formatDate, truncate } from '../utils/output.js';
|
|
11
|
-
export function registerDrilldownCommands(program) {
|
|
12
|
-
const dd = program.command('drilldown').description('Widget drilldown actions');
|
|
13
|
-
dd.command('list')
|
|
14
|
-
.description('List widget actions (includes drilldowns)')
|
|
15
|
-
.requiredOption('--widget <id>', 'Widget ID')
|
|
16
|
-
.option('-f, --format <format>', 'Output format')
|
|
17
|
-
.action(async (o) => {
|
|
18
|
-
try {
|
|
19
|
-
const d = await execWorkspace(ops.GET_WIDGET_ACTIONS, { widgetId: o.widget });
|
|
20
|
-
formatAndOutput(o, d.getWidgetActions, {
|
|
21
|
-
headers: ['ID', 'Widget', 'Type', 'Label', 'Created'],
|
|
22
|
-
rows: d.getWidgetActions.map((a) => [
|
|
23
|
-
truncate(a.id, 14),
|
|
24
|
-
truncate(a.widgetId, 14),
|
|
25
|
-
a.type,
|
|
26
|
-
truncate(a.label ?? '-', 24),
|
|
27
|
-
formatDate(a.createdAt),
|
|
28
|
-
]),
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
handleCommandError(e);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
dd.command('delete')
|
|
36
|
-
.description('Delete the drilldown configuration from a widget')
|
|
37
|
-
.requiredOption('--widget <id>', 'Widget ID')
|
|
38
|
-
.action(async (o) => {
|
|
39
|
-
try {
|
|
40
|
-
// deleteWidgetDrilldown takes the drilldown's own id; resolve it from the widget.
|
|
41
|
-
const lookup = await execWorkspace(ops.GET_WIDGET_DRILLDOWN, {
|
|
42
|
-
id: o.widget,
|
|
43
|
-
});
|
|
44
|
-
const drilldownId = lookup.getWidget?.drilldown?.id;
|
|
45
|
-
if (!drilldownId) {
|
|
46
|
-
throw new Error(`Widget ${o.widget} has no drilldown configuration`);
|
|
47
|
-
}
|
|
48
|
-
await execWorkspace(ops.DELETE_WIDGET_DRILLDOWN, { id: drilldownId });
|
|
49
|
-
printSuccess(`Removed drilldown from widget ${o.widget}`);
|
|
50
|
-
}
|
|
51
|
-
catch (e) {
|
|
52
|
-
handleCommandError(e);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
package/dist/commands/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export { registerAuthCommands } from './auth.js';
|
|
2
|
-
export { registerCLIConfigCommands } from './cli-config.js';
|
|
3
|
-
export { registerWorkspaceCommands } from './workspace.js';
|
|
4
|
-
export { registerDashboardCommands } from './dashboard.js';
|
|
5
|
-
export { registerWidgetCommands } from './widget.js';
|
|
6
|
-
export { registerDataSinkCommands } from './datasink.js';
|
|
7
|
-
export { registerParserCommands } from './parser.js';
|
|
8
|
-
export { registerPipelineCommands } from './pipeline.js';
|
|
9
|
-
export { registerWorkflowCommands } from './workflow.js';
|
|
10
|
-
export { registerDrilldownCommands } from './drilldown.js';
|
|
11
|
-
export { registerShareCommands } from './share.js';
|
|
12
|
-
export { registerTemplateCommands } from './template.js';
|
|
13
|
-
export { registerPromptCommands } from './prompt.js';
|
package/dist/commands/parser.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* parser commands — list, get, delete.
|
|
3
|
-
*/
|
|
4
|
-
import * as ops from '../graphql/operations.js';
|
|
5
|
-
import { execWorkspace, formatAndOutput, handleCommandError, loadTextInput } from './base.js';
|
|
6
|
-
import { printSuccess, printError, formatDate, formatStatus, truncate } from '../utils/output.js';
|
|
7
|
-
export function registerParserCommands(program) {
|
|
8
|
-
const p = program.command('parser').description('Parser operations');
|
|
9
|
-
p.command('list')
|
|
10
|
-
.description('List parsers in the current workspace (scoped to a console)')
|
|
11
|
-
.requiredOption('--console <id>', 'Console (dashboard) ID parsers belong to')
|
|
12
|
-
.option('--status <s>', 'Filter by status (active, inactive)')
|
|
13
|
-
.option('--type <t>', 'Filter by parser type (jq, jsonata, spark)')
|
|
14
|
-
.option('--input <sinkKey>', 'Filter by input sink key')
|
|
15
|
-
.option('--first <n>', 'Page size', (v) => parseInt(v, 10), 25)
|
|
16
|
-
.option('--after <cursor>', 'Cursor for next page')
|
|
17
|
-
.option('-f, --format <format>', 'Output format')
|
|
18
|
-
.action(async (o) => {
|
|
19
|
-
try {
|
|
20
|
-
// Parser resolvers are scoped per-console, not per-workspace.
|
|
21
|
-
// Canonical enum values are lowercase — match server schema exactly.
|
|
22
|
-
const VALID_STATUSES = new Set(['active', 'inactive']);
|
|
23
|
-
const VALID_TYPES = new Set(['jq', 'jsonata', 'spark']);
|
|
24
|
-
const filter = { consoleId: o.console };
|
|
25
|
-
if (o.status) {
|
|
26
|
-
const s = o.status.toLowerCase();
|
|
27
|
-
if (!VALID_STATUSES.has(s)) {
|
|
28
|
-
printError(`Invalid --status "${o.status}". Valid: ${[...VALID_STATUSES].join(', ')}`);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
filter.status = s;
|
|
32
|
-
}
|
|
33
|
-
if (o.type) {
|
|
34
|
-
const t = o.type.toLowerCase();
|
|
35
|
-
if (!VALID_TYPES.has(t)) {
|
|
36
|
-
printError(`Invalid --type "${o.type}". Valid: ${[...VALID_TYPES].join(', ')}`);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
filter.type = t;
|
|
40
|
-
}
|
|
41
|
-
if (o.input)
|
|
42
|
-
filter.inputSinkKey = o.input;
|
|
43
|
-
const d = await execWorkspace(ops.LIST_PARSERS, { first: o.first ?? 25, after: o.after, filter });
|
|
44
|
-
const items = d.listParsers.edges.map((e) => e.node);
|
|
45
|
-
formatAndOutput(o, items, {
|
|
46
|
-
headers: ['ID', 'Name', 'Type', 'Status', 'Input', 'Output', 'Updated'],
|
|
47
|
-
rows: items.map((x) => [
|
|
48
|
-
truncate(x.id, 14),
|
|
49
|
-
truncate(x.name, 24),
|
|
50
|
-
x.type,
|
|
51
|
-
formatStatus(x.status),
|
|
52
|
-
truncate(x.inputSinkKey, 18),
|
|
53
|
-
truncate(x.outputKey, 18),
|
|
54
|
-
formatDate(x.updatedAt),
|
|
55
|
-
]),
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
59
|
-
handleCommandError(e);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
p.command('get')
|
|
63
|
-
.description('Get a parser by ID (includes the expression body)')
|
|
64
|
-
.argument('<id>')
|
|
65
|
-
.option('-f, --format <format>', 'Output format')
|
|
66
|
-
.action(async (id, o) => {
|
|
67
|
-
try {
|
|
68
|
-
const d = await execWorkspace(ops.GET_PARSER, { id });
|
|
69
|
-
if (!d.parser) {
|
|
70
|
-
printError('Parser not found');
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
formatAndOutput(o, d.parser);
|
|
74
|
-
}
|
|
75
|
-
catch (e) {
|
|
76
|
-
handleCommandError(e);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
p.command('delete')
|
|
80
|
-
.description('Delete a parser')
|
|
81
|
-
.argument('<id>')
|
|
82
|
-
.action(async (id) => {
|
|
83
|
-
try {
|
|
84
|
-
await execWorkspace(ops.DELETE_PARSER, { id });
|
|
85
|
-
printSuccess(`Deleted parser ${id}`);
|
|
86
|
-
}
|
|
87
|
-
catch (e) {
|
|
88
|
-
handleCommandError(e);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
p.command('create')
|
|
92
|
-
.description('Create a parser')
|
|
93
|
-
.requiredOption('--name <name>')
|
|
94
|
-
.requiredOption('--console <id>', 'Parent dashboard/console ID')
|
|
95
|
-
.requiredOption('--input-key <key>', 'DataSink key this parser reads from')
|
|
96
|
-
.requiredOption('--output-key <key>', 'Key for parser output (used by widgets)')
|
|
97
|
-
.requiredOption('--type <t>', 'Parser type (JQ, JSONATA, ...)')
|
|
98
|
-
.option('--expression <expr>', 'Parser expression (inline)')
|
|
99
|
-
.option('--expression-file <path>', 'Parser expression from file')
|
|
100
|
-
.option('--description <d>')
|
|
101
|
-
.option('--output-widget <id>', 'Target widget ID (v2.1)')
|
|
102
|
-
.option('--ttl <seconds>', 'Cache TTL', (v) => parseInt(v, 10))
|
|
103
|
-
.option('-f, --format <format>', 'Output format')
|
|
104
|
-
.action(async (o) => {
|
|
105
|
-
try {
|
|
106
|
-
const expression = loadTextInput(o.expressionFile, o.expression);
|
|
107
|
-
if (!expression) {
|
|
108
|
-
printError('Provide --expression or --expression-file');
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
const input = {
|
|
112
|
-
name: o.name,
|
|
113
|
-
consoleId: o.console,
|
|
114
|
-
inputSinkKey: o.inputKey,
|
|
115
|
-
outputKey: o.outputKey,
|
|
116
|
-
type: o.type.toUpperCase(),
|
|
117
|
-
expression,
|
|
118
|
-
};
|
|
119
|
-
if (o.description)
|
|
120
|
-
input.description = o.description;
|
|
121
|
-
if (o.outputWidget)
|
|
122
|
-
input.outputWidgetId = o.outputWidget;
|
|
123
|
-
if (o.ttl !== undefined)
|
|
124
|
-
input.ttl = o.ttl;
|
|
125
|
-
const d = await execWorkspace(ops.CREATE_PARSER, {
|
|
126
|
-
input,
|
|
127
|
-
});
|
|
128
|
-
printSuccess(`Created parser: ${d.createParser.name} (${d.createParser.id})`);
|
|
129
|
-
formatAndOutput(o, d.createParser);
|
|
130
|
-
}
|
|
131
|
-
catch (e) {
|
|
132
|
-
handleCommandError(e);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
p.command('update')
|
|
136
|
-
.description('Update a parser (requires current version for optimistic concurrency)')
|
|
137
|
-
.argument('<id>')
|
|
138
|
-
.requiredOption('--version <n>', 'Current parser version', (v) => parseInt(v, 10))
|
|
139
|
-
.option('--name <n>')
|
|
140
|
-
.option('--description <d>')
|
|
141
|
-
.option('--input-key <k>')
|
|
142
|
-
.option('--output-key <k>')
|
|
143
|
-
.option('--output-widget <id>')
|
|
144
|
-
.option('--status <s>', 'Parser status')
|
|
145
|
-
.option('--expression <expr>')
|
|
146
|
-
.option('--expression-file <path>')
|
|
147
|
-
.option('--ttl <seconds>', '', (v) => parseInt(v, 10))
|
|
148
|
-
.option('-f, --format <format>', 'Output format')
|
|
149
|
-
.action(async (id, o) => {
|
|
150
|
-
try {
|
|
151
|
-
const expression = loadTextInput(o.expressionFile, o.expression);
|
|
152
|
-
const input = {};
|
|
153
|
-
if (o.name)
|
|
154
|
-
input.name = o.name;
|
|
155
|
-
if (o.description !== undefined)
|
|
156
|
-
input.description = o.description;
|
|
157
|
-
if (o.inputKey)
|
|
158
|
-
input.inputSinkKey = o.inputKey;
|
|
159
|
-
if (o.outputKey)
|
|
160
|
-
input.outputKey = o.outputKey;
|
|
161
|
-
if (o.outputWidget)
|
|
162
|
-
input.outputWidgetId = o.outputWidget;
|
|
163
|
-
if (o.status)
|
|
164
|
-
input.status = o.status.toUpperCase();
|
|
165
|
-
if (expression)
|
|
166
|
-
input.expression = expression;
|
|
167
|
-
if (o.ttl !== undefined)
|
|
168
|
-
input.ttl = o.ttl;
|
|
169
|
-
const d = await execWorkspace(ops.UPDATE_PARSER, {
|
|
170
|
-
id,
|
|
171
|
-
version: o.version,
|
|
172
|
-
input,
|
|
173
|
-
});
|
|
174
|
-
printSuccess(`Updated parser ${id} (now v${d.updateParser.version})`);
|
|
175
|
-
formatAndOutput(o, d.updateParser);
|
|
176
|
-
}
|
|
177
|
-
catch (e) {
|
|
178
|
-
handleCommandError(e);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|