diff options
Diffstat (limited to 'examples/with-docker/apps/api')
| -rw-r--r-- | examples/with-docker/apps/api/.eslintrc.js | 4 | ||||
| -rw-r--r-- | examples/with-docker/apps/api/Dockerfile | 48 | ||||
| -rw-r--r-- | examples/with-docker/apps/api/package.json | 42 | ||||
| -rw-r--r-- | examples/with-docker/apps/api/src/__tests__/server.test.ts | 22 | ||||
| -rw-r--r-- | examples/with-docker/apps/api/src/__tests__/tsconfig.json | 4 | ||||
| -rw-r--r-- | examples/with-docker/apps/api/src/index.ts | 9 | ||||
| -rw-r--r-- | examples/with-docker/apps/api/src/server.ts | 22 | ||||
| -rw-r--r-- | examples/with-docker/apps/api/tsconfig.json | 11 |
8 files changed, 162 insertions, 0 deletions
diff --git a/examples/with-docker/apps/api/.eslintrc.js b/examples/with-docker/apps/api/.eslintrc.js new file mode 100644 index 0000000..2308ff9 --- /dev/null +++ b/examples/with-docker/apps/api/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ["custom-server"], +}; diff --git a/examples/with-docker/apps/api/Dockerfile b/examples/with-docker/apps/api/Dockerfile new file mode 100644 index 0000000..1b8e878 --- /dev/null +++ b/examples/with-docker/apps/api/Dockerfile @@ -0,0 +1,48 @@ +# The web Dockerfile is copy-pasted into our main docs at /docs/handbook/deploying-with-docker. +# Make sure you update this Dockerfile, the Dockerfile in the web workspace and copy that over to Dockerfile in the docs. + +FROM node:alpine AS builder +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat +RUN apk update +# Set working directory +WORKDIR /app +RUN yarn global add turbo +COPY . . +RUN turbo prune --scope=api --docker + +# Add lockfile and package.json's of isolated subworkspace +FROM node:alpine AS installer +RUN apk add --no-cache libc6-compat +RUN apk update +WORKDIR /app + +# First install dependencies (as they change less often) +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/yarn.lock ./yarn.lock +RUN yarn install + +# Build the project and its dependencies +COPY --from=builder /app/out/full/ . +COPY turbo.json turbo.json + +# Uncomment and use build args to enable remote caching +# ARG TURBO_TEAM +# ENV TURBO_TEAM=$TURBO_TEAM + +# ARG TURBO_TOKEN +# ENV TURBO_TOKEN=$TURBO_TOKEN + +RUN yarn turbo run build --filter=api... + +FROM node:alpine AS runner +WORKDIR /app + +# Don't run production as root +RUN addgroup --system --gid 1001 expressjs +RUN adduser --system --uid 1001 expressjs +USER expressjs +COPY --from=installer /app . + +CMD node apps/api/dist/index.js diff --git a/examples/with-docker/apps/api/package.json b/examples/with-docker/apps/api/package.json new file mode 100644 index 0000000..abe79b4 --- /dev/null +++ b/examples/with-docker/apps/api/package.json @@ -0,0 +1,42 @@ +{ + "name": "api", + "version": "0.0.0", + "private": true, + "scripts": { + "build": "tsc", + "clean": "rm -rf dist", + "dev": "nodemon --exec \"node -r esbuild-register ./src/index.ts\" -e .ts", + "lint": "tsc --noEmit && eslint \"src/**/*.ts*\"", + "start": "node -r esbuild-register ./src/index.ts", + "test": "jest --detectOpenHandles" + }, + "jest": { + "preset": "jest-presets/jest/node" + }, + "dependencies": { + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "express": "^4.17.1", + "logger": "*", + "morgan": "^1.10.0" + }, + "devDependencies": { + "@types/body-parser": "^1.19.0", + "@types/cors": "^2.8.10", + "@types/express": "^4.17.12", + "@types/jest": "^26.0.22", + "@types/morgan": "^1.9.2", + "@types/node": "^15.12.2", + "@types/supertest": "^2.0.11", + "esbuild": "^0.14.38", + "esbuild-register": "^3.3.2", + "eslint": "^7.32.0", + "eslint-config-custom-server": "*", + "jest": "^26.6.3", + "jest-presets": "*", + "nodemon": "^2.0.15", + "supertest": "^6.1.3", + "tsconfig": "*", + "typescript": "^4.5.3" + } +} diff --git a/examples/with-docker/apps/api/src/__tests__/server.test.ts b/examples/with-docker/apps/api/src/__tests__/server.test.ts new file mode 100644 index 0000000..c0c9806 --- /dev/null +++ b/examples/with-docker/apps/api/src/__tests__/server.test.ts @@ -0,0 +1,22 @@ +import supertest from "supertest"; +import { createServer } from "../server"; + +describe("server", () => { + it("health check returns 200", async () => { + await supertest(createServer()) + .get("/healthz") + .expect(200) + .then((res) => { + expect(res.body.ok).toBe(true); + }); + }); + + it("message endpoint says hello", async () => { + await supertest(createServer()) + .get("/message/jared") + .expect(200) + .then((res) => { + expect(res.body).toEqual({ message: "hello jared" }); + }); + }); +}); diff --git a/examples/with-docker/apps/api/src/__tests__/tsconfig.json b/examples/with-docker/apps/api/src/__tests__/tsconfig.json new file mode 100644 index 0000000..bf65be6 --- /dev/null +++ b/examples/with-docker/apps/api/src/__tests__/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": [".", "../."] +} diff --git a/examples/with-docker/apps/api/src/index.ts b/examples/with-docker/apps/api/src/index.ts new file mode 100644 index 0000000..fbb9fda --- /dev/null +++ b/examples/with-docker/apps/api/src/index.ts @@ -0,0 +1,9 @@ +import { createServer } from "./server"; +import { log } from "logger"; + +const port = process.env.PORT || 3001; +const server = createServer(); + +server.listen(port, () => { + log(`api running on ${port}`); +}); diff --git a/examples/with-docker/apps/api/src/server.ts b/examples/with-docker/apps/api/src/server.ts new file mode 100644 index 0000000..70ccf0b --- /dev/null +++ b/examples/with-docker/apps/api/src/server.ts @@ -0,0 +1,22 @@ +import { json, urlencoded } from "body-parser"; +import express from "express"; +import morgan from "morgan"; +import cors from "cors"; + +export const createServer = () => { + const app = express(); + app + .disable("x-powered-by") + .use(morgan("dev")) + .use(urlencoded({ extended: true })) + .use(json()) + .use(cors()) + .get("/message/:name", (req, res) => { + return res.json({ message: `hello ${req.params.name}` }); + }) + .get("/healthz", (req, res) => { + return res.json({ ok: true }); + }); + + return app; +}; diff --git a/examples/with-docker/apps/api/tsconfig.json b/examples/with-docker/apps/api/tsconfig.json new file mode 100644 index 0000000..74f3de4 --- /dev/null +++ b/examples/with-docker/apps/api/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "lib": ["ES2015"], + "module": "CommonJS", + "outDir": "./dist", + "rootDir": "./src" + }, + "exclude": ["node_modules"], + "extends": "tsconfig/base.json", + "include": ["src"] +} |
