@amerged/ohmyhost-cli 0.1.10 → 0.1.13
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-Z75ASLEB.js → chunk-ZWAAQEOZ.js} +163 -10
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/apps/product-cli/cli.ts +39 -0
- package/src/apps/product-cli/command.ts +44 -0
- package/src/apps/product-cli/composition.ts +5 -3
- package/src/apps/product-cli/product-api.ts +33 -0
- package/src/apps/product-cli/repository-init.ts +25 -1
- package/src/apps/product-cli/runtime-contract.ts +41 -6
- package/src/packages/contracts/credit-pricing.ts +1 -1
- package/src/packages/sdk-ts/generated/index.ts +13 -0
- package/src/packages/sdk-ts/generated/sdk.gen.ts +97 -3
- package/src/packages/sdk-ts/generated/types.gen.ts +160 -4
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-ZWAAQEOZ.js";
|
|
6
6
|
import "./chunk-4HFQ54FP.js";
|
|
7
7
|
|
|
8
8
|
// apps/product-cli/dist/bin.js
|
|
@@ -15000,6 +15000,10 @@ var recognizedCommandLabel = (argv) => {
|
|
|
15000
15000
|
return "project notes set";
|
|
15001
15001
|
if (value === "project" && values[0] === "status")
|
|
15002
15002
|
return "project status";
|
|
15003
|
+
if (value === "project" && values[0] === "handle" && values[1] === "check")
|
|
15004
|
+
return "project handle check";
|
|
15005
|
+
if (value === "project" && values[0] === "handle" && values[1] === "set")
|
|
15006
|
+
return "project handle set";
|
|
15003
15007
|
if (value === "project" && values[0] === "dev-access" && values[1] === "create")
|
|
15004
15008
|
return "project dev-access create";
|
|
15005
15009
|
if (value === "database" && values[0] === "compute" && values[1] === "set")
|
|
@@ -15442,6 +15446,31 @@ var parseProductCliCommand = (argv) => {
|
|
|
15442
15446
|
}
|
|
15443
15447
|
if (first === "project") {
|
|
15444
15448
|
const subcommand = values.shift();
|
|
15449
|
+
if (subcommand === "handle" && values[0] === "set") {
|
|
15450
|
+
values.shift();
|
|
15451
|
+
if (yes || wait || follow || stdin)
|
|
15452
|
+
throw new InvalidCommandError();
|
|
15453
|
+
const options2 = parseOptions(values, [
|
|
15454
|
+
"--project",
|
|
15455
|
+
"--handle",
|
|
15456
|
+
"--if-match",
|
|
15457
|
+
"--idempotency-key"
|
|
15458
|
+
]);
|
|
15459
|
+
return {
|
|
15460
|
+
kind: "project-handle-set",
|
|
15461
|
+
projectId: options2["--project"],
|
|
15462
|
+
handle: options2["--handle"],
|
|
15463
|
+
ifMatch: options2["--if-match"],
|
|
15464
|
+
idempotencyKey: options2["--idempotency-key"],
|
|
15465
|
+
credentialStore
|
|
15466
|
+
};
|
|
15467
|
+
}
|
|
15468
|
+
if (subcommand === "handle" && values.shift() === "check") {
|
|
15469
|
+
if (yes || wait || follow || stdin)
|
|
15470
|
+
throw new InvalidCommandError();
|
|
15471
|
+
const options2 = parseOptions(values, ["--handle"]);
|
|
15472
|
+
return { kind: "project-handle-check", handle: options2["--handle"], credentialStore };
|
|
15473
|
+
}
|
|
15445
15474
|
if (subcommand === "dev-access" && values.shift() === "create") {
|
|
15446
15475
|
if (yes || wait || follow || stdin)
|
|
15447
15476
|
throw new InvalidCommandError();
|
|
@@ -16517,7 +16546,7 @@ function assertOrganizationAccount(value) {
|
|
|
16517
16546
|
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")
|
|
16518
16547
|
throw new TypeError("Invalid account fields");
|
|
16519
16548
|
const v = value;
|
|
16520
|
-
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", "
|
|
16549
|
+
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"))
|
|
16521
16550
|
throw new TypeError("Invalid account scope");
|
|
16522
16551
|
for (const field of ["available_micros", "monthly_micros", "one_time_micros", "reserved_micros"])
|
|
16523
16552
|
if (typeof v[field] !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(v[field]))
|
|
@@ -16743,6 +16772,26 @@ var PROBLEM_POLICY = {
|
|
|
16743
16772
|
retryable: true,
|
|
16744
16773
|
action: "Retry project creation with the same idempotency key."
|
|
16745
16774
|
},
|
|
16775
|
+
project_handle_taken: {
|
|
16776
|
+
status: 409,
|
|
16777
|
+
retryable: false,
|
|
16778
|
+
action: "Run 'ohmyhost project handle check' for a free address, then rename to one of the alternatives it returns."
|
|
16779
|
+
},
|
|
16780
|
+
project_handle_invalid: {
|
|
16781
|
+
status: 409,
|
|
16782
|
+
retryable: false,
|
|
16783
|
+
action: "Choose one to five lowercase words of letters and digits, three to fifty-nine characters, avoiding reserved words."
|
|
16784
|
+
},
|
|
16785
|
+
project_handle_unchanged: {
|
|
16786
|
+
status: 409,
|
|
16787
|
+
retryable: false,
|
|
16788
|
+
action: "The project already answers on this address; no rename is needed."
|
|
16789
|
+
},
|
|
16790
|
+
project_rename_blocked: {
|
|
16791
|
+
status: 409,
|
|
16792
|
+
retryable: true,
|
|
16793
|
+
action: "Wait for the running operation to finish, read the project again, then rename with the new ETag."
|
|
16794
|
+
},
|
|
16746
16795
|
project_identity_unavailable: {
|
|
16747
16796
|
status: 503,
|
|
16748
16797
|
retryable: true,
|
|
@@ -16808,6 +16857,11 @@ var PROBLEM_POLICY = {
|
|
|
16808
16857
|
retryable: false,
|
|
16809
16858
|
action: "Run 'ohmyhost init', apply the matching ohmyhost framework skill, then plan the new commit."
|
|
16810
16859
|
},
|
|
16860
|
+
repository_configuration_missing: {
|
|
16861
|
+
status: 409,
|
|
16862
|
+
retryable: false,
|
|
16863
|
+
action: "Place ohmyhost.yaml at the Git repository root and set applicationRoot to the application directory (for example website). Commit and push the change, then plan the new commit."
|
|
16864
|
+
},
|
|
16811
16865
|
migration_filename_noncanonical: {
|
|
16812
16866
|
status: 409,
|
|
16813
16867
|
retryable: false,
|
|
@@ -17066,7 +17120,7 @@ var parseDevAccessTicket = (value) => {
|
|
|
17066
17120
|
]);
|
|
17067
17121
|
const origin = input["origin"];
|
|
17068
17122
|
const redeemUrl = input["redeem_url"];
|
|
17069
|
-
if (!isUlid(input["ticket_id"]) || !isUlid(input["project_id"]) || !isUlid(input["environment_id"]) || typeof origin !== "string" || !/^https:\/\/dev-[a-
|
|
17123
|
+
if (!isUlid(input["ticket_id"]) || !isUlid(input["project_id"]) || !isUlid(input["environment_id"]) || typeof origin !== "string" || !/^https:\/\/dev-[a-z0-9]+(?:-[a-z0-9]+){0,4}\.(?:dev\.)?check\.omh\.st$/u.test(origin) || typeof redeemUrl !== "string" || !/^https:\/\/dev-[a-z0-9]+(?:-[a-z0-9]+){0,4}\.(?:dev\.)?check\.omh\.st\/\.ohmyhost\/dev-access\/redeem\?stage=dev&ticket=[A-Za-z0-9_-]{43}$/u.test(redeemUrl) || new URL(redeemUrl).origin !== origin || !isIsoInstant(input["expires_at"])) {
|
|
17070
17124
|
throw new ResponseContractError();
|
|
17071
17125
|
}
|
|
17072
17126
|
return input;
|
|
@@ -17189,7 +17243,7 @@ var parseProject = (value) => {
|
|
|
17189
17243
|
"region",
|
|
17190
17244
|
"created_at"
|
|
17191
17245
|
]);
|
|
17192
|
-
if (!isUlid(input["id"]) || !isUlid(input["organization_id"]) || !boundedString(input["name"], 1, 128) || input["name"] !== input["name"].trim() || !boundedString(input["handle"],
|
|
17246
|
+
if (!isUlid(input["id"]) || !isUlid(input["organization_id"]) || !boundedString(input["name"], 1, 128) || input["name"] !== input["name"].trim() || !boundedString(input["handle"], 3, 59) || !/^[a-z0-9]+(?:-[a-z0-9]+){0,4}$/u.test(input["handle"]) || input["data_mode"] !== "shared" && input["data_mode"] !== "isolated" || input["region"] !== "us" && input["region"] !== "eu" || !isIsoInstant(input["created_at"])) {
|
|
17193
17247
|
throw new ResponseContractError();
|
|
17194
17248
|
}
|
|
17195
17249
|
return input;
|
|
@@ -17207,6 +17261,7 @@ var parseProjectPage = (value) => {
|
|
|
17207
17261
|
var parseProjectStatus = (value) => {
|
|
17208
17262
|
const input = exactRecord2(value, [
|
|
17209
17263
|
"project_id",
|
|
17264
|
+
"etag",
|
|
17210
17265
|
"handle",
|
|
17211
17266
|
"region",
|
|
17212
17267
|
"lifecycle",
|
|
@@ -17220,7 +17275,7 @@ var parseProjectStatus = (value) => {
|
|
|
17220
17275
|
"cleanup_state"
|
|
17221
17276
|
]);
|
|
17222
17277
|
const handle = input["handle"];
|
|
17223
|
-
if (!isUlid(input["project_id"]) || !boundedString(handle,
|
|
17278
|
+
if (!isUlid(input["project_id"]) || typeof input["etag"] !== "string" || !/^"sha256-[a-f0-9]{64}"$/u.test(input["etag"]) || !boundedString(handle, 3, 59) || !/^[a-z0-9]+(?:-[a-z0-9]+){0,4}$/u.test(handle) || input["region"] !== "us" && input["region"] !== "eu" || input["lifecycle"] !== "active" && input["lifecycle"] !== "deleting" && input["lifecycle"] !== "deleted" || input["dev_url"] !== null && ![`https://dev-${handle}.dev.check.omh.st`, `https://dev-${handle}.check.omh.st`].includes(String(input["dev_url"])) || input["prod_url"] !== null && ![`https://${handle}.dev.check.omh.st`, `https://${handle}.check.omh.st`].includes(String(input["prod_url"])) || input["cleanup_state"] !== "not_started" && input["cleanup_state"] !== "pending" && input["cleanup_state"] !== "completed" && input["cleanup_state"] !== "reconciliation_required") {
|
|
17224
17279
|
throw new ResponseContractError();
|
|
17225
17280
|
}
|
|
17226
17281
|
if (input["source"] !== null)
|
|
@@ -17530,13 +17585,14 @@ var parseSafeProblem = (value) => {
|
|
|
17530
17585
|
if (typeof code !== "string" || !(code in PROBLEM_POLICY))
|
|
17531
17586
|
throw new ResponseContractError();
|
|
17532
17587
|
const policy = PROBLEM_POLICY[code];
|
|
17533
|
-
if (input["status"] !== policy.status || !boundedString(input["type"], 1, 512) || !isHttpsUrl(input["type"]) || !boundedString(input["title"], 1, 160) || !boundedString(input["request_id"], 1, 128) || typeof input["retryable"] !== "boolean" || !boundedString(input["suggested_action"], 1, 500) || input["detail"] !== void 0 && !boundedString(input["detail"], 1, 2e3) || input["instance"] !== void 0 && !boundedString(input["instance"], 1, 512)) {
|
|
17588
|
+
if (input["status"] !== policy.status || !boundedString(input["type"], 1, 512) || !isHttpsUrl(input["type"]) || !boundedString(input["title"], 1, 160) || !boundedString(input["request_id"], 1, 128) || /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(input["request_id"]) || typeof input["retryable"] !== "boolean" || !boundedString(input["suggested_action"], 1, 500) || input["detail"] !== void 0 && !boundedString(input["detail"], 1, 2e3) || input["instance"] !== void 0 && !boundedString(input["instance"], 1, 512)) {
|
|
17534
17589
|
throw new ResponseContractError();
|
|
17535
17590
|
}
|
|
17536
17591
|
const retryAfter = input["retry_after_seconds"];
|
|
17537
17592
|
if (retryAfter !== void 0 && (code !== "rate_limited" || typeof retryAfter !== "number" || !Number.isSafeInteger(retryAfter) || retryAfter < 1 || retryAfter > 86400))
|
|
17538
17593
|
throw new ResponseContractError();
|
|
17539
17594
|
return {
|
|
17595
|
+
requestId: input["request_id"],
|
|
17540
17596
|
code,
|
|
17541
17597
|
retryable: policy.retryable,
|
|
17542
17598
|
suggestedAction: (code === "framework_conversion_required" ? parseFrameworkConversionDetail(input["detail"]) ?? policy.action : policy.action) + (retryAfter === void 0 ? "" : ` Retry after ${String(retryAfter)} seconds.`),
|
|
@@ -17810,7 +17866,7 @@ function exact2(v, keys) {
|
|
|
17810
17866
|
// apps/product-cli/package.json
|
|
17811
17867
|
var package_default = {
|
|
17812
17868
|
name: "@ohmyhost/product-cli",
|
|
17813
|
-
version: "0.1.
|
|
17869
|
+
version: "0.1.13",
|
|
17814
17870
|
private: true,
|
|
17815
17871
|
ohmyhost: {
|
|
17816
17872
|
deployment: "production",
|
|
@@ -18173,6 +18229,8 @@ var HELP_USAGE = Object.freeze({
|
|
|
18173
18229
|
"project notes set": "ohmyhost project notes set --project ULID --version NUMBER --markdown TEXT --idempotency-key KEY --json (no credentials or signed URLs)",
|
|
18174
18230
|
"project status": "ohmyhost project status --project ULID --json",
|
|
18175
18231
|
"project dev-access create": "ohmyhost project dev-access create --project ULID --json",
|
|
18232
|
+
"project handle check": "ohmyhost project handle check --handle HANDLE --json (is this address free? answers with a reason and free alternatives; the address becomes HANDLE.check.omh.st)",
|
|
18233
|
+
"project handle set": "ohmyhost project handle set --project ULID --handle HANDLE --if-match ETAG --idempotency-key KEY --json (moves the project to a free address; the old one stops working and anyone may claim it)",
|
|
18176
18234
|
"database compute set": "ohmyhost database compute set --project ULID --environment dev|prod --profile standard|performance --idempotency-key KEY --yes [--wait] --json\n standard: Free 0.25 CU/1 GB/60s idle, Paid 0.5 CU/2 GB/60s idle. performance: Paid 1 CU/4 GB/300s idle, 2.5x database compute credits per equal active minute; longer idle time also consumes credits.",
|
|
18177
18235
|
"database compute get": "ohmyhost database compute get --project ULID [--environment dev|prod] --json",
|
|
18178
18236
|
"database write": "ohmyhost database write --project ULID --environment dev|prod --statement-file PATH --idempotency-key KEY [--parameters-json JSON] --yes --json",
|
|
@@ -18447,6 +18505,10 @@ var ProductCli = class {
|
|
|
18447
18505
|
return await this.createProject(command, signal);
|
|
18448
18506
|
if (command.kind === "project-list")
|
|
18449
18507
|
return await this.listProjects(command, signal);
|
|
18508
|
+
if (command.kind === "project-handle-check")
|
|
18509
|
+
return await this.checkProjectHandle(command, signal);
|
|
18510
|
+
if (command.kind === "project-handle-set")
|
|
18511
|
+
return await this.changeProjectHandle(command, signal);
|
|
18450
18512
|
if (command.kind === "database-compute-set") {
|
|
18451
18513
|
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
18452
18514
|
let operation = parseOperation(await api.changeDatabaseCompute(command));
|
|
@@ -18786,6 +18848,21 @@ var ProductCli = class {
|
|
|
18786
18848
|
}));
|
|
18787
18849
|
return success("project list", { status: "succeeded", projects });
|
|
18788
18850
|
}
|
|
18851
|
+
async changeProjectHandle(command, signal) {
|
|
18852
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
18853
|
+
const operation = parseOperation(await api.changeProjectHandle({
|
|
18854
|
+
projectId: command.projectId,
|
|
18855
|
+
handle: command.handle,
|
|
18856
|
+
ifMatch: command.ifMatch,
|
|
18857
|
+
idempotencyKey: command.idempotencyKey
|
|
18858
|
+
}));
|
|
18859
|
+
return success("project handle set", { status: "accepted", operation });
|
|
18860
|
+
}
|
|
18861
|
+
async checkProjectHandle(command, signal) {
|
|
18862
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
18863
|
+
const handle = await api.checkProjectHandle({ handle: command.handle });
|
|
18864
|
+
return success("project handle check", { status: "succeeded", handle });
|
|
18865
|
+
}
|
|
18789
18866
|
async getProjectStatus(command, signal) {
|
|
18790
18867
|
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
18791
18868
|
const project = parseProjectStatus(await api.getProjectStatus(command.projectId));
|
|
@@ -19290,7 +19367,7 @@ var classifyFailure = (command, error, signal) => {
|
|
|
19290
19367
|
if (looksLikeProblem(error)) {
|
|
19291
19368
|
try {
|
|
19292
19369
|
const problem = parseSafeProblem(error);
|
|
19293
|
-
return failure(command, 7, problem.code, problem.retryable, problem.suggestedAction, void 0, problem.retryAfterSeconds);
|
|
19370
|
+
return failure(command, 7, problem.code, problem.retryable, problem.suggestedAction, void 0, problem.retryAfterSeconds, problem.requestId);
|
|
19294
19371
|
} catch {
|
|
19295
19372
|
return failure(command, 7, "response_contract_invalid", false, "Retry only after the client or server contract is repaired.");
|
|
19296
19373
|
}
|
|
@@ -19310,7 +19387,7 @@ var success = (command, body) => ({
|
|
|
19310
19387
|
`,
|
|
19311
19388
|
stderr: ""
|
|
19312
19389
|
});
|
|
19313
|
-
var failure = (command, exitCode, code, retryable, suggestedAction, operation, retryAfterSeconds) => {
|
|
19390
|
+
var failure = (command, exitCode, code, retryable, suggestedAction, operation, retryAfterSeconds, requestId) => {
|
|
19314
19391
|
const document = {
|
|
19315
19392
|
version: 1,
|
|
19316
19393
|
command,
|
|
@@ -19321,6 +19398,7 @@ var failure = (command, exitCode, code, retryable, suggestedAction, operation, r
|
|
|
19321
19398
|
retryable,
|
|
19322
19399
|
suggested_action: suggestedAction,
|
|
19323
19400
|
...retryAfterSeconds === void 0 ? {} : { retry_after_seconds: retryAfterSeconds },
|
|
19401
|
+
...requestId === void 0 ? {} : { request_id: requestId },
|
|
19324
19402
|
...operation?.error === void 0 ? {} : { message: operation.error.message }
|
|
19325
19403
|
}
|
|
19326
19404
|
};
|
|
@@ -19390,6 +19468,10 @@ var parsedCommandName = (command) => {
|
|
|
19390
19468
|
return "project status";
|
|
19391
19469
|
if (command.kind === "project-dev-access-create")
|
|
19392
19470
|
return "project dev-access create";
|
|
19471
|
+
if (command.kind === "project-handle-check")
|
|
19472
|
+
return "project handle check";
|
|
19473
|
+
if (command.kind === "project-handle-set")
|
|
19474
|
+
return "project handle set";
|
|
19393
19475
|
if (command.kind === "database-write")
|
|
19394
19476
|
return "database write";
|
|
19395
19477
|
if (command.kind === "database-query")
|
|
@@ -20931,6 +21013,23 @@ var getProjectStatus = (parameters, options) => {
|
|
|
20931
21013
|
...params
|
|
20932
21014
|
});
|
|
20933
21015
|
};
|
|
21016
|
+
var getProjectHandleAvailability = (parameters, options) => {
|
|
21017
|
+
const params = buildClientParams([parameters], [
|
|
21018
|
+
{
|
|
21019
|
+
args: [
|
|
21020
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
21021
|
+
{ in: "path", key: "handle" }
|
|
21022
|
+
]
|
|
21023
|
+
}
|
|
21024
|
+
]);
|
|
21025
|
+
return (options?.client ?? client).get({
|
|
21026
|
+
responseStyle: "data",
|
|
21027
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
21028
|
+
url: "/v1/project-handles/{handle}",
|
|
21029
|
+
...options,
|
|
21030
|
+
...params
|
|
21031
|
+
});
|
|
21032
|
+
};
|
|
20934
21033
|
var createProjectDevAccessTicket = (parameters, options) => {
|
|
20935
21034
|
const params = buildClientParams([parameters], [
|
|
20936
21035
|
{
|
|
@@ -21071,6 +21170,31 @@ var getCloudflareDnsAuthorizationStatus = (parameters, options) => {
|
|
|
21071
21170
|
...params
|
|
21072
21171
|
});
|
|
21073
21172
|
};
|
|
21173
|
+
var changeProjectHandle = (parameters, options) => {
|
|
21174
|
+
const params = buildClientParams([parameters], [
|
|
21175
|
+
{
|
|
21176
|
+
args: [
|
|
21177
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
21178
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
21179
|
+
{ in: "headers", key: "If-Match" },
|
|
21180
|
+
{ in: "path", key: "project_id" },
|
|
21181
|
+
{ in: "body", key: "handle" }
|
|
21182
|
+
]
|
|
21183
|
+
}
|
|
21184
|
+
]);
|
|
21185
|
+
return (options?.client ?? client).put({
|
|
21186
|
+
responseStyle: "data",
|
|
21187
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
21188
|
+
url: "/v1/projects/{project_id}/handle",
|
|
21189
|
+
...options,
|
|
21190
|
+
...params,
|
|
21191
|
+
headers: {
|
|
21192
|
+
"Content-Type": "application/json",
|
|
21193
|
+
...options?.headers,
|
|
21194
|
+
...params.headers
|
|
21195
|
+
}
|
|
21196
|
+
});
|
|
21197
|
+
};
|
|
21074
21198
|
var configureProjectDomains = (parameters, options) => {
|
|
21075
21199
|
const params = buildClientParams([parameters], [
|
|
21076
21200
|
{
|
|
@@ -21817,6 +21941,17 @@ var GeneratedSdkProductApi = class {
|
|
|
21817
21941
|
async listProjects(input) {
|
|
21818
21942
|
return listProjects(input, { client: this.#client });
|
|
21819
21943
|
}
|
|
21944
|
+
async changeProjectHandle(input) {
|
|
21945
|
+
return changeProjectHandle({
|
|
21946
|
+
project_id: input.projectId,
|
|
21947
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
21948
|
+
"If-Match": input.ifMatch,
|
|
21949
|
+
handle: input.handle
|
|
21950
|
+
}, { client: this.#client });
|
|
21951
|
+
}
|
|
21952
|
+
async checkProjectHandle(input) {
|
|
21953
|
+
return getProjectHandleAvailability({ handle: input.handle }, { client: this.#client });
|
|
21954
|
+
}
|
|
21820
21955
|
async getProjectStatus(projectId) {
|
|
21821
21956
|
return getProjectStatus({ project_id: projectId }, { client: this.#client });
|
|
21822
21957
|
}
|
|
@@ -22078,7 +22213,7 @@ var OwnerOnlyProjectLinkStore = class {
|
|
|
22078
22213
|
// apps/product-cli/dist/repository-init.js
|
|
22079
22214
|
import { createHash } from "node:crypto";
|
|
22080
22215
|
import { lstat as lstat2, open as open3, readFile, readdir, stat } from "node:fs/promises";
|
|
22081
|
-
import { posix, resolve as resolve2 } from "node:path";
|
|
22216
|
+
import { dirname as dirname2, posix, resolve as resolve2 } from "node:path";
|
|
22082
22217
|
|
|
22083
22218
|
// packages/contracts/dist/application-root.js
|
|
22084
22219
|
var APPLICATION_ROOT_PATTERN = /^(?:\.|[A-Za-z0-9][A-Za-z0-9._-]*(?:\/[A-Za-z0-9][A-Za-z0-9._-]*)*)$/u;
|
|
@@ -23325,6 +23460,24 @@ async function assertRepositoryRoot(root) {
|
|
|
23325
23460
|
if (!information.isDirectory()) {
|
|
23326
23461
|
throw new RepositoryInitError("repository_not_directory", "Repository path is not a directory");
|
|
23327
23462
|
}
|
|
23463
|
+
for (let ancestor = root; ; ancestor = dirname2(ancestor)) {
|
|
23464
|
+
let marker;
|
|
23465
|
+
try {
|
|
23466
|
+
marker = await lstat2(resolve2(ancestor, ".git"));
|
|
23467
|
+
} catch (error) {
|
|
23468
|
+
if (error.code !== "ENOENT") {
|
|
23469
|
+
throw new RepositoryInitError("repository_unreadable", "Could not determine the Git repository root");
|
|
23470
|
+
}
|
|
23471
|
+
}
|
|
23472
|
+
if (marker !== void 0) {
|
|
23473
|
+
if (ancestor !== root) {
|
|
23474
|
+
throw new RepositoryInitError("repository_root_required", "Run ohmyhost init from the Git repository root and select the application directory with --root; ohmyhost.yaml must be at the repository root.");
|
|
23475
|
+
}
|
|
23476
|
+
return;
|
|
23477
|
+
}
|
|
23478
|
+
if (dirname2(ancestor) === ancestor)
|
|
23479
|
+
return;
|
|
23480
|
+
}
|
|
23328
23481
|
}
|
|
23329
23482
|
async function collectRepositoryFiles(root) {
|
|
23330
23483
|
const files = [];
|
|
@@ -24302,7 +24455,7 @@ var runOfflineInit = async (command, io, diagnostics) => {
|
|
|
24302
24455
|
});
|
|
24303
24456
|
const code = error instanceof RepositoryInitBlockedError ? "repository_init_blocked" : error instanceof RepositoryInitConflictError ? "repository_configuration_exists" : known ? error.code : "internal_error";
|
|
24304
24457
|
const exitCode = error instanceof RepositoryInitBlockedError ? 9 : known ? 2 : 1;
|
|
24305
|
-
const result = errorDocument("init", exitCode, code, false, error instanceof RepositoryInitConflictError ? "Keep the existing ohmyhost.yaml or remove it explicitly before retrying." : error instanceof RepositoryInitError && error.code === "project_name_invalid" ? "Pass a lowercase deployment slug with '--project', then rerun init." : "Run 'ohmyhost init --dry-run --json' and resolve every reported blocker.");
|
|
24458
|
+
const result = errorDocument("init", exitCode, code, false, error instanceof RepositoryInitConflictError ? "Keep the existing ohmyhost.yaml or remove it explicitly before retrying." : error instanceof RepositoryInitError && error.code === "repository_root_required" ? "Run ohmyhost init from the Git repository root with --root set to the application directory (for example --root website); commit the root ohmyhost.yaml before planning." : error instanceof RepositoryInitError && error.code === "project_name_invalid" ? "Pass a lowercase deployment slug with '--project', then rerun init." : "Run 'ohmyhost init --dry-run --json' and resolve every reported blocker.");
|
|
24306
24459
|
io.writeStdout(result.stdout);
|
|
24307
24460
|
return result.exitCode;
|
|
24308
24461
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -254,6 +254,7 @@ interface CliErrorDocument {
|
|
|
254
254
|
readonly suggested_action: string;
|
|
255
255
|
readonly message?: string;
|
|
256
256
|
readonly retry_after_seconds?: number;
|
|
257
|
+
readonly request_id?: string;
|
|
257
258
|
};
|
|
258
259
|
}
|
|
259
260
|
|
|
@@ -310,6 +311,10 @@ const HELP_USAGE = Object.freeze({
|
|
|
310
311
|
"ohmyhost project notes set --project ULID --version NUMBER --markdown TEXT --idempotency-key KEY --json (no credentials or signed URLs)",
|
|
311
312
|
"project status": "ohmyhost project status --project ULID --json",
|
|
312
313
|
"project dev-access create": "ohmyhost project dev-access create --project ULID --json",
|
|
314
|
+
"project handle check":
|
|
315
|
+
"ohmyhost project handle check --handle HANDLE --json (is this address free? answers with a reason and free alternatives; the address becomes HANDLE.check.omh.st)",
|
|
316
|
+
"project handle set":
|
|
317
|
+
"ohmyhost project handle set --project ULID --handle HANDLE --if-match ETAG --idempotency-key KEY --json (moves the project to a free address; the old one stops working and anyone may claim it)",
|
|
313
318
|
"database compute set":
|
|
314
319
|
"ohmyhost database compute set --project ULID --environment dev|prod --profile standard|performance --idempotency-key KEY --yes [--wait] --json\n" +
|
|
315
320
|
" standard: Free 0.25 CU/1 GB/60s idle, Paid 0.5 CU/2 GB/60s idle. performance: Paid 1 CU/4 GB/300s idle, 2.5x database compute credits per equal active minute; longer idle time also consumes credits.",
|
|
@@ -687,6 +692,10 @@ export class ProductCli {
|
|
|
687
692
|
}
|
|
688
693
|
if (command.kind === "project-create") return await this.createProject(command, signal);
|
|
689
694
|
if (command.kind === "project-list") return await this.listProjects(command, signal);
|
|
695
|
+
if (command.kind === "project-handle-check")
|
|
696
|
+
return await this.checkProjectHandle(command, signal);
|
|
697
|
+
if (command.kind === "project-handle-set")
|
|
698
|
+
return await this.changeProjectHandle(command, signal);
|
|
690
699
|
if (command.kind === "database-compute-set") {
|
|
691
700
|
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
692
701
|
let operation = parseOperation(await api.changeDatabaseCompute(command));
|
|
@@ -1165,6 +1174,31 @@ export class ProductCli {
|
|
|
1165
1174
|
return success("project list", { status: "succeeded", projects });
|
|
1166
1175
|
}
|
|
1167
1176
|
|
|
1177
|
+
private async changeProjectHandle(
|
|
1178
|
+
command: Extract<ProductCliCommand, { kind: "project-handle-set" }>,
|
|
1179
|
+
signal: AbortSignal,
|
|
1180
|
+
): Promise<CliResult> {
|
|
1181
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
1182
|
+
const operation = parseOperation(
|
|
1183
|
+
await api.changeProjectHandle({
|
|
1184
|
+
projectId: command.projectId,
|
|
1185
|
+
handle: command.handle,
|
|
1186
|
+
ifMatch: command.ifMatch,
|
|
1187
|
+
idempotencyKey: command.idempotencyKey,
|
|
1188
|
+
}),
|
|
1189
|
+
);
|
|
1190
|
+
return success("project handle set", { status: "accepted", operation });
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
private async checkProjectHandle(
|
|
1194
|
+
command: Extract<ProductCliCommand, { kind: "project-handle-check" }>,
|
|
1195
|
+
signal: AbortSignal,
|
|
1196
|
+
): Promise<CliResult> {
|
|
1197
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
1198
|
+
const handle = await api.checkProjectHandle({ handle: command.handle });
|
|
1199
|
+
return success("project handle check", { status: "succeeded", handle });
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1168
1202
|
private async getProjectStatus(
|
|
1169
1203
|
command: Extract<ProductCliCommand, { kind: "project-status" }>,
|
|
1170
1204
|
signal: AbortSignal,
|
|
@@ -2017,6 +2051,7 @@ const classifyFailure = (command: CommandLabel, error: unknown, signal: AbortSig
|
|
|
2017
2051
|
problem.suggestedAction,
|
|
2018
2052
|
undefined,
|
|
2019
2053
|
problem.retryAfterSeconds,
|
|
2054
|
+
problem.requestId,
|
|
2020
2055
|
);
|
|
2021
2056
|
} catch {
|
|
2022
2057
|
return failure(
|
|
@@ -2066,6 +2101,7 @@ const failure = (
|
|
|
2066
2101
|
suggestedAction: string,
|
|
2067
2102
|
operation?: ReturnType<typeof parseOperation>,
|
|
2068
2103
|
retryAfterSeconds?: number,
|
|
2104
|
+
requestId?: string,
|
|
2069
2105
|
): CliResult => {
|
|
2070
2106
|
const document: CliErrorDocument = {
|
|
2071
2107
|
version: 1,
|
|
@@ -2077,6 +2113,7 @@ const failure = (
|
|
|
2077
2113
|
retryable,
|
|
2078
2114
|
suggested_action: suggestedAction,
|
|
2079
2115
|
...(retryAfterSeconds === undefined ? {} : { retry_after_seconds: retryAfterSeconds }),
|
|
2116
|
+
...(requestId === undefined ? {} : { request_id: requestId }),
|
|
2080
2117
|
...(operation?.error === undefined ? {} : { message: operation.error.message }),
|
|
2081
2118
|
},
|
|
2082
2119
|
};
|
|
@@ -2115,6 +2152,8 @@ const parsedCommandName = (command: ProductCliCommand): CommandLabel => {
|
|
|
2115
2152
|
if (command.kind === "project-notes-set") return "project notes set";
|
|
2116
2153
|
if (command.kind === "project-status") return "project status";
|
|
2117
2154
|
if (command.kind === "project-dev-access-create") return "project dev-access create";
|
|
2155
|
+
if (command.kind === "project-handle-check") return "project handle check";
|
|
2156
|
+
if (command.kind === "project-handle-set") return "project handle set";
|
|
2118
2157
|
if (command.kind === "database-write") return "database write";
|
|
2119
2158
|
if (command.kind === "database-query") return "database query";
|
|
2120
2159
|
if (command.kind === "database-access-create") return "database access create";
|
|
@@ -132,6 +132,21 @@ export type ProductCliCommand =
|
|
|
132
132
|
readonly idempotencyKey: string;
|
|
133
133
|
readonly credentialStore: "native";
|
|
134
134
|
}
|
|
135
|
+
| {
|
|
136
|
+
/** Moves a project to a chosen address once its gateways serve it. */
|
|
137
|
+
readonly kind: "project-handle-set";
|
|
138
|
+
readonly projectId: string;
|
|
139
|
+
readonly handle: string;
|
|
140
|
+
readonly ifMatch: string;
|
|
141
|
+
readonly idempotencyKey: string;
|
|
142
|
+
readonly credentialStore: "native";
|
|
143
|
+
}
|
|
144
|
+
| {
|
|
145
|
+
/** Asks whether a project address is free; the candidate is sent exactly as the agent typed it. */
|
|
146
|
+
readonly kind: "project-handle-check";
|
|
147
|
+
readonly handle: string;
|
|
148
|
+
readonly credentialStore: "native";
|
|
149
|
+
}
|
|
135
150
|
| { readonly kind: "help"; readonly topic?: string }
|
|
136
151
|
| { readonly kind: "version" }
|
|
137
152
|
| { readonly kind: "whoami"; readonly credentialStore: "native" }
|
|
@@ -487,6 +502,8 @@ export type RecognizedCommandLabel =
|
|
|
487
502
|
| "project list"
|
|
488
503
|
| "project status"
|
|
489
504
|
| "project dev-access create"
|
|
505
|
+
| "project handle check"
|
|
506
|
+
| "project handle set"
|
|
490
507
|
| "database write"
|
|
491
508
|
| "database query"
|
|
492
509
|
| "database access create"
|
|
@@ -576,6 +593,10 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
576
593
|
if (value === "project" && values[0] === "notes" && values[1] === "set")
|
|
577
594
|
return "project notes set";
|
|
578
595
|
if (value === "project" && values[0] === "status") return "project status";
|
|
596
|
+
if (value === "project" && values[0] === "handle" && values[1] === "check")
|
|
597
|
+
return "project handle check";
|
|
598
|
+
if (value === "project" && values[0] === "handle" && values[1] === "set")
|
|
599
|
+
return "project handle set";
|
|
579
600
|
if (value === "project" && values[0] === "dev-access" && values[1] === "create")
|
|
580
601
|
return "project dev-access create";
|
|
581
602
|
if (value === "database" && values[0] === "compute" && values[1] === "set")
|
|
@@ -1045,6 +1066,29 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1045
1066
|
}
|
|
1046
1067
|
if (first === "project") {
|
|
1047
1068
|
const subcommand = values.shift();
|
|
1069
|
+
if (subcommand === "handle" && values[0] === "set") {
|
|
1070
|
+
values.shift();
|
|
1071
|
+
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1072
|
+
const options = parseOptions(values, [
|
|
1073
|
+
"--project",
|
|
1074
|
+
"--handle",
|
|
1075
|
+
"--if-match",
|
|
1076
|
+
"--idempotency-key",
|
|
1077
|
+
]);
|
|
1078
|
+
return {
|
|
1079
|
+
kind: "project-handle-set",
|
|
1080
|
+
projectId: options["--project"],
|
|
1081
|
+
handle: options["--handle"],
|
|
1082
|
+
ifMatch: options["--if-match"],
|
|
1083
|
+
idempotencyKey: options["--idempotency-key"],
|
|
1084
|
+
credentialStore,
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
if (subcommand === "handle" && values.shift() === "check") {
|
|
1088
|
+
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1089
|
+
const options = parseOptions(values, ["--handle"]);
|
|
1090
|
+
return { kind: "project-handle-check", handle: options["--handle"], credentialStore };
|
|
1091
|
+
}
|
|
1048
1092
|
if (subcommand === "dev-access" && values.shift() === "create") {
|
|
1049
1093
|
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1050
1094
|
const options = parseOptions(values, ["--project"]);
|
|
@@ -429,9 +429,11 @@ const runOfflineInit = async (
|
|
|
429
429
|
false,
|
|
430
430
|
error instanceof RepositoryInitConflictError
|
|
431
431
|
? "Keep the existing ohmyhost.yaml or remove it explicitly before retrying."
|
|
432
|
-
: error instanceof RepositoryInitError && error.code === "
|
|
433
|
-
? "
|
|
434
|
-
:
|
|
432
|
+
: error instanceof RepositoryInitError && error.code === "repository_root_required"
|
|
433
|
+
? "Run ohmyhost init from the Git repository root with --root set to the application directory (for example --root website); commit the root ohmyhost.yaml before planning."
|
|
434
|
+
: error instanceof RepositoryInitError && error.code === "project_name_invalid"
|
|
435
|
+
? "Pass a lowercase deployment slug with '--project', then rerun init."
|
|
436
|
+
: "Run 'ohmyhost init --dry-run --json' and resolve every reported blocker.",
|
|
435
437
|
);
|
|
436
438
|
io.writeStdout(result.stdout);
|
|
437
439
|
return result.exitCode;
|
|
@@ -83,6 +83,8 @@ import {
|
|
|
83
83
|
listEnvironmentSecrets,
|
|
84
84
|
listFunctionRuns,
|
|
85
85
|
listProjects,
|
|
86
|
+
changeProjectHandle,
|
|
87
|
+
getProjectHandleAvailability,
|
|
86
88
|
planDeployment,
|
|
87
89
|
planPaidProjectDomain,
|
|
88
90
|
planDeploymentRollback,
|
|
@@ -115,6 +117,7 @@ import {
|
|
|
115
117
|
type CurrentIdentity,
|
|
116
118
|
type DevAccessTicket,
|
|
117
119
|
type ProjectPage,
|
|
120
|
+
type ProjectHandleAvailability,
|
|
118
121
|
type ProjectStatus,
|
|
119
122
|
type PaidDomain,
|
|
120
123
|
type PaidDomainPlan,
|
|
@@ -208,6 +211,13 @@ export interface ProductApi {
|
|
|
208
211
|
/** The signed-in user's workspaces; an interactive session is required for this route. */
|
|
209
212
|
getAccountProfile(): Promise<readonly PublicWorkspace[]>;
|
|
210
213
|
listProjects(input: { readonly cursor?: string; readonly limit: number }): Promise<ProjectPage>;
|
|
214
|
+
checkProjectHandle(input: { readonly handle: string }): Promise<ProjectHandleAvailability>;
|
|
215
|
+
changeProjectHandle(input: {
|
|
216
|
+
readonly projectId: string;
|
|
217
|
+
readonly handle: string;
|
|
218
|
+
readonly ifMatch: string;
|
|
219
|
+
readonly idempotencyKey: string;
|
|
220
|
+
}): Promise<Operation>;
|
|
211
221
|
getProjectStatus(projectId: string): Promise<ProjectStatus>;
|
|
212
222
|
writeProjectDatabase(
|
|
213
223
|
input: ProjectDatabaseWriteRequest & { projectId: string; idempotencyKey: string },
|
|
@@ -582,6 +592,29 @@ export class GeneratedSdkProductApi implements ProductApi {
|
|
|
582
592
|
return listProjects(input, { client: this.#client });
|
|
583
593
|
}
|
|
584
594
|
|
|
595
|
+
public async changeProjectHandle(input: {
|
|
596
|
+
readonly projectId: string;
|
|
597
|
+
readonly handle: string;
|
|
598
|
+
readonly ifMatch: string;
|
|
599
|
+
readonly idempotencyKey: string;
|
|
600
|
+
}): Promise<Operation> {
|
|
601
|
+
return changeProjectHandle(
|
|
602
|
+
{
|
|
603
|
+
project_id: input.projectId,
|
|
604
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
605
|
+
"If-Match": input.ifMatch,
|
|
606
|
+
handle: input.handle,
|
|
607
|
+
},
|
|
608
|
+
{ client: this.#client },
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
public async checkProjectHandle(input: {
|
|
613
|
+
readonly handle: string;
|
|
614
|
+
}): Promise<ProjectHandleAvailability> {
|
|
615
|
+
return getProjectHandleAvailability({ handle: input.handle }, { client: this.#client });
|
|
616
|
+
}
|
|
617
|
+
|
|
585
618
|
public async getProjectStatus(projectId: string): Promise<ProjectStatus> {
|
|
586
619
|
return getProjectStatus({ project_id: projectId }, { client: this.#client });
|
|
587
620
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { lstat, open, readFile, readdir, stat } from "node:fs/promises";
|
|
3
|
-
import { posix, resolve } from "node:path";
|
|
3
|
+
import { dirname, posix, resolve } from "node:path";
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
normalizeApplicationRoot,
|
|
@@ -876,6 +876,30 @@ async function assertRepositoryRoot(root: string): Promise<void> {
|
|
|
876
876
|
if (!information.isDirectory()) {
|
|
877
877
|
throw new RepositoryInitError("repository_not_directory", "Repository path is not a directory");
|
|
878
878
|
}
|
|
879
|
+
// A Git worktree uses a .git file; never read or follow that file's target.
|
|
880
|
+
for (let ancestor = root; ; ancestor = dirname(ancestor)) {
|
|
881
|
+
let marker;
|
|
882
|
+
try {
|
|
883
|
+
marker = await lstat(resolve(ancestor, ".git"));
|
|
884
|
+
} catch (error) {
|
|
885
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
886
|
+
throw new RepositoryInitError(
|
|
887
|
+
"repository_unreadable",
|
|
888
|
+
"Could not determine the Git repository root",
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
if (marker !== undefined) {
|
|
893
|
+
if (ancestor !== root) {
|
|
894
|
+
throw new RepositoryInitError(
|
|
895
|
+
"repository_root_required",
|
|
896
|
+
"Run ohmyhost init from the Git repository root and select the application directory with --root; ohmyhost.yaml must be at the repository root.",
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
if (dirname(ancestor) === ancestor) return;
|
|
902
|
+
}
|
|
879
903
|
}
|
|
880
904
|
|
|
881
905
|
async function collectRepositoryFiles(root: string): Promise<string[]> {
|
|
@@ -129,6 +129,29 @@ const PROBLEM_POLICY = {
|
|
|
129
129
|
retryable: true,
|
|
130
130
|
action: "Retry project creation with the same idempotency key.",
|
|
131
131
|
},
|
|
132
|
+
project_handle_taken: {
|
|
133
|
+
status: 409,
|
|
134
|
+
retryable: false,
|
|
135
|
+
action:
|
|
136
|
+
"Run 'ohmyhost project handle check' for a free address, then rename to one of the alternatives it returns.",
|
|
137
|
+
},
|
|
138
|
+
project_handle_invalid: {
|
|
139
|
+
status: 409,
|
|
140
|
+
retryable: false,
|
|
141
|
+
action:
|
|
142
|
+
"Choose one to five lowercase words of letters and digits, three to fifty-nine characters, avoiding reserved words.",
|
|
143
|
+
},
|
|
144
|
+
project_handle_unchanged: {
|
|
145
|
+
status: 409,
|
|
146
|
+
retryable: false,
|
|
147
|
+
action: "The project already answers on this address; no rename is needed.",
|
|
148
|
+
},
|
|
149
|
+
project_rename_blocked: {
|
|
150
|
+
status: 409,
|
|
151
|
+
retryable: true,
|
|
152
|
+
action:
|
|
153
|
+
"Wait for the running operation to finish, read the project again, then rename with the new ETag.",
|
|
154
|
+
},
|
|
132
155
|
project_identity_unavailable: {
|
|
133
156
|
status: 503,
|
|
134
157
|
retryable: true,
|
|
@@ -196,6 +219,12 @@ const PROBLEM_POLICY = {
|
|
|
196
219
|
action:
|
|
197
220
|
"Run 'ohmyhost init', apply the matching ohmyhost framework skill, then plan the new commit.",
|
|
198
221
|
},
|
|
222
|
+
repository_configuration_missing: {
|
|
223
|
+
status: 409,
|
|
224
|
+
retryable: false,
|
|
225
|
+
action:
|
|
226
|
+
"Place ohmyhost.yaml at the Git repository root and set applicationRoot to the application directory (for example website). Commit and push the change, then plan the new commit.",
|
|
227
|
+
},
|
|
199
228
|
migration_filename_noncanonical: {
|
|
200
229
|
status: 409,
|
|
201
230
|
retryable: false,
|
|
@@ -278,6 +307,7 @@ export class ResponseContractError extends Error {
|
|
|
278
307
|
}
|
|
279
308
|
|
|
280
309
|
export interface SafeProblem {
|
|
310
|
+
readonly requestId: string;
|
|
281
311
|
readonly retryAfterSeconds?: number;
|
|
282
312
|
readonly code: ProblemCode;
|
|
283
313
|
readonly retryable: boolean;
|
|
@@ -676,9 +706,9 @@ export const parseDevAccessTicket = (value: unknown): PublicDevAccessTicket => {
|
|
|
676
706
|
!isUlid(input["project_id"]) ||
|
|
677
707
|
!isUlid(input["environment_id"]) ||
|
|
678
708
|
typeof origin !== "string" ||
|
|
679
|
-
!/^https:\/\/dev-[a-
|
|
709
|
+
!/^https:\/\/dev-[a-z0-9]+(?:-[a-z0-9]+){0,4}\.(?:dev\.)?check\.omh\.st$/u.test(origin) ||
|
|
680
710
|
typeof redeemUrl !== "string" ||
|
|
681
|
-
!/^https:\/\/dev-[a-
|
|
711
|
+
!/^https:\/\/dev-[a-z0-9]+(?:-[a-z0-9]+){0,4}\.(?:dev\.)?check\.omh\.st\/\.ohmyhost\/dev-access\/redeem\?stage=dev&ticket=[A-Za-z0-9_-]{43}$/u.test(
|
|
682
712
|
redeemUrl,
|
|
683
713
|
) ||
|
|
684
714
|
new URL(redeemUrl).origin !== origin ||
|
|
@@ -880,8 +910,8 @@ const parseProject = (value: unknown): PublicProject => {
|
|
|
880
910
|
!isUlid(input["organization_id"]) ||
|
|
881
911
|
!boundedString(input["name"], 1, 128) ||
|
|
882
912
|
input["name"] !== input["name"].trim() ||
|
|
883
|
-
!boundedString(input["handle"],
|
|
884
|
-
!/^[a-
|
|
913
|
+
!boundedString(input["handle"], 3, 59) ||
|
|
914
|
+
!/^[a-z0-9]+(?:-[a-z0-9]+){0,4}$/u.test(input["handle"]) ||
|
|
885
915
|
(input["data_mode"] !== "shared" && input["data_mode"] !== "isolated") ||
|
|
886
916
|
(input["region"] !== "us" && input["region"] !== "eu") ||
|
|
887
917
|
!isIsoInstant(input["created_at"])
|
|
@@ -910,6 +940,7 @@ export const parseProjectPage = (
|
|
|
910
940
|
export const parseProjectStatus = (value: unknown): Readonly<Record<string, unknown>> => {
|
|
911
941
|
const input = exactRecord(value, [
|
|
912
942
|
"project_id",
|
|
943
|
+
"etag",
|
|
913
944
|
"handle",
|
|
914
945
|
"region",
|
|
915
946
|
"lifecycle",
|
|
@@ -925,8 +956,10 @@ export const parseProjectStatus = (value: unknown): Readonly<Record<string, unkn
|
|
|
925
956
|
const handle = input["handle"];
|
|
926
957
|
if (
|
|
927
958
|
!isUlid(input["project_id"]) ||
|
|
928
|
-
|
|
929
|
-
!/^
|
|
959
|
+
typeof input["etag"] !== "string" ||
|
|
960
|
+
!/^"sha256-[a-f0-9]{64}"$/u.test(input["etag"]) ||
|
|
961
|
+
!boundedString(handle, 3, 59) ||
|
|
962
|
+
!/^[a-z0-9]+(?:-[a-z0-9]+){0,4}$/u.test(handle) ||
|
|
930
963
|
(input["region"] !== "us" && input["region"] !== "eu") ||
|
|
931
964
|
(input["lifecycle"] !== "active" &&
|
|
932
965
|
input["lifecycle"] !== "deleting" &&
|
|
@@ -1540,6 +1573,7 @@ export const parseSafeProblem = (value: unknown): SafeProblem => {
|
|
|
1540
1573
|
!isHttpsUrl(input["type"]) ||
|
|
1541
1574
|
!boundedString(input["title"], 1, 160) ||
|
|
1542
1575
|
!boundedString(input["request_id"], 1, 128) ||
|
|
1576
|
+
/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(input["request_id"]) ||
|
|
1543
1577
|
typeof input["retryable"] !== "boolean" ||
|
|
1544
1578
|
!boundedString(input["suggested_action"], 1, 500) ||
|
|
1545
1579
|
(input["detail"] !== undefined && !boundedString(input["detail"], 1, 2_000)) ||
|
|
@@ -1558,6 +1592,7 @@ export const parseSafeProblem = (value: unknown): SafeProblem => {
|
|
|
1558
1592
|
)
|
|
1559
1593
|
throw new ResponseContractError();
|
|
1560
1594
|
return {
|
|
1595
|
+
requestId: input["request_id"],
|
|
1561
1596
|
code: code as ProblemCode,
|
|
1562
1597
|
retryable: policy.retryable,
|
|
1563
1598
|
suggestedAction:
|
|
@@ -190,7 +190,7 @@ export function assertOrganizationAccount(value: unknown): void {
|
|
|
190
190
|
typeof v["workos_organization_id"] !== "string" ||
|
|
191
191
|
!/^org_[A-Za-z0-9_]+$/u.test(v["workos_organization_id"]) ||
|
|
192
192
|
(v["plan"] !== "paid" && v["plan"] !== "free") ||
|
|
193
|
-
!["free", "stripe", "
|
|
193
|
+
!["free", "stripe", "granted", "manual"].includes(String(v["plan_source"])) ||
|
|
194
194
|
(v["plan"] === "free") !== (v["plan_source"] === "free")
|
|
195
195
|
)
|
|
196
196
|
throw new TypeError("Invalid account scope");
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
export {
|
|
4
4
|
applyPaidProjectDomain,
|
|
5
5
|
changeDatabaseCompute,
|
|
6
|
+
changeProjectHandle,
|
|
6
7
|
completeCloudflareDnsAuthorization,
|
|
7
8
|
completeGithubSourceAuthorization,
|
|
8
9
|
configureBillingRecharge,
|
|
@@ -42,6 +43,7 @@ export {
|
|
|
42
43
|
getProjectContext,
|
|
43
44
|
getProjectCreditBudget,
|
|
44
45
|
getProjectExport,
|
|
46
|
+
getProjectHandleAvailability,
|
|
45
47
|
getProjectMailDomain,
|
|
46
48
|
getProjectSource,
|
|
47
49
|
getProjectSourceAutoDeploy,
|
|
@@ -100,6 +102,11 @@ export type {
|
|
|
100
102
|
ChangeDatabaseComputeErrors,
|
|
101
103
|
ChangeDatabaseComputeResponse,
|
|
102
104
|
ChangeDatabaseComputeResponses,
|
|
105
|
+
ChangeProjectHandleData,
|
|
106
|
+
ChangeProjectHandleError,
|
|
107
|
+
ChangeProjectHandleErrors,
|
|
108
|
+
ChangeProjectHandleResponse,
|
|
109
|
+
ChangeProjectHandleResponses,
|
|
103
110
|
ClientOptions,
|
|
104
111
|
CloudflareDnsAuthorization,
|
|
105
112
|
CloudflareDnsAuthorizationStatus,
|
|
@@ -331,6 +338,11 @@ export type {
|
|
|
331
338
|
GetProjectExportErrors,
|
|
332
339
|
GetProjectExportResponse,
|
|
333
340
|
GetProjectExportResponses,
|
|
341
|
+
GetProjectHandleAvailabilityData,
|
|
342
|
+
GetProjectHandleAvailabilityError,
|
|
343
|
+
GetProjectHandleAvailabilityErrors,
|
|
344
|
+
GetProjectHandleAvailabilityResponse,
|
|
345
|
+
GetProjectHandleAvailabilityResponses,
|
|
334
346
|
GetProjectMailDomainData,
|
|
335
347
|
GetProjectMailDomainError,
|
|
336
348
|
GetProjectMailDomainErrors,
|
|
@@ -467,6 +479,7 @@ export type {
|
|
|
467
479
|
ProjectExport,
|
|
468
480
|
ProjectExportArchive,
|
|
469
481
|
ProjectFilter,
|
|
482
|
+
ProjectHandleAvailability,
|
|
470
483
|
ProjectId,
|
|
471
484
|
ProjectLimit,
|
|
472
485
|
ProjectMailDomain,
|
|
@@ -15,6 +15,8 @@ import type {
|
|
|
15
15
|
ApplyPaidProjectDomainResponses,
|
|
16
16
|
ChangeDatabaseComputeErrors,
|
|
17
17
|
ChangeDatabaseComputeResponses,
|
|
18
|
+
ChangeProjectHandleErrors,
|
|
19
|
+
ChangeProjectHandleResponses,
|
|
18
20
|
CompleteCloudflareDnsAuthorizationErrors,
|
|
19
21
|
CompleteCloudflareDnsAuthorizationResponses,
|
|
20
22
|
CompleteGithubSourceAuthorizationErrors,
|
|
@@ -100,6 +102,8 @@ import type {
|
|
|
100
102
|
GetProjectErrors,
|
|
101
103
|
GetProjectExportErrors,
|
|
102
104
|
GetProjectExportResponses,
|
|
105
|
+
GetProjectHandleAvailabilityErrors,
|
|
106
|
+
GetProjectHandleAvailabilityResponses,
|
|
103
107
|
GetProjectMailDomainErrors,
|
|
104
108
|
GetProjectMailDomainResponses,
|
|
105
109
|
GetProjectResponses,
|
|
@@ -447,7 +451,7 @@ export const getFeatureInterests = <ThrowOnError extends boolean = true>(
|
|
|
447
451
|
"data"
|
|
448
452
|
>({
|
|
449
453
|
responseStyle: "data",
|
|
450
|
-
url: "/v1/
|
|
454
|
+
url: "/v1/site/feature-interests",
|
|
451
455
|
...options,
|
|
452
456
|
...params,
|
|
453
457
|
});
|
|
@@ -492,7 +496,7 @@ export const registerFeatureInterest = <ThrowOnError extends boolean = true>(
|
|
|
492
496
|
"data"
|
|
493
497
|
>({
|
|
494
498
|
responseStyle: "data",
|
|
495
|
-
url: "/v1/
|
|
499
|
+
url: "/v1/site/feature-interests",
|
|
496
500
|
...options,
|
|
497
501
|
...params,
|
|
498
502
|
headers: {
|
|
@@ -521,7 +525,7 @@ export const getPublicDeploymentStats = <ThrowOnError extends boolean = true>(
|
|
|
521
525
|
"data"
|
|
522
526
|
>({
|
|
523
527
|
responseStyle: "data",
|
|
524
|
-
url: "/v1/
|
|
528
|
+
url: "/v1/site/stats",
|
|
525
529
|
...options,
|
|
526
530
|
});
|
|
527
531
|
|
|
@@ -1682,6 +1686,48 @@ export const getProjectStatus = <ThrowOnError extends boolean = true>(
|
|
|
1682
1686
|
});
|
|
1683
1687
|
};
|
|
1684
1688
|
|
|
1689
|
+
/**
|
|
1690
|
+
* Check whether a project handle is free
|
|
1691
|
+
*
|
|
1692
|
+
* Reports whether a handle can be used for a project and why not when it cannot, with free alternatives an agent can offer. A handle is one to five lowercase words of letters and digits separated by single hyphens, three to fifty-nine characters, and never one of the reserved words. Availability is answered across all projects without revealing which organization holds a taken handle.
|
|
1693
|
+
*/
|
|
1694
|
+
export const getProjectHandleAvailability = <ThrowOnError extends boolean = true>(
|
|
1695
|
+
parameters: {
|
|
1696
|
+
"X-Request-Id"?: string;
|
|
1697
|
+
handle: string;
|
|
1698
|
+
},
|
|
1699
|
+
options?: Options<never, ThrowOnError>,
|
|
1700
|
+
): RequestResult<
|
|
1701
|
+
GetProjectHandleAvailabilityResponses,
|
|
1702
|
+
GetProjectHandleAvailabilityErrors,
|
|
1703
|
+
ThrowOnError,
|
|
1704
|
+
"data"
|
|
1705
|
+
> => {
|
|
1706
|
+
const params = buildClientParams(
|
|
1707
|
+
[parameters],
|
|
1708
|
+
[
|
|
1709
|
+
{
|
|
1710
|
+
args: [
|
|
1711
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
1712
|
+
{ in: "path", key: "handle" },
|
|
1713
|
+
],
|
|
1714
|
+
},
|
|
1715
|
+
],
|
|
1716
|
+
);
|
|
1717
|
+
return (options?.client ?? client).get<
|
|
1718
|
+
GetProjectHandleAvailabilityResponses,
|
|
1719
|
+
GetProjectHandleAvailabilityErrors,
|
|
1720
|
+
ThrowOnError,
|
|
1721
|
+
"data"
|
|
1722
|
+
>({
|
|
1723
|
+
responseStyle: "data",
|
|
1724
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1725
|
+
url: "/v1/project-handles/{handle}",
|
|
1726
|
+
...options,
|
|
1727
|
+
...params,
|
|
1728
|
+
});
|
|
1729
|
+
};
|
|
1730
|
+
|
|
1685
1731
|
/**
|
|
1686
1732
|
* Create a single-use dev access ticket
|
|
1687
1733
|
*
|
|
@@ -2026,6 +2072,54 @@ export const getCloudflareDnsAuthorizationStatus = <ThrowOnError extends boolean
|
|
|
2026
2072
|
});
|
|
2027
2073
|
};
|
|
2028
2074
|
|
|
2075
|
+
/**
|
|
2076
|
+
* Move a project to a chosen address
|
|
2077
|
+
*
|
|
2078
|
+
* Starts a durable operation that re-publishes the project's Dev and Prod gateways at the chosen address and stores it only once both serve it. The previous address stops answering and returns to the pool for any project to claim. Ask GET /v1/project-handles/{handle} first; a taken, unusable or unchanged address is refused before any gateway moves, and a project with an operation in flight is refused until it finishes.
|
|
2079
|
+
*/
|
|
2080
|
+
export const changeProjectHandle = <ThrowOnError extends boolean = true>(
|
|
2081
|
+
parameters: {
|
|
2082
|
+
"X-Request-Id"?: string;
|
|
2083
|
+
"Idempotency-Key": string;
|
|
2084
|
+
"If-Match": string;
|
|
2085
|
+
project_id: Ulid;
|
|
2086
|
+
handle: string;
|
|
2087
|
+
},
|
|
2088
|
+
options?: Options<never, ThrowOnError>,
|
|
2089
|
+
): RequestResult<ChangeProjectHandleResponses, ChangeProjectHandleErrors, ThrowOnError, "data"> => {
|
|
2090
|
+
const params = buildClientParams(
|
|
2091
|
+
[parameters],
|
|
2092
|
+
[
|
|
2093
|
+
{
|
|
2094
|
+
args: [
|
|
2095
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
2096
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
2097
|
+
{ in: "headers", key: "If-Match" },
|
|
2098
|
+
{ in: "path", key: "project_id" },
|
|
2099
|
+
{ in: "body", key: "handle" },
|
|
2100
|
+
],
|
|
2101
|
+
},
|
|
2102
|
+
],
|
|
2103
|
+
);
|
|
2104
|
+
return (options?.client ?? client).put<
|
|
2105
|
+
ChangeProjectHandleResponses,
|
|
2106
|
+
ChangeProjectHandleErrors,
|
|
2107
|
+
ThrowOnError,
|
|
2108
|
+
"data"
|
|
2109
|
+
>({
|
|
2110
|
+
responseStyle: "data",
|
|
2111
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
2112
|
+
url: "/v1/projects/{project_id}/handle",
|
|
2113
|
+
...options,
|
|
2114
|
+
...params,
|
|
2115
|
+
headers: {
|
|
2116
|
+
"Content-Type": "application/json",
|
|
2117
|
+
...options?.headers,
|
|
2118
|
+
...params.headers,
|
|
2119
|
+
},
|
|
2120
|
+
});
|
|
2121
|
+
};
|
|
2122
|
+
|
|
2029
2123
|
/**
|
|
2030
2124
|
* Apply the server-derived project domains
|
|
2031
2125
|
*
|
|
@@ -807,7 +807,7 @@ export type OrganizationAccount = {
|
|
|
807
807
|
name: string;
|
|
808
808
|
workos_organization_id: string;
|
|
809
809
|
plan: "free" | "paid";
|
|
810
|
-
plan_source: "free" | "stripe" | "
|
|
810
|
+
plan_source: "free" | "stripe" | "granted" | "manual";
|
|
811
811
|
paid_until: string | null;
|
|
812
812
|
available_micros: CreditMicros;
|
|
813
813
|
monthly_micros: CreditMicros;
|
|
@@ -845,7 +845,30 @@ export type ProjectEnvironment = {
|
|
|
845
845
|
name: string;
|
|
846
846
|
};
|
|
847
847
|
|
|
848
|
+
export type ProjectHandleAvailability = {
|
|
849
|
+
/**
|
|
850
|
+
* The handle exactly as it was asked about.
|
|
851
|
+
*/
|
|
852
|
+
handle: string;
|
|
853
|
+
/**
|
|
854
|
+
* True when a project may take this handle now.
|
|
855
|
+
*/
|
|
856
|
+
available: boolean;
|
|
857
|
+
/**
|
|
858
|
+
* Why the handle cannot be used. Absent when it is available.
|
|
859
|
+
*/
|
|
860
|
+
reason?: "taken" | "too_short" | "too_long" | "invalid_shape" | "prohibited_word";
|
|
861
|
+
/**
|
|
862
|
+
* Free handles to offer instead, empty when the handle is available.
|
|
863
|
+
*/
|
|
864
|
+
alternatives: Array<string>;
|
|
865
|
+
};
|
|
866
|
+
|
|
848
867
|
export type ProjectStatus = {
|
|
868
|
+
/**
|
|
869
|
+
* Optimistic-concurrency token for changing this project address; use it as If-Match on the handle endpoint.
|
|
870
|
+
*/
|
|
871
|
+
etag: string;
|
|
849
872
|
project_id: Ulid;
|
|
850
873
|
handle: string;
|
|
851
874
|
region: HostingRegion;
|
|
@@ -893,9 +916,14 @@ export type ProblemDetails = {
|
|
|
893
916
|
| "mail_domain_required"
|
|
894
917
|
| "storage_jurisdiction_conflict"
|
|
895
918
|
| "framework_conversion_required"
|
|
919
|
+
| "repository_configuration_missing"
|
|
896
920
|
| "migration_filename_noncanonical"
|
|
897
921
|
| "environment_secret_mutation_blocked"
|
|
898
922
|
| "workers_runtime_incompatible"
|
|
923
|
+
| "project_handle_invalid"
|
|
924
|
+
| "project_handle_taken"
|
|
925
|
+
| "project_handle_unchanged"
|
|
926
|
+
| "project_rename_blocked"
|
|
899
927
|
| "payload_too_large"
|
|
900
928
|
| "rate_limited"
|
|
901
929
|
| "insufficient_organization_credits"
|
|
@@ -1589,7 +1617,7 @@ export type GetFeatureInterestsData = {
|
|
|
1589
1617
|
};
|
|
1590
1618
|
path?: never;
|
|
1591
1619
|
query?: never;
|
|
1592
|
-
url: "/v1/
|
|
1620
|
+
url: "/v1/site/feature-interests";
|
|
1593
1621
|
};
|
|
1594
1622
|
|
|
1595
1623
|
export type GetFeatureInterestsErrors = {
|
|
@@ -1633,7 +1661,7 @@ export type RegisterFeatureInterestData = {
|
|
|
1633
1661
|
};
|
|
1634
1662
|
path?: never;
|
|
1635
1663
|
query?: never;
|
|
1636
|
-
url: "/v1/
|
|
1664
|
+
url: "/v1/site/feature-interests";
|
|
1637
1665
|
};
|
|
1638
1666
|
|
|
1639
1667
|
export type RegisterFeatureInterestErrors = {
|
|
@@ -1683,7 +1711,7 @@ export type GetPublicDeploymentStatsData = {
|
|
|
1683
1711
|
body?: never;
|
|
1684
1712
|
path?: never;
|
|
1685
1713
|
query?: never;
|
|
1686
|
-
url: "/v1/
|
|
1714
|
+
url: "/v1/site/stats";
|
|
1687
1715
|
};
|
|
1688
1716
|
|
|
1689
1717
|
export type GetPublicDeploymentStatsErrors = {
|
|
@@ -3255,6 +3283,60 @@ export type GetProjectStatusResponses = {
|
|
|
3255
3283
|
|
|
3256
3284
|
export type GetProjectStatusResponse = GetProjectStatusResponses[keyof GetProjectStatusResponses];
|
|
3257
3285
|
|
|
3286
|
+
export type GetProjectHandleAvailabilityData = {
|
|
3287
|
+
body?: never;
|
|
3288
|
+
headers?: {
|
|
3289
|
+
/**
|
|
3290
|
+
* Optional caller-provided correlation identifier.
|
|
3291
|
+
*/
|
|
3292
|
+
"X-Request-Id"?: string;
|
|
3293
|
+
};
|
|
3294
|
+
path: {
|
|
3295
|
+
/**
|
|
3296
|
+
* The handle a customer would like to use.
|
|
3297
|
+
*/
|
|
3298
|
+
handle: string;
|
|
3299
|
+
};
|
|
3300
|
+
query?: never;
|
|
3301
|
+
url: "/v1/project-handles/{handle}";
|
|
3302
|
+
};
|
|
3303
|
+
|
|
3304
|
+
export type GetProjectHandleAvailabilityErrors = {
|
|
3305
|
+
/**
|
|
3306
|
+
* The request failed.
|
|
3307
|
+
*/
|
|
3308
|
+
400: ProblemDetails;
|
|
3309
|
+
/**
|
|
3310
|
+
* The request failed.
|
|
3311
|
+
*/
|
|
3312
|
+
401: ProblemDetails;
|
|
3313
|
+
/**
|
|
3314
|
+
* The request failed.
|
|
3315
|
+
*/
|
|
3316
|
+
403: ProblemDetails;
|
|
3317
|
+
/**
|
|
3318
|
+
* The request failed.
|
|
3319
|
+
*/
|
|
3320
|
+
429: ProblemDetails;
|
|
3321
|
+
/**
|
|
3322
|
+
* The request failed.
|
|
3323
|
+
*/
|
|
3324
|
+
503: ProblemDetails;
|
|
3325
|
+
};
|
|
3326
|
+
|
|
3327
|
+
export type GetProjectHandleAvailabilityError =
|
|
3328
|
+
GetProjectHandleAvailabilityErrors[keyof GetProjectHandleAvailabilityErrors];
|
|
3329
|
+
|
|
3330
|
+
export type GetProjectHandleAvailabilityResponses = {
|
|
3331
|
+
/**
|
|
3332
|
+
* Whether the handle is usable, and alternatives when it is not.
|
|
3333
|
+
*/
|
|
3334
|
+
200: ProjectHandleAvailability;
|
|
3335
|
+
};
|
|
3336
|
+
|
|
3337
|
+
export type GetProjectHandleAvailabilityResponse =
|
|
3338
|
+
GetProjectHandleAvailabilityResponses[keyof GetProjectHandleAvailabilityResponses];
|
|
3339
|
+
|
|
3258
3340
|
export type CreateProjectDevAccessTicketData = {
|
|
3259
3341
|
body?: never;
|
|
3260
3342
|
headers?: {
|
|
@@ -3739,6 +3821,80 @@ export type GetCloudflareDnsAuthorizationStatusResponses = {
|
|
|
3739
3821
|
export type GetCloudflareDnsAuthorizationStatusResponse =
|
|
3740
3822
|
GetCloudflareDnsAuthorizationStatusResponses[keyof GetCloudflareDnsAuthorizationStatusResponses];
|
|
3741
3823
|
|
|
3824
|
+
export type ChangeProjectHandleData = {
|
|
3825
|
+
body: {
|
|
3826
|
+
/**
|
|
3827
|
+
* One to five lowercase words of letters and digits.
|
|
3828
|
+
*/
|
|
3829
|
+
handle: string;
|
|
3830
|
+
};
|
|
3831
|
+
headers: {
|
|
3832
|
+
/**
|
|
3833
|
+
* Optional caller-provided correlation identifier.
|
|
3834
|
+
*/
|
|
3835
|
+
"X-Request-Id"?: string;
|
|
3836
|
+
/**
|
|
3837
|
+
* Identifies one mutation and its canonical request payload.
|
|
3838
|
+
*/
|
|
3839
|
+
"Idempotency-Key": string;
|
|
3840
|
+
/**
|
|
3841
|
+
* Exact ETag returned for the current project or deployment state.
|
|
3842
|
+
*/
|
|
3843
|
+
"If-Match": string;
|
|
3844
|
+
};
|
|
3845
|
+
path: {
|
|
3846
|
+
/**
|
|
3847
|
+
* Project identifier.
|
|
3848
|
+
*/
|
|
3849
|
+
project_id: Ulid;
|
|
3850
|
+
};
|
|
3851
|
+
query?: never;
|
|
3852
|
+
url: "/v1/projects/{project_id}/handle";
|
|
3853
|
+
};
|
|
3854
|
+
|
|
3855
|
+
export type ChangeProjectHandleErrors = {
|
|
3856
|
+
/**
|
|
3857
|
+
* The request failed.
|
|
3858
|
+
*/
|
|
3859
|
+
400: ProblemDetails;
|
|
3860
|
+
/**
|
|
3861
|
+
* The request failed.
|
|
3862
|
+
*/
|
|
3863
|
+
401: ProblemDetails;
|
|
3864
|
+
/**
|
|
3865
|
+
* The request failed.
|
|
3866
|
+
*/
|
|
3867
|
+
403: ProblemDetails;
|
|
3868
|
+
/**
|
|
3869
|
+
* The resource does not exist or is not visible to the authenticated principal.
|
|
3870
|
+
*/
|
|
3871
|
+
404: ProblemDetails;
|
|
3872
|
+
/**
|
|
3873
|
+
* The idempotency key was already used with a different canonical request.
|
|
3874
|
+
*/
|
|
3875
|
+
409: IdempotencyConflictProblem;
|
|
3876
|
+
/**
|
|
3877
|
+
* The request failed.
|
|
3878
|
+
*/
|
|
3879
|
+
429: ProblemDetails;
|
|
3880
|
+
/**
|
|
3881
|
+
* The request failed.
|
|
3882
|
+
*/
|
|
3883
|
+
503: ProblemDetails;
|
|
3884
|
+
};
|
|
3885
|
+
|
|
3886
|
+
export type ChangeProjectHandleError = ChangeProjectHandleErrors[keyof ChangeProjectHandleErrors];
|
|
3887
|
+
|
|
3888
|
+
export type ChangeProjectHandleResponses = {
|
|
3889
|
+
/**
|
|
3890
|
+
* The mutation was accepted for asynchronous processing.
|
|
3891
|
+
*/
|
|
3892
|
+
202: Operation;
|
|
3893
|
+
};
|
|
3894
|
+
|
|
3895
|
+
export type ChangeProjectHandleResponse =
|
|
3896
|
+
ChangeProjectHandleResponses[keyof ChangeProjectHandleResponses];
|
|
3897
|
+
|
|
3742
3898
|
export type ConfigureProjectDomainsData = {
|
|
3743
3899
|
body?: never;
|
|
3744
3900
|
headers: {
|