@amerged/ohmyhost-cli 0.1.42 → 0.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-HBM2X2MV.js → chunk-VJWPDFZ5.js} +84 -133
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +3 -3
- package/src/apps/product-cli/src/psql-session.ts +20 -32
- package/src/apps/product-cli/src/runtime-contract.ts +1 -13
- package/src/packages/contracts/src/credit-pricing.ts +0 -90
- package/src/packages/contracts/src/operation-failure.ts +4 -4
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/index.ts +0 -1
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +4 -4
- package/src/packages/sdk-ts/src/generated/types.gen.ts +8 -22
package/README.md
CHANGED
package/dist/bin.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __ohmyhostCreateRequire } from "node:module"; const require = __ohmyhostCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
runProductionCli
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VJWPDFZ5.js";
|
|
6
6
|
import "./chunk-7D2RFLWM.js";
|
|
7
7
|
|
|
8
8
|
// apps/product-cli/dist/bin.js
|
|
@@ -38879,12 +38879,12 @@ var failures = {
|
|
|
38879
38879
|
"Do not repeat the write with a new key. Inspect the target data with a read query and retain this operation ID. The same key only reads this receipt."
|
|
38880
38880
|
],
|
|
38881
38881
|
database_compute_failed: [
|
|
38882
|
-
"The database size change
|
|
38883
|
-
"Read the current database compute and report this operation ID through feedback.
|
|
38882
|
+
"The database provider refused the size change or had no room for it. The database keeps its previous size and keeps running, and no credits are charged for the failed change.",
|
|
38883
|
+
"Read the current size with 'ohmyhost database compute get --project PROJECT_ULID --environment dev|prod --json' or MCP database_compute_get, then repeat the change with a new idempotency key; the old key only returns this failure. If it fails again after a few minutes, start a new deployment of the project, repeat the change and report this operation ID through feedback. Never reset the database to change its size."
|
|
38884
38884
|
],
|
|
38885
38885
|
database_compute_plan_changed: [
|
|
38886
|
-
"Paid access ended before the database size change started.",
|
|
38887
|
-
"Read the organization's plan
|
|
38886
|
+
"Paid access ended before the database size change started, so it was not sent to the database provider. The database keeps its previous size and keeps running, and no credits are charged for the change.",
|
|
38887
|
+
"Read the organization's plan with 'ohmyhost credits account --organization ORGANIZATION_ULID --json' or MCP organization_account_get. Sizes above 256 MiB need active Paid: ask the organization Owner to activate Paid through billing checkout, then read the current size with database compute get and repeat the change with a new idempotency key."
|
|
38888
38888
|
],
|
|
38889
38889
|
database_compute_rejected: [
|
|
38890
38890
|
"The database size change could not be started.",
|
|
@@ -40055,112 +40055,6 @@ function isSaasCnameTarget(value) {
|
|
|
40055
40055
|
return value === "customers.omh.st" || value === "customers.ohmyho.st";
|
|
40056
40056
|
}
|
|
40057
40057
|
|
|
40058
|
-
// packages/contracts/dist/credit-pricing.js
|
|
40059
|
-
function assertOrganizationCreditUsage(value) {
|
|
40060
|
-
const record7 = (input, keys) => {
|
|
40061
|
-
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join() !== keys.split(",").sort().join())
|
|
40062
|
-
throw new TypeError("Invalid usage fields");
|
|
40063
|
-
return input;
|
|
40064
|
-
};
|
|
40065
|
-
const identifier2 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
|
|
40066
|
-
const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
|
|
40067
|
-
const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
|
|
40068
|
-
const report = record7(value, "organization_id,as_of,unit,period,from,projects,days");
|
|
40069
|
-
if (!identifier2(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)
|
|
40070
|
-
throw new TypeError("Invalid usage report");
|
|
40071
|
-
let previous = "";
|
|
40072
|
-
for (const input of report["projects"]) {
|
|
40073
|
-
const project = record7(input, "project_id,used_micros");
|
|
40074
|
-
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
|
|
40075
|
-
throw new TypeError("Invalid usage project");
|
|
40076
|
-
previous = String(project["project_id"]);
|
|
40077
|
-
}
|
|
40078
|
-
let previousDay = "";
|
|
40079
|
-
for (const input of report["days"]) {
|
|
40080
|
-
const day = record7(input, "day,projects");
|
|
40081
|
-
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)
|
|
40082
|
-
throw new TypeError("Invalid usage day");
|
|
40083
|
-
previousDay = day["day"];
|
|
40084
|
-
previous = "";
|
|
40085
|
-
for (const projectInput of day["projects"]) {
|
|
40086
|
-
const project = record7(projectInput, "project_id,meters");
|
|
40087
|
-
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
|
|
40088
|
-
throw new TypeError("Invalid usage project");
|
|
40089
|
-
previous = String(project["project_id"]);
|
|
40090
|
-
for (const meterInput of project["meters"]) {
|
|
40091
|
-
const meter = record7(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
|
|
40092
|
-
if (meter["environment_id"] !== null && !identifier2(meter["environment_id"]))
|
|
40093
|
-
throw new TypeError("Invalid usage environment");
|
|
40094
|
-
for (const key of ["meter", "unit", "rate_card_id"])
|
|
40095
|
-
if (typeof meter[key] !== "string" || !/^[A-Za-z0-9_.:/-]{1,128}$/u.test(meter[key]))
|
|
40096
|
-
throw new TypeError("Invalid usage meter");
|
|
40097
|
-
if (typeof meter["quantity"] !== "string" || !/^(0|[1-9][0-9]{0,29})(\.[0-9]{1,12})?$/u.test(meter["quantity"]) || !amount(meter["charged_micros"]))
|
|
40098
|
-
throw new TypeError("Invalid usage amount");
|
|
40099
|
-
}
|
|
40100
|
-
}
|
|
40101
|
-
}
|
|
40102
|
-
}
|
|
40103
|
-
function assertPublishedCreditRateCards(value) {
|
|
40104
|
-
if (!Array.isArray(value) || value.length > 4)
|
|
40105
|
-
throw new TypeError("Invalid published prices");
|
|
40106
|
-
const ids = /* @__PURE__ */ new Set();
|
|
40107
|
-
for (const input of value) {
|
|
40108
|
-
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join() !== "currency,effective_from,id,published_at,rates")
|
|
40109
|
-
throw new TypeError("Invalid published price fields");
|
|
40110
|
-
const card = input;
|
|
40111
|
-
if (typeof card["id"] !== "string" || !/^[a-z0-9_.-]{1,128}$/u.test(card["id"]) || ids.has(card["id"]) || card["currency"] !== "USD")
|
|
40112
|
-
throw new TypeError("Invalid price identity");
|
|
40113
|
-
ids.add(card["id"]);
|
|
40114
|
-
for (const key of ["published_at", "effective_from"]) {
|
|
40115
|
-
const date2 = card[key];
|
|
40116
|
-
if (typeof date2 !== "string" || !Number.isFinite(Date.parse(date2)) || new Date(date2).toISOString() !== date2)
|
|
40117
|
-
throw new TypeError("Invalid price dates");
|
|
40118
|
-
}
|
|
40119
|
-
if (String(card["published_at"]) > String(card["effective_from"]) || !Array.isArray(card["rates"]) || card["rates"].length < 1 || card["rates"].length > 32)
|
|
40120
|
-
throw new TypeError("Invalid price publication");
|
|
40121
|
-
const meters = /* @__PURE__ */ new Set();
|
|
40122
|
-
for (const item of card["rates"]) {
|
|
40123
|
-
if (!item || typeof item !== "object" || Array.isArray(item) || Object.keys(item).sort().join() !== "credit_micros,meter,provider_cost_micros,unit,units_per_charge")
|
|
40124
|
-
throw new TypeError("Invalid rate fields");
|
|
40125
|
-
const rate = item;
|
|
40126
|
-
for (const key of ["meter", "unit"])
|
|
40127
|
-
if (typeof rate[key] !== "string" || !/^[a-z0-9_.-]{1,128}$/u.test(String(rate[key])))
|
|
40128
|
-
throw new TypeError("Invalid rate unit");
|
|
40129
|
-
const identity = String(rate["meter"]) + "/" + String(rate["unit"]);
|
|
40130
|
-
if (meters.has(identity))
|
|
40131
|
-
throw new TypeError("Duplicate rate");
|
|
40132
|
-
meters.add(identity);
|
|
40133
|
-
for (const key of ["units_per_charge", "provider_cost_micros", "credit_micros"]) {
|
|
40134
|
-
const amount = rate[key];
|
|
40135
|
-
if (key === "provider_cost_micros" && amount === null && rate["meter"] === "pgcf.memory.active")
|
|
40136
|
-
continue;
|
|
40137
|
-
if (typeof amount !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(amount) || BigInt(amount) > 9223372036854775807n || key === "units_per_charge" && amount === "0")
|
|
40138
|
-
throw new TypeError("Invalid rate amount");
|
|
40139
|
-
}
|
|
40140
|
-
}
|
|
40141
|
-
}
|
|
40142
|
-
}
|
|
40143
|
-
function assertOrganizationAccount(value) {
|
|
40144
|
-
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")
|
|
40145
|
-
throw new TypeError("Invalid account fields");
|
|
40146
|
-
const v = value;
|
|
40147
|
-
if (typeof v["organization_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(v["organization_id"]) || typeof v["name"] !== "string" || v["name"].length > 128 || typeof v["workos_organization_id"] !== "string" || !/^org_[A-Za-z0-9_]+$/u.test(v["workos_organization_id"]) || v["plan"] !== "paid" && v["plan"] !== "free" || !["free", "stripe", "granted", "manual"].includes(String(v["plan_source"])) || v["plan"] === "free" !== (v["plan_source"] === "free"))
|
|
40148
|
-
throw new TypeError("Invalid account scope");
|
|
40149
|
-
for (const field of ["available_micros", "monthly_micros", "one_time_micros", "reserved_micros"])
|
|
40150
|
-
if (typeof v[field] !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(v[field]))
|
|
40151
|
-
throw new TypeError("Invalid account credits");
|
|
40152
|
-
const held = BigInt(String(v["reserved_micros"]));
|
|
40153
|
-
const balance = BigInt(String(v["monthly_micros"])) + BigInt(String(v["one_time_micros"]));
|
|
40154
|
-
if (BigInt(String(v["available_micros"])) !== (balance > held ? balance - held : 0n))
|
|
40155
|
-
throw new TypeError("Account credit buckets do not balance");
|
|
40156
|
-
for (const field of ["as_of", "paid_until", "next_expiry"]) {
|
|
40157
|
-
if (field !== "as_of" && v[field] === null)
|
|
40158
|
-
continue;
|
|
40159
|
-
if (typeof v[field] !== "string" || !Number.isFinite(Date.parse(v[field])) || new Date(v[field]).toISOString() !== v[field])
|
|
40160
|
-
throw new TypeError("Invalid account timestamp");
|
|
40161
|
-
}
|
|
40162
|
-
}
|
|
40163
|
-
|
|
40164
40058
|
// packages/contracts/dist/problem-policy.js
|
|
40165
40059
|
var PROBLEM_POLICY = {
|
|
40166
40060
|
source_generation_conflict: {
|
|
@@ -40906,19 +40800,12 @@ function parseOrganizationCredits(value) {
|
|
|
40906
40800
|
"available_micros",
|
|
40907
40801
|
"reserved_micros",
|
|
40908
40802
|
"grace_started_at",
|
|
40909
|
-
"grace_expires_at"
|
|
40910
|
-
"active_meters",
|
|
40911
|
-
"rate_cards"
|
|
40803
|
+
"grace_expires_at"
|
|
40912
40804
|
]);
|
|
40913
|
-
try {
|
|
40914
|
-
assertPublishedCreditRateCards(input["rate_cards"]);
|
|
40915
|
-
} catch {
|
|
40916
|
-
throw new ResponseContractError();
|
|
40917
|
-
}
|
|
40918
40805
|
const graceStart = input["grace_started_at"], graceEnd = input["grace_expires_at"];
|
|
40919
40806
|
if (!(graceStart === null && graceEnd === null) && !(isIsoInstant(graceStart) && isIsoInstant(graceEnd) && Date.parse(graceEnd) - Date.parse(graceStart) === 6048e5))
|
|
40920
40807
|
throw new ResponseContractError();
|
|
40921
|
-
if (!isUlid(input["organization_id"]) || input["unit"] !== "microcredits" || !isIsoInstant(input["as_of"])
|
|
40808
|
+
if (!isUlid(input["organization_id"]) || input["unit"] !== "microcredits" || !isIsoInstant(input["as_of"]))
|
|
40922
40809
|
throw new ResponseContractError();
|
|
40923
40810
|
for (const field of ["available_micros", "reserved_micros"]) {
|
|
40924
40811
|
const amount = input[field];
|
|
@@ -45312,6 +45199,72 @@ function exact3(value, keys) {
|
|
|
45312
45199
|
return Object.keys(value).sort().join(",") === [...keys].sort().join(",");
|
|
45313
45200
|
}
|
|
45314
45201
|
|
|
45202
|
+
// packages/contracts/dist/credit-pricing.js
|
|
45203
|
+
function assertOrganizationCreditUsage(value) {
|
|
45204
|
+
const record7 = (input, keys) => {
|
|
45205
|
+
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join() !== keys.split(",").sort().join())
|
|
45206
|
+
throw new TypeError("Invalid usage fields");
|
|
45207
|
+
return input;
|
|
45208
|
+
};
|
|
45209
|
+
const identifier2 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
|
|
45210
|
+
const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
|
|
45211
|
+
const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
|
|
45212
|
+
const report = record7(value, "organization_id,as_of,unit,period,from,projects,days");
|
|
45213
|
+
if (!identifier2(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)
|
|
45214
|
+
throw new TypeError("Invalid usage report");
|
|
45215
|
+
let previous = "";
|
|
45216
|
+
for (const input of report["projects"]) {
|
|
45217
|
+
const project = record7(input, "project_id,used_micros");
|
|
45218
|
+
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
|
|
45219
|
+
throw new TypeError("Invalid usage project");
|
|
45220
|
+
previous = String(project["project_id"]);
|
|
45221
|
+
}
|
|
45222
|
+
let previousDay = "";
|
|
45223
|
+
for (const input of report["days"]) {
|
|
45224
|
+
const day = record7(input, "day,projects");
|
|
45225
|
+
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)
|
|
45226
|
+
throw new TypeError("Invalid usage day");
|
|
45227
|
+
previousDay = day["day"];
|
|
45228
|
+
previous = "";
|
|
45229
|
+
for (const projectInput of day["projects"]) {
|
|
45230
|
+
const project = record7(projectInput, "project_id,meters");
|
|
45231
|
+
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
|
|
45232
|
+
throw new TypeError("Invalid usage project");
|
|
45233
|
+
previous = String(project["project_id"]);
|
|
45234
|
+
for (const meterInput of project["meters"]) {
|
|
45235
|
+
const meter = record7(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
|
|
45236
|
+
if (meter["environment_id"] !== null && !identifier2(meter["environment_id"]))
|
|
45237
|
+
throw new TypeError("Invalid usage environment");
|
|
45238
|
+
for (const key of ["meter", "unit", "rate_card_id"])
|
|
45239
|
+
if (typeof meter[key] !== "string" || !/^[A-Za-z0-9_.:/-]{1,128}$/u.test(meter[key]))
|
|
45240
|
+
throw new TypeError("Invalid usage meter");
|
|
45241
|
+
if (typeof meter["quantity"] !== "string" || !/^(0|[1-9][0-9]{0,29})(\.[0-9]{1,12})?$/u.test(meter["quantity"]) || !amount(meter["charged_micros"]))
|
|
45242
|
+
throw new TypeError("Invalid usage amount");
|
|
45243
|
+
}
|
|
45244
|
+
}
|
|
45245
|
+
}
|
|
45246
|
+
}
|
|
45247
|
+
function assertOrganizationAccount(value) {
|
|
45248
|
+
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")
|
|
45249
|
+
throw new TypeError("Invalid account fields");
|
|
45250
|
+
const v = value;
|
|
45251
|
+
if (typeof v["organization_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(v["organization_id"]) || typeof v["name"] !== "string" || v["name"].length > 128 || typeof v["workos_organization_id"] !== "string" || !/^org_[A-Za-z0-9_]+$/u.test(v["workos_organization_id"]) || v["plan"] !== "paid" && v["plan"] !== "free" || !["free", "stripe", "granted", "manual"].includes(String(v["plan_source"])) || v["plan"] === "free" !== (v["plan_source"] === "free"))
|
|
45252
|
+
throw new TypeError("Invalid account scope");
|
|
45253
|
+
for (const field of ["available_micros", "monthly_micros", "one_time_micros", "reserved_micros"])
|
|
45254
|
+
if (typeof v[field] !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(v[field]))
|
|
45255
|
+
throw new TypeError("Invalid account credits");
|
|
45256
|
+
const held = BigInt(String(v["reserved_micros"]));
|
|
45257
|
+
const balance = BigInt(String(v["monthly_micros"])) + BigInt(String(v["one_time_micros"]));
|
|
45258
|
+
if (BigInt(String(v["available_micros"])) !== (balance > held ? balance - held : 0n))
|
|
45259
|
+
throw new TypeError("Account credit buckets do not balance");
|
|
45260
|
+
for (const field of ["as_of", "paid_until", "next_expiry"]) {
|
|
45261
|
+
if (field !== "as_of" && v[field] === null)
|
|
45262
|
+
continue;
|
|
45263
|
+
if (typeof v[field] !== "string" || !Number.isFinite(Date.parse(v[field])) || new Date(v[field]).toISOString() !== v[field])
|
|
45264
|
+
throw new TypeError("Invalid account timestamp");
|
|
45265
|
+
}
|
|
45266
|
+
}
|
|
45267
|
+
|
|
45315
45268
|
// packages/contracts/dist/database-compute.js
|
|
45316
45269
|
function assertDatabaseCompute(value) {
|
|
45317
45270
|
if (!record4(value) || !exact4(value, ["data_mode", "database", "environment", "observed_at", "project_id"]) || typeof value["project_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(value["project_id"]) || !["dev", "prod"].includes(String(value["environment"])) || !["shared", "isolated"].includes(String(value["data_mode"])) || typeof value["observed_at"] !== "string" || !Number.isFinite(Date.parse(value["observed_at"])) || new Date(value["observed_at"]).toISOString() !== value["observed_at"])
|
|
@@ -45364,7 +45317,7 @@ function exact4(v, keys) {
|
|
|
45364
45317
|
// apps/product-cli/package.json
|
|
45365
45318
|
var package_default = {
|
|
45366
45319
|
name: "@ohmyhost/product-cli",
|
|
45367
|
-
version: "0.1.
|
|
45320
|
+
version: "0.1.44",
|
|
45368
45321
|
private: true,
|
|
45369
45322
|
ohmyhost: {
|
|
45370
45323
|
deployment: "production",
|
|
@@ -45716,13 +45669,13 @@ var HELP_USAGE = Object.freeze({
|
|
|
45716
45669
|
"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)",
|
|
45717
45670
|
"database webhook deliveries": "ohmyhost database webhook deliveries --project ULID [--environment dev|prod] [--webhook ID] [--limit 1..100] [--cursor CURSOR] --json",
|
|
45718
45671
|
"database webhook replay": "ohmyhost database webhook replay --project ULID --environment dev|prod --delivery ID --yes --json",
|
|
45719
|
-
"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)",
|
|
45672
|
+
"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). A project whose Stop budget is reached has its schedules disabled automatically, within about an hour of the billed usage reaching the budget: the credit service does this after its hourly pgcf pass, and Continue budgets are never touched. While the budget is reached, schedule set with enabled true and schedule run are refused with project_budget_exceeded (HTTP 402). Re-enabling is manual: raise the budget (or wait for the next UTC month) and run database schedule set --enabled true again with the schedule body (read it with schedule get).",
|
|
45720
45673
|
"database schedule list": "ohmyhost database schedule list --project ULID [--environment dev|prod] --json (dev when omitted)",
|
|
45721
45674
|
"database schedule get": "ohmyhost database schedule get --project ULID [--environment dev|prod] --name NAME --json",
|
|
45722
45675
|
"database schedule delete": "ohmyhost database schedule delete --project ULID --environment dev|prod --name NAME --yes --json",
|
|
45723
45676
|
"database schedule runs": "ohmyhost database schedule runs --project ULID [--environment dev|prod] --name NAME [--limit 1..50] --json",
|
|
45724
|
-
"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)",
|
|
45725
|
-
"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;
|
|
45677
|
+
"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; refused with project_budget_exceeded (HTTP 402) while the project's Stop budget is reached)",
|
|
45678
|
+
"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; these are counters only, executions have no price of their own and the awake compute time of the database is what is billed)",
|
|
45726
45679
|
"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)",
|
|
45727
45680
|
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)",
|
|
45728
45681
|
"source auto-deploy set": "ohmyhost source auto-deploy set --project ULID --branch BRANCH --enabled true|false --idempotency-key KEY --json",
|
|
@@ -55906,9 +55859,9 @@ async function startBridge(raw, hooks = {}) {
|
|
|
55906
55859
|
// apps/product-cli/dist/psql-session.js
|
|
55907
55860
|
var runLocalPsql = async (input) => {
|
|
55908
55861
|
input.signal.throwIfAborted();
|
|
55909
|
-
if (input.websocketUrl !==
|
|
55862
|
+
if (input.websocketUrl !== `wss://${input.host}/`)
|
|
55910
55863
|
throw new Error("Invalid PGCF transport");
|
|
55911
|
-
const bridge =
|
|
55864
|
+
const bridge = await startBridge({
|
|
55912
55865
|
endpoint: input.websocketUrl,
|
|
55913
55866
|
database: input.database,
|
|
55914
55867
|
user: input.user,
|
|
@@ -55918,18 +55871,16 @@ var runLocalPsql = async (input) => {
|
|
|
55918
55871
|
input.signal.throwIfAborted();
|
|
55919
55872
|
const environment = Object.fromEntries(Object.entries(process.env).filter(([key]) => !/^PG[A-Z_]+$/iu.test(key)));
|
|
55920
55873
|
return await new Promise((resolve7, reject) => {
|
|
55921
|
-
const child = spawn("psql", ["-h", bridge
|
|
55874
|
+
const child = spawn("psql", ["-h", bridge.host, "-U", input.user, "-d", input.database], {
|
|
55922
55875
|
stdio: "inherit",
|
|
55923
55876
|
signal: input.signal,
|
|
55924
55877
|
env: {
|
|
55925
55878
|
...environment,
|
|
55926
55879
|
PGPASSWORD: input.password,
|
|
55927
|
-
PGSSLMODE:
|
|
55928
|
-
|
|
55929
|
-
|
|
55930
|
-
|
|
55931
|
-
PGGSSENCMODE: "disable"
|
|
55932
|
-
} : {}
|
|
55880
|
+
PGSSLMODE: "disable",
|
|
55881
|
+
PGPORT: String(bridge.port),
|
|
55882
|
+
PGCHANNELBINDING: "disable",
|
|
55883
|
+
PGGSSENCMODE: "disable"
|
|
55933
55884
|
}
|
|
55934
55885
|
});
|
|
55935
55886
|
child.once("error", (error) => {
|
|
@@ -55940,7 +55891,7 @@ var runLocalPsql = async (input) => {
|
|
|
55940
55891
|
});
|
|
55941
55892
|
});
|
|
55942
55893
|
} finally {
|
|
55943
|
-
await bridge
|
|
55894
|
+
await bridge.close();
|
|
55944
55895
|
}
|
|
55945
55896
|
};
|
|
55946
55897
|
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -434,7 +434,7 @@ const HELP_USAGE = Object.freeze({
|
|
|
434
434
|
"database webhook replay":
|
|
435
435
|
"ohmyhost database webhook replay --project ULID --environment dev|prod --delivery ID --yes --json",
|
|
436
436
|
"database schedule set":
|
|
437
|
-
"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)",
|
|
437
|
+
"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). A project whose Stop budget is reached has its schedules disabled automatically, within about an hour of the billed usage reaching the budget: the credit service does this after its hourly pgcf pass, and Continue budgets are never touched. While the budget is reached, schedule set with enabled true and schedule run are refused with project_budget_exceeded (HTTP 402). Re-enabling is manual: raise the budget (or wait for the next UTC month) and run database schedule set --enabled true again with the schedule body (read it with schedule get).",
|
|
438
438
|
"database schedule list":
|
|
439
439
|
"ohmyhost database schedule list --project ULID [--environment dev|prod] --json (dev when omitted)",
|
|
440
440
|
"database schedule get":
|
|
@@ -444,9 +444,9 @@ const HELP_USAGE = Object.freeze({
|
|
|
444
444
|
"database schedule runs":
|
|
445
445
|
"ohmyhost database schedule runs --project ULID [--environment dev|prod] --name NAME [--limit 1..50] --json",
|
|
446
446
|
"database schedule run":
|
|
447
|
-
"ohmyhost database schedule run --project ULID --environment dev|prod --name NAME --yes --json (queues one run now, in addition to the timer)",
|
|
447
|
+
"ohmyhost database schedule run --project ULID --environment dev|prod --name NAME --yes --json (queues one run now, in addition to the timer; refused with project_budget_exceeded (HTTP 402) while the project's Stop budget is reached)",
|
|
448
448
|
"database executions":
|
|
449
|
-
"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;
|
|
449
|
+
"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; these are counters only, executions have no price of their own and the awake compute time of the database is what is billed)",
|
|
450
450
|
"database psql":
|
|
451
451
|
"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)",
|
|
452
452
|
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)",
|
|
@@ -9,21 +9,17 @@ export const runLocalPsql = async (input: {
|
|
|
9
9
|
readonly user: string;
|
|
10
10
|
readonly password: string;
|
|
11
11
|
readonly database: string;
|
|
12
|
-
readonly websocketUrl
|
|
12
|
+
readonly websocketUrl: string;
|
|
13
13
|
readonly signal: AbortSignal;
|
|
14
14
|
}): Promise<number> => {
|
|
15
15
|
input.signal.throwIfAborted();
|
|
16
|
-
if (input.websocketUrl !==
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
input.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
database: input.database,
|
|
24
|
-
user: input.user,
|
|
25
|
-
port: 0,
|
|
26
|
-
});
|
|
16
|
+
if (input.websocketUrl !== `wss://${input.host}/`) throw new Error("Invalid PGCF transport");
|
|
17
|
+
const bridge = await startBridge({
|
|
18
|
+
endpoint: input.websocketUrl,
|
|
19
|
+
database: input.database,
|
|
20
|
+
user: input.user,
|
|
21
|
+
port: 0,
|
|
22
|
+
});
|
|
27
23
|
try {
|
|
28
24
|
input.signal.throwIfAborted();
|
|
29
25
|
// A caller's libpq service/hostaddr settings must not redirect this temporary credential.
|
|
@@ -31,26 +27,18 @@ export const runLocalPsql = async (input: {
|
|
|
31
27
|
Object.entries(process.env).filter(([key]) => !/^PG[A-Z_]+$/iu.test(key)),
|
|
32
28
|
);
|
|
33
29
|
return await new Promise<number>((resolve, reject) => {
|
|
34
|
-
const child = spawn(
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
...(bridge
|
|
45
|
-
? {
|
|
46
|
-
PGPORT: String(bridge.port),
|
|
47
|
-
PGCHANNELBINDING: "disable",
|
|
48
|
-
PGGSSENCMODE: "disable",
|
|
49
|
-
}
|
|
50
|
-
: {}),
|
|
51
|
-
},
|
|
30
|
+
const child = spawn("psql", ["-h", bridge.host, "-U", input.user, "-d", input.database], {
|
|
31
|
+
stdio: "inherit",
|
|
32
|
+
signal: input.signal,
|
|
33
|
+
env: {
|
|
34
|
+
...environment,
|
|
35
|
+
PGPASSWORD: input.password,
|
|
36
|
+
PGSSLMODE: "disable",
|
|
37
|
+
PGPORT: String(bridge.port),
|
|
38
|
+
PGCHANNELBINDING: "disable",
|
|
39
|
+
PGGSSENCMODE: "disable",
|
|
52
40
|
},
|
|
53
|
-
);
|
|
41
|
+
});
|
|
54
42
|
child.once("error", (error: NodeJS.ErrnoException) => {
|
|
55
43
|
reject(error.code === "ENOENT" ? new PsqlUnavailableError() : error);
|
|
56
44
|
});
|
|
@@ -59,6 +47,6 @@ export const runLocalPsql = async (input: {
|
|
|
59
47
|
});
|
|
60
48
|
});
|
|
61
49
|
} finally {
|
|
62
|
-
await bridge
|
|
50
|
+
await bridge.close();
|
|
63
51
|
}
|
|
64
52
|
};
|
|
@@ -23,7 +23,6 @@ import type {
|
|
|
23
23
|
ProjectCreditBudget,
|
|
24
24
|
} from "@ohmyhost/sdk-ts";
|
|
25
25
|
import { isSaasCnameTarget, type SaasCnameTarget } from "@ohmyhost/contracts/platform-origins";
|
|
26
|
-
import { assertPublishedCreditRateCards } from "@ohmyhost/contracts/credit-pricing";
|
|
27
26
|
import {
|
|
28
27
|
publicOperationFailure,
|
|
29
28
|
publicOperationReconciliation,
|
|
@@ -554,14 +553,7 @@ export function parseOrganizationCredits(value: unknown): OrganizationCredits {
|
|
|
554
553
|
"reserved_micros",
|
|
555
554
|
"grace_started_at",
|
|
556
555
|
"grace_expires_at",
|
|
557
|
-
"active_meters",
|
|
558
|
-
"rate_cards",
|
|
559
556
|
]);
|
|
560
|
-
try {
|
|
561
|
-
assertPublishedCreditRateCards(input["rate_cards"]);
|
|
562
|
-
} catch {
|
|
563
|
-
throw new ResponseContractError();
|
|
564
|
-
}
|
|
565
557
|
const graceStart = input["grace_started_at"],
|
|
566
558
|
graceEnd = input["grace_expires_at"];
|
|
567
559
|
if (
|
|
@@ -576,11 +568,7 @@ export function parseOrganizationCredits(value: unknown): OrganizationCredits {
|
|
|
576
568
|
if (
|
|
577
569
|
!isUlid(input["organization_id"]) ||
|
|
578
570
|
input["unit"] !== "microcredits" ||
|
|
579
|
-
!isIsoInstant(input["as_of"])
|
|
580
|
-
!Array.isArray(input["active_meters"]) ||
|
|
581
|
-
input["active_meters"].some(
|
|
582
|
-
(m: unknown) => typeof m !== "string" || !/^[a-z0-9_.-]{1,128}$/u.test(m),
|
|
583
|
-
)
|
|
571
|
+
!isIsoInstant(input["as_of"])
|
|
584
572
|
)
|
|
585
573
|
throw new ResponseContractError();
|
|
586
574
|
for (const field of ["available_micros", "reserved_micros"]) {
|
|
@@ -116,96 +116,6 @@ export function assertOrganizationCreditUsage(
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
export interface PublishedCreditRateCard {
|
|
120
|
-
readonly id: string;
|
|
121
|
-
readonly currency: "USD";
|
|
122
|
-
readonly published_at: string;
|
|
123
|
-
readonly effective_from: string;
|
|
124
|
-
readonly rates: readonly {
|
|
125
|
-
readonly meter: string;
|
|
126
|
-
readonly unit: string;
|
|
127
|
-
readonly units_per_charge: string;
|
|
128
|
-
readonly provider_cost_micros: string | null;
|
|
129
|
-
readonly credit_micros: string;
|
|
130
|
-
}[];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/** Shared wire validation only; clients never recompute accounting decisions. */
|
|
134
|
-
export function assertPublishedCreditRateCards(
|
|
135
|
-
value: unknown,
|
|
136
|
-
): asserts value is readonly PublishedCreditRateCard[] {
|
|
137
|
-
if (!Array.isArray(value) || value.length > 4) throw new TypeError("Invalid published prices");
|
|
138
|
-
const ids = new Set<string>();
|
|
139
|
-
for (const input of value) {
|
|
140
|
-
if (
|
|
141
|
-
!input ||
|
|
142
|
-
typeof input !== "object" ||
|
|
143
|
-
Array.isArray(input) ||
|
|
144
|
-
Object.keys(input).sort().join() !== "currency,effective_from,id,published_at,rates"
|
|
145
|
-
)
|
|
146
|
-
throw new TypeError("Invalid published price fields");
|
|
147
|
-
const card = input as Record<string, unknown>;
|
|
148
|
-
if (
|
|
149
|
-
typeof card["id"] !== "string" ||
|
|
150
|
-
!/^[a-z0-9_.-]{1,128}$/u.test(card["id"]) ||
|
|
151
|
-
ids.has(card["id"]) ||
|
|
152
|
-
card["currency"] !== "USD"
|
|
153
|
-
)
|
|
154
|
-
throw new TypeError("Invalid price identity");
|
|
155
|
-
ids.add(card["id"]);
|
|
156
|
-
for (const key of ["published_at", "effective_from"]) {
|
|
157
|
-
const date = card[key];
|
|
158
|
-
if (
|
|
159
|
-
typeof date !== "string" ||
|
|
160
|
-
!Number.isFinite(Date.parse(date)) ||
|
|
161
|
-
new Date(date).toISOString() !== date
|
|
162
|
-
)
|
|
163
|
-
throw new TypeError("Invalid price dates");
|
|
164
|
-
}
|
|
165
|
-
if (
|
|
166
|
-
String(card["published_at"]) > String(card["effective_from"]) ||
|
|
167
|
-
!Array.isArray(card["rates"]) ||
|
|
168
|
-
card["rates"].length < 1 ||
|
|
169
|
-
card["rates"].length > 32
|
|
170
|
-
)
|
|
171
|
-
throw new TypeError("Invalid price publication");
|
|
172
|
-
const meters = new Set<string>();
|
|
173
|
-
for (const item of card["rates"]) {
|
|
174
|
-
if (
|
|
175
|
-
!item ||
|
|
176
|
-
typeof item !== "object" ||
|
|
177
|
-
Array.isArray(item) ||
|
|
178
|
-
Object.keys(item).sort().join() !==
|
|
179
|
-
"credit_micros,meter,provider_cost_micros,unit,units_per_charge"
|
|
180
|
-
)
|
|
181
|
-
throw new TypeError("Invalid rate fields");
|
|
182
|
-
const rate = item as Record<string, unknown>;
|
|
183
|
-
for (const key of ["meter", "unit"])
|
|
184
|
-
if (typeof rate[key] !== "string" || !/^[a-z0-9_.-]{1,128}$/u.test(String(rate[key])))
|
|
185
|
-
throw new TypeError("Invalid rate unit");
|
|
186
|
-
const identity = String(rate["meter"]) + "/" + String(rate["unit"]);
|
|
187
|
-
if (meters.has(identity)) throw new TypeError("Duplicate rate");
|
|
188
|
-
meters.add(identity);
|
|
189
|
-
for (const key of ["units_per_charge", "provider_cost_micros", "credit_micros"]) {
|
|
190
|
-
const amount = rate[key];
|
|
191
|
-
if (
|
|
192
|
-
key === "provider_cost_micros" &&
|
|
193
|
-
amount === null &&
|
|
194
|
-
rate["meter"] === "pgcf.memory.active"
|
|
195
|
-
)
|
|
196
|
-
continue;
|
|
197
|
-
if (
|
|
198
|
-
typeof amount !== "string" ||
|
|
199
|
-
!/^(0|[1-9][0-9]{0,18})$/u.test(amount) ||
|
|
200
|
-
BigInt(amount) > 9223372036854775807n ||
|
|
201
|
-
(key === "units_per_charge" && amount === "0")
|
|
202
|
-
)
|
|
203
|
-
throw new TypeError("Invalid rate amount");
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
119
|
/** Effective feature access and the credit account: the monthly and one-time credit and what the open reservations hold. */
|
|
210
120
|
export function assertOrganizationAccount(value: unknown): void {
|
|
211
121
|
if (
|
|
@@ -34,12 +34,12 @@ const failures = {
|
|
|
34
34
|
"Do not repeat the write with a new key. Inspect the target data with a read query and retain this operation ID. The same key only reads this receipt.",
|
|
35
35
|
],
|
|
36
36
|
database_compute_failed: [
|
|
37
|
-
"The database size change
|
|
38
|
-
"Read the current database compute and report this operation ID through feedback.
|
|
37
|
+
"The database provider refused the size change or had no room for it. The database keeps its previous size and keeps running, and no credits are charged for the failed change.",
|
|
38
|
+
"Read the current size with 'ohmyhost database compute get --project PROJECT_ULID --environment dev|prod --json' or MCP database_compute_get, then repeat the change with a new idempotency key; the old key only returns this failure. If it fails again after a few minutes, start a new deployment of the project, repeat the change and report this operation ID through feedback. Never reset the database to change its size.",
|
|
39
39
|
],
|
|
40
40
|
database_compute_plan_changed: [
|
|
41
|
-
"Paid access ended before the database size change started.",
|
|
42
|
-
"Read the organization's plan
|
|
41
|
+
"Paid access ended before the database size change started, so it was not sent to the database provider. The database keeps its previous size and keeps running, and no credits are charged for the change.",
|
|
42
|
+
"Read the organization's plan with 'ohmyhost credits account --organization ORGANIZATION_ULID --json' or MCP organization_account_get. Sizes above 256 MiB need active Paid: ask the organization Owner to activate Paid through billing checkout, then read the current size with database compute get and repeat the change with a new idempotency key.",
|
|
43
43
|
],
|
|
44
44
|
database_compute_rejected: [
|
|
45
45
|
"The database size change could not be started.",
|
|
@@ -2192,7 +2192,7 @@ export const configureBillingRecharge = <ThrowOnError extends boolean = true>(
|
|
|
2192
2192
|
/**
|
|
2193
2193
|
* Read the owner's shared organization credit pool
|
|
2194
2194
|
*
|
|
2195
|
-
* Returns the spendable credit and the open reservations, in microcredits (one credit is 1000000 microcredits). available_micros is the monthly credit plus the one-time credit minus the reservations, never below zero. Only the organization Owner may read this balance.
|
|
2195
|
+
* Returns the spendable credit and the open reservations, in microcredits (one credit is 1000000 microcredits). available_micros is the monthly credit plus the one-time credit minus the reservations, never below zero. Only the organization Owner may read this balance. It states what is left and never what the credit was spent on; read the recent usage from getOrganizationCreditUsage. When the credit is used up, grace_started_at and grace_expires_at name the seven days that keep existing services running. Remains available at zero credit.
|
|
2196
2196
|
*/
|
|
2197
2197
|
export const getOrganizationCredits = <ThrowOnError extends boolean = true>(
|
|
2198
2198
|
parameters: {
|
|
@@ -5227,7 +5227,7 @@ export const getProjectDatabaseSchedule = <ThrowOnError extends boolean = true>(
|
|
|
5227
5227
|
/**
|
|
5228
5228
|
* Create or replace one database schedule
|
|
5229
5229
|
*
|
|
5230
|
-
* Creates the named schedule or replaces it. Each run executes the statements as the application's own runtime role, so row-level security applies as for the application. A run that does not finish within timeout_ms is cancelled.
|
|
5230
|
+
* Creates the named schedule or replaces it. Each run executes the statements as the application's own runtime role, so row-level security applies as for the application. A run that does not finish within timeout_ms is cancelled. A reached Stop budget (or exhausted credit past its grace) refuses an enabled schedule with project_budget_exceeded (402); disabling the schedule is never refused.
|
|
5231
5231
|
*/
|
|
5232
5232
|
export const setProjectDatabaseSchedule = <ThrowOnError extends boolean = true>(
|
|
5233
5233
|
parameters: {
|
|
@@ -5328,7 +5328,7 @@ export const listProjectDatabaseScheduleRuns = <ThrowOnError extends boolean = t
|
|
|
5328
5328
|
/**
|
|
5329
5329
|
* Queue one immediate run of a database schedule
|
|
5330
5330
|
*
|
|
5331
|
-
* Queues one manual run. The run is refused while the schedule is disabled or while a run is already queued.
|
|
5331
|
+
* Queues one manual run. The run is refused while the schedule is disabled or while a run is already queued. A reached Stop budget (or exhausted credit past its grace) refuses the run with project_budget_exceeded (402).
|
|
5332
5332
|
*/
|
|
5333
5333
|
export const runProjectDatabaseSchedule = <ThrowOnError extends boolean = true>(
|
|
5334
5334
|
parameters: {
|
|
@@ -5374,7 +5374,7 @@ export const runProjectDatabaseSchedule = <ThrowOnError extends boolean = true>(
|
|
|
5374
5374
|
/**
|
|
5375
5375
|
* Read metered database execution usage
|
|
5376
5376
|
*
|
|
5377
|
-
* Returns schedule runs and webhook attempts per time window. Only completed windows are final; the current window may still change. Windows are UTC and at most 31 days long.
|
|
5377
|
+
* Returns schedule runs and webhook attempts per time window. Only completed windows are final; the current window may still change. Windows are UTC and at most 31 days long. The counts are counters only; executions have no price of their own, and the awake compute time of the database is what is billed.
|
|
5378
5378
|
*/
|
|
5379
5379
|
export const getProjectDatabaseExecutionUsage = <ThrowOnError extends boolean = true>(
|
|
5380
5380
|
parameters: {
|
|
@@ -329,11 +329,6 @@ export type OrganizationCredits = {
|
|
|
329
329
|
* Seven days after the credit was used up. Existing services and domains are retained during this grace; no automatic data deletion. Explicit project stop budgets are separate.
|
|
330
330
|
*/
|
|
331
331
|
grace_expires_at: string | null;
|
|
332
|
-
active_meters: Array<string>;
|
|
333
|
-
/**
|
|
334
|
-
* Published integer prices, newest first. A published rate is not proof of enabled billing; only active_meters names currently billed sources. Builds retain their accepted quote. Provider cost is a list-price basis before platform allowances, not an invoice.
|
|
335
|
-
*/
|
|
336
|
-
rate_cards: Array<PublishedCreditRateCard>;
|
|
337
332
|
};
|
|
338
333
|
|
|
339
334
|
/**
|
|
@@ -379,23 +374,6 @@ export type OrganizationCreditUsage = {
|
|
|
379
374
|
}>;
|
|
380
375
|
};
|
|
381
376
|
|
|
382
|
-
export type PublishedCreditRateCard = {
|
|
383
|
-
id: string;
|
|
384
|
-
currency: "USD";
|
|
385
|
-
published_at: string;
|
|
386
|
-
effective_from: string;
|
|
387
|
-
rates: Array<{
|
|
388
|
-
meter: string;
|
|
389
|
-
unit: string;
|
|
390
|
-
units_per_charge: string;
|
|
391
|
-
/**
|
|
392
|
-
* Provider list-cost basis for units_per_charge, in USD micro-units (1000000 equals 1 USD), before shared allowances and discounts. Null for the PGCF RAM tariff means node infrastructure costs are tracked separately and are not allocated to this customer rate; null never means zero cost.
|
|
393
|
-
*/
|
|
394
|
-
provider_cost_micros: string | null;
|
|
395
|
-
credit_micros: CreditMicros;
|
|
396
|
-
}>;
|
|
397
|
-
};
|
|
398
|
-
|
|
399
377
|
export type SetProjectCreditBudgetRequest = {
|
|
400
378
|
/**
|
|
401
379
|
* The monthly budget, at most 9007199254740991 microcredits (about 9 billion credits); null removes it.
|
|
@@ -8812,6 +8790,10 @@ export type SetProjectDatabaseScheduleErrors = {
|
|
|
8812
8790
|
* The request failed.
|
|
8813
8791
|
*/
|
|
8814
8792
|
401: ProblemDetails;
|
|
8793
|
+
/**
|
|
8794
|
+
* The request failed.
|
|
8795
|
+
*/
|
|
8796
|
+
402: ProblemDetails;
|
|
8815
8797
|
/**
|
|
8816
8798
|
* The resource does not exist or is not visible to the authenticated principal.
|
|
8817
8799
|
*/
|
|
@@ -8946,6 +8928,10 @@ export type RunProjectDatabaseScheduleErrors = {
|
|
|
8946
8928
|
* The request failed.
|
|
8947
8929
|
*/
|
|
8948
8930
|
401: ProblemDetails;
|
|
8931
|
+
/**
|
|
8932
|
+
* The request failed.
|
|
8933
|
+
*/
|
|
8934
|
+
402: ProblemDetails;
|
|
8949
8935
|
/**
|
|
8950
8936
|
* The resource does not exist or is not visible to the authenticated principal.
|
|
8951
8937
|
*/
|