chadstart 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/.dockerignore +10 -0
  2. package/.env.example +46 -0
  3. package/.github/workflows/browser-test.yml +34 -0
  4. package/.github/workflows/docker-publish.yml +54 -0
  5. package/.github/workflows/docs.yml +31 -0
  6. package/.github/workflows/npm-chadstart.yml +27 -0
  7. package/.github/workflows/npm-sdk.yml +38 -0
  8. package/.github/workflows/test.yml +85 -0
  9. package/.weblate +9 -0
  10. package/Dockerfile +23 -0
  11. package/README.md +348 -0
  12. package/admin/index.html +2802 -0
  13. package/admin/login.html +207 -0
  14. package/chadstart.example.yml +416 -0
  15. package/chadstart.schema.json +367 -0
  16. package/chadstart.yaml +53 -0
  17. package/cli/cli.js +295 -0
  18. package/core/api-generator.js +606 -0
  19. package/core/auth.js +298 -0
  20. package/core/db.js +384 -0
  21. package/core/entity-engine.js +166 -0
  22. package/core/error-reporter.js +132 -0
  23. package/core/file-storage.js +97 -0
  24. package/core/functions-engine.js +353 -0
  25. package/core/openapi.js +171 -0
  26. package/core/plugin-loader.js +92 -0
  27. package/core/realtime.js +93 -0
  28. package/core/schema-validator.js +50 -0
  29. package/core/seeder.js +231 -0
  30. package/core/telemetry.js +119 -0
  31. package/core/upload.js +372 -0
  32. package/core/workers/php_worker.php +19 -0
  33. package/core/workers/python_worker.py +33 -0
  34. package/core/workers/ruby_worker.rb +21 -0
  35. package/core/yaml-loader.js +64 -0
  36. package/demo/chadstart.yaml +178 -0
  37. package/demo/docker-compose.yml +31 -0
  38. package/demo/functions/greet.go +39 -0
  39. package/demo/functions/hello.cpp +18 -0
  40. package/demo/functions/hello.py +13 -0
  41. package/demo/functions/hello.rb +10 -0
  42. package/demo/functions/onTodoCreated.js +13 -0
  43. package/demo/functions/ping.sh +13 -0
  44. package/demo/functions/stats.js +22 -0
  45. package/demo/public/index.html +522 -0
  46. package/docker-compose.yml +17 -0
  47. package/docs/access-policies.md +155 -0
  48. package/docs/admin-ui.md +29 -0
  49. package/docs/angular.md +69 -0
  50. package/docs/astro.md +71 -0
  51. package/docs/auth.md +160 -0
  52. package/docs/cli.md +56 -0
  53. package/docs/config.md +127 -0
  54. package/docs/crud.md +627 -0
  55. package/docs/deploy.md +113 -0
  56. package/docs/docker.md +59 -0
  57. package/docs/entities.md +385 -0
  58. package/docs/functions.md +196 -0
  59. package/docs/getting-started.md +79 -0
  60. package/docs/groups.md +85 -0
  61. package/docs/index.md +5 -0
  62. package/docs/llm-rules.md +81 -0
  63. package/docs/middlewares.md +78 -0
  64. package/docs/overrides/home.html +350 -0
  65. package/docs/plugins.md +59 -0
  66. package/docs/react.md +75 -0
  67. package/docs/realtime.md +43 -0
  68. package/docs/s3-storage.md +40 -0
  69. package/docs/security.md +23 -0
  70. package/docs/stylesheets/extra.css +375 -0
  71. package/docs/svelte.md +71 -0
  72. package/docs/telemetry.md +97 -0
  73. package/docs/upload.md +168 -0
  74. package/docs/validation.md +115 -0
  75. package/docs/vue.md +86 -0
  76. package/docs/webhooks.md +87 -0
  77. package/index.js +11 -0
  78. package/locales/en/admin.json +169 -0
  79. package/mkdocs.yml +82 -0
  80. package/package.json +65 -0
  81. package/playwright.config.js +24 -0
  82. package/public/.gitkeep +0 -0
  83. package/sdk/README.md +284 -0
  84. package/sdk/package.json +39 -0
  85. package/sdk/scripts/build.js +58 -0
  86. package/sdk/src/index.js +368 -0
  87. package/sdk/test/sdk.test.cjs +340 -0
  88. package/sdk/types/index.d.ts +217 -0
  89. package/server/express-server.js +734 -0
  90. package/test/access-policies.test.js +96 -0
  91. package/test/ai.test.js +81 -0
  92. package/test/api-keys.test.js +361 -0
  93. package/test/auth.test.js +122 -0
  94. package/test/browser/admin-ui.spec.js +127 -0
  95. package/test/browser/global-setup.js +71 -0
  96. package/test/browser/global-teardown.js +11 -0
  97. package/test/db.test.js +227 -0
  98. package/test/entity-engine.test.js +193 -0
  99. package/test/error-reporter.test.js +140 -0
  100. package/test/functions-engine.test.js +240 -0
  101. package/test/groups.test.js +212 -0
  102. package/test/hot-reload.test.js +153 -0
  103. package/test/i18n.test.js +173 -0
  104. package/test/middleware.test.js +76 -0
  105. package/test/openapi.test.js +67 -0
  106. package/test/schema-validator.test.js +83 -0
  107. package/test/sdk.test.js +90 -0
  108. package/test/seeder.test.js +279 -0
  109. package/test/settings.test.js +109 -0
  110. package/test/telemetry.test.js +254 -0
  111. package/test/test.js +17 -0
  112. package/test/upload.test.js +265 -0
  113. package/test/validation.test.js +96 -0
  114. package/test/yaml-loader.test.js +93 -0
  115. package/utils/logger.js +24 -0
