From b6bc0dcbff71ec4e32402cd2bd653592e36b9f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=98=88=EC=A4=80?= Date: Sat, 15 Nov 2025 16:55:53 +0900 Subject: [PATCH 1/6] feat: add uv dependency manager support for Python templates - Add uv option to django, fastapi, flask templates - Update template.tmpl with uv installation logic - Add uv to dependency_manager options in config.json - Support pyproject.toml and uv.lock files LP-496 --- templates/django/config.json | 1 + templates/django/template.tmpl | 4 ++++ templates/fastapi/config.json | 1 + templates/fastapi/template.tmpl | 4 ++++ templates/flask/config.json | 1 + templates/flask/template.tmpl | 4 ++++ 6 files changed, 15 insertions(+) diff --git a/templates/django/config.json b/templates/django/config.json index e9a3ee0..3fdc5ea 100644 --- a/templates/django/config.json +++ b/templates/django/config.json @@ -42,6 +42,7 @@ "options": [ "pip", "poetry", + "uv", "pipenv" ], "type": "select", diff --git a/templates/django/template.tmpl b/templates/django/template.tmpl index 38aa0bb..dacd9a1 100644 --- a/templates/django/template.tmpl +++ b/templates/django/template.tmpl @@ -9,6 +9,10 @@ RUN pip install --no-cache-dir --user -r requirements.txt {{ .wsgi_server }} RUN pip install --no-cache-dir poetry COPY pyproject.toml poetry.lock* ./ RUN poetry config virtualenvs.create false && poetry install --only main --no-root && pip install --no-cache-dir {{ .wsgi_server }} +{{ else if eq .dependency_manager "uv" }} +RUN pip install --no-cache-dir uv +COPY pyproject.toml uv.lock* ./ +RUN uv sync --frozen --no-dev && pip install --no-cache-dir {{ .wsgi_server }} {{ else }} RUN pip install --no-cache-dir pipenv COPY Pipfile Pipfile.lock* ./ diff --git a/templates/fastapi/config.json b/templates/fastapi/config.json index 0fd1132..172122e 100644 --- a/templates/fastapi/config.json +++ b/templates/fastapi/config.json @@ -38,6 +38,7 @@ "options": [ "pip", "poetry", + "uv", "pipenv" ], "type": "select", diff --git a/templates/fastapi/template.tmpl b/templates/fastapi/template.tmpl index 77394df..ef1bdbb 100644 --- a/templates/fastapi/template.tmpl +++ b/templates/fastapi/template.tmpl @@ -9,6 +9,10 @@ RUN pip install --no-cache-dir --user -r requirements.txt {{ .asgi_server }} RUN pip install --no-cache-dir poetry COPY pyproject.toml poetry.lock* ./ RUN poetry config virtualenvs.create false && poetry install --only main --no-root && pip install --no-cache-dir {{ .asgi_server }} +{{ else if eq .dependency_manager "uv" }} +RUN pip install --no-cache-dir uv +COPY pyproject.toml uv.lock* ./ +RUN uv sync --frozen --no-dev && pip install --no-cache-dir {{ .asgi_server }} {{ else }} RUN pip install --no-cache-dir pipenv COPY Pipfile Pipfile.lock* ./ diff --git a/templates/flask/config.json b/templates/flask/config.json index fe46597..18c8f6a 100644 --- a/templates/flask/config.json +++ b/templates/flask/config.json @@ -42,6 +42,7 @@ "options": [ "pip", "poetry", + "uv", "pipenv" ], "type": "select", diff --git a/templates/flask/template.tmpl b/templates/flask/template.tmpl index 5814574..efcc477 100644 --- a/templates/flask/template.tmpl +++ b/templates/flask/template.tmpl @@ -9,6 +9,10 @@ RUN pip install --no-cache-dir -r requirements.txt {{ .wsgi_server }} RUN pip install --no-cache-dir poetry COPY pyproject.toml poetry.lock* ./ RUN poetry config virtualenvs.create false && poetry install --only main --no-root && pip install --no-cache-dir {{ .wsgi_server }} +{{ else if eq .dependency_manager "uv" }} +RUN pip install --no-cache-dir uv +COPY pyproject.toml uv.lock* ./ +RUN uv sync --frozen --no-dev && pip install --no-cache-dir {{ .wsgi_server }} {{ else }} RUN pip install --no-cache-dir pipenv COPY Pipfile Pipfile.lock* ./ From 02a334496a1c190b7ee3c401c79de5ab65f2b91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=98=88=EC=A4=80?= Date: Sat, 15 Nov 2025 16:56:13 +0900 Subject: [PATCH 2/6] feat: add Bun package manager support for Node.js templates - Add bun option to nextjs, react, vuejs, expressjs, nestjs templates - Use oven/bun:1-alpine for latest stable 1.x version - Support bun.lockb and bun install commands - No version selection needed (auto-uses latest 1.x with backward compatibility) LP-496 --- templates/expressjs/config.json | 3 ++- templates/expressjs/template.tmpl | 20 +++++++++++++++++--- templates/nestjs/config.json | 3 ++- templates/nestjs/template.tmpl | 22 +++++++++++++++++++--- templates/nextjs/config.json | 3 ++- templates/nextjs/template.tmpl | 25 ++++++++++++++++++++++--- templates/react/config.json | 3 ++- templates/react/template.tmpl | 13 +++++++++++-- templates/vuejs/config.json | 3 ++- templates/vuejs/template.tmpl | 13 +++++++++++-- 10 files changed, 90 insertions(+), 18 deletions(-) diff --git a/templates/expressjs/config.json b/templates/expressjs/config.json index df5af99..127c297 100644 --- a/templates/expressjs/config.json +++ b/templates/expressjs/config.json @@ -35,7 +35,8 @@ "options": [ "npm", "yarn", - "pnpm" + "pnpm", + "bun" ], "type": "select", "category": "required" diff --git a/templates/expressjs/template.tmpl b/templates/expressjs/template.tmpl index 128cb61..8e1ff48 100644 --- a/templates/expressjs/template.tmpl +++ b/templates/expressjs/template.tmpl @@ -1,4 +1,8 @@ +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine +{{ else }} FROM node:{{ .node_version }}-alpine +{{ end }} WORKDIR /app @@ -6,9 +10,11 @@ WORKDIR /app COPY package*.json ./ {{ else if eq .package_manager "yarn" }} COPY package.json yarn.lock* ./ -{{ else }} +{{ else if eq .package_manager "pnpm" }} COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm +{{ else }} +COPY package.json bun.lockb* ./ {{ end }} {{ if eq .build_mode "production" }} @@ -16,16 +22,20 @@ RUN npm install -g pnpm RUN npm install --only=production --no-audit --prefer-offline {{ else if eq .package_manager "yarn" }} RUN yarn install --production -{{ else }} +{{ else if eq .package_manager "pnpm" }} RUN pnpm install --prod +{{ else }} +RUN bun install --production --frozen-lockfile {{ end }} {{ else }} {{ if eq .package_manager "npm" }} RUN npm install --no-audit --prefer-offline {{ else if eq .package_manager "yarn" }} RUN yarn install -{{ else }} +{{ else if eq .package_manager "pnpm" }} RUN pnpm install +{{ else }} +RUN bun install --frozen-lockfile {{ end }} {{ end }} @@ -46,5 +56,9 @@ CMD ["pm2-runtime", "start", "{{ .entry_file }}", "--name", "express-app"] {{ else if eq .process_manager "nodemon" }} CMD ["nodemon", "{{ .entry_file }}"] {{ else }} +{{ if eq .package_manager "bun" }} +CMD ["bun", "run", "{{ .entry_file }}"] +{{ else }} CMD ["node", "{{ .entry_file }}"] +{{ end }} {{ end }} \ No newline at end of file diff --git a/templates/nestjs/config.json b/templates/nestjs/config.json index 579eb68..c7d1d25 100644 --- a/templates/nestjs/config.json +++ b/templates/nestjs/config.json @@ -35,7 +35,8 @@ "options": [ "npm", "yarn", - "pnpm" + "pnpm", + "bun" ], "type": "select", "category": "required" diff --git a/templates/nestjs/template.tmpl b/templates/nestjs/template.tmpl index 6fc1afa..38e3a4e 100644 --- a/templates/nestjs/template.tmpl +++ b/templates/nestjs/template.tmpl @@ -1,4 +1,8 @@ +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine AS builder +{{ else }} FROM node:{{ .node_version }}-alpine AS builder +{{ end }} WORKDIR /app @@ -8,9 +12,12 @@ RUN npm install --no-audit --prefer-offline {{ else if eq .package_manager "yarn" }} COPY package.json yarn.lock* ./ RUN yarn install -{{ else }} +{{ else if eq .package_manager "pnpm" }} COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install +{{ else }} +COPY package.json bun.lockb* ./ +RUN bun install --frozen-lockfile {{ end }} COPY . . @@ -19,11 +26,17 @@ COPY . . RUN npm run build {{ else if eq .package_manager "yarn" }} RUN yarn build -{{ else }} +{{ else if eq .package_manager "pnpm" }} RUN pnpm build +{{ else }} +RUN bun run build {{ end }} +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine +{{ else }} FROM node:{{ .node_version }}-alpine +{{ end }} WORKDIR /app @@ -33,9 +46,12 @@ RUN npm install --only=production --no-audit --prefer-offline {{ else if eq .package_manager "yarn" }} COPY package.json yarn.lock* ./ RUN yarn install --production -{{ else }} +{{ else if eq .package_manager "pnpm" }} COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install --prod +{{ else }} +COPY package.json bun.lockb* ./ +RUN bun install --production --frozen-lockfile {{ end }} COPY --from=builder /app/dist ./dist diff --git a/templates/nextjs/config.json b/templates/nextjs/config.json index fbb8f9d..7d8039e 100644 --- a/templates/nextjs/config.json +++ b/templates/nextjs/config.json @@ -35,7 +35,8 @@ "options": [ "npm", "yarn", - "pnpm" + "pnpm", + "bun" ], "type": "select", "category": "required" diff --git a/templates/nextjs/template.tmpl b/templates/nextjs/template.tmpl index c5998cb..248de03 100644 --- a/templates/nextjs/template.tmpl +++ b/templates/nextjs/template.tmpl @@ -1,4 +1,8 @@ +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine AS deps +{{ else }} FROM node:{{ .node_version }}-alpine AS deps +{{ end }} WORKDIR /app @@ -8,12 +12,19 @@ RUN npm install --no-audit --prefer-offline {{ else if eq .package_manager "yarn" }} COPY package.json yarn.lock* ./ RUN yarn install -{{ else }} +{{ else if eq .package_manager "pnpm" }} COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install +{{ else }} +COPY package.json bun.lockb* ./ +RUN bun install --frozen-lockfile {{ end }} +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine AS builder +{{ else }} FROM node:{{ .node_version }}-alpine AS builder +{{ end }} WORKDIR /app @@ -30,11 +41,17 @@ RUN mkdir -p public RUN npm run build {{ else if eq .package_manager "yarn" }} RUN yarn build -{{ else }} +{{ else if eq .package_manager "pnpm" }} RUN pnpm build +{{ else }} +RUN bun run build {{ end }} +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine AS runner +{{ else }} FROM node:{{ .node_version }}-alpine AS runner +{{ end }} WORKDIR /app @@ -60,6 +77,8 @@ EXPOSE 3000 CMD ["npm", "start"] {{ else if eq .package_manager "yarn" }} CMD ["yarn", "start"] -{{ else }} +{{ else if eq .package_manager "pnpm" }} CMD ["pnpm", "start"] +{{ else }} +CMD ["bun", "run", "start"] {{ end }} \ No newline at end of file diff --git a/templates/react/config.json b/templates/react/config.json index 199452c..ba9cc5c 100644 --- a/templates/react/config.json +++ b/templates/react/config.json @@ -37,7 +37,8 @@ "options": [ "npm", "yarn", - "pnpm" + "pnpm", + "bun" ], "type": "select", "category": "required" diff --git a/templates/react/template.tmpl b/templates/react/template.tmpl index 9138fc8..2106e9f 100644 --- a/templates/react/template.tmpl +++ b/templates/react/template.tmpl @@ -1,4 +1,8 @@ +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine AS builder +{{ else }} FROM node:{{ .node_version }}-alpine AS builder +{{ end }} WORKDIR /app @@ -8,9 +12,12 @@ RUN npm install --no-audit --prefer-offline {{ else if eq .package_manager "yarn" }} COPY package.json yarn.lock* ./ RUN yarn install -{{ else }} +{{ else if eq .package_manager "pnpm" }} COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install +{{ else }} +COPY package.json bun.lockb* ./ +RUN bun install --frozen-lockfile {{ end }} COPY . . @@ -19,8 +26,10 @@ COPY . . RUN npm run build {{ else if eq .package_manager "yarn" }} RUN yarn build -{{ else }} +{{ else if eq .package_manager "pnpm" }} RUN pnpm build +{{ else }} +RUN bun run build {{ end }} FROM nginx:alpine diff --git a/templates/vuejs/config.json b/templates/vuejs/config.json index ada0c88..c95321e 100644 --- a/templates/vuejs/config.json +++ b/templates/vuejs/config.json @@ -37,7 +37,8 @@ "options": [ "npm", "yarn", - "pnpm" + "pnpm", + "bun" ], "type": "select", "category": "required" diff --git a/templates/vuejs/template.tmpl b/templates/vuejs/template.tmpl index 05c7a38..d720fb0 100644 --- a/templates/vuejs/template.tmpl +++ b/templates/vuejs/template.tmpl @@ -1,4 +1,8 @@ +{{ if eq .package_manager "bun" }} +FROM oven/bun:1-alpine AS builder +{{ else }} FROM node:{{ .node_version }}-alpine AS builder +{{ end }} WORKDIR /app {{ if eq .package_manager "npm" }} @@ -7,9 +11,12 @@ RUN npm install --no-audit --prefer-offline {{ else if eq .package_manager "yarn" }} COPY package.json yarn.lock* ./ RUN yarn install -{{ else }} +{{ else if eq .package_manager "pnpm" }} COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install +{{ else }} +COPY package.json bun.lockb* ./ +RUN bun install --frozen-lockfile {{ end }} COPY . . @@ -18,8 +25,10 @@ COPY . . RUN npm run build {{ else if eq .package_manager "yarn" }} RUN yarn build -{{ else }} +{{ else if eq .package_manager "pnpm" }} RUN pnpm build +{{ else }} +RUN bun run build {{ end }} FROM nginx:alpine From 344f01692382cacb986cb0223e342d0044ff2cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=98=88=EC=A4=80?= Date: Sat, 15 Nov 2025 17:36:23 +0900 Subject: [PATCH 3/6] fix: update Python uv templates to work without lock files Change uv installation from 'uv sync --frozen --no-dev' to 'uv pip install --system --no-cache-dir .' to support projects without uv.lock files. This makes the templates more user-friendly for simple applications that don't need a full package build. Test projects confirmed working without requiring uv.lock files or package build configuration. LP-496 --- templates/django/template.tmpl | 3 ++- templates/fastapi/template.tmpl | 3 ++- templates/flask/template.tmpl | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/templates/django/template.tmpl b/templates/django/template.tmpl index dacd9a1..9e780dd 100644 --- a/templates/django/template.tmpl +++ b/templates/django/template.tmpl @@ -12,7 +12,8 @@ RUN poetry config virtualenvs.create false && poetry install --only main --no-ro {{ else if eq .dependency_manager "uv" }} RUN pip install --no-cache-dir uv COPY pyproject.toml uv.lock* ./ -RUN uv sync --frozen --no-dev && pip install --no-cache-dir {{ .wsgi_server }} +RUN uv pip install --system --no-cache-dir . && \ + uv pip install --system --no-cache-dir {{ .wsgi_server }} {{ else }} RUN pip install --no-cache-dir pipenv COPY Pipfile Pipfile.lock* ./ diff --git a/templates/fastapi/template.tmpl b/templates/fastapi/template.tmpl index ef1bdbb..989d41b 100644 --- a/templates/fastapi/template.tmpl +++ b/templates/fastapi/template.tmpl @@ -12,7 +12,8 @@ RUN poetry config virtualenvs.create false && poetry install --only main --no-ro {{ else if eq .dependency_manager "uv" }} RUN pip install --no-cache-dir uv COPY pyproject.toml uv.lock* ./ -RUN uv sync --frozen --no-dev && pip install --no-cache-dir {{ .asgi_server }} +RUN uv pip install --system --no-cache-dir . && \ + uv pip install --system --no-cache-dir {{ .asgi_server }} {{ else }} RUN pip install --no-cache-dir pipenv COPY Pipfile Pipfile.lock* ./ diff --git a/templates/flask/template.tmpl b/templates/flask/template.tmpl index efcc477..0faa871 100644 --- a/templates/flask/template.tmpl +++ b/templates/flask/template.tmpl @@ -12,7 +12,8 @@ RUN poetry config virtualenvs.create false && poetry install --only main --no-ro {{ else if eq .dependency_manager "uv" }} RUN pip install --no-cache-dir uv COPY pyproject.toml uv.lock* ./ -RUN uv sync --frozen --no-dev && pip install --no-cache-dir {{ .wsgi_server }} +RUN uv pip install --system --no-cache-dir . && \ + uv pip install --system --no-cache-dir {{ .wsgi_server }} {{ else }} RUN pip install --no-cache-dir pipenv COPY Pipfile Pipfile.lock* ./ From 446840db007025062ecf0f2132fe9995cb01b401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=98=88=EC=A4=80?= Date: Sat, 15 Nov 2025 17:37:04 +0900 Subject: [PATCH 4/6] fix: update Bun templates for better compatibility Remove --frozen-lockfile flag from bun install commands to support projects without bun.lockb files. Also add --bun flag to Next.js start command and fix package.json permissions for non-root user. Changes: - Remove --frozen-lockfile from all Bun templates - Add --bun flag to Next.js CMD for proper Bun runtime execution - Add --chown=nextjs:nodejs to Next.js package.json copy Test projects confirmed working without lock files. LP-496 --- templates/expressjs/template.tmpl | 4 ++-- templates/nestjs/template.tmpl | 4 ++-- templates/nextjs/template.tmpl | 6 +++--- templates/react/template.tmpl | 2 +- templates/vuejs/template.tmpl | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/templates/expressjs/template.tmpl b/templates/expressjs/template.tmpl index 8e1ff48..e9698a3 100644 --- a/templates/expressjs/template.tmpl +++ b/templates/expressjs/template.tmpl @@ -25,7 +25,7 @@ RUN yarn install --production {{ else if eq .package_manager "pnpm" }} RUN pnpm install --prod {{ else }} -RUN bun install --production --frozen-lockfile +RUN bun install --production {{ end }} {{ else }} {{ if eq .package_manager "npm" }} @@ -35,7 +35,7 @@ RUN yarn install {{ else if eq .package_manager "pnpm" }} RUN pnpm install {{ else }} -RUN bun install --frozen-lockfile +RUN bun install {{ end }} {{ end }} diff --git a/templates/nestjs/template.tmpl b/templates/nestjs/template.tmpl index 38e3a4e..7ec8afc 100644 --- a/templates/nestjs/template.tmpl +++ b/templates/nestjs/template.tmpl @@ -17,7 +17,7 @@ COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install {{ else }} COPY package.json bun.lockb* ./ -RUN bun install --frozen-lockfile +RUN bun install {{ end }} COPY . . @@ -51,7 +51,7 @@ COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install --prod {{ else }} COPY package.json bun.lockb* ./ -RUN bun install --production --frozen-lockfile +RUN bun install --production {{ end }} COPY --from=builder /app/dist ./dist diff --git a/templates/nextjs/template.tmpl b/templates/nextjs/template.tmpl index 248de03..a1aac0d 100644 --- a/templates/nextjs/template.tmpl +++ b/templates/nextjs/template.tmpl @@ -17,7 +17,7 @@ COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install {{ else }} COPY package.json bun.lockb* ./ -RUN bun install --frozen-lockfile +RUN bun install {{ end }} {{ if eq .package_manager "bun" }} @@ -67,7 +67,7 @@ RUN npm install -g pnpm COPY --from=deps /app/node_modules ./node_modules COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next COPY --from=builder /app/public ./public -COPY --from=builder /app/package.json ./package.json +COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json USER nextjs @@ -80,5 +80,5 @@ CMD ["yarn", "start"] {{ else if eq .package_manager "pnpm" }} CMD ["pnpm", "start"] {{ else }} -CMD ["bun", "run", "start"] +CMD ["bun", "--bun", "run", "start"] {{ end }} \ No newline at end of file diff --git a/templates/react/template.tmpl b/templates/react/template.tmpl index 2106e9f..cce021d 100644 --- a/templates/react/template.tmpl +++ b/templates/react/template.tmpl @@ -17,7 +17,7 @@ COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install {{ else }} COPY package.json bun.lockb* ./ -RUN bun install --frozen-lockfile +RUN bun install {{ end }} COPY . . diff --git a/templates/vuejs/template.tmpl b/templates/vuejs/template.tmpl index d720fb0..2d9ecf8 100644 --- a/templates/vuejs/template.tmpl +++ b/templates/vuejs/template.tmpl @@ -16,7 +16,7 @@ COPY package.json pnpm-lock.yaml* ./ RUN npm install -g pnpm && pnpm install {{ else }} COPY package.json bun.lockb* ./ -RUN bun install --frozen-lockfile +RUN bun install {{ end }} COPY . . From 65b83f87ff57335a91941dc5bd32b1fec5e1a028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=98=88=EC=A4=80?= Date: Sat, 15 Nov 2025 17:38:38 +0900 Subject: [PATCH 5/6] test: add test projects for uv and Bun dependency managers Add comprehensive test projects to validate template functionality: Python uv projects: - flask-uv: Flask app with uv dependency manager - fastapi-uv: FastAPI app with uv - django-uv: Django project with uv Bun projects: - react-bun: React SPA with Bun - vuejs-bun: Vue.js SPA with Bun - nextjs-bun: Next.js app with Bun runtime - expressjs-bun-prod-none: Express.js with Bun (no process manager) - nestjs-bun: NestJS app with Bun All test projects include: - pyproject.toml (Python) or package.json (Node.js) without lock files - Dockerfile generated from templates - Simple endpoint returning framework and dependency manager info Verified all projects build and run successfully with updated templates. LP-496 --- .gitignore | 1 + test-projects/backend/django-uv/Dockerfile | 30 ++++++++++ .../backend/django-uv/config/__init__.py | 1 + .../backend/django-uv/config/settings.py | 58 +++++++++++++++++++ .../backend/django-uv/config/urls.py | 19 ++++++ .../backend/django-uv/config/wsgi.py | 11 ++++ test-projects/backend/django-uv/manage.py | 22 +++++++ .../backend/django-uv/pyproject.toml | 8 +++ .../expressjs-bun-prod-none/Dockerfile | 15 +++++ .../backend/expressjs-bun-prod-none/index.js | 21 +++++++ .../expressjs-bun-prod-none/package.json | 12 ++++ test-projects/backend/fastapi-uv/Dockerfile | 28 +++++++++ test-projects/backend/fastapi-uv/main.py | 20 +++++++ .../backend/fastapi-uv/pyproject.toml | 8 +++ test-projects/backend/flask-uv/Dockerfile | 20 +++++++ test-projects/backend/flask-uv/app.py | 24 ++++++++ test-projects/backend/flask-uv/pyproject.toml | 8 +++ test-projects/backend/nestjs-bun/Dockerfile | 23 ++++++++ .../backend/nestjs-bun/nest-cli.json | 8 +++ test-projects/backend/nestjs-bun/package.json | 23 ++++++++ .../backend/nestjs-bun/src/app.controller.ts | 17 ++++++ .../backend/nestjs-bun/src/app.module.ts | 10 ++++ .../backend/nestjs-bun/src/app.service.ts | 12 ++++ test-projects/backend/nestjs-bun/src/main.ts | 9 +++ .../backend/nestjs-bun/tsconfig.json | 21 +++++++ test-projects/frontend/nextjs-bun/Dockerfile | 37 ++++++++++++ .../frontend/nextjs-bun/app/layout.tsx | 16 +++++ .../frontend/nextjs-bun/app/page.tsx | 9 +++ .../frontend/nextjs-bun/next.config.js | 4 ++ .../frontend/nextjs-bun/package.json | 20 +++++++ .../frontend/nextjs-bun/tsconfig.json | 27 +++++++++ test-projects/frontend/react-bun/Dockerfile | 27 +++++++++ test-projects/frontend/react-bun/index.html | 12 ++++ test-projects/frontend/react-bun/package.json | 22 +++++++ test-projects/frontend/react-bun/src/App.tsx | 11 ++++ test-projects/frontend/react-bun/src/main.tsx | 9 +++ .../frontend/react-bun/tsconfig.json | 21 +++++++ .../frontend/react-bun/tsconfig.node.json | 10 ++++ .../frontend/react-bun/vite.config.ts | 6 ++ test-projects/frontend/vuejs-bun/Dockerfile | 27 +++++++++ test-projects/frontend/vuejs-bun/index.html | 12 ++++ test-projects/frontend/vuejs-bun/package.json | 20 +++++++ test-projects/frontend/vuejs-bun/src/App.vue | 11 ++++ test-projects/frontend/vuejs-bun/src/main.ts | 4 ++ .../frontend/vuejs-bun/tsconfig.json | 21 +++++++ .../frontend/vuejs-bun/tsconfig.node.json | 10 ++++ .../frontend/vuejs-bun/vite.config.ts | 6 ++ 47 files changed, 771 insertions(+) create mode 100644 test-projects/backend/django-uv/Dockerfile create mode 100644 test-projects/backend/django-uv/config/__init__.py create mode 100644 test-projects/backend/django-uv/config/settings.py create mode 100644 test-projects/backend/django-uv/config/urls.py create mode 100644 test-projects/backend/django-uv/config/wsgi.py create mode 100644 test-projects/backend/django-uv/manage.py create mode 100644 test-projects/backend/django-uv/pyproject.toml create mode 100644 test-projects/backend/expressjs-bun-prod-none/Dockerfile create mode 100644 test-projects/backend/expressjs-bun-prod-none/index.js create mode 100644 test-projects/backend/expressjs-bun-prod-none/package.json create mode 100644 test-projects/backend/fastapi-uv/Dockerfile create mode 100644 test-projects/backend/fastapi-uv/main.py create mode 100644 test-projects/backend/fastapi-uv/pyproject.toml create mode 100644 test-projects/backend/flask-uv/Dockerfile create mode 100644 test-projects/backend/flask-uv/app.py create mode 100644 test-projects/backend/flask-uv/pyproject.toml create mode 100644 test-projects/backend/nestjs-bun/Dockerfile create mode 100644 test-projects/backend/nestjs-bun/nest-cli.json create mode 100644 test-projects/backend/nestjs-bun/package.json create mode 100644 test-projects/backend/nestjs-bun/src/app.controller.ts create mode 100644 test-projects/backend/nestjs-bun/src/app.module.ts create mode 100644 test-projects/backend/nestjs-bun/src/app.service.ts create mode 100644 test-projects/backend/nestjs-bun/src/main.ts create mode 100644 test-projects/backend/nestjs-bun/tsconfig.json create mode 100644 test-projects/frontend/nextjs-bun/Dockerfile create mode 100644 test-projects/frontend/nextjs-bun/app/layout.tsx create mode 100644 test-projects/frontend/nextjs-bun/app/page.tsx create mode 100644 test-projects/frontend/nextjs-bun/next.config.js create mode 100644 test-projects/frontend/nextjs-bun/package.json create mode 100644 test-projects/frontend/nextjs-bun/tsconfig.json create mode 100644 test-projects/frontend/react-bun/Dockerfile create mode 100644 test-projects/frontend/react-bun/index.html create mode 100644 test-projects/frontend/react-bun/package.json create mode 100644 test-projects/frontend/react-bun/src/App.tsx create mode 100644 test-projects/frontend/react-bun/src/main.tsx create mode 100644 test-projects/frontend/react-bun/tsconfig.json create mode 100644 test-projects/frontend/react-bun/tsconfig.node.json create mode 100644 test-projects/frontend/react-bun/vite.config.ts create mode 100644 test-projects/frontend/vuejs-bun/Dockerfile create mode 100644 test-projects/frontend/vuejs-bun/index.html create mode 100644 test-projects/frontend/vuejs-bun/package.json create mode 100644 test-projects/frontend/vuejs-bun/src/App.vue create mode 100644 test-projects/frontend/vuejs-bun/src/main.ts create mode 100644 test-projects/frontend/vuejs-bun/tsconfig.json create mode 100644 test-projects/frontend/vuejs-bun/tsconfig.node.json create mode 100644 test-projects/frontend/vuejs-bun/vite.config.ts diff --git a/.gitignore b/.gitignore index 01c8bbf..36345c2 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ tmp/ # Generated migration files (local testing) /migrations/ *.sql +scripts/.cache/ diff --git a/test-projects/backend/django-uv/Dockerfile b/test-projects/backend/django-uv/Dockerfile new file mode 100644 index 0000000..47a6989 --- /dev/null +++ b/test-projects/backend/django-uv/Dockerfile @@ -0,0 +1,30 @@ +FROM python:3.12-slim AS builder + +WORKDIR /app + +RUN pip install --no-cache-dir uv +COPY pyproject.toml uv.lock* ./ +RUN uv pip install --system --no-cache-dir . && \ + uv pip install --system --no-cache-dir gunicorn + +FROM python:3.12-slim + +WORKDIR /app + +COPY --from=builder /usr/local/lib /usr/local/lib +COPY --from=builder /usr/local/bin /usr/local/bin + +COPY . . + +ENV DJANGO_SETTINGS_MODULE=config.settings +RUN python manage.py collectstatic --noinput || echo "Warning: collectstatic failed, continuing..." + +RUN addgroup --system --gid 1001 app && \ + adduser --system --uid 1001 --gid 1001 app && \ + chown -R app:app /app + +USER app + +EXPOSE 8000 + +CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "config.wsgi"] diff --git a/test-projects/backend/django-uv/config/__init__.py b/test-projects/backend/django-uv/config/__init__.py new file mode 100644 index 0000000..233c831 --- /dev/null +++ b/test-projects/backend/django-uv/config/__init__.py @@ -0,0 +1 @@ +# Django configuration package diff --git a/test-projects/backend/django-uv/config/settings.py b/test-projects/backend/django-uv/config/settings.py new file mode 100644 index 0000000..55a5b2f --- /dev/null +++ b/test-projects/backend/django-uv/config/settings.py @@ -0,0 +1,58 @@ +""" +Django settings for django-uv-test project. +""" + +from pathlib import Path + +BASE_DIR = Path(__file__).resolve().parent.parent + +SECRET_KEY = 'django-insecure-test-key-for-uv-template-testing-only' + +DEBUG = True + +ALLOWED_HOSTS = ['*'] + +INSTALLED_APPS = [ + 'django.contrib.contenttypes', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.middleware.common.CommonMiddleware', +] + +ROOT_URLCONF = 'config.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + ], + }, + }, +] + +WSGI_APPLICATION = 'config.wsgi.application' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + +LANGUAGE_CODE = 'en-us' +TIME_ZONE = 'UTC' +USE_I18N = True +USE_TZ = True + +STATIC_URL = 'static/' +STATIC_ROOT = BASE_DIR / 'staticfiles' + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/test-projects/backend/django-uv/config/urls.py b/test-projects/backend/django-uv/config/urls.py new file mode 100644 index 0000000..cc845e6 --- /dev/null +++ b/test-projects/backend/django-uv/config/urls.py @@ -0,0 +1,19 @@ +""" +URL configuration for django-uv-test project. +""" +from django.http import JsonResponse +from django.urls import path + + +def hello_world(request): + return JsonResponse({ + 'message': 'Hello from Django with uv!', + 'dependency_manager': 'uv', + 'framework': 'Django' + }) + + +urlpatterns = [ + path('', hello_world), + path('health/', hello_world), +] diff --git a/test-projects/backend/django-uv/config/wsgi.py b/test-projects/backend/django-uv/config/wsgi.py new file mode 100644 index 0000000..409fc63 --- /dev/null +++ b/test-projects/backend/django-uv/config/wsgi.py @@ -0,0 +1,11 @@ +""" +WSGI config for django-uv-test project. +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + +application = get_wsgi_application() diff --git a/test-projects/backend/django-uv/manage.py b/test-projects/backend/django-uv/manage.py new file mode 100644 index 0000000..8e7ac79 --- /dev/null +++ b/test-projects/backend/django-uv/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/test-projects/backend/django-uv/pyproject.toml b/test-projects/backend/django-uv/pyproject.toml new file mode 100644 index 0000000..c77fc18 --- /dev/null +++ b/test-projects/backend/django-uv/pyproject.toml @@ -0,0 +1,8 @@ +[project] +name = "django-uv-test" +version = "0.1.0" +description = "Django test project with uv dependency manager" +requires-python = ">=3.12" +dependencies = [ + "django>=5.0,<6.0", +] diff --git a/test-projects/backend/expressjs-bun-prod-none/Dockerfile b/test-projects/backend/expressjs-bun-prod-none/Dockerfile new file mode 100644 index 0000000..847dab9 --- /dev/null +++ b/test-projects/backend/expressjs-bun-prod-none/Dockerfile @@ -0,0 +1,15 @@ +FROM oven/bun:1-alpine + +WORKDIR /app + +COPY package.json bun.lockb* ./ + +RUN bun install + +COPY . . + +ENV NODE_ENV=production + +EXPOSE 3000 + +CMD ["bun", "run", "index.js"] diff --git a/test-projects/backend/expressjs-bun-prod-none/index.js b/test-projects/backend/expressjs-bun-prod-none/index.js new file mode 100644 index 0000000..5d0b65f --- /dev/null +++ b/test-projects/backend/expressjs-bun-prod-none/index.js @@ -0,0 +1,21 @@ +import express from 'express'; + +const app = express(); +const PORT = process.env.PORT || 3000; + +app.get('/', (req, res) => { + res.json({ + message: 'Hello from Express.js with Bun!', + package_manager: 'bun', + framework: 'Express.js', + runtime: 'Bun' + }); +}); + +app.get('/health', (req, res) => { + res.json({ status: 'healthy' }); +}); + +app.listen(PORT, () => { + console.log(`Server running on port ${PORT}`); +}); diff --git a/test-projects/backend/expressjs-bun-prod-none/package.json b/test-projects/backend/expressjs-bun-prod-none/package.json new file mode 100644 index 0000000..8861613 --- /dev/null +++ b/test-projects/backend/expressjs-bun-prod-none/package.json @@ -0,0 +1,12 @@ +{ + "name": "expressjs-bun-test", + "version": "0.1.0", + "type": "module", + "scripts": { + "start": "bun run index.js", + "dev": "bun run --watch index.js" + }, + "dependencies": { + "express": "^4.18.0" + } +} diff --git a/test-projects/backend/fastapi-uv/Dockerfile b/test-projects/backend/fastapi-uv/Dockerfile new file mode 100644 index 0000000..c029d09 --- /dev/null +++ b/test-projects/backend/fastapi-uv/Dockerfile @@ -0,0 +1,28 @@ +FROM python:3.12-slim AS builder + +WORKDIR /app + +RUN pip install --no-cache-dir uv +COPY pyproject.toml uv.lock* ./ +RUN uv pip install --system --no-cache-dir . && \ + uv pip install --system --no-cache-dir uvicorn + +FROM python:3.12-slim + +WORKDIR /app + +RUN addgroup --system --gid 1001 app && \ + adduser --system --uid 1001 --gid 1001 app + +COPY --from=builder /usr/local/lib /usr/local/lib +COPY --from=builder /usr/local/bin /usr/local/bin + +COPY . . + +RUN chown -R app:app /app + +USER app + +EXPOSE 8000 + +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"] diff --git a/test-projects/backend/fastapi-uv/main.py b/test-projects/backend/fastapi-uv/main.py new file mode 100644 index 0000000..a0cee3b --- /dev/null +++ b/test-projects/backend/fastapi-uv/main.py @@ -0,0 +1,20 @@ +""" +FastAPI test application with uv dependency manager +""" +from fastapi import FastAPI + +app = FastAPI(title="FastAPI uv Test") + + +@app.get("/") +async def root(): + return { + "message": "Hello from FastAPI with uv!", + "dependency_manager": "uv", + "framework": "FastAPI" + } + + +@app.get("/health") +async def health(): + return {"status": "healthy"} diff --git a/test-projects/backend/fastapi-uv/pyproject.toml b/test-projects/backend/fastapi-uv/pyproject.toml new file mode 100644 index 0000000..9305726 --- /dev/null +++ b/test-projects/backend/fastapi-uv/pyproject.toml @@ -0,0 +1,8 @@ +[project] +name = "fastapi-uv-test" +version = "0.1.0" +description = "FastAPI test project with uv dependency manager" +requires-python = ">=3.12" +dependencies = [ + "fastapi>=0.100.0", +] diff --git a/test-projects/backend/flask-uv/Dockerfile b/test-projects/backend/flask-uv/Dockerfile new file mode 100644 index 0000000..ad9c654 --- /dev/null +++ b/test-projects/backend/flask-uv/Dockerfile @@ -0,0 +1,20 @@ +FROM python:3.12-slim + +WORKDIR /app + +RUN pip install --no-cache-dir uv +COPY pyproject.toml uv.lock* ./ +RUN uv pip install --system --no-cache-dir . && \ + uv pip install --system --no-cache-dir gunicorn + +COPY . . + +RUN addgroup --system --gid 1001 app && \ + adduser --system --uid 1001 --gid 1001 app && \ + chown -R app:app /app + +USER app + +EXPOSE 8000 + +CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "app:app"] diff --git a/test-projects/backend/flask-uv/app.py b/test-projects/backend/flask-uv/app.py new file mode 100644 index 0000000..7037f7f --- /dev/null +++ b/test-projects/backend/flask-uv/app.py @@ -0,0 +1,24 @@ +""" +Flask test application with uv dependency manager +""" +from flask import Flask, jsonify + +app = Flask(__name__) + + +@app.route('/') +def hello(): + return jsonify({ + 'message': 'Hello from Flask with uv!', + 'dependency_manager': 'uv', + 'framework': 'Flask' + }) + + +@app.route('/health') +def health(): + return jsonify({'status': 'healthy'}) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git a/test-projects/backend/flask-uv/pyproject.toml b/test-projects/backend/flask-uv/pyproject.toml new file mode 100644 index 0000000..9ea8893 --- /dev/null +++ b/test-projects/backend/flask-uv/pyproject.toml @@ -0,0 +1,8 @@ +[project] +name = "flask-uv-test" +version = "0.1.0" +description = "Flask test project with uv dependency manager" +requires-python = ">=3.12" +dependencies = [ + "flask>=3.0.0", +] diff --git a/test-projects/backend/nestjs-bun/Dockerfile b/test-projects/backend/nestjs-bun/Dockerfile new file mode 100644 index 0000000..6e99fec --- /dev/null +++ b/test-projects/backend/nestjs-bun/Dockerfile @@ -0,0 +1,23 @@ +FROM oven/bun:1-alpine AS builder + +WORKDIR /app + +COPY package.json bun.lockb* ./ +RUN bun install + +COPY . . + +RUN bun run build + +FROM oven/bun:1-alpine + +WORKDIR /app + +COPY package.json bun.lockb* ./ +RUN bun install --production + +COPY --from=builder /app/dist ./dist + +EXPOSE 3000 + +CMD ["node", "dist/main"] diff --git a/test-projects/backend/nestjs-bun/nest-cli.json b/test-projects/backend/nestjs-bun/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/test-projects/backend/nestjs-bun/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/test-projects/backend/nestjs-bun/package.json b/test-projects/backend/nestjs-bun/package.json new file mode 100644 index 0000000..318511c --- /dev/null +++ b/test-projects/backend/nestjs-bun/package.json @@ -0,0 +1,23 @@ +{ + "name": "nestjs-bun-test", + "version": "0.1.0", + "scripts": { + "build": "nest build", + "start": "node dist/main", + "start:dev": "nest start --watch" + }, + "dependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.8.0" + }, + "devDependencies": { + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@types/express": "^4.17.0", + "@types/node": "^20.0.0", + "typescript": "^5.0.0" + } +} diff --git a/test-projects/backend/nestjs-bun/src/app.controller.ts b/test-projects/backend/nestjs-bun/src/app.controller.ts new file mode 100644 index 0000000..b698b3e --- /dev/null +++ b/test-projects/backend/nestjs-bun/src/app.controller.ts @@ -0,0 +1,17 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getHello() { + return this.appService.getHello(); + } + + @Get('health') + getHealth() { + return { status: 'healthy' }; + } +} diff --git a/test-projects/backend/nestjs-bun/src/app.module.ts b/test-projects/backend/nestjs-bun/src/app.module.ts new file mode 100644 index 0000000..8662803 --- /dev/null +++ b/test-projects/backend/nestjs-bun/src/app.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +@Module({ + imports: [], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule {} diff --git a/test-projects/backend/nestjs-bun/src/app.service.ts b/test-projects/backend/nestjs-bun/src/app.service.ts new file mode 100644 index 0000000..9635b05 --- /dev/null +++ b/test-projects/backend/nestjs-bun/src/app.service.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello() { + return { + message: 'Hello from NestJS with Bun!', + package_manager: 'bun', + framework: 'NestJS', + }; + } +} diff --git a/test-projects/backend/nestjs-bun/src/main.ts b/test-projects/backend/nestjs-bun/src/main.ts new file mode 100644 index 0000000..a913660 --- /dev/null +++ b/test-projects/backend/nestjs-bun/src/main.ts @@ -0,0 +1,9 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + await app.listen(3000); + console.log('NestJS application with Bun is running on port 3000'); +} +bootstrap(); diff --git a/test-projects/backend/nestjs-bun/tsconfig.json b/test-projects/backend/nestjs-bun/tsconfig.json new file mode 100644 index 0000000..95f5641 --- /dev/null +++ b/test-projects/backend/nestjs-bun/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/test-projects/frontend/nextjs-bun/Dockerfile b/test-projects/frontend/nextjs-bun/Dockerfile new file mode 100644 index 0000000..8afc383 --- /dev/null +++ b/test-projects/frontend/nextjs-bun/Dockerfile @@ -0,0 +1,37 @@ +FROM oven/bun:1-alpine AS deps + +WORKDIR /app + +COPY package.json bun.lockb* ./ +RUN bun install + +FROM oven/bun:1-alpine AS builder + +WORKDIR /app + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +RUN mkdir -p public + +RUN bun run build + +FROM oven/bun:1-alpine AS runner + +WORKDIR /app + +ENV NODE_ENV=production + +RUN addgroup --system --gid 1001 nodejs && \ + adduser --system --uid 1001 nextjs + +COPY --from=deps /app/node_modules ./node_modules +COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json + +USER nextjs + +EXPOSE 3000 + +CMD ["bun", "--bun", "run", "start"] diff --git a/test-projects/frontend/nextjs-bun/app/layout.tsx b/test-projects/frontend/nextjs-bun/app/layout.tsx new file mode 100644 index 0000000..d295378 --- /dev/null +++ b/test-projects/frontend/nextjs-bun/app/layout.tsx @@ -0,0 +1,16 @@ +export const metadata = { + title: 'Next.js Bun Test', + description: 'Testing Next.js with Bun package manager', +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/test-projects/frontend/nextjs-bun/app/page.tsx b/test-projects/frontend/nextjs-bun/app/page.tsx new file mode 100644 index 0000000..02fc6b6 --- /dev/null +++ b/test-projects/frontend/nextjs-bun/app/page.tsx @@ -0,0 +1,9 @@ +export default function Home() { + return ( +
+

