]>
Commit | Line | Data |
---|---|---|
11c834bd C |
1 | # Server code |
2 | ||
016b8878 C |
3 | ## Database model typing |
4 | ||
5 | Sequelize models contain optional fields corresponding to table joins. | |
6 | For example, `VideoModel` has a `VideoChannel?: VideoChannelModel` field. It can be filled if the SQL query joined with the `videoChannel` table or empty if not. | |
7 | It can be difficult in TypeScript to understand if a function argument expects associations to be filled or not. | |
8 | To improve clarity and reduce bugs, PeerTube defines multiple versions of a database model depending on its associations in `server/types/models/`. | |
9 | These models start with `M` and by default do not include any association. `MVideo` for example corresponds to `VideoModel` without any association, where `VideoChannel` attribute doesn't exist. On the other hand, `MVideoWithChannel` is a `MVideo` that has a `VideoChannel` field. This way, a function that accepts `video: MVideoWithChannel` argument expects a video with channel populated. Main PeerTube code should never use `...Model` (`VideoModel`) database type, but always `M...` instead (`MVideo`, `MVideoChannel` etc). | |
10 | ||
11c834bd C |
11 | ## Add a new feature walkthrough |
12 | ||
13 | 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. | |
14 | Some of these may be optional (for example your new endpoint may not need to send notifications) but this guide tries to be exhaustive. | |
15 | ||
16 | * Configuration: | |
17 | - Add you new configuration key in `config/default.yaml` and `config/production.yaml` | |
18 | - If you configuration needs to be different in dev or tests environments, also update `config/dev.yaml` and `config/test.yaml` | |
19 | - Load your configuration in `server/initializers/config.ts` | |
20 | - Check new configuration keys are set in `server/initializers/checker-before-init.ts` | |
21 | - You can also ensure configuration consistency in `server/initializers/checker-after-init.ts` | |
22 | - If you want your configuration to be available in the client: | |
23 | + Add your field in `shared/models/server/server-config.model.ts` | |
24 | + Update `server/lib/server-config-manager.ts` to include your new configuration | |
25 | - If you want your configuration to be updatable by the web admin in the client: | |
26 | + Add your field in `shared/models/server/custom-config.model.ts` | |
27 | + Add the configuration to the config object in the `server/controllers/api/config.ts` controller | |
28 | * Controllers: | |
29 | - Create the controller file and fill it with your REST API routes | |
30 | - Import and use your controller in the parent controller | |
31 | * Middlewares: | |
32 | - Create your validator middleware in `server/middlewares/validators` that will be used by your controllers | |
33 | - Add your new middleware file `server/middlewares/validators/index.ts` so it's easier to import | |
34 | - Create the entry in `server/types/express.d.ts` to attach the database model loaded by your middleware to the express response | |
35 | * Validators: | |
36 | - Create your validators that will be used by your middlewares in `server/helpers/custom-validators` | |
37 | * Typescript models: | |
38 | - Create the API models (request parameters or response) in `shared/models` | |
39 | - Add your models in `index.ts` of current directory to facilitate the imports | |
40 | * Sequelize model (BDD): | |
41 | - If you need to create a new table: | |
42 | + Create the Sequelize model in `server/models/`: | |
43 | * Create the `@Column` | |
44 | * Add some indexes if you need | |
45 | * Create static methods to load a specific from the database `loadBy...` | |
46 | * Create static methods to load a list of models from the database `listBy...` | |
47 | * Create the instance method `toFormattedJSON` that creates the JSON to send to the REST API from the model | |
48 | + Add your new Sequelize model to `server/initializers/database.ts` | |
49 | + Create a new file in `server/types` to define multiple versions of your Sequelize model depending on database associations | |
50 | + Add this new file to `server/types/*/index.ts` to facilitate the imports | |
51 | + Create database migrations: | |
52 | * Create the migration file in `server/initializers/migrations` using raw SQL (copy the same SQL query as at PeerTube startup) | |
53 | * Update `LAST_MIGRATION_VERSION` in `server/initializers/constants.ts` | |
54 | - If updating database schema (adding/removing/renaming a column): | |
55 | + Update the sequelize models in `server/models/` | |
56 | + Add migrations: | |
57 | * Create the migration file in `initializers/migrations` using Sequelize Query Interface (`.addColumn`, `.dropTable`, `.changeColumn`) | |
58 | * Update `LAST_MIGRATION_VERSION` in `server/initializers/constants.ts` | |
59 | * Notifications: | |
60 | - Create the new notification model in `shared/models/users/user-notification.model.ts` | |
61 | - Create the notification logic in `server/lib/notifier/shared`: | |
62 | + Email subject has a common prefix (defined by the admin in PeerTube configuration) | |
63 | - Add your notification to `server/lib/notifier/notifier.ts` | |
64 | - Create the email template in `server/lib/emails`: | |
65 | + A text version is automatically generated from the HTML | |
66 | + 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 | |
67 | - If you need to associate a new table with `userNotification`: | |
68 | + Associate the new table in `UserNotificationModel` (don't forget the index) | |
69 | + Add the object property in the API model definition (`shared/models/users/user-notification.model.ts`) | |
70 | + Add the object in `UserNotificationModel.toFormattedJSON` | |
71 | + Handle this new notification type in client (`UserNotificationsComponent`) | |
72 | + Handle the new object property in client model (`UserNotification`) | |
73 | * Tests: | |
74 | - Create your command class in `shared/server-commands/` that will wrap HTTP requests to your new endpoint | |
75 | - Add your command file in `index.ts` of current directory | |
76 | - Instantiate your command class in `shared/server-commands/server/server.ts` | |
77 | - Create your test file in `server/tests/api/check-params` to test middleware validators/authentification/user rights (offensive tests) | |
78 | - Add it to `server/tests/api/check-params/index.ts` | |
79 | - Create your test file in `server/tests/api` to test your new endpoints | |
80 | - Add it to `index.ts` of current directory | |
81 | - Add your notification test in `server/tests/api/notifications` | |
82 | * Update REST API documentation in `support/doc/api/openapi.yaml` |