b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
180 lines
6.7 KiB
TypeScript
180 lines
6.7 KiB
TypeScript
import { execSync } from "node:child_process";
|
|
import { readdirSync, readFileSync } from "node:fs";
|
|
import { relative, resolve as resolvePath } from "node:path";
|
|
|
|
import { defineConfig } from "tsdown";
|
|
|
|
import { routeArtifactName } from "./src/astro/integration/route-naming.ts";
|
|
|
|
const srcDir = resolvePath(import.meta.dirname, "src");
|
|
const TS_EXT = /\.tsx?$/;
|
|
|
|
/**
|
|
* Mirror each entry's path under src/ into dist/, preserving the original
|
|
* filename verbatim. tsdown/rolldown's default name template rewrites `[` and
|
|
* `]` to `_`, which would mangle dynamic-route entrypoints
|
|
* (`[collection]`, `[...path]`) and decouple `emdash/routes/*` resolution from
|
|
* the real filenames. Mirroring keeps dist a 1:1 image of src so route
|
|
* injection resolves entrypoints by their actual paths.
|
|
*/
|
|
function entryFileName(facadeModuleId: string | null, ext: string): string {
|
|
if (facadeModuleId) {
|
|
const rel = relative(srcDir, facadeModuleId);
|
|
if (!rel.startsWith("..")) return routeArtifactName(rel.replace(TS_EXT, "")) + ext;
|
|
}
|
|
return `[name]${ext}`;
|
|
}
|
|
|
|
/**
|
|
* Explicit name -> absolute-path input map for every .ts/.tsx file under
|
|
* src/astro/routes. Fed to rolldown via `inputOptions.input` (an object,
|
|
* resolved literally) rather than tsdown's `entry` (resolved as globs):
|
|
* dynamic-route dirnames like `[collection]` / `[...path]` are glob
|
|
* character-classes, so any glob-based entry silently drops routes nested
|
|
* under a bracketed segment. The map key is the src-relative path (no
|
|
* extension); `entryFileName` turns it back into a 1:1 dist mirror. .astro
|
|
* routes are excluded -- they ship as source for the consumer's Astro build.
|
|
*/
|
|
function routeInputMap(): Record<string, string> {
|
|
const routesDir = resolvePath(srcDir, "astro/routes");
|
|
const map: Record<string, string> = {};
|
|
for (const d of readdirSync(routesDir, { recursive: true, withFileTypes: true })) {
|
|
if (!d.isFile() || !TS_EXT.test(d.name)) continue;
|
|
const abs = resolvePath(d.parentPath, d.name);
|
|
const key = relative(srcDir, abs).replaceAll("\\", "/").replace(TS_EXT, "");
|
|
map[key] = abs;
|
|
}
|
|
return map;
|
|
}
|
|
|
|
function readPackageVersion(): string {
|
|
const parsed: unknown = JSON.parse(readFileSync("package.json", "utf-8"));
|
|
if (
|
|
typeof parsed === "object" &&
|
|
parsed !== null &&
|
|
"version" in parsed &&
|
|
typeof parsed.version === "string"
|
|
) {
|
|
return parsed.version;
|
|
}
|
|
throw new Error("package.json is missing a string `version` field");
|
|
}
|
|
const pkg = { version: readPackageVersion() };
|
|
const commit = (() => {
|
|
try {
|
|
return execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
|
|
} catch {
|
|
return "unknown";
|
|
}
|
|
})();
|
|
|
|
export default defineConfig({
|
|
entry: [
|
|
"src/index.ts",
|
|
// Request context (ALS singleton - must be a separate entry for dedup)
|
|
"src/request-context.ts",
|
|
// Astro integration (build-time)
|
|
"src/astro/index.ts",
|
|
"src/astro/middleware.ts",
|
|
"src/astro/middleware/setup.ts",
|
|
"src/astro/middleware/auth.ts",
|
|
"src/astro/middleware/redirect.ts",
|
|
"src/astro/middleware/request-context.ts",
|
|
"src/astro/types.ts",
|
|
// Database adapters (config-time + runtime via virtual:emdash/dialect)
|
|
"src/db/index.ts",
|
|
"src/db/sqlite.ts",
|
|
"src/db/libsql.ts",
|
|
"src/db/postgres.ts",
|
|
// Query instrumentation (used by first-party adapters like @emdash-cms/cloudflare)
|
|
"src/database/instrumentation.ts",
|
|
// Fail-fast Postgres migration lock (used by @emdash-cms/cloudflare's Hyperdrive adapter)
|
|
"src/database/pg-migration-lock.ts",
|
|
// Storage adapters (runtime - loaded via virtual:emdash/storage)
|
|
"src/storage/local.ts",
|
|
"src/storage/s3.ts",
|
|
// Object-cache memory backend (runtime - loaded via virtual:emdash/object-cache)
|
|
"src/object-cache/memory.ts",
|
|
// Media providers
|
|
"src/media/index.ts",
|
|
"src/media/local-runtime.ts",
|
|
// Image-endpoint helpers (portable) + the Node image endpoint
|
|
"src/media/image-endpoint.ts",
|
|
"src/astro/image-endpoint.ts",
|
|
// Runtime exports (depends on virtual modules - for live.config.ts)
|
|
"src/runtime.ts",
|
|
// Seed engine
|
|
"src/seed/index.ts",
|
|
// CLI
|
|
"src/cli/index.ts",
|
|
// Client (programmatic editing API)
|
|
"src/client/index.ts",
|
|
"src/client/cf-access.ts",
|
|
// SEO helpers
|
|
"src/seo/index.ts",
|
|
// Public page contributions
|
|
"src/page/index.ts",
|
|
// Plugin admin utilities (shared helpers for plugin admin.tsx files)
|
|
"src/plugin-utils.ts",
|
|
// `emdash/plugin` — type-only subpath for sandboxed plugin authors.
|
|
"src/plugin-types.ts",
|
|
// Standard plugin adapter (loaded by virtual:emdash/plugins at runtime)
|
|
"src/plugins/adapt-sandbox-entry.ts",
|
|
// Public source-exported subpaths -- compiled so consumers never
|
|
// type-check our raw .ts (avoids the dual-package identity hazard).
|
|
// `./ui`, `./ui/search` and the `*-admin.tsx` providers stay source:
|
|
// they bridge runtimes the consumer supplies (Astro components,
|
|
// the admin's React + @cloudflare/kumo), which their own build
|
|
// must process.
|
|
"src/api/route-utils.ts",
|
|
"src/api/schemas/index.ts",
|
|
"src/auth/providers/github.ts",
|
|
"src/auth/providers/google.ts",
|
|
// Injected API/page routes are added via inputOptions below (their
|
|
// `[param]` filenames are hostile to tsdown's glob-based `entry`).
|
|
],
|
|
format: "esm",
|
|
dts: true,
|
|
clean: true,
|
|
// Deps are externalized via `external` + package.json deps; nothing is
|
|
// unintentionally bundled. Suppress tsdown's advisory (CI escalates it).
|
|
inlineOnly: false,
|
|
inputOptions: (options) => {
|
|
// tsdown has already normalized the `entry` array into an input record
|
|
// by this hook; we only augment it with the route map.
|
|
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- normalized input record at the inputOptions hook
|
|
options.input = { ...(options.input as Record<string, string>), ...routeInputMap() };
|
|
return options;
|
|
},
|
|
outputOptions: {
|
|
entryFileNames: (chunk) => entryFileName(chunk.facadeModuleId, ".mjs"),
|
|
},
|
|
define: {
|
|
__EMDASH_VERSION__: JSON.stringify(pkg.version),
|
|
__EMDASH_COMMIT__: JSON.stringify(commit),
|
|
},
|
|
// Externalize native modules, dialect-specific packages, and internal shared modules
|
|
external: [
|
|
// Native modules that use __filename
|
|
"better-sqlite3",
|
|
"bindings",
|
|
"file-uri-to-path",
|
|
// Dialect-specific packages
|
|
"@libsql/kysely-libsql",
|
|
"pg",
|
|
// Optional S3 storage deps -- resolved at runtime only when used
|
|
/^@aws-sdk\//,
|
|
// Build tooling (CLI-time dependency with native bindings)
|
|
"tsdown",
|
|
// Self-import: compiled route entrypoints `import ... from "emdash"`,
|
|
// resolved at the consumer's runtime where the package is installed.
|
|
"emdash",
|
|
// Astro virtual modules (astro:assets, astro:middleware, astro:content, ...)
|
|
/^astro:/,
|
|
// .astro components/pages -- compiled by the consumer's Astro build
|
|
/\.astro$/,
|
|
// EmDash virtual modules (resolved at runtime by Vite)
|
|
/^virtual:emdash\//,
|
|
],
|
|
});
|