Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
WoH committed Nov 19, 2021
1 parent 142557c commit c24e334
Show file tree
Hide file tree
Showing 38 changed files with 26,959 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
on: [push, pull_request]
name: CI
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "16"
cache: "yarn"

- name: Install
run: yarn install --ignore-scripts

- name: Check
run: yarn run typecheck

- name: Lint
run: yarn run lint

- name: Test
run: yarn run test
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
yarn-error.log
11 changes: 11 additions & 0 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"lerna": "4.0.0",
"version": "0.0.0",
"useWorkspaces": true,
"npmClient": "yarn",
"command": {
"run": {
"stream": true
}
}
}
20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "cdtcloud-deploymentserver",
"version": "0.0.0",
"repository": "git@github.com:EclipseSource/cdtcloud-deploymentserver.git",
"author": "WoH <wolfgang@hey.com>",
"license": "EPL-2.0",
"private": true,
"workspaces": [
"packages/*",
"packages/theia-extension/*"
],
"scripts": {
"test": "lerna run --parallel test",
"typecheck": "lerna run --parallel typecheck",
"lint": "lerna run --parallel lint"
},
"dependencies": {
"lerna": "^4.0.0"
}
}
1 change: 1 addition & 0 deletions packages/deployment-server/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
11 changes: 11 additions & 0 deletions packages/deployment-server/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
root: true,
extends: 'standard-with-typescript',
env: {
node: true
},
parserOptions: {
tsconfigRootDir: __dirname,
project: 'tsconfig.json'
}
}
3 changes: 3 additions & 0 deletions packages/deployment-server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
dist
.nyc_output
17 changes: 17 additions & 0 deletions packages/deployment-server/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
// 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": [
{
"name": "Debug Deployment-Server tests",
"request": "launch",
"runtimeArgs": ["run", "test"],
"runtimeExecutable": "yarn",
"cwd": "${workspaceFolder}/packages/deployment-server",
"skipFiles": ["<node_internals>/**"],
"type": "node"
}
]
}
47 changes: 47 additions & 0 deletions packages/deployment-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "deployment-server",
"version": "0.0.0",
"main": "src/index.ts",
"repository": "git@github.com:EclipseSource/cdtcloud-deploymentserver.git",
"author": "WoH <wolfgang@hey.com>",
"license": "EPL-2.0",
"type": "module",
"scripts": {
"dev": "nodemon -x node --experimental-loader esbuild-node-loader src/index.ts",
"start": "node --experimental-loader esbuild-node-loader src/index.ts",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"test": "tap --node-arg=--experimental-loader=esbuild-node-loader --no-check-coverage -T test/*.spec.ts",
"test:dev": "yarn run test -- -w --no-coverage-report",
"typecheck": "tsc -noEmit"
},
"dependencies": {
"@sinclair/typebox": "^0.21.2",
"close-with-grace": "^1.1.0",
"esbuild-node-loader": "^0.6.3",
"express": "^4.17.1",
"express-json-validator-middleware": "^2.2.1",
"pino-http": "^6.0.0",
"undici": "^4.10.1"
},
"devDependencies": {
"@types/express": "^4.17.13",
"@types/node": "^16.11.7",
"@types/pino-http": "^5.8.1",
"@types/tap": "^15.0.5",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"eslint": "^8.2.0",
"eslint-config-standard": "^16.0.3",
"eslint-config-standard-with-typescript": "^21.0.1",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.1",
"nodemon": "^2.0.15",
"pino-pretty": "^7.2.0",
"tap": "^15.1.1",
"typescript": "^4.5.2"
},
"engines": {
"node": ">=16.5.0"
}
}
22 changes: 22 additions & 0 deletions packages/deployment-server/src/devices/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Router } from 'express'
import { validate } from '../util/validate'

export default (router: Router): void => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
router.get('/devices', validate({}), async (req, res) => {
req.log.info('GET /devices')

res.json([
{
id: '1',
name: 'Device 1',
type: 'device',
status: 'online',
last_seen: '2020-01-01T00:00:00.000Z',
last_seen_at: '2020-01-01T00:00:00.000Z',
last_seen_ip: ''
}
]
)
})
}
15 changes: 15 additions & 0 deletions packages/deployment-server/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { exit } from 'node:process'
import { closeServer, createServer } from './server'
import closeWithGrace from 'close-with-grace'
import logger from './util/logger'

closeWithGrace({ delay: 500 }, closeServer)

