@amerged/ohmyhost-mcp 0.1.40 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,7 +30,7 @@ import {
30
30
  serverIdentityOf,
31
31
  setNegotiatedProtocolVersion,
32
32
  validateEnvelopeMeta
33
- } from "./chunk-OW4IDEWK.js";
33
+ } from "./chunk-OD4R3WMQ.js";
34
34
 
35
35
  // node_modules/.pnpm/ignore@7.0.12/node_modules/ignore/index.js
36
36
  var require_ignore = __commonJS({
@@ -9034,17 +9034,17 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
9034
9034
  var VARIABLE_NAME_REGEX = /^[A-Za-z][A-Za-z-]*$/;
9035
9035
  var VARIABLE_VALUE_COMMENT_REGEX = /^(.*?)( *[#;].*)$/;
9036
9036
  var extractSectionLine = (line) => {
9037
- const matches = SECTION_LINE_REGEX.exec(line);
9038
- if (matches != null) {
9039
- const [section, subsection] = matches.slice(1);
9037
+ const matches2 = SECTION_LINE_REGEX.exec(line);
9038
+ if (matches2 != null) {
9039
+ const [section, subsection] = matches2.slice(1);
9040
9040
  return [section, subsection];
9041
9041
  }
9042
9042
  return null;
9043
9043
  };
9044
9044
  var extractVariableLine = (line) => {
9045
- const matches = VARIABLE_LINE_REGEX.exec(line);
9046
- if (matches != null) {
9047
- const [name, rawValue = "true"] = matches.slice(1);
9045
+ const matches2 = VARIABLE_LINE_REGEX.exec(line);
9046
+ if (matches2 != null) {
9047
+ const [name, rawValue = "true"] = matches2.slice(1);
9048
9048
  const valueWithoutComments = removeComments(rawValue);
9049
9049
  const valueWithoutQuotes = removeQuotes(valueWithoutComments);
9050
9050
  return [name, valueWithoutQuotes];
@@ -10663,14 +10663,14 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
10663
10663
  * @param {string} short
10664
10664
  * @param {string[]} matches
10665
10665
  */
10666
- constructor(nouns, short, matches) {
10666
+ constructor(nouns, short, matches2) {
10667
10667
  super(
10668
- `Found multiple ${nouns} matching "${short}" (${matches.join(
10668
+ `Found multiple ${nouns} matching "${short}" (${matches2.join(
10669
10669
  ", "
10670
10670
  )}). Use a longer abbreviation length to disambiguate them.`
10671
10671
  );
10672
10672
  this.code = this.name = _AmbiguousError.code;
10673
- this.data = { nouns, short, matches };
10673
+ this.data = { nouns, short, matches: matches2 };
10674
10674
  }
10675
10675
  };
10676
10676
  AmbiguousError.code = "AmbiguousError";
@@ -11043,9 +11043,9 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
11043
11043
  IndexResetError,
11044
11044
  NoCommitError
11045
11045
  });
11046
- function formatAuthor({ name, email, timestamp: timestamp6, timezoneOffset }) {
11046
+ function formatAuthor({ name, email, timestamp: timestamp7, timezoneOffset }) {
11047
11047
  timezoneOffset = formatTimezoneOffset(timezoneOffset);
11048
- return `${name} <${email}> ${timestamp6} ${timezoneOffset}`;
11048
+ return `${name} <${email}> ${timestamp7} ${timezoneOffset}`;
11049
11049
  }
11050
11050
  function formatTimezoneOffset(minutes) {
11051
11051
  const sign = simpleSign(negateExceptForZero(minutes));
@@ -11071,13 +11071,13 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
11071
11071
  return str;
11072
11072
  }
11073
11073
  function parseAuthor(author) {
11074
- const [, name, email, timestamp6, offset] = author.match(
11074
+ const [, name, email, timestamp7, offset] = author.match(
11075
11075
  /^(.*) <(.*)> (.*) (.*)$/
11076
11076
  );
11077
11077
  return {
11078
11078
  name,
11079
11079
  email,
11080
- timestamp: Number(timestamp6),
11080
+ timestamp: Number(timestamp7),
11081
11081
  timezoneOffset: parseTimezoneOffset(offset)
11082
11082
  };
11083
11083
  }
@@ -12417,13 +12417,13 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
12417
12417
  return target;
12418
12418
  }
12419
12419
  async function normalizeAuthorObject({ fs: fs3, gitdir, author, commit: commit3 }) {
12420
- const timestamp6 = Math.floor(Date.now() / 1e3);
12420
+ const timestamp7 = Math.floor(Date.now() / 1e3);
12421
12421
  const defaultAuthor = {
12422
12422
  name: await _getConfig({ fs: fs3, gitdir, path: "user.name" }),
12423
12423
  email: await _getConfig({ fs: fs3, gitdir, path: "user.email" }) || "",
12424
12424
  // author.email is allowed to be empty string
12425
- timestamp: timestamp6,
12426
- timezoneOffset: new Date(timestamp6 * 1e3).getTimezoneOffset()
12425
+ timestamp: timestamp7,
12426
+ timezoneOffset: new Date(timestamp7 * 1e3).getTimezoneOffset()
12427
12427
  };
12428
12428
  const normalizedAuthor = assignDefined(
12429
12429
  {},
@@ -12443,13 +12443,13 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
12443
12443
  committer,
12444
12444
  commit: commit3
12445
12445
  }) {
12446
- const timestamp6 = Math.floor(Date.now() / 1e3);
12446
+ const timestamp7 = Math.floor(Date.now() / 1e3);
12447
12447
  const defaultCommitter = {
12448
12448
  name: await _getConfig({ fs: fs3, gitdir, path: "user.name" }),
12449
12449
  email: await _getConfig({ fs: fs3, gitdir, path: "user.email" }) || "",
12450
12450
  // committer.email is allowed to be empty string
12451
- timestamp: timestamp6,
12452
- timezoneOffset: new Date(timestamp6 * 1e3).getTimezoneOffset()
12451
+ timestamp: timestamp7,
12452
+ timezoneOffset: new Date(timestamp7 * 1e3).getTimezoneOffset()
12453
12453
  };
12454
12454
  const normalizedCommitter = assignDefined(
12455
12455
  {},
@@ -14916,18 +14916,18 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
14916
14916
  address: url
14917
14917
  };
14918
14918
  }
14919
- const matches = url.match(/(\w+)(:\/\/|::)(.*)/);
14920
- if (matches === null) return;
14921
- if (matches[2] === "://") {
14919
+ const matches2 = url.match(/(\w+)(:\/\/|::)(.*)/);
14920
+ if (matches2 === null) return;
14921
+ if (matches2[2] === "://") {
14922
14922
  return {
14923
- transport: matches[1],
14924
- address: matches[0]
14923
+ transport: matches2[1],
14924
+ address: matches2[0]
14925
14925
  };
14926
14926
  }
14927
- if (matches[2] === "::") {
14927
+ if (matches2[2] === "::") {
14928
14928
  return {
14929
- transport: matches[1],
14930
- address: matches[3]
14929
+ transport: matches2[1],
14930
+ address: matches2[3]
14931
14931
  };
14932
14932
  }
14933
14933
  }
@@ -15552,12 +15552,12 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
15552
15552
  forAwait(lines, async (line) => {
15553
15553
  if (onMessage) await onMessage(line);
15554
15554
  if (onProgress) {
15555
- const matches = line.match(/([^:]*).*\((\d+?)\/(\d+?)\)/);
15556
- if (matches) {
15555
+ const matches2 = line.match(/([^:]*).*\((\d+?)\/(\d+?)\)/);
15556
+ if (matches2) {
15557
15557
  await onProgress({
15558
- phase: matches[1].trim(),
15559
- loaded: parseInt(matches[2], 10),
15560
- total: parseInt(matches[3], 10)
15558
+ phase: matches2[1].trim(),
15559
+ loaded: parseInt(matches2[2], 10),
15560
+ total: parseInt(matches2[3], 10)
15561
15561
  });
15562
15562
  }
15563
15563
  }
@@ -18626,9 +18626,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
18626
18626
  static createStashReflogEntry(author, stashCommit, message) {
18627
18627
  const nameNoSpace = author.name.replace(/\s/g, "");
18628
18628
  const z40 = "0000000000000000000000000000000000000000";
18629
- const timestamp6 = Math.floor(Date.now() / 1e3);
18629
+ const timestamp7 = Math.floor(Date.now() / 1e3);
18630
18630
  const timezoneOffset = _GitRefStash.timezoneOffsetForRefLogEntry;
18631
- return `${z40} ${stashCommit} ${nameNoSpace} ${author.email} ${timestamp6} ${timezoneOffset} ${message}
18631
+ return `${z40} ${stashCommit} ${nameNoSpace} ${author.email} ${timestamp7} ${timezoneOffset} ${message}
18632
18632
  `;
18633
18633
  }
18634
18634
  static getStashReflogEntry(reflogString, parsed = false) {
@@ -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 record7 = value;
24297
- const code = Object.hasOwn(record7, "code") ? record7["code"] : void 0;
24298
- const path2 = Object.hasOwn(record7, "path") ? record7["path"] : void 0;
24296
+ const record8 = value;
24297
+ const code = Object.hasOwn(record8, "code") ? record8["code"] : void 0;
24298
+ const path2 = Object.hasOwn(record8, "path") ? record8["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(record7, name) ? record7[name] : void 0]);
24303
- if (Object.keys(record7).length !== fields.length + 2 || pathClassOf(definition, path2) === null || fields.some(([, grammar, field]) => !fieldMatches(grammar, field)))
24302
+ const fields = Object.entries(definition.fields ?? {}).map(([name, grammar]) => [name, grammar, Object.hasOwn(record8, name) ? record8[name] : void 0]);
24303
+ if (Object.keys(record8).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],
@@ -24803,8 +24803,8 @@ function ulid(value) {
24803
24803
  if (typeof value !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(value))
24804
24804
  invalid();
24805
24805
  }
24806
- function commit(value, nullable = false) {
24807
- if (nullable && value === null)
24806
+ function commit(value, nullable2 = false) {
24807
+ if (nullable2 && value === null)
24808
24808
  return;
24809
24809
  if (typeof value !== "string" || !/^[a-f0-9]{40}$/u.test(value))
24810
24810
  invalid();
@@ -25410,38 +25410,48 @@ function isSaasCnameTarget(value) {
25410
25410
 
25411
25411
  // packages/contracts/dist/credit-pricing.js
25412
25412
  function assertOrganizationCreditUsage(value) {
25413
- const record7 = (input, keys) => {
25413
+ const record8 = (input, keys) => {
25414
25414
  if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join() !== keys.split(",").sort().join())
25415
25415
  throw new TypeError("Invalid usage fields");
25416
25416
  return input;
25417
25417
  };
25418
25418
  const identifier3 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
25419
25419
  const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
25420
- const report = record7(value, "organization_id,month,as_of,unit,data,next_cursor");
25421
- if (!identifier3(report["organization_id"]) || typeof report["month"] !== "string" || !/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(report["month"]) || typeof report["as_of"] !== "string" || !Number.isFinite(Date.parse(report["as_of"])) || new Date(report["as_of"]).toISOString() !== report["as_of"] || report["unit"] !== "microcredits" || !Array.isArray(report["data"]) || report["data"].length > 20 || report["next_cursor"] !== null && !identifier3(report["next_cursor"]))
25420
+ const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
25421
+ const report = record8(value, "organization_id,as_of,unit,period,from,projects,days");
25422
+ 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)
25422
25423
  throw new TypeError("Invalid usage report");
25423
25424
  let previous = "";
25424
- for (const input of report["data"]) {
25425
- const project = record7(input, "project_id,reserved_micros,meters");
25426
- if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["reserved_micros"]) || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
25425
+ for (const input of report["projects"]) {
25426
+ const project = record8(input, "project_id,used_micros");
25427
+ if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
25427
25428
  throw new TypeError("Invalid usage project");
25428
25429
  previous = String(project["project_id"]);
25429
- for (const input2 of project["meters"]) {
25430
- const meter = record7(input2, "environment_id,meter,unit,rate_card_id,quantity,charged_micros,funded_micros,platform_overrun_micros");
25431
- if (meter["environment_id"] !== null && !identifier3(meter["environment_id"]))
25432
- throw new TypeError("Invalid usage environment");
25433
- for (const key of ["meter", "unit", "rate_card_id"])
25434
- if (typeof meter[key] !== "string" || !/^[A-Za-z0-9_.:/-]{1,128}$/u.test(meter[key]))
25435
- throw new TypeError("Invalid usage meter");
25436
- for (const key of ["quantity", "charged_micros", "funded_micros", "platform_overrun_micros"])
25437
- if (!amount(meter[key]))
25430
+ }
25431
+ let previousDay = "";
25432
+ for (const input of report["days"]) {
25433
+ const day = record8(input, "day,projects");
25434
+ 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)
25435
+ throw new TypeError("Invalid usage day");
25436
+ previousDay = day["day"];
25437
+ previous = "";
25438
+ for (const projectInput of day["projects"]) {
25439
+ const project = record8(projectInput, "project_id,meters");
25440
+ if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
25441
+ throw new TypeError("Invalid usage project");
25442
+ previous = String(project["project_id"]);
25443
+ for (const meterInput of project["meters"]) {
25444
+ const meter = record8(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
25445
+ if (meter["environment_id"] !== null && !identifier3(meter["environment_id"]))
25446
+ throw new TypeError("Invalid usage environment");
25447
+ for (const key of ["meter", "unit", "rate_card_id"])
25448
+ if (typeof meter[key] !== "string" || !/^[A-Za-z0-9_.:/-]{1,128}$/u.test(meter[key]))
25449
+ throw new TypeError("Invalid usage meter");
25450
+ if (typeof meter["quantity"] !== "string" || !/^(0|[1-9][0-9]{0,29})(\.[0-9]{1,12})?$/u.test(meter["quantity"]) || !amount(meter["charged_micros"]))
25438
25451
  throw new TypeError("Invalid usage amount");
25439
- if (BigInt(String(meter["charged_micros"])) !== BigInt(String(meter["funded_micros"])) + BigInt(String(meter["platform_overrun_micros"])))
25440
- throw new TypeError("Inconsistent usage charge");
25452
+ }
25441
25453
  }
25442
25454
  }
25443
- if (report["next_cursor"] !== null && report["next_cursor"] !== previous)
25444
- throw new TypeError("Invalid usage cursor");
25445
25455
  }
25446
25456
  function assertOrganizationAccount(value) {
25447
25457
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== "as_of,available_micros,monthly_micros,name,next_expiry,one_time_micros,organization_id,paid_until,plan,plan_source,reserved_micros,workos_organization_id")
@@ -25452,7 +25462,9 @@ function assertOrganizationAccount(value) {
25452
25462
  for (const field of ["available_micros", "monthly_micros", "one_time_micros", "reserved_micros"])
25453
25463
  if (typeof v[field] !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(v[field]))
25454
25464
  throw new TypeError("Invalid account credits");
25455
- if (BigInt(String(v["monthly_micros"])) + BigInt(String(v["one_time_micros"])) !== BigInt(String(v["available_micros"])))
25465
+ const held = BigInt(String(v["reserved_micros"]));
25466
+ const balance = BigInt(String(v["monthly_micros"])) + BigInt(String(v["one_time_micros"]));
25467
+ if (BigInt(String(v["available_micros"])) !== (balance > held ? balance - held : 0n))
25456
25468
  throw new TypeError("Account credit buckets do not balance");
25457
25469
  for (const field of ["as_of", "paid_until", "next_expiry"]) {
25458
25470
  if (field !== "as_of" && v[field] === null)
@@ -25602,6 +25614,30 @@ var PROBLEM_POLICY = {
25602
25614
  action: "List the project's database credentials and revoke one you no longer need, then request access again.",
25603
25615
  title: "Database access limit reached"
25604
25616
  },
25617
+ database_webhook_limit: {
25618
+ status: 409,
25619
+ retryable: false,
25620
+ action: "List the project's database webhooks for this environment and delete one you no longer need, then create the webhook again.",
25621
+ title: "Database webhook limit reached"
25622
+ },
25623
+ database_schedule_limit: {
25624
+ status: 409,
25625
+ retryable: false,
25626
+ action: "List the project's database schedules for this environment and delete one you no longer need, then set the schedule again.",
25627
+ title: "Database schedule limit reached"
25628
+ },
25629
+ database_schedule_not_runnable: {
25630
+ status: 409,
25631
+ retryable: false,
25632
+ action: "Read the schedule and its runs. Enable a disabled schedule, or wait until the run already queued has finished, then request the run again.",
25633
+ title: "Database schedule cannot run now"
25634
+ },
25635
+ database_webhook_delivery_pending: {
25636
+ status: 409,
25637
+ retryable: false,
25638
+ 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.",
25639
+ title: "Webhook delivery still pending"
25640
+ },
25605
25641
  project_notes_conflict: {
25606
25642
  status: 409,
25607
25643
  retryable: false,
@@ -26285,8 +26321,8 @@ var isPaidValidationRecord = (value) => {
26285
26321
  if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).sort().join(",") !== "content,name,purpose,type") {
26286
26322
  return false;
26287
26323
  }
26288
- const record7 = value;
26289
- return (record7["type"] === "CNAME" || record7["type"] === "TXT") && boundedString(record7["name"], 1, 253) && boundedString(record7["content"], 1, 2048) && ["traffic", "ownership", "ssl", "dcv_delegation"].includes(String(record7["purpose"]));
26324
+ const record8 = value;
26325
+ return (record8["type"] === "CNAME" || record8["type"] === "TXT") && boundedString(record8["name"], 1, 253) && boundedString(record8["content"], 1, 2048) && ["traffic", "ownership", "ssl", "dcv_delegation"].includes(String(record8["purpose"]));
26290
26326
  };
26291
26327
 
26292
26328
  // apps/product-cli/dist/source-publisher.js
@@ -26556,7 +26592,7 @@ async function prepareLocalSourcePublication(input) {
26556
26592
  request = { ...request, expected_commit_sha: link2.source.last_confirmed_commit_sha };
26557
26593
  }
26558
26594
  parseManagedSourceRequest("upload", request);
26559
- const record7 = {
26595
+ const record8 = {
26560
26596
  version: 1,
26561
26597
  ...scope,
26562
26598
  operation_id: null,
@@ -26565,16 +26601,16 @@ async function prepareLocalSourcePublication(input) {
26565
26601
  request
26566
26602
  };
26567
26603
  if (original !== null) {
26568
- assertSameAttempt(original, record7);
26604
+ assertSameAttempt(original, record8);
26569
26605
  } else
26570
- await writePending(record7, true);
26606
+ await writePending(record8, true);
26571
26607
  return {
26572
26608
  request,
26573
26609
  accepted: async (operation) => {
26574
26610
  const current = await readPending(scope, replay);
26575
26611
  if (current === null)
26576
26612
  throw new LocalSourcePublicationError("source_publication_missing");
26577
- assertSameAttempt(current, record7);
26613
+ assertSameAttempt(current, record8);
26578
26614
  if (current.operation_id !== null && current.operation_id !== operation.id)
26579
26615
  throw new ResponseContractError();
26580
26616
  if (!replay)
@@ -26593,7 +26629,7 @@ async function prepareLocalSourcePublication(input) {
26593
26629
  const current = await readPending(scope);
26594
26630
  if (current === null || current.operation_id !== null)
26595
26631
  return;
26596
- assertSameAttempt(current, record7);
26632
+ assertSameAttempt(current, record8);
26597
26633
  } catch (error2) {
26598
26634
  if (error2 instanceof LocalSourcePublicationError && (error2.code === "source_publication_scope_mismatch" || error2.code === "source_publication_pending"))
26599
26635
  return;
@@ -26796,12 +26832,12 @@ async function readRecord(path2) {
26796
26832
  await handle?.close();
26797
26833
  }
26798
26834
  }
26799
- async function writePending(record7, create, completed = false) {
26800
- const parent = join3(record7.directory, ".ohmyhost");
26835
+ async function writePending(record8, create, completed = false) {
26836
+ const parent = join3(record8.directory, ".ohmyhost");
26801
26837
  for (const directory of [
26802
26838
  parent,
26803
- record7.metadata_directory,
26804
- join3(record7.metadata_directory, "publications")
26839
+ record8.metadata_directory,
26840
+ join3(record8.metadata_directory, "publications")
26805
26841
  ]) {
26806
26842
  try {
26807
26843
  await fs2.mkdir(directory, { mode: 448 });
@@ -26812,10 +26848,10 @@ async function writePending(record7, create, completed = false) {
26812
26848
  await checkedDirectory(directory);
26813
26849
  await fs2.chmod(directory, 448);
26814
26850
  }
26815
- const target = completed ? completedPath(record7) : pendingPath(record7);
26851
+ const target = completed ? completedPath(record8) : pendingPath(record8);
26816
26852
  const temporary = create ? target : `${target}.${randomUUID()}.tmp`;
26817
26853
  try {
26818
- await fs2.writeFile(temporary, `${JSON.stringify(record7)}
26854
+ await fs2.writeFile(temporary, `${JSON.stringify(record8)}
26819
26855
  `, { mode: 384, flag: "wx" });
26820
26856
  if (!create)
26821
26857
  await fs2.rename(temporary, target);
@@ -26879,6 +26915,9 @@ var ACCESS_KEYS = [
26879
26915
  "mode",
26880
26916
  "role_name",
26881
26917
  "host",
26918
+ "provider",
26919
+ "transport",
26920
+ "websocket_url",
26882
26921
  "database",
26883
26922
  "label",
26884
26923
  "state",
@@ -26889,16 +26928,16 @@ var ACCESS_KEYS = [
26889
26928
  ];
26890
26929
  var ACCESS_ROLE_PATTERN = /^ohmyho_da_[0-7][0-9a-hjkmnp-tv-z]{25}_[0-9a-z]{8}$/u;
26891
26930
  function assertProjectDatabaseAccess(value) {
26892
- if (!record2(value) || !exact2(value, accessKeys(value)))
26931
+ if (!record2(value) || !exact2(value, ACCESS_KEYS))
26893
26932
  throw new TypeError("Invalid database access");
26894
26933
  assertAccessFields(value);
26895
26934
  }
26896
26935
  function assertProjectDatabaseAccessCredential(value) {
26897
- if (!record2(value) || !exact2(value, [...accessKeys(value), "connection_uri", "psql_command"]))
26936
+ if (!record2(value) || !exact2(value, [...ACCESS_KEYS, "connection_uri", "psql_command"]))
26898
26937
  throw new TypeError("Invalid database access credential");
26899
26938
  assertAccessFields(value);
26900
26939
  const uri = value["connection_uri"];
26901
- if (typeof uri !== "string" || (value["provider"] === "pgcf" ? typeof value["psql_command"] !== "string" || !new RegExp(`^ohmyhost database psql --project [0-7][0-9A-HJKMNP-TV-Z]{25} --environment ${value["environment"]} --mode ${value["mode"]}$`, "u").test(value["psql_command"]) : value["psql_command"] !== `psql '${uri}'`))
26940
+ if (typeof uri !== "string" || typeof value["psql_command"] !== "string" || !new RegExp(`^ohmyhost database psql --project [0-7][0-9A-HJKMNP-TV-Z]{25} --environment ${value["environment"]} --mode ${value["mode"]}$`, "u").test(value["psql_command"]))
26902
26941
  throw new TypeError("Invalid database access credential");
26903
26942
  let parsed;
26904
26943
  try {
@@ -26906,7 +26945,7 @@ function assertProjectDatabaseAccessCredential(value) {
26906
26945
  } catch {
26907
26946
  throw new TypeError("Invalid database access credential");
26908
26947
  }
26909
- if ((value["provider"] === "pgcf" ? !["postgres:", "postgresql:"].includes(parsed.protocol) : parsed.protocol !== "postgresql:") || decodeURIComponent(parsed.username) !== value["role_name"] || parsed.password === "" || parsed.hostname !== value["host"] || (value["provider"] === "pgcf" ? parsed.port !== "" && parsed.port !== "5432" : parsed.host !== value["host"]) || decodeURIComponent(parsed.pathname.slice(1)) !== value["database"] || parsed.hash !== "" || (value["provider"] === "pgcf" ? !["", "?sslmode=require", "?sslmode=verify-full"].includes(parsed.search) : parsed.search !== "?sslmode=require"))
26948
+ if (!["postgres:", "postgresql:"].includes(parsed.protocol) || decodeURIComponent(parsed.username) !== value["role_name"] || parsed.password === "" || parsed.hostname !== value["host"] || parsed.port !== "" && parsed.port !== "5432" || decodeURIComponent(parsed.pathname.slice(1)) !== value["database"] || parsed.hash !== "" || !["", "?sslmode=require", "?sslmode=verify-full"].includes(parsed.search))
26910
26949
  throw new TypeError("Invalid database access credential");
26911
26950
  }
26912
26951
  function assertProjectDatabaseAccessPage(value) {
@@ -26915,12 +26954,9 @@ function assertProjectDatabaseAccessPage(value) {
26915
26954
  for (const item of value["items"])
26916
26955
  assertProjectDatabaseAccess(item);
26917
26956
  }
26918
- function accessKeys(value) {
26919
- return value["provider"] === "pgcf" ? [...ACCESS_KEYS, "provider", "transport", "websocket_url"] : ACCESS_KEYS;
26920
- }
26921
26957
  function assertAccessFields(value) {
26922
26958
  const revoked = value["revoked_at"], reason = value["revocation_reason"];
26923
- if (typeof value["access_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(value["access_id"]) || !["dev", "prod"].includes(String(value["environment"])) || !["read", "write"].includes(String(value["mode"])) || typeof value["role_name"] !== "string" || !ACCESS_ROLE_PATTERN.test(value["role_name"]) || typeof value["host"] !== "string" || !/^[a-z0-9]([a-z0-9.-]{0,251}[a-z0-9])?$/u.test(value["host"]) || (value["provider"] === "pgcf" ? typeof value["database"] !== "string" || !/^[a-z][a-z0-9]{19}$/u.test(value["database"]) || value["transport"] !== "wss" || value["websocket_url"] !== `wss://${value["host"]}/` : value["database"] !== "neondb") || value["label"] !== null && accessLabel(value["label"]) !== value["label"] || !["active", "expired", "revoked"].includes(String(value["state"])) || !timestamp2(value["issued_at"]) || !timestamp2(value["expires_at"]) || Date.parse(String(value["expires_at"])) <= Date.parse(String(value["issued_at"])) || revoked !== null && !timestamp2(revoked) || revoked === null !== (reason === null) || reason !== null && !["principal", "expired", "budget", "creation_failed", "data_change"].includes(String(reason)) || value["state"] === "revoked" !== (revoked !== null))
26959
+ if (typeof value["access_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(value["access_id"]) || !["dev", "prod"].includes(String(value["environment"])) || !["read", "write"].includes(String(value["mode"])) || typeof value["role_name"] !== "string" || !ACCESS_ROLE_PATTERN.test(value["role_name"]) || typeof value["host"] !== "string" || !/^[a-z0-9]([a-z0-9.-]{0,251}[a-z0-9])?$/u.test(value["host"]) || value["provider"] !== "pgcf" || value["transport"] !== "wss" || value["websocket_url"] !== `wss://${value["host"]}/` || typeof value["database"] !== "string" || !/^[a-z][a-z0-9]{19}$/u.test(value["database"]) || value["label"] !== null && accessLabel(value["label"]) !== value["label"] || !["active", "expired", "revoked"].includes(String(value["state"])) || !timestamp2(value["issued_at"]) || !timestamp2(value["expires_at"]) || Date.parse(String(value["expires_at"])) <= Date.parse(String(value["issued_at"])) || revoked !== null && !timestamp2(revoked) || revoked === null !== (reason === null) || reason !== null && !["principal", "expired", "budget", "creation_failed", "data_change"].includes(String(reason)) || value["state"] === "revoked" !== (revoked !== null))
26924
26960
  throw new TypeError("Invalid database access");
26925
26961
  }
26926
26962
  function accessLabel(value) {
@@ -27047,10 +27083,234 @@ function exact3(v, keys) {
27047
27083
  return Object.keys(v).sort().join(",") === keys.join(",");
27048
27084
  }
27049
27085
 
27086
+ // packages/contracts/dist/database-events.js
27087
+ var DATABASE_WEBHOOK_EVENT_TYPES = [
27088
+ "database.created",
27089
+ "database.ready",
27090
+ "database.woke",
27091
+ "database.slept",
27092
+ "database.suspended",
27093
+ "database.resized",
27094
+ "database.deleted"
27095
+ ];
27096
+ var DATABASE_WEBHOOK_MAX_EVENT_TYPES = 16;
27097
+ var DATABASE_WEBHOOK_MAX_HEADERS = 8;
27098
+ var DATABASE_WEBHOOK_URL_MAX_LENGTH = 2048;
27099
+ var DATABASE_SCHEDULE_MIN_EVERY_SECONDS = 60;
27100
+ var DATABASE_SCHEDULE_MAX_EVERY_SECONDS = 31 * 86400;
27101
+ var DATABASE_SCHEDULE_CRON_MIN_LENGTH = 9;
27102
+ var DATABASE_SCHEDULE_CRON_MAX_LENGTH = 120;
27103
+ var DATABASE_SCHEDULE_MAX_STATEMENTS = 20;
27104
+ var DATABASE_SCHEDULE_STATEMENT_MAX_BYTES = 16 * 1024;
27105
+ var DATABASE_SCHEDULE_STATEMENTS_MAX_BYTES = 64 * 1024;
27106
+ var DATABASE_SCHEDULE_MIN_TIMEOUT_MS = 1e3;
27107
+ var DATABASE_SCHEDULE_MAX_TIMEOUT_MS = 3e4;
27108
+ var DATABASE_SCHEDULE_OUTCOMES = [
27109
+ "succeeded",
27110
+ "failed",
27111
+ "timed_out",
27112
+ "outcome_unknown",
27113
+ "rejected",
27114
+ "skipped_capacity",
27115
+ "skipped_suspended",
27116
+ "skipped_deleted",
27117
+ "skipped_missed"
27118
+ ];
27119
+ var DATABASE_EXECUTION_METRICS = [
27120
+ "schedule_runs_succeeded",
27121
+ "schedule_runs_failed",
27122
+ "schedule_runs_timed_out",
27123
+ "schedule_runs_outcome_unknown",
27124
+ "schedule_runs_rejected",
27125
+ "schedule_runs_skipped",
27126
+ "events_emitted",
27127
+ "event_bytes",
27128
+ "webhook_attempts",
27129
+ "webhook_deliveries_delivered",
27130
+ "webhook_deliveries_dead_lettered"
27131
+ ];
27132
+ var DATABASE_PAGE_MAX_ITEMS = 100;
27133
+ var USAGE_HOUR_MS = 36e5;
27134
+ var USAGE_MAX_RANGE_MS = 31 * 24 * USAGE_HOUR_MS;
27135
+ var WEBHOOK_KEYS = ["id", "environment", "url", "event_types", "header_names", "created_at"];
27136
+ var WEBHOOK_ID_PATTERN = /^whk_[a-z0-9]{20}$/u;
27137
+ var DELIVERY_ID_PATTERN = /^dlv_[0-9a-f]{20}$/u;
27138
+ var EVENT_ID_PATTERN = /^evt_[0-9a-f]{20}$/u;
27139
+ var SCHEDULE_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/u;
27140
+ var CURSOR_PATTERN = /^[A-Za-z0-9._|:=+/-]{1,200}$/u;
27141
+ var HEADER_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9-]{0,63}$/u;
27142
+ function assertDatabaseWebhook(value) {
27143
+ if (!record4(value) || !exact4(value, WEBHOOK_KEYS))
27144
+ throw new TypeError("Invalid database webhook");
27145
+ assertWebhookFields(value);
27146
+ }
27147
+ function assertDatabaseWebhookCreated(value) {
27148
+ if (!record4(value) || !exact4(value, [...WEBHOOK_KEYS, "secret"]) || typeof value["secret"] !== "string" || value["secret"].length === 0)
27149
+ throw new TypeError("Invalid database webhook");
27150
+ assertWebhookFields(value);
27151
+ }
27152
+ function assertDatabaseWebhookPage(value) {
27153
+ if (!record4(value) || !exact4(value, ["items"]) || !pageItems(value["items"]))
27154
+ throw new TypeError("Invalid database webhook page");
27155
+ for (const item of value["items"])
27156
+ assertDatabaseWebhook(item);
27157
+ }
27158
+ function assertDatabaseWebhookDeleted(value) {
27159
+ if (!record4(value) || !exact4(value, ["id", "deleted"]) || !matches(value["id"], WEBHOOK_ID_PATTERN) || value["deleted"] !== true)
27160
+ throw new TypeError("Invalid database webhook deletion");
27161
+ }
27162
+ function assertDatabaseWebhookDelivery(value) {
27163
+ if (!record4(value) || !exact4(value, [
27164
+ "id",
27165
+ "event_id",
27166
+ "event_type",
27167
+ "webhook_id",
27168
+ "state",
27169
+ "attempts",
27170
+ "created_at",
27171
+ "next_attempt_at",
27172
+ "delivered_at",
27173
+ "last_status",
27174
+ "last_error"
27175
+ ]) || !matches(value["id"], DELIVERY_ID_PATTERN) || !matches(value["event_id"], EVENT_ID_PATTERN) || !oneOf(DATABASE_WEBHOOK_EVENT_TYPES, 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
+ throw new TypeError("Invalid database webhook delivery");
27177
+ }
27178
+ function assertDatabaseWebhookDeliveryPage(value) {
27179
+ if (!record4(value) || !exact4(value, ["items", "next_cursor"]) || !pageItems(value["items"]))
27180
+ throw new TypeError("Invalid database webhook delivery page");
27181
+ for (const item of value["items"])
27182
+ assertDatabaseWebhookDelivery(item);
27183
+ if (!nullable(value["next_cursor"], isCursor))
27184
+ throw new TypeError("Invalid database webhook delivery page");
27185
+ }
27186
+ function assertDatabaseWebhookTest(value) {
27187
+ if (!record4(value) || !exact4(value, ["delivered", "status", "error", "duration_ms"]) || typeof value["delivered"] !== "boolean" || !nullable(value["status"], Number.isSafeInteger) || !nullable(value["error"], (error) => oneOf(["timeout", "network", "http"], error)) || !nonNegativeInteger(value["duration_ms"]))
27188
+ throw new TypeError("Invalid database webhook test result");
27189
+ }
27190
+ function assertDatabaseWebhookReplayAccepted(value) {
27191
+ if (!record4(value) || !exact4(value, ["delivery_id", "state"]) || !matches(value["delivery_id"], DELIVERY_ID_PATTERN) || value["state"] !== "pending")
27192
+ throw new TypeError("Invalid database webhook replay");
27193
+ }
27194
+ function assertDatabaseSchedule(value) {
27195
+ if (!record4(value) || !exact4(value, [
27196
+ "name",
27197
+ "environment",
27198
+ "cron",
27199
+ "every_seconds",
27200
+ "statements",
27201
+ "timeout_ms",
27202
+ "enabled",
27203
+ "next_run_at",
27204
+ "created_at"
27205
+ ]) || !matches(value["name"], SCHEDULE_NAME_PATTERN) || !oneOf(["dev", "prod"], value["environment"]) || value["cron"] === null === (value["every_seconds"] === null) || !nullable(value["cron"], isCronText) || !nullable(value["every_seconds"], isEverySeconds) || !Array.isArray(value["statements"]) || value["statements"].length > DATABASE_SCHEDULE_MAX_STATEMENTS || !value["statements"].every((statement) => typeof statement === "string") || !isTimeout(value["timeout_ms"]) || typeof value["enabled"] !== "boolean" || !nullable(value["next_run_at"], timestamp3) || !timestamp3(value["created_at"]))
27206
+ throw new TypeError("Invalid database schedule");
27207
+ }
27208
+ function assertDatabaseSchedulePage(value) {
27209
+ if (!record4(value) || !exact4(value, ["items"]) || !pageItems(value["items"]))
27210
+ throw new TypeError("Invalid database schedule page");
27211
+ for (const item of value["items"])
27212
+ assertDatabaseSchedule(item);
27213
+ }
27214
+ function assertDatabaseScheduleDeleted(value) {
27215
+ if (!record4(value) || !exact4(value, ["name", "deleted"]) || !matches(value["name"], SCHEDULE_NAME_PATTERN) || value["deleted"] !== true)
27216
+ throw new TypeError("Invalid database schedule deletion");
27217
+ }
27218
+ function assertDatabaseScheduleRunPage(value) {
27219
+ if (!record4(value) || !exact4(value, ["items"]) || !pageItems(value["items"]))
27220
+ throw new TypeError("Invalid database schedule run page");
27221
+ for (const item of value["items"])
27222
+ assertDatabaseScheduleRun(item);
27223
+ }
27224
+ function assertDatabaseScheduleRunAccepted(value) {
27225
+ if (!record4(value) || !exact4(value, ["schedule", "state"]) || !matches(value["schedule"], SCHEDULE_NAME_PATTERN) || value["state"] !== "queued")
27226
+ throw new TypeError("Invalid database schedule run");
27227
+ }
27228
+ function assertDatabaseExecutionUsagePage(value) {
27229
+ if (!record4(value) || !exact4(value, ["items", "next_cursor"]) || !pageItems(value["items"]))
27230
+ throw new TypeError("Invalid database execution usage page");
27231
+ for (const row of value["items"])
27232
+ assertUsageRow(row);
27233
+ if (!nullable(value["next_cursor"], isCursor))
27234
+ throw new TypeError("Invalid database execution usage page");
27235
+ }
27236
+ function assertDatabaseScheduleRun(value) {
27237
+ if (!record4(value) || !exact4(value, [
27238
+ "id",
27239
+ "schedule",
27240
+ "scheduled_at",
27241
+ "started_at",
27242
+ "finished_at",
27243
+ "outcome",
27244
+ "sqlstate",
27245
+ "attempts",
27246
+ "manual"
27247
+ ]) || !nonNegativeInteger(value["id"]) || !matches(value["schedule"], SCHEDULE_NAME_PATTERN) || !timestamp3(value["scheduled_at"]) || !nullable(value["started_at"], timestamp3) || !timestamp3(value["finished_at"]) || !oneOf(DATABASE_SCHEDULE_OUTCOMES, value["outcome"]) || !nullable(value["sqlstate"], (state) => typeof state === "string") || !nonNegativeInteger(value["attempts"]) || typeof value["manual"] !== "boolean")
27248
+ throw new TypeError("Invalid database schedule run");
27249
+ }
27250
+ function assertUsageRow(value) {
27251
+ if (!record4(value) || !exact4(value, ["start", "end", "final", "metrics"]) || !timestamp3(value["start"]) || !timestamp3(value["end"]) || typeof value["final"] !== "boolean" || !record4(value["metrics"]) || !exact4(value["metrics"], DATABASE_EXECUTION_METRICS))
27252
+ throw new TypeError("Invalid database execution usage row");
27253
+ const metrics = value["metrics"];
27254
+ if (!DATABASE_EXECUTION_METRICS.every((metric) => nonNegativeInteger(metrics[metric])))
27255
+ throw new TypeError("Invalid database execution usage row");
27256
+ }
27257
+ 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((type) => oneOf(DATABASE_WEBHOOK_EVENT_TYPES, type)) || !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
+ throw new TypeError("Invalid database webhook");
27260
+ }
27261
+ function isHttpsUrl2(value) {
27262
+ if (typeof value !== "string" || value.length > DATABASE_WEBHOOK_URL_MAX_LENGTH)
27263
+ return false;
27264
+ try {
27265
+ return new URL(value).protocol === "https:";
27266
+ } catch {
27267
+ return false;
27268
+ }
27269
+ }
27270
+ function isCronText(value) {
27271
+ return typeof value === "string" && value.length >= DATABASE_SCHEDULE_CRON_MIN_LENGTH && value.length <= DATABASE_SCHEDULE_CRON_MAX_LENGTH;
27272
+ }
27273
+ function isEverySeconds(value) {
27274
+ return Number.isSafeInteger(value) && value >= DATABASE_SCHEDULE_MIN_EVERY_SECONDS && value <= DATABASE_SCHEDULE_MAX_EVERY_SECONDS;
27275
+ }
27276
+ function isTimeout(value) {
27277
+ return Number.isSafeInteger(value) && value >= DATABASE_SCHEDULE_MIN_TIMEOUT_MS && value <= DATABASE_SCHEDULE_MAX_TIMEOUT_MS;
27278
+ }
27279
+ function isCursor(value) {
27280
+ return matches(value, CURSOR_PATTERN);
27281
+ }
27282
+ function pageItems(value) {
27283
+ return Array.isArray(value) && value.length <= DATABASE_PAGE_MAX_ITEMS;
27284
+ }
27285
+ function nonNegativeInteger(value) {
27286
+ return Number.isSafeInteger(value) && value >= 0;
27287
+ }
27288
+ function nullable(value, check) {
27289
+ return value === null || check(value);
27290
+ }
27291
+ function matches(value, pattern) {
27292
+ return typeof value === "string" && pattern.test(value);
27293
+ }
27294
+ function oneOf(allowed, value) {
27295
+ return typeof value === "string" && allowed.includes(value);
27296
+ }
27297
+ function timestamp3(value) {
27298
+ if (typeof value !== "string")
27299
+ return false;
27300
+ const time3 = Date.parse(value);
27301
+ return Number.isFinite(time3) && new Date(time3).toISOString() === value;
27302
+ }
27303
+ function record4(value) {
27304
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27305
+ }
27306
+ function exact4(value, keys) {
27307
+ return Object.keys(value).sort().join(",") === [...keys].sort().join(",");
27308
+ }
27309
+
27050
27310
  // apps/product-cli/package.json
27051
27311
  var package_default2 = {
27052
27312
  name: "@ohmyhost/product-cli",
27053
- version: "0.1.40",
27313
+ version: "0.1.42",
27054
27314
  private: true,
27055
27315
  ohmyhost: {
27056
27316
  deployment: "production",
@@ -27120,32 +27380,32 @@ function isUserSecretName(value, action = "set") {
27120
27380
  }
27121
27381
 
27122
27382
  // packages/contracts/dist/project-context.js
27123
- var record4 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
27124
- var timestamp3 = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
27383
+ var record5 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
27384
+ var timestamp4 = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
27125
27385
  var version = (v) => Number.isInteger(v) && Number(v) >= 0 && Number(v) <= 2147483647;
27126
27386
  var bounded = (v, lines, bytes) => typeof v === "string" && !/[\r\u2028\u2029]/u.test(v) && !new RegExp("\\p{Cc}", "u").test(v.replace(/[\n\t]/gu, "")) && v.split("\n").length <= lines && new TextEncoder().encode(v).length <= bytes;
27127
27387
  function assertProjectNotesReceipt(v) {
27128
- if (!record4(v) || Object.keys(v).sort().join(",") !== "updated_at,version" || !version(v["version"]) || v["version"] === 0 || !timestamp3(v["updated_at"]))
27388
+ if (!record5(v) || Object.keys(v).sort().join(",") !== "updated_at,version" || !version(v["version"]) || v["version"] === 0 || !timestamp4(v["updated_at"]))
27129
27389
  throw new TypeError("Invalid project notes receipt");
27130
27390
  }
27131
27391
  function assertProjectContext(v) {
27132
- if (!record4(v) || Object.keys(v).sort().join(",") !== "credit_access,generated_at,markdown,notes,project_id" || typeof v["project_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(v["project_id"]) || !timestamp3(v["generated_at"]) || !["included", "not_authorized"].includes(String(v["credit_access"])) || !bounded(v["markdown"], 500, 32768))
27392
+ if (!record5(v) || Object.keys(v).sort().join(",") !== "credit_access,generated_at,markdown,notes,project_id" || typeof v["project_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(v["project_id"]) || !timestamp4(v["generated_at"]) || !["included", "not_authorized"].includes(String(v["credit_access"])) || !bounded(v["markdown"], 500, 32768))
27133
27393
  throw new TypeError("Invalid project context");
27134
27394
  const notes = v["notes"];
27135
- if (!record4(notes) || Object.keys(notes).sort().join(",") !== "markdown,updated_at,version" || !version(notes["version"]) || !bounded(notes["markdown"], 250, 16384) || (notes["version"] === 0 ? notes["updated_at"] !== null || notes["markdown"] !== "" : !timestamp3(notes["updated_at"])))
27395
+ if (!record5(notes) || Object.keys(notes).sort().join(",") !== "markdown,updated_at,version" || !version(notes["version"]) || !bounded(notes["markdown"], 250, 16384) || (notes["version"] === 0 ? notes["updated_at"] !== null || notes["markdown"] !== "" : !timestamp4(notes["updated_at"])))
27136
27396
  throw new TypeError("Invalid project notes");
27137
27397
  }
27138
27398
 
27139
27399
  // packages/contracts/dist/project-exports.js
27140
27400
  function assertProjectExport(value) {
27141
- if (!record5(value) || Object.keys(value).sort().join(",") !== "archive,error,id,next_poll_after_seconds,next_request_at,project_id,requested_at,state" || typeof value["id"] !== "string" || !id.test(value["id"]) || typeof value["project_id"] !== "string" || !id.test(value["project_id"]) || !["queued", "running", "succeeded", "failed", "cancelled"].includes(String(value["state"])) || !timestamp4(value["requested_at"]) || !timestamp4(value["next_request_at"]))
27401
+ if (!record6(value) || Object.keys(value).sort().join(",") !== "archive,error,id,next_poll_after_seconds,next_request_at,project_id,requested_at,state" || typeof value["id"] !== "string" || !id.test(value["id"]) || typeof value["project_id"] !== "string" || !id.test(value["project_id"]) || !["queued", "running", "succeeded", "failed", "cancelled"].includes(String(value["state"])) || !timestamp5(value["requested_at"]) || !timestamp5(value["next_request_at"]))
27142
27402
  invalid4();
27143
27403
  const active = value["state"] === "queued" || value["state"] === "running";
27144
27404
  if (value["next_poll_after_seconds"] !== (active ? 5 : null))
27145
27405
  invalid4();
27146
27406
  if (value["state"] === "failed") {
27147
27407
  const error = value["error"];
27148
- if (!record5(error) || Object.keys(error).sort().join(",") !== "code,message,retryable,suggested_action" || typeof error["code"] !== "string")
27408
+ if (!record6(error) || Object.keys(error).sort().join(",") !== "code,message,retryable,suggested_action" || typeof error["code"] !== "string")
27149
27409
  invalid4();
27150
27410
  const expected = publicOperationFailure(error["code"]);
27151
27411
  for (const key of Object.keys(expected))
@@ -27159,14 +27419,14 @@ function assertProjectExport(value) {
27159
27419
  invalid4();
27160
27420
  return;
27161
27421
  }
27162
- if (value["state"] !== "succeeded" || !record5(archive) || Object.keys(archive).sort().join(",") !== "bytes,captured_at,download_expires_at,download_url,expires_at,sha256,sql_files" || !Number.isSafeInteger(archive["bytes"]) || Number(archive["bytes"]) < 1 || Number(archive["bytes"]) > 536870912 || typeof archive["sha256"] !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(archive["sha256"]) || !['["dev.sql"]', '["prod.sql"]', '["dev.sql","prod.sql"]', '["shared.sql"]'].includes(JSON.stringify(archive["sql_files"])) || !timestamp4(archive["captured_at"]) || !timestamp4(archive["expires_at"]))
27422
+ if (value["state"] !== "succeeded" || !record6(archive) || Object.keys(archive).sort().join(",") !== "bytes,captured_at,download_expires_at,download_url,expires_at,sha256,sql_files" || !Number.isSafeInteger(archive["bytes"]) || Number(archive["bytes"]) < 1 || Number(archive["bytes"]) > 536870912 || typeof archive["sha256"] !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(archive["sha256"]) || !['["dev.sql"]', '["prod.sql"]', '["dev.sql","prod.sql"]', '["shared.sql"]'].includes(JSON.stringify(archive["sql_files"])) || !timestamp5(archive["captured_at"]) || !timestamp5(archive["expires_at"]))
27163
27423
  invalid4();
27164
27424
  if (archive["download_url"] === null) {
27165
27425
  if (archive["download_expires_at"] !== null)
27166
27426
  invalid4();
27167
27427
  return;
27168
27428
  }
27169
- if (typeof archive["download_url"] !== "string" || !timestamp4(archive["download_expires_at"]) || Date.parse(archive["download_expires_at"]) > Date.parse(archive["expires_at"]))
27429
+ if (typeof archive["download_url"] !== "string" || !timestamp5(archive["download_expires_at"]) || Date.parse(archive["download_expires_at"]) > Date.parse(archive["expires_at"]))
27170
27430
  invalid4();
27171
27431
  let url;
27172
27432
  try {
@@ -27178,10 +27438,10 @@ function assertProjectExport(value) {
27178
27438
  invalid4();
27179
27439
  }
27180
27440
  var id = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
27181
- function record5(value) {
27441
+ function record6(value) {
27182
27442
  return typeof value === "object" && value !== null && !Array.isArray(value);
27183
27443
  }
27184
- function timestamp4(value) {
27444
+ function timestamp5(value) {
27185
27445
  return typeof value === "string" && Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value;
27186
27446
  }
27187
27447
  function invalid4() {
@@ -27420,11 +27680,11 @@ function assertBillingTaxIssue(value) {
27420
27680
  "billing_tax_location_required",
27421
27681
  "billing_tax_calculation_failed",
27422
27682
  "billing_tax_configuration_required"
27423
- ].includes(String(v["code"])) || typeof v["invoice_id"] !== "string" || !/^in_[A-Za-z0-9_]{1,253}$/u.test(v["invoice_id"]) || !timestamp5(v["observed_at"]) || v["required_action"] !== (v["code"] === "billing_tax_location_required" ? "open_billing_portal" : "contact_support"))
27683
+ ].includes(String(v["code"])) || typeof v["invoice_id"] !== "string" || !/^in_[A-Za-z0-9_]{1,253}$/u.test(v["invoice_id"]) || !timestamp6(v["observed_at"]) || v["required_action"] !== (v["code"] === "billing_tax_location_required" ? "open_billing_portal" : "contact_support"))
27424
27684
  throw new Error("billing_response_invalid");
27425
27685
  }
27426
27686
  var ulid4 = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
27427
- var timestamp5 = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
27687
+ var timestamp6 = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
27428
27688
  function stripeUrl(value, host2) {
27429
27689
  if (typeof value !== "string" || value.length > 8192)
27430
27690
  return false;
@@ -27439,7 +27699,7 @@ function assertBillingCheckout(value) {
27439
27699
  if (!value || typeof value !== "object" || Array.isArray(value))
27440
27700
  throw new Error("billing_response_invalid");
27441
27701
  const v = value;
27442
- if (Object.keys(v).sort().join(",") !== "billing_issue,checkout_id,credited_micros,expires_at,offer,organization_id,packs,paid_until,payment_confirmed,required_action,revoked_micros,state,url" || typeof v["organization_id"] !== "string" || !ulid4.test(v["organization_id"]) || typeof v["checkout_id"] !== "string" || !ulid4.test(v["checkout_id"]) || typeof v["offer"] !== "string" || !["topup", "paid"].includes(v["offer"]) || typeof v["state"] !== "string" || !["open", "complete", "expired"].includes(v["state"]) || typeof v["payment_confirmed"] !== "boolean" || typeof v["required_action"] !== "string" || !["none", "complete_checkout", "open_billing_portal", "contact_support"].includes(v["required_action"]) || v["url"] !== null && !stripeUrl(v["url"], "checkout.stripe.com") || !timestamp5(v["expires_at"]) || v["paid_until"] !== null && !timestamp5(v["paid_until"]) || !Number.isInteger(v["packs"]) || Number(v["packs"]) < 1 || Number(v["packs"]) > 100 || v["offer"] === "paid" && v["packs"] !== 1 || ![v["credited_micros"], v["revoked_micros"]].every((x) => typeof x === "string" && /^(0|[1-9][0-9]{0,18})$/u.test(x)))
27702
+ if (Object.keys(v).sort().join(",") !== "billing_issue,checkout_id,credited_micros,expires_at,offer,organization_id,packs,paid_until,payment_confirmed,required_action,revoked_micros,state,url" || typeof v["organization_id"] !== "string" || !ulid4.test(v["organization_id"]) || typeof v["checkout_id"] !== "string" || !ulid4.test(v["checkout_id"]) || typeof v["offer"] !== "string" || !["topup", "paid"].includes(v["offer"]) || typeof v["state"] !== "string" || !["open", "complete", "expired"].includes(v["state"]) || typeof v["payment_confirmed"] !== "boolean" || typeof v["required_action"] !== "string" || !["none", "complete_checkout", "open_billing_portal", "contact_support"].includes(v["required_action"]) || v["url"] !== null && !stripeUrl(v["url"], "checkout.stripe.com") || !timestamp6(v["expires_at"]) || v["paid_until"] !== null && !timestamp6(v["paid_until"]) || !Number.isInteger(v["packs"]) || Number(v["packs"]) < 1 || Number(v["packs"]) > 100 || v["offer"] === "paid" && v["packs"] !== 1 || ![v["credited_micros"], v["revoked_micros"]].every((x) => typeof x === "string" && /^(0|[1-9][0-9]{0,18})$/u.test(x)))
27443
27703
  throw new Error("billing_response_invalid");
27444
27704
  assertBillingTaxIssue(v["billing_issue"]);
27445
27705
  }
@@ -27447,7 +27707,7 @@ function assertBillingPortal(value) {
27447
27707
  if (!value || typeof value !== "object" || Array.isArray(value))
27448
27708
  throw new Error("billing_response_invalid");
27449
27709
  const v = value;
27450
- if (Object.keys(v).sort().join(",") !== "created_at,organization_id,url" || typeof v["organization_id"] !== "string" || !ulid4.test(v["organization_id"]) || !timestamp5(v["created_at"]) || !stripeUrl(v["url"], "billing.stripe.com"))
27710
+ if (Object.keys(v).sort().join(",") !== "created_at,organization_id,url" || typeof v["organization_id"] !== "string" || !ulid4.test(v["organization_id"]) || !timestamp6(v["created_at"]) || !stripeUrl(v["url"], "billing.stripe.com"))
27451
27711
  throw new Error("billing_response_invalid");
27452
27712
  }
27453
27713
  function assertRecharge(value) {
@@ -28128,7 +28388,7 @@ var HELP_USAGE = Object.freeze({
28128
28388
  "billing checkout": "ohmyhost billing checkout --organization ULID --offer topup|paid [--packs 1] --idempotency-key KEY --json (returns a human payment URL; never auto-pays)",
28129
28389
  "billing status": "ohmyhost billing status --organization ULID --checkout ULID --json",
28130
28390
  "billing portal": "ohmyhost billing portal --organization ULID --json (short-lived human URL; request fresh after expiry)",
28131
- "credits usage": "ohmyhost credits usage --organization ULID --month YYYY-MM [--cursor ULID] --json",
28391
+ "credits usage": "ohmyhost credits usage --organization ULID --json (billed usage of the last up to 14 UTC days by day, project and meter, and each project's use this UTC month)",
28132
28392
  "budget get": "ohmyhost budget get --project ULID --json",
28133
28393
  "budget set": "ohmyhost budget set --project ULID --credits NUMBER|none [--mode continue|stop] --idempotency-key KEY --json",
28134
28394
  "organization create": "ohmyhost organization create --name NAME --idempotency-key KEY [--source SOURCE] --json (SOURCE is optional attribution from a link's r value; a login without organization is bound to the new workspace, another login keeps its own)",
@@ -28164,6 +28424,20 @@ var HELP_USAGE = Object.freeze({
28164
28424
  "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.",
28165
28425
  "database access list": "ohmyhost database access list --project ULID [--environment dev|prod] --json",
28166
28426
  "database access revoke": "ohmyhost database access revoke --project ULID --access ULID --yes --json",
28427
+ "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; the headers file is a UTF-8 JSON object of at most 8 KiB)",
28428
+ "database webhook list": "ohmyhost database webhook list --project ULID [--environment dev|prod] --json (dev when omitted; the secret is never listed)",
28429
+ "database webhook get": "ohmyhost database webhook get --project ULID [--environment dev|prod] --webhook ID --json",
28430
+ "database webhook delete": "ohmyhost database webhook delete --project ULID --environment dev|prod --webhook ID --yes --json",
28431
+ "database webhook test": "ohmyhost database webhook test --project ULID --environment dev|prod --webhook ID --yes --json (sends one signed test request to the receiver; nothing is stored)",
28432
+ "database webhook deliveries": "ohmyhost database webhook deliveries --project ULID [--environment dev|prod] [--webhook ID] [--limit 1..100] [--cursor CURSOR] --json",
28433
+ "database webhook replay": "ohmyhost database webhook replay --project ULID --environment dev|prod --delivery ID --yes --json",
28434
+ "database schedule set": "ohmyhost database schedule set --project ULID --environment dev|prod --name NAME (--cron EXPR | --every-seconds N) --statements-file PATH [--timeout-ms N] [--enabled true|false] --yes --json (runs the statements in the file, a UTF-8 JSON array of 1 to 20 SQL strings, as the runtime role of the application; cron has five fields in UTC; every-seconds is 60 to 2678400; timeout-ms is 1000 to 30000, default 10000)",
28435
+ "database schedule list": "ohmyhost database schedule list --project ULID [--environment dev|prod] --json (dev when omitted)",
28436
+ "database schedule get": "ohmyhost database schedule get --project ULID [--environment dev|prod] --name NAME --json",
28437
+ "database schedule delete": "ohmyhost database schedule delete --project ULID --environment dev|prod --name NAME --yes --json",
28438
+ "database schedule runs": "ohmyhost database schedule runs --project ULID [--environment dev|prod] --name NAME [--limit 1..50] --json",
28439
+ "database schedule run": "ohmyhost database schedule run --project ULID --environment dev|prod --name NAME --yes --json (queues one run now, in addition to the timer)",
28440
+ "database executions": "ohmyhost database executions --project ULID [--environment dev|prod] --from ISO --to ISO --granularity hour|day [--limit 1..100] [--cursor CURSOR] --json (UTC timestamps like 2026-10-30T00:00:00.000Z aligned to the granularity, at most 31 days; counts schedule runs, webhook attempts and events per hour or day; usage counters only, nothing is charged for them until the operator prices them)",
28167
28441
  "database psql": "ohmyhost database psql --project ULID --environment dev|prod [--mode read|write] [--ttl 5m|1h|24h|SECONDS] [--json] (starts local psql with a temporary credential and revokes it on exit)",
28168
28442
  link: "ohmyhost link --project ULID --repository-owner OWNER --repository-name REPOSITORY --idempotency-key KEY --json (uses the workspace GitHub connection and waits for the source-link operation)",
28169
28443
  "source auto-deploy set": "ohmyhost source auto-deploy set --project ULID --branch BRANCH --enabled true|false --idempotency-key KEY --json",
@@ -28292,12 +28566,12 @@ function buildClientParams(args, fields) {
28292
28566
  };
28293
28567
  const map = buildKeyMap(fields);
28294
28568
  function writeSlot(slot, key, value) {
28295
- let record7 = params[slot];
28296
- if (record7 === void 0) {
28297
- record7 = /* @__PURE__ */ Object.create(null);
28298
- params[slot] = record7;
28569
+ let record8 = params[slot];
28570
+ if (record8 === void 0) {
28571
+ record8 = /* @__PURE__ */ Object.create(null);
28572
+ params[slot] = record8;
28299
28573
  }
28300
- record7[key] = value;
28574
+ record8[key] = value;
28301
28575
  }
28302
28576
  let config;
28303
28577
  for (const [index, arg] of args.entries()) {
@@ -28574,9 +28848,9 @@ var serializeObjectParam = ({ allowReserved, explode, name, style, value, valueO
28574
28848
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
28575
28849
  var defaultPathSerializer = ({ path: path2, url: _url }) => {
28576
28850
  let url = _url;
28577
- const matches = _url.match(PATH_PARAM_RE);
28578
- if (matches) {
28579
- for (const match of matches) {
28851
+ const matches2 = _url.match(PATH_PARAM_RE);
28852
+ if (matches2) {
28853
+ for (const match of matches2) {
28580
28854
  let explode = false;
28581
28855
  let name = match.substring(1, match.length - 1);
28582
28856
  let style = "simple";
@@ -29791,9 +30065,7 @@ var getOrganizationCreditUsage = (parameters, options) => {
29791
30065
  {
29792
30066
  args: [
29793
30067
  { in: "headers", key: "X-Request-Id" },
29794
- { in: "path", key: "organization_id" },
29795
- { in: "query", key: "month" },
29796
- { in: "query", key: "cursor" }
30068
+ { in: "path", key: "organization_id" }
29797
30069
  ]
29798
30070
  }
29799
30071
  ]);
@@ -30946,6 +31218,289 @@ var revokeProjectDatabaseAccess = (parameters, options) => {
30946
31218
  ...params
30947
31219
  });
30948
31220
  };
31221
+ var listProjectDatabaseWebhooks = (parameters, options) => {
31222
+ const params = buildClientParams([parameters], [
31223
+ {
31224
+ args: [
31225
+ { in: "headers", key: "X-Request-Id" },
31226
+ { in: "path", key: "project_id" },
31227
+ { in: "query", key: "environment" }
31228
+ ]
31229
+ }
31230
+ ]);
31231
+ return (options?.client ?? client).get({
31232
+ responseStyle: "data",
31233
+ security: [{ scheme: "bearer", type: "http" }],
31234
+ url: "/v1/projects/{project_id}/database/webhooks",
31235
+ ...options,
31236
+ ...params
31237
+ });
31238
+ };
31239
+ var createProjectDatabaseWebhook = (parameters, options) => {
31240
+ const params = buildClientParams([parameters], [
31241
+ {
31242
+ args: [
31243
+ { in: "headers", key: "X-Request-Id" },
31244
+ { in: "headers", key: "Idempotency-Key" },
31245
+ { in: "path", key: "project_id" },
31246
+ { in: "query", key: "environment" },
31247
+ { key: "databaseWebhookCreateRequest", map: "body" }
31248
+ ]
31249
+ }
31250
+ ]);
31251
+ return (options?.client ?? client).post({
31252
+ responseStyle: "data",
31253
+ security: [{ scheme: "bearer", type: "http" }],
31254
+ url: "/v1/projects/{project_id}/database/webhooks",
31255
+ ...options,
31256
+ ...params,
31257
+ headers: {
31258
+ "Content-Type": "application/json",
31259
+ ...options?.headers,
31260
+ ...params.headers
31261
+ }
31262
+ });
31263
+ };
31264
+ var deleteProjectDatabaseWebhook = (parameters, options) => {
31265
+ const params = buildClientParams([parameters], [
31266
+ {
31267
+ args: [
31268
+ { in: "headers", key: "X-Request-Id" },
31269
+ { in: "path", key: "project_id" },
31270
+ { in: "path", key: "webhook_id" },
31271
+ { in: "query", key: "environment" }
31272
+ ]
31273
+ }
31274
+ ]);
31275
+ return (options?.client ?? client).delete({
31276
+ responseStyle: "data",
31277
+ security: [{ scheme: "bearer", type: "http" }],
31278
+ url: "/v1/projects/{project_id}/database/webhooks/{webhook_id}",
31279
+ ...options,
31280
+ ...params
31281
+ });
31282
+ };
31283
+ var getProjectDatabaseWebhook = (parameters, options) => {
31284
+ const params = buildClientParams([parameters], [
31285
+ {
31286
+ args: [
31287
+ { in: "headers", key: "X-Request-Id" },
31288
+ { in: "path", key: "project_id" },
31289
+ { in: "path", key: "webhook_id" },
31290
+ { in: "query", key: "environment" }
31291
+ ]
31292
+ }
31293
+ ]);
31294
+ return (options?.client ?? client).get({
31295
+ responseStyle: "data",
31296
+ security: [{ scheme: "bearer", type: "http" }],
31297
+ url: "/v1/projects/{project_id}/database/webhooks/{webhook_id}",
31298
+ ...options,
31299
+ ...params
31300
+ });
31301
+ };
31302
+ var testProjectDatabaseWebhook = (parameters, options) => {
31303
+ const params = buildClientParams([parameters], [
31304
+ {
31305
+ args: [
31306
+ { in: "headers", key: "X-Request-Id" },
31307
+ { in: "path", key: "project_id" },
31308
+ { in: "path", key: "webhook_id" },
31309
+ { in: "query", key: "environment" }
31310
+ ]
31311
+ }
31312
+ ]);
31313
+ return (options?.client ?? client).post({
31314
+ responseStyle: "data",
31315
+ security: [{ scheme: "bearer", type: "http" }],
31316
+ url: "/v1/projects/{project_id}/database/webhooks/{webhook_id}/test",
31317
+ ...options,
31318
+ ...params
31319
+ });
31320
+ };
31321
+ var listProjectDatabaseWebhookDeliveries = (parameters, options) => {
31322
+ const params = buildClientParams([parameters], [
31323
+ {
31324
+ args: [
31325
+ { in: "headers", key: "X-Request-Id" },
31326
+ { in: "path", key: "project_id" },
31327
+ { in: "query", key: "environment" },
31328
+ { in: "query", key: "webhook_id" },
31329
+ { in: "query", key: "limit" },
31330
+ { in: "query", key: "cursor" }
31331
+ ]
31332
+ }
31333
+ ]);
31334
+ return (options?.client ?? client).get({
31335
+ responseStyle: "data",
31336
+ security: [{ scheme: "bearer", type: "http" }],
31337
+ url: "/v1/projects/{project_id}/database/webhook-deliveries",
31338
+ ...options,
31339
+ ...params
31340
+ });
31341
+ };
31342
+ var replayProjectDatabaseWebhookDelivery = (parameters, options) => {
31343
+ const params = buildClientParams([parameters], [
31344
+ {
31345
+ args: [
31346
+ { in: "headers", key: "X-Request-Id" },
31347
+ { in: "path", key: "project_id" },
31348
+ { in: "path", key: "delivery_id" },
31349
+ { in: "query", key: "environment" }
31350
+ ]
31351
+ }
31352
+ ]);
31353
+ return (options?.client ?? client).post({
31354
+ responseStyle: "data",
31355
+ security: [{ scheme: "bearer", type: "http" }],
31356
+ url: "/v1/projects/{project_id}/database/webhook-deliveries/{delivery_id}/replay",
31357
+ ...options,
31358
+ ...params
31359
+ });
31360
+ };
31361
+ var listProjectDatabaseSchedules = (parameters, options) => {
31362
+ const params = buildClientParams([parameters], [
31363
+ {
31364
+ args: [
31365
+ { in: "headers", key: "X-Request-Id" },
31366
+ { in: "path", key: "project_id" },
31367
+ { in: "query", key: "environment" }
31368
+ ]
31369
+ }
31370
+ ]);
31371
+ return (options?.client ?? client).get({
31372
+ responseStyle: "data",
31373
+ security: [{ scheme: "bearer", type: "http" }],
31374
+ url: "/v1/projects/{project_id}/database/schedules",
31375
+ ...options,
31376
+ ...params
31377
+ });
31378
+ };
31379
+ var deleteProjectDatabaseSchedule = (parameters, options) => {
31380
+ const params = buildClientParams([parameters], [
31381
+ {
31382
+ args: [
31383
+ { in: "headers", key: "X-Request-Id" },
31384
+ { in: "path", key: "project_id" },
31385
+ { in: "path", key: "name" },
31386
+ { in: "query", key: "environment" }
31387
+ ]
31388
+ }
31389
+ ]);
31390
+ return (options?.client ?? client).delete({
31391
+ responseStyle: "data",
31392
+ security: [{ scheme: "bearer", type: "http" }],
31393
+ url: "/v1/projects/{project_id}/database/schedules/{name}",
31394
+ ...options,
31395
+ ...params
31396
+ });
31397
+ };
31398
+ var getProjectDatabaseSchedule = (parameters, options) => {
31399
+ const params = buildClientParams([parameters], [
31400
+ {
31401
+ args: [
31402
+ { in: "headers", key: "X-Request-Id" },
31403
+ { in: "path", key: "project_id" },
31404
+ { in: "path", key: "name" },
31405
+ { in: "query", key: "environment" }
31406
+ ]
31407
+ }
31408
+ ]);
31409
+ return (options?.client ?? client).get({
31410
+ responseStyle: "data",
31411
+ security: [{ scheme: "bearer", type: "http" }],
31412
+ url: "/v1/projects/{project_id}/database/schedules/{name}",
31413
+ ...options,
31414
+ ...params
31415
+ });
31416
+ };
31417
+ var setProjectDatabaseSchedule = (parameters, options) => {
31418
+ const params = buildClientParams([parameters], [
31419
+ {
31420
+ args: [
31421
+ { in: "headers", key: "X-Request-Id" },
31422
+ { in: "path", key: "project_id" },
31423
+ { in: "path", key: "name" },
31424
+ { in: "query", key: "environment" },
31425
+ { key: "databaseScheduleSetRequest", map: "body" }
31426
+ ]
31427
+ }
31428
+ ]);
31429
+ return (options?.client ?? client).put({
31430
+ responseStyle: "data",
31431
+ security: [{ scheme: "bearer", type: "http" }],
31432
+ url: "/v1/projects/{project_id}/database/schedules/{name}",
31433
+ ...options,
31434
+ ...params,
31435
+ headers: {
31436
+ "Content-Type": "application/json",
31437
+ ...options?.headers,
31438
+ ...params.headers
31439
+ }
31440
+ });
31441
+ };
31442
+ var listProjectDatabaseScheduleRuns = (parameters, options) => {
31443
+ const params = buildClientParams([parameters], [
31444
+ {
31445
+ args: [
31446
+ { in: "headers", key: "X-Request-Id" },
31447
+ { in: "path", key: "project_id" },
31448
+ { in: "path", key: "name" },
31449
+ { in: "query", key: "environment" },
31450
+ { in: "query", key: "limit" }
31451
+ ]
31452
+ }
31453
+ ]);
31454
+ return (options?.client ?? client).get({
31455
+ responseStyle: "data",
31456
+ security: [{ scheme: "bearer", type: "http" }],
31457
+ url: "/v1/projects/{project_id}/database/schedules/{name}/runs",
31458
+ ...options,
31459
+ ...params
31460
+ });
31461
+ };
31462
+ var runProjectDatabaseSchedule = (parameters, options) => {
31463
+ const params = buildClientParams([parameters], [
31464
+ {
31465
+ args: [
31466
+ { in: "headers", key: "X-Request-Id" },
31467
+ { in: "path", key: "project_id" },
31468
+ { in: "path", key: "name" },
31469
+ { in: "query", key: "environment" }
31470
+ ]
31471
+ }
31472
+ ]);
31473
+ return (options?.client ?? client).post({
31474
+ responseStyle: "data",
31475
+ security: [{ scheme: "bearer", type: "http" }],
31476
+ url: "/v1/projects/{project_id}/database/schedules/{name}/run",
31477
+ ...options,
31478
+ ...params
31479
+ });
31480
+ };
31481
+ var getProjectDatabaseExecutionUsage = (parameters, options) => {
31482
+ const params = buildClientParams([parameters], [
31483
+ {
31484
+ args: [
31485
+ { in: "headers", key: "X-Request-Id" },
31486
+ { in: "path", key: "project_id" },
31487
+ { in: "query", key: "environment" },
31488
+ { in: "query", key: "from" },
31489
+ { in: "query", key: "to" },
31490
+ { in: "query", key: "granularity" },
31491
+ { in: "query", key: "limit" },
31492
+ { in: "query", key: "cursor" }
31493
+ ]
31494
+ }
31495
+ ]);
31496
+ return (options?.client ?? client).get({
31497
+ responseStyle: "data",
31498
+ security: [{ scheme: "bearer", type: "http" }],
31499
+ url: "/v1/projects/{project_id}/database/execution-usage",
31500
+ ...options,
31501
+ ...params
31502
+ });
31503
+ };
30949
31504
  var planDeploymentRollback = (parameters, options) => {
30950
31505
  const params = buildClientParams([parameters], [
30951
31506
  {
@@ -31397,7 +31952,7 @@ var ULID3 = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
31397
31952
  function assertManagedMailResponse(value, input) {
31398
31953
  const r = object2(value);
31399
31954
  if (input.action === "configure" || input.action === "status" || input.action === "webhook_verify") {
31400
- exact4(r, [
31955
+ exact5(r, [
31401
31956
  "domain_id",
31402
31957
  "domain",
31403
31958
  "environment_id",
@@ -31427,14 +31982,14 @@ function assertManagedMailResponse(value, input) {
31427
31982
  invalid5();
31428
31983
  if (r["webhook"] !== null) {
31429
31984
  const hook = object2(r["webhook"]);
31430
- exact4(hook, ["url", "verified"]);
31985
+ exact5(hook, ["url", "verified"]);
31431
31986
  https(hook["url"]);
31432
31987
  if (typeof hook["verified"] !== "boolean")
31433
31988
  invalid5();
31434
31989
  }
31435
31990
  if (r["dns"] !== void 0) {
31436
31991
  const dns = object2(r["dns"]);
31437
- exact4(dns, ["status", "records"]);
31992
+ exact5(dns, ["status", "records"]);
31438
31993
  if (!["configured", "action_required", "conflict"].includes(String(dns["status"])))
31439
31994
  invalid5();
31440
31995
  records(dns["records"]);
@@ -31442,19 +31997,19 @@ function assertManagedMailResponse(value, input) {
31442
31997
  return;
31443
31998
  }
31444
31999
  if (input.action === "webhook_set") {
31445
- exact4(r, ["url", "signing_secret", "status"]);
32000
+ exact5(r, ["url", "signing_secret", "status"]);
31446
32001
  if (r["url"] !== input.url || r["status"] !== "verification_required" || typeof r["signing_secret"] !== "string" || !/^whsec_[A-Za-z0-9+/]{43}=$/u.test(r["signing_secret"]))
31447
32002
  invalid5();
31448
32003
  return;
31449
32004
  }
31450
32005
  if (input.action === "webhook_disable") {
31451
- exact4(r, ["status"]);
32006
+ exact5(r, ["status"]);
31452
32007
  if (r["status"] !== "disabled")
31453
32008
  invalid5();
31454
32009
  return;
31455
32010
  }
31456
32011
  if (input.action === "domain_delete") {
31457
- exact4(r, ["status", "domain", "dns_records"]);
32012
+ exact5(r, ["status", "domain", "dns_records"]);
31458
32013
  if (r["status"] !== "deleted")
31459
32014
  invalid5();
31460
32015
  domain(r["domain"]);
@@ -31462,12 +32017,12 @@ function assertManagedMailResponse(value, input) {
31462
32017
  return;
31463
32018
  }
31464
32019
  if (input.action === "messages_list") {
31465
- exact4(r, ["items"]);
32020
+ exact5(r, ["items"]);
31466
32021
  if (!Array.isArray(r["items"]) || r["items"].length > 50)
31467
32022
  invalid5();
31468
32023
  for (const value2 of r["items"]) {
31469
32024
  const item = object2(value2);
31470
- exact4(item, ["message_id", "received_at", "state", "attempts"]);
32025
+ exact5(item, ["message_id", "received_at", "state", "attempts"]);
31471
32026
  id2(item["message_id"]);
31472
32027
  time(item["received_at"]);
31473
32028
  if (!["pending", "delivering", "delivered", "delivery_failed", "expired"].includes(String(item["state"])) || !Number.isInteger(item["attempts"]) || Number(item["attempts"]) < 0 || Number(item["attempts"]) > 4)
@@ -31476,7 +32031,7 @@ function assertManagedMailResponse(value, input) {
31476
32031
  return;
31477
32032
  }
31478
32033
  if (input.action === "message_retry") {
31479
- exact4(r, ["attempted"], ["delivered"]);
32034
+ exact5(r, ["attempted"], ["delivered"]);
31480
32035
  if (typeof r["attempted"] !== "boolean" || r["delivered"] !== void 0 && typeof r["delivered"] !== "boolean")
31481
32036
  invalid5();
31482
32037
  return;
@@ -31484,10 +32039,10 @@ function assertManagedMailResponse(value, input) {
31484
32039
  if (input.action !== "message_get")
31485
32040
  invalid5();
31486
32041
  if (r["status"] === "expired") {
31487
- exact4(r, ["status"]);
32042
+ exact5(r, ["status"]);
31488
32043
  return;
31489
32044
  }
31490
- exact4(r, [
32045
+ exact5(r, [
31491
32046
  "id",
31492
32047
  "domain",
31493
32048
  "received_at",
@@ -31519,7 +32074,7 @@ function assertManagedMailResponse(value, input) {
31519
32074
  invalid5();
31520
32075
  for (const value2 of r["attachments"]) {
31521
32076
  const a = object2(value2);
31522
- exact4(a, ["id", "filename", "content_type", "download_path"]);
32077
+ exact5(a, ["id", "filename", "content_type", "download_path"]);
31523
32078
  if (typeof a["id"] !== "string" || !/^[A-Za-z0-9_-]{1,128}$/u.test(a["id"]) || a["filename"] !== null && typeof a["filename"] !== "string" || typeof a["content_type"] !== "string" || a["download_path"] !== `/v1/projects/${input.projectId}/environments/${input.environmentId}/mail/messages/${input.messageId}/attachments/${a["id"]}`)
31524
32079
  invalid5();
31525
32080
  }
@@ -31529,7 +32084,7 @@ function object2(v) {
31529
32084
  invalid5();
31530
32085
  return v;
31531
32086
  }
31532
- function exact4(v, required, optional = []) {
32087
+ function exact5(v, required, optional = []) {
31533
32088
  if (required.some((k) => !(k in v)) || Object.keys(v).some((k) => !required.includes(k) && !optional.includes(k)))
31534
32089
  invalid5();
31535
32090
  }
@@ -31554,7 +32109,7 @@ function records(v) {
31554
32109
  invalid5();
31555
32110
  for (const value of v) {
31556
32111
  const r = object2(value);
31557
- exact4(r, ["type", "name", "value", "purpose", "status"], ["priority"]);
32112
+ exact5(r, ["type", "name", "value", "purpose", "status"], ["priority"]);
31558
32113
  if (!["TXT", "CNAME", "MX"].includes(String(r["type"])) || ["name", "value", "purpose", "status"].some((k) => typeof r[k] !== "string") || r["type"] === "MX" && (!Number.isInteger(r["priority"]) || Number(r["priority"]) < 0 || Number(r["priority"]) > 65535))
31559
32114
  invalid5();
31560
32115
  }
@@ -31611,7 +32166,7 @@ var HOST = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}
31611
32166
  function assertSharedMailResponse(value, input) {
31612
32167
  const v = object3(value);
31613
32168
  if (input.action === "domains_list") {
31614
- exact5(v, ["items"]);
32169
+ exact6(v, ["items"]);
31615
32170
  if (!Array.isArray(v["items"]) || v["items"].length > 100)
31616
32171
  invalid6();
31617
32172
  for (const item of v["items"])
@@ -31623,7 +32178,7 @@ function assertSharedMailResponse(value, input) {
31623
32178
  return;
31624
32179
  }
31625
32180
  if (["domain_get", "domain_create", "domain_retire"].includes(input.action)) {
31626
- exact5(v, [
32181
+ exact6(v, [
31627
32182
  "domain_id",
31628
32183
  "organization_id",
31629
32184
  "domain",
@@ -31656,7 +32211,7 @@ function assertSharedMailResponse(value, input) {
31656
32211
  invalid6();
31657
32212
  for (const entry of v["dns_records"]) {
31658
32213
  const r = object3(entry);
31659
- exact5(r, ["type", "name", "value", "purpose", "status"], ["priority"]);
32214
+ exact6(r, ["type", "name", "value", "purpose", "status"], ["priority"]);
31660
32215
  member(r["type"], ["TXT", "MX", "CNAME"]);
31661
32216
  for (const k of ["name", "value", "purpose", "status"])
31662
32217
  if (typeof r[k] !== "string" || /[\r\n\0]/u.test(r[k]))
@@ -31669,7 +32224,7 @@ function assertSharedMailResponse(value, input) {
31669
32224
  return;
31670
32225
  }
31671
32226
  if (["binding_get", "binding_set", "binding_detach"].includes(input.action)) {
31672
- exact5(v, [
32227
+ exact6(v, [
31673
32228
  "mail_domain_id",
31674
32229
  "organization_id",
31675
32230
  "project_id",
@@ -31703,7 +32258,7 @@ function assertSharedMailResponse(value, input) {
31703
32258
  invalid6();
31704
32259
  if (v["application_domain_identity"] !== null) {
31705
32260
  const identity = object3(v["application_domain_identity"]);
31706
- exact5(identity, ["hostname", "registrable_domain", "revision", "status"]);
32261
+ exact6(identity, ["hostname", "registrable_domain", "revision", "status"]);
31707
32262
  host(identity["hostname"]);
31708
32263
  host(identity["registrable_domain"]);
31709
32264
  positive(identity["revision"]);
@@ -31712,7 +32267,7 @@ function assertSharedMailResponse(value, input) {
31712
32267
  return;
31713
32268
  }
31714
32269
  if (["identity_get", "identity_declare", "identity_verify", "identity_revoke"].includes(input.action)) {
31715
- exact5(v, [
32270
+ exact6(v, [
31716
32271
  "organization_id",
31717
32272
  "project_id",
31718
32273
  "hostname",
@@ -31732,7 +32287,7 @@ function assertSharedMailResponse(value, input) {
31732
32287
  positive(v["revision"]);
31733
32288
  member(v["status"], ["pending", "verified", "expired", "revoked"]);
31734
32289
  const challenge = object3(v["challenge"]);
31735
- exact5(challenge, ["type", "name", "value"]);
32290
+ exact6(challenge, ["type", "name", "value"]);
31736
32291
  if (challenge["type"] !== "TXT" || typeof challenge["name"] !== "string" || challenge["name"] !== `_omh-project.${v["hostname"]}` || typeof challenge["value"] !== "string" || challenge["value"].length < 16 || challenge["value"].length > 255 || /[\r\n\0]/u.test(challenge["value"]))
31737
32292
  invalid6();
31738
32293
  if (v["verified_at"] !== null)
@@ -31741,14 +32296,14 @@ function assertSharedMailResponse(value, input) {
31741
32296
  return;
31742
32297
  }
31743
32298
  if (input.action === "domain_dns_authorize" || input.action === "identity_authorize") {
31744
- exact5(v, ["authorization_id", "authorization_url", "expires_at"]);
32299
+ exact6(v, ["authorization_id", "authorization_url", "expires_at"]);
31745
32300
  id3(v["authorization_id"]);
31746
32301
  time2(v["expires_at"]);
31747
32302
  if (typeof v["authorization_url"] !== "string" || !/^https:\/\/dash\.cloudflare\.com\/oauth2\/auth\?/u.test(v["authorization_url"]))
31748
32303
  invalid6();
31749
32304
  return;
31750
32305
  }
31751
- exact5(v, ["status", "zone", "scopes", "expires_at"]);
32306
+ exact6(v, ["status", "zone", "scopes", "expires_at"]);
31752
32307
  member(v["status"], ["not_authorized", "pending", "authorized", "expired", "revoked"]);
31753
32308
  if (!Array.isArray(v["scopes"]) || v["scopes"].length > 2 || new Set(v["scopes"]).size !== v["scopes"].length || v["scopes"].some((s) => s !== "dns.write" && s !== "zone.read"))
31754
32309
  invalid6();
@@ -31764,7 +32319,7 @@ function object3(v) {
31764
32319
  invalid6();
31765
32320
  return v;
31766
32321
  }
31767
- function exact5(v, required, optional = []) {
32322
+ function exact6(v, required, optional = []) {
31768
32323
  if (required.some((k) => !(k in v)) || Object.keys(v).some((k) => !required.includes(k) && !optional.includes(k)))
31769
32324
  invalid6();
31770
32325
  }
@@ -32066,6 +32621,8 @@ function checkedResponse(kind, value) {
32066
32621
  }
32067
32622
 
32068
32623
  // apps/product-cli/dist/product-api.js
32624
+ var WEBHOOK_SCOPE_MISMATCH = "Webhook response scope mismatch";
32625
+ var SCHEDULE_SCOPE_MISMATCH = "Schedule response scope mismatch";
32069
32626
  var GeneratedSdkProductApi = class {
32070
32627
  #client;
32071
32628
  managedSource;
@@ -32175,12 +32732,8 @@ var GeneratedSdkProductApi = class {
32175
32732
  createBillingPortal(organizationId) {
32176
32733
  return createBillingPortal({ organization_id: organizationId, body: {} }, { client: this.#client });
32177
32734
  }
32178
- getOrganizationCreditUsage(input) {
32179
- return getOrganizationCreditUsage({
32180
- organization_id: input.organizationId,
32181
- month: input.month,
32182
- ...input.cursor ? { cursor: input.cursor } : {}
32183
- }, { client: this.#client });
32735
+ getOrganizationCreditUsage(organizationId) {
32736
+ return getOrganizationCreditUsage({ organization_id: organizationId }, { client: this.#client });
32184
32737
  }
32185
32738
  getProjectCreditBudget(projectId) {
32186
32739
  return getProjectCreditBudget({ project_id: projectId }, { client: this.#client });
@@ -32266,6 +32819,159 @@ var GeneratedSdkProductApi = class {
32266
32819
  assertProjectDatabaseAccess(value);
32267
32820
  return value;
32268
32821
  }
32822
+ /** The signing secret exists only in this answer; the CLI prints it once and stores nothing. */
32823
+ async createProjectDatabaseWebhook(input) {
32824
+ const value = await createProjectDatabaseWebhook({
32825
+ project_id: input.projectId,
32826
+ environment: input.environment,
32827
+ "Idempotency-Key": input.idempotencyKey,
32828
+ databaseWebhookCreateRequest: {
32829
+ url: input.url,
32830
+ event_types: [...input.eventTypes],
32831
+ headers: { ...input.headers }
32832
+ }
32833
+ }, { client: this.#client });
32834
+ assertDatabaseWebhookCreated(value);
32835
+ if (value.environment !== input.environment)
32836
+ throw new TypeError(WEBHOOK_SCOPE_MISMATCH);
32837
+ return value;
32838
+ }
32839
+ async listProjectDatabaseWebhooks(input) {
32840
+ const value = await listProjectDatabaseWebhooks({ project_id: input.projectId, environment: input.environment }, { client: this.#client });
32841
+ assertDatabaseWebhookPage(value);
32842
+ if (value.items.some((item) => item.environment !== input.environment))
32843
+ throw new TypeError(WEBHOOK_SCOPE_MISMATCH);
32844
+ return value;
32845
+ }
32846
+ async getProjectDatabaseWebhook(input) {
32847
+ const value = await getProjectDatabaseWebhook({
32848
+ project_id: input.projectId,
32849
+ environment: input.environment,
32850
+ webhook_id: input.webhookId
32851
+ }, { client: this.#client });
32852
+ assertDatabaseWebhook(value);
32853
+ if (value.id !== input.webhookId || value.environment !== input.environment)
32854
+ throw new TypeError(WEBHOOK_SCOPE_MISMATCH);
32855
+ return value;
32856
+ }
32857
+ async deleteProjectDatabaseWebhook(input) {
32858
+ const value = await deleteProjectDatabaseWebhook({
32859
+ project_id: input.projectId,
32860
+ environment: input.environment,
32861
+ webhook_id: input.webhookId
32862
+ }, { client: this.#client });
32863
+ assertDatabaseWebhookDeleted(value);
32864
+ if (value.id !== input.webhookId)
32865
+ throw new TypeError(WEBHOOK_SCOPE_MISMATCH);
32866
+ return value;
32867
+ }
32868
+ async testProjectDatabaseWebhook(input) {
32869
+ const value = await testProjectDatabaseWebhook({
32870
+ project_id: input.projectId,
32871
+ environment: input.environment,
32872
+ webhook_id: input.webhookId
32873
+ }, { client: this.#client });
32874
+ assertDatabaseWebhookTest(value);
32875
+ return value;
32876
+ }
32877
+ async listProjectDatabaseWebhookDeliveries(input) {
32878
+ const value = await listProjectDatabaseWebhookDeliveries({
32879
+ project_id: input.projectId,
32880
+ environment: input.environment,
32881
+ ...input.webhookId === void 0 ? {} : { webhook_id: input.webhookId },
32882
+ ...input.limit === void 0 ? {} : { limit: input.limit },
32883
+ ...input.cursor === void 0 ? {} : { cursor: input.cursor }
32884
+ }, { client: this.#client });
32885
+ assertDatabaseWebhookDeliveryPage(value);
32886
+ if (input.webhookId !== void 0 && value.items.some((item) => item.webhook_id !== input.webhookId))
32887
+ throw new TypeError(WEBHOOK_SCOPE_MISMATCH);
32888
+ return value;
32889
+ }
32890
+ async replayProjectDatabaseWebhookDelivery(input) {
32891
+ const value = await replayProjectDatabaseWebhookDelivery({
32892
+ project_id: input.projectId,
32893
+ environment: input.environment,
32894
+ delivery_id: input.deliveryId
32895
+ }, { client: this.#client });
32896
+ assertDatabaseWebhookReplayAccepted(value);
32897
+ if (value.delivery_id !== input.deliveryId)
32898
+ throw new TypeError(WEBHOOK_SCOPE_MISMATCH);
32899
+ return value;
32900
+ }
32901
+ /** A schedule runs the statements as the application's runtime role; the request confirms it. */
32902
+ async setProjectDatabaseSchedule(input) {
32903
+ const request = input.request;
32904
+ const value = await setProjectDatabaseSchedule({
32905
+ project_id: input.projectId,
32906
+ environment: input.environment,
32907
+ name: input.name,
32908
+ databaseScheduleSetRequest: {
32909
+ ...request.cron === null ? {} : { cron: request.cron },
32910
+ ...request.every_seconds === null ? {} : { every_seconds: request.every_seconds },
32911
+ statements: [...request.statements],
32912
+ timeout_ms: request.timeout_ms,
32913
+ enabled: request.enabled,
32914
+ confirm: true
32915
+ }
32916
+ }, { client: this.#client });
32917
+ assertDatabaseSchedule(value);
32918
+ if (value.name !== input.name || value.environment !== input.environment)
32919
+ throw new TypeError(SCHEDULE_SCOPE_MISMATCH);
32920
+ return value;
32921
+ }
32922
+ async listProjectDatabaseSchedules(input) {
32923
+ const value = await listProjectDatabaseSchedules({ project_id: input.projectId, environment: input.environment }, { client: this.#client });
32924
+ assertDatabaseSchedulePage(value);
32925
+ if (value.items.some((item) => item.environment !== input.environment))
32926
+ throw new TypeError(SCHEDULE_SCOPE_MISMATCH);
32927
+ return value;
32928
+ }
32929
+ async getProjectDatabaseSchedule(input) {
32930
+ const value = await getProjectDatabaseSchedule({ project_id: input.projectId, environment: input.environment, name: input.name }, { client: this.#client });
32931
+ assertDatabaseSchedule(value);
32932
+ if (value.name !== input.name || value.environment !== input.environment)
32933
+ throw new TypeError(SCHEDULE_SCOPE_MISMATCH);
32934
+ return value;
32935
+ }
32936
+ async deleteProjectDatabaseSchedule(input) {
32937
+ const value = await deleteProjectDatabaseSchedule({ project_id: input.projectId, environment: input.environment, name: input.name }, { client: this.#client });
32938
+ assertDatabaseScheduleDeleted(value);
32939
+ if (value.name !== input.name)
32940
+ throw new TypeError(SCHEDULE_SCOPE_MISMATCH);
32941
+ return value;
32942
+ }
32943
+ async listProjectDatabaseScheduleRuns(input) {
32944
+ const value = await listProjectDatabaseScheduleRuns({
32945
+ project_id: input.projectId,
32946
+ environment: input.environment,
32947
+ name: input.name,
32948
+ ...input.limit === void 0 ? {} : { limit: input.limit }
32949
+ }, { client: this.#client });
32950
+ assertDatabaseScheduleRunPage(value);
32951
+ if (value.items.some((item) => item.schedule !== input.name))
32952
+ throw new TypeError(SCHEDULE_SCOPE_MISMATCH);
32953
+ return value;
32954
+ }
32955
+ async runProjectDatabaseSchedule(input) {
32956
+ const value = await runProjectDatabaseSchedule({ project_id: input.projectId, environment: input.environment, name: input.name }, { client: this.#client });
32957
+ assertDatabaseScheduleRunAccepted(value);
32958
+ if (value.schedule !== input.name)
32959
+ throw new TypeError(SCHEDULE_SCOPE_MISMATCH);
32960
+ return value;
32961
+ }
32962
+ async getProjectDatabaseExecutionUsage(input) {
32963
+ const value = await getProjectDatabaseExecutionUsage({
32964
+ project_id: input.projectId,
32965
+ environment: input.environment,
32966
+ from: input.from,
32967
+ to: input.to,
32968
+ granularity: input.granularity,
32969
+ ...input.limit === void 0 ? {} : { limit: input.limit },
32970
+ ...input.cursor === void 0 ? {} : { cursor: input.cursor }
32971
+ }, { client: this.#client });
32972
+ assertDatabaseExecutionUsagePage(value);
32973
+ return value;
32974
+ }
32269
32975
  async planPaidDomain(input) {
32270
32976
  return planPaidProjectDomain({ project_id: input.projectId, paidDomainRequest: { hostname: input.hostname } }, { client: this.#client });
32271
32977
  }
@@ -33000,6 +33706,10 @@ async function createAuthenticatedLocalMcpClient(signal, overrides = {}) {
33000
33706
  throw error;
33001
33707
  }
33002
33708
  }
33709
+ function requireScope(matches2) {
33710
+ if (!matches2)
33711
+ throw new TypeError("Database event scope mismatch");
33712
+ }
33003
33713
  var GeneratedSdkLocalMcpClient = class {
33004
33714
  managedSource;
33005
33715
  productApiOrigin;
@@ -33209,12 +33919,8 @@ var GeneratedSdkLocalMcpClient = class {
33209
33919
  assertBillingPortal(value);
33210
33920
  return value;
33211
33921
  }
33212
- async getOrganizationCreditUsage(input) {
33213
- const value = await getOrganizationCreditUsage({
33214
- organization_id: input.organizationId,
33215
- month: input.month,
33216
- ...input.cursor ? { cursor: input.cursor } : {}
33217
- }, { client: this.#client });
33922
+ async getOrganizationCreditUsage(organizationId) {
33923
+ const value = await getOrganizationCreditUsage({ organization_id: organizationId }, { client: this.#client });
33218
33924
  assertOrganizationCreditUsage(value);
33219
33925
  return value;
33220
33926
  }
@@ -33383,6 +34089,131 @@ var GeneratedSdkLocalMcpClient = class {
33383
34089
  assertProjectDatabaseAccess(value);
33384
34090
  return value;
33385
34091
  }
34092
+ async listDatabaseWebhooks(input) {
34093
+ const environment2 = input.environment ?? "dev";
34094
+ const value = await listProjectDatabaseWebhooks({ project_id: input.projectId, environment: environment2 }, { client: this.#client });
34095
+ assertDatabaseWebhookPage(value);
34096
+ requireScope(value.items.every((webhook) => webhook.environment === environment2));
34097
+ return value;
34098
+ }
34099
+ /** The signing secret exists only in this response and is never stored by the client. */
34100
+ async createDatabaseWebhook(input) {
34101
+ const value = await createProjectDatabaseWebhook({
34102
+ project_id: input.projectId,
34103
+ environment: input.environment,
34104
+ "Idempotency-Key": input.idempotencyKey,
34105
+ databaseWebhookCreateRequest: {
34106
+ url: input.url,
34107
+ event_types: [...input.eventTypes],
34108
+ headers: { ...input.headers }
34109
+ }
34110
+ }, { client: this.#client });
34111
+ assertDatabaseWebhookCreated(value);
34112
+ requireScope(value.environment === input.environment);
34113
+ return value;
34114
+ }
34115
+ async testDatabaseWebhook(input) {
34116
+ const value = await testProjectDatabaseWebhook({
34117
+ project_id: input.projectId,
34118
+ environment: input.environment,
34119
+ webhook_id: input.webhookId
34120
+ }, { client: this.#client });
34121
+ assertDatabaseWebhookTest(value);
34122
+ return value;
34123
+ }
34124
+ async deleteDatabaseWebhook(input) {
34125
+ const value = await deleteProjectDatabaseWebhook({
34126
+ project_id: input.projectId,
34127
+ environment: input.environment,
34128
+ webhook_id: input.webhookId
34129
+ }, { client: this.#client });
34130
+ assertDatabaseWebhookDeleted(value);
34131
+ requireScope(value.id === input.webhookId);
34132
+ return value;
34133
+ }
34134
+ async listDatabaseWebhookDeliveries(input) {
34135
+ const value = await listProjectDatabaseWebhookDeliveries({
34136
+ project_id: input.projectId,
34137
+ environment: input.environment ?? "dev",
34138
+ ...input.webhookId === void 0 ? {} : { webhook_id: input.webhookId },
34139
+ ...input.limit === void 0 ? {} : { limit: input.limit },
34140
+ ...input.cursor === void 0 ? {} : { cursor: input.cursor }
34141
+ }, { client: this.#client });
34142
+ assertDatabaseWebhookDeliveryPage(value);
34143
+ requireScope(input.webhookId === void 0 || value.items.every((delivery) => delivery.webhook_id === input.webhookId));
34144
+ return value;
34145
+ }
34146
+ async replayDatabaseWebhookDelivery(input) {
34147
+ const value = await replayProjectDatabaseWebhookDelivery({
34148
+ project_id: input.projectId,
34149
+ environment: input.environment,
34150
+ delivery_id: input.deliveryId
34151
+ }, { client: this.#client });
34152
+ assertDatabaseWebhookReplayAccepted(value);
34153
+ requireScope(value.delivery_id === input.deliveryId);
34154
+ return value;
34155
+ }
34156
+ async listDatabaseSchedules(input) {
34157
+ const environment2 = input.environment ?? "dev";
34158
+ const value = await listProjectDatabaseSchedules({ project_id: input.projectId, environment: environment2 }, { client: this.#client });
34159
+ assertDatabaseSchedulePage(value);
34160
+ requireScope(value.items.every((schedule) => schedule.environment === environment2));
34161
+ return value;
34162
+ }
34163
+ async setDatabaseSchedule(input) {
34164
+ const value = await setProjectDatabaseSchedule({
34165
+ project_id: input.projectId,
34166
+ name: input.name,
34167
+ environment: input.environment,
34168
+ databaseScheduleSetRequest: {
34169
+ ...input.cron === void 0 ? {} : { cron: input.cron },
34170
+ ...input.everySeconds === void 0 ? {} : { every_seconds: input.everySeconds },
34171
+ statements: [...input.statements],
34172
+ ...input.timeoutMs === void 0 ? {} : { timeout_ms: input.timeoutMs },
34173
+ ...input.enabled === void 0 ? {} : { enabled: input.enabled },
34174
+ confirm: true
34175
+ }
34176
+ }, { client: this.#client });
34177
+ assertDatabaseSchedule(value);
34178
+ requireScope(value.name === input.name && value.environment === input.environment);
34179
+ return value;
34180
+ }
34181
+ async deleteDatabaseSchedule(input) {
34182
+ const value = await deleteProjectDatabaseSchedule({ project_id: input.projectId, name: input.name, environment: input.environment }, { client: this.#client });
34183
+ assertDatabaseScheduleDeleted(value);
34184
+ requireScope(value.name === input.name);
34185
+ return value;
34186
+ }
34187
+ async listDatabaseScheduleRuns(input) {
34188
+ const value = await listProjectDatabaseScheduleRuns({
34189
+ project_id: input.projectId,
34190
+ name: input.name,
34191
+ environment: input.environment ?? "dev",
34192
+ ...input.limit === void 0 ? {} : { limit: input.limit }
34193
+ }, { client: this.#client });
34194
+ assertDatabaseScheduleRunPage(value);
34195
+ requireScope(value.items.every((run) => run.schedule === input.name));
34196
+ return value;
34197
+ }
34198
+ async runDatabaseSchedule(input) {
34199
+ const value = await runProjectDatabaseSchedule({ project_id: input.projectId, name: input.name, environment: input.environment }, { client: this.#client });
34200
+ assertDatabaseScheduleRunAccepted(value);
34201
+ requireScope(value.schedule === input.name);
34202
+ return value;
34203
+ }
34204
+ async getDatabaseExecutionUsage(input) {
34205
+ const value = await getProjectDatabaseExecutionUsage({
34206
+ project_id: input.projectId,
34207
+ environment: input.environment ?? "dev",
34208
+ from: input.from,
34209
+ to: input.to,
34210
+ granularity: input.granularity,
34211
+ ...input.limit === void 0 ? {} : { limit: input.limit },
34212
+ ...input.cursor === void 0 ? {} : { cursor: input.cursor }
34213
+ }, { client: this.#client });
34214
+ assertDatabaseExecutionUsagePage(value);
34215
+ return value;
34216
+ }
33386
34217
  planPromotion(input) {
33387
34218
  return planDeploymentPromotion({ project_id: input.projectId, source_deployment_id: input.sourceDeploymentId }, { client: this.#client });
33388
34219
  }
@@ -33614,13 +34445,13 @@ function normalizeMcpSourceChanges(value) {
33614
34445
  }
33615
34446
  }
33616
34447
  function normalizeSourceChanges(value) {
33617
- const body = record6(value);
34448
+ const body = record7(value);
33618
34449
  const changes = body["changes"];
33619
34450
  if (!Array.isArray(changes) || changes.length < 1 || changes.length > MANAGED_SOURCE_LIMITS.files)
33620
34451
  invalid7();
33621
34452
  let textBytes = 0;
33622
34453
  const normalized = changes.map((change) => {
33623
- const entry = record6(change);
34454
+ const entry = record7(change);
33624
34455
  const hasText = Object.hasOwn(entry, "content_text");
33625
34456
  if (hasText === Object.hasOwn(entry, "content_base64"))
33626
34457
  invalid7();
@@ -33679,7 +34510,7 @@ function encodeBase64(bytes) {
33679
34510
  binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
33680
34511
  return btoa(binary);
33681
34512
  }
33682
- function record6(value) {
34513
+ function record7(value) {
33683
34514
  if (typeof value !== "object" || value === null || Array.isArray(value))
33684
34515
  invalid7();
33685
34516
  return value;
@@ -33690,6 +34521,10 @@ function invalid7() {
33690
34521
 
33691
34522
  // apps/mcp/dist/local-server.js
33692
34523
  var identifier2 = external_exports.string().min(1).max(256);
34524
+ var databaseEnvironment = external_exports.enum(["dev", "prod"]);
34525
+ var databaseWebhookId = external_exports.string().regex(/^whk_[a-z0-9]{20}$/u);
34526
+ var databaseDeliveryId = external_exports.string().regex(/^dlv_[0-9a-f]{20}$/u);
34527
+ var databaseScheduleName = external_exports.string().regex(/^[a-z][a-z0-9_-]{0,62}$/u);
33693
34528
  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.");
33694
34529
  var idempotencyKey = external_exports.string().min(1).max(128);
33695
34530
  var commitSha = external_exports.string().regex(/^[a-f0-9]{40}$/u);
@@ -33804,7 +34639,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
33804
34639
  hostname: input.hostname,
33805
34640
  idempotencyKey: input.idempotency_key
33806
34641
  }), destructiveAnnotations());
33807
- registerProductTool(server, dependencies, "billing_checkout_create", "Owner-only: create or resume a hosted Checkout. Paid is USD 10/month; each top-up pack is USD 10 before tax; a purchase grants 100 credits per dollar up to USD 100 and 125 credits per dollar for the part above, so 10 packs grant 10000 and 20 packs grant 22500 top-up credits. Monthly Paid credits expire at billing-period end; top-ups carry over while Paid and expire on downgrade to Free. Return the URL to the human to review/pay; never auto-pay or treat browser return as confirmation. Preserve the same offer/packs/idempotency key after uncertainty. An existing active, overdue, unpaid or paused subscription must be managed through billing_portal_create, not replaced with another Paid purchase. Then read checkout status and organization credits. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.", external_exports.object({
34642
+ registerProductTool(server, dependencies, "billing_checkout_create", "Owner-only: create or resume a hosted Checkout. Paid is USD 10/month; each top-up pack is USD 10 before tax; a purchase grants 100 credits per dollar up to USD 100 and 125 credits per dollar for the part above, so 10 packs grant 10000 and 20 packs grant 22500 top-up credits. Monthly Paid credits expire at billing-period end; top-ups never expire, also after a downgrade to Free. Return the URL to the human to review/pay; never auto-pay or treat browser return as confirmation. Preserve the same offer/packs/idempotency key after uncertainty. An existing active, overdue, unpaid or paused subscription must be managed through billing_portal_create, not replaced with another Paid purchase. Then read checkout status and organization credits. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.", external_exports.object({
33808
34643
  organization_id: identifier2,
33809
34644
  offer: external_exports.enum(["topup", "paid"]),
33810
34645
  packs: external_exports.number().int().min(1).max(100).default(1),
@@ -33815,12 +34650,12 @@ function createLocalOhmyhostMcpServer(dependencies) {
33815
34650
  packs: input.packs,
33816
34651
  idempotencyKey: input.idempotency_key
33817
34652
  }), mutationAnnotations());
33818
- registerProductTool(server, dependencies, "billing_checkout_get", "Owner-only: observe the original checkout and reconcile confirmed credits/refunds, without another purchase. payment_confirmed is historical; read organization_credits_get for spendable funds and organization_account_get's effective plan for Paid coverage; paid_until remains the paid Stripe period end during renewal grace. Follow required_action: complete_checkout means give its URL to the human; open_billing_portal means call billing_portal_create and give that fresh URL to the human to resolve payment. contact_support means contact https://ohmyho.st/contact about the original invoice; none means no human payment step now, not proof of current Paid coverage. Never start a second subscription to repair a failed renewal. Follow billing_issue when tax needs attention: use billing_portal_create for open_billing_portal, or https://ohmyho.st/contact for contact_support; retain the original invoice and never disable tax. Retry the same checkout after an outage. state=expired ends this attempt; use a new key only for an explicitly requested new purchase, never automatically after an error or timeout.", external_exports.object({ organization_id: identifier2, checkout_id: identifier2 }), (client2, input) => client2.getBillingCheckout({
34653
+ registerProductTool(server, dependencies, "billing_checkout_get", "Owner-only: observe the original checkout and reconcile confirmed credits/refunds, without another purchase. payment_confirmed is historical; read organization_credits_get for spendable funds and organization_account_get's effective plan for Paid coverage; paid_until is the end of paid coverage: the paid Stripe period end plus its 14-day renewal grace. Follow required_action: complete_checkout means give its URL to the human; open_billing_portal means call billing_portal_create and give that fresh URL to the human to resolve payment. contact_support means contact https://ohmyho.st/contact about the original invoice; none means no human payment step now, not proof of current Paid coverage. Never start a second subscription to repair a failed renewal. Follow billing_issue when tax needs attention: use billing_portal_create for open_billing_portal, or https://ohmyho.st/contact for contact_support; retain the original invoice and never disable tax. Retry the same checkout after an outage. state=expired ends this attempt; use a new key only for an explicitly requested new purchase, never automatically after an error or timeout.", external_exports.object({ organization_id: identifier2, checkout_id: identifier2 }), (client2, input) => client2.getBillingCheckout({
33819
34654
  organizationId: input.organization_id,
33820
34655
  checkoutId: input.checkout_id
33821
34656
  }));
33822
34657
  registerProductTool(server, dependencies, "billing_recharge_get", "Owner-only: read auto-recharge consent, spending limit and payment handoff. Reading never initiates a charge. Return private setup_url/invoice_url only to the human; never log them. Read again after Stripe card setup or payment. billing_issue identifies the original invoice: open_billing_portal means collect corrected billing details through billing_portal_create; contact_support means use https://ohmyho.st/contact. Never disable tax, discard the invoice or start another purchase to repair it.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getBillingRecharge(input.organization_id));
33823
- registerProductTool(server, dependencies, "billing_recharge_configure", "Owner-only: enable or disable automatic off-session payments. Enabling requires active Paid access. NEVER enable without explicit human approval for USD 9 plus tax per 1000 top-up credits, which carry over while Paid and expire on downgrade to Free, refill below 100 credits, and the chosen gross USD monthly limit. Set consent off_session_v1 only after that approval; null when disabling. Read current revision first. Preserve the original idempotency key and payload after uncertainty. A saved Stripe card may require setup_url. Disabling prevents new payment initiation; in-progress payments may finish. This does not create a subscription or Paid access.", external_exports.object({
34658
+ registerProductTool(server, dependencies, "billing_recharge_configure", "Owner-only: enable or disable automatic off-session payments. Enabling requires active Paid access. NEVER enable without explicit human approval for USD 9 plus tax per 1000 top-up credits, which never expire, refill below 100 credits, and the chosen gross USD monthly limit. Set consent off_session_v1 only after that approval; null when disabling. Read current revision first. Preserve the original idempotency key and payload after uncertainty. A saved Stripe card may require setup_url. Disabling prevents new payment initiation; in-progress payments may finish. This does not create a subscription or Paid access.", external_exports.object({
33824
34659
  organization_id: identifier2,
33825
34660
  enabled: external_exports.boolean(),
33826
34661
  monthly_limit_minor: external_exports.number().int().min(1e3).max(1e5),
@@ -33846,19 +34681,11 @@ function createLocalOhmyhostMcpServer(dependencies) {
33846
34681
  idempotencyKey: input.idempotency_key
33847
34682
  }), mutationAnnotations());
33848
34683
  registerProductTool(server, dependencies, "project_export_get", "Owner-only: read the original SQL ZIP export's progress/error and verified download URL. Follow next_poll_after_seconds while queued/running; never create another export to poll. The signed URL lasts 24 hours and is only issued with sufficient remaining seven-day archive retention. Keep the URL out of source, logs and persisted project notes. The password cannot be retrieved. Available at zero credits.", external_exports.object({ project_id: identifier2, export_id: identifier2 }), (client2, input) => client2.getProjectExport({ projectId: input.project_id, exportId: input.export_id }));
33849
- registerProductTool(server, dependencies, "organization_usage_get", "Read posted UTC-month usage by project, environment and published meter/rate. One credit is 1000000 microcredits. Includes corrections; null environment means shared project cost. Current reservations are separate. Follow next_cursor with the same month (20 projects/page). Late or unmetered usage is not zero consumption. platform_overrun_micros is platform expense, not customer debt. Owner-only; works at zero credit without new charges.", external_exports.object({
33850
- organization_id: identifier2,
33851
- month: external_exports.string().regex(/^20[0-9]{2}-(0[1-9]|1[0-2])$/u),
33852
- cursor: identifier2.optional()
33853
- }), (client2, input) => client2.getOrganizationCreditUsage({
33854
- organizationId: input.organization_id,
33855
- month: input.month,
33856
- ...input.cursor ? { cursor: input.cursor } : {}
33857
- }));
33858
- registerProductTool(server, dependencies, "organization_account_get", "Owner-only: read the effective Free/Paid plan, its Stripe or granted source, available monthly credits that expire at period end and top-up credits that carry over while Paid but expire on downgrade to Free, reservations and next expiry. Granted Paid features do not imply a Stripe subscription or extra monthly Paid allowance. paid_until is the paid Stripe period end or grant end; null on Free or for an unbounded grant. An unpaid renewal may retain Paid features for up to 14 days after that Stripe period end, without new monthly credits. This read grants no access or credits.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationAccount(input.organization_id));
34684
+ registerProductTool(server, dependencies, "organization_usage_get", "Read the billed usage of the last up to 14 UTC days (today included) grouped by day, project and meter, and what each project has used so far this UTC month. One credit is 1000000 microcredits. Null environment means shared project cost. Charges can arrive late and unmetered usage is not zero consumption. Owner-only; works at zero credit without new charges.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationCreditUsage(input.organization_id));
34685
+ registerProductTool(server, dependencies, "organization_account_get", "Owner-only: read the effective Free/Paid plan, its Stripe or granted source, the monthly credits that expire at next_expiry, the top-up and bonus credits that never expire, the reservations that hold part of them, and available_micros (monthly plus one-time minus reservations). Granted Paid features do not imply a Stripe subscription or extra monthly Paid allowance. paid_until is the end of the paid coverage, which includes the 14-day renewal grace of a Stripe subscription; null on Free. This read grants no access or credits.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationAccount(input.organization_id));
33859
34686
  registerProductTool(server, dependencies, "referral_link_get", "Read the workspace's referral link to share. A new user whose first workspace comes from it starts with 30 days of Paid and 1,000 credits; that workspace's first payment gives this workspace 1,000 credits, plus 30 days of Paid unless a Stripe subscription or an unbounded grant already covers it. Any member may read it.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationReferral(input.organization_id));
33860
- registerProductTool(server, dependencies, "organization_credits_get", "Read the owner's shared organization credit pool, seven-day grace_started_at/grace_expires_at and published rate_cards. Existing services/domains are not immediately shut down at zero credit; an explicit project stop budget is separate. One credit is 1000000 microcredits. Each rate states credit_micros for units_per_charge; publication alone does not enable billing. active_meters identifies billed sources; provider outages and platform overrun are not customer debt. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationCredits(input.organization_id));
33861
- registerProductTool(server, dependencies, "project_budget_get", "Read the owner's project UTC-month budget, measured usage and open reservations. A budget never allocates a second wallet.", external_exports.object({ project_id: identifier2 }), (client2, input) => client2.getProjectCreditBudget(input.project_id));
34687
+ registerProductTool(server, dependencies, "organization_credits_get", "Read the owner's shared organization credit pool (available_micros is monthly plus one-time credit minus reservations), the seven-day grace_started_at/grace_expires_at that begins when the credit is used up, and published rate_cards. Existing services/domains are not immediately shut down at zero credit; an explicit project stop budget is separate. One credit is 1000000 microcredits. Each rate states credit_micros for units_per_charge; publication alone does not enable billing. active_meters identifies billed sources; provider outages are not customer debt. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationCredits(input.organization_id));
34688
+ registerProductTool(server, dependencies, "project_budget_get", "Read the owner's project UTC-month budget, this month's use and open reservations. A budget never allocates a second wallet.", external_exports.object({ project_id: identifier2 }), (client2, input) => client2.getProjectCreditBudget(input.project_id));
33862
34689
  registerProductTool(server, dependencies, "project_budget_set", "Set an owner's optional monthly project budget in microcredits (1000000 = one credit). continue is the default and uses the org pool after the threshold; stop blocks new billable work. null clears the budget and requires continue. Changing it never resets usage or adds credits. Replay the same key after uncertainty; read the budget again for current usage.", external_exports.object({
33863
34690
  project_id: identifier2,
33864
34691
  amount_micros: external_exports.string().regex(/^(0|[1-9][0-9]{0,18})$/u).nullable(),
@@ -33947,6 +34774,142 @@ function createLocalOhmyhostMcpServer(dependencies) {
33947
34774
  ...input.environment === void 0 ? {} : { environment: input.environment }
33948
34775
  }));
33949
34776
  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());
34777
+ 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
+ projectId: input.project_id,
34779
+ ...input.environment === void 0 ? {} : { environment: input.environment }
34780
+ }));
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({
34782
+ project_id: identifier2,
34783
+ environment: databaseEnvironment,
34784
+ url: external_exports.string().max(2048).regex(/^https:\/\//u),
34785
+ event_types: external_exports.array(external_exports.enum(DATABASE_WEBHOOK_EVENT_TYPES)).min(1).max(16),
34786
+ headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
34787
+ idempotency_key: idempotencyKey,
34788
+ confirmed: external_exports.literal(true)
34789
+ }), (client2, input) => client2.createDatabaseWebhook({
34790
+ projectId: input.project_id,
34791
+ environment: input.environment,
34792
+ url: input.url,
34793
+ eventTypes: input.event_types,
34794
+ headers: input.headers ?? {},
34795
+ idempotencyKey: input.idempotency_key
34796
+ }), mutationAnnotations());
34797
+ registerProductTool(server, dependencies, "database_webhook_test", "Send one signed test request to a database webhook and report the outcome synchronously. Each call sends one request to the receiver; the platform allows one test per webhook every five seconds. If the answer is lost, read database_webhook_delivery_list before calling again; a second call sends another request.", external_exports.object({
34798
+ project_id: identifier2,
34799
+ environment: databaseEnvironment,
34800
+ webhook_id: databaseWebhookId
34801
+ }), (client2, input) => client2.testDatabaseWebhook({
34802
+ projectId: input.project_id,
34803
+ environment: input.environment,
34804
+ webhookId: input.webhook_id
34805
+ }), { ...mutationAnnotations(), idempotentHint: false });
34806
+ registerProductTool(server, dependencies, "database_webhook_delete", "Stop all deliveries to one database webhook. Destructive: requires confirmed: true. Deleting an already deleted webhook answers not found.", external_exports.object({
34807
+ project_id: identifier2,
34808
+ environment: databaseEnvironment,
34809
+ webhook_id: databaseWebhookId,
34810
+ confirmed: external_exports.literal(true)
34811
+ }), (client2, input) => client2.deleteDatabaseWebhook({
34812
+ projectId: input.project_id,
34813
+ environment: input.environment,
34814
+ webhookId: input.webhook_id
34815
+ }), destructiveAnnotations());
34816
+ registerProductTool(server, dependencies, "database_webhook_delivery_list", "List recent database webhook deliveries, newest first, optionally for one webhook. Each delivery shows its state (pending, delivered or dead_lettered), attempts and last error.", external_exports.object({
34817
+ project_id: identifier2,
34818
+ environment: databaseEnvironment.optional(),
34819
+ webhook_id: databaseWebhookId.optional(),
34820
+ limit: external_exports.number().int().min(1).max(100).optional(),
34821
+ cursor: external_exports.string().min(1).max(200).optional()
34822
+ }), (client2, input) => client2.listDatabaseWebhookDeliveries({
34823
+ projectId: input.project_id,
34824
+ ...input.environment === void 0 ? {} : { environment: input.environment },
34825
+ ...input.webhook_id === void 0 ? {} : { webhookId: input.webhook_id },
34826
+ ...input.limit === void 0 ? {} : { limit: input.limit },
34827
+ ...input.cursor === void 0 ? {} : { cursor: input.cursor }
34828
+ }));
34829
+ registerProductTool(server, dependencies, "database_webhook_delivery_replay", "Queue one more attempt for a database webhook delivery that is no longer being retried. Each call queues one attempt; the delivery returns to pending until it is delivered or dead-lettered again. If the answer is lost, read database_webhook_delivery_list before calling again; a second call queues another attempt.", external_exports.object({
34830
+ project_id: identifier2,
34831
+ environment: databaseEnvironment,
34832
+ delivery_id: databaseDeliveryId
34833
+ }), (client2, input) => client2.replayDatabaseWebhookDelivery({
34834
+ projectId: input.project_id,
34835
+ environment: input.environment,
34836
+ deliveryId: input.delivery_id
34837
+ }), { ...mutationAnnotations(), idempotentHint: false });
34838
+ registerProductTool(server, dependencies, "database_schedule_list", "List this project's database schedules of one Dev or Prod environment (dev when omitted), with their cadence, statements, timeout and next run.", external_exports.object({ project_id: identifier2, environment: databaseEnvironment.optional() }), (client2, input) => client2.listDatabaseSchedules({
34839
+ projectId: input.project_id,
34840
+ ...input.environment === void 0 ? {} : { environment: input.environment }
34841
+ }));
34842
+ registerProductTool(server, dependencies, "database_schedule_set", "Create or replace a named database schedule that runs SQL statements repeatedly on a timer, as the application's own runtime role, so row-level security applies. Send exactly one of cron (five-field UTC expression) or every_seconds (60 to 2678400). Each run is cancelled after timeout_ms (1000 to 30000, default 10000). Statements run in order and must be safe to repeat: write idempotent statements. Destructive: requires confirmed: true.", external_exports.object({
34843
+ project_id: identifier2,
34844
+ environment: databaseEnvironment,
34845
+ name: databaseScheduleName,
34846
+ cron: external_exports.string().min(9).max(120).optional(),
34847
+ every_seconds: external_exports.number().int().min(DATABASE_SCHEDULE_MIN_EVERY_SECONDS).max(DATABASE_SCHEDULE_MAX_EVERY_SECONDS).optional(),
34848
+ statements: external_exports.array(external_exports.string().min(1).max(DATABASE_SCHEDULE_STATEMENT_MAX_BYTES)).min(1).max(DATABASE_SCHEDULE_MAX_STATEMENTS),
34849
+ timeout_ms: external_exports.number().int().min(DATABASE_SCHEDULE_MIN_TIMEOUT_MS).max(DATABASE_SCHEDULE_MAX_TIMEOUT_MS).optional(),
34850
+ enabled: external_exports.boolean().optional(),
34851
+ confirmed: external_exports.literal(true)
34852
+ }).refine((value) => value.cron === void 0 !== (value.every_seconds === void 0), {
34853
+ message: "Send exactly one of cron or every_seconds",
34854
+ path: ["every_seconds"]
34855
+ }), (client2, input) => client2.setDatabaseSchedule({
34856
+ projectId: input.project_id,
34857
+ environment: input.environment,
34858
+ name: input.name,
34859
+ cron: input.cron,
34860
+ everySeconds: input.every_seconds,
34861
+ statements: input.statements,
34862
+ timeoutMs: input.timeout_ms,
34863
+ enabled: input.enabled
34864
+ }), destructiveAnnotations());
34865
+ registerProductTool(server, dependencies, "database_schedule_delete", "Remove one database schedule so it never runs again. Destructive: requires confirmed: true.", external_exports.object({
34866
+ project_id: identifier2,
34867
+ environment: databaseEnvironment,
34868
+ name: databaseScheduleName,
34869
+ confirmed: external_exports.literal(true)
34870
+ }), (client2, input) => client2.deleteDatabaseSchedule({
34871
+ projectId: input.project_id,
34872
+ environment: input.environment,
34873
+ name: input.name
34874
+ }), destructiveAnnotations());
34875
+ registerProductTool(server, dependencies, "database_schedule_run_list", "List the newest runs of one database schedule, newest first, with each run's outcome (succeeded, failed, timed_out, outcome_unknown, rejected or a skipped reason) and SQLSTATE when one applies.", external_exports.object({
34876
+ project_id: identifier2,
34877
+ environment: databaseEnvironment.optional(),
34878
+ name: databaseScheduleName,
34879
+ limit: external_exports.number().int().min(1).max(50).optional()
34880
+ }), (client2, input) => client2.listDatabaseScheduleRuns({
34881
+ projectId: input.project_id,
34882
+ ...input.environment === void 0 ? {} : { environment: input.environment },
34883
+ name: input.name,
34884
+ ...input.limit === void 0 ? {} : { limit: input.limit }
34885
+ }));
34886
+ registerProductTool(server, dependencies, "database_schedule_run_now", "Queue one immediate run of a database schedule. Refused while the schedule is disabled or a run is already queued. Destructive: the statements execute against the database; requires confirmed: true. If the answer is lost, read database_schedule_run_list before calling again; a second call queues another run.", external_exports.object({
34887
+ project_id: identifier2,
34888
+ environment: databaseEnvironment,
34889
+ name: databaseScheduleName,
34890
+ confirmed: external_exports.literal(true)
34891
+ }), (client2, input) => client2.runDatabaseSchedule({
34892
+ projectId: input.project_id,
34893
+ environment: input.environment,
34894
+ name: input.name
34895
+ }), { ...destructiveAnnotations(), idempotentHint: false });
34896
+ registerProductTool(server, dependencies, "database_execution_usage_get", "Read metered database execution usage: schedule runs and webhook attempts per UTC hour or day window. from and to are UTC timestamps with milliseconds (Z), aligned to the granularity, at most 31 days apart. Only completed windows are final. Rejected, skipped, event and delivery counts are reported but not billed.", external_exports.object({
34897
+ project_id: identifier2,
34898
+ environment: databaseEnvironment.optional(),
34899
+ from: external_exports.string().regex(/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$/u),
34900
+ to: external_exports.string().regex(/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$/u),
34901
+ granularity: external_exports.enum(["hour", "day"]),
34902
+ limit: external_exports.number().int().min(1).max(100).optional(),
34903
+ cursor: external_exports.string().min(1).max(200).optional()
34904
+ }), (client2, input) => client2.getDatabaseExecutionUsage({
34905
+ projectId: input.project_id,
34906
+ ...input.environment === void 0 ? {} : { environment: input.environment },
34907
+ from: input.from,
34908
+ to: input.to,
34909
+ granularity: input.granularity,
34910
+ ...input.limit === void 0 ? {} : { limit: input.limit },
34911
+ ...input.cursor === void 0 ? {} : { cursor: input.cursor }
34912
+ }));
33950
34913
  registerProductTool(server, dependencies, "promotion_plan", "Plan promotion of the current Dev artifact to Prod without a rebuild.", external_exports.object({ project_id: identifier2, source_deployment_id: identifier2 }), (client2, input) => client2.planPromotion({
33951
34914
  projectId: input.project_id,
33952
34915
  sourceDeploymentId: input.source_deployment_id
@@ -34875,7 +35838,7 @@ function safeFailure(error, commandPrefix) {
34875
35838
  return {
34876
35839
  code: "request_timeout",
34877
35840
  retryable: true,
34878
- suggestedAction: "The ohmyho.st API did not answer within 30 seconds. Call this tool again; for a change use the same idempotency_key, because it may already be under way."
35841
+ suggestedAction: "The ohmyho.st API did not answer within 30 seconds. Call this tool again; for a change that takes an idempotency_key use the same key, because it may already be under way. A change without a key (webhook delete, test or replay, schedule set, delete or run) is repeated only after a read tool shows the current state."
34879
35842
  };
34880
35843
  if (error instanceof Error) {
34881
35844
  const local = localFailure(error, commandPrefix);
@@ -34942,7 +35905,7 @@ function localFailure(error, commandPrefix) {
34942
35905
  return {
34943
35906
  code: "network_error",
34944
35907
  retryable: true,
34945
- suggestedAction: "The request did not reach the ohmyho.st API, or its answer was cut off. Call this tool again; for a change use the same idempotency_key, because it may already have been applied."
35908
+ suggestedAction: "The request did not reach the ohmyho.st API, or its answer was cut off. Call this tool again; for a change that takes an idempotency_key use the same key, because it may already have been applied. A change without a key (webhook delete, test or replay, schedule set, delete or run) is repeated only after a read tool shows the current state."
34946
35909
  };
34947
35910
  case "ResponseContractError":
34948
35911
  return {