@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
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-2GRH5YCK.js";
|
|
34
34
|
|
|
35
35
|
// node_modules/.pnpm/ignore@7.0.12/node_modules/ignore/index.js
|
|
36
36
|
var require_ignore = __commonJS({
|
|
@@ -24293,14 +24293,14 @@ function isFrameworkConversionDiagnosticCode(value) {
|
|
|
24293
24293
|
function parseFrameworkConversionDiagnostic(value) {
|
|
24294
24294
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
24295
24295
|
return null;
|
|
24296
|
-
const
|
|
24297
|
-
const code = Object.hasOwn(
|
|
24298
|
-
const path2 = Object.hasOwn(
|
|
24296
|
+
const record9 = value;
|
|
24297
|
+
const code = Object.hasOwn(record9, "code") ? record9["code"] : void 0;
|
|
24298
|
+
const path2 = Object.hasOwn(record9, "path") ? record9["path"] : void 0;
|
|
24299
24299
|
if (!isFrameworkConversionDiagnosticCode(code) || typeof path2 !== "string")
|
|
24300
24300
|
return null;
|
|
24301
24301
|
const definition = DETAIL_DEFINITIONS[code];
|
|
24302
|
-
const fields = Object.entries(definition.fields ?? {}).map(([name, grammar]) => [name, grammar, Object.hasOwn(
|
|
24303
|
-
if (Object.keys(
|
|
24302
|
+
const fields = Object.entries(definition.fields ?? {}).map(([name, grammar]) => [name, grammar, Object.hasOwn(record9, name) ? record9[name] : void 0]);
|
|
24303
|
+
if (Object.keys(record9).length !== fields.length + 2 || pathClassOf(definition, path2) === null || fields.some(([, grammar, field]) => !fieldMatches(grammar, field)))
|
|
24304
24304
|
return null;
|
|
24305
24305
|
return Object.freeze(Object.fromEntries([
|
|
24306
24306
|
["code", code],
|
|
@@ -25572,6 +25572,48 @@ 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
|
+
},
|
|
25605
|
+
database_table_conflict: {
|
|
25606
|
+
status: 409,
|
|
25607
|
+
retryable: false,
|
|
25608
|
+
action: "A table with this name already exists with another definition. Choose another table name, or create the table again with the same columns, types, nullability, identity, defaults and primary key it has.",
|
|
25609
|
+
title: "Table already exists with another definition"
|
|
25610
|
+
},
|
|
25611
|
+
database_table_limit: {
|
|
25612
|
+
status: 409,
|
|
25613
|
+
retryable: false,
|
|
25614
|
+
action: "This database already holds the maximum number of tables in its public schema, so no table can be added. Use an existing table, or remove a table you no longer need through a deployed migration, then create the table again.",
|
|
25615
|
+
title: "Database table limit reached"
|
|
25616
|
+
},
|
|
25575
25617
|
project_notes_conflict: {
|
|
25576
25618
|
status: 409,
|
|
25577
25619
|
retryable: false,
|
|
@@ -25836,7 +25878,7 @@ var PROBLEM_POLICY = {
|
|
|
25836
25878
|
api_key_permissions_unavailable: {
|
|
25837
25879
|
status: 503,
|
|
25838
25880
|
retryable: false,
|
|
25839
|
-
action: "Report the platform user-key permission configuration through feedback. Repeated login
|
|
25881
|
+
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
25882
|
title: "Token permissions unavailable"
|
|
25841
25883
|
},
|
|
25842
25884
|
reconciliation_exhausted: {
|
|
@@ -26255,8 +26297,8 @@ var isPaidValidationRecord = (value) => {
|
|
|
26255
26297
|
if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).sort().join(",") !== "content,name,purpose,type") {
|
|
26256
26298
|
return false;
|
|
26257
26299
|
}
|
|
26258
|
-
const
|
|
26259
|
-
return (
|
|
26300
|
+
const record9 = value;
|
|
26301
|
+
return (record9["type"] === "CNAME" || record9["type"] === "TXT") && boundedString(record9["name"], 1, 253) && boundedString(record9["content"], 1, 2048) && ["traffic", "ownership", "ssl", "dcv_delegation"].includes(String(record9["purpose"]));
|
|
26260
26302
|
};
|
|
26261
26303
|
|
|
26262
26304
|
// apps/product-cli/dist/source-publisher.js
|
|
@@ -26526,7 +26568,7 @@ async function prepareLocalSourcePublication(input) {
|
|
|
26526
26568
|
request = { ...request, expected_commit_sha: link2.source.last_confirmed_commit_sha };
|
|
26527
26569
|
}
|
|
26528
26570
|
parseManagedSourceRequest("upload", request);
|
|
26529
|
-
const
|
|
26571
|
+
const record9 = {
|
|
26530
26572
|
version: 1,
|
|
26531
26573
|
...scope,
|
|
26532
26574
|
operation_id: null,
|
|
@@ -26535,16 +26577,16 @@ async function prepareLocalSourcePublication(input) {
|
|
|
26535
26577
|
request
|
|
26536
26578
|
};
|
|
26537
26579
|
if (original !== null) {
|
|
26538
|
-
assertSameAttempt(original,
|
|
26580
|
+
assertSameAttempt(original, record9);
|
|
26539
26581
|
} else
|
|
26540
|
-
await writePending(
|
|
26582
|
+
await writePending(record9, true);
|
|
26541
26583
|
return {
|
|
26542
26584
|
request,
|
|
26543
26585
|
accepted: async (operation) => {
|
|
26544
26586
|
const current = await readPending(scope, replay);
|
|
26545
26587
|
if (current === null)
|
|
26546
26588
|
throw new LocalSourcePublicationError("source_publication_missing");
|
|
26547
|
-
assertSameAttempt(current,
|
|
26589
|
+
assertSameAttempt(current, record9);
|
|
26548
26590
|
if (current.operation_id !== null && current.operation_id !== operation.id)
|
|
26549
26591
|
throw new ResponseContractError();
|
|
26550
26592
|
if (!replay)
|
|
@@ -26563,7 +26605,7 @@ async function prepareLocalSourcePublication(input) {
|
|
|
26563
26605
|
const current = await readPending(scope);
|
|
26564
26606
|
if (current === null || current.operation_id !== null)
|
|
26565
26607
|
return;
|
|
26566
|
-
assertSameAttempt(current,
|
|
26608
|
+
assertSameAttempt(current, record9);
|
|
26567
26609
|
} catch (error2) {
|
|
26568
26610
|
if (error2 instanceof LocalSourcePublicationError && (error2.code === "source_publication_scope_mismatch" || error2.code === "source_publication_pending"))
|
|
26569
26611
|
return;
|
|
@@ -26766,12 +26808,12 @@ async function readRecord(path2) {
|
|
|
26766
26808
|
await handle?.close();
|
|
26767
26809
|
}
|
|
26768
26810
|
}
|
|
26769
|
-
async function writePending(
|
|
26770
|
-
const parent = join3(
|
|
26811
|
+
async function writePending(record9, create, completed = false) {
|
|
26812
|
+
const parent = join3(record9.directory, ".ohmyhost");
|
|
26771
26813
|
for (const directory of [
|
|
26772
26814
|
parent,
|
|
26773
|
-
|
|
26774
|
-
join3(
|
|
26815
|
+
record9.metadata_directory,
|
|
26816
|
+
join3(record9.metadata_directory, "publications")
|
|
26775
26817
|
]) {
|
|
26776
26818
|
try {
|
|
26777
26819
|
await fs2.mkdir(directory, { mode: 448 });
|
|
@@ -26782,10 +26824,10 @@ async function writePending(record8, create, completed = false) {
|
|
|
26782
26824
|
await checkedDirectory(directory);
|
|
26783
26825
|
await fs2.chmod(directory, 448);
|
|
26784
26826
|
}
|
|
26785
|
-
const target = completed ? completedPath(
|
|
26827
|
+
const target = completed ? completedPath(record9) : pendingPath(record9);
|
|
26786
26828
|
const temporary = create ? target : `${target}.${randomUUID()}.tmp`;
|
|
26787
26829
|
try {
|
|
26788
|
-
await fs2.writeFile(temporary, `${JSON.stringify(
|
|
26830
|
+
await fs2.writeFile(temporary, `${JSON.stringify(record9)}
|
|
26789
26831
|
`, { mode: 384, flag: "wx" });
|
|
26790
26832
|
if (!create)
|
|
26791
26833
|
await fs2.rename(temporary, target);
|
|
@@ -26915,7 +26957,7 @@ function exact2(value, keys) {
|
|
|
26915
26957
|
|
|
26916
26958
|
// packages/contracts/dist/credit-pricing.js
|
|
26917
26959
|
function assertOrganizationCreditUsage(value) {
|
|
26918
|
-
const
|
|
26960
|
+
const record9 = (input, keys) => {
|
|
26919
26961
|
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join() !== keys.split(",").sort().join())
|
|
26920
26962
|
throw new TypeError("Invalid usage fields");
|
|
26921
26963
|
return input;
|
|
@@ -26923,30 +26965,30 @@ function assertOrganizationCreditUsage(value) {
|
|
|
26923
26965
|
const identifier3 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
|
|
26924
26966
|
const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
|
|
26925
26967
|
const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
|
|
26926
|
-
const report =
|
|
26968
|
+
const report = record9(value, "organization_id,as_of,unit,period,from,projects,days");
|
|
26927
26969
|
if (!identifier3(report["organization_id"]) || !instant2(report["as_of"]) || !instant2(report["from"]) || report["unit"] !== "microcredits" || typeof report["period"] !== "string" || !/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(report["period"]) || !Array.isArray(report["projects"]) || report["projects"].length > 1e3 || !Array.isArray(report["days"]) || report["days"].length > 15)
|
|
26928
26970
|
throw new TypeError("Invalid usage report");
|
|
26929
26971
|
let previous = "";
|
|
26930
26972
|
for (const input of report["projects"]) {
|
|
26931
|
-
const project =
|
|
26973
|
+
const project = record9(input, "project_id,used_micros");
|
|
26932
26974
|
if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
|
|
26933
26975
|
throw new TypeError("Invalid usage project");
|
|
26934
26976
|
previous = String(project["project_id"]);
|
|
26935
26977
|
}
|
|
26936
26978
|
let previousDay = "";
|
|
26937
26979
|
for (const input of report["days"]) {
|
|
26938
|
-
const day =
|
|
26980
|
+
const day = record9(input, "day,projects");
|
|
26939
26981
|
if (typeof day["day"] !== "string" || !/^20[0-9]{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/u.test(day["day"]) || day["day"] <= previousDay || !Array.isArray(day["projects"]) || day["projects"].length > 1e3)
|
|
26940
26982
|
throw new TypeError("Invalid usage day");
|
|
26941
26983
|
previousDay = day["day"];
|
|
26942
26984
|
previous = "";
|
|
26943
26985
|
for (const projectInput of day["projects"]) {
|
|
26944
|
-
const project =
|
|
26986
|
+
const project = record9(projectInput, "project_id,meters");
|
|
26945
26987
|
if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
|
|
26946
26988
|
throw new TypeError("Invalid usage project");
|
|
26947
26989
|
previous = String(project["project_id"]);
|
|
26948
26990
|
for (const meterInput of project["meters"]) {
|
|
26949
|
-
const meter =
|
|
26991
|
+
const meter = record9(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
|
|
26950
26992
|
if (meter["environment_id"] !== null && !identifier3(meter["environment_id"]))
|
|
26951
26993
|
throw new TypeError("Invalid usage environment");
|
|
26952
26994
|
for (const key of ["meter", "unit", "rate_card_id"])
|
|
@@ -27093,6 +27135,9 @@ var DATABASE_WEBHOOK_EVENT_TYPES = [
|
|
|
27093
27135
|
"database.resized",
|
|
27094
27136
|
"database.deleted"
|
|
27095
27137
|
];
|
|
27138
|
+
var DATABASE_WATCH_OPERATIONS = ["insert", "update", "delete"];
|
|
27139
|
+
var DATABASE_WATCH_MAX_COLUMNS = 32;
|
|
27140
|
+
var DATABASE_WATCH_DEFAULT_SCHEMA = "public";
|
|
27096
27141
|
var DATABASE_WEBHOOK_MAX_EVENT_TYPES = 16;
|
|
27097
27142
|
var DATABASE_WEBHOOK_MAX_HEADERS = 8;
|
|
27098
27143
|
var DATABASE_WEBHOOK_URL_MAX_LENGTH = 2048;
|
|
@@ -27135,15 +27180,61 @@ var USAGE_MAX_RANGE_MS = 31 * 24 * USAGE_HOUR_MS;
|
|
|
27135
27180
|
var WEBHOOK_KEYS = ["id", "environment", "url", "event_types", "header_names", "created_at"];
|
|
27136
27181
|
var WEBHOOK_ID_PATTERN = /^whk_[a-z0-9]{20}$/u;
|
|
27137
27182
|
var DELIVERY_ID_PATTERN = /^dlv_[0-9a-f]{20}$/u;
|
|
27138
|
-
var EVENT_ID_PATTERN = /^evt_[0-9a-f]{20}$/u;
|
|
27183
|
+
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;
|
|
27184
|
+
var DATA_SUBSCRIPTION_PATTERN = /^data\.(?:\*|[a-z][a-z0-9_]{0,47})$/u;
|
|
27185
|
+
var DATA_EVENT_TYPE_PATTERN = /^data\.[a-z][a-z0-9_]{0,47}$/u;
|
|
27186
|
+
var DATABASE_WATCH_ID_PATTERN = /^pgcf_watch_[0-9a-f]{8}$/u;
|
|
27187
|
+
var DATABASE_WATCH_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/u;
|
|
27188
|
+
var DATABASE_WATCH_FORBIDDEN_SCHEMAS = ["information_schema", "pgcf", "ohmyhost"];
|
|
27189
|
+
var DATABASE_WATCH_KEYS = [
|
|
27190
|
+
"id",
|
|
27191
|
+
"environment",
|
|
27192
|
+
"schema",
|
|
27193
|
+
"table",
|
|
27194
|
+
"columns",
|
|
27195
|
+
"operations",
|
|
27196
|
+
"topic",
|
|
27197
|
+
"event_type"
|
|
27198
|
+
];
|
|
27139
27199
|
var SCHEDULE_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/u;
|
|
27140
27200
|
var CURSOR_PATTERN = /^[A-Za-z0-9._|:=+/-]{1,200}$/u;
|
|
27141
27201
|
var HEADER_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9-]{0,63}$/u;
|
|
27202
|
+
function isDatabaseWatchIdentifier(value) {
|
|
27203
|
+
return matches(value, DATABASE_WATCH_IDENTIFIER_PATTERN);
|
|
27204
|
+
}
|
|
27205
|
+
function isDatabaseWatchSchema(value) {
|
|
27206
|
+
if (!isDatabaseWatchIdentifier(value))
|
|
27207
|
+
return false;
|
|
27208
|
+
const lower = value.toLowerCase();
|
|
27209
|
+
return !lower.startsWith("pg_") && !DATABASE_WATCH_FORBIDDEN_SCHEMAS.includes(lower);
|
|
27210
|
+
}
|
|
27211
|
+
function dataEventTopic(tableName) {
|
|
27212
|
+
const mapped = Array.from(tableName, (character) => {
|
|
27213
|
+
const lower = Array.from(character.toLowerCase())[0] ?? "_";
|
|
27214
|
+
return /^[a-z0-9_]$/u.test(lower) ? lower : "_";
|
|
27215
|
+
}).join("");
|
|
27216
|
+
const topic = /^[a-z]/u.test(mapped) ? mapped : `t_${mapped}`;
|
|
27217
|
+
return topic.slice(0, 48);
|
|
27218
|
+
}
|
|
27142
27219
|
function assertDatabaseWebhook(value) {
|
|
27143
27220
|
if (!record4(value) || !exact4(value, WEBHOOK_KEYS))
|
|
27144
27221
|
throw new TypeError("Invalid database webhook");
|
|
27145
27222
|
assertWebhookFields(value);
|
|
27146
27223
|
}
|
|
27224
|
+
function assertDatabaseWatch(value) {
|
|
27225
|
+
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"]}`)
|
|
27226
|
+
throw new TypeError("Invalid database watch");
|
|
27227
|
+
}
|
|
27228
|
+
function assertDatabaseWatchPage(value) {
|
|
27229
|
+
if (!record4(value) || !exact4(value, ["items"]) || !pageItems(value["items"]))
|
|
27230
|
+
throw new TypeError("Invalid database watch page");
|
|
27231
|
+
for (const item of value["items"])
|
|
27232
|
+
assertDatabaseWatch(item);
|
|
27233
|
+
}
|
|
27234
|
+
function assertDatabaseWatchDeleted(value) {
|
|
27235
|
+
if (!record4(value) || !exact4(value, ["id", "deleted"]) || !matches(value["id"], DATABASE_WATCH_ID_PATTERN) || value["deleted"] !== true)
|
|
27236
|
+
throw new TypeError("Invalid database watch deletion");
|
|
27237
|
+
}
|
|
27147
27238
|
function assertDatabaseWebhookCreated(value) {
|
|
27148
27239
|
if (!record4(value) || !exact4(value, [...WEBHOOK_KEYS, "secret"]) || typeof value["secret"] !== "string" || value["secret"].length === 0)
|
|
27149
27240
|
throw new TypeError("Invalid database webhook");
|
|
@@ -27172,7 +27263,7 @@ function assertDatabaseWebhookDelivery(value) {
|
|
|
27172
27263
|
"delivered_at",
|
|
27173
27264
|
"last_status",
|
|
27174
27265
|
"last_error"
|
|
27175
|
-
]) || !matches(value["id"], DELIVERY_ID_PATTERN) || !matches(value["event_id"], EVENT_ID_PATTERN) || !
|
|
27266
|
+
]) || !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
27267
|
throw new TypeError("Invalid database webhook delivery");
|
|
27177
27268
|
}
|
|
27178
27269
|
function assertDatabaseWebhookDeliveryPage(value) {
|
|
@@ -27255,7 +27346,7 @@ function assertUsageRow(value) {
|
|
|
27255
27346
|
throw new TypeError("Invalid database execution usage row");
|
|
27256
27347
|
}
|
|
27257
27348
|
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(
|
|
27349
|
+
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
27350
|
throw new TypeError("Invalid database webhook");
|
|
27260
27351
|
}
|
|
27261
27352
|
function isHttpsUrl2(value) {
|
|
@@ -27267,6 +27358,18 @@ function isHttpsUrl2(value) {
|
|
|
27267
27358
|
return false;
|
|
27268
27359
|
}
|
|
27269
27360
|
}
|
|
27361
|
+
function isDatabaseWebhookEventPattern(value) {
|
|
27362
|
+
return oneOf(DATABASE_WEBHOOK_EVENT_TYPES, value) || matches(value, DATA_SUBSCRIPTION_PATTERN);
|
|
27363
|
+
}
|
|
27364
|
+
function isDeliveredEventType(value) {
|
|
27365
|
+
return oneOf(DATABASE_WEBHOOK_EVENT_TYPES, value) || matches(value, DATA_EVENT_TYPE_PATTERN);
|
|
27366
|
+
}
|
|
27367
|
+
function isCanonicalOperations(value) {
|
|
27368
|
+
if (!Array.isArray(value) || value.length < 1)
|
|
27369
|
+
return false;
|
|
27370
|
+
const canonical = DATABASE_WATCH_OPERATIONS.filter((operation) => value.includes(operation));
|
|
27371
|
+
return canonical.length === value.length && canonical.every((op, index) => op === value[index]);
|
|
27372
|
+
}
|
|
27270
27373
|
function isCronText(value) {
|
|
27271
27374
|
return typeof value === "string" && value.length >= DATABASE_SCHEDULE_CRON_MIN_LENGTH && value.length <= DATABASE_SCHEDULE_CRON_MAX_LENGTH;
|
|
27272
27375
|
}
|
|
@@ -27310,7 +27413,7 @@ function exact4(value, keys) {
|
|
|
27310
27413
|
// apps/product-cli/package.json
|
|
27311
27414
|
var package_default2 = {
|
|
27312
27415
|
name: "@ohmyhost/product-cli",
|
|
27313
|
-
version: "0.1.
|
|
27416
|
+
version: "0.1.46",
|
|
27314
27417
|
private: true,
|
|
27315
27418
|
ohmyhost: {
|
|
27316
27419
|
deployment: "production",
|
|
@@ -27759,6 +27862,170 @@ function expectPositiveInteger(value, field, options = {}) {
|
|
|
27759
27862
|
return value;
|
|
27760
27863
|
}
|
|
27761
27864
|
|
|
27865
|
+
// packages/contracts/dist/database-tables.js
|
|
27866
|
+
var DATABASE_TABLE_COLUMN_TYPES = [
|
|
27867
|
+
"text",
|
|
27868
|
+
"integer",
|
|
27869
|
+
"bigint",
|
|
27870
|
+
"boolean",
|
|
27871
|
+
"numeric",
|
|
27872
|
+
"double precision",
|
|
27873
|
+
"timestamptz",
|
|
27874
|
+
"date",
|
|
27875
|
+
"uuid",
|
|
27876
|
+
"jsonb"
|
|
27877
|
+
];
|
|
27878
|
+
var DATABASE_TABLE_DEFAULTS = ["now", "uuid"];
|
|
27879
|
+
var DATABASE_TABLE_MAX_COLUMNS = 64;
|
|
27880
|
+
var DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS = 8;
|
|
27881
|
+
var DATABASE_TABLE_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_]{0,62}$/u;
|
|
27882
|
+
var RESERVED_WORDS = /* @__PURE__ */ new Set([
|
|
27883
|
+
"all",
|
|
27884
|
+
"analyse",
|
|
27885
|
+
"analyze",
|
|
27886
|
+
"and",
|
|
27887
|
+
"any",
|
|
27888
|
+
"array",
|
|
27889
|
+
"as",
|
|
27890
|
+
"asc",
|
|
27891
|
+
"asymmetric",
|
|
27892
|
+
"both",
|
|
27893
|
+
"case",
|
|
27894
|
+
"cast",
|
|
27895
|
+
"check",
|
|
27896
|
+
"collate",
|
|
27897
|
+
"column",
|
|
27898
|
+
"constraint",
|
|
27899
|
+
"create",
|
|
27900
|
+
"current_catalog",
|
|
27901
|
+
"current_date",
|
|
27902
|
+
"current_role",
|
|
27903
|
+
"current_time",
|
|
27904
|
+
"current_timestamp",
|
|
27905
|
+
"current_user",
|
|
27906
|
+
"default",
|
|
27907
|
+
"deferrable",
|
|
27908
|
+
"desc",
|
|
27909
|
+
"distinct",
|
|
27910
|
+
"do",
|
|
27911
|
+
"else",
|
|
27912
|
+
"end",
|
|
27913
|
+
"except",
|
|
27914
|
+
"false",
|
|
27915
|
+
"fetch",
|
|
27916
|
+
"for",
|
|
27917
|
+
"foreign",
|
|
27918
|
+
"from",
|
|
27919
|
+
"grant",
|
|
27920
|
+
"group",
|
|
27921
|
+
"having",
|
|
27922
|
+
"in",
|
|
27923
|
+
"initially",
|
|
27924
|
+
"intersect",
|
|
27925
|
+
"into",
|
|
27926
|
+
"lateral",
|
|
27927
|
+
"leading",
|
|
27928
|
+
"limit",
|
|
27929
|
+
"localtime",
|
|
27930
|
+
"localtimestamp",
|
|
27931
|
+
"not",
|
|
27932
|
+
"null",
|
|
27933
|
+
"offset",
|
|
27934
|
+
"on",
|
|
27935
|
+
"only",
|
|
27936
|
+
"or",
|
|
27937
|
+
"order",
|
|
27938
|
+
"placing",
|
|
27939
|
+
"primary",
|
|
27940
|
+
"references",
|
|
27941
|
+
"returning",
|
|
27942
|
+
"select",
|
|
27943
|
+
"session_user",
|
|
27944
|
+
"some",
|
|
27945
|
+
"symmetric",
|
|
27946
|
+
"table",
|
|
27947
|
+
"then",
|
|
27948
|
+
"to",
|
|
27949
|
+
"trailing",
|
|
27950
|
+
"true",
|
|
27951
|
+
"union",
|
|
27952
|
+
"unique",
|
|
27953
|
+
"user",
|
|
27954
|
+
"using",
|
|
27955
|
+
"variadic",
|
|
27956
|
+
"when",
|
|
27957
|
+
"where",
|
|
27958
|
+
"window",
|
|
27959
|
+
"with"
|
|
27960
|
+
]);
|
|
27961
|
+
function isDatabaseTableIdentifier(value) {
|
|
27962
|
+
return typeof value === "string" && DATABASE_TABLE_IDENTIFIER_PATTERN.test(value) && !value.startsWith("pg_") && !RESERVED_WORDS.has(value);
|
|
27963
|
+
}
|
|
27964
|
+
function parseDatabaseTableCreateRequest(value) {
|
|
27965
|
+
if (!record7(value) || !onlyKeys(value, ["table", "columns", "primaryKey"]) || !isDatabaseTableIdentifier(value["table"]) || !Array.isArray(value["columns"]) || value["columns"].length < 1 || value["columns"].length > DATABASE_TABLE_MAX_COLUMNS)
|
|
27966
|
+
throw new TypeError("Invalid database table request");
|
|
27967
|
+
const inputs = value["columns"].map(parseColumn);
|
|
27968
|
+
const names = inputs.map((column) => column.name);
|
|
27969
|
+
if (new Set(names).size !== names.length || inputs.filter((column) => column.identity).length > 1)
|
|
27970
|
+
throw new TypeError("Invalid database table request");
|
|
27971
|
+
const primaryKey = parsePrimaryKey(value["primaryKey"], names);
|
|
27972
|
+
return {
|
|
27973
|
+
table: value["table"],
|
|
27974
|
+
columns: inputs.map((column) => completeColumn(column, primaryKey.includes(column.name))),
|
|
27975
|
+
primaryKey
|
|
27976
|
+
};
|
|
27977
|
+
}
|
|
27978
|
+
function parseColumn(value) {
|
|
27979
|
+
if (!record7(value) || !onlyKeys(value, ["name", "type", "nullable", "identity", "default"]) || !isDatabaseTableIdentifier(value["name"]) || !oneOf2(DATABASE_TABLE_COLUMN_TYPES, value["type"]) || value["nullable"] !== void 0 && typeof value["nullable"] !== "boolean" || value["identity"] !== void 0 && typeof value["identity"] !== "boolean" || value["default"] !== void 0 && !oneOf2(DATABASE_TABLE_DEFAULTS, value["default"]))
|
|
27980
|
+
throw new TypeError("Invalid database table request");
|
|
27981
|
+
const type = value["type"];
|
|
27982
|
+
const identity = value["identity"] === true;
|
|
27983
|
+
const defaultValue = value["default"] ?? null;
|
|
27984
|
+
if (identity && type !== "integer" && type !== "bigint")
|
|
27985
|
+
throw new TypeError("Invalid database table request");
|
|
27986
|
+
if (identity && defaultValue !== null)
|
|
27987
|
+
throw new TypeError("Invalid database table request");
|
|
27988
|
+
if (defaultValue === "now" && type !== "timestamptz")
|
|
27989
|
+
throw new TypeError("Invalid database table request");
|
|
27990
|
+
if (defaultValue === "uuid" && type !== "uuid")
|
|
27991
|
+
throw new TypeError("Invalid database table request");
|
|
27992
|
+
return {
|
|
27993
|
+
name: value["name"],
|
|
27994
|
+
type,
|
|
27995
|
+
nullable: value["nullable"],
|
|
27996
|
+
identity,
|
|
27997
|
+
default: defaultValue
|
|
27998
|
+
};
|
|
27999
|
+
}
|
|
28000
|
+
function parsePrimaryKey(value, names) {
|
|
28001
|
+
if (value === void 0)
|
|
28002
|
+
return [];
|
|
28003
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS || new Set(value).size !== value.length || !value.every((name) => typeof name === "string" && names.includes(name)))
|
|
28004
|
+
throw new TypeError("Invalid database table request");
|
|
28005
|
+
return value;
|
|
28006
|
+
}
|
|
28007
|
+
function completeColumn(column, keyed) {
|
|
28008
|
+
const required = column.identity || keyed;
|
|
28009
|
+
if (required && column.nullable === true)
|
|
28010
|
+
throw new TypeError("Invalid database table request");
|
|
28011
|
+
return {
|
|
28012
|
+
name: column.name,
|
|
28013
|
+
type: column.type,
|
|
28014
|
+
nullable: required ? false : column.nullable ?? true,
|
|
28015
|
+
identity: column.identity,
|
|
28016
|
+
default: column.default
|
|
28017
|
+
};
|
|
28018
|
+
}
|
|
28019
|
+
function oneOf2(allowed, value) {
|
|
28020
|
+
return typeof value === "string" && allowed.includes(value);
|
|
28021
|
+
}
|
|
28022
|
+
function record7(value) {
|
|
28023
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28024
|
+
}
|
|
28025
|
+
function onlyKeys(value, allowed) {
|
|
28026
|
+
return Object.keys(value).every((key) => allowed.includes(key));
|
|
28027
|
+
}
|
|
28028
|
+
|
|
27762
28029
|
// packages/workos-auth-contracts/dist/user-api-keys.js
|
|
27763
28030
|
var WORKOS_USER_API_KEY_PATTERN = /^sk_[A-Za-z0-9_-]{20,128}$/u;
|
|
27764
28031
|
|
|
@@ -28424,7 +28691,11 @@ var HELP_USAGE = Object.freeze({
|
|
|
28424
28691
|
"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
28692
|
"database access list": "ohmyhost database access list --project ULID [--environment dev|prod] --json",
|
|
28426
28693
|
"database access revoke": "ohmyhost database access revoke --project ULID --access ULID --yes --json",
|
|
28427
|
-
"database
|
|
28694
|
+
"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>')",
|
|
28695
|
+
"database watch list": "ohmyhost database watch list --project ULID [--environment dev|prod] --json (dev when omitted; a sleeping database wakes)",
|
|
28696
|
+
"database watch delete": "ohmyhost database watch delete --project ULID --environment dev|prod --watch ID --idempotency-key KEY --yes --json",
|
|
28697
|
+
"database table create": "ohmyhost database table create --project ULID --environment dev|prod --table NAME --columns-file PATH [--primary-key COL[,COL]] --idempotency-key KEY --yes --json (the table is created in the public schema as the migration role, with the same access as migration tables, so a database watch can attach later; the columns file is a UTF-8 JSON array of 1 to 64 column objects, at most 64 KiB, each with name, type and optional nullable, identity and default; types: text, integer, bigint, boolean, numeric, double precision, timestamptz, date, uuid, jsonb; identity needs integer or bigint; default now needs timestamptz and default uuid needs uuid; identical repeats answer created false; at most 100 tables, 64 columns per table)",
|
|
28698
|
+
"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
28699
|
"database webhook list": "ohmyhost database webhook list --project ULID [--environment dev|prod] --json (dev when omitted; the secret is never listed)",
|
|
28429
28700
|
"database webhook get": "ohmyhost database webhook get --project ULID [--environment dev|prod] --webhook ID --json",
|
|
28430
28701
|
"database webhook delete": "ohmyhost database webhook delete --project ULID --environment dev|prod --webhook ID --yes --json",
|
|
@@ -28566,12 +28837,12 @@ function buildClientParams(args, fields) {
|
|
|
28566
28837
|
};
|
|
28567
28838
|
const map = buildKeyMap(fields);
|
|
28568
28839
|
function writeSlot(slot, key, value) {
|
|
28569
|
-
let
|
|
28570
|
-
if (
|
|
28571
|
-
|
|
28572
|
-
params[slot] =
|
|
28840
|
+
let record9 = params[slot];
|
|
28841
|
+
if (record9 === void 0) {
|
|
28842
|
+
record9 = /* @__PURE__ */ Object.create(null);
|
|
28843
|
+
params[slot] = record9;
|
|
28573
28844
|
}
|
|
28574
|
-
|
|
28845
|
+
record9[key] = value;
|
|
28575
28846
|
}
|
|
28576
28847
|
let config;
|
|
28577
28848
|
for (const [index, arg] of args.entries()) {
|
|
@@ -31218,6 +31489,92 @@ var revokeProjectDatabaseAccess = (parameters, options) => {
|
|
|
31218
31489
|
...params
|
|
31219
31490
|
});
|
|
31220
31491
|
};
|
|
31492
|
+
var createProjectDatabaseTable = (parameters, options) => {
|
|
31493
|
+
const params = buildClientParams([parameters], [
|
|
31494
|
+
{
|
|
31495
|
+
args: [
|
|
31496
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
31497
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
31498
|
+
{ in: "path", key: "project_id" },
|
|
31499
|
+
{ key: "databaseTableCreateRequest", map: "body" }
|
|
31500
|
+
]
|
|
31501
|
+
}
|
|
31502
|
+
]);
|
|
31503
|
+
return (options?.client ?? client).post({
|
|
31504
|
+
responseStyle: "data",
|
|
31505
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
31506
|
+
url: "/v1/projects/{project_id}/database/tables",
|
|
31507
|
+
...options,
|
|
31508
|
+
...params,
|
|
31509
|
+
headers: {
|
|
31510
|
+
"Content-Type": "application/json",
|
|
31511
|
+
...options?.headers,
|
|
31512
|
+
...params.headers
|
|
31513
|
+
}
|
|
31514
|
+
});
|
|
31515
|
+
};
|
|
31516
|
+
var listProjectDatabaseWatches = (parameters, options) => {
|
|
31517
|
+
const params = buildClientParams([parameters], [
|
|
31518
|
+
{
|
|
31519
|
+
args: [
|
|
31520
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
31521
|
+
{ in: "path", key: "project_id" },
|
|
31522
|
+
{ in: "query", key: "environment" }
|
|
31523
|
+
]
|
|
31524
|
+
}
|
|
31525
|
+
]);
|
|
31526
|
+
return (options?.client ?? client).get({
|
|
31527
|
+
responseStyle: "data",
|
|
31528
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
31529
|
+
url: "/v1/projects/{project_id}/database/watches",
|
|
31530
|
+
...options,
|
|
31531
|
+
...params
|
|
31532
|
+
});
|
|
31533
|
+
};
|
|
31534
|
+
var createProjectDatabaseWatch = (parameters, options) => {
|
|
31535
|
+
const params = buildClientParams([parameters], [
|
|
31536
|
+
{
|
|
31537
|
+
args: [
|
|
31538
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
31539
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
31540
|
+
{ in: "path", key: "project_id" },
|
|
31541
|
+
{ key: "databaseWatchCreateRequest", map: "body" }
|
|
31542
|
+
]
|
|
31543
|
+
}
|
|
31544
|
+
]);
|
|
31545
|
+
return (options?.client ?? client).post({
|
|
31546
|
+
responseStyle: "data",
|
|
31547
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
31548
|
+
url: "/v1/projects/{project_id}/database/watches",
|
|
31549
|
+
...options,
|
|
31550
|
+
...params,
|
|
31551
|
+
headers: {
|
|
31552
|
+
"Content-Type": "application/json",
|
|
31553
|
+
...options?.headers,
|
|
31554
|
+
...params.headers
|
|
31555
|
+
}
|
|
31556
|
+
});
|
|
31557
|
+
};
|
|
31558
|
+
var deleteProjectDatabaseWatch = (parameters, options) => {
|
|
31559
|
+
const params = buildClientParams([parameters], [
|
|
31560
|
+
{
|
|
31561
|
+
args: [
|
|
31562
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
31563
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
31564
|
+
{ in: "path", key: "project_id" },
|
|
31565
|
+
{ in: "path", key: "watch_id" },
|
|
31566
|
+
{ in: "query", key: "environment" }
|
|
31567
|
+
]
|
|
31568
|
+
}
|
|
31569
|
+
]);
|
|
31570
|
+
return (options?.client ?? client).delete({
|
|
31571
|
+
responseStyle: "data",
|
|
31572
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
31573
|
+
url: "/v1/projects/{project_id}/database/watches/{watch_id}",
|
|
31574
|
+
...options,
|
|
31575
|
+
...params
|
|
31576
|
+
});
|
|
31577
|
+
};
|
|
31221
31578
|
var listProjectDatabaseWebhooks = (parameters, options) => {
|
|
31222
31579
|
const params = buildClientParams([parameters], [
|
|
31223
31580
|
{
|
|
@@ -32622,7 +32979,25 @@ function checkedResponse(kind, value) {
|
|
|
32622
32979
|
|
|
32623
32980
|
// apps/product-cli/dist/product-api.js
|
|
32624
32981
|
var WEBHOOK_SCOPE_MISMATCH = "Webhook response scope mismatch";
|
|
32982
|
+
var WATCH_SCOPE_MISMATCH = "Watch response scope mismatch";
|
|
32983
|
+
var TABLE_SCOPE_MISMATCH = "Table response scope mismatch";
|
|
32625
32984
|
var SCHEDULE_SCOPE_MISMATCH = "Schedule response scope mismatch";
|
|
32985
|
+
function assertDatabaseTableAnswer(value) {
|
|
32986
|
+
const table = isRecordValue(value) ? value["table"] : void 0;
|
|
32987
|
+
const columns = isRecordValue(table) ? table["columns"] : void 0;
|
|
32988
|
+
const primaryKey = isRecordValue(table) ? table["primary_key"] : void 0;
|
|
32989
|
+
if (!isRecordValue(table) || !hasExactKeys(table, ["environment", "schema", "table", "columns", "primary_key", "created"]) || table["environment"] !== "dev" && table["environment"] !== "prod" || table["schema"] !== "public" || !isDatabaseTableIdentifier(table["table"]) || typeof table["created"] !== "boolean" || !Array.isArray(columns) || columns.length < 1 || !columns.every(isDatabaseTableAnswerColumn) || !Array.isArray(primaryKey) || !primaryKey.every((name) => columns.some((column) => column["name"] === name)))
|
|
32990
|
+
throw new TypeError("Invalid database table answer");
|
|
32991
|
+
}
|
|
32992
|
+
function isDatabaseTableAnswerColumn(value) {
|
|
32993
|
+
return isRecordValue(value) && hasExactKeys(value, ["name", "type", "nullable", "identity", "default"]) && isDatabaseTableIdentifier(value["name"]) && DATABASE_TABLE_COLUMN_TYPES.includes(value["type"]) && typeof value["nullable"] === "boolean" && typeof value["identity"] === "boolean" && (value["default"] === null || DATABASE_TABLE_DEFAULTS.includes(value["default"]));
|
|
32994
|
+
}
|
|
32995
|
+
function isRecordValue(value) {
|
|
32996
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32997
|
+
}
|
|
32998
|
+
function hasExactKeys(value, keys) {
|
|
32999
|
+
return Object.keys(value).sort().join(",") === [...keys].sort().join(",");
|
|
33000
|
+
}
|
|
32626
33001
|
var GeneratedSdkProductApi = class {
|
|
32627
33002
|
#client;
|
|
32628
33003
|
managedSource;
|
|
@@ -32819,6 +33194,58 @@ var GeneratedSdkProductApi = class {
|
|
|
32819
33194
|
assertProjectDatabaseAccess(value);
|
|
32820
33195
|
return value;
|
|
32821
33196
|
}
|
|
33197
|
+
async createProjectDatabaseWatch(input) {
|
|
33198
|
+
const value = await createProjectDatabaseWatch({
|
|
33199
|
+
project_id: input.projectId,
|
|
33200
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
33201
|
+
databaseWatchCreateRequest: {
|
|
33202
|
+
environment: input.environment,
|
|
33203
|
+
schema: input.request.schema,
|
|
33204
|
+
table: input.request.table,
|
|
33205
|
+
columns: [...input.request.columns],
|
|
33206
|
+
operations: [...input.request.operations]
|
|
33207
|
+
}
|
|
33208
|
+
}, { client: this.#client });
|
|
33209
|
+
assertDatabaseWatch(value);
|
|
33210
|
+
if (value.environment !== input.environment || value.schema !== input.request.schema || value.table !== input.request.table)
|
|
33211
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
33212
|
+
return value;
|
|
33213
|
+
}
|
|
33214
|
+
async listProjectDatabaseWatches(input) {
|
|
33215
|
+
const value = await listProjectDatabaseWatches({ project_id: input.projectId, environment: input.environment }, { client: this.#client });
|
|
33216
|
+
assertDatabaseWatchPage(value);
|
|
33217
|
+
if (value.items.some((item) => item.environment !== input.environment))
|
|
33218
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
33219
|
+
return value;
|
|
33220
|
+
}
|
|
33221
|
+
async deleteProjectDatabaseWatch(input) {
|
|
33222
|
+
const value = await deleteProjectDatabaseWatch({
|
|
33223
|
+
project_id: input.projectId,
|
|
33224
|
+
environment: input.environment,
|
|
33225
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
33226
|
+
watch_id: input.watchId
|
|
33227
|
+
}, { client: this.#client });
|
|
33228
|
+
assertDatabaseWatchDeleted(value);
|
|
33229
|
+
if (value.id !== input.watchId)
|
|
33230
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
33231
|
+
return value;
|
|
33232
|
+
}
|
|
33233
|
+
async createProjectDatabaseTable(input) {
|
|
33234
|
+
const value = await createProjectDatabaseTable({
|
|
33235
|
+
project_id: input.projectId,
|
|
33236
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
33237
|
+
databaseTableCreateRequest: {
|
|
33238
|
+
environment: input.environment,
|
|
33239
|
+
table: input.request.table,
|
|
33240
|
+
columns: [...input.request.columns],
|
|
33241
|
+
...input.request.primaryKey.length === 0 ? {} : { primary_key: [...input.request.primaryKey] }
|
|
33242
|
+
}
|
|
33243
|
+
}, { client: this.#client });
|
|
33244
|
+
assertDatabaseTableAnswer(value);
|
|
33245
|
+
if (value.table.environment !== input.environment || value.table.table !== input.request.table)
|
|
33246
|
+
throw new TypeError(TABLE_SCOPE_MISMATCH);
|
|
33247
|
+
return value;
|
|
33248
|
+
}
|
|
32822
33249
|
/** The signing secret exists only in this answer; the CLI prints it once and stores nothing. */
|
|
32823
33250
|
async createProjectDatabaseWebhook(input) {
|
|
32824
33251
|
const value = await createProjectDatabaseWebhook({
|
|
@@ -34096,6 +34523,55 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
34096
34523
|
requireScope(value.items.every((webhook) => webhook.environment === environment2));
|
|
34097
34524
|
return value;
|
|
34098
34525
|
}
|
|
34526
|
+
async listDatabaseWatches(input) {
|
|
34527
|
+
const environment2 = input.environment ?? "dev";
|
|
34528
|
+
const value = await listProjectDatabaseWatches({ project_id: input.projectId, environment: environment2 }, { client: this.#client });
|
|
34529
|
+
assertDatabaseWatchPage(value);
|
|
34530
|
+
requireScope(value.items.every((watch) => watch.environment === environment2));
|
|
34531
|
+
return value;
|
|
34532
|
+
}
|
|
34533
|
+
async createDatabaseWatch(input) {
|
|
34534
|
+
const value = await createProjectDatabaseWatch({
|
|
34535
|
+
project_id: input.projectId,
|
|
34536
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
34537
|
+
databaseWatchCreateRequest: {
|
|
34538
|
+
environment: input.environment,
|
|
34539
|
+
...input.schema === void 0 ? {} : { schema: input.schema },
|
|
34540
|
+
table: input.table,
|
|
34541
|
+
columns: [...input.columns],
|
|
34542
|
+
...input.operations === void 0 ? {} : { operations: [...input.operations] }
|
|
34543
|
+
}
|
|
34544
|
+
}, { client: this.#client });
|
|
34545
|
+
assertDatabaseWatch(value);
|
|
34546
|
+
requireScope(value.environment === input.environment && value.table === input.table && value.schema === (input.schema ?? DATABASE_WATCH_DEFAULT_SCHEMA));
|
|
34547
|
+
return value;
|
|
34548
|
+
}
|
|
34549
|
+
async createDatabaseTable(input) {
|
|
34550
|
+
const value = await createProjectDatabaseTable({
|
|
34551
|
+
project_id: input.projectId,
|
|
34552
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
34553
|
+
databaseTableCreateRequest: {
|
|
34554
|
+
environment: input.environment,
|
|
34555
|
+
table: input.table,
|
|
34556
|
+
columns: [...input.columns],
|
|
34557
|
+
...input.primaryKey === void 0 || input.primaryKey.length === 0 ? {} : { primary_key: [...input.primaryKey] }
|
|
34558
|
+
}
|
|
34559
|
+
}, { client: this.#client });
|
|
34560
|
+
assertDatabaseTableAnswer(value);
|
|
34561
|
+
requireScope(value.table.environment === input.environment && value.table.table === input.table);
|
|
34562
|
+
return value;
|
|
34563
|
+
}
|
|
34564
|
+
async deleteDatabaseWatch(input) {
|
|
34565
|
+
const value = await deleteProjectDatabaseWatch({
|
|
34566
|
+
project_id: input.projectId,
|
|
34567
|
+
environment: input.environment,
|
|
34568
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
34569
|
+
watch_id: input.watchId
|
|
34570
|
+
}, { client: this.#client });
|
|
34571
|
+
assertDatabaseWatchDeleted(value);
|
|
34572
|
+
requireScope(value.id === input.watchId);
|
|
34573
|
+
return value;
|
|
34574
|
+
}
|
|
34099
34575
|
/** The signing secret exists only in this response and is never stored by the client. */
|
|
34100
34576
|
async createDatabaseWebhook(input) {
|
|
34101
34577
|
const value = await createProjectDatabaseWebhook({
|
|
@@ -34445,13 +34921,13 @@ function normalizeMcpSourceChanges(value) {
|
|
|
34445
34921
|
}
|
|
34446
34922
|
}
|
|
34447
34923
|
function normalizeSourceChanges(value) {
|
|
34448
|
-
const body =
|
|
34924
|
+
const body = record8(value);
|
|
34449
34925
|
const changes = body["changes"];
|
|
34450
34926
|
if (!Array.isArray(changes) || changes.length < 1 || changes.length > MANAGED_SOURCE_LIMITS.files)
|
|
34451
34927
|
invalid7();
|
|
34452
34928
|
let textBytes = 0;
|
|
34453
34929
|
const normalized = changes.map((change) => {
|
|
34454
|
-
const entry =
|
|
34930
|
+
const entry = record8(change);
|
|
34455
34931
|
const hasText = Object.hasOwn(entry, "content_text");
|
|
34456
34932
|
if (hasText === Object.hasOwn(entry, "content_base64"))
|
|
34457
34933
|
invalid7();
|
|
@@ -34510,7 +34986,7 @@ function encodeBase64(bytes) {
|
|
|
34510
34986
|
binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
|
|
34511
34987
|
return btoa(binary);
|
|
34512
34988
|
}
|
|
34513
|
-
function
|
|
34989
|
+
function record8(value) {
|
|
34514
34990
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
34515
34991
|
invalid7();
|
|
34516
34992
|
return value;
|
|
@@ -34523,7 +34999,10 @@ function invalid7() {
|
|
|
34523
34999
|
var identifier2 = external_exports.string().min(1).max(256);
|
|
34524
35000
|
var databaseEnvironment = external_exports.enum(["dev", "prod"]);
|
|
34525
35001
|
var databaseWebhookId = external_exports.string().regex(/^whk_[a-z0-9]{20}$/u);
|
|
35002
|
+
var databaseWatchId = external_exports.string().regex(/^pgcf_watch_[0-9a-f]{8}$/u);
|
|
35003
|
+
var databaseIdentifier = external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,62}$/u);
|
|
34526
35004
|
var databaseDeliveryId = external_exports.string().regex(/^dlv_[0-9a-f]{20}$/u);
|
|
35005
|
+
var databaseTableIdentifier = external_exports.string().refine(isDatabaseTableIdentifier);
|
|
34527
35006
|
var databaseScheduleName = external_exports.string().regex(/^[a-z][a-z0-9_-]{0,62}$/u);
|
|
34528
35007
|
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.");
|
|
34529
35008
|
var idempotencyKey = external_exports.string().min(1).max(128);
|
|
@@ -34774,15 +35253,81 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
34774
35253
|
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
34775
35254
|
}));
|
|
34776
35255
|
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());
|
|
35256
|
+
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({
|
|
35257
|
+
projectId: input.project_id,
|
|
35258
|
+
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
35259
|
+
}));
|
|
35260
|
+
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({
|
|
35261
|
+
project_id: identifier2,
|
|
35262
|
+
environment: databaseEnvironment,
|
|
35263
|
+
schema: databaseIdentifier.refine(isDatabaseWatchSchema).optional(),
|
|
35264
|
+
table: databaseIdentifier,
|
|
35265
|
+
columns: external_exports.array(databaseIdentifier).min(1).max(32).refine((columns) => new Set(columns).size === columns.length),
|
|
35266
|
+
operations: external_exports.array(external_exports.enum(DATABASE_WATCH_OPERATIONS)).min(1).max(3).refine((operations) => new Set(operations).size === operations.length).optional(),
|
|
35267
|
+
idempotency_key: idempotencyKey,
|
|
35268
|
+
confirmed: external_exports.literal(true)
|
|
35269
|
+
}), (client2, input) => client2.createDatabaseWatch({
|
|
35270
|
+
projectId: input.project_id,
|
|
35271
|
+
environment: input.environment,
|
|
35272
|
+
...input.schema === void 0 ? {} : { schema: input.schema },
|
|
35273
|
+
table: input.table,
|
|
35274
|
+
columns: input.columns,
|
|
35275
|
+
...input.operations === void 0 ? {} : { operations: input.operations },
|
|
35276
|
+
idempotencyKey: input.idempotency_key
|
|
35277
|
+
}), mutationAnnotations());
|
|
35278
|
+
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({
|
|
35279
|
+
project_id: identifier2,
|
|
35280
|
+
environment: databaseEnvironment,
|
|
35281
|
+
watch_id: databaseWatchId,
|
|
35282
|
+
idempotency_key: idempotencyKey,
|
|
35283
|
+
confirmed: external_exports.literal(true)
|
|
35284
|
+
}), (client2, input) => client2.deleteDatabaseWatch({
|
|
35285
|
+
projectId: input.project_id,
|
|
35286
|
+
environment: input.environment,
|
|
35287
|
+
watchId: input.watch_id,
|
|
35288
|
+
idempotencyKey: input.idempotency_key
|
|
35289
|
+
}), destructiveAnnotations());
|
|
35290
|
+
registerProductTool(server, dependencies, "database_table_create", "Create one ordinary table in the public schema of a Dev or Prod database, as the migration role with the same access as migration tables, so a database_watch_create can attach later. Each column has a lower-case name, a type (text, integer, bigint, boolean, numeric, double precision, timestamptz, date, uuid or jsonb) and optional nullable, identity (integer or bigint only) and default (now for timestamptz, uuid for uuid); at most 64 columns, 8 primary-key columns and 100 tables per database. An identical repeat answers created: false; a table of the same name with another definition is refused with database_table_conflict. Tables created this way are not in the repository's migration files: record them in project notes and add a migration when the source should reproduce the database. Requires confirmed: true and an idempotency key. Refused with project_budget_exceeded while the Stop budget is reached.", external_exports.object({
|
|
35291
|
+
project_id: identifier2,
|
|
35292
|
+
environment: databaseEnvironment,
|
|
35293
|
+
table: databaseTableIdentifier,
|
|
35294
|
+
columns: external_exports.array(external_exports.object({
|
|
35295
|
+
name: databaseTableIdentifier,
|
|
35296
|
+
type: external_exports.enum(DATABASE_TABLE_COLUMN_TYPES),
|
|
35297
|
+
nullable: external_exports.boolean().optional(),
|
|
35298
|
+
identity: external_exports.boolean().optional(),
|
|
35299
|
+
default: external_exports.enum(DATABASE_TABLE_DEFAULTS).optional()
|
|
35300
|
+
})).min(1).max(DATABASE_TABLE_MAX_COLUMNS),
|
|
35301
|
+
primary_key: external_exports.array(databaseTableIdentifier).min(1).max(DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS).optional(),
|
|
35302
|
+
idempotency_key: idempotencyKey,
|
|
35303
|
+
confirmed: external_exports.literal(true)
|
|
35304
|
+
}), (client2, input) => {
|
|
35305
|
+
const request = parseDatabaseTableCreateRequest({
|
|
35306
|
+
table: input.table,
|
|
35307
|
+
columns: input.columns,
|
|
35308
|
+
...input.primary_key === void 0 ? {} : { primaryKey: input.primary_key }
|
|
35309
|
+
});
|
|
35310
|
+
return client2.createDatabaseTable({
|
|
35311
|
+
projectId: input.project_id,
|
|
35312
|
+
environment: input.environment,
|
|
35313
|
+
table: request.table,
|
|
35314
|
+
columns: input.columns,
|
|
35315
|
+
...request.primaryKey.length === 0 ? {} : { primaryKey: request.primaryKey },
|
|
35316
|
+
idempotencyKey: input.idempotency_key
|
|
35317
|
+
});
|
|
35318
|
+
}, mutationAnnotations());
|
|
34777
35319
|
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
35320
|
projectId: input.project_id,
|
|
34779
35321
|
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
34780
35322
|
}));
|
|
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({
|
|
35323
|
+
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
35324
|
project_id: identifier2,
|
|
34783
35325
|
environment: databaseEnvironment,
|
|
34784
35326
|
url: external_exports.string().max(2048).regex(/^https:\/\//u),
|
|
34785
|
-
event_types: external_exports.array(external_exports.
|
|
35327
|
+
event_types: external_exports.array(external_exports.union([
|
|
35328
|
+
external_exports.enum(DATABASE_WEBHOOK_EVENT_TYPES),
|
|
35329
|
+
external_exports.string().regex(/^data\.(?:\*|[a-z][a-z0-9_]{0,47})$/u).refine(isDatabaseWebhookEventPattern)
|
|
35330
|
+
])).min(1).max(16),
|
|
34786
35331
|
headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
34787
35332
|
idempotency_key: idempotencyKey,
|
|
34788
35333
|
confirmed: external_exports.literal(true)
|