diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45d058d..364d25e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -230,6 +230,35 @@ jobs: run: pnpm exec tsc --noEmit -p tsconfig.lambda.json working-directory: templates/snippets + # Generates a real project per target with setup-project.sh and type-checks + # it. Unlike typecheck-templates this has no lockfile on purpose: it installs + # whatever `pnpm add` resolves today, so a dependency release that breaks + # freshly generated projects (e.g. the TypeScript 6 @types auto-include + # removal, #119) fails here instead of only on user machines. + generated-projects: + name: Generate & Type-check (${{ matrix.platform }}) + runs-on: ubuntu-latest + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + platform: [cloudflare, node, lambda, railway, fly] + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-node@v6 + with: + node-version: 22 + + - run: corepack enable + + - name: Generate project + run: ./scripts/setup-project.sh demo-${{ matrix.platform }} --${{ matrix.platform }} + + - name: Type-check generated project + run: pnpm typecheck + working-directory: demo-${{ matrix.platform }}/api + check-links: name: Check Markdown Links runs-on: ubuntu-latest diff --git a/scripts/setup-project.sh b/scripts/setup-project.sh old mode 100644 new mode 100755 index cb064ec..8f47778 --- a/scripts/setup-project.sh +++ b/scripts/setup-project.sh @@ -124,7 +124,16 @@ make_dirs "$TARGET_DIR/docs" success "Directory structure created." step "Copying shared configuration templates..." -copy_file "$TEMPLATES_DIR/shared/tsconfig.json" "$API_DIR/tsconfig.json" +# TypeScript 6 no longer auto-includes node_modules/@types/*, so each target +# gets a tsconfig.json that opts into its globals via "types" on top of the +# shared base. templates/snippets/tsconfig.*.json extend the same per-target +# files, so the typecheck-templates CI job checks exactly what ships here. +copy_file "$TEMPLATES_DIR/shared/tsconfig.base.json" "$API_DIR/tsconfig.base.json" +if [[ "$PLATFORM" == "cloudflare" ]]; then + copy_file "$TEMPLATES_DIR/shared/tsconfig.cloudflare.json" "$API_DIR/tsconfig.json" +else + copy_file "$TEMPLATES_DIR/shared/tsconfig.node.json" "$API_DIR/tsconfig.json" +fi copy_file "$TEMPLATES_DIR/shared/eslint.config.js" "$API_DIR/eslint.config.js" copy_file "$TEMPLATES_DIR/shared/prettier.config.js" "$API_DIR/prettier.config.js" copy_file "$TEMPLATES_DIR/shared/vitest.config.ts" "$API_DIR/vitest.config.ts" @@ -176,9 +185,12 @@ run_cmd pnpm add hono drizzle-orm postgres zod @hono/zod-validator success "Production dependencies installed." step "Installing dev dependencies..." -# NOTE: @types/node and @cloudflare/workers-types (added per-platform below) -# also live in templates/snippets/package.json — bump in both places. -run_cmd pnpm add -D vitest typescript eslint prettier drizzle-kit @types/node tsx \ +# NOTE: @types/node and @cloudflare/workers-types (added in the cloudflare +# branch below) also live in templates/snippets/package.json — bump in both +# places. typescript is pinned to its major because a new major can change how +# generated projects compile (TS 6 stopped auto-including @types/*); bump it +# deliberately, together with the snippets and the shared tsconfig templates. +run_cmd pnpm add -D vitest typescript@^6 eslint prettier drizzle-kit @types/node tsx \ @eslint/js typescript-eslint @vitest/coverage-v8 success "Dev dependencies installed." @@ -248,7 +260,8 @@ success "Initial source files created." # ---- Platform-specific setup ---- if [[ "$PLATFORM" == "cloudflare" ]]; then step "Setting up Cloudflare Workers..." - run_cmd pnpm add -D wrangler + # @cloudflare/workers-types backs the "types" entry in the cloudflare tsconfig + run_cmd pnpm add -D wrangler @cloudflare/workers-types copy_file "$TEMPLATES_DIR/cloudflare-workers/wrangler.toml" "$API_DIR/wrangler.toml" write_file "$API_DIR/.dev.vars.example" << 'DVEOF' diff --git a/templates/docker/Dockerfile b/templates/docker/Dockerfile index 6639989..fe3bd11 100644 --- a/templates/docker/Dockerfile +++ b/templates/docker/Dockerfile @@ -13,7 +13,7 @@ COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile # Copy source code -COPY tsconfig.json drizzle.config.ts ./ +COPY tsconfig.json tsconfig.base.json drizzle.config.ts ./ COPY src/ ./src/ # Build the application diff --git a/templates/node-server/Dockerfile b/templates/node-server/Dockerfile index 6639989..fe3bd11 100644 --- a/templates/node-server/Dockerfile +++ b/templates/node-server/Dockerfile @@ -13,7 +13,7 @@ COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile # Copy source code -COPY tsconfig.json drizzle.config.ts ./ +COPY tsconfig.json tsconfig.base.json drizzle.config.ts ./ COPY src/ ./src/ # Build the application diff --git a/templates/shared/tsconfig.json b/templates/shared/tsconfig.base.json similarity index 100% rename from templates/shared/tsconfig.json rename to templates/shared/tsconfig.base.json diff --git a/templates/shared/tsconfig.cloudflare.json b/templates/shared/tsconfig.cloudflare.json new file mode 100644 index 0000000..fdeb566 --- /dev/null +++ b/templates/shared/tsconfig.cloudflare.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "types": [ + "@cloudflare/workers-types", + "node" + ] + } +} diff --git a/templates/shared/tsconfig.node.json b/templates/shared/tsconfig.node.json new file mode 100644 index 0000000..14e2c7f --- /dev/null +++ b/templates/shared/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "types": [ + "node" + ] + } +} diff --git a/templates/snippets/tsconfig.cloudflare.json b/templates/snippets/tsconfig.cloudflare.json index 0ac4652..fb0639b 100644 --- a/templates/snippets/tsconfig.cloudflare.json +++ b/templates/snippets/tsconfig.cloudflare.json @@ -1,9 +1,8 @@ { - "extends": "../shared/tsconfig.json", + "extends": "../shared/tsconfig.cloudflare.json", "compilerOptions": { "noEmit": true, "moduleResolution": "bundler", - "types": ["@cloudflare/workers-types", "node"], "rootDir": ".", "rootDirs": ["shared/src", "cloudflare/src"], "paths": {} diff --git a/templates/snippets/tsconfig.lambda.json b/templates/snippets/tsconfig.lambda.json index a9c627e..3abc9a1 100644 --- a/templates/snippets/tsconfig.lambda.json +++ b/templates/snippets/tsconfig.lambda.json @@ -1,9 +1,8 @@ { - "extends": "../shared/tsconfig.json", + "extends": "../shared/tsconfig.node.json", "compilerOptions": { "noEmit": true, "moduleResolution": "bundler", - "types": ["node"], "rootDir": ".", "rootDirs": ["shared/src", "aws-lambda/src"], "paths": {} diff --git a/templates/snippets/tsconfig.node.json b/templates/snippets/tsconfig.node.json index 8899b3e..a2987a0 100644 --- a/templates/snippets/tsconfig.node.json +++ b/templates/snippets/tsconfig.node.json @@ -1,9 +1,8 @@ { - "extends": "../shared/tsconfig.json", + "extends": "../shared/tsconfig.node.json", "compilerOptions": { "noEmit": true, "moduleResolution": "bundler", - "types": ["node"], "rootDir": ".", "rootDirs": ["shared/src", "node/src"], "paths": {}