@tenderprompt/cli 0.1.13 → 0.1.15
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 +21 -10
- package/bin/tender.js +1 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.js +363 -59
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ npm install -g @tenderprompt/cli
|
|
|
16
16
|
Then run:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
+
tender --version
|
|
19
20
|
tender capabilities --json
|
|
20
21
|
```
|
|
21
22
|
|
|
@@ -25,6 +26,8 @@ Use the CLI to work with Tender Apps from a local checkout or coding-agent
|
|
|
25
26
|
session:
|
|
26
27
|
|
|
27
28
|
- sign in with a bounded device token and optional artifact scope
|
|
29
|
+
- print the installed CLI package version with `tender --version`, `tender -v`,
|
|
30
|
+
or `tender version --json`
|
|
28
31
|
- list, create, and rename apps
|
|
29
32
|
- bootstrap a local app checkout with Tender project context
|
|
30
33
|
- configure the Tender artifact Git remote and credential helper
|
|
@@ -48,6 +51,7 @@ interactive prompts unless the command is explicitly an auth flow.
|
|
|
48
51
|
## Typical Flow
|
|
49
52
|
|
|
50
53
|
```bash
|
|
54
|
+
tender --version
|
|
51
55
|
tender capabilities --json
|
|
52
56
|
|
|
53
57
|
tender auth login --device --profile edit-preview --artifact artifact_123 --ttl 7d
|
|
@@ -120,6 +124,7 @@ indexing the accepted commit after upstream Git accepts the push.
|
|
|
120
124
|
## Useful Commands
|
|
121
125
|
|
|
122
126
|
```bash
|
|
127
|
+
tender --version
|
|
123
128
|
tender capabilities --json
|
|
124
129
|
tender app list --json
|
|
125
130
|
tender app create --name "Exit Intent Widget" --json
|
|
@@ -133,9 +138,10 @@ tender app build artifact_123 --commit "$(git rev-parse HEAD)" --json
|
|
|
133
138
|
tender app preview artifact_123 --commit "$(git rev-parse HEAD)" --stream --json
|
|
134
139
|
tender app publish artifact_123 --dry-run --json
|
|
135
140
|
tender app db capabilities artifact_123 --json
|
|
136
|
-
tender app db tables artifact_123 --json
|
|
137
|
-
tender app db schema artifact_123 --table votes --json
|
|
138
|
-
tender app db query artifact_123 --sql "select * from votes limit 20" --json
|
|
141
|
+
tender app db tables artifact_123 --env published --json
|
|
142
|
+
tender app db schema artifact_123 --env published --table votes --json
|
|
143
|
+
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --json
|
|
144
|
+
tender app db query artifact_123 --env published --sql "select * from votes order by created_at" --limit 50 --offset 50 --json
|
|
139
145
|
```
|
|
140
146
|
|
|
141
147
|
## Analytics
|
|
@@ -249,7 +255,8 @@ ids, URLs, or high-cardinality values unless the chart has a clear purpose.
|
|
|
249
255
|
App database commands are artifact-scoped and go through Tender's server-side
|
|
250
256
|
authorization and read-only query checks. The CLI only accepts an app id; it
|
|
251
257
|
does not accept tenant ids, runner names, provider account ids, or runtime
|
|
252
|
-
storage identifiers.
|
|
258
|
+
storage identifiers. Commands that read data require an explicit `--env preview`
|
|
259
|
+
or `--env published`; there is no default environment.
|
|
253
260
|
|
|
254
261
|
Start with capabilities:
|
|
255
262
|
|
|
@@ -262,24 +269,28 @@ tender app db capabilities artifact_123 --profile db --json
|
|
|
262
269
|
Common read-only commands:
|
|
263
270
|
|
|
264
271
|
```bash
|
|
265
|
-
tender app db tables artifact_123 --profile db --json
|
|
272
|
+
tender app db tables artifact_123 --env published --profile db --json
|
|
266
273
|
|
|
267
|
-
tender app db schema artifact_123 --table votes --profile db --json
|
|
274
|
+
tender app db schema artifact_123 --env published --table votes --profile db --json
|
|
268
275
|
|
|
269
|
-
tender app db query artifact_123 --sql "select * from votes limit 20" --profile db --json
|
|
276
|
+
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --profile db --json
|
|
270
277
|
|
|
271
278
|
tender app db query artifact_123 \
|
|
279
|
+
--env published \
|
|
272
280
|
--sql "select * from votes where choice = ?" \
|
|
273
281
|
--param coffee \
|
|
274
282
|
--profile db \
|
|
275
283
|
--json
|
|
276
284
|
|
|
277
|
-
tender app db query artifact_123 --file ./debug.sql --limit 50 --profile db --json
|
|
285
|
+
tender app db query artifact_123 --env published --file ./debug.sql --limit 50 --offset 100 --profile db --json
|
|
278
286
|
|
|
279
|
-
tender app db query artifact_123 --file - --profile db --json < debug.sql
|
|
287
|
+
tender app db query artifact_123 --env published --file - --offset 100 --profile db --json < debug.sql
|
|
280
288
|
```
|
|
281
289
|
|
|
282
|
-
The query command sends one read-only statement with positional bindings.
|
|
290
|
+
The query command sends one read-only statement with positional bindings. Query
|
|
291
|
+
responses include `requestedLimit`, `appliedLimit`, `maxInteractiveLimit`,
|
|
292
|
+
`offset`, and `nextOffset`; agents must request each page explicitly and should
|
|
293
|
+
not auto-drain large tables. The interactive row cap is 50 rows per request.
|
|
283
294
|
Client and server limits include a 100 KB statement cap and at most 100 bound
|
|
284
295
|
parameters. The server enforces the final policy, row limits, response limits,
|
|
285
296
|
artifact scope, and audit logging.
|
package/bin/tender.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { runTenderCli } from "../dist/index.js";
|
|
4
|
-
|
|
5
|
-
function shouldReadEntrypointStdin(args) {
|
|
6
|
-
return (
|
|
7
|
-
args[0] === "artifacts" &&
|
|
8
|
-
args[1] === "git" &&
|
|
9
|
-
args[2] === "credential"
|
|
10
|
-
);
|
|
11
|
-
}
|
|
3
|
+
import { runTenderCli, shouldReadEntrypointStdin } from "../dist/index.js";
|
|
12
4
|
|
|
13
5
|
async function readEntrypointStdin() {
|
|
14
6
|
if (process.stdin.isTTY) {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -41,18 +41,28 @@ class TenderCliUsageError extends Error {
|
|
|
41
41
|
}
|
|
42
42
|
class TenderCliAnalyticsApiError extends Error {
|
|
43
43
|
reasonCode;
|
|
44
|
-
|
|
44
|
+
scope;
|
|
45
|
+
example;
|
|
46
|
+
constructor(message, reasonCode, scope = null, example = null) {
|
|
45
47
|
super(message);
|
|
46
48
|
this.name = "TenderCliAnalyticsApiError";
|
|
47
49
|
this.reasonCode = reasonCode;
|
|
50
|
+
this.scope = scope;
|
|
51
|
+
this.example = example;
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
class TenderCliDbApiError extends Error {
|
|
51
55
|
reasonCode;
|
|
52
|
-
|
|
56
|
+
scope;
|
|
57
|
+
example;
|
|
58
|
+
nextAction;
|
|
59
|
+
constructor(message, reasonCode, scope, example, nextAction = null) {
|
|
53
60
|
super(message);
|
|
54
61
|
this.name = "TenderCliDbApiError";
|
|
55
62
|
this.reasonCode = reasonCode;
|
|
63
|
+
this.scope = scope;
|
|
64
|
+
this.example = example;
|
|
65
|
+
this.nextAction = nextAction;
|
|
56
66
|
}
|
|
57
67
|
}
|
|
58
68
|
const DEFAULT_PROFILE_NAME = "default";
|
|
@@ -65,6 +75,8 @@ function rootHelp() {
|
|
|
65
75
|
return `Usage: tender <command> [options]
|
|
66
76
|
|
|
67
77
|
Commands:
|
|
78
|
+
tender --version
|
|
79
|
+
Show the installed Tender CLI version
|
|
68
80
|
tender capabilities --json
|
|
69
81
|
Describe the CLI command surface for coding agents
|
|
70
82
|
tender auth login --device
|
|
@@ -101,7 +113,7 @@ Commands:
|
|
|
101
113
|
Generate useful starter chart suggestions
|
|
102
114
|
tender app db capabilities <app-id>
|
|
103
115
|
Describe app database query limits and policy
|
|
104
|
-
tender app db query <app-id> --sql <sql>
|
|
116
|
+
tender app db query <app-id> --env <preview|published> --sql <sql>
|
|
105
117
|
Run one read-only app database query
|
|
106
118
|
tender app context fetch <app-id>
|
|
107
119
|
Fetch managed agent context into a checkout
|
|
@@ -118,6 +130,7 @@ Commands:
|
|
|
118
130
|
Regenerate src/env.d.ts from app.json and bindings
|
|
119
131
|
|
|
120
132
|
Examples:
|
|
133
|
+
tender --version
|
|
121
134
|
tender capabilities --json
|
|
122
135
|
tender auth login --device --profile edit-preview --artifact artifact_123 --ttl 7d
|
|
123
136
|
tender auth status --json
|
|
@@ -135,9 +148,9 @@ Examples:
|
|
|
135
148
|
tender app analytics query artifact_123 --spec chart.json --json
|
|
136
149
|
tender app analytics suggestions artifact_123 --range 30d --json
|
|
137
150
|
tender app db capabilities artifact_123 --json
|
|
138
|
-
tender app db tables artifact_123 --json
|
|
139
|
-
tender app db schema artifact_123 --table votes --json
|
|
140
|
-
tender app db query artifact_123 --sql "select * from votes limit 20" --json
|
|
151
|
+
tender app db tables artifact_123 --env published --json
|
|
152
|
+
tender app db schema artifact_123 --env published --table votes --json
|
|
153
|
+
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --json
|
|
141
154
|
tender app context fetch artifact_123 --dir ./widget --dry-run --json
|
|
142
155
|
tender app context status artifact_123 --dir ./widget --json
|
|
143
156
|
tender app context refresh artifact_123 --dir ./widget --dry-run --json
|
|
@@ -238,11 +251,11 @@ Commands:
|
|
|
238
251
|
Make a custom event property queryable
|
|
239
252
|
tender app db capabilities <app-id>
|
|
240
253
|
Describe app database query limits and policy
|
|
241
|
-
tender app db tables <app-id>
|
|
254
|
+
tender app db tables <app-id> --env <preview|published>
|
|
242
255
|
List app database tables and views
|
|
243
|
-
tender app db schema <app-id> --table <name>
|
|
256
|
+
tender app db schema <app-id> --env <preview|published> --table <name>
|
|
244
257
|
Show table and index schema for one table
|
|
245
|
-
tender app db query <app-id> --sql <sql>
|
|
258
|
+
tender app db query <app-id> --env <preview|published> --sql <sql>
|
|
246
259
|
Run one read-only app database query
|
|
247
260
|
tender app context fetch <app-id>
|
|
248
261
|
Fetch AGENTS.md, skills, and Tender App scaffold files
|
|
@@ -285,9 +298,9 @@ Examples:
|
|
|
285
298
|
tender app analytics properties list artifact_123 --json
|
|
286
299
|
tender app analytics properties activate artifact_123 --event signup_started --property plan --type dimension --dry-run --json
|
|
287
300
|
tender app db capabilities artifact_123 --json
|
|
288
|
-
tender app db tables artifact_123 --json
|
|
289
|
-
tender app db schema artifact_123 --table votes --json
|
|
290
|
-
tender app db query artifact_123 --sql "select * from votes limit 20" --json
|
|
301
|
+
tender app db tables artifact_123 --env published --json
|
|
302
|
+
tender app db schema artifact_123 --env published --table votes --json
|
|
303
|
+
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --json
|
|
291
304
|
tender app context fetch artifact_123 --dir ./widget --dry-run --json
|
|
292
305
|
tender app context status artifact_123 --dir ./widget --json
|
|
293
306
|
tender app context refresh artifact_123 --dir ./widget --dry-run --json
|
|
@@ -307,6 +320,17 @@ copying long command lists into skill prompts.
|
|
|
307
320
|
Examples:
|
|
308
321
|
tender capabilities --json`;
|
|
309
322
|
}
|
|
323
|
+
function versionHelp() {
|
|
324
|
+
return `Usage: tender --version
|
|
325
|
+
tender -v
|
|
326
|
+
tender version [--json]
|
|
327
|
+
|
|
328
|
+
Prints the installed Tender CLI package version.
|
|
329
|
+
|
|
330
|
+
Examples:
|
|
331
|
+
tender --version
|
|
332
|
+
tender version --json`;
|
|
333
|
+
}
|
|
310
334
|
function analyticsHelp() {
|
|
311
335
|
return `Usage: tender app analytics <command> <app-id> [options]
|
|
312
336
|
|
|
@@ -471,16 +495,19 @@ function dbHelp() {
|
|
|
471
495
|
|
|
472
496
|
Commands:
|
|
473
497
|
tender app db capabilities <app-id> Describe app database policy and limits
|
|
474
|
-
tender app db tables <app-id>
|
|
475
|
-
|
|
476
|
-
tender app db
|
|
498
|
+
tender app db tables <app-id> --env <preview|published>
|
|
499
|
+
List app database tables and views
|
|
500
|
+
tender app db schema <app-id> --env <preview|published>
|
|
501
|
+
Show schema for one table
|
|
502
|
+
tender app db query <app-id> --env <preview|published>
|
|
503
|
+
Run one read-only SQL query
|
|
477
504
|
|
|
478
505
|
Examples:
|
|
479
506
|
tender app db capabilities artifact_123 --json
|
|
480
|
-
tender app db tables artifact_123 --json
|
|
481
|
-
tender app db schema artifact_123 --table votes --json
|
|
482
|
-
tender app db query artifact_123 --sql "select * from votes limit 20" --json
|
|
483
|
-
tender app db query artifact_123 --file ./debug.sql --param active --limit 50 --json`;
|
|
507
|
+
tender app db tables artifact_123 --env published --json
|
|
508
|
+
tender app db schema artifact_123 --env published --table votes --json
|
|
509
|
+
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --json
|
|
510
|
+
tender app db query artifact_123 --env published --file ./debug.sql --param active --limit 50 --json`;
|
|
484
511
|
}
|
|
485
512
|
function dbCapabilitiesHelp() {
|
|
486
513
|
return `Usage: tender app db capabilities <app-id> [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
@@ -489,33 +516,35 @@ Examples:
|
|
|
489
516
|
tender app db capabilities artifact_123 --json`;
|
|
490
517
|
}
|
|
491
518
|
function dbTablesHelp() {
|
|
492
|
-
return `Usage: tender app db tables <app-id>
|
|
519
|
+
return `Usage: tender app db tables <app-id> --env <preview|published> [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
493
520
|
|
|
494
521
|
Examples:
|
|
495
|
-
tender app db tables artifact_123 --json
|
|
522
|
+
tender app db tables artifact_123 --env published --json
|
|
496
523
|
tender app db tables artifact_123 --env preview --json`;
|
|
497
524
|
}
|
|
498
525
|
function dbSchemaHelp() {
|
|
499
|
-
return `Usage: tender app db schema <app-id> --
|
|
526
|
+
return `Usage: tender app db schema <app-id> --env <preview|published> --table <name> [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
500
527
|
|
|
501
528
|
Examples:
|
|
502
|
-
tender app db schema artifact_123 --table votes --json
|
|
529
|
+
tender app db schema artifact_123 --env published --table votes --json
|
|
503
530
|
tender app db schema artifact_123 --table preference_votes --env preview --json`;
|
|
504
531
|
}
|
|
505
532
|
function dbQueryHelp() {
|
|
506
|
-
return `Usage: tender app db query <app-id> (--sql <sql> | --file <path|->) [--param <value>] [--limit <n>] [--
|
|
533
|
+
return `Usage: tender app db query <app-id> --env <preview|published> (--sql <sql> | --file <path|->) [--param <value>] [--limit <n>] [--offset <n>] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
507
534
|
|
|
508
535
|
Options:
|
|
536
|
+
--env <value> Target app environment: preview or published. Required.
|
|
509
537
|
--sql <sql> SQL statement. Must be one read-only statement.
|
|
510
538
|
--file <path|-> Read SQL from a file or stdin with -.
|
|
511
|
-
--param <value> Bind one positional parameter. Repeat for multiple params. Values parse as
|
|
512
|
-
--limit <n> Interactive row limit. Server caps the maximum.
|
|
539
|
+
--param <value> Bind one positional parameter. Repeat for multiple params. Values parse as numbers or null; other values are passed as strings.
|
|
540
|
+
--limit <n> Interactive row limit. Server caps the maximum at 50.
|
|
541
|
+
--offset <n> Skip rows before returning results. Server caps the maximum offset.
|
|
513
542
|
|
|
514
543
|
Examples:
|
|
515
|
-
tender app db query artifact_123 --sql "select * from votes limit 20" --json
|
|
516
|
-
tender app db query artifact_123 --sql "select * from votes where choice = ?" --param coffee --json
|
|
517
|
-
tender app db query artifact_123 --file ./debug.sql --limit 50 --json
|
|
518
|
-
tender app db query artifact_123 --file - --json < debug.sql`;
|
|
544
|
+
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --json
|
|
545
|
+
tender app db query artifact_123 --env published --sql "select * from votes where choice = ?" --param coffee --json
|
|
546
|
+
tender app db query artifact_123 --env published --file ./debug.sql --limit 50 --offset 100 --json
|
|
547
|
+
tender app db query artifact_123 --env published --file - --json < debug.sql`;
|
|
519
548
|
}
|
|
520
549
|
function artifactsListHelp() {
|
|
521
550
|
return `Usage: tender app list [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
@@ -845,6 +874,7 @@ function tenderCliCapabilities() {
|
|
|
845
874
|
discovery: {
|
|
846
875
|
primary: "npm exec --yes @tenderprompt/cli@latest -- capabilities --json",
|
|
847
876
|
layeredHelp: [
|
|
877
|
+
"tender --version",
|
|
848
878
|
"tender --help",
|
|
849
879
|
"tender auth --help",
|
|
850
880
|
"tender app --help",
|
|
@@ -921,10 +951,10 @@ function tenderCliCapabilities() {
|
|
|
921
951
|
commands: [
|
|
922
952
|
"tender auth login --device --profile db-read --artifact <artifact-id> --ttl 7d --save-profile db --json",
|
|
923
953
|
"tender app db capabilities <artifact-id> --profile db --json",
|
|
924
|
-
"tender app db tables <artifact-id> --profile db --json",
|
|
925
|
-
"tender app db schema <artifact-id> --table <table-name> --profile db --json",
|
|
926
|
-
"tender app db query <artifact-id> --sql \"select * from <table-name> limit 20\" --profile db --json",
|
|
927
|
-
"tender app db query <artifact-id> --file ./debug.sql --profile db --json",
|
|
954
|
+
"tender app db tables <artifact-id> --env published --profile db --json",
|
|
955
|
+
"tender app db schema <artifact-id> --env published --table <table-name> --profile db --json",
|
|
956
|
+
"tender app db query <artifact-id> --env published --sql \"select * from <table-name> limit 20\" --profile db --json",
|
|
957
|
+
"tender app db query <artifact-id> --env published --file ./debug.sql --profile db --json",
|
|
928
958
|
],
|
|
929
959
|
notes: [
|
|
930
960
|
"The CLI only accepts artifact ids. It never accepts tenant ids, runner names, provider account ids, or runtime storage identifiers.",
|
|
@@ -947,6 +977,18 @@ function tenderCliCapabilities() {
|
|
|
947
977
|
},
|
|
948
978
|
],
|
|
949
979
|
commands: [
|
|
980
|
+
{
|
|
981
|
+
command: "tender --version",
|
|
982
|
+
purpose: "Print the installed Tender CLI package version.",
|
|
983
|
+
requiresAuth: false,
|
|
984
|
+
writes: false,
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
command: "tender version --json",
|
|
988
|
+
purpose: "Print the installed Tender CLI package version in a stable JSON shape.",
|
|
989
|
+
requiresAuth: false,
|
|
990
|
+
writes: false,
|
|
991
|
+
},
|
|
950
992
|
{
|
|
951
993
|
command: "tender capabilities --json",
|
|
952
994
|
purpose: "Discover this CLI surface in a machine-readable shape.",
|
|
@@ -1032,19 +1074,19 @@ function tenderCliCapabilities() {
|
|
|
1032
1074
|
writes: false,
|
|
1033
1075
|
},
|
|
1034
1076
|
{
|
|
1035
|
-
command: "tender app db tables <artifact-id> --json",
|
|
1077
|
+
command: "tender app db tables <artifact-id> --env published --json",
|
|
1036
1078
|
purpose: "List app database tables and views for one artifact.",
|
|
1037
1079
|
requiresAuth: true,
|
|
1038
1080
|
writes: false,
|
|
1039
1081
|
},
|
|
1040
1082
|
{
|
|
1041
|
-
command: "tender app db schema <artifact-id> --table <table-name> --json",
|
|
1083
|
+
command: "tender app db schema <artifact-id> --env published --table <table-name> --json",
|
|
1042
1084
|
purpose: "Inspect table, index, and trigger schema for one app database table.",
|
|
1043
1085
|
requiresAuth: true,
|
|
1044
1086
|
writes: false,
|
|
1045
1087
|
},
|
|
1046
1088
|
{
|
|
1047
|
-
command: "tender app db query <artifact-id> --sql \"select * from <table-name> limit 20\" --json",
|
|
1089
|
+
command: "tender app db query <artifact-id> --env published --sql \"select * from <table-name> limit 20\" --json",
|
|
1048
1090
|
purpose: "Run one bounded read-only app database query.",
|
|
1049
1091
|
requiresAuth: true,
|
|
1050
1092
|
writes: false,
|
|
@@ -1078,6 +1120,19 @@ function runCapabilities(command, io) {
|
|
|
1078
1120
|
}
|
|
1079
1121
|
return 0;
|
|
1080
1122
|
}
|
|
1123
|
+
function runVersion(command, io) {
|
|
1124
|
+
if (command.json) {
|
|
1125
|
+
io.stdout(JSON.stringify({
|
|
1126
|
+
ok: true,
|
|
1127
|
+
name: CLI_PACKAGE_NAME,
|
|
1128
|
+
version: CLI_PACKAGE_VERSION,
|
|
1129
|
+
}, null, 2));
|
|
1130
|
+
}
|
|
1131
|
+
else {
|
|
1132
|
+
io.stdout(CLI_PACKAGE_VERSION);
|
|
1133
|
+
}
|
|
1134
|
+
return 0;
|
|
1135
|
+
}
|
|
1081
1136
|
function normalizeBaseUrl(value) {
|
|
1082
1137
|
return (value ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
1083
1138
|
}
|
|
@@ -2402,6 +2457,13 @@ function parsePositiveIntegerFlag(value, flag) {
|
|
|
2402
2457
|
}
|
|
2403
2458
|
return parsed;
|
|
2404
2459
|
}
|
|
2460
|
+
function parseNonNegativeIntegerFlag(value, flag) {
|
|
2461
|
+
const parsed = Number(value);
|
|
2462
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
2463
|
+
throw new TenderCliUsageError(`${flag} requires a non-negative integer.`);
|
|
2464
|
+
}
|
|
2465
|
+
return parsed;
|
|
2466
|
+
}
|
|
2405
2467
|
function parseAuthLoginArgs(args) {
|
|
2406
2468
|
if (args.includes("--help") || args.includes("-h")) {
|
|
2407
2469
|
return { command: "help", topic: "auth login" };
|
|
@@ -2575,6 +2637,20 @@ function parseCapabilitiesArgs(args) {
|
|
|
2575
2637
|
}
|
|
2576
2638
|
return { command: "capabilities", json };
|
|
2577
2639
|
}
|
|
2640
|
+
function parseVersionArgs(args) {
|
|
2641
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
2642
|
+
return { command: "help", topic: "version" };
|
|
2643
|
+
}
|
|
2644
|
+
let json = false;
|
|
2645
|
+
for (const arg of args) {
|
|
2646
|
+
if (arg === "--json") {
|
|
2647
|
+
json = true;
|
|
2648
|
+
continue;
|
|
2649
|
+
}
|
|
2650
|
+
throw new TenderCliUsageError(`Unknown version option: ${arg}`);
|
|
2651
|
+
}
|
|
2652
|
+
return { command: "version", json };
|
|
2653
|
+
}
|
|
2578
2654
|
function parseBindingId(value) {
|
|
2579
2655
|
if (!value || value.startsWith("-")) {
|
|
2580
2656
|
throw new TenderCliUsageError("--id requires a binding id.");
|
|
@@ -3457,10 +3533,23 @@ function parseDbCommonArgs(args, startIndex) {
|
|
|
3457
3533
|
return { baseUrl, flagToken, profileName, json, remaining };
|
|
3458
3534
|
}
|
|
3459
3535
|
function parseDbEnvironment(value) {
|
|
3460
|
-
if (value
|
|
3536
|
+
if (!value || value.startsWith("--")) {
|
|
3537
|
+
throw new TenderCliUsageError("--env requires a value. Use preview or published.");
|
|
3538
|
+
}
|
|
3539
|
+
if (value === "preview") {
|
|
3461
3540
|
return "preview";
|
|
3462
3541
|
}
|
|
3463
|
-
|
|
3542
|
+
if (value === "published" ||
|
|
3543
|
+
value === "live" ||
|
|
3544
|
+
value === "production" ||
|
|
3545
|
+
value === "prod") {
|
|
3546
|
+
return "published";
|
|
3547
|
+
}
|
|
3548
|
+
throw new TenderCliUsageError("--env must be preview or published.");
|
|
3549
|
+
}
|
|
3550
|
+
function parseFlagAssignment(arg, flag) {
|
|
3551
|
+
const prefix = `${flag}=`;
|
|
3552
|
+
return arg.startsWith(prefix) ? arg.slice(prefix.length) : null;
|
|
3464
3553
|
}
|
|
3465
3554
|
function parseDbFlagValue(value, flag) {
|
|
3466
3555
|
if (!value || value.startsWith("--")) {
|
|
@@ -3468,6 +3557,12 @@ function parseDbFlagValue(value, flag) {
|
|
|
3468
3557
|
}
|
|
3469
3558
|
return value;
|
|
3470
3559
|
}
|
|
3560
|
+
function parseDbSqlFlagValue(value) {
|
|
3561
|
+
if (value === undefined || value.length === 0) {
|
|
3562
|
+
throw new TenderCliUsageError("--sql requires a value.");
|
|
3563
|
+
}
|
|
3564
|
+
return value;
|
|
3565
|
+
}
|
|
3471
3566
|
function parseDbFilePath(value) {
|
|
3472
3567
|
if (!value || (value !== "-" && value.startsWith("-"))) {
|
|
3473
3568
|
throw new TenderCliUsageError("--file requires a SQL file path or - for stdin.");
|
|
@@ -3509,12 +3604,17 @@ function parseDbTablesArgs(args) {
|
|
|
3509
3604
|
}
|
|
3510
3605
|
const artifactId = args[0];
|
|
3511
3606
|
if (!artifactId || artifactId.startsWith("-")) {
|
|
3512
|
-
throw new TenderCliUsageError("app id is required. Example: tender app db tables <app-id> --json");
|
|
3607
|
+
throw new TenderCliUsageError("app id is required. Example: tender app db tables <app-id> --env published --json");
|
|
3513
3608
|
}
|
|
3514
3609
|
const parsed = parseDbCommonArgs(args, 1);
|
|
3515
|
-
let environment =
|
|
3610
|
+
let environment = null;
|
|
3516
3611
|
for (let index = 0; index < parsed.remaining.length; index += 1) {
|
|
3517
3612
|
const arg = parsed.remaining[index];
|
|
3613
|
+
const envAssignment = parseFlagAssignment(arg, "--env");
|
|
3614
|
+
if (envAssignment !== null) {
|
|
3615
|
+
environment = parseDbEnvironment(envAssignment);
|
|
3616
|
+
continue;
|
|
3617
|
+
}
|
|
3518
3618
|
if (arg === "--env") {
|
|
3519
3619
|
environment = parseDbEnvironment(parsed.remaining[index + 1]);
|
|
3520
3620
|
index += 1;
|
|
@@ -3522,6 +3622,9 @@ function parseDbTablesArgs(args) {
|
|
|
3522
3622
|
}
|
|
3523
3623
|
throw new TenderCliUsageError(`Unknown app db tables option: ${arg}`);
|
|
3524
3624
|
}
|
|
3625
|
+
if (!environment) {
|
|
3626
|
+
throw new TenderCliUsageError("--env is required. Example: tender app db tables artifact_123 --env published --json");
|
|
3627
|
+
}
|
|
3525
3628
|
return { command: "app db tables", artifactId, environment, ...parsed };
|
|
3526
3629
|
}
|
|
3527
3630
|
function parseDbSchemaArgs(args) {
|
|
@@ -3530,13 +3633,23 @@ function parseDbSchemaArgs(args) {
|
|
|
3530
3633
|
}
|
|
3531
3634
|
const artifactId = args[0];
|
|
3532
3635
|
if (!artifactId || artifactId.startsWith("-")) {
|
|
3533
|
-
throw new TenderCliUsageError("app id is required. Example: tender app db schema <app-id> --table votes --json");
|
|
3636
|
+
throw new TenderCliUsageError("app id is required. Example: tender app db schema <app-id> --env published --table votes --json");
|
|
3534
3637
|
}
|
|
3535
3638
|
const parsed = parseDbCommonArgs(args, 1);
|
|
3536
|
-
let environment =
|
|
3639
|
+
let environment = null;
|
|
3537
3640
|
let tableName = null;
|
|
3538
3641
|
for (let index = 0; index < parsed.remaining.length; index += 1) {
|
|
3539
3642
|
const arg = parsed.remaining[index];
|
|
3643
|
+
const envAssignment = parseFlagAssignment(arg, "--env");
|
|
3644
|
+
if (envAssignment !== null) {
|
|
3645
|
+
environment = parseDbEnvironment(envAssignment);
|
|
3646
|
+
continue;
|
|
3647
|
+
}
|
|
3648
|
+
const tableAssignment = parseFlagAssignment(arg, "--table");
|
|
3649
|
+
if (tableAssignment !== null) {
|
|
3650
|
+
tableName = parseRequiredFlagValue(tableAssignment, "--table");
|
|
3651
|
+
continue;
|
|
3652
|
+
}
|
|
3540
3653
|
if (arg === "--env") {
|
|
3541
3654
|
environment = parseDbEnvironment(parsed.remaining[index + 1]);
|
|
3542
3655
|
index += 1;
|
|
@@ -3549,8 +3662,11 @@ function parseDbSchemaArgs(args) {
|
|
|
3549
3662
|
}
|
|
3550
3663
|
throw new TenderCliUsageError(`Unknown app db schema option: ${arg}`);
|
|
3551
3664
|
}
|
|
3665
|
+
if (!environment) {
|
|
3666
|
+
throw new TenderCliUsageError("--env is required. Example: tender app db schema artifact_123 --env published --table votes --json");
|
|
3667
|
+
}
|
|
3552
3668
|
if (!tableName) {
|
|
3553
|
-
throw new TenderCliUsageError("--table is required. Example: tender app db schema artifact_123 --table votes --json");
|
|
3669
|
+
throw new TenderCliUsageError("--table is required. Example: tender app db schema artifact_123 --env published --table votes --json");
|
|
3554
3670
|
}
|
|
3555
3671
|
return {
|
|
3556
3672
|
command: "app db schema",
|
|
@@ -3566,15 +3682,58 @@ function parseDbQueryArgs(args) {
|
|
|
3566
3682
|
}
|
|
3567
3683
|
const artifactId = args[0];
|
|
3568
3684
|
if (!artifactId || artifactId.startsWith("-")) {
|
|
3569
|
-
throw new TenderCliUsageError("app id is required. Example: tender app db query <app-id> --sql \"select * from votes limit 20\" --json");
|
|
3685
|
+
throw new TenderCliUsageError("app id is required. Example: tender app db query <app-id> --env published --sql \"select * from votes limit 20\" --json");
|
|
3570
3686
|
}
|
|
3571
3687
|
const parsed = parseDbCommonArgs(args, 1);
|
|
3572
|
-
let environment =
|
|
3688
|
+
let environment = null;
|
|
3573
3689
|
let sqlSource = null;
|
|
3574
3690
|
const params = [];
|
|
3575
3691
|
let limit = null;
|
|
3692
|
+
let offset = 0;
|
|
3576
3693
|
for (let index = 0; index < parsed.remaining.length; index += 1) {
|
|
3577
3694
|
const arg = parsed.remaining[index];
|
|
3695
|
+
const envAssignment = parseFlagAssignment(arg, "--env");
|
|
3696
|
+
if (envAssignment !== null) {
|
|
3697
|
+
environment = parseDbEnvironment(envAssignment);
|
|
3698
|
+
continue;
|
|
3699
|
+
}
|
|
3700
|
+
const sqlAssignment = parseFlagAssignment(arg, "--sql");
|
|
3701
|
+
if (sqlAssignment !== null) {
|
|
3702
|
+
if (sqlSource) {
|
|
3703
|
+
throw new TenderCliUsageError("--sql and --file cannot be repeated or combined.");
|
|
3704
|
+
}
|
|
3705
|
+
sqlSource = {
|
|
3706
|
+
kind: "inline",
|
|
3707
|
+
value: parseDbSqlFlagValue(sqlAssignment),
|
|
3708
|
+
};
|
|
3709
|
+
continue;
|
|
3710
|
+
}
|
|
3711
|
+
const fileAssignment = parseFlagAssignment(arg, "--file");
|
|
3712
|
+
if (fileAssignment !== null) {
|
|
3713
|
+
if (sqlSource) {
|
|
3714
|
+
throw new TenderCliUsageError("--sql and --file cannot be repeated or combined.");
|
|
3715
|
+
}
|
|
3716
|
+
sqlSource = {
|
|
3717
|
+
kind: "file",
|
|
3718
|
+
value: parseDbFilePath(fileAssignment),
|
|
3719
|
+
};
|
|
3720
|
+
continue;
|
|
3721
|
+
}
|
|
3722
|
+
const paramAssignment = parseFlagAssignment(arg, "--param");
|
|
3723
|
+
if (paramAssignment !== null) {
|
|
3724
|
+
params.push(parseDbParameter(paramAssignment));
|
|
3725
|
+
continue;
|
|
3726
|
+
}
|
|
3727
|
+
const limitAssignment = parseFlagAssignment(arg, "--limit");
|
|
3728
|
+
if (limitAssignment !== null) {
|
|
3729
|
+
limit = parsePositiveIntegerFlag(limitAssignment, "--limit");
|
|
3730
|
+
continue;
|
|
3731
|
+
}
|
|
3732
|
+
const offsetAssignment = parseFlagAssignment(arg, "--offset");
|
|
3733
|
+
if (offsetAssignment !== null) {
|
|
3734
|
+
offset = parseNonNegativeIntegerFlag(offsetAssignment, "--offset");
|
|
3735
|
+
continue;
|
|
3736
|
+
}
|
|
3578
3737
|
if (arg === "--env") {
|
|
3579
3738
|
environment = parseDbEnvironment(parsed.remaining[index + 1]);
|
|
3580
3739
|
index += 1;
|
|
@@ -3586,7 +3745,7 @@ function parseDbQueryArgs(args) {
|
|
|
3586
3745
|
}
|
|
3587
3746
|
sqlSource = {
|
|
3588
3747
|
kind: "inline",
|
|
3589
|
-
value:
|
|
3748
|
+
value: parseDbSqlFlagValue(parsed.remaining[index + 1]),
|
|
3590
3749
|
};
|
|
3591
3750
|
index += 1;
|
|
3592
3751
|
continue;
|
|
@@ -3612,10 +3771,18 @@ function parseDbQueryArgs(args) {
|
|
|
3612
3771
|
index += 1;
|
|
3613
3772
|
continue;
|
|
3614
3773
|
}
|
|
3774
|
+
if (arg === "--offset") {
|
|
3775
|
+
offset = parseNonNegativeIntegerFlag(parsed.remaining[index + 1], "--offset");
|
|
3776
|
+
index += 1;
|
|
3777
|
+
continue;
|
|
3778
|
+
}
|
|
3615
3779
|
throw new TenderCliUsageError(`Unknown app db query option: ${arg}`);
|
|
3616
3780
|
}
|
|
3781
|
+
if (!environment) {
|
|
3782
|
+
throw new TenderCliUsageError("--env is required. Example: tender app db query artifact_123 --env published --sql \"select * from votes limit 20\" --json");
|
|
3783
|
+
}
|
|
3617
3784
|
if (!sqlSource) {
|
|
3618
|
-
throw new TenderCliUsageError("--sql or --file is required. Example: tender app db query artifact_123 --sql \"select * from votes limit 20\" --json");
|
|
3785
|
+
throw new TenderCliUsageError("--sql or --file is required. Example: tender app db query artifact_123 --env published --sql \"select * from votes limit 20\" --json");
|
|
3619
3786
|
}
|
|
3620
3787
|
if (params.length > DB_MAX_BOUND_PARAMETERS) {
|
|
3621
3788
|
throw new TenderCliUsageError(`App database queries are limited to ${DB_MAX_BOUND_PARAMETERS} bound parameters.`);
|
|
@@ -3627,6 +3794,7 @@ function parseDbQueryArgs(args) {
|
|
|
3627
3794
|
sqlSource,
|
|
3628
3795
|
params,
|
|
3629
3796
|
limit,
|
|
3797
|
+
offset,
|
|
3630
3798
|
...parsed,
|
|
3631
3799
|
};
|
|
3632
3800
|
}
|
|
@@ -3634,6 +3802,12 @@ function parseTenderArgs(args) {
|
|
|
3634
3802
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
3635
3803
|
return { command: "help", topic: "root" };
|
|
3636
3804
|
}
|
|
3805
|
+
if (args[0] === "--version" || args[0] === "-v") {
|
|
3806
|
+
return parseVersionArgs(args.slice(1));
|
|
3807
|
+
}
|
|
3808
|
+
if (args[0] === "version") {
|
|
3809
|
+
return parseVersionArgs(args.slice(1));
|
|
3810
|
+
}
|
|
3637
3811
|
if (args[0] === "capabilities") {
|
|
3638
3812
|
return parseCapabilitiesArgs(args.slice(1));
|
|
3639
3813
|
}
|
|
@@ -4192,12 +4366,16 @@ async function requestAnalyticsApi(input) {
|
|
|
4192
4366
|
const message = (typeof payload?.message === "string" && payload.message) ||
|
|
4193
4367
|
(typeof payload?.reasonCode === "string" && payload.reasonCode) ||
|
|
4194
4368
|
`Analytics request failed with HTTP ${response.status}.`;
|
|
4369
|
+
const example = analyticsCorrectedExample(input.artifactId, input.analyticsPath);
|
|
4195
4370
|
throw new TenderCliAnalyticsApiError([
|
|
4196
4371
|
message,
|
|
4197
4372
|
`Scope: artifact ${input.artifactId}, analytics/${input.analyticsPath || "summary"}.`,
|
|
4198
4373
|
`Reason: ${reasonCode}.`,
|
|
4199
|
-
`Example: ${
|
|
4200
|
-
].join("\n"), reasonCode
|
|
4374
|
+
`Example: ${example}.`,
|
|
4375
|
+
].join("\n"), reasonCode, {
|
|
4376
|
+
artifactId: input.artifactId,
|
|
4377
|
+
surface: `analytics/${input.analyticsPath || "summary"}`,
|
|
4378
|
+
}, example);
|
|
4201
4379
|
}
|
|
4202
4380
|
return payload;
|
|
4203
4381
|
}
|
|
@@ -4229,12 +4407,22 @@ async function requestDbApi(input) {
|
|
|
4229
4407
|
const message = (typeof payload?.message === "string" && payload.message) ||
|
|
4230
4408
|
(typeof payload?.reasonCode === "string" && payload.reasonCode) ||
|
|
4231
4409
|
`App database request failed with HTTP ${response.status}.`;
|
|
4410
|
+
const nextAction = typeof payload?.nextAction === "string" && payload.nextAction
|
|
4411
|
+
? payload.nextAction
|
|
4412
|
+
: null;
|
|
4413
|
+
const example = dbCorrectedExample(input.artifactId, input.dbPath);
|
|
4232
4414
|
throw new TenderCliDbApiError([
|
|
4233
4415
|
message,
|
|
4234
4416
|
`Scope: artifact ${input.artifactId}, db/${input.dbPath}.`,
|
|
4235
4417
|
`Reason: ${reasonCode}.`,
|
|
4236
|
-
`Example: ${
|
|
4237
|
-
].join("\n"), reasonCode
|
|
4418
|
+
`Example: ${example}.`,
|
|
4419
|
+
].join("\n"), reasonCode, {
|
|
4420
|
+
artifactId: input.artifactId,
|
|
4421
|
+
surface: `db/${input.dbPath}`,
|
|
4422
|
+
...(input.scopeEnvironment ?? input.environment
|
|
4423
|
+
? { environment: input.scopeEnvironment ?? input.environment }
|
|
4424
|
+
: {}),
|
|
4425
|
+
}, example, nextAction);
|
|
4238
4426
|
}
|
|
4239
4427
|
return payload;
|
|
4240
4428
|
}
|
|
@@ -4243,12 +4431,12 @@ function dbCorrectedExample(artifactId, dbPath) {
|
|
|
4243
4431
|
return `tender app db capabilities ${artifactId} --json`;
|
|
4244
4432
|
}
|
|
4245
4433
|
if (dbPath === "tables") {
|
|
4246
|
-
return `tender app db tables ${artifactId} --json`;
|
|
4434
|
+
return `tender app db tables ${artifactId} --env published --json`;
|
|
4247
4435
|
}
|
|
4248
4436
|
if (dbPath === "schema") {
|
|
4249
|
-
return `tender app db schema ${artifactId} --table <table-name> --json`;
|
|
4437
|
+
return `tender app db schema ${artifactId} --env published --table <table-name> --json`;
|
|
4250
4438
|
}
|
|
4251
|
-
return `tender app db query ${artifactId} --sql "select * from <table-name> limit 20" --json`;
|
|
4439
|
+
return `tender app db query ${artifactId} --env published --sql "select * from <table-name> limit 20" --json`;
|
|
4252
4440
|
}
|
|
4253
4441
|
function analyticsCorrectedExample(artifactId, analyticsPath) {
|
|
4254
4442
|
if (analyticsPath === "capabilities") {
|
|
@@ -4497,7 +4685,7 @@ async function requestAnalyticsQueryWithPropertyGuidance(input) {
|
|
|
4497
4685
|
spec: input.spec,
|
|
4498
4686
|
});
|
|
4499
4687
|
if (guidance) {
|
|
4500
|
-
throw new TenderCliAnalyticsApiError(`${error.message}\n\n${guidance}`, error.reasonCode);
|
|
4688
|
+
throw new TenderCliAnalyticsApiError(`${error.message}\n\n${guidance}`, error.reasonCode, error.scope, error.example);
|
|
4501
4689
|
}
|
|
4502
4690
|
}
|
|
4503
4691
|
throw error;
|
|
@@ -6641,6 +6829,7 @@ async function runDbQuery(command, io, runtime) {
|
|
|
6641
6829
|
sql,
|
|
6642
6830
|
params: command.params,
|
|
6643
6831
|
...(command.limit === null ? {} : { limit: command.limit }),
|
|
6832
|
+
offset: command.offset,
|
|
6644
6833
|
};
|
|
6645
6834
|
const payload = await requestDbApi({
|
|
6646
6835
|
artifactId: command.artifactId,
|
|
@@ -6649,6 +6838,7 @@ async function runDbQuery(command, io, runtime) {
|
|
|
6649
6838
|
baseUrl: credentials.baseUrl,
|
|
6650
6839
|
token: credentials.token,
|
|
6651
6840
|
fetcher: runtime.fetcher ?? fetch,
|
|
6841
|
+
scopeEnvironment: command.environment,
|
|
6652
6842
|
body,
|
|
6653
6843
|
});
|
|
6654
6844
|
const rows = Array.isArray(payload.rows) ? payload.rows : [];
|
|
@@ -6656,7 +6846,12 @@ async function runDbQuery(command, io, runtime) {
|
|
|
6656
6846
|
`app_id: ${command.artifactId}`,
|
|
6657
6847
|
`environment: ${command.environment}`,
|
|
6658
6848
|
`rows: ${rows.length}`,
|
|
6849
|
+
`offset: ${String(payload.offset ?? command.offset)}`,
|
|
6850
|
+
`applied_limit: ${String(payload.appliedLimit ?? command.limit ?? "")}`,
|
|
6659
6851
|
`truncated: ${String(payload.truncated ?? false)}`,
|
|
6852
|
+
...(typeof payload.nextOffset === "number"
|
|
6853
|
+
? [`next_offset: ${payload.nextOffset}`]
|
|
6854
|
+
: []),
|
|
6660
6855
|
]);
|
|
6661
6856
|
return 0;
|
|
6662
6857
|
}
|
|
@@ -7063,16 +7258,118 @@ async function runAnalyticsChartsDelete(command, io, runtime) {
|
|
|
7063
7258
|
]);
|
|
7064
7259
|
return 0;
|
|
7065
7260
|
}
|
|
7261
|
+
function cliErrorMessage(error) {
|
|
7262
|
+
if (error instanceof Error) {
|
|
7263
|
+
return error.message.split("\n")[0] ?? error.message;
|
|
7264
|
+
}
|
|
7265
|
+
return String(error);
|
|
7266
|
+
}
|
|
7267
|
+
function cliErrorCode(error) {
|
|
7268
|
+
if (error instanceof TenderCliDbApiError || error instanceof TenderCliAnalyticsApiError) {
|
|
7269
|
+
return error.reasonCode;
|
|
7270
|
+
}
|
|
7271
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
7272
|
+
const code = error.code;
|
|
7273
|
+
if (code === "ENOENT") {
|
|
7274
|
+
return "file_not_found";
|
|
7275
|
+
}
|
|
7276
|
+
if (typeof code === "string" && code.length > 0) {
|
|
7277
|
+
return code.toLowerCase();
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
return error instanceof TenderCliUsageError ? "cli_usage_error" : "cli_error";
|
|
7281
|
+
}
|
|
7282
|
+
function commandNameForError(args, command) {
|
|
7283
|
+
if (command) {
|
|
7284
|
+
return command.command === "help" ? `help ${command.topic}` : command.command;
|
|
7285
|
+
}
|
|
7286
|
+
if (args[0] === "app" && args[1] === "db" && args[2]) {
|
|
7287
|
+
return `app db ${args[2]}`;
|
|
7288
|
+
}
|
|
7289
|
+
if (args[0] === "app" && args[1]) {
|
|
7290
|
+
return `app ${args[1]}`;
|
|
7291
|
+
}
|
|
7292
|
+
return args[0] ?? "unknown";
|
|
7293
|
+
}
|
|
7294
|
+
function dbPathFromCommandName(commandName) {
|
|
7295
|
+
if (commandName === "app db capabilities") {
|
|
7296
|
+
return "capabilities";
|
|
7297
|
+
}
|
|
7298
|
+
if (commandName === "app db tables") {
|
|
7299
|
+
return "tables";
|
|
7300
|
+
}
|
|
7301
|
+
if (commandName === "app db schema") {
|
|
7302
|
+
return "schema";
|
|
7303
|
+
}
|
|
7304
|
+
if (commandName === "app db query") {
|
|
7305
|
+
return "query";
|
|
7306
|
+
}
|
|
7307
|
+
return null;
|
|
7308
|
+
}
|
|
7309
|
+
function artifactIdForError(args, command) {
|
|
7310
|
+
if (command && "artifactId" in command) {
|
|
7311
|
+
return command.artifactId;
|
|
7312
|
+
}
|
|
7313
|
+
if (args[0] === "app" && args[1] === "db" && args[3] && !args[3].startsWith("-")) {
|
|
7314
|
+
return args[3];
|
|
7315
|
+
}
|
|
7316
|
+
return null;
|
|
7317
|
+
}
|
|
7318
|
+
function scopeForError(error, args, command) {
|
|
7319
|
+
if (error instanceof TenderCliDbApiError || error instanceof TenderCliAnalyticsApiError) {
|
|
7320
|
+
return error.scope;
|
|
7321
|
+
}
|
|
7322
|
+
const commandName = commandNameForError(args, command);
|
|
7323
|
+
const dbPath = dbPathFromCommandName(commandName);
|
|
7324
|
+
const artifactId = artifactIdForError(args, command);
|
|
7325
|
+
if (dbPath && artifactId) {
|
|
7326
|
+
return {
|
|
7327
|
+
artifactId,
|
|
7328
|
+
surface: `db/${dbPath}`,
|
|
7329
|
+
};
|
|
7330
|
+
}
|
|
7331
|
+
return null;
|
|
7332
|
+
}
|
|
7333
|
+
function exampleForError(error, args, command) {
|
|
7334
|
+
if (error instanceof TenderCliDbApiError || error instanceof TenderCliAnalyticsApiError) {
|
|
7335
|
+
return error.example;
|
|
7336
|
+
}
|
|
7337
|
+
const commandName = commandNameForError(args, command);
|
|
7338
|
+
const dbPath = dbPathFromCommandName(commandName);
|
|
7339
|
+
const artifactId = artifactIdForError(args, command) ?? "artifact_123";
|
|
7340
|
+
return dbPath ? dbCorrectedExample(artifactId, dbPath) : null;
|
|
7341
|
+
}
|
|
7342
|
+
function nextActionForError(error) {
|
|
7343
|
+
return error instanceof TenderCliDbApiError ? error.nextAction : null;
|
|
7344
|
+
}
|
|
7345
|
+
function cliErrorPayload(error, args, command) {
|
|
7346
|
+
const scope = scopeForError(error, args, command);
|
|
7347
|
+
const example = exampleForError(error, args, command);
|
|
7348
|
+
const nextAction = nextActionForError(error);
|
|
7349
|
+
return {
|
|
7350
|
+
ok: false,
|
|
7351
|
+
command: commandNameForError(args, command),
|
|
7352
|
+
reasonCode: cliErrorCode(error),
|
|
7353
|
+
message: cliErrorMessage(error),
|
|
7354
|
+
...(scope ? { scope } : {}),
|
|
7355
|
+
...(nextAction ? { nextAction } : {}),
|
|
7356
|
+
...(example ? { example } : {}),
|
|
7357
|
+
};
|
|
7358
|
+
}
|
|
7066
7359
|
export async function runTenderCli(args, io = {
|
|
7067
7360
|
stdout: (message) => console.log(message),
|
|
7068
7361
|
stderr: (message) => console.error(message),
|
|
7069
7362
|
}, runtime = {}) {
|
|
7363
|
+
let command = null;
|
|
7070
7364
|
try {
|
|
7071
|
-
|
|
7365
|
+
command = parseTenderArgs(args);
|
|
7072
7366
|
if (command.command === "help") {
|
|
7073
7367
|
if (command.topic === "capabilities") {
|
|
7074
7368
|
io.stdout(capabilitiesHelp());
|
|
7075
7369
|
}
|
|
7370
|
+
else if (command.topic === "version") {
|
|
7371
|
+
io.stdout(versionHelp());
|
|
7372
|
+
}
|
|
7076
7373
|
else if (command.topic === "auth login") {
|
|
7077
7374
|
io.stdout(authLoginHelp());
|
|
7078
7375
|
}
|
|
@@ -7219,6 +7516,9 @@ export async function runTenderCli(args, io = {
|
|
|
7219
7516
|
if (command.command === "capabilities") {
|
|
7220
7517
|
return runCapabilities(command, io);
|
|
7221
7518
|
}
|
|
7519
|
+
if (command.command === "version") {
|
|
7520
|
+
return runVersion(command, io);
|
|
7521
|
+
}
|
|
7222
7522
|
if (command.command === "auth login") {
|
|
7223
7523
|
return await runAuthLogin(command, io, runtime);
|
|
7224
7524
|
}
|
|
@@ -7342,6 +7642,10 @@ export async function runTenderCli(args, io = {
|
|
|
7342
7642
|
return await runDoctor(command, io);
|
|
7343
7643
|
}
|
|
7344
7644
|
catch (error) {
|
|
7645
|
+
if (args.includes("--json") && args[0] === "app" && args[1] === "db") {
|
|
7646
|
+
io.stdout(JSON.stringify(cliErrorPayload(error, args, command), null, 2));
|
|
7647
|
+
return error instanceof TenderCliUsageError ? 2 : 1;
|
|
7648
|
+
}
|
|
7345
7649
|
io.stderr(error instanceof Error ? error.message : String(error));
|
|
7346
7650
|
io.stderr("Run `tender --help` for examples.");
|
|
7347
7651
|
return error instanceof TenderCliUsageError ? 2 : 1;
|
|
@@ -7349,9 +7653,9 @@ export async function runTenderCli(args, io = {
|
|
|
7349
7653
|
}
|
|
7350
7654
|
const currentFile = fileURLToPath(import.meta.url);
|
|
7351
7655
|
function hasFlagValue(args, flag, value) {
|
|
7352
|
-
return args.some((arg, index) => arg === flag && args[index + 1] === value);
|
|
7656
|
+
return args.some((arg, index) => (arg === flag && args[index + 1] === value) || arg === `${flag}=${value}`);
|
|
7353
7657
|
}
|
|
7354
|
-
function shouldReadEntrypointStdin(args) {
|
|
7658
|
+
export function shouldReadEntrypointStdin(args) {
|
|
7355
7659
|
return (args[0] === "app" &&
|
|
7356
7660
|
((args[1] === "git" && args[2] === "credential") ||
|
|
7357
7661
|
(args[1] === "analytics" && hasFlagValue(args, "--spec", "-")) ||
|