@amerged/ohmyhost-cli 0.1.26 → 0.1.27

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @amerged/ohmyhost-cli
2
2
 
3
- ohmyho.st cli client, version 0.1.26.
3
+ ohmyho.st cli client, version 0.1.27.
4
4
 
5
5
  ```sh
6
6
  npm install --global @amerged/ohmyhost-cli
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-YMVBC7UB.js";
5
+ } from "./chunk-KTRUF6C5.js";
6
6
  import "./chunk-7D2RFLWM.js";
7
7
 
8
8
  // apps/product-cli/dist/bin.js
@@ -17002,6 +17002,19 @@ function hasControlCharacter(value, multiline) {
17002
17002
 
17003
17003
  // packages/contracts/dist/framework-build-script.mjs
17004
17004
  var PINNED_BUN_VERSION = "1.2.22";
17005
+ function isAdmittedNextVersion(version2) {
17006
+ if (typeof version2 !== "string")
17007
+ return false;
17008
+ const match = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/u.exec(version2);
17009
+ if (match === null)
17010
+ return false;
17011
+ const major = Number(match[1]);
17012
+ const minor = Number(match[2]);
17013
+ const patch = Number(match[3]);
17014
+ if (![major, minor, patch].every(Number.isSafeInteger))
17015
+ return false;
17016
+ return major === 15 && minor === 5 && patch >= 26 || major === 16 && minor === 3 && patch >= 6 && patch <= 7;
17017
+ }
17005
17018
  var TYPESCRIPT_BUILD_STAGE = /^tsc(?:[ \t]+(?:--noEmit|-b|--build))?$/u;
17006
17019
  function isAdmittedFrameworkBuildScript(framework, script) {
17007
17020
  if (typeof script !== "string")
@@ -17110,7 +17123,7 @@ function resolveFrameworkConfig(basename2, files) {
17110
17123
  var VERIFIED_VERSIONS = Object.freeze({
17111
17124
  vite: /* @__PURE__ */ new Set(["5.4.21", "8.0.16", "8.2.2"]),
17112
17125
  "tanstack-start": /* @__PURE__ */ new Set(["1.168.26", "1.168.49"]),
17113
- nextjs: /* @__PURE__ */ new Set(["15.5.23", "16.3.2"])
17126
+ nextjs: /* @__PURE__ */ new Set(["15.5.26", "16.3.7"])
17114
17127
  });
17115
17128
  function classifyFrameworkVersion(framework, version2) {
17116
17129
  const parsed = parseVersionSpec(version2);
@@ -17139,7 +17152,7 @@ function insideAdmittedWindow(framework, version2) {
17139
17152
  case "tanstack-start":
17140
17153
  return compareVersions(version2, [1, 168, 26]) >= 0 && compareVersions(version2, [1, 168, 49]) <= 0;
17141
17154
  case "nextjs":
17142
- return version2[0] === 15 && version2[1] === 5 || compareVersions(version2, [16, 0, 0]) >= 0 && compareVersions(version2, [16, 3, 4]) <= 0;
17155
+ return isAdmittedNextVersion(version2.join("."));
17143
17156
  }
17144
17157
  }
17145
17158
  function compareVersions(left, right) {
@@ -17976,6 +17989,7 @@ var parsePaidDomain = (value) => {
17976
17989
  const records2 = input["validation_records"];
17977
17990
  if (![
17978
17991
  "not_configured",
17992
+ "awaiting_deployment",
17979
17993
  "pending",
17980
17994
  "active",
17981
17995
  "reconciliation_required",
@@ -17986,7 +18000,7 @@ var parsePaidDomain = (value) => {
17986
18000
  "paid_plan_required",
17987
18001
  "insufficient_organization_credits",
17988
18002
  "project_budget_exceeded"
17989
- ].includes(input["suspension_reason"]) || status === "suspended" !== (input["suspension_reason"] !== null) || status === "suspended" && input["url"] !== null || input["environment"] !== "prod" || !isSaasCnameTarget(input["cname_target"]) || hostname !== null && !isPaidHostname(hostname) || input["custom_hostname_status"] !== null && typeof input["custom_hostname_status"] !== "string" || input["ssl_status"] !== null && typeof input["ssl_status"] !== "string" || !Array.isArray(records2) || records2.length > 16 || !records2.every(isPaidValidationRecord) || input["url"] !== null && input["url"] !== `https://${String(hostname)}`) {
18003
+ ].includes(input["suspension_reason"]) || status === "suspended" !== (input["suspension_reason"] !== null) || status === "suspended" && input["url"] !== null || input["environment"] !== "prod" || !isSaasCnameTarget(input["cname_target"]) || hostname !== null && !isPaidHostname(hostname) || input["custom_hostname_status"] !== null && typeof input["custom_hostname_status"] !== "string" || input["ssl_status"] !== null && typeof input["ssl_status"] !== "string" || !Array.isArray(records2) || records2.length > 16 || !records2.every(isPaidValidationRecord) || input["url"] !== null && input["url"] !== `https://${String(hostname)}` || status === "awaiting_deployment" && (hostname === null || input["custom_hostname_status"] !== null || input["ssl_status"] !== null || input["url"] !== null || records2.length !== 0)) {
17990
18004
  throw new ResponseContractError();
17991
18005
  }
