|
|
|
This page is all about the `src/db` folder and its subdirectories. If you want to find out how to run the and configure the API, take a look at the [installation instructions](/en/Installation.md) and [docker page](Docker)
|
|
|
|
|
|
|
|
[TOC]
|
|
|
|
|
|
|
|
## Database
|
|
|
|
|
|
|
|
### questions.json
|
|
|
|
|
|
|
|
This file was initially used to generate the SQL statements for the database and is now kept to provide a more human readable overview of questions than SQL has. This file is not read by anything except the user
|
|
|
|
|
|
|
|
### schema.sql
|
|
|
|
|
|
|
|
The database schema file contains all definitions for tables for the database, but also inserts predefined questions. If you want to extend the database, you can create a new table and if you want to add more questions, you can do so, by appending lines to the `INSERT INTO "question"` statement. Please note that you need to generate UUIDs for your questions beforehand, you can do this by accessing any system that has Postgres installed and executing the following:
|
|
|
|
|
|
|
|
```sql
|
|
|
|
psql -U postgres
|
|
|
|
|
|
|
|
SELECT gen_random_uuid();
|
|
|
|
```
|
|
|
|
|
|
|
|
## API
|
|
|
|
|
|
|
|
This folder contains the logic for the API, it runs on NodeJS with the [express package](https://expressjs.com). To simplify API creation and to follow the [OpenAPI standard](https://swagger.io/specification/), the package [express-openapi](https://www.npmjs.com/package/express-openapi) generates endpoints based on file structure.
|
|
|
|
|
|
|
|
### api-doc.js
|
|
|
|
|
|
|
|
This file contains an OpenAPI compliant specification, where you can provide information about your API. In the `definitions` key you can add Models you may want as input, or you return to the user. You can find information on how to create these definitions in the [OpenAPI documentation](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#schema).
|
|
|
|
|
|
|
|
If you have types that are a little more dynamic, you can append them to the `open-api-types.js` file and expand them with additional attributes if needed like this:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
Model: {
|
|
|
|
type: "object",
|
|
|
|
properties: {
|
|
|
|
id: {
|
|
|
|
type: "string"
|
|
|
|
},
|
|
|
|
...type_to_expand
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
This way you can prevent having to repeat definitions.
|
|
|
|
|
|
|
|
### Defining endpoints
|
|
|
|
|
|
|
|
`express-openapi` generates endpoints based on the file structure in the `paths` folder. An endpoint is assembled by following the folders down to the final JavaScript file. This means a structure like
|
|
|
|
|
|
|
|
```shell
|
|
|
|
└── give
|
|
|
|
└── me
|
|
|
|
└── examples.js
|
|
|
|
```
|
|
|
|
|
|
|
|
creates the path `give/me/examples`.
|
|
|
|
|
|
|
|
Paths that require dynamic parameters like `/give/me/example/id1` is created by surrounding the parameters with curly braces. If we want to enable the id to be dynamic, the file structure needs to be:
|
|
|
|
|
|
|
|
```shell
|
|
|
|
└── give
|
|
|
|
└── me
|
|
|
|
└── examples
|
|
|
|
└── {id}.js
|
|
|
|
```
|
|
|
|
|
|
|
|
Both JavaScript files hold the logic for the endpoint. In them, you can declare what type of HTTP requests are excepted, how the input looks and how the output looks. An example file that would allow GET requests for the just constructed path would look like this:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
export default function() {
|
|
|
|
//Defines accepted requests
|
|
|
|
let operations = {
|
|
|
|
GET
|
|
|
|
};
|
|
|
|
|
|
|
|
// req is the request, res the response and _next could provide middleware
|
|
|
|
function GET(req, res, _next) {
|
|
|
|
//Returns 200 Status code and the formatted string
|
|
|
|
res.status(200).send(`You send {req.params.id}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Documentation
|
|
|
|
GET.apiDoc = {
|
|
|
|
summary: "Returns your id",
|
|
|
|
// Input
|
|
|
|
parameters: [
|
|
|
|
{
|
|
|
|
in: "path",
|
|
|
|
name: "id",
|
|
|
|
type: "number",
|
|
|
|
description: "The id"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
// Defines all possible status codes
|
|
|
|
responses: {
|
|
|
|
200: {
|
|
|
|
description: "Sends you your id",
|
|
|
|
//Return type
|
|
|
|
schema: {
|
|
|
|
type: "string"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
If you want to create your own endpoint, you can simply create the file like mentioned above and the package will do the rest for you.
|
|
|
|
|
|
|
|
### Services
|
|
|
|
|
|
|
|
Most files for the endpoints will reference a service in the `services` folder. This offloads the logic onto the service. Services typically group together functions that provide similar functionality, i.e. all endpoints that handle questions will point to the `questionsService.js` file. If you want to add functionality either expand an existing service or create your own. However, if you create your own, don't forget to register it in `index.js` by importing it and adding it as a dependency in the `initialize` function.
|
|
|
|
|
|
|
|
### postgres.js
|
|
|
|
|
|
|
|
This file is dedicated to interacting with the database. Most services will probably call functions from this file to retrieve results from the database. The functions here are syntactic sugar for direct SQL statements into the database. If you want to make your own query, you can do so with the `client.query("query")` function. Please note if you want to add dynamic parameter, don't put them into your query string directly, but rather do this:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
client.query("SELECT from table WHERE id = $1 AND name = $2", [id, name])
|
|
|
|
```
|
|
|
|
|
|
|
|
Creating queries this way sanitizes input and prevents SQL injections. The number with the dollar sign ($) will be replaced with the elements in the provided array with the same place as the number. |