@columnus/shared 0.1.54 → 0.1.55
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/dist/ciPreviewEnv.js +19 -2
- package/dist/ciPreviewEnv.js.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/previewDeployName.d.ts +0 -7
- package/dist/previewDeployName.js +19 -2
- package/dist/previewDeployName.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sanitized Convex preview deployment name for CI / Coolify preview builds.
|
|
3
|
-
* "/" breaks preview/<name> lookups in Convex deployment references.
|
|
4
|
-
*
|
|
5
|
-
* Coolify preview env vars: COOLIFY_BRANCH, COOLIFY_IS_PREVIEW, COOLIFY_FQDN,
|
|
6
|
-
* COOLIFY_URL (BuildKit build secrets).
|
|
7
|
-
*/
|
|
8
1
|
export declare function coolifyHostnameFromEnv(env?: NodeJS.ProcessEnv): string | null;
|
|
9
2
|
/**
|
|
10
3
|
* Browser origin Better Auth expects on server-side OTP probes.
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
// packages/@columnus/shared/src/previewDeployName.ts
|
|
2
|
+
function hostnameFromCoolifyToken(raw) {
|
|
3
|
+
const token = raw.trim();
|
|
4
|
+
if (!token || /^https?:?$/i.test(token)) return null;
|
|
5
|
+
try {
|
|
6
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(token)) {
|
|
7
|
+
return new URL(token).hostname || null;
|
|
8
|
+
}
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const host = token.split("/")[0]?.split(":")[0] ?? "";
|
|
13
|
+
if (!host || !host.includes(".") && host !== "localhost") return null;
|
|
14
|
+
return host;
|
|
15
|
+
}
|
|
2
16
|
function coolifyHostnameFromEnv(env = process.env) {
|
|
3
17
|
const raw = env.COOLIFY_FQDN ?? env.COOLIFY_URL;
|
|
4
18
|
if (!raw) return null;
|
|
5
|
-
const
|
|
6
|
-
|
|
19
|
+
for (const part of raw.split(",")) {
|
|
20
|
+
const host = hostnameFromCoolifyToken(part);
|
|
21
|
+
if (host) return host;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
7
24
|
}
|
|
8
25
|
function resolveTrustedAuthOrigin(env = process.env) {
|
|
9
26
|
const explicit = env.COLUMNUS_AUTH_ORIGIN?.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/previewDeployName.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../src/previewDeployName.ts"],"names":[],"mappings":";AAWA,SAAS,yBAAyB,GAAA,EAA4B;AAC5D,EAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,EAAK;AACvB,EAAA,IAAI,CAAC,KAAA,IAAS,aAAA,CAAc,IAAA,CAAK,KAAK,GAAG,OAAO,IAAA;AAEhD,EAAA,IAAI;AACF,IAAA,IAAI,0BAAA,CAA2B,IAAA,CAAK,KAAK,CAAA,EAAG;AAC1C,MAAA,OAAO,IAAI,GAAA,CAAI,KAAK,CAAA,CAAE,QAAA,IAAY,IAAA;AAAA,IACpC;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AACnD,EAAA,IAAI,CAAC,QAAS,CAAC,IAAA,CAAK,SAAS,GAAG,CAAA,IAAK,IAAA,KAAS,WAAA,EAAc,OAAO,IAAA;AACnE,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,sBAAA,CAAuB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAoB;AAC1F,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,YAAA,IAAgB,GAAA,CAAI,WAAA;AACpC,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,EAAA,KAAA,MAAW,IAAA,IAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,EAAG;AACjC,IAAA,MAAM,IAAA,GAAO,yBAAyB,IAAI,CAAA;AAC1C,IAAA,IAAI,MAAM,OAAO,IAAA;AAAA,EACnB;AACA,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,wBAAA,CAAyB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAyB;AACjG,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,oBAAA,EAAsB,IAAA,EAAK;AAChD,EAAA,IAAI,QAAA,EAAU,OAAO,QAAA,CAAS,OAAA,CAAQ,OAAO,EAAE,CAAA;AAE/C,EAAA,MAAM,IAAA,GAAO,uBAAuB,GAAG,CAAA;AACvC,EAAA,IAAI,IAAA,EAAM,OAAO,CAAA,QAAA,EAAW,IAAI,CAAA,CAAA;AAEhC,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,QAAA,EAAU,IAAA,EAAK;AACnC,EAAA,IAAI,OAAA,IAAW,CAAC,yBAAA,CAA0B,IAAA,CAAK,OAAO,CAAA,EAAG;AACvD,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,gBAAA,CAAiB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAc;AAC9E,EAAA,IAAI,GAAA,CAAI,UAAA,KAAe,MAAA,IAAU,GAAA,CAAI,uBAAuB,MAAA,EAAQ;AAClE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAA,GAAO,uBAAuB,GAAG,CAAA;AAEvC,EAAA,OAAO,OAAA,CAAQ,IAAA,IAAQ,oCAAA,CAAqC,IAAA,CAAK,IAAI,CAAC,CAAA;AACxE;AAEA,IAAM,mBAAA,GAAsB,sBAAA;AAC5B,IAAM,kBAAA,GAAqB,sCAAA;AAGpB,SAAS,kBAAA,CAAmB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAoB;AACtF,EAAA,MAAM,IAAA,GAAO,uBAAuB,GAAG,CAAA;AACvC,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,IAAA,CAAK,IAAI,IAAI,CAAC,CAAA;AAClD,IAAA,IAAI,UAAU,OAAO,QAAA;AAAA,EACvB;AAEA,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,cAAA,IAAkB,GAAA,CAAI,UAAA;AACzC,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,aAAa,mBAAA,CAAoB,IAAA,CAAK,qBAAqB,MAAM,CAAC,IAAI,CAAC,CAAA;AAC7E,IAAA,IAAI,YAAY,OAAO,UAAA;AAAA,EACzB;AAEA,EAAA,OAAO,IAAA;AACT;AAMO,SAAS,oBAAA,CAAqB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAoB;AACxF,EAAA,IAAI,GAAA,CAAI,eAAA,EAAiB,OAAO,oBAAA,CAAqB,IAAI,eAAe,CAAA;AAExE,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,cAAA,IAAkB,GAAA,CAAI,UAAA;AACzC,EAAA,MAAM,IAAA,GAAO,mBAAmB,GAAG,CAAA;AACnC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,IAAA,GAAO,CAAA,QAAA,EAAW,IAAI,CAAA,CAAA,GAAK,IAAA;AAAA,EACpC;AAEA,EAAA,MAAM,QAAA,GAAW,qBAAqB,MAAM,CAAA;AAC5C,EAAA,IAAI,mBAAA,CAAoB,IAAA,CAAK,QAAQ,CAAA,EAAG;AACtC,IAAA,IAAI,IAAA,EAAM,OAAO,CAAA,QAAA,EAAW,IAAI,CAAA,CAAA;AAAA,EAClC;AAEA,EAAA,IAAA,CAAK,QAAA,KAAa,MAAA,IAAU,QAAA,KAAa,QAAA,KAAa,IAAA,EAAM;AAC1D,IAAA,OAAO,WAAW,IAAI,CAAA,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,QAAA;AACT;AAGA,SAAS,qBAAqB,MAAA,EAAwB;AACpD,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA;AAChC,EAAA,OAAO,QAAQ,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,GAAI,MAAA;AAC9C;AAEO,SAAS,0BAA0B,MAAA,EAAwB;AAChE,EAAA,OAAO,oBAAA,CAAqB,MAAM,CAAA,CAAE,OAAA,CAAQ,OAAO,GAAG,CAAA;AACxD;AAGO,SAAS,2BAA2B,IAAA,EAAsB;AAC/D,EAAA,OAAO,yBAAA,CAA0B,IAAA,CAAK,IAAA,EAAM,CAAA;AAC9C;AAEO,SAAS,mBAAA,CAAoB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAoB;AACvF,EAAA,IAAI,CAAC,gBAAA,CAAiB,GAAG,CAAA,EAAG,OAAO,IAAA;AAEnC,EAAA,MAAM,MAAA,GAAS,qBAAqB,GAAG,CAAA;AACvC,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,EAAA,OAAO,0BAA0B,MAAM,CAAA;AACzC;AAGO,IAAM,2BAAA,GACX;AAEK,SAAS,2BAA2B,KAAA,EAAoC;AAC7E,EAAA,OAAO,KAAA,IAAS,IAAA,IAAQ,2BAAA,CAA4B,IAAA,CAAK,KAAK,CAAA;AAChE;AAGO,SAAS,yBAAyB,KAAA,EAAoC;AAC3E,EAAA,IAAI,KAAA,IAAS,MAAM,OAAO,KAAA;AAC1B,EAAA,IAAI,0BAAA,CAA2B,KAAK,CAAA,EAAG,OAAO,IAAA;AAC9C,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,iBAAiB,CAAA,EAAG,OAAO,IAAA;AAC9C,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,6BAA6B,CAAA,EAAG,OAAO,IAAA;AAC1D,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,2BAA2B,CAAA,EAAG,OAAO,IAAA;AACxD,EAAA,OACE,KAAA,CAAM,QAAA,CAAS,oBAAoB,CAAA,IACnC,KAAA,CAAM,SAAS,yBAAyB,CAAA,IACxC,KAAA,CAAM,QAAA,CAAS,0BAA0B,CAAA;AAE7C","file":"previewDeployName.js","sourcesContent":["/**\n * Sanitized Convex preview deployment name for CI / Coolify preview builds.\n * \"/\" breaks preview/<name> lookups in Convex deployment references.\n *\n * Coolify preview env vars: COOLIFY_BRANCH, COOLIFY_IS_PREVIEW, COOLIFY_FQDN,\n * COOLIFY_URL (BuildKit build secrets).\n *\n * Production Coolify often injects a comma-separated FQDN/URL list\n * (`app.columnus.app,bro.columnus.app,…`). Take the first valid hostname —\n * Better Auth Origin must be a single origin, not the whole list.\n */\nfunction hostnameFromCoolifyToken(raw: string): string | null {\n const token = raw.trim();\n if (!token || /^https?:?$/i.test(token)) return null;\n\n try {\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(token)) {\n return new URL(token).hostname || null;\n }\n } catch {\n return null;\n }\n\n const host = token.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n if (!host || (!host.includes(\".\") && host !== \"localhost\")) return null;\n return host;\n}\n\nexport function coolifyHostnameFromEnv(env: NodeJS.ProcessEnv = process.env): string | null {\n const raw = env.COOLIFY_FQDN ?? env.COOLIFY_URL;\n if (!raw) return null;\n for (const part of raw.split(\",\")) {\n const host = hostnameFromCoolifyToken(part);\n if (host) return host;\n }\n return null;\n}\n\n/**\n * Browser origin Better Auth expects on server-side OTP probes.\n * Preview configure sets SITE_URL to `https://<coolify-host>`; Origin must match.\n * Coolify often injects `COOLIFY_URL=http://…` — do not use that scheme.\n */\nexport function resolveTrustedAuthOrigin(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const explicit = env.COLUMNUS_AUTH_ORIGIN?.trim();\n if (explicit) return explicit.replace(/\\/$/, \"\");\n\n const host = coolifyHostnameFromEnv(env);\n if (host) return `https://${host}`;\n\n const siteUrl = env.SITE_URL?.trim();\n if (siteUrl && !/\\.convex\\.site(?:\\/|$)/i.test(siteUrl)) {\n return siteUrl.replace(/\\/$/, \"\");\n }\n return undefined;\n}\n\n/** True when Coolify (or CI_PREVIEW) indicates a PR preview Docker build. */\nexport function isCiPreviewBuild(env: NodeJS.ProcessEnv = process.env): boolean {\n if (env.CI_PREVIEW === \"true\" || env.COOLIFY_IS_PREVIEW === \"true\") {\n return true;\n }\n const host = coolifyHostnameFromEnv(env);\n // preview-<pr>, manage-preview-<pr>, deploy-preview-<pr>\n return Boolean(host && /^(?:manage-|deploy-)?preview-\\d+\\./.test(host));\n}\n\nconst PULL_HEAD_BRANCH_RE = /^pull\\/(\\d+)\\/head$/i;\nconst PREVIEW_HOST_PR_RE = /^(?:manage-|deploy-)?preview-(\\d+)\\./;\n\n/** PR id from `preview-<n>.<domain>` / `manage-preview-<n>` hostname or `pull/<n>/head` branch. */\nexport function resolvePreviewPrId(env: NodeJS.ProcessEnv = process.env): string | null {\n const host = coolifyHostnameFromEnv(env);\n if (host) {\n const fromHost = PREVIEW_HOST_PR_RE.exec(host)?.[1];\n if (fromHost) return fromHost;\n }\n\n const branch = env.COOLIFY_BRANCH ?? env.GIT_BRANCH;\n if (branch) {\n const fromBranch = PULL_HEAD_BRANCH_RE.exec(stripQualifiedBranch(branch))?.[1];\n if (fromBranch) return fromBranch;\n }\n\n return null;\n}\n\n/**\n * Resolve the git branch used for Convex `--preview-name`.\n * Coolify often sets COOLIFY_BRANCH to `pull/<n>/head` at runtime (see coollabsio/coolify#9572).\n */\nexport function resolvePreviewBranch(env: NodeJS.ProcessEnv = process.env): string | null {\n if (env.GITHUB_HEAD_REF) return stripQualifiedBranch(env.GITHUB_HEAD_REF);\n\n const branch = env.COOLIFY_BRANCH ?? env.GIT_BRANCH;\n const prId = resolvePreviewPrId(env);\n if (!branch) {\n return prId ? `preview-${prId}` : null;\n }\n\n const stripped = stripQualifiedBranch(branch);\n if (PULL_HEAD_BRANCH_RE.test(stripped)) {\n if (prId) return `preview-${prId}`;\n }\n // Coolify PR apps often leave COOLIFY_BRANCH=main while FQDN is *-preview-<n>.\n if ((stripped === \"main\" || stripped === \"master\") && prId) {\n return `preview-${prId}`;\n }\n return stripped;\n}\n\n/** Strip Coolify/Convex qualified suffixes (e.g. `pull-48-head:pr-48-coolify`). */\nfunction stripQualifiedBranch(branch: string): string {\n const colon = branch.indexOf(\":\");\n return colon > 0 ? branch.slice(0, colon) : branch;\n}\n\nexport function sanitizePreviewDeployName(branch: string): string {\n return stripQualifiedBranch(branch).replace(/\\//g, \"-\");\n}\n\n/** Normalize a preview name from Convex env before `convex deploy --preview-name`. */\nexport function normalizePreviewDeployName(name: string): string {\n return sanitizePreviewDeployName(name.trim());\n}\n\nexport function ciPreviewDeployName(env: NodeJS.ProcessEnv = process.env): string | null {\n if (!isCiPreviewBuild(env)) return null;\n\n const branch = resolvePreviewBranch(env);\n if (!branch) return null;\n return sanitizePreviewDeployName(branch);\n}\n\n/** Stale failures from broken preview deploy before the bridge was live. */\nexport const STALE_ENDPOINT_DEPLOY_ERROR =\n /^deploy endpoint returned (?:200(?: OK)?|500(?: Internal Server Error)?)$/;\n\nexport function isStaleEndpointDeployError(error: string | undefined): boolean {\n return error != null && STALE_ENDPOINT_DEPLOY_ERROR.test(error);\n}\n\n/** Infra failures from a prior broken deploy that a fresh save can retry. */\nexport function isRecoverableDeployError(error: string | undefined): boolean {\n if (error == null) return false;\n if (isStaleEndpointDeployError(error)) return true;\n if (error.includes(\"502 Bad Gateway\")) return true;\n if (error.includes(\"deploy endpoint unreachable\")) return true;\n if (error.includes(\"deploy endpoint timed out\")) return true;\n return (\n error.includes(\"convex/bin/main.js\") ||\n error.includes(\"convex CLI (bin/main.js\") ||\n error.includes(\"convex CLI not available\")\n );\n}\n"]}
|