|
| 1 | +import { execSync } from "node:child_process"; |
1 | 2 | import { existsSync, readFileSync } from "node:fs"; |
2 | 3 | import { chmod, readFile, writeFile } from "node:fs/promises"; |
3 | 4 | import { createRequire } from "node:module"; |
@@ -60,6 +61,39 @@ assertWorkspaceDtsDependencies(); |
60 | 61 | * without declarations, so a source missing from the entry list ships a types |
61 | 62 | * path that does not exist and every consumer's tsc fails with TS7016 (#839). |
62 | 63 | */ |
| 64 | +// The dts emit is per-entry across parallel rolldown-plugin-dts workers; on |
| 65 | +// fresh CI checkouts the ui/auth emit has (rarely, non-deterministically) |
| 66 | +// raced the dependency-types resolution and collapsed the plugin chain to |
| 67 | +// `any` (2026-11-09: red on the first GH attempt, green on rerun with zero |
| 68 | +// source delta). The guard is therefore self-healing: one declarations-only |
| 69 | +// re-emit — serial, no JS bundle — before failing. The build only goes red |
| 70 | +// on persistent collapse, which is a real regression worth a human. |
| 71 | +async function assertAuthClientDtsTypes(): Promise<void> { |
| 72 | + const authDtsPath = join("dist", "ui", "auth.d.mts"); |
| 73 | + const collapsed = async (): Promise<boolean> => |
| 74 | + /declare function createAuthClient\(.*\): any;/.test( |
| 75 | + await readFile(authDtsPath, "utf-8").catch(() => ""), |
| 76 | + ); |
| 77 | + if (!(await collapsed())) return; |
| 78 | + if (process.env.BOS_TS_DOWN_DTS_REEMIT) { |
| 79 | + throw new Error( |
| 80 | + "dist/ui/auth.d.mts emitted createAuthClient(): any after re-emit — the better-auth " + |
| 81 | + "plugin-chain inference collapsed persistently. Check that better-near-auth's dist " + |
| 82 | + "types are built and fresh.", |
| 83 | + ); |
| 84 | + } |
| 85 | + console.warn("[tsdown] ui/auth dts collapsed to any — re-emitting declarations"); |
| 86 | + process.env.BOS_TS_DOWN_DTS_REEMIT = "1"; |
| 87 | + execSync("pnpm exec tsdown --dts", { stdio: "inherit", cwd: import.meta.dirname }); |
| 88 | + if (await collapsed()) { |
| 89 | + throw new Error( |
| 90 | + "dist/ui/auth.d.mts emitted createAuthClient(): any after re-emit — the better-auth " + |
| 91 | + "plugin-chain inference collapsed persistently. Check that better-near-auth's dist " + |
| 92 | + "types are built and fresh.", |
| 93 | + ); |
| 94 | + } |
| 95 | +} |
| 96 | + |
63 | 97 | function assertExportsDistTypesExist() { |
64 | 98 | const manifest = JSON.parse(readFileSync(join(import.meta.dirname, "package.json"), "utf-8")) as { |
65 | 99 | exports?: Record<string, unknown>; |
@@ -177,13 +211,7 @@ export default defineConfig({ |
177 | 211 | }, |
178 | 212 | async onSuccess() { |
179 | 213 | assertExportsDistTypesExist(); |
180 | | - const authDts = await readFile(join("dist", "ui", "auth.d.mts"), "utf-8").catch(() => ""); |
181 | | - if (/declare function createAuthClient\(.*\): any;/.test(authDts)) { |
182 | | - throw new Error( |
183 | | - "dist/ui/auth.d.mts emitted createAuthClient(): any — the better-auth plugin-chain " + |
184 | | - "inference collapsed. Check that better-near-auth's dist types are built and fresh.", |
185 | | - ); |
186 | | - } |
| 214 | + await assertAuthClientDtsTypes(); |
187 | 215 | for (const file of ["cli.mjs", "cli.cjs"]) { |
188 | 216 | const filepath = join("dist", file); |
189 | 217 | try { |
|
0 commit comments