@amerged/ohmyhost-cli 0.1.40 → 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-MRBUGDRW.js → chunk-HBM2X2MV.js} +1626 -259
- package/dist/index.js +5 -3
- package/dist/licenses/pgcf-bridge-NOTICE +1 -1
- package/package.json +1 -1
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +440 -40
- package/src/apps/product-cli/src/command.ts +492 -19
- package/src/apps/product-cli/src/composition.ts +6 -3
- package/src/apps/product-cli/src/product-api.ts +366 -13
- package/src/apps/product-cli/src/runtime-contract.ts +1 -10
- package/src/packages/contracts/package.json +5 -0
- package/src/packages/contracts/src/credit-pricing.ts +78 -50
- 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/feedback.ts +0 -5
- package/src/packages/contracts/src/problem-policy.ts +28 -0
- package/src/packages/postgres-bridge/NOTICE +1 -1
- 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 +702 -10
- package/src/packages/sdk-ts/src/generated/types.gen.ts +1205 -49
|
@@ -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,
|
|
@@ -199,8 +210,6 @@ export type ProductCliCommand =
|
|
|
199
210
|
| {
|
|
200
211
|
readonly kind: "credits-usage";
|
|
201
212
|
readonly organizationId: string;
|
|
202
|
-
readonly month: string;
|
|
203
|
-
readonly cursor?: string;
|
|
204
213
|
readonly credentialStore: "native";
|
|
205
214
|
}
|
|
206
215
|
| {
|
|
@@ -395,6 +404,124 @@ export type ProductCliCommand =
|
|
|
395
404
|
readonly yes: true;
|
|
396
405
|
readonly credentialStore: "native";
|
|
397
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
|
+
}
|
|
398
525
|
| {
|
|
399
526
|
readonly kind: "database-psql";
|
|
400
527
|
readonly projectId: string;
|
|
@@ -876,6 +1003,20 @@ export type RecognizedCommandLabel =
|
|
|
876
1003
|
| "database access create"
|
|
877
1004
|
| "database access list"
|
|
878
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"
|
|
879
1020
|
| "database psql"
|
|
880
1021
|
| "link"
|
|
881
1022
|
| "source auto-deploy set"
|
|
@@ -1033,6 +1174,24 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
1033
1174
|
if (values[1] === "list") return "database access list";
|
|
1034
1175
|
if (values[1] === "revoke") return "database access revoke";
|
|
1035
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";
|
|
1036
1195
|
if (value === "database" && values[0] === "psql") return "database psql";
|
|
1037
1196
|
if (value === "link" || value === "plan" || value === "deploy" || value === "logs")
|
|
1038
1197
|
return value;
|
|
@@ -1109,6 +1268,9 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
1109
1268
|
return "unknown";
|
|
1110
1269
|
};
|
|
1111
1270
|
|
|
1271
|
+
/** `database schedule runs --limit` is at most 50 entries, the route's own maximum. */
|
|
1272
|
+
const SCHEDULE_RUNS_MAX_ITEMS = 50;
|
|
1273
|
+
|
|
1112
1274
|
export const parseProductCliCommand = (argv: readonly string[]): ProductCliCommand => {
|
|
1113
1275
|
const values = [...argv];
|
|
1114
1276
|
removeFlag(values, "--json");
|
|
@@ -1116,10 +1278,12 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1116
1278
|
if ((values.length === 1 && values[0] === "help") || values.length === 0) {
|
|
1117
1279
|
return { kind: "help" };
|
|
1118
1280
|
}
|
|
1281
|
+
// `help database` is the same request as `database --help`.
|
|
1282
|
+
if (values[0] === "help") return parseProductCliCommand([...values.slice(1), "--help"]);
|
|
1119
1283
|
if (help) {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
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();
|
|
1123
1287
|
return { kind: "help", topic };
|
|
1124
1288
|
}
|
|
1125
1289
|
if (values.length === 1 && (values[0] === "--version" || values[0] === "version")) {
|
|
@@ -1407,20 +1571,8 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1407
1571
|
if (first === "credits" && values[0] === "usage") {
|
|
1408
1572
|
values.shift();
|
|
1409
1573
|
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1410
|
-
const options =
|
|
1411
|
-
|
|
1412
|
-
!options["--organization"] ||
|
|
1413
|
-
!options["--month"] ||
|
|
1414
|
-
!/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(options["--month"])
|
|
1415
|
-
)
|
|
1416
|
-
throw new InvalidCommandError();
|
|
1417
|
-
return {
|
|
1418
|
-
kind: "credits-usage",
|
|
1419
|
-
organizationId: options["--organization"],
|
|
1420
|
-
month: options["--month"],
|
|
1421
|
-
...(options["--cursor"] ? { cursor: options["--cursor"] } : {}),
|
|
1422
|
-
credentialStore,
|
|
1423
|
-
};
|
|
1574
|
+
const options = parseOptions(values, ["--organization"]);
|
|
1575
|
+
return { kind: "credits-usage", organizationId: options["--organization"], credentialStore };
|
|
1424
1576
|
}
|
|
1425
1577
|
if (first === "credits" && values[0] === "account") {
|
|
1426
1578
|
values.shift();
|
|
@@ -1911,6 +2063,318 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1911
2063
|
}
|
|
1912
2064
|
throw new InvalidCommandError();
|
|
1913
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
|
+
}
|
|
1914
2378
|
if (first === "database" && values[0] === "psql") {
|
|
1915
2379
|
values.shift();
|
|
1916
2380
|
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
@@ -2560,6 +3024,15 @@ const handedAccount = (
|
|
|
2560
3024
|
const isValue = (value: string | undefined): value is string =>
|
|
2561
3025
|
value !== undefined && value.length > 0 && !value.startsWith("--");
|
|
2562
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
|
+
|
|
2563
3036
|
const validGithubBranchName = (value: string): boolean =>
|
|
2564
3037
|
!(
|
|
2565
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;
|