@amerged/ohmyhost-mcp 0.1.44 → 0.1.46
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/{chunk-NUWAJ4TH.js → chunk-2GRH5YCK.js} +6 -6
- package/dist/index.js +1 -1
- package/dist/stdio-main.js +586 -41
- package/package.json +1 -1
- package/src/apps/mcp/package.json +1 -1
- package/src/apps/mcp/src/local-client.ts +87 -0
- package/src/apps/mcp/src/local-server.ts +176 -4
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +137 -2
- package/src/apps/product-cli/src/command.ts +186 -2
- package/src/apps/product-cli/src/product-api.ts +202 -2
- package/src/packages/agent-skills/src/generated-skill-resources.ts +5 -5
- package/src/packages/contracts/package.json +5 -0
- package/src/packages/contracts/src/database-events.ts +208 -11
- package/src/packages/contracts/src/database-migration-admission.ts +22 -0
- package/src/packages/contracts/src/database-migration-capture.ts +177 -0
- package/src/packages/contracts/src/database-migration-lexical.ts +1 -0
- package/src/packages/contracts/src/database-tables.ts +317 -0
- package/src/packages/contracts/src/problem-policy.ts +50 -1
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/index.ts +37 -0
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +204 -0
- package/src/packages/sdk-ts/src/generated/types.gen.ts +407 -4
|
@@ -6,10 +6,17 @@ import {
|
|
|
6
6
|
parseDatabaseListLimit,
|
|
7
7
|
parseDatabaseScheduleName,
|
|
8
8
|
parseDatabaseUsageWindow,
|
|
9
|
+
parseDatabaseWatchCreateRequest,
|
|
10
|
+
parseDatabaseWatchId,
|
|
9
11
|
parseDatabaseWebhookCreateRequest,
|
|
10
12
|
parseDatabaseWebhookId,
|
|
11
|
-
type
|
|
13
|
+
type DatabaseWatchRequest,
|
|
14
|
+
type DatabaseWebhookEventPattern,
|
|
12
15
|
} from "@ohmyhost/contracts/database-events";
|
|
16
|
+
import {
|
|
17
|
+
DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS,
|
|
18
|
+
isDatabaseTableIdentifier,
|
|
19
|
+
} from "@ohmyhost/contracts/database-tables";
|
|
13
20
|
import {
|
|
14
21
|
databaseSizeForMemory,
|
|
15
22
|
type DatabaseComputeSelection,
|
|
@@ -404,12 +411,47 @@ export type ProductCliCommand =
|
|
|
404
411
|
readonly yes: true;
|
|
405
412
|
readonly credentialStore: "native";
|
|
406
413
|
}
|
|
414
|
+
| {
|
|
415
|
+
readonly kind: "database-watch-create";
|
|
416
|
+
readonly projectId: string;
|
|
417
|
+
readonly environment: "dev" | "prod";
|
|
418
|
+
readonly request: DatabaseWatchRequest;
|
|
419
|
+
readonly idempotencyKey: string;
|
|
420
|
+
readonly yes: true;
|
|
421
|
+
readonly credentialStore: "native";
|
|
422
|
+
}
|
|
423
|
+
| {
|
|
424
|
+
readonly kind: "database-table-create";
|
|
425
|
+
readonly projectId: string;
|
|
426
|
+
readonly environment: "dev" | "prod";
|
|
427
|
+
readonly table: string;
|
|
428
|
+
readonly columnsFile: string;
|
|
429
|
+
readonly primaryKey: readonly string[];
|
|
430
|
+
readonly idempotencyKey: string;
|
|
431
|
+
readonly yes: true;
|
|
432
|
+
readonly credentialStore: "native";
|
|
433
|
+
}
|
|
434
|
+
| {
|
|
435
|
+
readonly kind: "database-watch-list";
|
|
436
|
+
readonly projectId: string;
|
|
437
|
+
readonly environment: "dev" | "prod";
|
|
438
|
+
readonly credentialStore: "native";
|
|
439
|
+
}
|
|
440
|
+
| {
|
|
441
|
+
readonly kind: "database-watch-delete";
|
|
442
|
+
readonly projectId: string;
|
|
443
|
+
readonly environment: "dev" | "prod";
|
|
444
|
+
readonly watchId: string;
|
|
445
|
+
readonly idempotencyKey: string;
|
|
446
|
+
readonly yes: true;
|
|
447
|
+
readonly credentialStore: "native";
|
|
448
|
+
}
|
|
407
449
|
| {
|
|
408
450
|
readonly kind: "database-webhook-create";
|
|
409
451
|
readonly projectId: string;
|
|
410
452
|
readonly environment: "dev" | "prod";
|
|
411
453
|
readonly url: string;
|
|
412
|
-
readonly eventTypes: readonly
|
|
454
|
+
readonly eventTypes: readonly DatabaseWebhookEventPattern[];
|
|
413
455
|
readonly headersFile: string | null;
|
|
414
456
|
readonly idempotencyKey: string;
|
|
415
457
|
readonly yes: true;
|
|
@@ -1003,6 +1045,10 @@ export type RecognizedCommandLabel =
|
|
|
1003
1045
|
| "database access create"
|
|
1004
1046
|
| "database access list"
|
|
1005
1047
|
| "database access revoke"
|
|
1048
|
+
| "database watch create"
|
|
1049
|
+
| "database watch list"
|
|
1050
|
+
| "database watch delete"
|
|
1051
|
+
| "database table create"
|
|
1006
1052
|
| "database webhook create"
|
|
1007
1053
|
| "database webhook list"
|
|
1008
1054
|
| "database webhook get"
|
|
@@ -1174,6 +1220,13 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
1174
1220
|
if (values[1] === "list") return "database access list";
|
|
1175
1221
|
if (values[1] === "revoke") return "database access revoke";
|
|
1176
1222
|
}
|
|
1223
|
+
if (value === "database" && values[0] === "watch") {
|
|
1224
|
+
if (values[1] === "create") return "database watch create";
|
|
1225
|
+
if (values[1] === "list") return "database watch list";
|
|
1226
|
+
if (values[1] === "delete") return "database watch delete";
|
|
1227
|
+
}
|
|
1228
|
+
if (value === "database" && values[0] === "table" && values[1] === "create")
|
|
1229
|
+
return "database table create";
|
|
1177
1230
|
if (value === "database" && values[0] === "webhook") {
|
|
1178
1231
|
if (values[1] === "create") return "database webhook create";
|
|
1179
1232
|
if (values[1] === "list") return "database webhook list";
|
|
@@ -2063,6 +2116,137 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
2063
2116
|
}
|
|
2064
2117
|
throw new InvalidCommandError();
|
|
2065
2118
|
}
|
|
2119
|
+
if (first === "database" && values[0] === "watch") {
|
|
2120
|
+
values.shift();
|
|
2121
|
+
const subcommand = values.shift();
|
|
2122
|
+
if (subcommand === "create") {
|
|
2123
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2124
|
+
const options = parseOptionalOptions(values, [
|
|
2125
|
+
"--project",
|
|
2126
|
+
"--environment",
|
|
2127
|
+
"--table",
|
|
2128
|
+
"--schema",
|
|
2129
|
+
"--columns",
|
|
2130
|
+
"--operations",
|
|
2131
|
+
"--idempotency-key",
|
|
2132
|
+
]);
|
|
2133
|
+
const projectId = options["--project"],
|
|
2134
|
+
environment = options["--environment"],
|
|
2135
|
+
table = options["--table"],
|
|
2136
|
+
schema = options["--schema"],
|
|
2137
|
+
columns = options["--columns"],
|
|
2138
|
+
operations = options["--operations"],
|
|
2139
|
+
idempotencyKey = options["--idempotency-key"];
|
|
2140
|
+
if (
|
|
2141
|
+
!isValue(projectId) ||
|
|
2142
|
+
!isValue(idempotencyKey) ||
|
|
2143
|
+
!isValue(table) ||
|
|
2144
|
+
!isValue(columns) ||
|
|
2145
|
+
(environment !== "dev" && environment !== "prod")
|
|
2146
|
+
)
|
|
2147
|
+
throw new InvalidCommandError();
|
|
2148
|
+
const request = contractValue(() =>
|
|
2149
|
+
parseDatabaseWatchCreateRequest({
|
|
2150
|
+
schema,
|
|
2151
|
+
table,
|
|
2152
|
+
columns: columns.split(","),
|
|
2153
|
+
...(operations === undefined ? {} : { operations: operations.split(",") }),
|
|
2154
|
+
}),
|
|
2155
|
+
);
|
|
2156
|
+
return {
|
|
2157
|
+
kind: "database-watch-create",
|
|
2158
|
+
projectId,
|
|
2159
|
+
environment,
|
|
2160
|
+
request,
|
|
2161
|
+
idempotencyKey,
|
|
2162
|
+
yes: true,
|
|
2163
|
+
credentialStore,
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
if (subcommand === "list") {
|
|
2167
|
+
if (yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2168
|
+
const options = parseOptionalOptions(values, ["--project", "--environment"]);
|
|
2169
|
+
const projectId = options["--project"],
|
|
2170
|
+
environment = options["--environment"] ?? "dev";
|
|
2171
|
+
if (!isValue(projectId) || (environment !== "dev" && environment !== "prod"))
|
|
2172
|
+
throw new InvalidCommandError();
|
|
2173
|
+
return { kind: "database-watch-list", projectId, environment, credentialStore };
|
|
2174
|
+
}
|
|
2175
|
+
if (subcommand === "delete") {
|
|
2176
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2177
|
+
const options = parseOptionalOptions(values, [
|
|
2178
|
+
"--project",
|
|
2179
|
+
"--environment",
|
|
2180
|
+
"--watch",
|
|
2181
|
+
"--idempotency-key",
|
|
2182
|
+
]);
|
|
2183
|
+
const projectId = options["--project"],
|
|
2184
|
+
environment = options["--environment"],
|
|
2185
|
+
watchId = options["--watch"],
|
|
2186
|
+
idempotencyKey = options["--idempotency-key"];
|
|
2187
|
+
if (
|
|
2188
|
+
!isValue(projectId) ||
|
|
2189
|
+
!isValue(idempotencyKey) ||
|
|
2190
|
+
(environment !== "dev" && environment !== "prod")
|
|
2191
|
+
)
|
|
2192
|
+
throw new InvalidCommandError();
|
|
2193
|
+
return {
|
|
2194
|
+
kind: "database-watch-delete",
|
|
2195
|
+
projectId,
|
|
2196
|
+
environment,
|
|
2197
|
+
watchId: contractValue(() => parseDatabaseWatchId(watchId)),
|
|
2198
|
+
idempotencyKey,
|
|
2199
|
+
yes: true,
|
|
2200
|
+
credentialStore,
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
throw new InvalidCommandError();
|
|
2204
|
+
}
|
|
2205
|
+
if (first === "database" && values[0] === "table") {
|
|
2206
|
+
values.shift();
|
|
2207
|
+
const subcommand = values.shift();
|
|
2208
|
+
if (subcommand === "create") {
|
|
2209
|
+
if (!yes || wait || follow || revoke || stdin) throw new InvalidCommandError();
|
|
2210
|
+
const options = parseOptionalOptions(values, [
|
|
2211
|
+
"--project",
|
|
2212
|
+
"--environment",
|
|
2213
|
+
"--table",
|
|
2214
|
+
"--columns-file",
|
|
2215
|
+
"--primary-key",
|
|
2216
|
+
"--idempotency-key",
|
|
2217
|
+
]);
|
|
2218
|
+
const projectId = options["--project"],
|
|
2219
|
+
environment = options["--environment"],
|
|
2220
|
+
table = options["--table"],
|
|
2221
|
+
columnsFile = options["--columns-file"],
|
|
2222
|
+
primaryKey = options["--primary-key"],
|
|
2223
|
+
idempotencyKey = options["--idempotency-key"];
|
|
2224
|
+
const keyNames = primaryKey === undefined ? [] : primaryKey.split(",");
|
|
2225
|
+
if (
|
|
2226
|
+
!isValue(projectId) ||
|
|
2227
|
+
!isValue(idempotencyKey) ||
|
|
2228
|
+
!isValue(table) ||
|
|
2229
|
+
!isValue(columnsFile) ||
|
|
2230
|
+
(primaryKey !== undefined && !keyNames.every(isDatabaseTableIdentifier)) ||
|
|
2231
|
+
keyNames.length > DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS ||
|
|
2232
|
+
!isDatabaseTableIdentifier(table) ||
|
|
2233
|
+
(environment !== "dev" && environment !== "prod")
|
|
2234
|
+
)
|
|
2235
|
+
throw new InvalidCommandError();
|
|
2236
|
+
return {
|
|
2237
|
+
kind: "database-table-create",
|
|
2238
|
+
projectId,
|
|
2239
|
+
environment,
|
|
2240
|
+
table,
|
|
2241
|
+
columnsFile,
|
|
2242
|
+
primaryKey: keyNames,
|
|
2243
|
+
idempotencyKey,
|
|
2244
|
+
yes: true,
|
|
2245
|
+
credentialStore,
|
|
2246
|
+
};
|
|
2247
|
+
}
|
|
2248
|
+
throw new InvalidCommandError();
|
|
2249
|
+
}
|
|
2066
2250
|
if (first === "database" && values[0] === "webhook") {
|
|
2067
2251
|
values.shift();
|
|
2068
2252
|
const subcommand = values.shift();
|
|
@@ -20,6 +20,13 @@ import {
|
|
|
20
20
|
type ProjectDatabaseWriteReceipt,
|
|
21
21
|
} from "@ohmyhost/contracts/database-access";
|
|
22
22
|
import { assertDatabaseCompute, type DatabaseCompute } from "@ohmyhost/contracts/database-compute";
|
|
23
|
+
import {
|
|
24
|
+
DATABASE_TABLE_COLUMN_TYPES,
|
|
25
|
+
DATABASE_TABLE_DEFAULTS,
|
|
26
|
+
isDatabaseTableIdentifier,
|
|
27
|
+
type DatabaseTableColumnType,
|
|
28
|
+
type DatabaseTableDefault,
|
|
29
|
+
} from "@ohmyhost/contracts/database-tables";
|
|
23
30
|
import {
|
|
24
31
|
assertDatabaseExecutionUsagePage,
|
|
25
32
|
assertDatabaseSchedule,
|
|
@@ -33,6 +40,9 @@ import {
|
|
|
33
40
|
assertDatabaseWebhookDeliveryPage,
|
|
34
41
|
assertDatabaseWebhookPage,
|
|
35
42
|
assertDatabaseWebhookReplayAccepted,
|
|
43
|
+
assertDatabaseWatch,
|
|
44
|
+
assertDatabaseWatchDeleted,
|
|
45
|
+
assertDatabaseWatchPage,
|
|
36
46
|
assertDatabaseWebhookTest,
|
|
37
47
|
type DatabaseExecutionUsagePage,
|
|
38
48
|
type DatabaseSchedule,
|
|
@@ -45,7 +55,11 @@ import {
|
|
|
45
55
|
type DatabaseWebhookCreated,
|
|
46
56
|
type DatabaseWebhookDeleted,
|
|
47
57
|
type DatabaseWebhookDeliveryPage,
|
|
48
|
-
type
|
|
58
|
+
type DatabaseWatch,
|
|
59
|
+
type DatabaseWatchDeleted,
|
|
60
|
+
type DatabaseWatchPage,
|
|
61
|
+
type DatabaseWatchRequest,
|
|
62
|
+
type DatabaseWebhookEventPattern,
|
|
49
63
|
type DatabaseWebhookPage,
|
|
50
64
|
type DatabaseWebhookReplayAccepted,
|
|
51
65
|
type DatabaseWebhookTestResult,
|
|
@@ -152,6 +166,10 @@ import {
|
|
|
152
166
|
getProjectDatabaseWebhook,
|
|
153
167
|
deleteProjectDatabaseWebhook,
|
|
154
168
|
testProjectDatabaseWebhook,
|
|
169
|
+
createProjectDatabaseWatch,
|
|
170
|
+
listProjectDatabaseWatches,
|
|
171
|
+
deleteProjectDatabaseWatch,
|
|
172
|
+
createProjectDatabaseTable,
|
|
155
173
|
listProjectDatabaseWebhookDeliveries,
|
|
156
174
|
replayProjectDatabaseWebhookDelivery,
|
|
157
175
|
setProjectDatabaseSchedule,
|
|
@@ -205,6 +223,39 @@ export interface ProjectCreateInput {
|
|
|
205
223
|
readonly idempotencyKey: string;
|
|
206
224
|
}
|
|
207
225
|
|
|
226
|
+
/** One column of a table to create; nullable, identity and default are optional as the REST body allows. */
|
|
227
|
+
export interface DatabaseTableColumnInput {
|
|
228
|
+
readonly name: string;
|
|
229
|
+
readonly type: DatabaseTableColumnType;
|
|
230
|
+
readonly nullable?: boolean;
|
|
231
|
+
readonly identity?: boolean;
|
|
232
|
+
readonly default?: DatabaseTableDefault;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface DatabaseTableCreateInput {
|
|
236
|
+
readonly table: string;
|
|
237
|
+
readonly columns: readonly DatabaseTableColumnInput[];
|
|
238
|
+
readonly primaryKey: readonly string[];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** The created or identical existing table, every column with its concrete nullability and default. */
|
|
242
|
+
export interface DatabaseTableAnswer {
|
|
243
|
+
readonly table: {
|
|
244
|
+
readonly environment: "dev" | "prod";
|
|
245
|
+
readonly schema: "public";
|
|
246
|
+
readonly table: string;
|
|
247
|
+
readonly columns: readonly {
|
|
248
|
+
readonly name: string;
|
|
249
|
+
readonly type: DatabaseTableColumnType;
|
|
250
|
+
readonly nullable: boolean;
|
|
251
|
+
readonly identity: boolean;
|
|
252
|
+
readonly default: DatabaseTableDefault | null;
|
|
253
|
+
}[];
|
|
254
|
+
readonly primary_key: readonly string[];
|
|
255
|
+
readonly created: boolean;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
208
259
|
export interface ProductApi {
|
|
209
260
|
readonly managedSource?: ManagedSourceApi;
|
|
210
261
|
planProjectDataChange(input: {
|
|
@@ -328,7 +379,7 @@ export interface ProductApi {
|
|
|
328
379
|
readonly environment: "dev" | "prod";
|
|
329
380
|
readonly idempotencyKey: string;
|
|
330
381
|
readonly url: string;
|
|
331
|
-
readonly eventTypes: readonly
|
|
382
|
+
readonly eventTypes: readonly DatabaseWebhookEventPattern[];
|
|
332
383
|
readonly headers: Readonly<Record<string, string>>;
|
|
333
384
|
}): Promise<DatabaseWebhookCreated>;
|
|
334
385
|
listProjectDatabaseWebhooks(input: {
|
|
@@ -350,6 +401,28 @@ export interface ProductApi {
|
|
|
350
401
|
readonly environment: "dev" | "prod";
|
|
351
402
|
readonly webhookId: string;
|
|
352
403
|
}): Promise<DatabaseWebhookTestResult>;
|
|
404
|
+
createProjectDatabaseWatch(input: {
|
|
405
|
+
readonly projectId: string;
|
|
406
|
+
readonly environment: "dev" | "prod";
|
|
407
|
+
readonly idempotencyKey: string;
|
|
408
|
+
readonly request: DatabaseWatchRequest;
|
|
409
|
+
}): Promise<DatabaseWatch>;
|
|
410
|
+
listProjectDatabaseWatches(input: {
|
|
411
|
+
readonly projectId: string;
|
|
412
|
+
readonly environment: "dev" | "prod";
|
|
413
|
+
}): Promise<DatabaseWatchPage>;
|
|
414
|
+
deleteProjectDatabaseWatch(input: {
|
|
415
|
+
readonly projectId: string;
|
|
416
|
+
readonly environment: "dev" | "prod";
|
|
417
|
+
readonly idempotencyKey: string;
|
|
418
|
+
readonly watchId: string;
|
|
419
|
+
}): Promise<DatabaseWatchDeleted>;
|
|
420
|
+
createProjectDatabaseTable(input: {
|
|
421
|
+
readonly projectId: string;
|
|
422
|
+
readonly environment: "dev" | "prod";
|
|
423
|
+
readonly idempotencyKey: string;
|
|
424
|
+
readonly request: DatabaseTableCreateInput;
|
|
425
|
+
}): Promise<DatabaseTableAnswer>;
|
|
353
426
|
listProjectDatabaseWebhookDeliveries(input: {
|
|
354
427
|
readonly projectId: string;
|
|
355
428
|
readonly environment: "dev" | "prod";
|
|
@@ -566,9 +639,55 @@ export interface ProductApi {
|
|
|
566
639
|
|
|
567
640
|
/** A webhook answer that names another environment, webhook or delivery than the request did. */
|
|
568
641
|
const WEBHOOK_SCOPE_MISMATCH = "Webhook response scope mismatch";
|
|
642
|
+
const WATCH_SCOPE_MISMATCH = "Watch response scope mismatch";
|
|
643
|
+
const TABLE_SCOPE_MISMATCH = "Table response scope mismatch";
|
|
569
644
|
/** A schedule answer that names another environment or schedule than the request did. */
|
|
570
645
|
const SCHEDULE_SCOPE_MISMATCH = "Schedule response scope mismatch";
|
|
571
646
|
|
|
647
|
+
/** The REST answer read exactly: no extra keys, closed column types and defaults, keys among the columns. */
|
|
648
|
+
export function assertDatabaseTableAnswer(value: unknown): asserts value is DatabaseTableAnswer {
|
|
649
|
+
const table = isRecordValue(value) ? value["table"] : undefined;
|
|
650
|
+
const columns = isRecordValue(table) ? table["columns"] : undefined;
|
|
651
|
+
const primaryKey = isRecordValue(table) ? table["primary_key"] : undefined;
|
|
652
|
+
if (
|
|
653
|
+
!isRecordValue(table) ||
|
|
654
|
+
!hasExactKeys(table, ["environment", "schema", "table", "columns", "primary_key", "created"]) ||
|
|
655
|
+
(table["environment"] !== "dev" && table["environment"] !== "prod") ||
|
|
656
|
+
table["schema"] !== "public" ||
|
|
657
|
+
!isDatabaseTableIdentifier(table["table"]) ||
|
|
658
|
+
typeof table["created"] !== "boolean" ||
|
|
659
|
+
!Array.isArray(columns) ||
|
|
660
|
+
columns.length < 1 ||
|
|
661
|
+
!columns.every(isDatabaseTableAnswerColumn) ||
|
|
662
|
+
!Array.isArray(primaryKey) ||
|
|
663
|
+
!primaryKey.every((name: unknown) =>
|
|
664
|
+
columns.some((column: Record<string, unknown>) => column["name"] === name),
|
|
665
|
+
)
|
|
666
|
+
)
|
|
667
|
+
throw new TypeError("Invalid database table answer");
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function isDatabaseTableAnswerColumn(value: unknown): boolean {
|
|
671
|
+
return (
|
|
672
|
+
isRecordValue(value) &&
|
|
673
|
+
hasExactKeys(value, ["name", "type", "nullable", "identity", "default"]) &&
|
|
674
|
+
isDatabaseTableIdentifier(value["name"]) &&
|
|
675
|
+
(DATABASE_TABLE_COLUMN_TYPES as readonly unknown[]).includes(value["type"]) &&
|
|
676
|
+
typeof value["nullable"] === "boolean" &&
|
|
677
|
+
typeof value["identity"] === "boolean" &&
|
|
678
|
+
(value["default"] === null ||
|
|
679
|
+
(DATABASE_TABLE_DEFAULTS as readonly unknown[]).includes(value["default"]))
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
function isRecordValue(value: unknown): value is Record<string, unknown> {
|
|
684
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function hasExactKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {
|
|
688
|
+
return Object.keys(value).sort().join(",") === [...keys].sort().join(",");
|
|
689
|
+
}
|
|
690
|
+
|
|
572
691
|
export class GeneratedSdkProductApi implements ProductApi {
|
|
573
692
|
readonly #client: OhMyHostClient;
|
|
574
693
|
public readonly managedSource: ManagedSourceApi;
|
|
@@ -889,6 +1008,87 @@ export class GeneratedSdkProductApi implements ProductApi {
|
|
|
889
1008
|
return value;
|
|
890
1009
|
}
|
|
891
1010
|
|
|
1011
|
+
public async createProjectDatabaseWatch(
|
|
1012
|
+
input: Parameters<ProductApi["createProjectDatabaseWatch"]>[0],
|
|
1013
|
+
): Promise<DatabaseWatch> {
|
|
1014
|
+
const value = await createProjectDatabaseWatch(
|
|
1015
|
+
{
|
|
1016
|
+
project_id: input.projectId,
|
|
1017
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
1018
|
+
databaseWatchCreateRequest: {
|
|
1019
|
+
environment: input.environment,
|
|
1020
|
+
schema: input.request.schema,
|
|
1021
|
+
table: input.request.table,
|
|
1022
|
+
columns: [...input.request.columns],
|
|
1023
|
+
operations: [...input.request.operations],
|
|
1024
|
+
},
|
|
1025
|
+
},
|
|
1026
|
+
{ client: this.#client },
|
|
1027
|
+
);
|
|
1028
|
+
assertDatabaseWatch(value);
|
|
1029
|
+
if (
|
|
1030
|
+
value.environment !== input.environment ||
|
|
1031
|
+
value.schema !== input.request.schema ||
|
|
1032
|
+
value.table !== input.request.table
|
|
1033
|
+
)
|
|
1034
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
1035
|
+
return value;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
public async listProjectDatabaseWatches(
|
|
1039
|
+
input: Parameters<ProductApi["listProjectDatabaseWatches"]>[0],
|
|
1040
|
+
): Promise<DatabaseWatchPage> {
|
|
1041
|
+
const value = await listProjectDatabaseWatches(
|
|
1042
|
+
{ project_id: input.projectId, environment: input.environment },
|
|
1043
|
+
{ client: this.#client },
|
|
1044
|
+
);
|
|
1045
|
+
assertDatabaseWatchPage(value);
|
|
1046
|
+
if (value.items.some((item) => item.environment !== input.environment))
|
|
1047
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
1048
|
+
return value;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
public async deleteProjectDatabaseWatch(
|
|
1052
|
+
input: Parameters<ProductApi["deleteProjectDatabaseWatch"]>[0],
|
|
1053
|
+
): Promise<DatabaseWatchDeleted> {
|
|
1054
|
+
const value = await deleteProjectDatabaseWatch(
|
|
1055
|
+
{
|
|
1056
|
+
project_id: input.projectId,
|
|
1057
|
+
environment: input.environment,
|
|
1058
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
1059
|
+
watch_id: input.watchId,
|
|
1060
|
+
},
|
|
1061
|
+
{ client: this.#client },
|
|
1062
|
+
);
|
|
1063
|
+
assertDatabaseWatchDeleted(value);
|
|
1064
|
+
if (value.id !== input.watchId) throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
1065
|
+
return value;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
public async createProjectDatabaseTable(
|
|
1069
|
+
input: Parameters<ProductApi["createProjectDatabaseTable"]>[0],
|
|
1070
|
+
): Promise<DatabaseTableAnswer> {
|
|
1071
|
+
const value = await createProjectDatabaseTable(
|
|
1072
|
+
{
|
|
1073
|
+
project_id: input.projectId,
|
|
1074
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
1075
|
+
databaseTableCreateRequest: {
|
|
1076
|
+
environment: input.environment,
|
|
1077
|
+
table: input.request.table,
|
|
1078
|
+
columns: [...input.request.columns],
|
|
1079
|
+
...(input.request.primaryKey.length === 0
|
|
1080
|
+
? {}
|
|
1081
|
+
: { primary_key: [...input.request.primaryKey] }),
|
|
1082
|
+
},
|
|
1083
|
+
},
|
|
1084
|
+
{ client: this.#client },
|
|
1085
|
+
);
|
|
1086
|
+
assertDatabaseTableAnswer(value);
|
|
1087
|
+
if (value.table.environment !== input.environment || value.table.table !== input.request.table)
|
|
1088
|
+
throw new TypeError(TABLE_SCOPE_MISMATCH);
|
|
1089
|
+
return value;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
892
1092
|
/** The signing secret exists only in this answer; the CLI prints it once and stores nothing. */
|
|
893
1093
|
public async createProjectDatabaseWebhook(
|
|
894
1094
|
input: Parameters<ProductApi["createProjectDatabaseWebhook"]>[0],
|