Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions src/frontend/ec.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ import { pluginDisableCopy } from './src/expressive-code-plugins/disable-copy.mj

const __dirname = dirname(fileURLToPath(import.meta.url));
const ASPIRE_TYPES_PATH = resolve(__dirname, 'src/data/twoslash/aspire.d.ts');
const aspireTypes = existsSync(ASPIRE_TYPES_PATH)
? readFileSync(ASPIRE_TYPES_PATH, 'utf8')
: '';

if (!aspireTypes) {
// Non-fatal — twoslash blocks that import the SDK will just show `any`.
// Run `pnpm twoslash-types` to refresh.
console.warn('[ec] src/data/twoslash/aspire.d.ts missing — run `pnpm twoslash-types`');
// The bundle is source-controlled (see #741), so a missing file means the
// tree is corrupted — not a normal path. Fail the build rather than silently
// shipping samples that can't resolve `./.modules/aspire.js`.
if (!existsSync(ASPIRE_TYPES_PATH)) {
throw new Error(
`[ec] src/data/twoslash/aspire.d.ts not found at ${ASPIRE_TYPES_PATH}. ` +
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message includes an absolute path, which can leak runner/workspace paths into public CI logs. Consider switching to a relative path in the message (e.g., relative to process.cwd()), while still keeping enough context to debug locally.

Copilot uses AI. Check for mistakes.
'Run `pnpm twoslash-types` to regenerate it from src/data/ts-modules.'
);
}
const aspireTypes = readFileSync(ASPIRE_TYPES_PATH, 'utf8');
Comment on lines +16 to +22
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a check-then-read pattern (TOCTOU). It’s more robust to read the file directly and throw a tailored error if it fails (e.g., wrap readFileSync in a try/catch). This avoids rare edge cases where the file is deleted/moved between existsSync and readFileSync, and keeps the failure mode consistent.

Copilot uses AI. Check for mistakes.

Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the new behavior, an empty (or whitespace-only) aspire.d.ts will still pass and will populate .modules/aspire.ts with empty content, which can re-introduce the ‘silent regression’ this PR is trying to prevent (imports resolve, but types effectively disappear). Consider validating aspireTypes.trim().length > 0 and throwing with a clear message if it’s empty.

Suggested change
if (aspireTypes.trim().length === 0) {
throw new Error(
`[ec] src/data/twoslash/aspire.d.ts is empty at ${ASPIRE_TYPES_PATH}. ` +
'Run `pnpm twoslash-types` to regenerate it from src/data/ts-modules.'
);
}

Copilot uses AI. Check for mistakes.
/** @type {import('@astrojs/starlight/expressive-code').StarlightExpressiveCodeOptions} */
export default {
Expand Down Expand Up @@ -49,15 +51,17 @@ export default {
// an explicit `lib` array breaks those references in the VFS.
},
handbookOptions: {
// Keep type squigglies rendered inline but don't fail the build when
// a sample has unannotated compiler errors — the generated SDK is a
// best-effort shape and docs samples shouldn't need `// @errors` tags.
noErrorValidation: true,
// Fail the build on unannotated TS errors instead of rendering them
// as squigglies in shipped HTML. Blocks that deliberately illustrate
// a compiler error must opt in with `// @errors: <codes>`; otherwise
// an error means the sample (or the generated SDK shape) is wrong
// and should be fixed, not rendered to readers.
noErrorValidation: false,
},
// Virtual files merged into the Twoslash VFS. The Aspire SDK types
// are declared at `.modules/aspire.ts` so docs samples that import
// `'./.modules/aspire.js'` resolve against the real API surface.
extraFiles: aspireTypes ? { '.modules/aspire.ts': aspireTypes } : {},
extraFiles: { '.modules/aspire.ts': aspireTypes },
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the new behavior, an empty (or whitespace-only) aspire.d.ts will still pass and will populate .modules/aspire.ts with empty content, which can re-introduce the ‘silent regression’ this PR is trying to prevent (imports resolve, but types effectively disappear). Consider validating aspireTypes.trim().length > 0 and throwing with a clear message if it’s empty.

Copilot uses AI. Check for mistakes.
},
}),
],
Expand Down
Loading