createServer()
.then(() => logger.info('Listening'))
.catch((err) => {
closeServer({ err }).catch((err) => {
logger.error(err)
exit(1)
})
})
27 changes: 27 additions & 0 deletions packages/deployment-server/src/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { env } from 'process'
import { app } from './util/app'

import type { Server } from 'node:net'
import logger from './util/logger'

export let server: Server

export async function createServer (): Promise<void> {
server = app.listen(env.PORT)
}

export async function closeServer ({ err }: { err?: Error }): Promise<void> {
if (err != null) {
logger.error(err)
}

await new Promise<void>((resolve, reject) => {
server.close((err) => {
if (err != null) {
reject(err)
} else {
resolve()
}
})
})
}
14 changes: 14 additions & 0 deletions packages/deployment-server/src/util/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import express from 'express'
import { pinoHttp } from './logger'
import deviceRoutes from '../devices'

export const app = express()

app.disable('x-powered-by')
app.disable('etag')

app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(pinoHttp)

deviceRoutes(app)
26 changes: 26 additions & 0 deletions packages/deployment-server/src/util/errorHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Request, Response, NextFunction } from 'express'
import { ValidationError } from 'express-json-validator-middleware'
import { logger } from './logger'

export function errorHandler (
err: Error,
_req: Request,
res: Response,
_next: NextFunction
): Response {
if (err instanceof Error) {
if (err instanceof SyntaxError) {
return res.status(400).json(err)
} else if (err instanceof ValidationError) {
return res
.status(400)
.json({
message: err.message.length > 0 ? err.message : 'Bad Request',
errors: err.validationErrors
})
}
}

logger.error(err, 'Caught Error')
return res.sendStatus(500)
}
16 changes: 16 additions & 0 deletions packages/deployment-server/src/util/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pino from 'pino-http'

const devTransport = {
target: 'pino-pretty',
options: {
colorize: true
}
}

export const pinoHttp = pino({
transport: process.env.NODE_ENV === 'production' ? undefined : devTransport
})

export const logger = pinoHttp.logger

export default logger
9 changes: 9 additions & 0 deletions packages/deployment-server/src/util/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Validator } from 'express-json-validator-middleware'
import { RequestHandler } from 'express'

export const validate = new Validator({
coerceTypes: true,
useDefaults: 'empty'
}).validate as <Params = any, ResBody = any, ReqBody = any, Locals = Record<string, any>>(
...args: Parameters<Validator['validate']>
) => RequestHandler<Params, ResBody, ReqBody, Locals>
39 changes: 39 additions & 0 deletions packages/deployment-server/test/sample.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
import tap from 'tap'
import { server, close } from './util/server'
import { fetch } from './util/fetch'
import type { AddressInfo } from 'node:net'

const { before, teardown, test } = tap

let baseUrl: string

before(async () => {
server.listen()
const { port } = server.address() as AddressInfo
baseUrl = `http://localhost:${port}`
})

teardown(async () => {
close()
})

test('GET retrieves according to primary preference if possible', async (t) => {
const response = await fetch(`${baseUrl}/devices`, {
method: 'GET'
})

t.equal(response.status, 200)

const body = await response.json()

t.match(body, [{
id: '1',
name: 'Device 1',
type: 'device',
status: 'online',
last_seen: '2020-01-01T00:00:00.000Z',
last_seen_at: '2020-01-01T00:00:00.000Z',
last_seen_ip: ''
}])
})
12 changes: 12 additions & 0 deletions packages/deployment-server/test/util/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import undici from 'undici'

const { Agent, setGlobalDispatcher, fetch } = undici

const testAgent = new Agent({
keepAliveTimeout: 10,
keepAliveMaxTimeout: 10
})

setGlobalDispatcher(testAgent)

export { undici, fetch }
16 changes: 16 additions & 0 deletions packages/deployment-server/test/util/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { app } from '../../src/util/app'
import { createServer } from 'http'

export const server = createServer(app)

export const close = async (): Promise<void> => {
await new Promise<void>((resolve, reject) => {
server.close((err) => {
if (err != null) {
reject(err)
} else {
resolve()
}
})
})
}
16 changes: 16 additions & 0 deletions packages/deployment-server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"rootDir": ".",
"outDir": "dist",
"target": "es2020",
"lib": ["es2020", "DOM"],
"module": "es2022",
"moduleResolution": "node",
"strict": true,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"declaration": true,
"isolatedModules": true,
"skipLibCheck": true
}
}
Empty file added packages/device-connector/.keep
Empty file.
6 changes: 6 additions & 0 deletions packages/theia-extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
.browser_modules
lib
*.log
*-app/*
!*-app/package.json

0 comments on commit c24e334

Please sign in to comment.