diff --git a/.env.example b/.env.example index 8e19eccf..e69de29b 100644 --- a/.env.example +++ b/.env.example @@ -1 +0,0 @@ -COUCHDB_URL="http://localhost:5984" diff --git a/.eslintrc.js b/.eslintrc.js index 0b15c56e..dd47d317 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,7 +8,7 @@ module.exports = { ], parser: '@typescript-eslint/parser', parserOptions: { - project: ['./tsconfig.json', './test/tsconfig.json', './src/db/tsconfig.json'], + project: ['./tsconfig.json', './test/tsconfig.json'], tsconfigRootDir: './', }, plugins: ['@typescript-eslint', 'prettier'], diff --git a/.github/ISSUE_TEMPLATE/security.md b/.github/ISSUE_TEMPLATE/security.md index 220fccc7..76ca873d 100644 --- a/.github/ISSUE_TEMPLATE/security.md +++ b/.github/ISSUE_TEMPLATE/security.md @@ -1,6 +1,8 @@ --- name: 👮 Security Issue about: Responsible Disclosure +labels: 'security' + --- ## 👮 [Responsible Disclosure](https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md) @@ -8,4 +10,4 @@ about: Responsible Disclosure Do not open issues that might have security implications. It is critical that security related issues are reported privately so we have time to address them before they become public knowledge. -Vulnerabilities can also be reported by emailing security@hospitalrun.io +Vulnerabilities can also be reported by emailing security@hospitalrun.io diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10095473..558acd59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node-version: [12.x] + node-version: [10.x, 12.x, 14.x] os: [ubuntu-latest, windows-latest, macOS-latest] # exclude: # - os: windows-latest @@ -36,35 +36,3 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: ./lcov.info - - yarn: - runs-on: ${{ matrix.os }} - strategy: - matrix: - node-version: [12.x] - os: [ubuntu-latest, windows-latest, macOS-latest] - # exclude: - # - os: windows-latest - # node-version: 13.x - steps: - - run: git config --global core.autocrlf false # this is needed to prevent git changing EOL after cloning on Windows OS - - uses: actions/checkout@v2 - - name: Use Node.js - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: Init yarn - run: | - npm install -g yarn - - name: Install with yarn - run: | - yarn install - - name: Lint code - run: | - yarn lint - - name: Build - run: | - yarn build:all - - name: Run tests - run: | - yarn test diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..8df05f7f --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,54 @@ +name: "Code scanning" + +on: + push: + branches: [master] + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + schedule: + - cron: '0 6 * * 6' + +jobs: + CodeQL-Build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.gitignore b/.gitignore index 14bc0e75..71eb1634 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,4 @@ db/* !db/config.json !db/designs .env +.idea/ diff --git a/.prettierrc b/.prettierrc index 48360d60..87b4a12b 100644 --- a/.prettierrc +++ b/.prettierrc @@ -6,7 +6,7 @@ "trailingComma": "all", "bracketSpacing": true, "jsxBracketSameLine": false, - "arrowParens": "avoid", + "arrowParens": "always", "endOfLine": "lf", "parser": "typescript" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 41a1c654..be9d650f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.0.0-alpha.3](https://github.com/HospitalRun/hospitalrun-server/compare/v2.0.0-alpha.2...v2.0.0-alpha.3) (2020-09-01) + + +### Features + +* add docker compose ([237c1a9](https://github.com/HospitalRun/hospitalrun-server/commit/237c1a99a125fcde565f8e31c5d6186308e9257b)) + ## 2.0.0-alpha.2 (2020-05-17) diff --git a/README.md b/README.md index f1e41551..fcf71fc2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@
-![Status](https://img.shields.io/badge/Status-developing-brightgree) [![Release](https://img.shields.io/github/release/HospitalRun/hospitalrun-server.svg)](https://github.com/HospitalRun/hospitalrun-server/releases) [![Version](https://img.shields.io/github/package-json/v/hospitalrun/hospitalrun-frontend)](https://github.com/HospitalRun/hospitalrun-server/releases) [![GitHub CI](https://github.com/HospitalRun/server/workflows/GitHub%20CI/badge.svg)](https://github.com/HospitalRun/server/actions) [![Coverage Status](https://coveralls.io/repos/github/HospitalRun/hospitalrun-server/badge.svg?branch=master)](https://coveralls.io/github/HospitalRun/hospitalrun-server?branch=master) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/HospitalRun/hospitalrun-server.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/HospitalRun/hospitalrun-server/context:javascript) [![Documentation Status](https://readthedocs.org/projects/hospitalrun-server/badge/?version=latest)](https://hospitalrun-server.readthedocs.io) +![Status](https://img.shields.io/badge/Status-developing-brightgree) [![Release](https://img.shields.io/github/release/HospitalRun/hospitalrun-server.svg)](https://github.com/HospitalRun/hospitalrun-server/releases) [![Version](https://img.shields.io/github/package-json/v/hospitalrun/hospitalrun-server)](https://github.com/HospitalRun/hospitalrun-server/releases) [![GitHub CI](https://github.com/HospitalRun/server/workflows/GitHub%20CI/badge.svg)](https://github.com/HospitalRun/server/actions) [![Coverage Status](https://coveralls.io/repos/github/HospitalRun/hospitalrun-server/badge.svg?branch=master)](https://coveralls.io/github/HospitalRun/hospitalrun-server?branch=master) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/HospitalRun/hospitalrun-server.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/HospitalRun/hospitalrun-server/context:javascript) ![Code scanning](https://github.com/HospitalRun/hospitalrun-server/workflows/Code%20scanning/badge.svg?branch=master) [![Documentation Status](https://readthedocs.org/projects/hospitalrun-server/badge/?version=latest)](https://hospitalrun-server.readthedocs.io) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FHospitalRun%2Fhospitalrun-server.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FHospitalRun%2Fhospitalrun-server?ref=badge_shield) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) ![dependabot](https://api.dependabot.com/badges/status?host=github&repo=HospitalRun/hospitalrun-server) [![Slack](https://hospitalrun-slack.herokuapp.com/badge.svg)](https://hospitalrun-slack.herokuapp.com)
@@ -20,8 +20,9 @@ Contributions are always welcome. Before contributing please read our [contribut 1. [Fork](https://github.com/HospitalRun/hospitalrun-server/fork) this repository to your own GitHub account 2. Clone it to your local machine 3. Navigate to the cloned folder: `cd hospitalrun-server` -4. Install the dependencies: `npm install` or `yarn install` -5. Run `npm run dev` or `yarn dev` to build and watch for code changes: +4. Install the dependencies: `npm install` +5. Check that [env variables](https://github.com/HospitalRun/hospitalrun-server#environment) are set correctly +6. Run `npm run dev` to build and watch for code changes: - a development database will start on http://localhost:5984 - you can access its Admin interface on http://localhost:5984/_utils, `username: dev` and `password: dev` @@ -32,16 +33,16 @@ In order to optimize the workflow and to prevent multiple contributors working o In order to run `hospitalrun-server` you need to set the correct environment variables. Since [dotenv](https://www.npmjs.com/package/dotenv) is already included, it is just matter of renaming `.env.example` file to `.env`: this file include all of the mandatory defaults. ## Development Database -This project uses [pouchdb-server](https://www.npmjs.com/package/pouchdb-server) for development and you, as contributor, don't need to provide your own CouchDB instance. Upon first run of the `dev` script (`npm run dev` or `yarn dev`), a new `data` folder will be created inside the `./db` folder. The database credentials are: `username: dev` and `password: dev`. The file `./db/config.json` contains the DB's configuration: you can change it if you want, but please don't commit any changes to it. +This project uses [pouchdb-server](https://www.npmjs.com/package/pouchdb-server) for development and you, as contributor, don't need to provide your own CouchDB instance. Upon first run of the `dev` script (`npm run dev`), a new `data` folder will be created inside the `./db` folder. The database credentials are: `username: dev` and `password: dev`. The file `./db/config.json` contains the DB's configuration: you can change it if you want, but please don't commit any changes to it. **Note: PouchDB-server is meant to be use only during development. Please don't deploy any production/testing HospitalRun instances on it. For production deployments please follow the deployment guide.** ## Tests -Every code additions or fixs on the existing code, has to be tested. This project uses [node-tap](https://node-tap.org/) as test runner. To run all tests use `npm run test` or `yarn test`. +Every code additions or fixs on the existing code, has to be tested. This project uses [node-tap](https://node-tap.org/) as test runner. To run all tests use `npm run test`. ## How to commit -This repo uses [Conventional Commits](https://www.conventionalcommits.org/). [Commitizen](https://github.com/commitizen/cz-cli) is mandatory for making proper commits. Once you have staged your changes, can run `npm run commit` or `yarn commit` from the root directory in order to commit following our standards. +This repo uses [Conventional Commits](https://www.conventionalcommits.org/). [Commitizen](https://github.com/commitizen/cz-cli) is mandatory for making proper commits. Once you have staged your changes, can run `npm run commit` from the root directory in order to commit following our standards. # Documentation ## DataBase @@ -53,46 +54,6 @@ Read more at HospitalRun Services. -
- -# Behind HospitalRun - -## Hosted by - -[](https://openjsf.org/projects/#atlarge) - -## Sponsors - -[![Sponsors](https://opencollective.com/hospitalrun/sponsors.svg?width=890)](https://opencollective.com/hospitalrun/contribute/sponsors-336/checkout) - -## Backers - -[![Backers](https://opencollective.com/hospitalrun/backers.svg?width=890)](https://opencollective.com/hospitalrun/contribute/backers-335/checkout) - -## Lead Maintainer -[
Maksim Sinik](https://github.com/fox1t)
- -## Core Team - - -| [
Stefano Casasola](https://github.com/irvelervel) |[
Michael Daly](https://github.com/MichaelDalyDev)|[
Riccardo Gulin](https://github.com/nclBaz) | [
Grace Lau](https://github.com/lauggh) | [
Jack Meyer](https://github.com/jackcmeyer) | [
Matteo Vivona](https://github.com/tehKapa) | -|---|---|---|---|---|---| - - -## Medical Supervisor - -[
M.D. Daniele Piccolo](https://it.linkedin.com/in/danielepiccolo)
- -## Contributors - -[![Contributors](https://opencollective.com/hospitalrun/contributors.svg?width=960&button=false)](https://github.com/HospitalRun/hospitalrun-frontend/graphs/contributors) - -## Founders - - -| [
John Kleinschmidtr](https://github.com/jkleinsc) | [
Joel Worrall](https://github.com/tangollama) | [
Joel Glovier](https://github.com/jglovier) | -|---|---|---| - # License Released under the [MIT license](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..798ae845 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Responsible Disclosure Policy + +A responsible disclosure policy helps protect the project and its users from security vulnerabilities discovered in the project’s scope by employing a process where vulnerabilities are publicly disclosed after a reasonable time period to allow patching the vulnerability. + +All security bugs are taken seriously and are considered as top priority. +Your efforts to responsibly disclose your findings are appreciated and will be taken into account to acknowledge your contributions. + +## Supported Versions + +This versions of HospitalRun project are currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 2.0.0 | :white_check_mark: | +| 1.0.0-beta | :x: | + +## Reporting a Vulnerability + +Report security bugs by opening a new [Security Issue](https://github.com/HospitalRun/hospitalrun-server/issues/new?template=security.md). You can also report a vulnerability by emailing security@hospitalrun.io. + +Report security bugs in third-party modules to the maintainer or team maintaining the module. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..76b956bc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3' + +services: + mongo: + image: mongo + restart: always + environment: + MONGO_INITDB_DATABASE: hospitalrun + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: password diff --git a/package.json b/package.json index 997445f6..94fbfc11 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@hospitalrun/server", - "version": "2.0.0-alpha.2", - "description": "HospitalRun Nodejs server", + "version": "2.0.0-alpha.3", + "description": "HospitalRun Node.js server", "main": "dist", "repository": { "type": "git", @@ -11,16 +11,13 @@ "ddoc": "node bin/ddoc", "commit": "npx git-cz", "build": "npm run clean && tsc -p ./tsconfig.json", - "build:all": "run-s build build:ddoc build:designs", - "build:ddoc": "rimraf bin && tsc -p ./src/bin/tsconfig.json", - "build:designs": "npm run ddoc -- src/db/designs -c src/db/tsconfig.json", + "build:all": "run-s build", "start": "node dist", "clean": "rimraf dist", - "dev:db": "pouchdb-server --config ./db/config.json", - "dev:build": "tsc --incremental -p tsconfig.json && npm run build:designs", + "dev:build": "tsc --incremental -p tsconfig.json", "dev:start": "node --inspect -r source-map-support/register -r dotenv/config dist/index.js | pino-colada", "dev:watch": "cross-env NODE_ENV=development npm run clean && nodemon -w src -e ts --exec \"npm run dev:build && npm run dev:start\"", - "dev": "run-p dev:db dev:watch", + "dev": "run-p dev:watch", "update": "yarn upgrade-interactive --latest", "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\" \"test/**/*.{js,jsx,ts,tsx}\"", "lint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx}\" \"test/**/*.{js,jsx,ts,tsx}\" --fix", @@ -33,40 +30,39 @@ "author": "Maksim Sinik ", "license": "MIT", "dependencies": { - "fastify": "~2.14.0", - "fastify-autoload": "~1.2.2", - "fastify-blipp": "~2.3.0", - "fastify-cors": "~3.0.2", - "fastify-helmet": "~3.0.2", - "fastify-http-proxy": "~3.1.0", - "fastify-no-icon": "~3.0.0", - "fastify-plugin": "~1.6.1", - "make-promises-safe": "~5.1.0", - "nano": "~8.2.1", - "qs": "~6.9.1", - "require-from-string": "~2.0.2" + "fastify": "~3.3.0", + "fastify-autoload": "~3.0.8", + "fastify-blipp": "~3.0.0", + "fastify-cors": "~4.1.0", + "fastify-gql": "~5.6.0", + "fastify-helmet": "~5.0.1", + "fastify-no-icon": "~4.0.0", + "fastify-plugin": "~2.3.3", + "graphql-tools": "~6.1.0" }, "devDependencies": { - "@commitlint/cli": "~8.3.5", - "@commitlint/config-conventional": "~8.3.4", - "@commitlint/prompt": "~8.3.5", + "@commitlint/cli": "~9.1.2", + "@commitlint/config-conventional": "~9.1.1", + "@commitlint/prompt": "~9.1.1", "@types/glob": "~7.1.1", "@types/mkdirp": "~1.0.0", - "@types/node": "~13.13.2", + "@types/node": "~14.6.0", "@types/qs": "6.9.1", - "@typescript-eslint/eslint-plugin": "~2.30.0", - "@typescript-eslint/parser": "~2.31.0", "@types/require-from-string": "~1.2.0", - "@types/sade": "~1.6.0", - "chalk": "~4.0.0", - "commitizen": "~4.1.2", + "@types/sade": "~1.7.0", + "@types/tap": "~14.10.0", + "@types/ws": "~7.2.6", + "@typescript-eslint/eslint-plugin": "~2.34.0", + "@typescript-eslint/parser": "~2.34.0", + "chalk": "~4.1.0", + "commitizen": "~4.2.1", "commitlint-config-cz": "~0.13.0", "cross-env": "~7.0.0", "cz-conventional-changelog": "~3.2.0", "dotenv": "~8.2.0", "eslint": "~6.8.0", "eslint-config-prettier": "~6.11.0", - "eslint-plugin-import": "~2.20.0", + "eslint-plugin-import": "~2.22.0", "eslint-plugin-prettier": "~3.1.0", "glob": "~7.1.6", "husky": "~4.2.0", @@ -74,13 +70,13 @@ "mkdirp": "~1.0.3", "nodemon": "~2.0.0", "npm-run-all": "~4.1.5", - "pino-colada": "~2.0.0", + "pino-colada": "~2.1.0", "pouchdb-server": "~4.2.0", - "prettier": "~2.0.2", + "prettier": "~2.1.1", "rimraf": "~3.0.0", "sade": "~1.7.3", "source-map-support": "~0.5.16", - "tap": "~14.10.5", + "tap": "~14.10.8", "tap-mocha-reporter": "~5.0.0", "typescript": "~3.9.2" }, diff --git a/src/app.ts b/src/app.ts index 8a62d226..4b76ac52 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,40 +1,26 @@ +import { Server, IncomingMessage, ServerResponse } from 'http' +import { FastifyInstance, FastifyPluginOptions } from 'fastify' +import fastifyCors from 'fastify-cors' +import fastifyHelmet from 'fastify-helmet' +import fastifyAutoload from 'fastify-autoload' import { join } from 'path' -import AutoLoad from 'fastify-autoload' -import { FastifyInstance } from 'fastify' -import { nextCallback } from 'fastify-plugin' -import noIcon from 'fastify-no-icon' -import helmet from 'fastify-helmet' -import qs from 'qs' -import cors from 'fastify-cors' +import GQL from 'fastify-gql' +import schema from './graphql/schema' +import resolvers from './graphql/resolvers' -function HospitalRun(fastify: FastifyInstance, opts: any, next: nextCallback) { - fastify.register(cors, { +export default ( + fastify: FastifyInstance, + _: FastifyPluginOptions, + next: (error?: Error) => void, +) => { + fastify.register(fastifyCors, { allowedHeaders: ['Content-Type', 'Authorization'], }) - fastify.register(helmet) - fastify.register(noIcon) - - // This loads all application wide plugins defined in plugins folder - fastify.register(AutoLoad, { - dir: join(__dirname, 'plugins'), - includeTypeScript: true, - options: { ...opts }, - }) - - // This loads all routes and services defined in services folder - fastify.register(AutoLoad, { + fastify.register(fastifyHelmet) + fastify.register(fastifyAutoload, { dir: join(__dirname, 'services'), - includeTypeScript: true, - options: { ...opts }, }) + fastify.register(GQL, { schema, resolvers }) next() } - -HospitalRun.options = { - querystringParser: (str: string) => qs.parse(str), - logger: true, - ignoreTrailingSlash: true, -} - -export = HospitalRun diff --git a/src/bin/ddoc.ts b/src/bin/ddoc.ts deleted file mode 100644 index 9b75c229..00000000 --- a/src/bin/ddoc.ts +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env node - -import path from 'path' -import fs from 'fs' -import { promisify } from 'util' -import sade from 'sade' -import ts from 'typescript' -import requireFromString from 'require-from-string' -import originalGlob from 'glob' -import mkdirp from 'mkdirp' -import chalk from 'chalk' - -const stat = promisify(fs.stat) -const readFile = promisify(fs.readFile) -const writeFile = promisify(fs.writeFile) -const unlink = promisify(fs.unlink) -const glob = promisify(originalGlob) - -async function deleteOldDdocs(dest: string) { - const oldDdocs = await glob(path.join(dest, '**/*.json')) - return Promise.all(oldDdocs.map(file => unlink(file))) -} - -const prog = sade('ddoc') - -prog.version('0.1.0') - -prog - .command('build ', 'Build design document(s) from TypeScript soruce directory or file.', { - default: true, - }) - // .describe('Build design documents from TypeScript soruce directory or file.') - .option('-c, --config', 'Provide path to custom tsconfig.json', './tsconfig.json') - .example('build src/db/designs') - .example('build src/db/designs/patient.ts -c src/db/tsconfig.json') - .action(async (src, opts) => { - try { - const cwd = process.cwd() - const tsconfigPath = path.isAbsolute(opts.config) ? opts.config : path.join(cwd, opts.config) - - console.log( - `> ${chalk.bgBlueBright(chalk.black(' ddoc build config '))} ${chalk.cyan(tsconfigPath)}`, - ) - const tsconfig = require(tsconfigPath) // eslint-disable-line - - src = path.isAbsolute(src) ? path.normalize(src) : path.join(cwd, src) // eslint-disable-line - let srcStats: any - try { - srcStats = await stat(src) - } catch (err) { - if (err.code === 'ENOENT') { - console.log(chalk.bgGreen(chalk.black(`\n ddoc build - No input files found. Done. `))) - process.exit(0) - } - throw err - } - // use outDir if specified inside tsconfig, otherwise build json alongside ts files - let dest: string = tsconfig?.compilerOptions?.outDir - ? path.join(path.dirname(tsconfigPath), tsconfig.compilerOptions.outDir) - : '' - let ddocs: string[] - if (srcStats.isDirectory()) { - dest = dest || src - ddocs = await glob(path.join(src, '**/*.ts')) - } else { - dest = dest || path.dirname(src) - ddocs = [src] - } - - console.log(`> ${chalk.bgBlueBright(chalk.black(' ddoc build src '))} ${chalk.cyan(src)}`) - await mkdirp(dest) - await deleteOldDdocs(dest) - console.log(`> ${chalk.bgBlueBright(chalk.black(' ddoc build dest '))} ${chalk.cyan(dest)}`) - - const errors: { file: string; error: Error }[] = [] - await Promise.all( - ddocs.map(async srcPath => { - try { - const sourceFile = (await readFile(srcPath)).toString() - const output = ts.transpileModule(sourceFile, tsconfig) - const filename = path.basename(srcPath, '.ts') - const ddoc = requireFromString(output.outputText) - - const stringifiedDesign = JSON.stringify( - ddoc.default ?? ddoc, - (_, val) => { - if (typeof val === 'function') { - return val.toString() - } - return val - }, - 1, - ) - await writeFile(path.join(dest, `${filename}.json`), stringifiedDesign) - } catch (error) { - errors.push({ file: srcPath, error }) - } - }), - ) - if (errors.length > 0) { - errors.forEach(err => { - console.log( - `\n> ${chalk.bgRed(chalk.white(' ddoc build compile error '))} ${chalk.cyan( - err.file, - )}${err.error.stack?.toString()}\n`, - ) - }) - throw new Error( - `ddoc compilation failed. Resolve errors ${errors.length} ${ - errors.length > 1 ? 'files' : 'file' - } and try again.`, - ) - } - console.log(chalk.bgGreen(chalk.black(`\n ddoc build - done on ${ddocs.length} files. `))) - } catch (err) { - console.error(chalk.bgRed(chalk.white(` ${err.message} `))) - process.exit(1) - } - }) - -prog.parse(process.argv) diff --git a/src/db/design-document.ts b/src/db/design-document.ts deleted file mode 100644 index 0da8afd6..00000000 --- a/src/db/design-document.ts +++ /dev/null @@ -1,123 +0,0 @@ -// Reference: https://docs.couchdb.org/en/latest/ddocs/ddocs.html and https://docs.couchdb.org/en/latest/api/ddoc/common.html#put--db-_design-ddoc -interface DesignDocument { - _id: string - _rev?: string - language?: string // defaults to 'javascript' - autoupdate?: boolean // defaults to 'true' - // Reference: https://docs.couchdb.org/en/stable/api/ddoc/views.html#view-options - options?: { - local_seq?: boolean - include_design?: boolean - } - views?: { - [key: string]: { - /** - * Map functions accept a single document as the argument and (optionally) emit() key/value pairs that are stored in a view. - * Since version 1.1.0, map supports CommonJS modules and the require() function. - * - * Reference: https://docs.couchdb.org/en/master/ddocs/ddocs.html#map-functions - * @param {Object} doc - The document that is being processed - * @returns {void} - */ - map?(doc: T): void - /** - * Reduce functions take two required arguments of keys and values lists - the result of the related map function - and an optional third value which indicates if rereduce mode is active or not. - * Rereduce is used for additional reduce values list, so when it is true there is no information about related keys (first argument is null). - * - * Reference: https://docs.couchdb.org/en/master/ddocs/ddocs.html#reduce-and-rereduce-functions - * @param {[string, string][] | null} keys - Array of pairs of docid-key for related map function results. Always null if rereduce is running (has true value). - * @returns {Object} - */ - reduce?(keys: [string, string][] | null, values: any[], rereduce?: boolean): any - } - } - updates?: { - /** - * Update handlers are functions that clients can request to invoke server-side logic that will create or update a document. - * This feature allows a range of use cases such as providing a server-side last modified timestamp, - * updating individual fields in a document without first getting the latest revision, etc. - * - * Reference: https://docs.couchdb.org/en/master/ddocs/ddocs.html#update-functions - * @param {Object | null} doc - Thedocument that is being processed - * @param {Object} req - Request object - * @returns {[Object, any]} - the first element is the (updated or new) document, which is committed to the database; The second element is the response that will be sent back to the caller. - */ - [key: string]:

( - doc: P, - req: CouchDB.RequestObject, - ) => [Partial | null, any] - } - filters?: { - /** - * Filter functions mostly act like Show Functions and List Functions: they format, or filter the changes feed. - * - * Reference: https://docs.couchdb.org/en/master/ddocs/ddocs.html#filter-functions - * @param {Object} doc - The document that is being processed - * @param {Object} req - Request object - * @returns {boolean} - true means that doc passes the filter rules, false means that it does not - */ - [key: string]: (doc: T, req: CouchDB.RequestObject) => boolean - } - /** - * Used to prevent invalid or unauthorized document update requests from being stored. - * The function is passed the new document from the update request, the current document stored in the database, - * a User Context Object containing information about the user writing the document (if present), - * and a Security Object with lists of database security roles. - * - * Reference: https://docs.couchdb.org/en/master/ddocs/ddocs.html#validatefun - * @param {Object} newDoc - New version of document that will be stored - * @param {Object} oldDoc - Previous version of document that is already stored - * @param {Object} userCtx - User Context Object - * @param {Object} secObj - Security Object - * @returns {void} - */ - // - validate_doc_update?( // eslint-disable-line - newDoc: T, - oldDoc: T, - userCtx: CouchDB.UserCtx, - secObj: CouchDB.SecurityObject, - ): void - /** - * @deprecated in CouchDB 3.0, and will be removed in CouchDB 4.0 - */ - shows?: { - /** - * @deprecated in CouchDB 3.0, and will be removed in CouchDB 4.0 - * Show functions are used to represent documents in various formats, commonly as HTML pages with nice formatting. - * They can also be used to run server-side functions without requiring a pre-existing document. - * - * Reference: https://docs.couchdb.org/en/master/ddocs/ddocs.html#show-functions - * @param {Object} doc - The document that is being processed; may be omitted - * @param {Object} req - Request object - * @returns {Object | string} - */ - [key: string]: (doc: T, req: CouchDB.RequestObject) => string | CouchDB.ResponseObject | void - } - /** - * @deprecated in CouchDB 3.0, and will be removed in CouchDB 4.0 - */ - lists?: { - /** - * @deprecated in CouchDB 3.0, and will be removed in CouchDB 4.0 - * While Show Functions are used to customize document presentation, - * List Functions are used for the same purpose, but on View Functions results. - * - * Reference: https://docs.couchdb.org/en/master/ddocs/ddocs.html#list-functions - * @param {Object} head - View Head Information - * @param {Object} req - Request object - * @returns {string} Last chunk - */ - [key: string]: (head: CouchDB.ViewHeadInformation, req: CouchDB.RequestObject) => string | void - } - /** - * @deprecated in CouchDB 3.0, and will be removed in CouchDB 4.0 - * Rewrites the specified path by rules defined in the specified design document. - * The rewrite rules are defined by the rewrites field of the design document. - * The rewrites field can either be a string containing the a rewrite function or an array of rule definitions. - * - */ - rewrites?: ((req: CouchDB.Request2Object) => CouchDB.RewriteReturnObject) | CouchDB.RewriteRule[] -} - -export default DesignDocument diff --git a/src/db/design-functions-context.d.ts b/src/db/design-functions-context.d.ts deleted file mode 100644 index e5c447a6..00000000 --- a/src/db/design-functions-context.d.ts +++ /dev/null @@ -1,195 +0,0 @@ -// Reference: https://docs.couchdb.org/en/latest/query-server/javascript.html#design-functions-context - -declare namespace CouchDB { - type HttpMethods = 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'TRACE' - interface InitResp { - code?: number - json?: object - body?: string - base64?: string - headers?: any - stop?: boolean - } - - interface UserCtx { - db: string - name: string | null - roles: string[] - } - - interface SecurityObject { - admins: { - names: string[] - roles: string[] - } - members: { - names: string[] - roles: string[] - } - } - - interface DataBaseInformationObject { - db_name: string - committed_update_seq: number - doc_count: number - doc_del_count: number - compact_running: boolean - disk_format_version: number - disk_size: number - instance_start_time: string - purge_seq: number - update_seq: number - sizes: { - active: number - disk: number - external: number - } - } - - interface RequestObject { - body: string - cookie: unknown - form: unknown - headers: unknown - id: string | null - info: CouchDB.DataBaseInformationObject - method: HttpMethods - path: string[] - peer: string - query: unknown - raw_path: string - requested_path: string[] - secObj: CouchDB.SecurityObject - userCtx: CouchDB.UserCtx - uuid: string - } - - interface RewriteRule { - method?: string - from: string - to: string - query: unknown - } - - interface Request2Object { - body: string - cookie: unknown - headers: unknown - method: HttpMethods - path: string[] - peer: string - query: unknown - requested_path: string[] - raw_path: string - secObj: CouchDB.SecurityObject - userCtx: CouchDB.UserCtx - } - - interface RewriteReturnObject { - path: string - code?: number - query?: unknown - headers?: any - method?: HttpMethods - body?: string - } - - interface ResponseObject { - code?: number - json?: any - body?: string - base64?: string - headers?: any - stop?: boolean - } - - interface ViewHeadInformation { - total_rows: number - offset: number - } -} - -/** - * Emits a key-value pair for further processing by CouchDB after the map function is done. - * @param {string} key - The view key - * @param {any} value - The key’s associated value - * @returns {void} - */ -declare function emit(key: string, value: any): void -/** - * @deprecated since version 2.0 - * Extracts the next row from a related view result. - * @returns {Object} - View result row - */ -declare function getRow(): T - -/** - * A helper function to check if the provided value is an Array. - * @param {Object} obj - Any JavaScript value - * @returns {boolean} - */ -declare function isArray(obj: T): boolean - -/** - * Log a message to the CouchDB log (at the INFO level). - * @param {string} message - Message to be logged - * @returns {void} - */ -declare function log(message: string): void - -/** - * @deprecated since version 2.0 - * Registers callable handler for specified MIME key. - * @param {string} key - MIME key previously defined by registerType() - * @param {Function} value - MIME type handler - * @returns {void} - */ -declare function provides(key: string, func: Function): string | CouchDB.ResponseObject - -/** - * @deprecated since version 2.0 - * Registers list of MIME types by associated key. - * @param {string} key - MIME types - * @param {string[]} mimes - MMIME types enumeration - * @returns {void} - */ -declare function registerType(key: string, mimes: string[]): void - -/** - * @deprecated since version 2.0 - * Sends a single string chunk in response. - * @param {string} chunk - Text chunk - * @returns {void} - */ -declare function send(chunk: string): void - -/** - * @deprecated since version 2.0 - * Initiates chunked response. As an option, a custom response object may be sent at this point. For list-functions only! - * @param {Object} init_resp - InitResp object - * @returns {void} - */ -// eslint-disable-next-line -declare function start(init_resp?: CouchDB.InitResp): void - -/** - * Sum arr’s items. - * @param {number[]} arr - Array of numbers - * @returns {number} - */ -declare function sum(arr: number[]): number - -/** - * Encodes obj to JSON string. This is an alias for the JSON.stringify method. - * @param {any} obj - Array of numbers - * @returns {string} - */ -declare function toJSON(obj: any): string - -/** - * Reduce functions take two required arguments of keys and values lists - the result of the related map function - and an optional third value which indicates if rereduce mode is active or not. - * Rereduce is used for additional reduce values list, so when it is true there is no information about related keys (first argument is null). - * @param {string[] | null} keys - Array of pairs of docid-key for related map function results. Always null if rereduce is running (has true value). - * @returns {void} - */ -declare type redfun = (keys: [string, string][] | null, values: any[], rereduce?: boolean) => any diff --git a/src/db/tsconfig.json b/src/db/tsconfig.json deleted file mode 100644 index 65c19345..00000000 --- a/src/db/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": [ - "." - ], - "exclude": [ - "node_modules" - ], - "compilerOptions": { - "typeRoots": [ - "./design-functions-context.d.ts" - ], - "outDir": "../../db/designs", - "sourceMap": false - } -} diff --git a/src/graphql/resolvers.ts b/src/graphql/resolvers.ts new file mode 100644 index 00000000..d47818d0 --- /dev/null +++ b/src/graphql/resolvers.ts @@ -0,0 +1,7 @@ +const resolvers = { + Query: { + add: async (_: any, { x, y }: any) => x + y, + }, +} + +export default resolvers diff --git a/src/graphql/schema.ts b/src/graphql/schema.ts new file mode 100644 index 00000000..c13a2253 --- /dev/null +++ b/src/graphql/schema.ts @@ -0,0 +1,7 @@ +const schema = ` + type Query { + add(x: Int, y: Int): Int + } +` + +export default schema diff --git a/src/index.ts b/src/index.ts index 478b365b..0d41d15d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,29 +1,19 @@ -// we need this file because of this issue: https://github.com/fastify/fastify-cli/issues/131 -import 'make-promises-safe' import Fastify from 'fastify' -import hospitalRun from './app' +import app from './app' const port = Number(process.env.PORT) || 3000 -const ip = process.env.IP || '0.0.0.0' +const ip = process.env.IP || 'localhost' -const fastify = Fastify(hospitalRun.options) -fastify.register(hospitalRun) +const fastify = Fastify({ + ignoreTrailingSlash: true, + logger: true, +}) -if (process.env.NODE_ENV !== 'production') { - // eslint-disable-next-line - const blipp = require('fastify-blipp') - fastify.register(blipp) -} +fastify.register(app) -fastify.listen(port, ip, err => { +fastify.listen(port, ip, (err) => { if (err) { fastify.log.error(err) process.exit(1) } - if (process.env.NODE_ENV !== 'production') { - fastify.blipp() - fastify.log.info( - `Database username 'dev', password 'dev, GUI running on: http://localhost:5984/_utils`, - ) - } }) diff --git a/src/plugins/couchdb/index.ts b/src/plugins/couchdb/index.ts deleted file mode 100644 index 6491347a..00000000 --- a/src/plugins/couchdb/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { FastifyInstance, FastifyError } from 'fastify' -import fp from 'fastify-plugin' -import nano, { ServerScope, Configuration } from 'nano' -import proxy from './proxy' - -const COUCHDB_URL = process.env.COUCHDB_URL ? String(process.env.COUCHDB_URL) : undefined - -function couchDB( - fastify: FastifyInstance, - options: Configuration, - next: (err?: FastifyError | undefined) => void, -) { - const url = COUCHDB_URL || options.url - const couch = nano({ ...options, url }) - fastify.decorate('couch', couch) - fastify.register(proxy, { url }) - next() -} - -couchDB.autoConfig = { - url: COUCHDB_URL, -} - -export default fp(couchDB) - -declare module 'fastify' { - interface FastifyInstance { - couch: ServerScope - } -} diff --git a/src/plugins/couchdb/proxy.ts b/src/plugins/couchdb/proxy.ts deleted file mode 100644 index c34738ed..00000000 --- a/src/plugins/couchdb/proxy.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { FastifyInstance, FastifyError } from 'fastify' -import proxy from 'fastify-http-proxy' - -interface Options { - url: string -} - -function couchDBProxy( - fastify: FastifyInstance, - options: Options, - next: (err?: FastifyError | undefined) => void, -) { - fastify.register(proxy, { - upstream: options.url, - prefix: '/_db', - }) - next() -} - -couchDBProxy.autoConfig = { - url: process.env.COUCHDB_URL, -} - -export default couchDBProxy diff --git a/src/plugins/support.ts b/src/plugins/support.ts deleted file mode 100644 index 50d9da3c..00000000 --- a/src/plugins/support.ts +++ /dev/null @@ -1,14 +0,0 @@ -import fp from 'fastify-plugin' - -export default fp((fastify, _, next) => { - fastify.decorate('someSupport', function () { - return 'hugs' - }) - next() -}) - -declare module 'fastify' { - interface FastifyInstance { - someSupport(): string - } -} diff --git a/src/services/health.ts b/src/services/health.ts new file mode 100644 index 00000000..12136e37 --- /dev/null +++ b/src/services/health.ts @@ -0,0 +1,13 @@ +import { Server, IncomingMessage, ServerResponse } from 'http' +import { FastifyInstance, FastifyPluginOptions } from 'fastify' + +export default ( + fastify: FastifyInstance, + _: FastifyPluginOptions, + next: (error?: Error) => void, +) => { + fastify.get('/health', (_, reply) => { + reply.send({ status: 'UP' }) + }) + next() +} diff --git a/src/services/root.ts b/src/services/root.ts index 07376de1..3bf3fe0e 100644 --- a/src/services/root.ts +++ b/src/services/root.ts @@ -1,14 +1,15 @@ import { Server, IncomingMessage, ServerResponse } from 'http' -import { FastifyInstance } from 'fastify' -import { nextCallback } from 'fastify-plugin' +import { FastifyInstance, FastifyPluginOptions } from 'fastify' export default ( fastify: FastifyInstance, - _: {}, - next: nextCallback, + _: FastifyPluginOptions, + next: (error?: Error) => void, ) => { fastify.get('/', (_, reply) => { - reply.send({ root: true }) + const query = '{ add(x: 2, y: 2) }' + return reply.graphql(query) }) + next() } diff --git a/test/helper.ts b/test/helper.ts index 47cf2994..7a2bc624 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -1,6 +1,6 @@ import Fastify from 'fastify' import fp from 'fastify-plugin' -import App from '../src/app' +import App from './../src/app' // Fill in this config with all the configurations // needed for testing the application diff --git a/test/plugins/support.test.ts b/test/plugins/support.test.ts deleted file mode 100644 index a0d3bad6..00000000 --- a/test/plugins/support.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { test } from 'tap' -import Fastify from 'fastify' -import Support from '../../src/plugins/support' - -test('support works standalone', async (t: any) => { - const fastify = Fastify() - fastify.register(Support) - - await fastify.ready() - t.equal(fastify.someSupport(), 'hugs') -}) diff --git a/test/services/root.test.ts b/test/services/health.test.ts similarity index 51% rename from test/services/root.test.ts rename to test/services/health.test.ts index 0119b9b6..30dbf82b 100644 --- a/test/services/root.test.ts +++ b/test/services/health.test.ts @@ -1,11 +1,11 @@ import { test } from 'tap' import { build } from '../helper' -test('default root route', async (t: any) => { +test('default root route', async (t) => { const app = build(t) const res = await app.inject({ - url: '/', + url: '/health', }) - t.deepEqual(JSON.parse(res.payload), { root: true }) + t.deepEqual(JSON.parse(res.payload), { status: 'UP' }) }) diff --git a/typings/fastify-blipp/index.d.ts b/typings/fastify-blipp/index.d.ts deleted file mode 100644 index 32a7a590..00000000 --- a/typings/fastify-blipp/index.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare module 'fastify-blipp' { - import { Plugin } from 'fastify' - import http from 'http' - - let blipp: Plugin - export default blipp -} diff --git a/typings/fastify-no-icon/index.d.ts b/typings/fastify-no-icon/index.d.ts deleted file mode 100644 index feb0499b..00000000 --- a/typings/fastify-no-icon/index.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare module 'fastify-no-icon' { - import { Plugin } from 'fastify' - import http from 'http' - - let noIcon: Plugin - export default noIcon -} diff --git a/typings/fastify/index.d.ts b/typings/fastify/index.d.ts deleted file mode 100644 index f27d87af..00000000 --- a/typings/fastify/index.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import 'fastify' -declare module 'fastify' { - interface FastifyInstance { - blipp(): unknown - } -} diff --git a/typings/tap/index.d.ts b/typings/tap/index.d.ts deleted file mode 100644 index b70a31f2..00000000 --- a/typings/tap/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// improve tap typings and publish them on @types/tap - -declare module 'tap' { - function test(description: string, t: unknown): unknown -}