@amerged/ohmyhost-mcp 0.1.44 → 0.1.45
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-AJV4T4LM.js} +6 -6
- package/dist/index.js +1 -1
- package/dist/stdio-main.js +275 -9
- package/package.json +1 -1
- package/src/apps/mcp/package.json +1 -1
- package/src/apps/mcp/src/local-client.ts +60 -0
- package/src/apps/mcp/src/local-server.ts +111 -4
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +61 -1
- package/src/apps/product-cli/src/command.ts +123 -2
- package/src/apps/product-cli/src/product-api.ts +86 -2
- package/src/packages/agent-skills/src/generated-skill-resources.ts +5 -5
- 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/problem-policy.ts +36 -1
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/index.ts +25 -0
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +150 -0
- package/src/packages/sdk-ts/src/generated/types.gen.ts +266 -4
package/dist/index.js
CHANGED
package/dist/stdio-main.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
serverIdentityOf,
|
|
31
31
|
setNegotiatedProtocolVersion,
|
|
32
32
|
validateEnvelopeMeta
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-AJV4T4LM.js";
|
|
34
34
|
|
|
35
35
|
// node_modules/.pnpm/ignore@7.0.12/node_modules/ignore/index.js
|
|
36
36
|
var require_ignore = __commonJS({
|
|
@@ -25572,6 +25572,36 @@ var PROBLEM_POLICY = {
|
|
|
25572
25572
|
action: "The platform is still retrying this webhook delivery. Read the delivery in the delivery list; replay it only if it ends dead_lettered or the receiver needs the event again.",
|
|
25573
25573
|
title: "Webhook delivery still pending"
|
|
25574
25574
|
},
|
|
25575
|
+
database_watch_limit: {
|
|
25576
|
+
status: 409,
|
|
25577
|
+
retryable: false,
|
|
25578
|
+
action: "List the project's database watches for this environment and delete one you no longer need, then create the watch again.",
|
|
25579
|
+
title: "Database watch limit reached"
|
|
25580
|
+
},
|
|
25581
|
+
database_watch_table_unavailable: {
|
|
25582
|
+
status: 409,
|
|
25583
|
+
retryable: false,
|
|
25584
|
+
action: "The table must exist as an ordinary table owned by the application, created by a deployed migration; views, partitions, temporary tables and the schemas pgcf, ohmyhost, information_schema and pg_* cannot be watched. Fix the name or deploy the migration, then create the watch again.",
|
|
25585
|
+
title: "Table cannot be watched"
|
|
25586
|
+
},
|
|
25587
|
+
database_watch_column_unavailable: {
|
|
25588
|
+
status: 409,
|
|
25589
|
+
retryable: false,
|
|
25590
|
+
action: "List only existing column names exactly as written, names are case-sensitive. Delete the watch before a migration drops a published column, because the write would fail.",
|
|
25591
|
+
title: "Watched column does not exist"
|
|
25592
|
+
},
|
|
25593
|
+
database_watch_events_unavailable: {
|
|
25594
|
+
status: 409,
|
|
25595
|
+
retryable: false,
|
|
25596
|
+
action: "The platform event schema is installed when the database wakes: run any query against that environment, wait for the answer, then create the watch again. If it still fails, report the request_id through feedback.",
|
|
25597
|
+
title: "Database events not installed yet"
|
|
25598
|
+
},
|
|
25599
|
+
database_watch_conflict: {
|
|
25600
|
+
status: 409,
|
|
25601
|
+
retryable: false,
|
|
25602
|
+
action: "A migration already attaches a capture trigger to this table: keep it and skip the watch, or remove it from the migrations, deploy and create the watch again. A table carries one capture trigger.",
|
|
25603
|
+
title: "Table already has a capture trigger"
|
|
25604
|
+
},
|
|
25575
25605
|
project_notes_conflict: {
|
|
25576
25606
|
status: 409,
|
|
25577
25607
|
retryable: false,
|
|
@@ -25836,7 +25866,7 @@ var PROBLEM_POLICY = {
|
|
|
25836
25866
|
api_key_permissions_unavailable: {
|
|
25837
25867
|
status: 503,
|
|
25838
25868
|
retryable: false,
|
|
25839
|
-
action: "Report the platform user-key permission configuration through feedback. Repeated login
|
|
25869
|
+
action: "Report the platform user-key permission configuration through feedback with this request_id; it affects every token the same way, whatever the integration. Repeated login does not fix it. After the platform confirms the fix, repeat the same create with the same name and Idempotency-Key.",
|
|
25840
25870
|
title: "Token permissions unavailable"
|
|
25841
25871
|
},
|
|
25842
25872
|
reconciliation_exhausted: {
|
|
@@ -27093,6 +27123,9 @@ var DATABASE_WEBHOOK_EVENT_TYPES = [
|
|
|
27093
27123
|
"database.resized",
|
|
27094
27124
|
"database.deleted"
|
|
27095
27125
|
];
|
|
27126
|
+
var DATABASE_WATCH_OPERATIONS = ["insert", "update", "delete"];
|
|
27127
|
+
var DATABASE_WATCH_MAX_COLUMNS = 32;
|
|
27128
|
+
var DATABASE_WATCH_DEFAULT_SCHEMA = "public";
|
|
27096
27129
|
var DATABASE_WEBHOOK_MAX_EVENT_TYPES = 16;
|
|
27097
27130
|
var DATABASE_WEBHOOK_MAX_HEADERS = 8;
|
|
27098
27131
|
var DATABASE_WEBHOOK_URL_MAX_LENGTH = 2048;
|
|
@@ -27135,15 +27168,61 @@ var USAGE_MAX_RANGE_MS = 31 * 24 * USAGE_HOUR_MS;
|
|
|
27135
27168
|
var WEBHOOK_KEYS = ["id", "environment", "url", "event_types", "header_names", "created_at"];
|
|
27136
27169
|
var WEBHOOK_ID_PATTERN = /^whk_[a-z0-9]{20}$/u;
|
|
27137
27170
|
var DELIVERY_ID_PATTERN = /^dlv_[0-9a-f]{20}$/u;
|
|
27138
|
-
var EVENT_ID_PATTERN = /^evt_[0-9a-f]{20}$/u;
|
|
27171
|
+
var EVENT_ID_PATTERN = /^(?:evt_[0-9a-f]{20}|[a-z][a-z0-9]{19}:[1-9][0-9]{0,15}:[1-9][0-9]{0,15})$/u;
|
|
27172
|
+
var DATA_SUBSCRIPTION_PATTERN = /^data\.(?:\*|[a-z][a-z0-9_]{0,47})$/u;
|
|
27173
|
+
var DATA_EVENT_TYPE_PATTERN = /^data\.[a-z][a-z0-9_]{0,47}$/u;
|
|
27174
|
+
var DATABASE_WATCH_ID_PATTERN = /^pgcf_watch_[0-9a-f]{8}$/u;
|
|
27175
|
+
var DATABASE_WATCH_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/u;
|
|
27176
|
+
var DATABASE_WATCH_FORBIDDEN_SCHEMAS = ["information_schema", "pgcf", "ohmyhost"];
|
|
27177
|
+
var DATABASE_WATCH_KEYS = [
|
|
27178
|
+
"id",
|
|
27179
|
+
"environment",
|
|
27180
|
+
"schema",
|
|
27181
|
+
"table",
|
|
27182
|
+
"columns",
|
|
27183
|
+
"operations",
|
|
27184
|
+
"topic",
|
|
27185
|
+
"event_type"
|
|
27186
|
+
];
|
|
27139
27187
|
var SCHEDULE_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/u;
|
|
27140
27188
|
var CURSOR_PATTERN = /^[A-Za-z0-9._|:=+/-]{1,200}$/u;
|
|
27141
27189
|
var HEADER_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9-]{0,63}$/u;
|
|
27190
|
+
function isDatabaseWatchIdentifier(value) {
|
|
27191
|
+
return matches(value, DATABASE_WATCH_IDENTIFIER_PATTERN);
|
|
27192
|
+
}
|
|
27193
|
+
function isDatabaseWatchSchema(value) {
|
|
27194
|
+
if (!isDatabaseWatchIdentifier(value))
|
|
27195
|
+
return false;
|
|
27196
|
+
const lower = value.toLowerCase();
|
|
27197
|
+
return !lower.startsWith("pg_") && !DATABASE_WATCH_FORBIDDEN_SCHEMAS.includes(lower);
|
|
27198
|
+
}
|
|
27199
|
+
function dataEventTopic(tableName) {
|
|
27200
|
+
const mapped = Array.from(tableName, (character) => {
|
|
27201
|
+
const lower = Array.from(character.toLowerCase())[0] ?? "_";
|
|
27202
|
+
return /^[a-z0-9_]$/u.test(lower) ? lower : "_";
|
|
27203
|
+
}).join("");
|
|
27204
|
+
const topic = /^[a-z]/u.test(mapped) ? mapped : `t_${mapped}`;
|
|
27205
|
+
return topic.slice(0, 48);
|
|
27206
|
+
}
|
|
27142
27207
|
function assertDatabaseWebhook(value) {
|
|
27143
27208
|
if (!record4(value) || !exact4(value, WEBHOOK_KEYS))
|
|
27144
27209
|
throw new TypeError("Invalid database webhook");
|
|
27145
27210
|
assertWebhookFields(value);
|
|
27146
27211
|
}
|
|
27212
|
+
function assertDatabaseWatch(value) {
|
|
27213
|
+
if (!record4(value) || !exact4(value, DATABASE_WATCH_KEYS) || !matches(value["id"], DATABASE_WATCH_ID_PATTERN) || !oneOf(["dev", "prod"], value["environment"]) || !isDatabaseWatchSchema(value["schema"]) || !isDatabaseWatchIdentifier(value["table"]) || !Array.isArray(value["columns"]) || value["columns"].length < 1 || value["columns"].length > DATABASE_WATCH_MAX_COLUMNS || !value["columns"].every(isDatabaseWatchIdentifier) || !isCanonicalOperations(value["operations"]) || value["topic"] !== dataEventTopic(value["table"]) || value["event_type"] !== `data.${value["topic"]}`)
|
|
27214
|
+
throw new TypeError("Invalid database watch");
|
|
27215
|
+
}
|
|
27216
|
+
function assertDatabaseWatchPage(value) {
|
|
27217
|
+
if (!record4(value) || !exact4(value, ["items"]) || !pageItems(value["items"]))
|
|
27218
|
+
throw new TypeError("Invalid database watch page");
|
|
27219
|
+
for (const item of value["items"])
|
|
27220
|
+
assertDatabaseWatch(item);
|
|
27221
|
+
}
|
|
27222
|
+
function assertDatabaseWatchDeleted(value) {
|
|
27223
|
+
if (!record4(value) || !exact4(value, ["id", "deleted"]) || !matches(value["id"], DATABASE_WATCH_ID_PATTERN) || value["deleted"] !== true)
|
|
27224
|
+
throw new TypeError("Invalid database watch deletion");
|
|
27225
|
+
}
|
|
27147
27226
|
function assertDatabaseWebhookCreated(value) {
|
|
27148
27227
|
if (!record4(value) || !exact4(value, [...WEBHOOK_KEYS, "secret"]) || typeof value["secret"] !== "string" || value["secret"].length === 0)
|
|
27149
27228
|
throw new TypeError("Invalid database webhook");
|
|
@@ -27172,7 +27251,7 @@ function assertDatabaseWebhookDelivery(value) {
|
|
|
27172
27251
|
"delivered_at",
|
|
27173
27252
|
"last_status",
|
|
27174
27253
|
"last_error"
|
|
27175
|
-
]) || !matches(value["id"], DELIVERY_ID_PATTERN) || !matches(value["event_id"], EVENT_ID_PATTERN) || !
|
|
27254
|
+
]) || !matches(value["id"], DELIVERY_ID_PATTERN) || !matches(value["event_id"], EVENT_ID_PATTERN) || !isDeliveredEventType(value["event_type"]) || !matches(value["webhook_id"], WEBHOOK_ID_PATTERN) || !oneOf(["pending", "delivered", "dead_lettered"], value["state"]) || !nonNegativeInteger(value["attempts"]) || !timestamp3(value["created_at"]) || !nullable(value["next_attempt_at"], timestamp3) || !nullable(value["delivered_at"], timestamp3) || !nullable(value["last_status"], Number.isSafeInteger) || !nullable(value["last_error"], (error) => oneOf(["timeout", "network", "http", "expired", "permanent"], error)))
|
|
27176
27255
|
throw new TypeError("Invalid database webhook delivery");
|
|
27177
27256
|
}
|
|
27178
27257
|
function assertDatabaseWebhookDeliveryPage(value) {
|
|
@@ -27255,7 +27334,7 @@ function assertUsageRow(value) {
|
|
|
27255
27334
|
throw new TypeError("Invalid database execution usage row");
|
|
27256
27335
|
}
|
|
27257
27336
|
function assertWebhookFields(value) {
|
|
27258
|
-
if (!matches(value["id"], WEBHOOK_ID_PATTERN) || !oneOf(["dev", "prod"], value["environment"]) || !isHttpsUrl2(value["url"]) || !Array.isArray(value["event_types"]) || value["event_types"].length < 1 || value["event_types"].length > DATABASE_WEBHOOK_MAX_EVENT_TYPES || !value["event_types"].every(
|
|
27337
|
+
if (!matches(value["id"], WEBHOOK_ID_PATTERN) || !oneOf(["dev", "prod"], value["environment"]) || !isHttpsUrl2(value["url"]) || !Array.isArray(value["event_types"]) || value["event_types"].length < 1 || value["event_types"].length > DATABASE_WEBHOOK_MAX_EVENT_TYPES || !value["event_types"].every(isDatabaseWebhookEventPattern) || !Array.isArray(value["header_names"]) || value["header_names"].length > DATABASE_WEBHOOK_MAX_HEADERS || !value["header_names"].every((name) => matches(name, HEADER_NAME_PATTERN)) || !timestamp3(value["created_at"]))
|
|
27259
27338
|
throw new TypeError("Invalid database webhook");
|
|
27260
27339
|
}
|
|
27261
27340
|
function isHttpsUrl2(value) {
|
|
@@ -27267,6 +27346,18 @@ function isHttpsUrl2(value) {
|
|
|
27267
27346
|
return false;
|
|
27268
27347
|
}
|
|
27269
27348
|
}
|
|
27349
|
+
function isDatabaseWebhookEventPattern(value) {
|
|
27350
|
+
return oneOf(DATABASE_WEBHOOK_EVENT_TYPES, value) || matches(value, DATA_SUBSCRIPTION_PATTERN);
|
|
27351
|
+
}
|
|
27352
|
+
function isDeliveredEventType(value) {
|
|
27353
|
+
return oneOf(DATABASE_WEBHOOK_EVENT_TYPES, value) || matches(value, DATA_EVENT_TYPE_PATTERN);
|
|
27354
|
+
}
|
|
27355
|
+
function isCanonicalOperations(value) {
|
|
27356
|
+
if (!Array.isArray(value) || value.length < 1)
|
|
27357
|
+
return false;
|
|
27358
|
+
const canonical = DATABASE_WATCH_OPERATIONS.filter((operation) => value.includes(operation));
|
|
27359
|
+
return canonical.length === value.length && canonical.every((op, index) => op === value[index]);
|
|
27360
|
+
}
|
|
27270
27361
|
function isCronText(value) {
|
|
27271
27362
|
return typeof value === "string" && value.length >= DATABASE_SCHEDULE_CRON_MIN_LENGTH && value.length <= DATABASE_SCHEDULE_CRON_MAX_LENGTH;
|
|
27272
27363
|
}
|
|
@@ -27310,7 +27401,7 @@ function exact4(value, keys) {
|
|
|
27310
27401
|
// apps/product-cli/package.json
|
|
27311
27402
|
var package_default2 = {
|
|
27312
27403
|
name: "@ohmyhost/product-cli",
|
|
27313
|
-
version: "0.1.
|
|
27404
|
+
version: "0.1.45",
|
|
27314
27405
|
private: true,
|
|
27315
27406
|
ohmyhost: {
|
|
27316
27407
|
deployment: "production",
|
|
@@ -28424,7 +28515,10 @@ var HELP_USAGE = Object.freeze({
|
|
|
28424
28515
|
"database access create": "ohmyhost database access create --project ULID --environment dev|prod [--mode read|write] [--ttl 5m|1h|24h|SECONDS] [--label TEXT] --yes --json\n The connection URI is shown once. Use it immediately, never store it in files, notes or source, and revoke it when finished.",
|
|
28425
28516
|
"database access list": "ohmyhost database access list --project ULID [--environment dev|prod] --json",
|
|
28426
28517
|
"database access revoke": "ohmyhost database access revoke --project ULID --access ULID --yes --json",
|
|
28427
|
-
"database
|
|
28518
|
+
"database watch create": "ohmyhost database watch create --project ULID --environment dev|prod --table NAME [--schema public] --columns COL[,COL] [--operations insert,update,delete] --idempotency-key KEY --yes --json (publishes only the listed columns, at most 32, of each row change as the event type data.<topic> printed in this answer; the table must exist as an ordinary table of the application; a sleeping database wakes; next, subscribe with 'ohmyhost database webhook create ... --event-types data.<topic>')",
|
|
28519
|
+
"database watch list": "ohmyhost database watch list --project ULID [--environment dev|prod] --json (dev when omitted; a sleeping database wakes)",
|
|
28520
|
+
"database watch delete": "ohmyhost database watch delete --project ULID --environment dev|prod --watch ID --idempotency-key KEY --yes --json",
|
|
28521
|
+
"database webhook create": "ohmyhost database webhook create --project ULID --environment dev|prod --url HTTPS_URL --event-types TYPE[,TYPE] [--headers-file PATH] --idempotency-key KEY --yes --json (the signing secret is shown once in this answer; types: database.created, database.ready, database.woke, database.slept, database.suspended, database.resized, database.deleted, data.<topic> for the rows of one watched table printed by database watch create, or data.* for every watched table; a bare * is not accepted and does not include data events; the headers file is a UTF-8 JSON object of at most 8 KiB)",
|
|
28428
28522
|
"database webhook list": "ohmyhost database webhook list --project ULID [--environment dev|prod] --json (dev when omitted; the secret is never listed)",
|
|
28429
28523
|
"database webhook get": "ohmyhost database webhook get --project ULID [--environment dev|prod] --webhook ID --json",
|
|
28430
28524
|
"database webhook delete": "ohmyhost database webhook delete --project ULID --environment dev|prod --webhook ID --yes --json",
|
|
@@ -31218,6 +31312,68 @@ var revokeProjectDatabaseAccess = (parameters, options) => {
|
|
|
31218
31312
|
...params
|
|
31219
31313
|
});
|
|
31220
31314
|
};
|
|
31315
|
+
var listProjectDatabaseWatches = (parameters, options) => {
|
|
31316
|
+
const params = buildClientParams([parameters], [
|
|
31317
|
+
{
|
|
31318
|
+
args: [
|
|
31319
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
31320
|
+
{ in: "path", key: "project_id" },
|
|
31321
|
+
{ in: "query", key: "environment" }
|
|
31322
|
+
]
|
|
31323
|
+
}
|
|
31324
|
+
]);
|
|
31325
|
+
return (options?.client ?? client).get({
|
|
31326
|
+
responseStyle: "data",
|
|
31327
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
31328
|
+
url: "/v1/projects/{project_id}/database/watches",
|
|
31329
|
+
...options,
|
|
31330
|
+
...params
|
|
31331
|
+
});
|
|
31332
|
+
};
|
|
31333
|
+
var createProjectDatabaseWatch = (parameters, options) => {
|
|
31334
|
+
const params = buildClientParams([parameters], [
|
|
31335
|
+
{
|
|
31336
|
+
args: [
|
|
31337
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
31338
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
31339
|
+
{ in: "path", key: "project_id" },
|
|
31340
|
+
{ key: "databaseWatchCreateRequest", map: "body" }
|
|
31341
|
+
]
|
|
31342
|
+
}
|
|
31343
|
+
]);
|
|
31344
|
+
return (options?.client ?? client).post({
|
|
31345
|
+
responseStyle: "data",
|
|
31346
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
31347
|
+
url: "/v1/projects/{project_id}/database/watches",
|
|
31348
|
+
...options,
|
|
31349
|
+
...params,
|
|
31350
|
+
headers: {
|
|
31351
|
+
"Content-Type": "application/json",
|
|
31352
|
+
...options?.headers,
|
|
31353
|
+
...params.headers
|
|
31354
|
+
}
|
|
31355
|
+
});
|
|
31356
|
+
};
|
|
31357
|
+
var deleteProjectDatabaseWatch = (parameters, options) => {
|
|
31358
|
+
const params = buildClientParams([parameters], [
|
|
31359
|
+
{
|
|
31360
|
+
args: [
|
|
31361
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
31362
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
31363
|
+
{ in: "path", key: "project_id" },
|
|
31364
|
+
{ in: "path", key: "watch_id" },
|
|
31365
|
+
{ in: "query", key: "environment" }
|
|
31366
|
+
]
|
|
31367
|
+
}
|
|
31368
|
+
]);
|
|
31369
|
+
return (options?.client ?? client).delete({
|
|
31370
|
+
responseStyle: "data",
|
|
31371
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
31372
|
+
url: "/v1/projects/{project_id}/database/watches/{watch_id}",
|
|
31373
|
+
...options,
|
|
31374
|
+
...params
|
|
31375
|
+
});
|
|
31376
|
+
};
|
|
31221
31377
|
var listProjectDatabaseWebhooks = (parameters, options) => {
|
|
31222
31378
|
const params = buildClientParams([parameters], [
|
|
31223
31379
|
{
|
|
@@ -32622,6 +32778,7 @@ function checkedResponse(kind, value) {
|
|
|
32622
32778
|
|
|
32623
32779
|
// apps/product-cli/dist/product-api.js
|
|
32624
32780
|
var WEBHOOK_SCOPE_MISMATCH = "Webhook response scope mismatch";
|
|
32781
|
+
var WATCH_SCOPE_MISMATCH = "Watch response scope mismatch";
|
|
32625
32782
|
var SCHEDULE_SCOPE_MISMATCH = "Schedule response scope mismatch";
|
|
32626
32783
|
var GeneratedSdkProductApi = class {
|
|
32627
32784
|
#client;
|
|
@@ -32819,6 +32976,42 @@ var GeneratedSdkProductApi = class {
|
|
|
32819
32976
|
assertProjectDatabaseAccess(value);
|
|
32820
32977
|
return value;
|
|
32821
32978
|
}
|
|
32979
|
+
async createProjectDatabaseWatch(input) {
|
|
32980
|
+
const value = await createProjectDatabaseWatch({
|
|
32981
|
+
project_id: input.projectId,
|
|
32982
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
32983
|
+
databaseWatchCreateRequest: {
|
|
32984
|
+
environment: input.environment,
|
|
32985
|
+
schema: input.request.schema,
|
|
32986
|
+
table: input.request.table,
|
|
32987
|
+
columns: [...input.request.columns],
|
|
32988
|
+
operations: [...input.request.operations]
|
|
32989
|
+
}
|
|
32990
|
+
}, { client: this.#client });
|
|
32991
|
+
assertDatabaseWatch(value);
|
|
32992
|
+
if (value.environment !== input.environment || value.schema !== input.request.schema || value.table !== input.request.table)
|
|
32993
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
32994
|
+
return value;
|
|
32995
|
+
}
|
|
32996
|
+
async listProjectDatabaseWatches(input) {
|
|
32997
|
+
const value = await listProjectDatabaseWatches({ project_id: input.projectId, environment: input.environment }, { client: this.#client });
|
|
32998
|
+
assertDatabaseWatchPage(value);
|
|
32999
|
+
if (value.items.some((item) => item.environment !== input.environment))
|
|
33000
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
33001
|
+
return value;
|
|
33002
|
+
}
|
|
33003
|
+
async deleteProjectDatabaseWatch(input) {
|
|
33004
|
+
const value = await deleteProjectDatabaseWatch({
|
|
33005
|
+
project_id: input.projectId,
|
|
33006
|
+
environment: input.environment,
|
|
33007
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
33008
|
+
watch_id: input.watchId
|
|
33009
|
+
}, { client: this.#client });
|
|
33010
|
+
assertDatabaseWatchDeleted(value);
|
|
33011
|
+
if (value.id !== input.watchId)
|
|
33012
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
33013
|
+
return value;
|
|
33014
|
+
}
|
|
32822
33015
|
/** The signing secret exists only in this answer; the CLI prints it once and stores nothing. */
|
|
32823
33016
|
async createProjectDatabaseWebhook(input) {
|
|
32824
33017
|
const value = await createProjectDatabaseWebhook({
|
|
@@ -34096,6 +34289,40 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
34096
34289
|
requireScope(value.items.every((webhook) => webhook.environment === environment2));
|
|
34097
34290
|
return value;
|
|
34098
34291
|
}
|
|
34292
|
+
async listDatabaseWatches(input) {
|
|
34293
|
+
const environment2 = input.environment ?? "dev";
|
|
34294
|
+
const value = await listProjectDatabaseWatches({ project_id: input.projectId, environment: environment2 }, { client: this.#client });
|
|
34295
|
+
assertDatabaseWatchPage(value);
|
|
34296
|
+
requireScope(value.items.every((watch) => watch.environment === environment2));
|
|
34297
|
+
return value;
|
|
34298
|
+
}
|
|
34299
|
+
async createDatabaseWatch(input) {
|
|
34300
|
+
const value = await createProjectDatabaseWatch({
|
|
34301
|
+
project_id: input.projectId,
|
|
34302
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
34303
|
+
databaseWatchCreateRequest: {
|
|
34304
|
+
environment: input.environment,
|
|
34305
|
+
...input.schema === void 0 ? {} : { schema: input.schema },
|
|
34306
|
+
table: input.table,
|
|
34307
|
+
columns: [...input.columns],
|
|
34308
|
+
...input.operations === void 0 ? {} : { operations: [...input.operations] }
|
|
34309
|
+
}
|
|
34310
|
+
}, { client: this.#client });
|
|
34311
|
+
assertDatabaseWatch(value);
|
|
34312
|
+
requireScope(value.environment === input.environment && value.table === input.table && value.schema === (input.schema ?? DATABASE_WATCH_DEFAULT_SCHEMA));
|
|
34313
|
+
return value;
|
|
34314
|
+
}
|
|
34315
|
+
async deleteDatabaseWatch(input) {
|
|
34316
|
+
const value = await deleteProjectDatabaseWatch({
|
|
34317
|
+
project_id: input.projectId,
|
|
34318
|
+
environment: input.environment,
|
|
34319
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
34320
|
+
watch_id: input.watchId
|
|
34321
|
+
}, { client: this.#client });
|
|
34322
|
+
assertDatabaseWatchDeleted(value);
|
|
34323
|
+
requireScope(value.id === input.watchId);
|
|
34324
|
+
return value;
|
|
34325
|
+
}
|
|
34099
34326
|
/** The signing secret exists only in this response and is never stored by the client. */
|
|
34100
34327
|
async createDatabaseWebhook(input) {
|
|
34101
34328
|
const value = await createProjectDatabaseWebhook({
|
|
@@ -34523,6 +34750,8 @@ function invalid7() {
|
|
|
34523
34750
|
var identifier2 = external_exports.string().min(1).max(256);
|
|
34524
34751
|
var databaseEnvironment = external_exports.enum(["dev", "prod"]);
|
|
34525
34752
|
var databaseWebhookId = external_exports.string().regex(/^whk_[a-z0-9]{20}$/u);
|
|
34753
|
+
var databaseWatchId = external_exports.string().regex(/^pgcf_watch_[0-9a-f]{8}$/u);
|
|
34754
|
+
var databaseIdentifier = external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,62}$/u);
|
|
34526
34755
|
var databaseDeliveryId = external_exports.string().regex(/^dlv_[0-9a-f]{20}$/u);
|
|
34527
34756
|
var databaseScheduleName = external_exports.string().regex(/^[a-z][a-z0-9_-]{0,62}$/u);
|
|
34528
34757
|
var profileName = external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,62}$/u).optional().describe("Saved login to act as (profile_list shows them). Needed only when several logins could run this call; OHMYHOST_PROFILE of this server must match it.");
|
|
@@ -34774,15 +35003,52 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
34774
35003
|
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
34775
35004
|
}));
|
|
34776
35005
|
registerProductTool(server, dependencies, "database_access_revoke", "Revoke one issued database credential immediately: open sessions end and its PostgreSQL role is removed. Revocation is idempotent and never touches application roles or data.", external_exports.object({ project_id: identifier2, access_id: identifier2 }), (client2, input) => client2.revokeDatabaseAccess({ projectId: input.project_id, accessId: input.access_id }), destructiveAnnotations());
|
|
35006
|
+
registerProductTool(server, dependencies, "database_watch_list", "List this project's database watches of one Dev or Prod environment (dev when omitted). Each watch shows its table, columns, operations and the event type data.<topic> it publishes. Listing wakes a sleeping database.", external_exports.object({ project_id: identifier2, environment: databaseEnvironment.optional() }), (client2, input) => client2.listDatabaseWatches({
|
|
35007
|
+
projectId: input.project_id,
|
|
35008
|
+
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
35009
|
+
}));
|
|
35010
|
+
registerProductTool(server, dependencies, "database_watch_create", "Publish row changes of one table of a Dev or Prod database as data events: only the listed columns (at most 32) of each insert, update or delete are published, with the event type data.<topic> returned by this call. Pass that event type to database_webhook_create. The table must exist as an ordinary table of the application, created by a deployed migration; a sleeping database wakes. Rows written before the watch exists are not published, and a published column must not be dropped while the watch exists. Requires confirmed: true and an idempotency key. Refused with project_budget_exceeded while the Stop budget is reached.", external_exports.object({
|
|
35011
|
+
project_id: identifier2,
|
|
35012
|
+
environment: databaseEnvironment,
|
|
35013
|
+
schema: databaseIdentifier.refine(isDatabaseWatchSchema).optional(),
|
|
35014
|
+
table: databaseIdentifier,
|
|
35015
|
+
columns: external_exports.array(databaseIdentifier).min(1).max(32).refine((columns) => new Set(columns).size === columns.length),
|
|
35016
|
+
operations: external_exports.array(external_exports.enum(DATABASE_WATCH_OPERATIONS)).min(1).max(3).refine((operations) => new Set(operations).size === operations.length).optional(),
|
|
35017
|
+
idempotency_key: idempotencyKey,
|
|
35018
|
+
confirmed: external_exports.literal(true)
|
|
35019
|
+
}), (client2, input) => client2.createDatabaseWatch({
|
|
35020
|
+
projectId: input.project_id,
|
|
35021
|
+
environment: input.environment,
|
|
35022
|
+
...input.schema === void 0 ? {} : { schema: input.schema },
|
|
35023
|
+
table: input.table,
|
|
35024
|
+
columns: input.columns,
|
|
35025
|
+
...input.operations === void 0 ? {} : { operations: input.operations },
|
|
35026
|
+
idempotencyKey: input.idempotency_key
|
|
35027
|
+
}), mutationAnnotations());
|
|
35028
|
+
registerProductTool(server, dependencies, "database_watch_delete", "Remove the capture trigger of one database watch: its table publishes no more data events. Destructive: requires confirmed: true and an idempotency key. Deleting an already deleted watch answers not found.", external_exports.object({
|
|
35029
|
+
project_id: identifier2,
|
|
35030
|
+
environment: databaseEnvironment,
|
|
35031
|
+
watch_id: databaseWatchId,
|
|
35032
|
+
idempotency_key: idempotencyKey,
|
|
35033
|
+
confirmed: external_exports.literal(true)
|
|
35034
|
+
}), (client2, input) => client2.deleteDatabaseWatch({
|
|
35035
|
+
projectId: input.project_id,
|
|
35036
|
+
environment: input.environment,
|
|
35037
|
+
watchId: input.watch_id,
|
|
35038
|
+
idempotencyKey: input.idempotency_key
|
|
35039
|
+
}), destructiveAnnotations());
|
|
34777
35040
|
registerProductTool(server, dependencies, "database_webhook_list", "List this project's database webhooks of one Dev or Prod environment (dev when omitted), without signing secrets. Each webhook lists its event types and header names only.", external_exports.object({ project_id: identifier2, environment: databaseEnvironment.optional() }), (client2, input) => client2.listDatabaseWebhooks({
|
|
34778
35041
|
projectId: input.project_id,
|
|
34779
35042
|
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
34780
35043
|
}));
|
|
34781
|
-
registerProductTool(server, dependencies, "database_webhook_create", "Subscribe one HTTPS receiver to database lifecycle events (database.created, ready, woke, slept, suspended, resized, deleted) of one Dev or Prod database. The signing secret is RETURNED EXACTLY ONCE: store it in a secret manager and never write it into files, notes, source, commit messages or later messages. Deliveries are signed, retried and dead-lettered when retries stop. At most five webhooks exist per project environment. Requires confirmed: true and an idempotency key; the same key with the same request returns the stored answer.", external_exports.object({
|
|
35044
|
+
registerProductTool(server, dependencies, "database_webhook_create", "Subscribe one HTTPS receiver to database lifecycle events (database.created, ready, woke, slept, suspended, resized, deleted) of one Dev or Prod database, or to data events: data.<topic> for the rows of one watched table (the event type database_watch_create returns) or data.* for every watched table; a bare * never matches data events. The signing secret is RETURNED EXACTLY ONCE: store it in a secret manager and never write it into files, notes, source, commit messages or later messages. Deliveries are signed, retried and dead-lettered when retries stop. At most five webhooks exist per project environment. Requires confirmed: true and an idempotency key; the same key with the same request returns the stored answer.", external_exports.object({
|
|
34782
35045
|
project_id: identifier2,
|
|
34783
35046
|
environment: databaseEnvironment,
|
|
34784
35047
|
url: external_exports.string().max(2048).regex(/^https:\/\//u),
|
|
34785
|
-
event_types: external_exports.array(external_exports.
|
|
35048
|
+
event_types: external_exports.array(external_exports.union([
|
|
35049
|
+
external_exports.enum(DATABASE_WEBHOOK_EVENT_TYPES),
|
|
35050
|
+
external_exports.string().regex(/^data\.(?:\*|[a-z][a-z0-9_]{0,47})$/u).refine(isDatabaseWebhookEventPattern)
|
|
35051
|
+
])).min(1).max(16),
|
|
34786
35052
|
headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
34787
35053
|
idempotency_key: idempotencyKey,
|
|
34788
35054
|
confirmed: external_exports.literal(true)
|
package/package.json
CHANGED
|
@@ -20,6 +20,10 @@ import {
|
|
|
20
20
|
assertDatabaseScheduleRunAccepted,
|
|
21
21
|
assertDatabaseScheduleRunPage,
|
|
22
22
|
assertDatabaseWebhookCreated,
|
|
23
|
+
assertDatabaseWatch,
|
|
24
|
+
assertDatabaseWatchDeleted,
|
|
25
|
+
assertDatabaseWatchPage,
|
|
26
|
+
DATABASE_WATCH_DEFAULT_SCHEMA,
|
|
23
27
|
assertDatabaseWebhookDeleted,
|
|
24
28
|
assertDatabaseWebhookDeliveryPage,
|
|
25
29
|
assertDatabaseWebhookPage,
|
|
@@ -115,6 +119,9 @@ import {
|
|
|
115
119
|
createProjectDatabaseWebhook,
|
|
116
120
|
listProjectDatabaseWebhooks,
|
|
117
121
|
deleteProjectDatabaseWebhook,
|
|
122
|
+
createProjectDatabaseWatch,
|
|
123
|
+
listProjectDatabaseWatches,
|
|
124
|
+
deleteProjectDatabaseWatch,
|
|
118
125
|
testProjectDatabaseWebhook,
|
|
119
126
|
listProjectDatabaseWebhookDeliveries,
|
|
120
127
|
replayProjectDatabaseWebhookDelivery,
|
|
@@ -849,6 +856,59 @@ export class GeneratedSdkLocalMcpClient implements LocalMcpProductClient {
|
|
|
849
856
|
requireScope(value.items.every((webhook) => webhook.environment === environment));
|
|
850
857
|
return value;
|
|
851
858
|
}
|
|
859
|
+
public async listDatabaseWatches(
|
|
860
|
+
input: Parameters<LocalMcpProductClient["listDatabaseWatches"]>[0],
|
|
861
|
+
) {
|
|
862
|
+
const environment = input.environment ?? "dev";
|
|
863
|
+
const value = await listProjectDatabaseWatches(
|
|
864
|
+
{ project_id: input.projectId, environment },
|
|
865
|
+
{ client: this.#client },
|
|
866
|
+
);
|
|
867
|
+
assertDatabaseWatchPage(value);
|
|
868
|
+
requireScope(value.items.every((watch) => watch.environment === environment));
|
|
869
|
+
return value;
|
|
870
|
+
}
|
|
871
|
+
public async createDatabaseWatch(
|
|
872
|
+
input: Parameters<LocalMcpProductClient["createDatabaseWatch"]>[0],
|
|
873
|
+
) {
|
|
874
|
+
const value = await createProjectDatabaseWatch(
|
|
875
|
+
{
|
|
876
|
+
project_id: input.projectId,
|
|
877
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
878
|
+
databaseWatchCreateRequest: {
|
|
879
|
+
environment: input.environment,
|
|
880
|
+
...(input.schema === undefined ? {} : { schema: input.schema }),
|
|
881
|
+
table: input.table,
|
|
882
|
+
columns: [...input.columns],
|
|
883
|
+
...(input.operations === undefined ? {} : { operations: [...input.operations] }),
|
|
884
|
+
},
|
|
885
|
+
},
|
|
886
|
+
{ client: this.#client },
|
|
887
|
+
);
|
|
888
|
+
assertDatabaseWatch(value);
|
|
889
|
+
requireScope(
|
|
890
|
+
value.environment === input.environment &&
|
|
891
|
+
value.table === input.table &&
|
|
892
|
+
value.schema === (input.schema ?? DATABASE_WATCH_DEFAULT_SCHEMA),
|
|
893
|
+
);
|
|
894
|
+
return value;
|
|
895
|
+
}
|
|
896
|
+
public async deleteDatabaseWatch(
|
|
897
|
+
input: Parameters<LocalMcpProductClient["deleteDatabaseWatch"]>[0],
|
|
898
|
+
) {
|
|
899
|
+
const value = await deleteProjectDatabaseWatch(
|
|
900
|
+
{
|
|
901
|
+
project_id: input.projectId,
|
|
902
|
+
environment: input.environment,
|
|
903
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
904
|
+
watch_id: input.watchId,
|
|
905
|
+
},
|
|
906
|
+
{ client: this.#client },
|
|
907
|
+
);
|
|
908
|
+
assertDatabaseWatchDeleted(value);
|
|
909
|
+
requireScope(value.id === input.watchId);
|
|
910
|
+
return value;
|
|
911
|
+
}
|
|
852
912
|
/** The signing secret exists only in this response and is never stored by the client. */
|
|
853
913
|
public async createDatabaseWebhook(
|
|
854
914
|
input: Parameters<LocalMcpProductClient["createDatabaseWebhook"]>[0],
|