@amerged/ohmyhost-cli 0.1.41 → 0.1.42
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 +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-SB6RMO3M.js → chunk-HBM2X2MV.js} +1592 -214
- package/dist/index.js +5 -3
- package/package.json +1 -1
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +438 -38
- package/src/apps/product-cli/src/command.ts +490 -3
- package/src/apps/product-cli/src/composition.ts +6 -3
- package/src/apps/product-cli/src/product-api.ts +363 -0
- package/src/packages/contracts/package.json +5 -0
- package/src/packages/contracts/src/database-access.ts +24 -45
- package/src/packages/contracts/src/database-events.ts +697 -0
- package/src/packages/contracts/src/problem-policy.ts +28 -0
- package/src/packages/postgres-bridge/src/bridge.ts +0 -4
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/index.ts +109 -0
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +696 -0
- package/src/packages/sdk-ts/src/generated/types.gen.ts +1153 -25
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { isUserSecretName } from "@ohmyhost/contracts/secret-names";
|
|
2
|
+
import {
|
|
3
|
+
DATABASE_PAGE_MAX_ITEMS,
|
|
4
|
+
parseDatabaseCursor,
|
|
5
|
+
parseDatabaseDeliveryId,
|
|
6
|
+
parseDatabaseListLimit,
|
|
7
|
+
parseDatabaseScheduleName,
|
|
8
|
+
parseDatabaseUsageWindow,
|
|
9
|
+
parseDatabaseWebhookCreateRequest,
|
|
10
|
+
parseDatabaseWebhookId,
|
|
11
|
+
type DatabaseWebhookEventType,
|
|
12
|
+
} from "@ohmyhost/contracts/database-events";
|
|
2
13
|
import {
|
|
3
14
|
databaseSizeForMemory,
|
|
4
15
|
type DatabaseComputeSelection,
|
|
@@ -393,6 +404,124 @@ export type ProductCliCommand =
|
|
|
393
404
|
readonly yes: true;
|
|
394
405
|
readonly credentialStore: "native";
|
|
395
406
|
}
|
|
407
|
+
| {
|
|
408
|
+
readonly kind: "database-webhook-create";
|
|
409
|
+
readonly projectId: string;
|
|
410
|
+
readonly environment: "dev" | "prod";
|
|
411
|
+
readonly url: string;
|
|
412
|
+
readonly eventTypes: readonly DatabaseWebhookEventType[];
|
|
413
|
+
readonly headersFile: string | null;
|
|
414
|
+
readonly idempotencyKey: string;
|
|
415
|
+
readonly yes: true;
|
|
416
|
+
readonly credentialStore: "native";
|
|
417
|
+
}
|
|
418
|
+
| {
|
|
419
|
+
readonly kind: "database-webhook-list";
|
|
420
|
+
readonly projectId: string;
|
|
421
|
+
readonly environment: "dev" | "prod";
|
|
422
|
+
readonly credentialStore: "native";
|
|
423
|
+
}
|
|
424
|
+
| {
|
|
425
|
+
readonly kind: "database-webhook-get";
|
|
426
|
+
readonly projectId: string;
|
|
427
|
+
readonly environment: "dev" | "prod";
|
|
428
|
+
readonly webhookId: string;
|
|
429
|
+
readonly credentialStore: "native";
|
|
430
|
+
}
|
|
431
|
+
| {
|
|
432
|
+
readonly kind: "database-webhook-delete";
|
|
433
|
+
readonly projectId: string;
|
|
434
|
+
readonly environment: "dev" | "prod";
|
|
435
|
+
readonly webhookId: string;
|
|
436
|
+
readonly yes: true;
|
|
437
|
+
readonly credentialStore: "native";
|
|
438
|
+
}
|
|
439
|
+
| {
|
|
440
|
+
readonly kind: "database-webhook-test";
|
|
441
|
+
readonly projectId: string;
|
|
442
|
+
readonly environment: "dev" | "prod";
|
|
443
|
+
readonly webhookId: string;
|
|
444
|
+
readonly yes: true;
|
|
445
|
+
readonly credentialStore: "native";
|
|
446
|
+
}
|
|
447
|
+
| {
|
|
448
|
+
readonly kind: "database-webhook-deliveries";
|
|
449
|
+
readonly projectId: string;
|
|
450
|
+
readonly environment: "dev" | "prod";
|
|
451
|
+
readonly webhookId: string | null;
|
|
452
|
+
readonly limit: number | null;
|
|
453
|
+
readonly cursor: string | null;
|
|
454
|
+
readonly credentialStore: "native";
|
|
455
|
+
}
|
|
456
|
+
| {
|
|
457
|
+
readonly kind: "database-webhook-replay";
|
|
458
|
+
readonly projectId: string;
|
|
459
|
+
readonly environment: "dev" | "prod";
|
|
460
|
+
readonly deliveryId: string;
|
|
461
|
+
readonly yes: true;
|
|
462
|
+
readonly credentialStore: "native";
|
|
463
|
+
}
|
|
464
|
+
| {
|
|
465
|
+
readonly kind: "database-schedule-set";
|
|
466
|
+
readonly projectId: string;
|
|
467
|
+
readonly environment: "dev" | "prod";
|
|
468
|
+
readonly name: string;
|
|
469
|
+
readonly cron: string | null;
|
|
470
|
+
readonly everySeconds: number | null;
|
|
471
|
+
readonly statementsFile: string;
|
|
472
|
+
readonly timeoutMs: number | null;
|
|
473
|
+
readonly enabled: boolean | null;
|
|
474
|
+
readonly yes: true;
|
|
475
|
+
readonly credentialStore: "native";
|
|
476
|
+
}
|
|
477
|
+
| {
|
|
478
|
+
readonly kind: "database-schedule-list";
|
|
479
|
+
readonly projectId: string;
|
|
480
|
+
readonly environment: "dev" | "prod";
|
|
481
|
+
readonly credentialStore: "native";
|
|
482
|
+
}
|
|
483
|
+
| {
|
|
484
|
+
readonly kind: "database-schedule-get";
|
|
485
|
+
readonly projectId: string;
|
|
486
|
+
readonly environment: "dev" | "prod";
|
|
487
|
+
readonly name: string;
|
|
488
|
+
readonly credentialStore: "native";
|
|
489
|
+
}
|
|
490
|
+
| {
|
|
491
|
+
readonly kind: "database-schedule-delete";
|
|
492
|
+
readonly projectId: string;
|
|
493
|
+
readonly environment: "dev" | "prod";
|
|
494
|
+
readonly name: string;
|
|
495
|
+
readonly yes: true;
|
|
496
|
+
readonly credentialStore: "native";
|
|
497
|
+
}
|
|
498
|
+
| {
|
|
499
|
+
readonly kind: "database-schedule-runs";
|
|
500
|
+
readonly projectId: string;
|
|
501
|
+
readonly environment: "dev" | "prod";
|
|
502
|
+
readonly name: string;
|
|
503
|
+
readonly limit: number | null;
|
|
504
|
+
readonly credentialStore: "native";
|
|
505
|
+
}
|
|
506
|
+
| {
|
|
507
|
+
readonly kind: "database-schedule-run";
|
|
508
|
+
readonly projectId: string;
|
|
509
|
+
readonly environment: "dev" | "prod";
|
|
510
|
+
readonly name: string;
|
|
511
|
+
readonly yes: true;
|
|
512
|
+
readonly credentialStore: "native";
|
|
513
|
+
}
|
|
514
|
+
| {
|
|
515
|
+
readonly kind: "database-executions";
|
|
516
|
+
readonly projectId: string;
|
|
517
|
+
readonly environment: "dev" | "prod";
|
|
518
|
+
readonly from: string;
|
|
519
|
+
readonly to: string;
|
|
520
|
+
readonly granularity: "hour" | "day";
|
|
521
|
+
readonly limit: number | null;
|
|
522
|
+
readonly cursor: string | null;
|
|
523
|
+
readonly credentialStore: "native";
|
|
524
|
+
}
|
|
396
525
|
| {
|
|
397
526
|
readonly kind: "database-psql";
|
|
398
527
|
readonly projectId: string;
|
|
@@ -874,6 +1003,20 @@ export type RecognizedCommandLabel =
|
|
|
874
1003
|
| "database access create"
|
|
875
1004
|
| "database access list"
|
|
876
1005
|
| "database access revoke"
|
|
1006
|
+
| "database webhook create"
|
|
1007
|
+
| "database webhook list"
|
|
1008
|
+
| "database webhook get"
|
|
1009
|
+
| "database webhook delete"
|
|
1010
|
+
| "database webhook test"
|
|
1011
|
+
| "database webhook deliveries"
|
|
1012
|
+
| "database webhook replay"
|
|
1013
|
+
| "database schedule set"
|
|
1014
|
+
| "database schedule list"
|
|
1015
|
+
| "database schedule get"
|
|
1016
|
+
| "database schedule delete"
|
|
1017
|
+
| "database schedule runs"
|
|
1018
|
+
| "database schedule run"
|
|
1019
|
+
| "database executions"
|
|
877
1020
|
| "database psql"
|
|
878
1021
|
| "link"
|
|
879
1022
|
| "source auto-deploy set"
|
|
@@ -1031,6 +1174,24 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
1031
1174
|
if (values[1] === "list") return "database access list";
|
|
1032
1175
|
if (values[1] === "revoke") return "database access revoke";
|
|
1033
1176
|
}
|
|
1177
|
+
if (value === "database" && values[0] === "webhook") {
|
|
1178
|
+
if (values[1] === "create") return "database webhook create";
|
|
1179
|
+
if (values[1] === "list") return "database webhook list";
|
|
1180
|
+
if (values[1] === "get") return "database webhook get";
|
|
1181
|
+
if (values[1] === "delete") return "database webhook delete";
|
|
1182
|
+
if (values[1] === "test") return "database webhook test";
|
|
1183
|
+
if (values[1] === "deliveries") return "database webhook deliveries";
|
|
1184
|
+
if (values[1] === "replay") return "database webhook replay";
|
|
1185
|
+
}
|
|
1186
|
+
if (value === "database" && values[0] === "schedule") {
|
|
1187
|
+
if (values[1] === "set") return "database schedule set";
|
|
1188
|
+
if (values[1] === "list") return "database schedule list";
|
|
1189
|
+
if (values[1] === "get") return "database schedule get";
|
|
1190
|
+
if (values[1] === "delete") return "database schedule delete";
|
|
1191
|
+
if (values[1] === "runs") return "database schedule runs";
|
|
1192
|
+
if (values[1] === "run") return "database schedule run";
|
|
1193
|
+
}
|
|
1194
|
+
if (value === "database" && values[0] === "executions") return "database executions";
|
|
1034
1195
|
if (value === "database" && values[0] === "psql") return "database psql";
|
|
1035
1196
|
if (value === "link" || value === "plan" || value === "deploy" || value === "logs")
|
|
1036
1197
|
return value;
|
|
@@ -1107,6 +1268,9 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
1107
1268
|
return "unknown";
|
|
1108
1269
|
};
|
|
1109
1270
|
|
|
1271
|
+
/** `database schedule runs --limit` is at most 50 entries, the route's own maximum. */
|
|
1272
|
+
const SCHEDULE_RUNS_MAX_ITEMS = 50;
|
|
1273
|
+
|
|
1110
1274
|
export const parseProductCliCommand = (argv: readonly string[]): ProductCliCommand => {
|
|
1111
1275
|
const values = [...argv];
|
|
1112
1276
|
removeFlag(values, "--json");
|
|
@@ -1114,10 +1278,12 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1114
1278
|
if ((values.length === 1 && values[0] === "help") || values.length === 0) {
|
|
1115
1279
|
return { kind: "help" };
|
|
1116
1280
|
}
|
|
1281
|
+
// `help database` is the same request as `database --help`.
|
|
1282
|
+
if (values[0] === "help") return parseProductCliCommand([...values.slice(1), "--help"]);
|
|
1117
1283
|
if (help) {
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1284
|
+
// The topic is only checked for shape here; the CLI answers unknown topics with invalid_command.
|
|
1285
|
+
const topic = values.join(" ");
|
|
1286
|
+
if (!/^[a-z][a-z0-9 -]*$/u.test(topic) || topic === "version") throw new InvalidCommandError();
|
|
1121
1287
|
return { kind: "help", topic };
|
|
1122
1288
|
}
|
|
1123
1289
|
if (values.length === 1 && (values[0] === "--version" || values[0] === "version")) {
|
|
@@ -1897,6 +2063,318 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1897
2063
|
}
|
|
1898
2064
|
throw new InvalidCommandError();
|
|
1899
2065
|
}
|
|
2066
|
+
if (first === "database" && values[0] === "webhook") {
|
|
2067
|
+
values.shift();
|
|
2068
|
+
const subcommand = values.shift();
|
|
2069
|
+
if (subcommand === "create") {
|
|
2070
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2071
|
+
const options = parseOptionalOptions(values, [
|
|
2072
|
+
"--project",
|
|
2073
|
+
"--environment",
|
|
2074
|
+
"--url",
|
|
2075
|
+
"--event-types",
|
|
2076
|
+
"--headers-file",
|
|
2077
|
+
"--idempotency-key",
|
|
2078
|
+
]);
|
|
2079
|
+
const projectId = options["--project"],
|
|
2080
|
+
environment = options["--environment"],
|
|
2081
|
+
url = options["--url"],
|
|
2082
|
+
eventTypes = options["--event-types"],
|
|
2083
|
+
headersFile = options["--headers-file"],
|
|
2084
|
+
idempotencyKey = options["--idempotency-key"];
|
|
2085
|
+
if (
|
|
2086
|
+
!isValue(projectId) ||
|
|
2087
|
+
!isValue(idempotencyKey) ||
|
|
2088
|
+
!isValue(url) ||
|
|
2089
|
+
!isValue(eventTypes) ||
|
|
2090
|
+
(headersFile !== undefined && !isValue(headersFile)) ||
|
|
2091
|
+
(environment !== "dev" && environment !== "prod")
|
|
2092
|
+
)
|
|
2093
|
+
throw new InvalidCommandError();
|
|
2094
|
+
const request = contractValue(() =>
|
|
2095
|
+
parseDatabaseWebhookCreateRequest({ url, event_types: eventTypes.split(",") }),
|
|
2096
|
+
);
|
|
2097
|
+
return {
|
|
2098
|
+
kind: "database-webhook-create",
|
|
2099
|
+
projectId,
|
|
2100
|
+
environment,
|
|
2101
|
+
url: request.url,
|
|
2102
|
+
eventTypes: request.event_types,
|
|
2103
|
+
headersFile: headersFile ?? null,
|
|
2104
|
+
idempotencyKey,
|
|
2105
|
+
yes: true,
|
|
2106
|
+
credentialStore,
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
if (subcommand === "list") {
|
|
2110
|
+
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2111
|
+
const options = parseOptionalOptions(values, ["--project", "--environment"]);
|
|
2112
|
+
const projectId = options["--project"],
|
|
2113
|
+
environment = options["--environment"] ?? "dev";
|
|
2114
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2115
|
+
throw new InvalidCommandError();
|
|
2116
|
+
return { kind: "database-webhook-list", projectId, environment, credentialStore };
|
|
2117
|
+
}
|
|
2118
|
+
if (subcommand === "get") {
|
|
2119
|
+
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2120
|
+
const options = parseOptionalOptions(values, ["--project", "--environment", "--webhook"]);
|
|
2121
|
+
const projectId = options["--project"],
|
|
2122
|
+
environment = options["--environment"] ?? "dev",
|
|
2123
|
+
webhookId = options["--webhook"];
|
|
2124
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2125
|
+
throw new InvalidCommandError();
|
|
2126
|
+
return {
|
|
2127
|
+
kind: "database-webhook-get",
|
|
2128
|
+
projectId,
|
|
2129
|
+
environment,
|
|
2130
|
+
webhookId: contractValue(() => parseDatabaseWebhookId(webhookId)),
|
|
2131
|
+
credentialStore,
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2134
|
+
if (subcommand === "delete" || subcommand === "test") {
|
|
2135
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2136
|
+
const options = parseOptionalOptions(values, ["--project", "--environment", "--webhook"]);
|
|
2137
|
+
const projectId = options["--project"],
|
|
2138
|
+
environment = options["--environment"],
|
|
2139
|
+
webhookId = options["--webhook"];
|
|
2140
|
+
if (!isValue(projectId)) throw new InvalidCommandError();
|
|
2141
|
+
if (environment !== "dev" && environment !== "prod") throw new InvalidCommandError();
|
|
2142
|
+
const target = contractValue(() => parseDatabaseWebhookId(webhookId));
|
|
2143
|
+
if (subcommand === "delete")
|
|
2144
|
+
return {
|
|
2145
|
+
kind: "database-webhook-delete",
|
|
2146
|
+
projectId,
|
|
2147
|
+
environment,
|
|
2148
|
+
webhookId: target,
|
|
2149
|
+
yes: true,
|
|
2150
|
+
credentialStore,
|
|
2151
|
+
};
|
|
2152
|
+
return {
|
|
2153
|
+
kind: "database-webhook-test",
|
|
2154
|
+
projectId,
|
|
2155
|
+
environment,
|
|
2156
|
+
webhookId: target,
|
|
2157
|
+
yes: true,
|
|
2158
|
+
credentialStore,
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
if (subcommand === "deliveries") {
|
|
2162
|
+
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2163
|
+
const options = parseOptionalOptions(values, [
|
|
2164
|
+
"--project",
|
|
2165
|
+
"--environment",
|
|
2166
|
+
"--webhook",
|
|
2167
|
+
"--limit",
|
|
2168
|
+
"--cursor",
|
|
2169
|
+
]);
|
|
2170
|
+
const projectId = options["--project"],
|
|
2171
|
+
environment = options["--environment"] ?? "dev",
|
|
2172
|
+
webhookId = options["--webhook"],
|
|
2173
|
+
limit = options["--limit"],
|
|
2174
|
+
cursor = options["--cursor"];
|
|
2175
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2176
|
+
throw new InvalidCommandError();
|
|
2177
|
+
return {
|
|
2178
|
+
kind: "database-webhook-deliveries",
|
|
2179
|
+
projectId,
|
|
2180
|
+
environment,
|
|
2181
|
+
webhookId:
|
|
2182
|
+
webhookId === undefined ? null : contractValue(() => parseDatabaseWebhookId(webhookId)),
|
|
2183
|
+
limit:
|
|
2184
|
+
limit === undefined
|
|
2185
|
+
? null
|
|
2186
|
+
: contractValue(() =>
|
|
2187
|
+
parseDatabaseListLimit(limit, DATABASE_PAGE_MAX_ITEMS, DATABASE_PAGE_MAX_ITEMS),
|
|
2188
|
+
),
|
|
2189
|
+
cursor: contractValue(() => parseDatabaseCursor(cursor)),
|
|
2190
|
+
credentialStore,
|
|
2191
|
+
};
|
|
2192
|
+
}
|
|
2193
|
+
if (subcommand === "replay") {
|
|
2194
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2195
|
+
const options = parseOptionalOptions(values, ["--project", "--environment", "--delivery"]);
|
|
2196
|
+
const projectId = options["--project"],
|
|
2197
|
+
environment = options["--environment"],
|
|
2198
|
+
deliveryId = options["--delivery"];
|
|
2199
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2200
|
+
throw new InvalidCommandError();
|
|
2201
|
+
return {
|
|
2202
|
+
kind: "database-webhook-replay",
|
|
2203
|
+
projectId,
|
|
2204
|
+
environment,
|
|
2205
|
+
deliveryId: contractValue(() => parseDatabaseDeliveryId(deliveryId)),
|
|
2206
|
+
yes: true,
|
|
2207
|
+
credentialStore,
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
2210
|
+
throw new InvalidCommandError();
|
|
2211
|
+
}
|
|
2212
|
+
if (first === "database" && values[0] === "schedule") {
|
|
2213
|
+
values.shift();
|
|
2214
|
+
const subcommand = values.shift();
|
|
2215
|
+
if (subcommand === "set") {
|
|
2216
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2217
|
+
const options = parseOptionalOptions(values, [
|
|
2218
|
+
"--project",
|
|
2219
|
+
"--environment",
|
|
2220
|
+
"--name",
|
|
2221
|
+
"--cron",
|
|
2222
|
+
"--every-seconds",
|
|
2223
|
+
"--statements-file",
|
|
2224
|
+
"--timeout-ms",
|
|
2225
|
+
"--enabled",
|
|
2226
|
+
]);
|
|
2227
|
+
const projectId = options["--project"],
|
|
2228
|
+
environment = options["--environment"],
|
|
2229
|
+
name = options["--name"],
|
|
2230
|
+
cron = options["--cron"],
|
|
2231
|
+
everySeconds = options["--every-seconds"],
|
|
2232
|
+
statementsFile = options["--statements-file"],
|
|
2233
|
+
timeoutMs = options["--timeout-ms"],
|
|
2234
|
+
enabled = options["--enabled"];
|
|
2235
|
+
if (
|
|
2236
|
+
!isValue(projectId) ||
|
|
2237
|
+
!isValue(statementsFile) ||
|
|
2238
|
+
(environment !== "dev" && environment !== "prod") ||
|
|
2239
|
+
(cron === undefined) === (everySeconds === undefined) ||
|
|
2240
|
+
(everySeconds !== undefined && !/^[0-9]{1,9}$/u.test(everySeconds)) ||
|
|
2241
|
+
(timeoutMs !== undefined && !/^[0-9]{1,6}$/u.test(timeoutMs)) ||
|
|
2242
|
+
(enabled !== undefined && enabled !== "true" && enabled !== "false")
|
|
2243
|
+
)
|
|
2244
|
+
throw new InvalidCommandError();
|
|
2245
|
+
return {
|
|
2246
|
+
kind: "database-schedule-set",
|
|
2247
|
+
projectId,
|
|
2248
|
+
environment,
|
|
2249
|
+
name: contractValue(() => parseDatabaseScheduleName(name)),
|
|
2250
|
+
cron: cron ?? null,
|
|
2251
|
+
everySeconds: everySeconds === undefined ? null : Number(everySeconds),
|
|
2252
|
+
statementsFile,
|
|
2253
|
+
timeoutMs: timeoutMs === undefined ? null : Number(timeoutMs),
|
|
2254
|
+
enabled: enabled === undefined ? null : enabled === "true",
|
|
2255
|
+
yes: true,
|
|
2256
|
+
credentialStore,
|
|
2257
|
+
};
|
|
2258
|
+
}
|
|
2259
|
+
if (subcommand === "list") {
|
|
2260
|
+
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2261
|
+
const options = parseOptionalOptions(values, ["--project", "--environment"]);
|
|
2262
|
+
const projectId = options["--project"],
|
|
2263
|
+
environment = options["--environment"] ?? "dev";
|
|
2264
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2265
|
+
throw new InvalidCommandError();
|
|
2266
|
+
return { kind: "database-schedule-list", projectId, environment, credentialStore };
|
|
2267
|
+
}
|
|
2268
|
+
if (subcommand === "get" || subcommand === "runs") {
|
|
2269
|
+
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2270
|
+
const options = parseOptionalOptions(
|
|
2271
|
+
values,
|
|
2272
|
+
subcommand === "get"
|
|
2273
|
+
? ["--project", "--environment", "--name"]
|
|
2274
|
+
: ["--project", "--environment", "--name", "--limit"],
|
|
2275
|
+
);
|
|
2276
|
+
const projectId = options["--project"],
|
|
2277
|
+
environment = options["--environment"] ?? "dev",
|
|
2278
|
+
name = options["--name"],
|
|
2279
|
+
limit = options["--limit"];
|
|
2280
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2281
|
+
throw new InvalidCommandError();
|
|
2282
|
+
const scheduleName = contractValue(() => parseDatabaseScheduleName(name));
|
|
2283
|
+
if (subcommand === "get")
|
|
2284
|
+
return {
|
|
2285
|
+
kind: "database-schedule-get",
|
|
2286
|
+
projectId,
|
|
2287
|
+
environment,
|
|
2288
|
+
name: scheduleName,
|
|
2289
|
+
credentialStore,
|
|
2290
|
+
};
|
|
2291
|
+
return {
|
|
2292
|
+
kind: "database-schedule-runs",
|
|
2293
|
+
projectId,
|
|
2294
|
+
environment,
|
|
2295
|
+
name: scheduleName,
|
|
2296
|
+
limit:
|
|
2297
|
+
limit === undefined
|
|
2298
|
+
? null
|
|
2299
|
+
: contractValue(() =>
|
|
2300
|
+
parseDatabaseListLimit(limit, SCHEDULE_RUNS_MAX_ITEMS, SCHEDULE_RUNS_MAX_ITEMS),
|
|
2301
|
+
),
|
|
2302
|
+
credentialStore,
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
if (subcommand === "delete" || subcommand === "run") {
|
|
2306
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2307
|
+
const options = parseOptionalOptions(values, ["--project", "--environment", "--name"]);
|
|
2308
|
+
const projectId = options["--project"],
|
|
2309
|
+
environment = options["--environment"];
|
|
2310
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2311
|
+
throw new InvalidCommandError();
|
|
2312
|
+
const name = contractValue(() => parseDatabaseScheduleName(options["--name"]));
|
|
2313
|
+
return subcommand === "delete"
|
|
2314
|
+
? {
|
|
2315
|
+
kind: "database-schedule-delete",
|
|
2316
|
+
projectId,
|
|
2317
|
+
environment,
|
|
2318
|
+
name,
|
|
2319
|
+
yes: true,
|
|
2320
|
+
credentialStore,
|
|
2321
|
+
}
|
|
2322
|
+
: {
|
|
2323
|
+
kind: "database-schedule-run",
|
|
2324
|
+
projectId,
|
|
2325
|
+
environment,
|
|
2326
|
+
name,
|
|
2327
|
+
yes: true,
|
|
2328
|
+
credentialStore,
|
|
2329
|
+
};
|
|
2330
|
+
}
|
|
2331
|
+
throw new InvalidCommandError();
|
|
2332
|
+
}
|
|
2333
|
+
if (first === "database" && values[0] === "executions") {
|
|
2334
|
+
values.shift();
|
|
2335
|
+
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2336
|
+
const options = parseOptionalOptions(values, [
|
|
2337
|
+
"--project",
|
|
2338
|
+
"--environment",
|
|
2339
|
+
"--from",
|
|
2340
|
+
"--to",
|
|
2341
|
+
"--granularity",
|
|
2342
|
+
"--limit",
|
|
2343
|
+
"--cursor",
|
|
2344
|
+
]);
|
|
2345
|
+
const projectId = options["--project"],
|
|
2346
|
+
environment = options["--environment"] ?? "dev",
|
|
2347
|
+
from = options["--from"],
|
|
2348
|
+
to = options["--to"],
|
|
2349
|
+
granularity = options["--granularity"],
|
|
2350
|
+
limit = options["--limit"],
|
|
2351
|
+
cursor = options["--cursor"];
|
|
2352
|
+
if (
|
|
2353
|
+
!isValue(projectId) ||
|
|
2354
|
+
(environment !== "dev" && environment !== "prod") ||
|
|
2355
|
+
!isValue(from) ||
|
|
2356
|
+
!isValue(to) ||
|
|
2357
|
+
(granularity !== "hour" && granularity !== "day")
|
|
2358
|
+
)
|
|
2359
|
+
throw new InvalidCommandError();
|
|
2360
|
+
const window = contractValue(() => parseDatabaseUsageWindow(from, to, granularity));
|
|
2361
|
+
return {
|
|
2362
|
+
kind: "database-executions",
|
|
2363
|
+
projectId,
|
|
2364
|
+
environment,
|
|
2365
|
+
from: window.from,
|
|
2366
|
+
to: window.to,
|
|
2367
|
+
granularity: window.granularity,
|
|
2368
|
+
limit:
|
|
2369
|
+
limit === undefined
|
|
2370
|
+
? null
|
|
2371
|
+
: contractValue(() =>
|
|
2372
|
+
parseDatabaseListLimit(limit, DATABASE_PAGE_MAX_ITEMS, DATABASE_PAGE_MAX_ITEMS),
|
|
2373
|
+
),
|
|
2374
|
+
cursor: contractValue(() => parseDatabaseCursor(cursor)),
|
|
2375
|
+
credentialStore,
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
1900
2378
|
if (first === "database" && values[0] === "psql") {
|
|
1901
2379
|
values.shift();
|
|
1902
2380
|
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
@@ -2546,6 +3024,15 @@ const handedAccount = (
|
|
|
2546
3024
|
const isValue = (value: string | undefined): value is string =>
|
|
2547
3025
|
value !== undefined && value.length > 0 && !value.startsWith("--");
|
|
2548
3026
|
|
|
3027
|
+
/** A value the contract refuses, or one that is missing, is an invalid command. */
|
|
3028
|
+
const contractValue = <T>(parse: () => T): T => {
|
|
3029
|
+
try {
|
|
3030
|
+
return parse();
|
|
3031
|
+
} catch {
|
|
3032
|
+
throw new InvalidCommandError();
|
|
3033
|
+
}
|
|
3034
|
+
};
|
|
3035
|
+
|
|
2549
3036
|
const validGithubBranchName = (value: string): boolean =>
|
|
2550
3037
|
!(
|
|
2551
3038
|
value.length < 1 ||
|
|
@@ -29,7 +29,8 @@ import {
|
|
|
29
29
|
cliMetadataResult,
|
|
30
30
|
CREDENTIAL_STORE_UNAVAILABLE_ACTION,
|
|
31
31
|
endedLoginAction,
|
|
32
|
-
|
|
32
|
+
helpTopicKnown,
|
|
33
|
+
internalErrorAction,
|
|
33
34
|
invalidCommandAction,
|
|
34
35
|
refreshFailedAction,
|
|
35
36
|
NetworkTransportError,
|
|
@@ -642,7 +643,7 @@ export const runProductionCli = async (
|
|
|
642
643
|
1,
|
|
643
644
|
"internal_error",
|
|
644
645
|
false,
|
|
645
|
-
|
|
646
|
+
internalErrorAction(recognizedCommandLabel(args)),
|
|
646
647
|
);
|
|
647
648
|
if (!(error instanceof InvalidCommandError)) {
|
|
648
649
|
diagnostics.record({
|
|
@@ -683,6 +684,8 @@ export const runProductionCli = async (
|
|
|
683
684
|
);
|
|
684
685
|
}
|
|
685
686
|
}
|
|
687
|
+
if (command.kind === "help" && command.topic !== undefined && !helpTopicKnown(command.topic))
|
|
688
|
+
return written(invalidCommandFailure(args, environment));
|
|
686
689
|
if (command.kind === "help" || command.kind === "version") {
|
|
687
690
|
return written(
|
|
688
691
|
cliMetadataResult(command.kind, command.kind === "help" ? command.topic : undefined),
|
|
@@ -1135,7 +1138,7 @@ const runOfflineInit = async (
|
|
|
1135
1138
|
exitCode,
|
|
1136
1139
|
code,
|
|
1137
1140
|
false,
|
|
1138
|
-
known ? initFailureAction(error) :
|
|
1141
|
+
known ? initFailureAction(error) : internalErrorAction("init"),
|
|
1139
1142
|
);
|
|
1140
1143
|
io.writeStdout(result.stdout);
|
|
1141
1144
|
return result.exitCode;
|