@amerged/ohmyhost-cli 0.1.13 → 0.1.15
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-ZWAAQEOZ.js → chunk-3BEMNNWB.js} +557 -211
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/apps/product-cli/cli.ts +23 -32
- package/src/apps/product-cli/command.ts +110 -35
- package/src/apps/product-cli/product-api.ts +4 -26
- package/src/apps/product-cli/repository-init.ts +2 -2
- package/src/apps/product-cli/runtime-contract.ts +0 -94
- package/src/packages/contracts/framework-admission.ts +2 -2
- package/src/packages/sdk-ts/generated/index.ts +65 -16
- package/src/packages/sdk-ts/generated/sdk.gen.ts +450 -96
- package/src/packages/sdk-ts/generated/types.gen.ts +662 -166
- package/src/packages/sdk-ts/index.ts +1 -0
- package/src/packages/sdk-ts/managed-mail-response.ts +195 -0
- package/src/packages/sdk-ts/managed-mail.ts +85 -0
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -75,7 +75,6 @@ import {
|
|
|
75
75
|
type PublicEnvironmentSecret,
|
|
76
76
|
parseOperation,
|
|
77
77
|
parseOperationEvent,
|
|
78
|
-
parseProjectMailDomain,
|
|
79
78
|
parseProjectPage,
|
|
80
79
|
parseProjectStatus,
|
|
81
80
|
parseProjectDatabaseQuery,
|
|
@@ -370,9 +369,24 @@ const HELP_USAGE = Object.freeze({
|
|
|
370
369
|
"printf '%s' \"$SECRET_VALUE\" | ohmyhost secret set NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY --stdin [--wait] --json",
|
|
371
370
|
"secret delete":
|
|
372
371
|
"ohmyhost secret delete NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY [--wait] --json",
|
|
372
|
+
"mail setup":
|
|
373
|
+
"ohmyhost mail setup --project ULID --environment ULID --domain DOMAIN --sending true --receiving false --idempotency-key KEY --json",
|
|
374
|
+
"mail status": "ohmyhost mail status --project ULID --environment ULID --json",
|
|
375
|
+
"mail webhook set":
|
|
376
|
+
"ohmyhost mail webhook set --project ULID --environment ULID --url HTTPS_URL --idempotency-key KEY --json",
|
|
377
|
+
"mail webhook verify":
|
|
378
|
+
"ohmyhost mail webhook verify --project ULID --environment ULID --idempotency-key KEY --json",
|
|
379
|
+
"mail webhook disable":
|
|
380
|
+
"ohmyhost mail webhook disable --project ULID --environment ULID --idempotency-key KEY --json",
|
|
381
|
+
"mail messages list":
|
|
382
|
+
"ohmyhost mail messages list --project ULID --environment ULID [--after ULID] --json",
|
|
383
|
+
"mail messages get":
|
|
384
|
+
"ohmyhost mail messages get --project ULID --environment ULID --message ULID --json",
|
|
385
|
+
"mail messages retry":
|
|
386
|
+
"ohmyhost mail messages retry --project ULID --environment ULID --message ULID --idempotency-key KEY --json",
|
|
373
387
|
"mail domain set":
|
|
374
|
-
"ohmyhost mail domain set --project ULID --domain DOMAIN --idempotency-key KEY --json",
|
|
375
|
-
"mail domain status": "ohmyhost mail domain status --project ULID --json",
|
|
388
|
+
"ohmyhost mail domain set --project ULID --environment ULID --domain DOMAIN --sending true --receiving false --idempotency-key KEY --json",
|
|
389
|
+
"mail domain status": "ohmyhost mail domain status --project ULID --environment ULID --json",
|
|
376
390
|
} satisfies Readonly<Record<CustomerCommandLabel, string>>);
|
|
377
391
|
|
|
378
392
|
const HELP_COMMANDS = Object.freeze(
|
|
@@ -807,9 +821,11 @@ export class ProductCli {
|
|
|
807
821
|
if (command.kind === "secret-list") return await this.listEnvironmentSecrets(command, signal);
|
|
808
822
|
if (command.kind === "function-runs") return await this.listFunctionRuns(command, signal);
|
|
809
823
|
if (command.kind === "secret-set") return await this.putEnvironmentSecret(command, signal);
|
|
810
|
-
if (command.kind === "mail
|
|
811
|
-
|
|
812
|
-
|
|
824
|
+
if (command.kind === "managed-mail") {
|
|
825
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
826
|
+
if (!api.managedMail) throw new Error("Mail unavailable");
|
|
827
|
+
return success(command.label, { mail: await api.managedMail(command.request) });
|
|
828
|
+
}
|
|
813
829
|
return await this.deleteEnvironmentSecret(command, signal);
|
|
814
830
|
} catch (error) {
|
|
815
831
|
if (error instanceof UserTokenFileError)
|
|
@@ -1763,30 +1779,6 @@ export class ProductCli {
|
|
|
1763
1779
|
);
|
|
1764
1780
|
}
|
|
1765
1781
|
|
|
1766
|
-
private async configureMailDomain(
|
|
1767
|
-
command: Extract<ProductCliCommand, { kind: "mail-domain-set" }>,
|
|
1768
|
-
signal: AbortSignal,
|
|
1769
|
-
): Promise<CliResult> {
|
|
1770
|
-
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
1771
|
-
const mailDomain = parseProjectMailDomain(
|
|
1772
|
-
await api.configureMailDomain({
|
|
1773
|
-
projectId: command.projectId,
|
|
1774
|
-
domain: command.domain,
|
|
1775
|
-
idempotencyKey: command.idempotencyKey,
|
|
1776
|
-
}),
|
|
1777
|
-
);
|
|
1778
|
-
return success("mail domain set", { status: mailDomain.status, mail_domain: mailDomain });
|
|
1779
|
-
}
|
|
1780
|
-
|
|
1781
|
-
private async getMailDomain(
|
|
1782
|
-
command: Extract<ProductCliCommand, { kind: "mail-domain-status" }>,
|
|
1783
|
-
signal: AbortSignal,
|
|
1784
|
-
): Promise<CliResult> {
|
|
1785
|
-
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
1786
|
-
const mailDomain = parseProjectMailDomain(await api.getMailDomain(command.projectId));
|
|
1787
|
-
return success("mail domain status", { status: mailDomain.status, mail_domain: mailDomain });
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
1782
|
private async waitForOperation(
|
|
1791
1783
|
api: ProductApi,
|
|
1792
1784
|
initial: ReturnType<typeof parseOperation>,
|
|
@@ -2178,8 +2170,7 @@ const parsedCommandName = (command: ProductCliCommand): CommandLabel => {
|
|
|
2178
2170
|
if (command.kind === "function-runs") return "function runs";
|
|
2179
2171
|
if (command.kind === "secret-set") return "secret set";
|
|
2180
2172
|
if (command.kind === "secret-delete") return "secret delete";
|
|
2181
|
-
if (command.kind === "mail
|
|
2182
|
-
if (command.kind === "mail-domain-status") return "mail domain status";
|
|
2173
|
+
if (command.kind === "managed-mail") return command.label;
|
|
2183
2174
|
return command.kind;
|
|
2184
2175
|
};
|
|
2185
2176
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ManagedMailCommand } from "@ohmyhost/sdk-ts";
|
|
1
2
|
import { USER_API_KEY_ID } from "@ohmyhost/contracts/user-api-keys";
|
|
2
3
|
export type ProductCliCommand =
|
|
3
4
|
| {
|
|
@@ -397,15 +398,19 @@ export type ProductCliCommand =
|
|
|
397
398
|
readonly credentialStore: "native";
|
|
398
399
|
}
|
|
399
400
|
| {
|
|
400
|
-
readonly kind: "mail
|
|
401
|
-
readonly
|
|
402
|
-
readonly
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
401
|
+
readonly kind: "managed-mail";
|
|
402
|
+
readonly request: ManagedMailCommand;
|
|
403
|
+
readonly label:
|
|
404
|
+
| "mail domain set"
|
|
405
|
+
| "mail domain status"
|
|
406
|
+
| "mail setup"
|
|
407
|
+
| "mail status"
|
|
408
|
+
| "mail webhook set"
|
|
409
|
+
| "mail webhook verify"
|
|
410
|
+
| "mail webhook disable"
|
|
411
|
+
| "mail messages list"
|
|
412
|
+
| "mail messages get"
|
|
413
|
+
| "mail messages retry";
|
|
409
414
|
readonly credentialStore: "native";
|
|
410
415
|
}
|
|
411
416
|
| {
|
|
@@ -534,6 +539,14 @@ export type RecognizedCommandLabel =
|
|
|
534
539
|
| "function runs"
|
|
535
540
|
| "secret set"
|
|
536
541
|
| "secret delete"
|
|
542
|
+
| "mail setup"
|
|
543
|
+
| "mail status"
|
|
544
|
+
| "mail webhook set"
|
|
545
|
+
| "mail webhook verify"
|
|
546
|
+
| "mail webhook disable"
|
|
547
|
+
| "mail messages list"
|
|
548
|
+
| "mail messages get"
|
|
549
|
+
| "mail messages retry"
|
|
537
550
|
| "mail domain set"
|
|
538
551
|
| "mail domain status";
|
|
539
552
|
|
|
@@ -639,6 +652,20 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
639
652
|
if (values[0] === "delete") return "secret delete";
|
|
640
653
|
}
|
|
641
654
|
if (value === "function" && values[0] === "runs") return "function runs";
|
|
655
|
+
if (value === "mail") {
|
|
656
|
+
if (values[0] === "setup") return "mail setup";
|
|
657
|
+
if (values[0] === "status") return "mail status";
|
|
658
|
+
if (values[0] === "webhook") {
|
|
659
|
+
if (values[1] === "set") return "mail webhook set";
|
|
660
|
+
if (values[1] === "verify") return "mail webhook verify";
|
|
661
|
+
if (values[1] === "disable") return "mail webhook disable";
|
|
662
|
+
}
|
|
663
|
+
if (values[0] === "messages") {
|
|
664
|
+
if (values[1] === "list") return "mail messages list";
|
|
665
|
+
if (values[1] === "get") return "mail messages get";
|
|
666
|
+
if (values[1] === "retry") return "mail messages retry";
|
|
667
|
+
}
|
|
668
|
+
}
|
|
642
669
|
if (value === "mail" && values[0] === "domain") {
|
|
643
670
|
if (values[1] === "set") return "mail domain set";
|
|
644
671
|
if (values[1] === "status") return "mail domain status";
|
|
@@ -1724,34 +1751,82 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1724
1751
|
}
|
|
1725
1752
|
throw new InvalidCommandError();
|
|
1726
1753
|
}
|
|
1727
|
-
if (first === "mail"
|
|
1754
|
+
if (first === "mail") {
|
|
1728
1755
|
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1729
|
-
values.
|
|
1730
|
-
const
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1748
|
-
values.splice(0, 2);
|
|
1749
|
-
const options = parseOptions(values, ["--project"]);
|
|
1750
|
-
return {
|
|
1751
|
-
kind: "mail-domain-status",
|
|
1752
|
-
projectId: options["--project"],
|
|
1753
|
-
credentialStore,
|
|
1756
|
+
const area = values.shift();
|
|
1757
|
+
const sub =
|
|
1758
|
+
area === "webhook" || area === "messages" || area === "domain" ? values.shift() : undefined;
|
|
1759
|
+
const options = parseOptionalOptions(values, [
|
|
1760
|
+
"--project",
|
|
1761
|
+
"--environment",
|
|
1762
|
+
"--domain",
|
|
1763
|
+
"--sending",
|
|
1764
|
+
"--receiving",
|
|
1765
|
+
"--url",
|
|
1766
|
+
"--idempotency-key",
|
|
1767
|
+
"--message",
|
|
1768
|
+
"--after",
|
|
1769
|
+
]);
|
|
1770
|
+
const required = (key: keyof typeof options) => {
|
|
1771
|
+
const value = options[key];
|
|
1772
|
+
if (!value) throw new InvalidCommandError();
|
|
1773
|
+
return value;
|
|
1754
1774
|
};
|
|
1775
|
+
const scope = { projectId: required("--project"), environmentId: required("--environment") };
|
|
1776
|
+
let request: ManagedMailCommand,
|
|
1777
|
+
label: Extract<ProductCliCommand, { kind: "managed-mail" }>["label"];
|
|
1778
|
+
if (area === "setup" || (area === "domain" && sub === "set")) {
|
|
1779
|
+
const sending = required("--sending"),
|
|
1780
|
+
receiving = required("--receiving");
|
|
1781
|
+
if (!["true", "false"].includes(sending) || !["true", "false"].includes(receiving))
|
|
1782
|
+
throw new InvalidCommandError();
|
|
1783
|
+
request = {
|
|
1784
|
+
...scope,
|
|
1785
|
+
action: "configure",
|
|
1786
|
+
domain: required("--domain"),
|
|
1787
|
+
sending: sending === "true",
|
|
1788
|
+
receiving: receiving === "true",
|
|
1789
|
+
idempotencyKey: required("--idempotency-key"),
|
|
1790
|
+
};
|
|
1791
|
+
label = area === "domain" ? "mail domain set" : "mail setup";
|
|
1792
|
+
} else if (area === "status" || (area === "domain" && sub === "status")) {
|
|
1793
|
+
request = { ...scope, action: "status" };
|
|
1794
|
+
label = area === "domain" ? "mail domain status" : "mail status";
|
|
1795
|
+
} else if (area === "webhook" && sub === "set") {
|
|
1796
|
+
request = {
|
|
1797
|
+
...scope,
|
|
1798
|
+
action: "webhook_set",
|
|
1799
|
+
url: required("--url"),
|
|
1800
|
+
idempotencyKey: required("--idempotency-key"),
|
|
1801
|
+
};
|
|
1802
|
+
label = "mail webhook set";
|
|
1803
|
+
} else if (area === "webhook" && (sub === "verify" || sub === "disable")) {
|
|
1804
|
+
request = {
|
|
1805
|
+
...scope,
|
|
1806
|
+
action: sub === "verify" ? "webhook_verify" : "webhook_disable",
|
|
1807
|
+
idempotencyKey: required("--idempotency-key"),
|
|
1808
|
+
};
|
|
1809
|
+
label = sub === "verify" ? "mail webhook verify" : "mail webhook disable";
|
|
1810
|
+
} else if (area === "messages" && sub === "list") {
|
|
1811
|
+
request = {
|
|
1812
|
+
...scope,
|
|
1813
|
+
action: "messages_list",
|
|
1814
|
+
...(options["--after"] ? { after: options["--after"] } : {}),
|
|
1815
|
+
};
|
|
1816
|
+
label = "mail messages list";
|
|
1817
|
+
} else if (area === "messages" && sub === "get") {
|
|
1818
|
+
request = { ...scope, action: "message_get", messageId: required("--message") };
|
|
1819
|
+
label = "mail messages get";
|
|
1820
|
+
} else if (area === "messages" && sub === "retry") {
|
|
1821
|
+
request = {
|
|
1822
|
+
...scope,
|
|
1823
|
+
action: "message_retry",
|
|
1824
|
+
messageId: required("--message"),
|
|
1825
|
+
idempotencyKey: required("--idempotency-key"),
|
|
1826
|
+
};
|
|
1827
|
+
label = "mail messages retry";
|
|
1828
|
+
} else throw new InvalidCommandError();
|
|
1829
|
+
return { kind: "managed-mail", request, label, credentialStore };
|
|
1755
1830
|
}
|
|
1756
1831
|
throw new InvalidCommandError();
|
|
1757
1832
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { executeManagedMail, type ManagedMailCommand } from "@ohmyhost/sdk-ts";
|
|
1
2
|
import {
|
|
2
3
|
assertProjectDatabaseAccess,
|
|
3
4
|
assertProjectDatabaseAccessCredential,
|
|
@@ -53,7 +54,6 @@ import {
|
|
|
53
54
|
type ProjectCreditBudget,
|
|
54
55
|
applyPaidProjectDomain,
|
|
55
56
|
configureProjectDomains,
|
|
56
|
-
configureProjectMailDomain,
|
|
57
57
|
configureProjectSourceAutoDeploy,
|
|
58
58
|
createCloudflareDnsAuthorization,
|
|
59
59
|
createProjectDevAccessTicket,
|
|
@@ -74,7 +74,6 @@ import {
|
|
|
74
74
|
getAccountProfile,
|
|
75
75
|
getCurrentIdentity,
|
|
76
76
|
getDeployment,
|
|
77
|
-
getProjectMailDomain,
|
|
78
77
|
getProjectSourceAutoDeploy,
|
|
79
78
|
getProjectStatus,
|
|
80
79
|
getPaidProjectDomain,
|
|
@@ -113,7 +112,6 @@ import {
|
|
|
113
112
|
type DeleteEnvironmentSecretResult,
|
|
114
113
|
type OhMyHostClient,
|
|
115
114
|
type ProviderReconciliationAttempt,
|
|
116
|
-
type ProjectMailDomain,
|
|
117
115
|
type CurrentIdentity,
|
|
118
116
|
type DevAccessTicket,
|
|
119
117
|
type ProjectPage,
|
|
@@ -375,12 +373,7 @@ export interface ProductApi {
|
|
|
375
373
|
readonly name: string;
|
|
376
374
|
readonly idempotencyKey: string;
|
|
377
375
|
}): Promise<DeleteEnvironmentSecretResult>;
|
|
378
|
-
|
|
379
|
-
readonly projectId: string;
|
|
380
|
-
readonly domain: string;
|
|
381
|
-
readonly idempotencyKey: string;
|
|
382
|
-
}): Promise<ProjectMailDomain>;
|
|
383
|
-
getMailDomain(projectId: string): Promise<ProjectMailDomain>;
|
|
376
|
+
managedMail?(input: ManagedMailCommand): Promise<unknown>;
|
|
384
377
|
}
|
|
385
378
|
|
|
386
379
|
export class GeneratedSdkProductApi implements ProductApi {
|
|
@@ -1094,22 +1087,7 @@ export class GeneratedSdkProductApi implements ProductApi {
|
|
|
1094
1087
|
);
|
|
1095
1088
|
}
|
|
1096
1089
|
|
|
1097
|
-
public
|
|
1098
|
-
|
|
1099
|
-
readonly domain: string;
|
|
1100
|
-
readonly idempotencyKey: string;
|
|
1101
|
-
}): Promise<ProjectMailDomain> {
|
|
1102
|
-
return configureProjectMailDomain(
|
|
1103
|
-
{
|
|
1104
|
-
"Idempotency-Key": input.idempotencyKey,
|
|
1105
|
-
project_id: input.projectId,
|
|
1106
|
-
configureProjectMailDomainRequest: { domain: input.domain },
|
|
1107
|
-
},
|
|
1108
|
-
{ client: this.#client },
|
|
1109
|
-
);
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
public async getMailDomain(projectId: string): Promise<ProjectMailDomain> {
|
|
1113
|
-
return getProjectMailDomain({ project_id: projectId }, { client: this.#client });
|
|
1090
|
+
public managedMail(input: ManagedMailCommand) {
|
|
1091
|
+
return executeManagedMail(this.#client, input);
|
|
1114
1092
|
}
|
|
1115
1093
|
}
|
|
@@ -50,7 +50,7 @@ const MAXIMUM_SOURCE_BYTES = 2 * 1024 * 1024;
|
|
|
50
50
|
const SOURCE_MODULE_PATTERN = /\.(?:[cm]?[jt]s|[jt]sx)$/u;
|
|
51
51
|
const STORAGE_CLIENT_CALL_PATTERN = /\bcreatePrivateStorageClient\s*\(/u;
|
|
52
52
|
// Both database mistakes of 2026-09-18 are visible in the source before anything is built: one read
|
|
53
|
-
// a
|
|
53
|
+
// a retired database binding, the other opened a socket driver. Neither can work in a customer Worker, so
|
|
54
54
|
// naming them here costs a customer minutes instead of a deployment that fails its health check.
|
|
55
55
|
const DATABASE_PRIVATE_BINDING_PATTERN =
|
|
56
56
|
/\bHYPERDRIVE\b|\bconnectionString\b|\bDATABASE_URL\b|postgres(?:ql)?:\/\//u;
|
|
@@ -549,7 +549,7 @@ async function databaseContractBlockers(
|
|
|
549
549
|
if (DATABASE_PRIVATE_BINDING_PATTERN.test(source)) {
|
|
550
550
|
blockers.push({
|
|
551
551
|
code: "database_binding_private",
|
|
552
|
-
message: `${path} reaches for a managed database connection string.
|
|
552
|
+
message: `${path} reaches for a managed database connection string. HYPERDRIVE is retired; DATABASE_URL and postgres:// URLs never reach a customer Worker. Call the database with createPrivateDatabaseClient from "@ohmyhost/customer-runtime/database".`,
|
|
553
553
|
});
|
|
554
554
|
}
|
|
555
555
|
if (DATABASE_SOCKET_DRIVER_PATTERN.test(source)) {
|
|
@@ -1304,100 +1304,6 @@ function validDelivery(input: Readonly<Record<string, unknown>>): boolean {
|
|
|
1304
1304
|
);
|
|
1305
1305
|
}
|
|
1306
1306
|
|
|
1307
|
-
export type PublicProjectMailDomain =
|
|
1308
|
-
| Readonly<{ domain: string; status: "configured"; configured_at: string }>
|
|
1309
|
-
| Readonly<{
|
|
1310
|
-
domain: string;
|
|
1311
|
-
status: "delegation_required" | "ready" | "verification_pending" | "verification_failed";
|
|
1312
|
-
observed_at?: string;
|
|
1313
|
-
verification_issue?:
|
|
1314
|
-
| "identity_missing"
|
|
1315
|
-
| "identity_verification_failed"
|
|
1316
|
-
| "dkim_verification_failed"
|
|
1317
|
-
| "dkim_records_changed"
|
|
1318
|
-
| "tenant_association_missing"
|
|
1319
|
-
| null;
|
|
1320
|
-
next_check_after_seconds?: 3600 | null;
|
|
1321
|
-
configured_at: string;
|
|
1322
|
-
name_servers: readonly [string, string, string, string];
|
|
1323
|
-
change_id: string;
|
|
1324
|
-
}>;
|
|
1325
|
-
|
|
1326
|
-
export const parseProjectMailDomain = (value: unknown): PublicProjectMailDomain => {
|
|
1327
|
-
const input = exactRecord(value, [
|
|
1328
|
-
"domain",
|
|
1329
|
-
"status",
|
|
1330
|
-
"configured_at",
|
|
1331
|
-
"name_servers",
|
|
1332
|
-
"change_id",
|
|
1333
|
-
"observed_at",
|
|
1334
|
-
"verification_issue",
|
|
1335
|
-
"next_check_after_seconds",
|
|
1336
|
-
]);
|
|
1337
|
-
if (
|
|
1338
|
-
typeof input["domain"] !== "string" ||
|
|
1339
|
-
!/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/u.test(
|
|
1340
|
-
input["domain"],
|
|
1341
|
-
) ||
|
|
1342
|
-
!isIsoInstant(input["configured_at"])
|
|
1343
|
-
) {
|
|
1344
|
-
throw new ResponseContractError();
|
|
1345
|
-
}
|
|
1346
|
-
if (input["status"] === "configured") {
|
|
1347
|
-
if (
|
|
1348
|
-
input["name_servers"] !== undefined ||
|
|
1349
|
-
input["change_id"] !== undefined ||
|
|
1350
|
-
input["observed_at"] !== undefined ||
|
|
1351
|
-
input["verification_issue"] !== undefined ||
|
|
1352
|
-
input["next_check_after_seconds"] !== undefined
|
|
1353
|
-
) {
|
|
1354
|
-
throw new ResponseContractError();
|
|
1355
|
-
}
|
|
1356
|
-
return input as unknown as PublicProjectMailDomain;
|
|
1357
|
-
}
|
|
1358
|
-
if (
|
|
1359
|
-
!["delegation_required", "ready", "verification_pending", "verification_failed"].includes(
|
|
1360
|
-
String(input["status"]),
|
|
1361
|
-
) ||
|
|
1362
|
-
!Array.isArray(input["name_servers"]) ||
|
|
1363
|
-
input["name_servers"].length !== 4 ||
|
|
1364
|
-
new Set(input["name_servers"]).size !== 4 ||
|
|
1365
|
-
input["name_servers"].some(
|
|
1366
|
-
(nameServer) =>
|
|
1367
|
-
typeof nameServer !== "string" ||
|
|
1368
|
-
!/^ns-[0-9]{1,4}\.awsdns-[0-9]{1,2}\.(?:com|net|org|co\.uk)$/u.test(nameServer),
|
|
1369
|
-
) ||
|
|
1370
|
-
typeof input["change_id"] !== "string" ||
|
|
1371
|
-
!/^C[A-Z0-9]{8,31}$/u.test(input["change_id"])
|
|
1372
|
-
) {
|
|
1373
|
-
throw new ResponseContractError();
|
|
1374
|
-
}
|
|
1375
|
-
if (input["observed_at"] !== undefined) {
|
|
1376
|
-
if (
|
|
1377
|
-
![
|
|
1378
|
-
null,
|
|
1379
|
-
"identity_missing",
|
|
1380
|
-
"identity_verification_failed",
|
|
1381
|
-
"dkim_verification_failed",
|
|
1382
|
-
"dkim_records_changed",
|
|
1383
|
-
"tenant_association_missing",
|
|
1384
|
-
].includes(input["verification_issue"] as string | null)
|
|
1385
|
-
)
|
|
1386
|
-
throw new ResponseContractError();
|
|
1387
|
-
if (
|
|
1388
|
-
!isIsoInstant(input["observed_at"]) ||
|
|
1389
|
-
input["next_check_after_seconds"] !== (input["status"] === "ready" ? null : 3600)
|
|
1390
|
-
)
|
|
1391
|
-
throw new ResponseContractError();
|
|
1392
|
-
} else if (
|
|
1393
|
-
input["next_check_after_seconds"] !== undefined ||
|
|
1394
|
-
input["verification_issue"] !== undefined ||
|
|
1395
|
-
["verification_pending", "verification_failed"].includes(String(input["status"]))
|
|
1396
|
-
)
|
|
1397
|
-
throw new ResponseContractError();
|
|
1398
|
-
return input as unknown as PublicProjectMailDomain;
|
|
1399
|
-
};
|
|
1400
|
-
|
|
1401
1307
|
export const parseDeploymentPlan = (value: unknown): Readonly<Record<string, unknown>> => {
|
|
1402
1308
|
const input = exactRecord(value, [
|
|
1403
1309
|
"id",
|
|
@@ -208,9 +208,9 @@ const FRAMEWORK_CONVERSION_DETAILS: Readonly<
|
|
|
208
208
|
> = Object.freeze({
|
|
209
209
|
database_binding_private: Object.freeze({
|
|
210
210
|
render: (path: string) =>
|
|
211
|
-
`"${path}" reads a managed database connection string.
|
|
211
|
+
`"${path}" reads a managed database connection string. HYPERDRIVE is retired; DATABASE_URL and postgres:// URLs never reach a customer Worker. Call the database with createPrivateDatabaseClient from "@ohmyhost/customer-runtime/database". Commit the change, then plan again.`,
|
|
212
212
|
pattern:
|
|
213
|
-
/^"([^"]+)" reads a managed database connection string\.
|
|
213
|
+
/^"([^"]+)" reads a managed database connection string\. HYPERDRIVE is retired; DATABASE_URL and postgres:\/\/ URLs never reach a customer Worker\. Call the database with createPrivateDatabaseClient from "@ohmyhost\/customer-runtime\/database"\. Commit the change, then plan again\.$/u,
|
|
214
214
|
}),
|
|
215
215
|
database_driver_unsupported: Object.freeze({
|
|
216
216
|
render: (path: string) =>
|