@amerged/ohmyhost-cli 0.1.39 → 0.1.41
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-R2BC42EW.js → chunk-SB6RMO3M.js} +42 -53
- package/dist/index.js +1 -1
- package/dist/licenses/pgcf-bridge-NOTICE +1 -1
- package/package.json +1 -1
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +2 -2
- package/src/apps/product-cli/src/command.ts +2 -16
- package/src/apps/product-cli/src/product-api.ts +3 -13
- package/src/apps/product-cli/src/runtime-contract.ts +1 -10
- package/src/packages/contracts/src/credit-pricing.ts +78 -50
- package/src/packages/contracts/src/feedback.ts +0 -5
- package/src/packages/contracts/src/framework-admission.ts +1 -1
- package/src/packages/contracts/src/framework-source-rules.ts +1 -1
- package/src/packages/postgres-bridge/NOTICE +1 -1
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +6 -10
- package/src/packages/sdk-ts/src/generated/types.gen.ts +52 -24
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-SB6RMO3M.js";
|
|
6
6
|
import "./chunk-7D2RFLWM.js";
|
|
7
7
|
|
|
8
8
|
// apps/product-cli/dist/bin.js
|
|
@@ -38593,7 +38593,7 @@ var FRAMEWORK_CONVERSION_DETAILS = Object.freeze({
|
|
|
38593
38593
|
},
|
|
38594
38594
|
better_auth_version_required: {
|
|
38595
38595
|
paths: ["manifest"],
|
|
38596
|
-
template: '"{{path}}" must declare better-auth at exactly 1.7.
|
|
38596
|
+
template: '"{{path}}" must declare better-auth at exactly 1.7.7 in dependencies because ohmyhost.yaml sets auth.provider: better-auth. Pin that version or set auth.provider: none, commit and push the change, then plan the new commit.'
|
|
38597
38597
|
},
|
|
38598
38598
|
package_manifest_invalid: {
|
|
38599
38599
|
paths: ["manifest"],
|
|
@@ -40064,31 +40064,41 @@ function assertOrganizationCreditUsage(value) {
|
|
|
40064
40064
|
};
|
|
40065
40065
|
const identifier2 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
|
|
40066
40066
|
const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
|
|
40067
|
-
const
|
|
40068
|
-
|
|
40067
|
+
const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
|
|
40068
|
+
const report = record6(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)
|
|
40069
40070
|
throw new TypeError("Invalid usage report");
|
|
40070
40071
|
let previous = "";
|
|
40071
|
-
for (const input of report["
|
|
40072
|
-
const project = record6(input, "project_id,
|
|
40073
|
-
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["
|
|
40072
|
+
for (const input of report["projects"]) {
|
|
40073
|
+
const project = record6(input, "project_id,used_micros");
|
|
40074
|
+
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
|
|
40074
40075
|
throw new TypeError("Invalid usage project");
|
|
40075
40076
|
previous = String(project["project_id"]);
|
|
40076
|
-
|
|
40077
|
-
|
|
40078
|
-
|
|
40079
|
-
|
|
40080
|
-
|
|
40081
|
-
|
|
40082
|
-
|
|
40083
|
-
|
|
40084
|
-
|
|
40077
|
+
}
|
|
40078
|
+
let previousDay = "";
|
|
40079
|
+
for (const input of report["days"]) {
|
|
40080
|
+
const day = record6(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 = record6(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 = record6(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"]))
|
|
40085
40098
|
throw new TypeError("Invalid usage amount");
|
|
40086
|
-
|
|
40087
|
-
throw new TypeError("Inconsistent usage charge");
|
|
40099
|
+
}
|
|
40088
40100
|
}
|
|
40089
40101
|
}
|
|
40090
|
-
if (report["next_cursor"] !== null && report["next_cursor"] !== previous)
|
|
40091
|
-
throw new TypeError("Invalid usage cursor");
|
|
40092
40102
|
}
|
|
40093
40103
|
function assertPublishedCreditRateCards(value) {
|
|
40094
40104
|
if (!Array.isArray(value) || value.length > 4)
|
|
@@ -40139,7 +40149,9 @@ function assertOrganizationAccount(value) {
|
|
|
40139
40149
|
for (const field of ["available_micros", "monthly_micros", "one_time_micros", "reserved_micros"])
|
|
40140
40150
|
if (typeof v[field] !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(v[field]))
|
|
40141
40151
|
throw new TypeError("Invalid account credits");
|
|
40142
|
-
|
|
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))
|
|
40143
40155
|
throw new TypeError("Account credit buckets do not balance");
|
|
40144
40156
|
for (const field of ["as_of", "paid_until", "next_expiry"]) {
|
|
40145
40157
|
if (field !== "as_of" && v[field] === null)
|
|
@@ -40869,9 +40881,6 @@ function parseOrganizationCredits(value) {
|
|
|
40869
40881
|
"as_of",
|
|
40870
40882
|
"available_micros",
|
|
40871
40883
|
"reserved_micros",
|
|
40872
|
-
"spent_micros",
|
|
40873
|
-
"expired_micros",
|
|
40874
|
-
"platform_overrun_micros",
|
|
40875
40884
|
"grace_started_at",
|
|
40876
40885
|
"grace_expires_at",
|
|
40877
40886
|
"active_meters",
|
|
@@ -40887,13 +40896,7 @@ function parseOrganizationCredits(value) {
|
|
|
40887
40896
|
throw new ResponseContractError();
|
|
40888
40897
|
if (!isUlid(input["organization_id"]) || input["unit"] !== "microcredits" || !isIsoInstant(input["as_of"]) || !Array.isArray(input["active_meters"]) || input["active_meters"].some((m) => typeof m !== "string" || !/^[a-z0-9_.-]{1,128}$/u.test(m)))
|
|
40889
40898
|
throw new ResponseContractError();
|
|
40890
|
-
for (const field of [
|
|
40891
|
-
"available_micros",
|
|
40892
|
-
"reserved_micros",
|
|
40893
|
-
"spent_micros",
|
|
40894
|
-
"expired_micros",
|
|
40895
|
-
"platform_overrun_micros"
|
|
40896
|
-
]) {
|
|
40899
|
+
for (const field of ["available_micros", "reserved_micros"]) {
|
|
40897
40900
|
const amount = input[field];
|
|
40898
40901
|
if (typeof amount !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(amount) || BigInt(amount) > 9223372036854775807n)
|
|
40899
40902
|
throw new ResponseContractError();
|
|
@@ -43160,16 +43163,8 @@ var parseProductCliCommand = (argv) => {
|
|
|
43160
43163
|
values.shift();
|
|
43161
43164
|
if (yes || wait || follow || stdin)
|
|
43162
43165
|
throw new InvalidCommandError();
|
|
43163
|
-
const options =
|
|
43164
|
-
|
|
43165
|
-
throw new InvalidCommandError();
|
|
43166
|
-
return {
|
|
43167
|
-
kind: "credits-usage",
|
|
43168
|
-
organizationId: options["--organization"],
|
|
43169
|
-
month: options["--month"],
|
|
43170
|
-
...options["--cursor"] ? { cursor: options["--cursor"] } : {},
|
|
43171
|
-
credentialStore
|
|
43172
|
-
};
|
|
43166
|
+
const options = parseOptions(values, ["--organization"]);
|
|
43167
|
+
return { kind: "credits-usage", organizationId: options["--organization"], credentialStore };
|
|
43173
43168
|
}
|
|
43174
43169
|
if (first === "credits" && values[0] === "account") {
|
|
43175
43170
|
values.shift();
|
|
@@ -44714,7 +44709,7 @@ function exact3(v, keys) {
|
|
|
44714
44709
|
// apps/product-cli/package.json
|
|
44715
44710
|
var package_default = {
|
|
44716
44711
|
name: "@ohmyhost/product-cli",
|
|
44717
|
-
version: "0.1.
|
|
44712
|
+
version: "0.1.41",
|
|
44718
44713
|
private: true,
|
|
44719
44714
|
ohmyhost: {
|
|
44720
44715
|
deployment: "production",
|
|
@@ -45023,7 +45018,7 @@ var HELP_USAGE = Object.freeze({
|
|
|
45023
45018
|
"billing checkout": "ohmyhost billing checkout --organization ULID --offer topup|paid [--packs 1] --idempotency-key KEY --json (returns a human payment URL; never auto-pays)",
|
|
45024
45019
|
"billing status": "ohmyhost billing status --organization ULID --checkout ULID --json",
|
|
45025
45020
|
"billing portal": "ohmyhost billing portal --organization ULID --json (short-lived human URL; request fresh after expiry)",
|
|
45026
|
-
"credits usage": "ohmyhost credits usage --organization ULID --
|
|
45021
|
+
"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)",
|
|
45027
45022
|
"budget get": "ohmyhost budget get --project ULID --json",
|
|
45028
45023
|
"budget set": "ohmyhost budget set --project ULID --credits NUMBER|none [--mode continue|stop] --idempotency-key KEY --json",
|
|
45029
45024
|
"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)",
|
|
@@ -45312,7 +45307,7 @@ var ProductCli = class {
|
|
|
45312
45307
|
}
|
|
45313
45308
|
if (command.kind === "credits-usage") {
|
|
45314
45309
|
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
45315
|
-
const usage = await api.getOrganizationCreditUsage(command);
|
|
45310
|
+
const usage = await api.getOrganizationCreditUsage(command.organizationId);
|
|
45316
45311
|
try {
|
|
45317
45312
|
assertOrganizationCreditUsage(usage);
|
|
45318
45313
|
} catch {
|
|
@@ -48563,9 +48558,7 @@ var getOrganizationCreditUsage = (parameters, options) => {
|
|
|
48563
48558
|
{
|
|
48564
48559
|
args: [
|
|
48565
48560
|
{ in: "headers", key: "X-Request-Id" },
|
|
48566
|
-
{ in: "path", key: "organization_id" }
|
|
48567
|
-
{ in: "query", key: "month" },
|
|
48568
|
-
{ in: "query", key: "cursor" }
|
|
48561
|
+
{ in: "path", key: "organization_id" }
|
|
48569
48562
|
]
|
|
48570
48563
|
}
|
|
48571
48564
|
]);
|
|
@@ -50897,12 +50890,8 @@ var GeneratedSdkProductApi = class {
|
|
|
50897
50890
|
createBillingPortal(organizationId) {
|
|
50898
50891
|
return createBillingPortal({ organization_id: organizationId, body: {} }, { client: this.#client });
|
|
50899
50892
|
}
|
|
50900
|
-
getOrganizationCreditUsage(
|
|
50901
|
-
return getOrganizationCreditUsage({
|
|
50902
|
-
organization_id: input.organizationId,
|
|
50903
|
-
month: input.month,
|
|
50904
|
-
...input.cursor ? { cursor: input.cursor } : {}
|
|
50905
|
-
}, { client: this.#client });
|
|
50893
|
+
getOrganizationCreditUsage(organizationId) {
|
|
50894
|
+
return getOrganizationCreditUsage({ organization_id: organizationId }, { client: this.#client });
|
|
50906
50895
|
}
|
|
50907
50896
|
getProjectCreditBudget(projectId) {
|
|
50908
50897
|
return getProjectCreditBudget({ project_id: projectId }, { client: this.#client });
|
|
@@ -51956,7 +51945,7 @@ function classifyFrameworkFamily(dependencies) {
|
|
|
51956
51945
|
}
|
|
51957
51946
|
|
|
51958
51947
|
// packages/contracts/dist/framework-source-rules.js
|
|
51959
|
-
var MANAGED_BETTER_AUTH_VERSION = "1.7.
|
|
51948
|
+
var MANAGED_BETTER_AUTH_VERSION = "1.7.7";
|
|
51960
51949
|
var MAXIMUM_FRAMEWORK_CONFIG_BYTES = 256 * 1024;
|
|
51961
51950
|
var WORKER_MODULE_PATH = "src/ohmyhost/worker.ts";
|
|
51962
51951
|
var VITE_COMPANION_ENTRY_PATH = "src/ohmyhost/companion.ts";
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
PostgreSQL WebSocket bridge and authentication prelude handling adapted from cloudflare-postgres packages/cli, commit e05d9102c840e283602272ed0e16a95be3e3b8ea. Upstream license: Apache-2.0.
|
|
1
|
+
PostgreSQL WebSocket bridge and authentication prelude handling adapted from cloudflare-postgres (https://github.com/amerged-org/cloudflare-postgres) packages/cli, commit e05d9102c840e283602272ed0e16a95be3e3b8ea. Upstream license: Apache-2.0.
|
package/package.json
CHANGED
|
@@ -351,7 +351,7 @@ const HELP_USAGE = Object.freeze({
|
|
|
351
351
|
"billing portal":
|
|
352
352
|
"ohmyhost billing portal --organization ULID --json (short-lived human URL; request fresh after expiry)",
|
|
353
353
|
"credits usage":
|
|
354
|
-
"ohmyhost credits usage --organization ULID --
|
|
354
|
+
"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)",
|
|
355
355
|
"budget get": "ohmyhost budget get --project ULID --json",
|
|
356
356
|
"budget set":
|
|
357
357
|
"ohmyhost budget set --project ULID --credits NUMBER|none [--mode continue|stop] --idempotency-key KEY --json",
|
|
@@ -844,7 +844,7 @@ export class ProductCli {
|
|
|
844
844
|
}
|
|
845
845
|
if (command.kind === "credits-usage") {
|
|
846
846
|
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
847
|
-
const usage = await api.getOrganizationCreditUsage(command);
|
|
847
|
+
const usage = await api.getOrganizationCreditUsage(command.organizationId);
|
|
848
848
|
try {
|
|
849
849
|
assertOrganizationCreditUsage(usage);
|
|
850
850
|
} catch {
|
|
@@ -199,8 +199,6 @@ export type ProductCliCommand =
|
|
|
199
199
|
| {
|
|
200
200
|
readonly kind: "credits-usage";
|
|
201
201
|
readonly organizationId: string;
|
|
202
|
-
readonly month: string;
|
|
203
|
-
readonly cursor?: string;
|
|
204
202
|
readonly credentialStore: "native";
|
|
205
203
|
}
|
|
206
204
|
| {
|
|
@@ -1407,20 +1405,8 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1407
1405
|
if (first === "credits" && values[0] === "usage") {
|
|
1408
1406
|
values.shift();
|
|
1409
1407
|
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1410
|
-
const options =
|
|
1411
|
-
|
|
1412
|
-
!options["--organization"] ||
|
|
1413
|
-
!options["--month"] ||
|
|
1414
|
-
!/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(options["--month"])
|
|
1415
|
-
)
|
|
1416
|
-
throw new InvalidCommandError();
|
|
1417
|
-
return {
|
|
1418
|
-
kind: "credits-usage",
|
|
1419
|
-
organizationId: options["--organization"],
|
|
1420
|
-
month: options["--month"],
|
|
1421
|
-
...(options["--cursor"] ? { cursor: options["--cursor"] } : {}),
|
|
1422
|
-
credentialStore,
|
|
1423
|
-
};
|
|
1408
|
+
const options = parseOptions(values, ["--organization"]);
|
|
1409
|
+
return { kind: "credits-usage", organizationId: options["--organization"], credentialStore };
|
|
1424
1410
|
}
|
|
1425
1411
|
if (first === "credits" && values[0] === "account") {
|
|
1426
1412
|
values.shift();
|
|
@@ -230,11 +230,7 @@ export interface ProductApi {
|
|
|
230
230
|
organizationId: string,
|
|
231
231
|
): Promise<import("@ohmyhost/sdk-ts").OrganizationReferral>;
|
|
232
232
|
getOrganizationCredits(organizationId: string): Promise<OrganizationCredits>;
|
|
233
|
-
getOrganizationCreditUsage(
|
|
234
|
-
organizationId: string;
|
|
235
|
-
month: string;
|
|
236
|
-
cursor?: string;
|
|
237
|
-
}): Promise<OrganizationCreditUsage>;
|
|
233
|
+
getOrganizationCreditUsage(organizationId: string): Promise<OrganizationCreditUsage>;
|
|
238
234
|
getProjectCreditBudget(projectId: string): Promise<ProjectCreditBudget>;
|
|
239
235
|
setProjectCreditBudget(input: {
|
|
240
236
|
projectId: string;
|
|
@@ -614,15 +610,9 @@ export class GeneratedSdkProductApi implements ProductApi {
|
|
|
614
610
|
{ client: this.#client },
|
|
615
611
|
);
|
|
616
612
|
}
|
|
617
|
-
public getOrganizationCreditUsage(
|
|
618
|
-
input: Parameters<ProductApi["getOrganizationCreditUsage"]>[0],
|
|
619
|
-
) {
|
|
613
|
+
public getOrganizationCreditUsage(organizationId: string) {
|
|
620
614
|
return getOrganizationCreditUsage(
|
|
621
|
-
{
|
|
622
|
-
organization_id: input.organizationId,
|
|
623
|
-
month: input.month,
|
|
624
|
-
...(input.cursor ? { cursor: input.cursor } : {}),
|
|
625
|
-
},
|
|
615
|
+
{ organization_id: organizationId },
|
|
626
616
|
{ client: this.#client },
|
|
627
617
|
);
|
|
628
618
|
}
|
|
@@ -552,9 +552,6 @@ export function parseOrganizationCredits(value: unknown): OrganizationCredits {
|
|
|
552
552
|
"as_of",
|
|
553
553
|
"available_micros",
|
|
554
554
|
"reserved_micros",
|
|
555
|
-
"spent_micros",
|
|
556
|
-
"expired_micros",
|
|
557
|
-
"platform_overrun_micros",
|
|
558
555
|
"grace_started_at",
|
|
559
556
|
"grace_expires_at",
|
|
560
557
|
"active_meters",
|
|
@@ -586,13 +583,7 @@ export function parseOrganizationCredits(value: unknown): OrganizationCredits {
|
|
|
586
583
|
)
|
|
587
584
|
)
|
|
588
585
|
throw new ResponseContractError();
|
|
589
|
-
for (const field of [
|
|
590
|
-
"available_micros",
|
|
591
|
-
"reserved_micros",
|
|
592
|
-
"spent_micros",
|
|
593
|
-
"expired_micros",
|
|
594
|
-
"platform_overrun_micros",
|
|
595
|
-
]) {
|
|
586
|
+
for (const field of ["available_micros", "reserved_micros"]) {
|
|
596
587
|
const amount = input[field];
|
|
597
588
|
if (
|
|
598
589
|
typeof amount !== "string" ||
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
export interface OrganizationCreditUsage {
|
|
2
2
|
organization_id: string;
|
|
3
|
-
month: string;
|
|
4
3
|
as_of: string;
|
|
5
4
|
unit: "microcredits";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
/** The UTC month (`YYYY-MM`) that `projects[].used_micros` counts. */
|
|
6
|
+
period: string;
|
|
7
|
+
/** The first instant of the daily lines: the start of the oldest UTC day that is reported. */
|
|
8
|
+
from: string;
|
|
9
|
+
/** What each project has used so far in `period`. */
|
|
10
|
+
projects: { project_id: string; used_micros: string }[];
|
|
11
|
+
/** The credit-log lines of the last up to 14 UTC days, grouped by day, project and meter, oldest day first. */
|
|
12
|
+
days: {
|
|
13
|
+
day: string;
|
|
14
|
+
projects: {
|
|
15
|
+
project_id: string;
|
|
16
|
+
meters: {
|
|
17
|
+
environment_id: string | null;
|
|
18
|
+
meter: string;
|
|
19
|
+
unit: string;
|
|
20
|
+
rate_card_id: string;
|
|
21
|
+
quantity: string;
|
|
22
|
+
charged_micros: string;
|
|
23
|
+
}[];
|
|
18
24
|
}[];
|
|
19
25
|
}[];
|
|
20
|
-
next_cursor: string | null;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
/** A bounded read model, not a new source of accounting or billing authorization. */
|
|
@@ -38,53 +43,77 @@ export function assertOrganizationCreditUsage(
|
|
|
38
43
|
typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
|
|
39
44
|
const amount = (input: unknown) =>
|
|
40
45
|
typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
|
|
41
|
-
const
|
|
46
|
+
const instant = (input: unknown) =>
|
|
47
|
+
typeof input === "string" &&
|
|
48
|
+
Number.isFinite(Date.parse(input)) &&
|
|
49
|
+
new Date(input).toISOString() === input;
|
|
50
|
+
const report = record(value, "organization_id,as_of,unit,period,from,projects,days");
|
|
42
51
|
if (
|
|
43
52
|
!identifier(report["organization_id"]) ||
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
typeof report["as_of"] !== "string" ||
|
|
47
|
-
!Number.isFinite(Date.parse(report["as_of"])) ||
|
|
48
|
-
new Date(report["as_of"]).toISOString() !== report["as_of"] ||
|
|
53
|
+
!instant(report["as_of"]) ||
|
|
54
|
+
!instant(report["from"]) ||
|
|
49
55
|
report["unit"] !== "microcredits" ||
|
|
50
|
-
|
|
51
|
-
report["
|
|
52
|
-
|
|
56
|
+
typeof report["period"] !== "string" ||
|
|
57
|
+
!/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(report["period"]) ||
|
|
58
|
+
!Array.isArray(report["projects"]) ||
|
|
59
|
+
report["projects"].length > 1000 ||
|
|
60
|
+
!Array.isArray(report["days"]) ||
|
|
61
|
+
report["days"].length > 15
|
|
53
62
|
)
|
|
54
63
|
throw new TypeError("Invalid usage report");
|
|
55
64
|
let previous = "";
|
|
56
|
-
for (const input of report["
|
|
57
|
-
const project = record(input, "project_id,
|
|
65
|
+
for (const input of report["projects"]) {
|
|
66
|
+
const project = record(input, "project_id,used_micros");
|
|
58
67
|
if (
|
|
59
68
|
!identifier(project["project_id"]) ||
|
|
60
69
|
String(project["project_id"]) <= previous ||
|
|
61
|
-
!amount(project["
|
|
62
|
-
!Array.isArray(project["meters"]) ||
|
|
63
|
-
project["meters"].length > 1000
|
|
70
|
+
!amount(project["used_micros"])
|
|
64
71
|
)
|
|
65
72
|
throw new TypeError("Invalid usage project");
|
|
66
73
|
previous = String(project["project_id"]);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
}
|
|
75
|
+
let previousDay = "";
|
|
76
|
+
for (const input of report["days"]) {
|
|
77
|
+
const day = record(input, "day,projects");
|
|
78
|
+
if (
|
|
79
|
+
typeof day["day"] !== "string" ||
|
|
80
|
+
!/^20[0-9]{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/u.test(day["day"]) ||
|
|
81
|
+
day["day"] <= previousDay ||
|
|
82
|
+
!Array.isArray(day["projects"]) ||
|
|
83
|
+
day["projects"].length > 1000
|
|
84
|
+
)
|
|
85
|
+
throw new TypeError("Invalid usage day");
|
|
86
|
+
previousDay = day["day"];
|
|
87
|
+
previous = "";
|
|
88
|
+
for (const projectInput of day["projects"]) {
|
|
89
|
+
const project = record(projectInput, "project_id,meters");
|
|
79
90
|
if (
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
!identifier(project["project_id"]) ||
|
|
92
|
+
String(project["project_id"]) <= previous ||
|
|
93
|
+
!Array.isArray(project["meters"]) ||
|
|
94
|
+
project["meters"].length > 1000
|
|
82
95
|
)
|
|
83
|
-
throw new TypeError("
|
|
96
|
+
throw new TypeError("Invalid usage project");
|
|
97
|
+
previous = String(project["project_id"]);
|
|
98
|
+
for (const meterInput of project["meters"]) {
|
|
99
|
+
const meter = record(
|
|
100
|
+
meterInput,
|
|
101
|
+
"environment_id,meter,unit,rate_card_id,quantity,charged_micros",
|
|
102
|
+
);
|
|
103
|
+
if (meter["environment_id"] !== null && !identifier(meter["environment_id"]))
|
|
104
|
+
throw new TypeError("Invalid usage environment");
|
|
105
|
+
for (const key of ["meter", "unit", "rate_card_id"])
|
|
106
|
+
if (typeof meter[key] !== "string" || !/^[A-Za-z0-9_.:/-]{1,128}$/u.test(meter[key]))
|
|
107
|
+
throw new TypeError("Invalid usage meter");
|
|
108
|
+
if (
|
|
109
|
+
typeof meter["quantity"] !== "string" ||
|
|
110
|
+
!/^(0|[1-9][0-9]{0,29})(\.[0-9]{1,12})?$/u.test(meter["quantity"]) ||
|
|
111
|
+
!amount(meter["charged_micros"])
|
|
112
|
+
)
|
|
113
|
+
throw new TypeError("Invalid usage amount");
|
|
114
|
+
}
|
|
84
115
|
}
|
|
85
116
|
}
|
|
86
|
-
if (report["next_cursor"] !== null && report["next_cursor"] !== previous)
|
|
87
|
-
throw new TypeError("Invalid usage cursor");
|
|
88
117
|
}
|
|
89
118
|
|
|
90
119
|
export interface PublishedCreditRateCard {
|
|
@@ -177,7 +206,7 @@ export function assertPublishedCreditRateCards(
|
|
|
177
206
|
}
|
|
178
207
|
}
|
|
179
208
|
|
|
180
|
-
/** Effective feature access and credit
|
|
209
|
+
/** Effective feature access and the credit account: the monthly and one-time credit and what the open reservations hold. */
|
|
181
210
|
export function assertOrganizationAccount(value: unknown): void {
|
|
182
211
|
if (
|
|
183
212
|
!value ||
|
|
@@ -203,10 +232,9 @@ export function assertOrganizationAccount(value: unknown): void {
|
|
|
203
232
|
for (const field of ["available_micros", "monthly_micros", "one_time_micros", "reserved_micros"])
|
|
204
233
|
if (typeof v[field] !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(v[field] as string))
|
|
205
234
|
throw new TypeError("Invalid account credits");
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
)
|
|
235
|
+
const held = BigInt(String(v["reserved_micros"]));
|
|
236
|
+
const balance = BigInt(String(v["monthly_micros"])) + BigInt(String(v["one_time_micros"]));
|
|
237
|
+
if (BigInt(String(v["available_micros"])) !== (balance > held ? balance - held : 0n))
|
|
210
238
|
throw new TypeError("Account credit buckets do not balance");
|
|
211
239
|
for (const field of ["as_of", "paid_until", "next_expiry"]) {
|
|
212
240
|
if (field !== "as_of" && v[field] === null) continue;
|
|
@@ -214,11 +214,6 @@ export function parseFeedbackStatus(value: unknown): FeedbackStatus {
|
|
|
214
214
|
return v as unknown as FeedbackStatus;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
/** Bounded, trimmed text without control characters other than tab and line breaks. */
|
|
218
|
-
export function validFeedbackText(value: unknown, max: number): value is string {
|
|
219
|
-
return validText(value, max, true);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
217
|
function validUpdate(value: unknown): boolean {
|
|
223
218
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
224
219
|
const v = value as Record<string, unknown>;
|
|
@@ -450,7 +450,7 @@ const FRAMEWORK_CONVERSION_DETAILS = Object.freeze({
|
|
|
450
450
|
better_auth_version_required: {
|
|
451
451
|
paths: ["manifest"],
|
|
452
452
|
template:
|
|
453
|
-
'"{{path}}" must declare better-auth at exactly 1.7.
|
|
453
|
+
'"{{path}}" must declare better-auth at exactly 1.7.7 in dependencies because ohmyhost.yaml sets auth.provider: better-auth. Pin that version or set auth.provider: none, commit and push the change, then plan the new commit.',
|
|
454
454
|
},
|
|
455
455
|
package_manifest_invalid: {
|
|
456
456
|
paths: ["manifest"],
|
|
@@ -32,7 +32,7 @@ import { classifyFrameworkFamily } from "./framework-family.js";
|
|
|
32
32
|
import { parseOhmyhostConfigYaml, type OhmyhostConfig } from "./index.js";
|
|
33
33
|
|
|
34
34
|
/** The only better-auth release the managed auth bridge installs. */
|
|
35
|
-
export const MANAGED_BETTER_AUTH_VERSION = "1.7.
|
|
35
|
+
export const MANAGED_BETTER_AUTH_VERSION = "1.7.7" as const;
|
|
36
36
|
/** The largest framework config the rules inspect, in UTF-8 bytes. */
|
|
37
37
|
export const MAXIMUM_FRAMEWORK_CONFIG_BYTES = 256 * 1024;
|
|
38
38
|
/** The customer Worker module of the functions runtime and of Next.js or TanStack Start crons. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
PostgreSQL WebSocket bridge and authentication prelude handling adapted from cloudflare-postgres packages/cli, commit e05d9102c840e283602272ed0e16a95be3e3b8ea. Upstream license: Apache-2.0.
|
|
1
|
+
PostgreSQL WebSocket bridge and authentication prelude handling adapted from cloudflare-postgres (https://github.com/amerged-org/cloudflare-postgres) packages/cli, commit e05d9102c840e283602272ed0e16a95be3e3b8ea. Upstream license: Apache-2.0.
|
|
@@ -1930,7 +1930,7 @@ export const createOrganization = <ThrowOnError extends boolean = true>(
|
|
|
1930
1930
|
/**
|
|
1931
1931
|
* Create or resume an owner's hosted Stripe Checkout
|
|
1932
1932
|
*
|
|
1933
|
-
* Returns a human payment URL, never charges a saved card. 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 credits. Top-ups require active Paid access and
|
|
1933
|
+
* Returns a human payment URL, never charges a saved card. 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 credits. Top-ups require active Paid access and never expire, also after the workspace returns to Free. Monthly Paid credits expire at billing-period end without rollover. Retry the same offer, packs and Idempotency-Key after uncertainty. Browser return is not payment proof; read this checkout and the organization balance. A conflicting or existing subscription returns billing_purchase_conflict (409); read the original checkout or request an owner billing portal URL instead of another purchase. Works at zero credits.
|
|
1934
1934
|
*/
|
|
1935
1935
|
export const createBillingCheckout = <ThrowOnError extends boolean = true>(
|
|
1936
1936
|
parameters: {
|
|
@@ -1983,7 +1983,7 @@ export const createBillingCheckout = <ThrowOnError extends boolean = true>(
|
|
|
1983
1983
|
/**
|
|
1984
1984
|
* Observe and reconcile an owner's original checkout
|
|
1985
1985
|
*
|
|
1986
|
-
* Reads Stripe and reconciles confirmed credits/refunds idempotently. payment_confirmed describes the original Checkout, not spendable credit or current Paid entitlement. Read organization credits for available funding and the organization account's effective plan for Paid coverage; paid_until is the paid Stripe period end
|
|
1986
|
+
* Reads Stripe and reconciles confirmed credits/refunds idempotently. payment_confirmed describes the original Checkout, not spendable credit or current Paid entitlement. Read organization credits for available funding and the organization account'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. No new purchase intent or payment is created; an uncertain original Checkout can resume using its stored identity.
|
|
1987
1987
|
*/
|
|
1988
1988
|
export const getBillingCheckout = <ThrowOnError extends boolean = true>(
|
|
1989
1989
|
parameters: {
|
|
@@ -2105,7 +2105,7 @@ export const getBillingRecharge = <ThrowOnError extends boolean = true>(
|
|
|
2105
2105
|
/**
|
|
2106
2106
|
* Enable or disable explicitly authorized auto-recharge
|
|
2107
2107
|
*
|
|
2108
|
-
* Owner-only. An agent must obtain explicit approval for off-session charges and the gross monthly spending cap before enabling. Each refill costs USD 9 before tax for 1000 top-up credits when available credits fall below 100. Active Paid access is required to enable recharge and initiate a payment;
|
|
2108
|
+
* Owner-only. An agent must obtain explicit approval for off-session charges and the gross monthly spending cap before enabling. Each refill costs USD 9 before tax for 1000 top-up credits when available credits fall below 100. Active Paid access is required to enable recharge and initiate a payment; bought credits never expire, also after a downgrade to Free. A saved Stripe card is required; follow setup_url if returned. Current revision prevents stale edits; retry the original Idempotency-Key and payload after uncertainty. Disable prevents new charge initiation; already initiated payments may complete. No subscription or Paid features are created.
|
|
2109
2109
|
*/
|
|
2110
2110
|
export const configureBillingRecharge = <ThrowOnError extends boolean = true>(
|
|
2111
2111
|
parameters: {
|
|
@@ -2162,7 +2162,7 @@ export const configureBillingRecharge = <ThrowOnError extends boolean = true>(
|
|
|
2162
2162
|
/**
|
|
2163
2163
|
* Read the owner's shared organization credit pool
|
|
2164
2164
|
*
|
|
2165
|
-
* Returns
|
|
2165
|
+
* 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. active_meters names the currently billed sources; usage that is not billed yet is not included. 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.
|
|
2166
2166
|
*/
|
|
2167
2167
|
export const getOrganizationCredits = <ThrowOnError extends boolean = true>(
|
|
2168
2168
|
parameters: {
|
|
@@ -2202,16 +2202,14 @@ export const getOrganizationCredits = <ThrowOnError extends boolean = true>(
|
|
|
2202
2202
|
};
|
|
2203
2203
|
|
|
2204
2204
|
/**
|
|
2205
|
-
* Read
|
|
2205
|
+
* Read recent measured usage by day, project and meter
|
|
2206
2206
|
*
|
|
2207
|
-
* Owner-only
|
|
2207
|
+
* Owner-only. days holds the credit-log charges of the last up to 14 UTC days (today included, oldest first), grouped by day, project and meter. projects holds what each project has used so far in the current UTC month. A null environment_id means a project-shared cost, never a guessed Dev allocation. Only billed usage is included; charges may arrive later, so this is not a complete provider invoice or a zero-usage guarantee. No credit is granted or charged by this read; it remains usable at zero credits.
|
|
2208
2208
|
*/
|
|
2209
2209
|
export const getOrganizationCreditUsage = <ThrowOnError extends boolean = true>(
|
|
2210
2210
|
parameters: {
|
|
2211
2211
|
"X-Request-Id"?: string;
|
|
2212
2212
|
organization_id: Ulid;
|
|
2213
|
-
month: string;
|
|
2214
|
-
cursor?: Ulid;
|
|
2215
2213
|
},
|
|
2216
2214
|
options?: Options<never, ThrowOnError>,
|
|
2217
2215
|
): RequestResult<
|
|
@@ -2227,8 +2225,6 @@ export const getOrganizationCreditUsage = <ThrowOnError extends boolean = true>(
|
|
|
2227
2225
|
args: [
|
|
2228
2226
|
{ in: "headers", key: "X-Request-Id" },
|
|
2229
2227
|
{ in: "path", key: "organization_id" },
|
|
2230
|
-
{ in: "query", key: "month" },
|
|
2231
|
-
{ in: "query", key: "cursor" },
|
|
2232
2228
|
],
|
|
2233
2229
|
},
|
|
2234
2230
|
],
|
|
@@ -321,15 +321,12 @@ export type OrganizationCredits = {
|
|
|
321
321
|
as_of: string;
|
|
322
322
|
available_micros: CreditMicros;
|
|
323
323
|
reserved_micros: CreditMicros;
|
|
324
|
-
spent_micros: CreditMicros;
|
|
325
|
-
expired_micros: CreditMicros;
|
|
326
|
-
platform_overrun_micros: CreditMicros;
|
|
327
324
|
/**
|
|
328
|
-
*
|
|
325
|
+
* When the credit was used up; null while funded or after the monthly credit renewed.
|
|
329
326
|
*/
|
|
330
327
|
grace_started_at: string | null;
|
|
331
328
|
/**
|
|
332
|
-
* Seven days after
|
|
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.
|
|
333
330
|
*/
|
|
334
331
|
grace_expires_at: string | null;
|
|
335
332
|
active_meters: Array<string>;
|
|
@@ -346,22 +343,38 @@ export type UsageTotal = string;
|
|
|
346
343
|
|
|
347
344
|
export type OrganizationCreditUsage = {
|
|
348
345
|
organization_id: Ulid;
|
|
349
|
-
month: string;
|
|
350
346
|
as_of: string;
|
|
351
347
|
unit: "microcredits";
|
|
352
|
-
|
|
353
|
-
|
|
348
|
+
/**
|
|
349
|
+
* The UTC month that projects[].used_micros counts.
|
|
350
|
+
*/
|
|
351
|
+
period: string;
|
|
352
|
+
/**
|
|
353
|
+
* The start of the oldest UTC day in days.
|
|
354
|
+
*/
|
|
355
|
+
from: string;
|
|
356
|
+
/**
|
|
357
|
+
* What each project has used so far in period, in ID order; projects without use are left out.
|
|
358
|
+
*/
|
|
359
|
+
projects: Array<{
|
|
354
360
|
project_id: Ulid;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
361
|
+
used_micros: UsageTotal;
|
|
362
|
+
}>;
|
|
363
|
+
/**
|
|
364
|
+
* Billed charges of the last up to 14 UTC days, oldest first.
|
|
365
|
+
*/
|
|
366
|
+
days: Array<{
|
|
367
|
+
day: string;
|
|
368
|
+
projects: Array<{
|
|
369
|
+
project_id: Ulid;
|
|
370
|
+
meters: Array<{
|
|
371
|
+
environment_id: Ulid | null;
|
|
372
|
+
meter: string;
|
|
373
|
+
unit: string;
|
|
374
|
+
rate_card_id: string;
|
|
375
|
+
quantity: string;
|
|
376
|
+
charged_micros: UsageTotal;
|
|
377
|
+
}>;
|
|
365
378
|
}>;
|
|
366
379
|
}>;
|
|
367
380
|
};
|
|
@@ -384,6 +397,9 @@ export type PublishedCreditRateCard = {
|
|
|
384
397
|
};
|
|
385
398
|
|
|
386
399
|
export type SetProjectCreditBudgetRequest = {
|
|
400
|
+
/**
|
|
401
|
+
* The monthly budget, at most 9007199254740991 microcredits (about 9 billion credits); null removes it.
|
|
402
|
+
*/
|
|
387
403
|
amount_micros: CreditMicros | null;
|
|
388
404
|
mode: "continue" | "stop";
|
|
389
405
|
};
|
|
@@ -1264,13 +1280,28 @@ export type OrganizationAccount = {
|
|
|
1264
1280
|
plan: "free" | "paid";
|
|
1265
1281
|
plan_source: "free" | "stripe" | "granted" | "manual";
|
|
1266
1282
|
/**
|
|
1267
|
-
* End of the paid Stripe billing period or the
|
|
1283
|
+
* End of the paid coverage: the Stripe billing period plus its 14-day renewal grace, or the end of the grant; null on Free. Paid features stay available until this instant.
|
|
1268
1284
|
*/
|
|
1269
1285
|
paid_until: string | null;
|
|
1286
|
+
/**
|
|
1287
|
+
* Spendable credit: monthly plus one-time credit minus the open reservations, never below zero.
|
|
1288
|
+
*/
|
|
1270
1289
|
available_micros: CreditMicros;
|
|
1290
|
+
/**
|
|
1291
|
+
* The monthly credit, which ends at next_expiry; the Free allowance is 200 credits and the Paid allowance 1000 credits per period.
|
|
1292
|
+
*/
|
|
1271
1293
|
monthly_micros: CreditMicros;
|
|
1294
|
+
/**
|
|
1295
|
+
* Top-up, bonus and referral credit. It does not expire.
|
|
1296
|
+
*/
|
|
1272
1297
|
one_time_micros: CreditMicros;
|
|
1298
|
+
/**
|
|
1299
|
+
* Credit held for open builds; it is part of the monthly and one-time credit until the build settles.
|
|
1300
|
+
*/
|
|
1273
1301
|
reserved_micros: CreditMicros;
|
|
1302
|
+
/**
|
|
1303
|
+
* When the monthly credit ends and renews; null when none is left.
|
|
1304
|
+
*/
|
|
1274
1305
|
next_expiry: string | null;
|
|
1275
1306
|
as_of: string;
|
|
1276
1307
|
};
|
|
@@ -4396,10 +4427,7 @@ export type GetOrganizationCreditUsageData = {
|
|
|
4396
4427
|
path: {
|
|
4397
4428
|
organization_id: Ulid;
|
|
4398
4429
|
};
|
|
4399
|
-
query
|
|
4400
|
-
month: string;
|
|
4401
|
-
cursor?: Ulid;
|
|
4402
|
-
};
|
|
4430
|
+
query?: never;
|
|
4403
4431
|
url: "/v1/organizations/{organization_id}/credit-usage";
|
|
4404
4432
|
};
|
|
4405
4433
|
|
|
@@ -4431,7 +4459,7 @@ export type GetOrganizationCreditUsageError =
|
|
|
4431
4459
|
|
|
4432
4460
|
export type GetOrganizationCreditUsageResponses = {
|
|
4433
4461
|
/**
|
|
4434
|
-
*
|
|
4462
|
+
* Recent billed usage of the organization.
|
|
4435
4463
|
*/
|
|
4436
4464
|
200: OrganizationCreditUsage;
|
|
4437
4465
|
};
|