Hello from Next.js with Bun!

+

Package Manager: Bun

+

Framework: Next.js 14 (App Router)

+
+ ); +} diff --git a/test-projects/frontend/nextjs-bun/next.config.js b/test-projects/frontend/nextjs-bun/next.config.js new file mode 100644 index 0000000..658404a --- /dev/null +++ b/test-projects/frontend/nextjs-bun/next.config.js @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +module.exports = nextConfig; diff --git a/test-projects/frontend/nextjs-bun/package.json b/test-projects/frontend/nextjs-bun/package.json new file mode 100644 index 0000000..d4474d2 --- /dev/null +++ b/test-projects/frontend/nextjs-bun/package.json @@ -0,0 +1,20 @@ +{ + "name": "nextjs-bun-test", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "next": "^14.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/react": "^18.2.0", + "typescript": "^5.0.0" + } +} diff --git a/test-projects/frontend/nextjs-bun/tsconfig.json b/test-projects/frontend/nextjs-bun/tsconfig.json new file mode 100644 index 0000000..d8b9323 --- /dev/null +++ b/test-projects/frontend/nextjs-bun/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/test-projects/frontend/react-bun/Dockerfile b/test-projects/frontend/react-bun/Dockerfile new file mode 100644 index 0000000..57ba37d --- /dev/null +++ b/test-projects/frontend/react-bun/Dockerfile @@ -0,0 +1,27 @@ +FROM oven/bun:1-alpine AS builder + +WORKDIR /app + +COPY package.json bun.lockb* ./ +RUN bun install + +COPY . . + +RUN bun run build + +FROM nginx:alpine + +COPY --from=builder /app/dist /usr/share/nginx/html + +RUN echo 'server { \ + listen 3000; \ + location / { \ + root /usr/share/nginx/html; \ + index index.html; \ + try_files $uri $uri/ /index.html; \ + } \ +}' > /etc/nginx/conf.d/default.conf + +EXPOSE 3000 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/test-projects/frontend/react-bun/index.html b/test-projects/frontend/react-bun/index.html new file mode 100644 index 0000000..dd92b2c --- /dev/null +++ b/test-projects/frontend/react-bun/index.html @@ -0,0 +1,12 @@ + + + + + + React Bun Test + + +
+ + + diff --git a/test-projects/frontend/react-bun/package.json b/test-projects/frontend/react-bun/package.json new file mode 100644 index 0000000..8996202 --- /dev/null +++ b/test-projects/frontend/react-bun/package.json @@ -0,0 +1,22 @@ +{ + "name": "react-bun-test", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@vitejs/plugin-react": "^4.2.0", + "typescript": "^5.0.0", + "vite": "^5.0.0" + } +} diff --git a/test-projects/frontend/react-bun/src/App.tsx b/test-projects/frontend/react-bun/src/App.tsx new file mode 100644 index 0000000..b7f5adf --- /dev/null +++ b/test-projects/frontend/react-bun/src/App.tsx @@ -0,0 +1,11 @@ +function App() { + return ( +
+

Hello from React with Bun!

+

Package Manager: Bun

+

Framework: React 18 + Vite

+
+ ); +} + +export default App; diff --git a/test-projects/frontend/react-bun/src/main.tsx b/test-projects/frontend/react-bun/src/main.tsx new file mode 100644 index 0000000..9707d82 --- /dev/null +++ b/test-projects/frontend/react-bun/src/main.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + +); diff --git a/test-projects/frontend/react-bun/tsconfig.json b/test-projects/frontend/react-bun/tsconfig.json new file mode 100644 index 0000000..3934b8f --- /dev/null +++ b/test-projects/frontend/react-bun/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/test-projects/frontend/react-bun/tsconfig.node.json b/test-projects/frontend/react-bun/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/test-projects/frontend/react-bun/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/test-projects/frontend/react-bun/vite.config.ts b/test-projects/frontend/react-bun/vite.config.ts new file mode 100644 index 0000000..0466183 --- /dev/null +++ b/test-projects/frontend/react-bun/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/test-projects/frontend/vuejs-bun/Dockerfile b/test-projects/frontend/vuejs-bun/Dockerfile new file mode 100644 index 0000000..57ba37d --- /dev/null +++ b/test-projects/frontend/vuejs-bun/Dockerfile @@ -0,0 +1,27 @@ +FROM oven/bun:1-alpine AS builder + +WORKDIR /app + +COPY package.json bun.lockb* ./ +RUN bun install + +COPY . . + +RUN bun run build + +FROM nginx:alpine + +COPY --from=builder /app/dist /usr/share/nginx/html + +RUN echo 'server { \ + listen 3000; \ + location / { \ + root /usr/share/nginx/html; \ + index index.html; \ + try_files $uri $uri/ /index.html; \ + } \ +}' > /etc/nginx/conf.d/default.conf + +EXPOSE 3000 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/test-projects/frontend/vuejs-bun/index.html b/test-projects/frontend/vuejs-bun/index.html new file mode 100644 index 0000000..3bdf219 --- /dev/null +++ b/test-projects/frontend/vuejs-bun/index.html @@ -0,0 +1,12 @@ + + + + + + Vue.js Bun Test + + +
+ + + diff --git a/test-projects/frontend/vuejs-bun/package.json b/test-projects/frontend/vuejs-bun/package.json new file mode 100644 index 0000000..9b97eeb --- /dev/null +++ b/test-projects/frontend/vuejs-bun/package.json @@ -0,0 +1,20 @@ +{ + "name": "vuejs-bun-test", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.3.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.0", + "typescript": "^5.0.0", + "vite": "^5.0.0", + "vue-tsc": "^1.8.0" + } +} diff --git a/test-projects/frontend/vuejs-bun/src/App.vue b/test-projects/frontend/vuejs-bun/src/App.vue new file mode 100644 index 0000000..0f7d32e --- /dev/null +++ b/test-projects/frontend/vuejs-bun/src/App.vue @@ -0,0 +1,11 @@ + + + diff --git a/test-projects/frontend/vuejs-bun/src/main.ts b/test-projects/frontend/vuejs-bun/src/main.ts new file mode 100644 index 0000000..684d042 --- /dev/null +++ b/test-projects/frontend/vuejs-bun/src/main.ts @@ -0,0 +1,4 @@ +import { createApp } from 'vue'; +import App from './App.vue'; + +createApp(App).mount('#app'); diff --git a/test-projects/frontend/vuejs-bun/tsconfig.json b/test-projects/frontend/vuejs-bun/tsconfig.json new file mode 100644 index 0000000..a18b191 --- /dev/null +++ b/test-projects/frontend/vuejs-bun/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/test-projects/frontend/vuejs-bun/tsconfig.node.json b/test-projects/frontend/vuejs-bun/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/test-projects/frontend/vuejs-bun/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/test-projects/frontend/vuejs-bun/vite.config.ts b/test-projects/frontend/vuejs-bun/vite.config.ts new file mode 100644 index 0000000..1ebc4fc --- /dev/null +++ b/test-projects/frontend/vuejs-bun/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; + +export default defineConfig({ + plugins: [vue()], +}); From 44e358190607515c248a6f76dd0b85d2b9d164fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=98=88=EC=A4=80?= Date: Sat, 15 Nov 2025 21:52:07 +0900 Subject: [PATCH 6/6] fix: use Bun runtime for NestJS when Bun package manager selected Change CMD from always using 'node dist/main' to conditionally using 'bun run dist/main' when package_manager is 'bun'. This ensures NestJS apps leverage the Bun runtime instead of Node.js compatibility layer. Addresses code review feedback about inconsistent runtime usage. LP-496 --- templates/nestjs/template.tmpl | 6 +++++- test-projects/backend/nestjs-bun/Dockerfile | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/templates/nestjs/template.tmpl b/templates/nestjs/template.tmpl index 7ec8afc..aba25d9 100644 --- a/templates/nestjs/template.tmpl +++ b/templates/nestjs/template.tmpl @@ -58,4 +58,8 @@ COPY --from=builder /app/dist ./dist EXPOSE 3000 -CMD ["node", "dist/main"] \ No newline at end of file +{{ if eq .package_manager "bun" }} +CMD ["bun", "run", "dist/main"] +{{ else }} +CMD ["node", "dist/main"] +{{ end }} \ No newline at end of file diff --git a/test-projects/backend/nestjs-bun/Dockerfile b/test-projects/backend/nestjs-bun/Dockerfile index 6e99fec..e5e2476 100644 --- a/test-projects/backend/nestjs-bun/Dockerfile +++ b/test-projects/backend/nestjs-bun/Dockerfile @@ -20,4 +20,4 @@ COPY --from=builder /app/dist ./dist EXPOSE 3000 -CMD ["node", "dist/main"] +CMD ["bun", "run", "dist/main"]