Skip to content

Commit

Permalink
Merge branch 'master' into v2-0-0
Browse files Browse the repository at this point in the history
  • Loading branch information
LoicPoullain committed May 28, 2020
2 parents 44e4c33 + ad5646b commit 37af9c7
Show file tree
Hide file tree
Showing 224 changed files with 6,457 additions and 1,890 deletions.
162 changes: 111 additions & 51 deletions .github/CONTRIBUTING.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,86 @@ Thanks for your interest in FoalTS!

There are several ways to contribute. **Reporting bugs are greatly appreciated**, so do not hesitate to open an issue/PR for that!

- [Submit an issue](#submit-an-issue)
- [Submit a PR](#submit-a-pr)
- [Security](#security)

## Submit an issue

If you find a security vulnerability, please do NOT open an issue. Email [email protected] instead.

- [Report a bug](https://github.com/FoalTS/foal/issues/new)
- [Suggest a new feature](https://github.com/FoalTS/foal/issues/new)
- [Other (ask a question, etc)](https://github.com/FoalTS/foal/issues/new)

## Submit a PR

If the PR is about code (not documentation), please submit an issue first to discuss on this. There are also [pending issues](https://github.com/FoalTS/foal/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) that may require your help.

### Set up the development/test environment

1. Install [docker](https://www.docker.com/).
2. Install [lerna](https://lernajs.io/) by running `npm i -g lerna`
3. Start the dev/test environment by running `npm run start-docker` (to stop use `npm run stop-docker`)

### Install dependencies

Run `lerna bootstrap`.

### Run tests and linting

Run `lerna run --no-bail test` and `npm run lint` from the root directory.

You can also run the tests of only one package by going to its directory and running `npm run test` or `npm run dev:test` (watch mode).

### General guidelines

Do not install any new dependencies unless they have been approved. Dependencies (except peer ones) should point to *minor* versions (`~1.2.0` instead of `^1.2.0`).

When writting code, use the *Test-Driven Developpement (TDD)* approach.
## Security Vulnerabilities

If you think you have found a security hole, please do NOT submit an issue but send an email directly to [email protected].

## Pull Requests

There are [pending issues](https://github.com/FoalTS/foal/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) that may require your help.

If you wish to submit a PR, please first submit an issue for discussion (or add a comment on an existing issue).

PRs that correct grammatical errors or small bugs can be submitted directly.

## Development Environment

The framework development environment uses [lerna](https://lernajs.io/) for managing packages and [docker](https://www.docker.com/) for database provisioning.

**Steps:**
1. Install docker.
2. Install lerna
```
npm install -g lerna
```
3. Start the databases.
```sh
npm run start-docker # use `npm run stop-docker` to stop them
```
4. Install the root dependencies.
```
npm install
```
5. Install the dependencies of each package and build each package.
```
lerna bootstrap
```
6. Check code format.
```
npm run lint
```
7. Run all the tests.
```
lerna run --no-bail test
```
Tests can also be run individually for each package using `npm run test` or `npm run dev:test` (watch mode) at the root of the package directory.
## Dependency Policy
**Do not add new dependencies** (unless they have been improved). Do not install `@types` packages.
FoalTS is based on very few dependencies for all these reasons:
- Adding a new dependency often means installing many other packages on which it depends. This phenomenon is often referred to as a *black hole* in Node's ecosystem.
- The size of the `node_modules` directory grows very fast. This can slow down deployment and cause problems if a size limit is imposed on the directory (e.g. in a serverless architecture).
- Due to the large number of dependencies to load, the application may be slow to start.
- The application is more vulnerable to the release of malicious packages. This is what happened on July 12, 2018 when an [attacker compromised the npm account](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) of an ESLint maintainer.
- We have no guarantee that the maintainers follow the same Foal safety rules (2FA enabled on both Github and npm).
- When a new version of an external package is released (bug fixes, security updates, new features, etc.), it takes time to review each change made in the new version and time to verify that the framework still works as expected with it.
- Packages may support different versions of TypeScript and Node than those supported by the framework.
- External packages can become unmaintained.
- Semantic versioning is not always respected, which is problematic if we want to integrate a security update without introducing breaking changes.
- If we need a new feature in the external dependency, it may take time for the maintainer(s) to implement it. The feature may also be rejected.
- The `@types` packages very often lead to issues.
- The types may be outdated with respect to the current version.
- Semantic versioning is often not respected, which causes the code to break between two *patch* versions.
- Type choices may be arbitrary and not decided by the official maintainers.
- Two packages using the same `@types` module but with different versions may not work properly together.
- Type packages depend on each other by specifying `*` as the version number which causes incompatibilities and great difficulty in defining a replicable environment.
- The installation is often polluted by messages of indirect dependencies in search of funds.
Some packages, however, can override this policy and be installed if they meet one of the following criteria:
- Rewriting the entire package would require too much work and would be difficult to maintain in the long term. Examples: `TypeORM`, `Mongoose`.
- The code requires very specific knowledge. Examples: `pump`, `jsonwebtoken`, `TypeORM`, `Mongoose`.
- The packages are base packages of the Express.Js framework and can therefore be considered stable, safe and mature. Examples: `cookie-parser`, `morgan`.
> Dependencies (except peer ones) should point to *minor* versions (`~1.2.0` instead of `^1.2.0`).
## Testing and Documentation Policy
**Testing and documentating the framework is put on a very high priority**. Each line of code must be tested. It is okay to delay the release of a new version if it is to ensure that it is based on robust testing.
If you wish to submit a PR, please use the *Test-Driven Developpement (TDD)* approach:
1. Write a test.
2. Check that the test fails.
3. Write just enough code to make the test pass.
Expand All @@ -49,28 +92,45 @@ When writting code, use the *Test-Driven Developpement (TDD)* approach.
This method may seem cumbersome at first glance, but it ensures that every line of code in the framework is tested. Reviewers must pull the branch and verify that the tests are actually testing something. If they change even one line of code, they must see that at least one of the tests fails.
**A PR without tests is automatically rejected.**
A PR without robust tests is automatically rejected.
## Security
## Semantic Versioning
To report a security issue please email directly [email protected].
The framework follows the semantic versioning specification.
## Project Structure
| Code status | Stage | Example version |
| --- | --- | --- |
| Backward compatible bug fixes | Patch release | 1.0.1 |
| Backward compatible new features | Minor release | 1.1.0 |
| Changes that break backward compatibility | Major release | 2.0.0 |
The FoalTS project consists of several packages. The publication and dependency management is handled by [lerna](https://github.com/lerna/lerna), a tool for managing JavaScript projects with multiple packages.
## Long-Term Support Policy and Schedule
All of major releases are supported for 18 months.
- 12 months of *active support* (new features, bug fixes, etc).
- 6 months of *maintenance (LTS)* (critical fixes and security patches).
| Release | Status | Active Start | Maintenance Start | End-of-life | Node min version | TS min version |
| --- | --- | --- | --- | --- | --- | --- |
| 2.x | *Pending* | Summer 2020 | Summer 2021 | 2021-12-31 | 10.x | 3.5 |
| 1.x | *Active* | 2019-07-11 | Summer 2020 | 2020-12-31 | 8.x | 3.5 |
| 0.8 | *End-of-Life* | 2019-02-16 | - | 2019-07-11 | 8.x | 2.9 |
## Project Architecture
### `@foal/cli` Package Structure
```sh
generate # Handles the commands `foal createapp` and `foal generate`
|- generators # Contains the code which renders the templates or updates the files
|- mocks # Contains some pieces of code used to test the file "updaters"
|- specs # Defines how the generated files should look like in different scenarios (specifications)
|- templates # Contains the actual templates used to generate the files
'- utils # Contains some helpers shared by all the generators
```
The directory `src/generate/` contains the source code of the commands `foal createapp` and `foal generate`.
Here is the list of its sub-directories:
Usually components that do not rely on a third-party library are located in the `@foal/core` package.
| Directory | Description |
| --- | --- |
| generators | Contains the code which renders the templates or updates the files |
| fixtures | Contains some pieces of code used to test the file "updaters" |
| specs | Defines how the generated files should look like in different scenarios (specifications) |
| templates | Contains the actual templates used to generate the files |
| utils | Contains some helpers shared by all the generators |
## Conventions
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Test

on: [push]
on:
push:
branches:
- master
pull_request:

jobs:
build:
Expand All @@ -12,9 +16,6 @@ jobs:
node-version: [10, 12]

env:
AUTH0_DOMAIN: ${{ secrets.AUTH0_DOMAIN }}
AUTH0_AUDIENCE: ${{ secrets.AUTH0_AUDIENCE }}
AUTH0_TOKEN: ${{ secrets.AUTH0_TOKEN }}
SETTINGS_AWS_ACCESS_KEY_ID: ${{ secrets.SETTINGS_AWS_ACCESS_KEY_ID }}
SETTINGS_AWS_SECRET_ACCESS_KEY: ${{ secrets.SETTINGS_AWS_SECRET_ACCESS_KEY }}
NODE_VERSION: ${{ matrix.node-version }}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<p align="center">
<a href="https://foalts.org/">Website</a>
-
<a href="https://foalts.gitbook.io/docs/content/">Documentation</a>
<a href="https://foalts.gitbook.io/docs/">Documentation</a>
-
<a href="https://twitter.com/foalts">Twitter</a>
-
Expand All @@ -66,7 +66,7 @@ $ npm run develop

The development server is started! Go to `http://localhost:3001` and find our welcoming page!

:point_right: [Continue with the tutorial](https://foalts.gitbook.io/docs/content/) :seedling:
:point_right: [Continue with the tutorial](https://foalts.gitbook.io/docs/) :seedling:

![Screenshot](./docs/screenshot.png)

Expand Down
3 changes: 2 additions & 1 deletion benchmarks/run.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -e

# Empty benchmark.txt if it exists.
:> benchmark.txt
Expand Down
4 changes: 2 additions & 2 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
* [Hooks](./architecture/hooks.md)
* [Initialization](./architecture/initialization.md)
* Databases
* [TypeORM (SQL & noSQL)](./databases/typeorm.md)
* [SQL Databases (TypeORM)](./databases/typeorm.md)
* [Create Models & Queries](./databases/create-models-and-queries.md)
* [Generate & Run Migrations](./databases/generate-and-run-migrations.md)
* [Use Mongoose (MongoDB)](./databases/using-mongoose.md)
* [MongoDB (TypeORM or Mongoose)](./databases/mongodb.md)
* [Use Another ORM](./databases/using-another-orm.md)
* Authentication & Access Control
* [Quick Start](./authentication-and-access-control/quick-start.md)
Expand Down
17 changes: 14 additions & 3 deletions docs/api-section/rest-blueprints.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
foal generate rest-api product --register
```

Building a REST API is often a common task when creating an application. To avoid reinventing the wheel, FoalTS provides an integrated command to achieve this.
Building a REST API is often a common task when creating an application. To avoid reinventing the wheel, FoalTS provides a CLI command to achieve this.

```
foal generate rest-api <name> [--register]
foal generate rest-api <name> [--register] [--auth]
```

This command generates three files: an entity, a controller and the controller's test. Depending on your directory structure, they may be generated in different locations:
Expand Down Expand Up @@ -116,7 +116,18 @@ export const productSchhema = {
};
```

## Generate OpenAPI documentation
## Using Authentication

If you wish to attach a user to the resource, you can use the `--auth` flag to do so.

*Example:*
```
foal generate rest-api product --auth
```

This flags adds an `owner: User` column to your entity and uses it in the API.

## Generating OpenAPI documentation

The generated controllers also have OpenAPI decorators on their methods to document the API.

Expand Down
25 changes: 22 additions & 3 deletions docs/architecture/controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ import { Context, HttpResponseCreated, Post } from '@foal/core';
class AppController {
@Post('/products')
createProduct(ctx: Context) {
const requestBody = ctx.request.body;
const body = ctx.request.body;
// Do something.
return new HttpResponseCreated();
}
Expand All @@ -140,7 +140,7 @@ import { Context, HttpResponseOK, Post } from '@foal/core';

class AppController {
@Get('/products/:id')
createProduct(ctx: Context) {
readProduct(ctx: Context) {
const productId = ctx.request.params.id;
// Do something.
return new HttpResponseOK(/* something */);
Expand All @@ -161,7 +161,7 @@ import { Context, HttpResponseOK, Post } from '@foal/core';

class AppController {
@Get('/products')
createProduct(ctx: Context) {
readProducts(ctx: Context) {
const limit = ctx.request.query.limit;
// Do something.
return new HttpResponseOK(/* something */);
Expand Down Expand Up @@ -201,6 +201,25 @@ class AppController {
}
```


#### The Controller Method Arguments

> Available in Foal v1.9.0 onwards.
The path paramaters and request body are also passed as second and third arguments to the controller method.

```typescript
import { Context, HttpResponseCreated, Put } from '@foal/core';

class AppController {
@Put('/products/:id')
updateProduct(ctx: Context, { id }, body) {
// Do something.
return new HttpResponseCreated();
}
}
```

## HTTP Responses

HTTP responses are defined using `HttpResponse` objects. Each controller method must return an instance of this class (or a *promise* of this instance).
Expand Down
5 changes: 3 additions & 2 deletions docs/architecture/services-and-dependency-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,10 @@ export class Logger implements ILogger {
*src/index.ts (example)*
```typescript
import { createApp, ServiceManager } from '@foal/core';
import { Connection, createConnection } from 'typeorm';
import { createConnection } from 'typeorm';

import { AppController } from './app/app.controller';
import { Product } from './app/entities';
import { Logger } from './app/services';

async function main() {
Expand Down Expand Up @@ -326,7 +327,7 @@ import { Repository } from 'typeorm';
import { Product } from '../entities';
import { ILogger } from '../services';

class ApiController {
export class ApiController {

@Dependency('product')
productRepository: Repository<Product>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export class User extends UserWithPermissions {

}

// You MUST export Group and Permission so that TypeORM can generate migrations.
export { Group, Permission } from '@foal/typeorm';
```

Expand Down
Loading

0 comments on commit 37af9c7

Please sign in to comment.