diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4b62a7a30..56c3b65d1 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -138,8 +138,6 @@ You can get a complete PeerTube development setup with Gitpod, a free one-click ### Server side -You can find a documentation of the server code/architecture [here](https://docs.joinpeertube.org/contribute/architecture#server). - To develop on the server-side: ``` @@ -150,12 +148,12 @@ Then, the server will listen on `localhost:9000`. When server source files change, these are automatically recompiled and the server will automatically restart. +More detailed documentation is available: + * [Server code/architecture](https://docs.joinpeertube.org/contribute/architecture#server) + * [Server development (adding a new feature...)](/support/doc/development/server.md) + ### Client side -You can find a documentation of the client code/architecture -[here](https://docs.joinpeertube.org/contribute/architecture#client). - - To develop on the client side: ``` @@ -166,6 +164,10 @@ The API will listen on `localhost:9000` and the frontend on `localhost:3000`. Client files are automatically compiled on change, and the web browser will reload them automatically thanks to hot module replacement. +More detailed documentation is available: + * [Client code/architecture](https://docs.joinpeertube.org/contribute/architecture#client) + + ### Client and server side The API will listen on `localhost:9000` and the frontend on `localhost:3000`. diff --git a/support/doc/development/server.md b/support/doc/development/server.md new file mode 100644 index 000000000..4647f2b4f --- /dev/null +++ b/support/doc/development/server.md @@ -0,0 +1,74 @@ +# Server code + +## Add a new feature walkthrough + +Here's a list of all the parts of the server to update if you want to add a new feature (new API REST endpoints for example) to the PeerTube server. +Some of these may be optional (for example your new endpoint may not need to send notifications) but this guide tries to be exhaustive. + + * Configuration: + - Add you new configuration key in `config/default.yaml` and `config/production.yaml` + - If you configuration needs to be different in dev or tests environments, also update `config/dev.yaml` and `config/test.yaml` + - Load your configuration in `server/initializers/config.ts` + - Check new configuration keys are set in `server/initializers/checker-before-init.ts` + - You can also ensure configuration consistency in `server/initializers/checker-after-init.ts` + - If you want your configuration to be available in the client: + + Add your field in `shared/models/server/server-config.model.ts` + + Update `server/lib/server-config-manager.ts` to include your new configuration + - If you want your configuration to be updatable by the web admin in the client: + + Add your field in `shared/models/server/custom-config.model.ts` + + Add the configuration to the config object in the `server/controllers/api/config.ts` controller + * Controllers: + - Create the controller file and fill it with your REST API routes + - Import and use your controller in the parent controller + * Middlewares: + - Create your validator middleware in `server/middlewares/validators` that will be used by your controllers + - Add your new middleware file `server/middlewares/validators/index.ts` so it's easier to import + - Create the entry in `server/types/express.d.ts` to attach the database model loaded by your middleware to the express response + * Validators: + - Create your validators that will be used by your middlewares in `server/helpers/custom-validators` + * Typescript models: + - Create the API models (request parameters or response) in `shared/models` + - Add your models in `index.ts` of current directory to facilitate the imports + * Sequelize model (BDD): + - If you need to create a new table: + + Create the Sequelize model in `server/models/`: + * Create the `@Column` + * Add some indexes if you need + * Create static methods to load a specific from the database `loadBy...` + * Create static methods to load a list of models from the database `listBy...` + * Create the instance method `toFormattedJSON` that creates the JSON to send to the REST API from the model + + Add your new Sequelize model to `server/initializers/database.ts` + + Create a new file in `server/types` to define multiple versions of your Sequelize model depending on database associations + + Add this new file to `server/types/*/index.ts` to facilitate the imports + + Create database migrations: + * Create the migration file in `server/initializers/migrations` using raw SQL (copy the same SQL query as at PeerTube startup) + * Update `LAST_MIGRATION_VERSION` in `server/initializers/constants.ts` + - If updating database schema (adding/removing/renaming a column): + + Update the sequelize models in `server/models/` + + Add migrations: + * Create the migration file in `initializers/migrations` using Sequelize Query Interface (`.addColumn`, `.dropTable`, `.changeColumn`) + * Update `LAST_MIGRATION_VERSION` in `server/initializers/constants.ts` + * Notifications: + - Create the new notification model in `shared/models/users/user-notification.model.ts` + - Create the notification logic in `server/lib/notifier/shared`: + + Email subject has a common prefix (defined by the admin in PeerTube configuration) + - Add your notification to `server/lib/notifier/notifier.ts` + - Create the email template in `server/lib/emails`: + + A text version is automatically generated from the HTML + + The template usually extends `../common/grettings` that already says "Hi" and "Cheers". You just have to write the title and the content blocks that will be inserted in the appropriate places in the HTML template + - If you need to associate a new table with `userNotification`: + + Associate the new table in `UserNotificationModel` (don't forget the index) + + Add the object property in the API model definition (`shared/models/users/user-notification.model.ts`) + + Add the object in `UserNotificationModel.toFormattedJSON` + + Handle this new notification type in client (`UserNotificationsComponent`) + + Handle the new object property in client model (`UserNotification`) + * Tests: + - Create your command class in `shared/server-commands/` that will wrap HTTP requests to your new endpoint + - Add your command file in `index.ts` of current directory + - Instantiate your command class in `shared/server-commands/server/server.ts` + - Create your test file in `server/tests/api/check-params` to test middleware validators/authentification/user rights (offensive tests) + - Add it to `server/tests/api/check-params/index.ts` + - Create your test file in `server/tests/api` to test your new endpoints + - Add it to `index.ts` of current directory + - Add your notification test in `server/tests/api/notifications` + * Update REST API documentation in `support/doc/api/openapi.yaml`