generated from well-known-components/template-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit baaa1b0
Showing
28 changed files
with
3,093 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
npm-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# This file is supposed to be autogenerated for each environment. | ||
# To set default values for .env please use the file .env.default | ||
# You may want to add this .env file to .gitignore to save development | ||
# credentials | ||
|
||
HTTP_SERVER_PORT=5000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# This file should be safe to commit and can act as documentation for all | ||
# the possible configurations of our server. | ||
|
||
# This file contains the default environment variables, by default, | ||
# it is third in precedence: | ||
# 1. process environment variables | ||
# 2. `.env` file contents | ||
# 3. `.env.default` file contents. | ||
|
||
HTTP_SERVER_PORT=3000 | ||
HTTP_SERVER_HOST=0.0.0.0 | ||
|
||
# reset metrics at 00:00UTC | ||
WKC_METRICS_RESET_AT_NIGHT=false | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: npm | ||
directory: "/" | ||
schedule: | ||
interval: daily | ||
open-pull-requests-limit: 10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
name: docker | ||
|
||
on: | ||
push: | ||
|
||
jobs: | ||
main: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v3 | ||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
# - | ||
# name: Login to DockerHub | ||
# uses: docker/login-action@v1 | ||
# with: | ||
# username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
# password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
- name: Build and push | ||
id: docker_build | ||
uses: docker/build-push-action@v5 | ||
with: | ||
# push: true | ||
tags: well-known-components/template-server:latest | ||
# build-args: | | ||
# arg1=value1 | ||
# arg2=value2 | ||
- name: Image digest | ||
run: echo ${{ steps.docker_build.outputs.digest }} | ||
|
||
|
||
# QUAY | ||
# - uses: actions/checkout@v2 | ||
# - name: Build Image | ||
# id: build-image | ||
# uses: redhat-actions/buildah-build@v2 | ||
# with: | ||
# image: IMAGENAME | ||
# tags: ${{ github.sha }} next | ||
# dockerfiles: | | ||
# ./Dockerfile | ||
|
||
# # Podman Login action (https://github.com/redhat-actions/podman-login) also be used to log in, | ||
# # in which case 'username' and 'password' can be omitted. | ||
# - name: Push To quay.io | ||
# id: push-to-quay | ||
# uses: redhat-actions/push-to-registry@v2 | ||
# with: | ||
# image: ${{ steps.build-image.outputs.image }} | ||
# tags: ${{ steps.build-image.outputs.tags }} | ||
# registry: quay.io/decentraland | ||
# username: ${{ secrets.QUAY_USERNAME }} | ||
# password: ${{ secrets.QUAY_TOKEN }} | ||
|
||
# - name: Print image url | ||
# run: echo "Image pushed to ${{ steps.push-to-quay.outputs.registry-paths }}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
name: node | ||
|
||
on: | ||
push: | ||
|
||
jobs: | ||
install: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@master | ||
- name: Use Node.js 18.x | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: 18.x | ||
cache: yarn | ||
- name: install | ||
run: yarn | ||
- name: build | ||
run: yarn build | ||
- name: test | ||
run: yarn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
dist/ | ||
node_modules/ | ||
**/.DS_Store | ||
coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"type": "node", | ||
"request": "launch", | ||
"name": "Launch Program", | ||
"restart": true, | ||
"skipFiles": [ | ||
"<node_internals>/**/*.js", | ||
"node_modules/**/*.js" | ||
], | ||
"runtimeExecutable": "node", | ||
"sourceMaps": true, | ||
"showAsyncStacks": true, | ||
"autoAttachChildProcesses": true, | ||
"runtimeArgs": [ | ||
"--preserve-symlinks" | ||
], | ||
"outFiles": [ | ||
"${workspaceFolder}/dist/**/*.js" | ||
], | ||
"program": "${workspaceFolder}/dist/index.js", | ||
"preLaunchTask": "npm: build" | ||
}, | ||
{ | ||
"name": "Debug Jest Tests", | ||
"type": "node", | ||
"request": "launch", | ||
"runtimeArgs": [ | ||
"--inspect-brk", | ||
"${workspaceRoot}/node_modules/.bin/jest", | ||
"--runInBand" | ||
], | ||
"console": "integratedTerminal", | ||
"internalConsoleOptions": "neverOpen", | ||
"port": 9229 | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"version": "2.0.0", | ||
"tasks": [ | ||
{ | ||
"type": "npm", | ||
"script": "build", | ||
"options": { | ||
"env": { | ||
"NODE_ENV": "development" | ||
} | ||
}, | ||
"group": { | ||
"kind": "build", | ||
"isDefault": true | ||
}, | ||
"problemMatcher": [ | ||
"$tsc" | ||
], | ||
"label": "npm: build", | ||
"detail": "build" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
ARG RUN | ||
|
||
FROM node:lts as builderenv | ||
|
||
WORKDIR /app | ||
|
||
# some packages require a build step | ||
RUN apt-get update && apt-get -y -qq install build-essential | ||
|
||
# We use Tini to handle signals and PID1 (https://github.com/krallin/tini, read why here https://github.com/krallin/tini/issues/8) | ||
ENV TINI_VERSION v0.19.0 | ||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini | ||
RUN chmod +x /tini | ||
|
||
# install dependencies | ||
COPY package.json /app/package.json | ||
COPY yarn.lock /app/yarn.lock | ||
RUN yarn | ||
|
||
# build the app | ||
COPY . /app | ||
RUN yarn build | ||
RUN yarn test | ||
|
||
# remove devDependencies, keep only used dependencies | ||
RUN yarn install --frozen-lockfile --production | ||
|
||
########################## END OF BUILD STAGE ########################## | ||
|
||
FROM node:lts | ||
|
||
# NODE_ENV is used to configure some runtime options, like JSON logger | ||
ENV NODE_ENV production | ||
|
||
WORKDIR /app | ||
COPY --from=builderenv /app /app | ||
COPY --from=builderenv /tini /tini | ||
# Please _DO NOT_ use a custom ENTRYPOINT because it may prevent signals | ||
# (i.e. SIGTERM) to reach the service | ||
# Read more here: https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/ | ||
# and: https://www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/ | ||
ENTRYPOINT ["/tini", "--"] | ||
# Run the program under Tini | ||
CMD [ "/usr/local/bin/node", "--trace-warnings", "--abort-on-uncaught-exception", "--unhandled-rejections=strict", "dist/index.js" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# template-server | ||
|
||
## Architecture | ||
|
||
Extension of "ports and adapters architecture", also known as "hexagonal architecture". | ||
|
||
With this architecture, code is organized into several layers: logic, controllers, adapters, and components (ports). | ||
|
||
## Application lifecycle | ||
|
||
1. **Start application lifecycle** - Handled by [src/index.ts](src/index.ts) in only one line of code: `Lifecycle.run({ main, initComponents })` | ||
2. **Create components** - Handled by [src/components.ts](src/components.ts) in the function `initComponents` | ||
3. **Wire application & start components** - Handled by [src/service.ts](src/service.ts) in the funciton `main`. | ||
1. First wire HTTP routes and other events with [controllers](#src/controllers) | ||
2. Then call to `startComponents()` to initialize the components (i.e. http-listener) | ||
|
||
The same lifecycle is also valid for tests: [test/components.ts](test/components.ts) | ||
|
||
## Namespaces | ||
|
||
### src/logic | ||
|
||
Deals with pure business logic and shouldn't have side-effects or throw exceptions. | ||
|
||
### src/controllers | ||
|
||
The "glue" between all the other layers, orchestrating calls between pure business logic and adapters. | ||
|
||
Controllers always receive an hydrated context containing components and parameters to call the business logic e.g: | ||
|
||
```ts | ||
// handler for /ping | ||
export async function pingHandler(context: { | ||
url: URL // parameter added by http-server | ||
components: AppComponents // components of the app, part of the global context | ||
}) { | ||
components.metrics.increment("test_ping_counter") | ||
return { status: 200 } | ||
} | ||
``` | ||
|
||
### src/adapters | ||
|
||
The layer that converts external data representations into internal ones, and vice-versa. Acts as buffer to protect the service from changes in the outside world; when a data representation changes, you only need to change how the adapters deal with it. | ||
|
||
### src/components.ts | ||
|
||
We use the components abstraction to organize our adapters (e.g. HTTP client, database client, redis client) and any other logic that needs to track mutable state or encode dependencies between stateful components. For every environment (e.g. test, e2e, prod, staging...) we have a different version of our component systems, enabling us to easily inject mocks or different implementations for different contexts. | ||
|
||
We make components available to incoming http and kafka handlers. For instance, the http-server handlers have access to things like the database or HTTP components, and pass them down to the controller level for general use. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module.exports = { | ||
transform: { | ||
"^.+\\.(ts|tsx)$": ["ts-jest", {tsconfig: "test/tsconfig.json"}] | ||
}, | ||
moduleFileExtensions: ["ts", "js"], | ||
coverageDirectory: "coverage", | ||
collectCoverageFrom: ["src/**/*.ts", "src/**/*.js"], | ||
testMatch: ["**/*.spec.(ts)"], | ||
testEnvironment: "node", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "template-server", | ||
"scripts": { | ||
"build": "tsc -p tsconfig.json", | ||
"start": "node --trace-warnings --abort-on-uncaught-exception --unhandled-rejections=strict dist/index.js", | ||
"test": "jest --forceExit --detectOpenHandles --coverage --verbose" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.11.28", | ||
"@well-known-components/test-helpers": "^1.5.6", | ||
"typescript": "^5.4.2" | ||
}, | ||
"prettier": { | ||
"printWidth": 120, | ||
"semi": false, | ||
"singleQuote": true, | ||
"trailingComma": "none", | ||
"tabWidth": 2 | ||
}, | ||
"dependencies": { | ||
"@well-known-components/env-config-provider": "^1.2.0", | ||
"@well-known-components/http-server": "^2.1.0", | ||
"@well-known-components/interfaces": "^1.4.3", | ||
"@well-known-components/logger": "^3.1.3", | ||
"@well-known-components/metrics": "^2.1.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Here goes all the code adapters, transforming one data type into another. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { createDotEnvConfigComponent } from '@well-known-components/env-config-provider' | ||
import { | ||
createServerComponent, | ||
createStatusCheckComponent, | ||
instrumentHttpServerWithPromClientRegistry | ||
} from '@well-known-components/http-server' | ||
import { createLogComponent } from '@well-known-components/logger' | ||
import { createMetricsComponent } from '@well-known-components/metrics' | ||
import { AppComponents, GlobalContext } from './types' | ||
import { metricDeclarations } from './metrics' | ||
|
||
// Initialize all the components of the app | ||
export async function initComponents(): Promise<AppComponents> { | ||
const config = await createDotEnvConfigComponent({ path: ['.env.default', '.env'] }) | ||
const metrics = await createMetricsComponent(metricDeclarations, { config }) | ||
const logs = await createLogComponent({ metrics }) | ||
const server = await createServerComponent<GlobalContext>({ config, logs }, {}) | ||
const statusChecks = await createStatusCheckComponent({ server, config }) | ||
|
||
await instrumentHttpServerWithPromClientRegistry({ metrics, server, config, registry: metrics.registry! }) | ||
|
||
return { | ||
config, | ||
logs, | ||
server, | ||
statusChecks, | ||
metrics | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { HandlerContextWithPath } from "../../types" | ||
|
||
// handlers arguments only type what they need, to make unit testing easier | ||
export async function pingHandler(context: Pick<HandlerContextWithPath<"metrics", "/ping">, "url" | "components">) { | ||
const { | ||
url, | ||
components: { metrics }, | ||
} = context | ||
|
||
metrics.increment("test_ping_counter", { | ||
pathname: url.pathname, | ||
}) | ||
|
||
return { | ||
body: url.pathname, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Router } from "@well-known-components/http-server" | ||
import { GlobalContext } from "../types" | ||
import { pingHandler } from "./handlers/ping-handler" | ||
|
||
// We return the entire router because it will be easier to test than a whole server | ||
export async function setupRouter(globalContext: GlobalContext): Promise<Router<GlobalContext>> { | ||
const router = new Router<GlobalContext>() | ||
|
||
router.get("/ping", pingHandler) | ||
|
||
return router | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { Lifecycle } from "@well-known-components/interfaces" | ||
import { initComponents } from "./components" | ||
import { main } from "./service" | ||
|
||
// This file is the program entry point, it only calls the Lifecycle function | ||
Lifecycle.run({ main, initComponents }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Here goes all the unit-testable functions. |
Oops, something went wrong.