Skip to content

feat(ci): type-check embedded TS templates#93

Merged
PAMulligan merged 7 commits into
mainfrom
57-add-drizzle-schema-validation-to-ci-workflow
May 14, 2026
Merged

feat(ci): type-check embedded TS templates#93
PAMulligan merged 7 commits into
mainfrom
57-add-drizzle-schema-validation-to-ci-workflow

Conversation

@PAMulligan
Copy link
Copy Markdown
Contributor

Summary

Catches Drizzle / Hono / postgres API regressions in setup-project.sh templates during development rather than after users run the script. Closes #57.

What changed:

  • Extracted the 12 TypeScript heredoc bodies in setup-project.sh to real files under templates/snippets/{shared,cloudflare,node}/. Setup script now uses copy_file calls (-446 lines).
  • Added a small typecheck scaffold at templates/snippets/ (package.json, tsconfig.cloudflare.json, tsconfig.node.json) with deps pinned to match what generated projects install.
  • New CI job Type-check Embedded Templates runs tsc --noEmit against both tsconfigs on every push.
  • Cross-reference comments in setup-project.sh and a new CONTRIBUTING.md section so future contributors keep pnpm add lines and templates/snippets/package.json in sync.

Notable design choices (full rationale in docs/plans/2026-05-14-typecheck-embedded-templates.md):

  • Snippets are canonical, not extracted snapshots. One copy, zero drift. setup-project.sh cps them at runtime; editors give LSP, autocomplete, and formatting for free.
  • Scaffold co-located with snippets (templates/snippets/ not tests/typecheck-templates/). Required for tsc's upward-walk module resolution to find node_modules/.
  • rootDirs in each tsconfig merges shared/src and the respective platform's src into one virtual root. That's what lets node/src/db/ping.ts's import { client } from './client.js' resolve to shared/src/db/client.ts (in a generated project those files are siblings; in the snippet layout they live in different dirs).
  • Cloudflare tsconfig declares both @cloudflare/workers-types and nodeshared/seed.ts uses process.env and runs under tsx (Node), even on Cloudflare-target projects.
  • Test files excluded from typecheck for now — would need vitest types + globals; their runtime correctness is already verified by running them on generated projects.

Test Plan

  • pnpm install --frozen-lockfile && pnpm run typecheck in templates/snippets/ exits 0
  • bash scripts/setup-project.sh /tmp/x --node → 7/7 health tests pass on the generated project
  • bash scripts/setup-project.sh /tmp/x --cloudflare → 7/7 health tests pass on the generated project
  • bash -n scripts/setup-project.sh clean
  • CI: Validate Structure, Node 20 / Node 22 Compatibility, Type-check Embedded Templates (new), Check Markdown Links

Out of scope (follow-ups)

  • Typechecking the snippet test files (templates/snippets/**/tests/) — needs vitest types and vitest/globals configured.
  • Pre-existing template gaps surfaced in earlier smoke tests: templates/shared/tsconfig.json doesn't declare ["types"] and setup-project.sh doesn't install @cloudflare/workers-types for Workers projects. Generated projects still test fine (vitest doesn't typecheck by default), but pnpm typecheck on a freshly-generated project will fail until those are fixed. Separate issue.

🤖 Generated with Claude Code

Paul Mulligan and others added 7 commits May 14, 2026 13:30
Captures the design decisions (snippets as source of truth, setup-project.sh
cp's them at runtime, dedicated CI job typechecks against current dep
versions) and breaks implementation into eight task-scoped commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lifts the 12 .ts heredoc bodies from setup-project.sh into real files
under templates/snippets/{shared,cloudflare,node}/. Content is verbatim
from the heredocs — no rewrites, no behavior change. setup-project.sh
still uses heredocs; the next commit wires it to copy these files.

Layout:

  templates/snippets/
  ├── shared/
  │   ├── src/db/{schema,client,seed}.ts
  │   └── tests/setup.ts
  ├── cloudflare/
  │   ├── src/index.ts
  │   ├── src/db/ping.ts
  │   ├── src/routes/health.ts
  │   └── tests/unit/health.test.ts
  └── node/
      ├── src/index.ts
      ├── src/db/ping.ts
      ├── src/routes/health.ts
      └── tests/unit/health.test.ts

First step toward type-checking embedded templates in CI (#57).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds package.json + two tsconfigs at templates/snippets/ so the snippet
files can be type-checked against the deps the generated projects ship
with. Co-located with the snippets so node_modules sits where tsc's
upward-walk module resolution can find it.

Each tsconfig uses TypeScript's `rootDirs` to merge `shared/src` and the
respective platform's `src` into one virtual root — that's what lets
`node/src/db/ping.ts`'s `import { client } from './client.js'` resolve
to `shared/src/db/client.ts` (in a generated project those files are
siblings; in the snippet layout they live in different platform dirs).

Both tsconfigs declare `["@cloudflare/workers-types", "node"]` types
(Cloudflare) or `["node"]` (Node). Cloudflare needs Node types too
because the shared seed.ts runs under tsx — `process.env`, `process.exit`
are reachable even on Workers projects via the seed CLI.

Local results: `pnpm run typecheck` exits 0 against both tsconfigs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ippets/

Replaces 12 write_file ... << 'EOF' blocks in scripts/setup-project.sh
with copy_file calls pointing at the real .ts files extracted to
templates/snippets/ in the previous commit. Net delta: 446 lines removed
from the shell script.

Generation output is byte-identical to the heredoc version. Verified by
generating both Node and Cloudflare projects from the refactored script:
each produces 7/7 passing health tests on the generated tree.

drizzle.config.ts stays as a heredoc — it's tiny, has no app-code
imports, and its only failure mode would be a drizzle-kit defineConfig
signature change (caught downstream by drizzle-kit's own typecheck if
it ever happens).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a typecheck-templates job that installs the snippet typecheck
scaffold (templates/snippets/package.json) with --frozen-lockfile and
runs tsc --noEmit against both tsconfig.cloudflare.json and
tsconfig.node.json.

This catches type drift between setup-project.sh's templates and the
Drizzle/Hono/postgres APIs the generated projects will actually
install — without needing to run the full setup-project.sh + pnpm
install + pnpm typecheck on a freshly-generated project.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds NOTE comments near setup-project.sh's pnpm add lines pointing at
templates/snippets/package.json. Bumping a dep on one side without the
other is exactly what the typecheck-templates CI job is meant to catch,
but a comment helps future maintainers update both proactively.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documents the new template authoring model:

- TS templates live in templates/snippets/, not in setup-project.sh
  heredocs
- shared/cloudflare/node split matches generation logic
- Bumping deps requires updating templates/snippets/package.json too
- typecheck-templates CI job catches drift; local equivalent is `cd
  templates/snippets && pnpm run typecheck`

Helps future contributors land template changes without surprising
CI failures (#57).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@PAMulligan PAMulligan linked an issue May 14, 2026 that may be closed by this pull request
4 tasks
@github-actions github-actions Bot added area: scripts Automation scripts area: templates Starter templates area: ci-cd CI/CD workflows area: docs Documentation labels May 14, 2026
@PAMulligan PAMulligan self-assigned this May 14, 2026
@PAMulligan PAMulligan moved this from Todo to Done in PMDS Open Source Roadmap May 14, 2026
@PAMulligan PAMulligan merged commit f88f870 into main May 14, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci-cd CI/CD workflows area: docs Documentation area: scripts Automation scripts area: templates Starter templates

Projects

Development

Successfully merging this pull request may close these issues.

Add Drizzle schema validation to CI workflow

1 participant