@@ -0,0 +1,196 @@
1
+ ---
2
+ id: functions
3
+ title: Functions
4
+ description: Add custom functions to your ChadStart app — with multiple runtimes, triggers, and formats.
5
+ ---
6
+
7
+ # Functions
8
+
9
+ ## Introduction
10
+
11
+ Functions let you run custom logic on the server. Each function can be triggered by one or more events: an HTTP request, a scheduled cron job, or an emitted application event.
12
+
13
+ ## Syntax
14
+
15
+ ```yaml title="chadstart.yaml"
16
+ functions:
17
+ hello:
18
+ runtime: js # js (default) | bash | python | go | c++ | ruby | php
19
+ function: hello.js # file path relative to /functions (or CHADSTART_FUNCTIONS_FOLDER)
20
+ triggers:
21
+ - type: http
22
+ method: GET
23
+ path: /hello
24
+ - type: cron
25
+ schedule: "@daily"
26
+ - type: event
27
+ name: user.created
28
+ ```
29
+
30
+ ## Triggers
31
+
32
+ ### HTTP trigger
33
+
34
+ Registers an HTTP route. The function receives an `event` object and a `ctx` context.
35
+
36
+ ```yaml
37
+ triggers:
38
+ - type: http
39
+ method: GET # GET | POST | PUT | PATCH | DELETE
40
+ path: /hello
41
+ # policies omitted → public (anyone can call)
42
+ ```
43
+
44
+ #### Access policies
45
+
46
+ Add a `policies` array to restrict who can call an HTTP trigger:
47
+
48
+ ```yaml
49
+ triggers:
50
+ - type: http
51
+ method: GET
52
+ path: /public-data
53
+ policies:
54
+ - access: public # Anyone can call (default when omitted)
55
+
56
+ - type: http
57
+ method: GET
58
+ path: /admin-data
59
+ policies:
60
+ - access: admin # Any valid JWT is required
61
+
62
+ - type: http
63
+ method: GET
64
+ path: /customer-data
65
+ policies:
66
+ - access: restricted # JWT required, filtered by entity
67
+ allow: Customer # Only Customer tokens are allowed (string or array)
68
+
69
+ - type: http
70
+ method: GET
71
+ path: /disabled
72
+ policies:
73
+ - access: forbidden # Always returns 403
74
+ ```
75
+
76
+ **Policy access values:**
77
+
78
+ | Value | Emoji alias | Description |
79
+ | ------------ | ----------- | ----------------------------------------------------------------- |
80
+ | `public` | `🌐` | Open to everyone (default when `policies` is omitted) |
81
+ | `admin` | `👨🏻‍💻` | Requires any valid JWT (any entity) |
82
+ | `restricted` | `🔒` | Requires a valid JWT; combine with `allow` to limit to an entity |
83
+ | `forbidden` | `🚫` | Always returns 403 — disables the route |
84
+
85
+ ### Cron trigger
86
+
87
+ Runs the function on a schedule. Supports standard cron expressions and predefined aliases.
88
+
89
+ ```yaml
90
+ triggers:
91
+ - type: cron
92
+ schedule: "*/10 * * * *" # every 10 minutes
93
+ - type: cron
94
+ schedule: "@daily" # once a day at midnight
95
+ ```
96
+
97
+ **Predefined aliases:**
98
+
99
+ | Alias | Equivalent | Description |
100
+ | ----------- | --------------- | ------------------------ |
101
+ | `@yearly` | `0 0 1 1 *` | Once a year, Jan 1st |
102
+ | `@annually` | `0 0 1 1 *` | Same as @yearly |
103
+ | `@monthly` | `0 0 1 * *` | First day of each month |
104
+ | `@weekly` | `0 0 * * 0` | Every Sunday at midnight |
105
+ | `@daily` | `0 0 * * *` | Every day at midnight |
106
+ | `@midnight` | `0 0 * * *` | Same as @daily |
107
+ | `@hourly` | `0 * * * *` | Every hour |
108
+
109
+ ### Event trigger
110
+
111
+ Runs the function when a named event is emitted via the shared `eventBus`.
112
+
113
+ ```yaml
114
+ triggers:
115
+ - type: event
116
+ name: user.created
117
+ ```
118
+
119
+ Emit from middleware or other functions:
120
+
121
+ ```js
122
+ const { eventBus } = require('./core/functions-engine');
123
+ eventBus.emit('user.created', { id: user.id });
124
+ ```
125
+
126
+ ## Function formats (JS runtime)
127
+
128
+ ### Universal (recommended)
129
+
130
+ ```js title="functions/hello.js"
131
+ module.exports = async function(event, ctx) {
132
+ if (ctx.trigger === 'http') return { message: 'Hello from HTTP!' };
133
+ if (ctx.trigger === 'cron') console.log('Running scheduled task');
134
+ if (ctx.trigger === 'event') console.log('Event payload:', event);
135
+ };
136
+ ```
137
+
138
+ The `event` object for HTTP triggers contains `{ req, body, query, params, headers }`.
139
+ The `ctx` object always has `{ trigger, name }` plus trigger-specific fields (`method`, `path`, `schedule`, `event`).
140
+
141
+ ### AWS Lambda format
142
+
143
+ ```js title="functions/hello.js"
144
+ exports.handler = async (event, context) => {
145
+ return { statusCode: 200, body: JSON.stringify({ message: 'Hello!' }) };
146
+ };
147
+ ```
148
+
149
+ ### Cloudflare Workers format
150
+
151
+ ```js title="functions/hello.js"
152
+ export default {
153
+ async fetch(request) {
154
+ return new Response(JSON.stringify({ message: 'Hello!' }), {
155
+ headers: { 'Content-Type': 'application/json' },
156
+ });
157
+ },
158
+ };
159
+ ```
160
+
161
+ ## Runtimes
162
+
163
+ | Runtime | Execution | Notes |
164
+ | -------- | ------------------ | -------------------------------- |
165
+ | `js` | In-process | Default. Supports all formats. |
166
+ | `python` | Persistent worker | Reads `event` from stdin as JSON |
167
+ | `ruby` | Persistent worker | Reads `event` from stdin as JSON |
168
+ | `php` | Persistent worker | Reads `event` from stdin as JSON |
169
+ | `bash` | Per-invocation | Reads `event` from stdin as JSON |
170
+ | `go` | Per-invocation | `go run` per invocation |
171
+ | `c++` | Per-invocation | Compiled with `g++` |
172
+
173
+ Python/Ruby/PHP runtimes spawn one persistent worker process per runtime (not per request) for better performance.
174
+
175
+ ## Configuration
176
+
177
+ ### Function options
178
+
179
+ | Option | Default | Description |
180
+ | ------------ | ------- | ---------------------------------------------------- |
181
+ | `function`* | — | File name relative to the functions folder |
182
+ | `runtime` | `js` | Runtime to use |
183
+ | `description`| — | Optional description (shown in OpenAPI docs) |
184
+ | `triggers`* | — | Array of trigger definitions |
185
+
186
+ ### HTTP trigger options
187
+
188
+ | Option | Default | Description |
189
+ | ---------- | -------- | -------------------------------------------------------- |
190
+ | `type`* | — | `http` |
191
+ | `method` | `GET` | HTTP verb: `GET` `POST` `PUT` `PATCH` `DELETE` |
192
+ | `path`* | — | URL path, e.g. `/hello` or `/users/:id/activate` |
193
+ | `policies` | `public` | Array of policy objects to restrict access (see above) |
194
+
195
+ !!! tip
196
+ Set `CHADSTART_FUNCTIONS_FOLDER` in your `.env` to use a different folder than `/functions`.
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: Get Started
3
+ description: ChadStart is an Open Source backend that fits in a single YAML file. Easy to edit, validate and version for humans and LLMs.
4
+ ---
5
+
6
+ # Get Started 👋
7
+
8
+ ## Introduction
9
+
10
+ ChadStart is a **1-file backend** for prototypes and MVPs.
11
+
12
+ Most backend tools feel too heavy for simple apps. They force you to use bloated configuration UIs. Even with AI tools that generate frontend code, the backend remains a pain to set up and validate. It slows you down when you just want to test an idea or build something simple.
13
+
14
+ ChadStart is an open source backend that fits in only 1 file. You define it in a simple yaml language to get data, auth, storage, logic and an admin panel.
15
+
16
+ **Key advantages:**
17
+
18
+ - 🧠 Zero friction setup
19
+ - 🚀 Ship your backend fast and stay focused on building your app
20
+ - 🤖 Easy for LLMs to generate
21
+ - 💻 Can run everywhere
22
+
23
+ ## Install ChadStart
24
+
25
+ Follow the steps below to install ChadStart in your local machine.
26
+
27
+ ### Prerequisites
28
+
29
+ - [NodeJS](https://nodejs.org/en/) (**20.x** or superior).
30
+
31
+ ### Installation steps
32
+
33
+ Run this command to create a ChadStart project ready to use with Cursor IDE.
34
+
35
+ ```bash
36
+ # NPX
37
+ npx chadstart my-project --cursor
38
+
39
+ # Yarn
40
+ yarn create chadstart my-project --cursor
41
+ ```
42
+
43
+ This will create a `my-project` folder with a ChadStart backend configured for Cursor.
44
+
45
+ You can replace `--cursor` with another option if you're using a different AI tool:
46
+
47
+ - `--copilot` if you're using **GitHub Copilot**
48
+ - `--windsurf` for **Windsurf**
49
+ - or remove it entirely if you're not using any AI coding tool
50
+
51
+ To start the ChadStart backend, run the following command in the new project folder:
52
+
53
+ ```
54
+ cd my-project
55
+ npm run start
56
+ ```
57
+
58
+ You can now:
59
+
60
+ - See your **Admin panel** at http://localhost:3000 using the email `admin@chadstart.com` and the password `admin`
61
+
62
+ - Use your **REST API** at http://localhost:3000/api
63
+
64
+ !!! tip
65
+ If you already have a frontend app, we recommend that you use a **monorepo** structure with one folder for the backend and one folder for the frontend. For example you can run `npx chadstart server` at root level to add your ChadStart to a `server` folder that you put next to the `client` folder that will contain your frontend.
66
+
67
+ #### Note with PNPM
68
+
69
+ As [PNPM](https://pnpm.io/fr/) blocks postinstall scripts, we have to adapt the `package.json`. Add this to your `package.json` file before doing `pnpm install`:
70
+
71
+ ```json
72
+ "pnpm": {
73
+ "onlyBuiltDependencies": [
74
+ "@nestjs/core",
75
+ "sharp",
76
+ "sqlite3"
77
+ ]
78
+ }
79
+ ```
package/docs/groups.md ADDED
@@ -0,0 +1,85 @@
1
+ ---
2
+ id: groups
3
+ title: Groups (nested entities)
4
+ slug: groups
5
+ description: TODO
6
+ ---
7
+
8
+ # Groups (nested entities)
9
+
10
+ A group is a **reusable set of properties** that you can attach to your entities: whether they are [single](./entities.md#singles) or [collections](./entities.md#collections). They help you structure your nested data without having to repeat yourself. Some common use cases for groups are:
11
+
12
+ - Testimonials
13
+ - FAQs
14
+ - Widgets (CTA, UI elements like cards, blocks etc.)
15
+
16
+ Groups are automatically loaded when you fetch a list or a detail version of the parent entity (using both REST API and SDK).
17
+
18
+ ## Syntax
19
+
20
+ Define your groups in the `chadstart.yaml` file to use it in entities as a property.
21
+
22
+ ```yaml title="chadstart.yaml"
23
+ entities:
24
+ Service:
25
+ properties:
26
+ - name
27
+ - { name: description, helpText: 'Description of the service' }
28
+ - {
29
+ name: testimonials,
30
+ type: group, # Group type indicates that it is a group.
31
+ helpText: 'Add some testimonials for the service',
32
+ options: { group: Testimonial } # Pass the name of the group in the "group" option
33
+ }
34
+
35
+ groups:
36
+ Testimonial: # We create a testimonial group with 3 properties.
37
+ properties:
38
+ - { name: author, type: text }
39
+ - { name: content, type: text }
40
+ - { name: rating, type: number, helpText: '1 to 5 stars' }
41
+ validation:
42
+ rating: { isNotEmpty: true }
43
+ ```
44
+
45
+ The code above will add testimonials to service. Once the `Testimonial` group is created, you can add it in as many entities as you want.
46
+
47
+ ## Non-multiple groups
48
+
49
+ In the example above, each service can have several testimonials, but you can also have non-multiple groups.
50
+
51
+ This example shows a backend for a website where each page has a single "call to action" element that can be used as widget UI.
52
+
53
+ ```yaml title="chadstart.yaml"
54
+ Homepage:
55
+ single: true
56
+ properties:
57
+ - { name: title, type: text }
58
+ - {
59
+ name: callToAction,
60
+ type: group,
61
+ options: { group: CallToAction, multiple: false }
62
+ }
63
+
64
+ AboutPage:
65
+ single: true
66
+ properties:
67
+ - { name: title, type: text }
68
+ - { name: description, type: text }
69
+ - {
70
+ name: callToAction,
71
+ type: group,
72
+ options: { group: CallToAction, multiple: false }
73
+ }
74
+
75
+ groups:
76
+ CallToAction:
77
+ properties:
78
+ - { name: title, type: string }
79
+ - { name: description, type: text }
80
+ - { name: buttonText, type: string, helpText: "Text for the button" }
81
+ - { name: buttonLink, type: link }
82
+ validation:
83
+ title: { isNotEmpty: true }
84
+ description: { isNotEmpty: true }
85
+ ```
package/docs/index.md ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ template: home.html
3
+ title: ChadStart — YAML-first Backend as a Service
4
+ description: ChadStart is an Open Source backend that fits in a single YAML file. Easy to edit, validate and version for humans and LLMs.
5
+ ---
@@ -0,0 +1,81 @@
1
+ ---
2
+ id: llm-rules
3
+ title: LLM Rules
4
+ description: Configure AI coding assistants to understand your ChadStart YAML backend. Works with Cursor, GitHub Copilot, Windsurf, and more.
5
+ ---
6
+
7
+ # LLM Rules
8
+
9
+ ChadStart is designed to be **LLM-friendly**: the entire backend is described in a single YAML file that AI coding assistants can read, generate, and modify with ease.
10
+
11
+ When you scaffold a new project with the `--cursor`, `--copilot`, or `--windsurf` flag, ChadStart automatically creates the appropriate rules file that teaches your AI assistant about the `chadstart.yaml` format.
12
+
13
+ ## Scaffolding with AI rules
14
+
15
+ === "Cursor"
16
+
17
+ ```bash
18
+ npx chadstart my-project --cursor
19
+ ```
20
+
21
+ Creates `.cursor/rules/chadstart.mdc` — a Cursor rules file that helps Cursor understand the ChadStart schema.
22
+
23
+ === "GitHub Copilot"
24
+
25
+ ```bash
26
+ npx chadstart my-project --copilot
27
+ ```
28
+
29
+ Creates `.github/copilot-instructions.md` — custom instructions for GitHub Copilot.
30
+
31
+ === "Windsurf"
32
+
33
+ ```bash
34
+ npx chadstart my-project --windsurf
35
+ ```
36
+
37
+ Creates `.windsurf/rules/chadstart.md` — rules for the Windsurf AI assistant.
38
+
39
+ === "No AI tool"
40
+
41
+ ```bash
42
+ npx chadstart my-project
43
+ ```
44
+
45
+ Creates the project without any AI assistant configuration.
46
+
47
+ ## What the rules file contains
48
+
49
+ The generated rules file provides your AI assistant with:
50
+
51
+ - The full `chadstart.yaml` schema (entities, fields, auth, policies, etc.)
52
+ - Descriptions of available field types (`string`, `text`, `image`, `file`, `boolean`, `choice`, …)
53
+ - Examples of common patterns (authenticable entities, access policies, relations)
54
+ - Instructions on how to generate valid YAML for ChadStart
55
+
56
+ This means you can describe your app in plain English and let Cursor, Copilot, or Windsurf write the `chadstart.yaml` for you.
57
+
58
+ ## Prompt examples
59
+
60
+ Once the rules file is in place you can use prompts like:
61
+
62
+ > *"Add a `Comment` entity with a `body` (text) field, a relation to `Post`, and make it authenticable so only the author can delete their own comments."*
63
+
64
+ > *"Add rate limiting: max 100 requests per minute."*
65
+
66
+ > *"Create a `Product` entity with a `name` (string), `price` (money), `image` (image), and a `category` choice field with options: Electronics, Clothing, Food."*
67
+
68
+ ## Manual setup
69
+
70
+ If you already have an existing project and want to add AI rules manually, create one of the following files with content describing the [ChadStart YAML schema](./entities.md):
71
+
72
+ | AI tool | Rules file location |
73
+ | ------------------ | ---------------------------------------------- |
74
+ | **Cursor** | `.cursor/rules/chadstart.mdc` |
75
+ | **GitHub Copilot** | `.github/copilot-instructions.md` |
76
+ | **Windsurf** | `.windsurf/rules/chadstart.md` |
77
+
78
+ You can base your rules file on the [chadstart.example.yml](https://github.com/saulmmendoza/chadstart.com/blob/main/chadstart.example.yml) reference file, which documents every available configuration option.
79
+
80
+ !!! tip
81
+ Keep your rules file up to date whenever you upgrade ChadStart. Newer versions may introduce new field types, options, or top-level blocks that your AI assistant won't know about unless the rules file is updated.
@@ -0,0 +1,78 @@
1
+ ---
2
+ id: middlewares
3
+ title: Middlewares
4
+ description: Add middlewares to trigger custom logic at defined lifecycle events of your ChadStart backend. 6 available events related to entities.
5
+ ---
6
+
7
+ ## Introduction
8
+
9
+ **Middleware functions** or **middlewares** are intermediary functions that sit between the client's request and the server's response. They have access to the request object (req) and the response object (res).
10
+
11
+ As ChadStart works with **ExpressJS**, ChadStart middlewares are [ExpressJS middlewares](https://expressjs.com/en/guide/using-middleware.html) enhanced with the [ChadStart SDK](./crud.md#using-the-javascript-sdk) that allows you to interact with your data with ease.
12
+
13
+ ## Middleware use cases
14
+
15
+ Here are some examples of middleware use cases:
16
+
17
+ - Patch the request body before storing it in the DB
18
+ - Call an external API or any other custom logic
19
+ - Hide some data from the response
20
+ - Trigger an internal or external action on an event (see also [webhooks](./webhooks.md))
21
+
22
+ ## Syntax
23
+
24
+ ```yaml title="chadstart.yaml"
25
+ entities:
26
+ Project 🗂️:
27
+ properties:
28
+ - name
29
+ - { name: date, type: date }
30
+ middlewares:
31
+ beforeCreate:
32
+ - function: setDate.js
33
+ afterCreate:
34
+ - function: sendEmail.js
35
+ ```
36
+
37
+ This example triggers the function located at `/functions/setDate.js` before the item is created and stored in the database, and triggers `/functions/sendEmail.js` after.
38
+
39
+ ```js title="/functions/setDate.js"
40
+ module.exports = async (req, res) => {
41
+ console.log('Hello from the function!')
42
+
43
+ req.body['date'] = new Date()
44
+ }
45
+ ```
46
+
47
+ !!! tip
48
+ You can add **several middlewares** for an event. They will be processed sequentially in the order you define.
49
+
50
+ ## Use your data with the ChadStart backend SDK
51
+
52
+ ChadStart passes the [JS SDK](./crud.md#using-the-javascript-sdk) to middleware functions as third argument. You can use it to fetch or write data.
53
+
54
+ ```js title="/functions/patchDocumentNameIfEmpty.js"
55
+ module.exports = async (req, res, chadstart) => {
56
+ // If the 'name' property of the item is empty.
57
+ if (!req.body['name']) {
58
+ // Get the user from the request body.
59
+ const user = await chadstart.from('users').findOneById(req.body['userId'])
60
+
61
+ // Set a custom name based on the user.
62
+ req.body['name'] = `${user.name}'s untitled document`
63
+ }
64
+ }
65
+ ```
66
+
67
+ ## Events
68
+
69
+ This is the list and description of the 6 events available to which you can attach middlewares. All of them are related to an [entity](./entities.md)
70
+
71
+ | Name | Description |
72
+ | ---------------- | ------------------------ |
73
+ | **beforeCreate** | Before creating a record |
74
+ | **afterCreate** | After creating a record |
75
+ | **beforeUpdate** | Before updating a record |
76
+ | **afterUpdate** | After updating a record |
77
+ | **beforeDelete** | Before deleting a record |
78
+ | **afterDelete** | After deleting a record |