17992
18006
  return input;
@@ -18947,7 +18961,7 @@ function exact2(v, keys) {
18947
18961
  // apps/product-cli/package.json
18948
18962
  var package_default = {
18949
18963
  name: "@ohmyhost/product-cli",
18950
- version: "0.1.26",
18964
+ version: "0.1.27",
18951
18965
  private: true,
18952
18966
  ohmyhost: {
18953
18967
  deployment: "production",
@@ -25868,7 +25882,7 @@ function repositoryBlockers(packageJson, framework, nextStandaloneOutput, tanSta
25868
25882
  const unsupported = compatibility.frameworks.filter((entry) => entry.classification === "unsupported").map((entry) => `${FRAMEWORK_PACKAGE[entry.framework]}@${entry.version || "missing"}`).join(", ");
25869
25883
  blockers.push({
25870
25884
  code: "framework_version_unsupported",
25871
- message: `${unsupported} is outside the versions ohmyho.st builds: next 15.5.x or 16.0.0\u201316.3.4, vite 5.4.0\u20138.2.2, @tanstack/react-start 1.168.26\u20131.168.49, as an exact version or a ^ or ~ range whose base version is inside. Pin a version in that range in package.json, update the lockfile, commit and push.`
25885
+ message: `${unsupported} is outside the versions ohmyho.st builds: next 15.5.26+ (15.5.x) or 16.3.6\u201316.3.7, vite 5.4.0\u20138.2.2, @tanstack/react-start 1.168.26\u20131.168.49, as an exact version or a ^ or ~ range whose base version is inside. Pin a version in that range in package.json, update the lockfile, commit and push.`
25872
25886
  });
25873
25887
  }
25874
25888
  const scripts = packageJson["scripts"];
@@ -25906,7 +25920,7 @@ function repositoryBlockers(packageJson, framework, nextStandaloneOutput, tanSta
25906
25920
  if (!nextConfigured) {
25907
25921
  blockers.push({
25908
25922
  code: "next_adapter_unconfigured",
25909
- message: 'Next.js needs scripts.build exactly "next build" or "next build --webpack", react and react-dom at exact versions such as "19.1.0" (no ^ or ~), next within 15.5.x or 16.0.0\u201316.3.4, and exactly one next.config.js, .mjs or .ts, with at most one open-next.config file. ohmyho.st adds the OpenNext build itself; do not make it the build script.'
25923
+ message: 'Next.js needs scripts.build exactly "next build" or "next build --webpack", react and react-dom at exact versions such as "19.1.0" (no ^ or ~), next within 15.5.26+ (15.5.x) or 16.3.6\u201316.3.7, and exactly one next.config.js, .mjs or .ts, with at most one open-next.config file. ohmyho.st adds the OpenNext build itself; do not make it the build script.'
25910
25924
  });
25911
25925
  }
25912
25926
  }
package/dist/index.js CHANGED
@@ -86,7 +86,7 @@ import {
86
86
  selectWorkspace,
87
87
  verifiedUserId,
88
88
  workspaceOf
89
- } from "./chunk-YMVBC7UB.js";
89
+ } from "./chunk-KTRUF6C5.js";
90
90
  import {
91
91
  CredentialStoreIntegrityError,
92
92
  CredentialStoreUnavailableError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amerged/ohmyhost-cli",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohmyhost/product-cli",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "private": true,
5
5
  "ohmyhost": {
6
6
  "deployment": "production",
@@ -1230,7 +1230,7 @@ function repositoryBlockers(
1230
1230
  .join(", ");
1231
1231
  blockers.push({
1232
1232
  code: "framework_version_unsupported",
1233
- message: `${unsupported} is outside the versions ohmyho.st builds: next 15.5.x or 16.0.0–16.3.4, vite 5.4.0–8.2.2, @tanstack/react-start 1.168.26–1.168.49, as an exact version or a ^ or ~ range whose base version is inside. Pin a version in that range in package.json, update the lockfile, commit and push.`,
1233
+ message: `${unsupported} is outside the versions ohmyho.st builds: next 15.5.26+ (15.5.x) or 16.3.6–16.3.7, vite 5.4.0–8.2.2, @tanstack/react-start 1.168.26–1.168.49, as an exact version or a ^ or ~ range whose base version is inside. Pin a version in that range in package.json, update the lockfile, commit and push.`,
1234
1234
  });
1235
1235
  }
1236
1236
  const scripts = packageJson["scripts"];
@@ -1285,7 +1285,7 @@ function repositoryBlockers(
1285
1285
  blockers.push({
1286
1286
  code: "next_adapter_unconfigured",
1287
1287
  message:
1288
- 'Next.js needs scripts.build exactly "next build" or "next build --webpack", react and react-dom at exact versions such as "19.1.0" (no ^ or ~), next within 15.5.x or 16.0.0–16.3.4, and exactly one next.config.js, .mjs or .ts, with at most one open-next.config file. ohmyho.st adds the OpenNext build itself; do not make it the build script.',
1288
+ 'Next.js needs scripts.build exactly "next build" or "next build --webpack", react and react-dom at exact versions such as "19.1.0" (no ^ or ~), next within 15.5.26+ (15.5.x) or 16.3.6–16.3.7, and exactly one next.config.js, .mjs or .ts, with at most one open-next.config file. ohmyho.st adds the OpenNext build itself; do not make it the build script.',
1289
1289
  });
1290
1290
  }
1291
1291
  }
@@ -94,6 +94,7 @@ export interface PublicPaidDomainPlan {
94
94
  export interface PublicPaidDomain {
95
95
  readonly status:
96
96
  | "not_configured"
97
+ | "awaiting_deployment"
97
98
  | "pending"
98
99
  | "active"
99
100
  | "reconciliation_required"
@@ -153,6 +154,7 @@ export const parsePaidDomain = (value: unknown): PublicPaidDomain => {
153
154
  if (
154
155
  ![
155
156
  "not_configured",
157
+ "awaiting_deployment",
156
158
  "pending",
157
159
  "active",
158
160
  "reconciliation_required",
@@ -176,7 +178,13 @@ export const parsePaidDomain = (value: unknown): PublicPaidDomain => {
176
178
  !Array.isArray(records) ||
177
179
  records.length > 16 ||
178
180
  !records.every(isPaidValidationRecord) ||
179
- (input["url"] !== null && input["url"] !== `https://${String(hostname)}`)
181
+ (input["url"] !== null && input["url"] !== `https://${String(hostname)}`) ||
182
+ (status === "awaiting_deployment" &&
183
+ (hostname === null ||
184
+ input["custom_hostname_status"] !== null ||
185
+ input["ssl_status"] !== null ||
186
+ input["url"] !== null ||
187
+ records.length !== 0))
180
188
  ) {
181
189
  throw new ResponseContractError();
182
190
  }
@@ -1,4 +1,4 @@
1
- import { PINNED_BUN_VERSION } from "./framework-build-script.mjs";
1
+ import { isAdmittedNextVersion, PINNED_BUN_VERSION } from "./framework-build-script.mjs";
2
2
  import { managedCustomerAuthDatabaseMessage } from "./customer-auth-admission.js";
3
3
  export { managedCustomerAuthAdmissionIssue } from "./customer-auth-admission.js";
4
4
 
@@ -129,7 +129,7 @@ export interface FrameworkVersionAdmission {
129
129
  const VERIFIED_VERSIONS: Readonly<Record<AdmittedFramework, ReadonlySet<string>>> = Object.freeze({
130
130
  vite: new Set(["5.4.21", "8.0.16", "8.2.2"]),
131
131
  "tanstack-start": new Set(["1.168.26", "1.168.49"]),
132
- nextjs: new Set(["15.5.23", "16.3.2"]),
132
+ nextjs: new Set(["15.5.26", "16.3.7"]),
133
133
  });
134
134
 
135
135
  export function classifyFrameworkVersion(
@@ -173,10 +173,7 @@ function insideAdmittedWindow(framework: AdmittedFramework, version: VersionTupl
173
173
  compareVersions(version, [1, 168, 26]) >= 0 && compareVersions(version, [1, 168, 49]) <= 0
174
174
  );
175
175
  case "nextjs":
176
- return (
177
- (version[0] === 15 && version[1] === 5) ||
178
- (compareVersions(version, [16, 0, 0]) >= 0 && compareVersions(version, [16, 3, 4]) <= 0)
179
- );
176
+ return isAdmittedNextVersion(version.join("."));
180
177
  }
181
178
  }
182
179
 
@@ -1,5 +1,24 @@
1
1
  export const PINNED_BUN_VERSION = "1.2.22";
2
2
 
3
+ /**
4
+ * The installed Next.js release must satisfy the same window as source admission.
5
+ * @param {unknown} version
6
+ * @returns {boolean}
7
+ */
8
+ export function isAdmittedNextVersion(version) {
9
+ if (typeof version !== "string") return false;
10
+ const match = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/u.exec(version);
11
+ if (match === null) return false;
12
+ const major = Number(match[1]);
13
+ const minor = Number(match[2]);
14
+ const patch = Number(match[3]);
15
+ if (![major, minor, patch].every(Number.isSafeInteger)) return false;
16
+ return (
17
+ (major === 15 && minor === 5 && patch >= 26) ||
18
+ (major === 16 && minor === 3 && patch >= 6 && patch <= 7)
19
+ );
20
+ }
21
+
3
22
  const TYPESCRIPT_BUILD_STAGE = /^tsc(?:[ \t]+(?:--noEmit|-b|--build))?$/u;
4
23
 
5
24
  /**
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohmyhost/sdk-ts",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -2560,7 +2560,7 @@ export const configureProjectDomains = <ThrowOnError extends boolean = true>(
2560
2560
  /**
2561
2561
  * Plan one Paid customer-owned hostname
2562
2562
  *
2563
- * The hostname routes to the project's current Prod deployment. A project whose Prod environment has no active deployment returns production_deployment_required (409); deploy to Prod or promote the current Dev deployment, then plan again.
2563
+ * Plan the customer's requested hostname before or after the first Prod deployment. This read-only plan explains declaration, Cloudflare consent and activation; it does not claim the hostname, create provider resources or change DNS.
2564
2564
  */
2565
2565
  export const planPaidProjectDomain = <ThrowOnError extends boolean = true>(
2566
2566
  parameters: {
@@ -2698,7 +2698,7 @@ export const getPaidProjectDomain = <ThrowOnError extends boolean = true>(
2698
2698
  /**
2699
2699
  * Apply one Paid customer-owned hostname
2700
2700
  *
2701
- * Requires Paid access (a Stripe period or a grant) or, for a Free workspace, a project that currently shows the powered-by flag, and no expired credit-exhaustion grace. Returns paid_plan_required otherwise, or insufficient_organization_credits after seven days with no available credits, without provider mutation. Top-ups lift a credit-exhaustion block but never start or extend Paid access. After that check, a project whose Prod environment has no active deployment returns production_deployment_required (409) without claiming the hostname or any provider mutation; a changed request under a used key returns idempotency_key_reused (409).
2701
+ * Requires Paid access (a Stripe period or a grant) or, for a Free workspace, a project that currently shows the powered-by flag, and no expired credit-exhaustion grace. Returns paid_plan_required otherwise, or insufficient_organization_credits after seven days with no available credits, without provider mutation. Top-ups lift a credit-exhaustion block but never start or extend Paid access. Without an active Prod deployment, apply declares the hostname as awaiting_deployment, enabling Cloudflare consent without provider resources, DNS changes or domain charges. After a successful Prod deployment, replay the same hostname and idempotency key to activate it. A changed request under a used key returns idempotency_key_reused (409).
2702
2702
  */
2703
2703
  export const applyPaidProjectDomain = <ThrowOnError extends boolean = true>(
2704
2704
  parameters: {
@@ -351,9 +351,13 @@ export type PaidDomainPlan = {
351
351
  risks: Array<string>;
352
352
  };
353
353
 
354
+ /**
355
+ * awaiting_deployment means the requested hostname is declared but not provisioned. Its hostname is present, suspension_reason, custom_hostname_status, ssl_status and url are null, and validation_records is empty. Authorize Cloudflare, deploy to Prod, then repeat the same apply.
356
+ */
354
357
  export type PaidDomain = {
355
358
  status:
356
359
  | "not_configured"
360
+ | "awaiting_deployment"
357
361
  | "pending"
358
362
  | "active"
359
363
  | "reconciliation_required"
@@ -4686,7 +4690,7 @@ export type PlanPaidProjectDomainError =
4686
4690
 
4687
4691
  export type PlanPaidProjectDomainResponses = {
4688
4692
  /**
4689
- * Manual CNAME instructions and exact provider effects.
4693
+ * The requested hostname, routing target and staged provider effects.
4690
4694
  */
4691
4695
  200: PaidDomainPlan;
4692
4696
  };
@@ -4880,7 +4884,7 @@ export type ApplyPaidProjectDomainError =
4880
4884
 
4881
4885
  export type ApplyPaidProjectDomainResponses = {
4882
4886
  /**
4883
- * Current Cloudflare for SaaS hostname and certificate state.
4887
+ * Declared hostname or current Cloudflare for SaaS hostname and certificate state.
4884
4888
  */
4885
4889
  200: PaidDomain;
4886
4890
  };