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
package/docs/deploy.md ADDED
@@ -0,0 +1,113 @@
1
+ ---
2
+ id: deploy
3
+ title: Deploy to Production
4
+ description: Deploy your ChadStart backend to production in no time. Server, Databases and Storage options. Deploy on popular cloud providers and use Docker image.
5
+ ---
6
+
7
+ # Deploy ChadStart
8
+
9
+ ## Introduction
10
+
11
+ ChadStart is made to be **self-hosted**: backends can be deployed with ease wherever you want using different methods.
12
+
13
+ We recommend using [Docker](#docker) to simplify deployments but you also can install ChadStart manually on a VM or on a bare-metal server.
14
+
15
+ ## System requirements
16
+
17
+ The minimum system requirements to run a small ChadStart backend are **1vCPU** and **512 MB RAM**. It usually corresponds to one of the cheapest options on cloud providers.
18
+
19
+ The server needs at least [Node.js v18 or more](https://nodejs.org/fr) and a process manager like [pm2](https://github.com/Unitech/pm2/).
20
+
21
+ ### Database
22
+
23
+ ChadStart works by default in local with SQLite but we recommend to [switch to PostgreSQL](./config.md#database) for production deployments.
24
+
25
+ All popular hosting providers have their managed PostgreSQL solutions and there are many DB-as-a-Service providers like [Neon](https://neon.tech/) that offer generous free-tier to get started. Here is a list of popular services:
26
+
27
+ | Provider | Service Name |
28
+ | ------------------- | ----------------------------------------------------------------------------------------------------- |
29
+ | **Amazon** | [Amazon Aurora PostgreSQL](https://aws.amazon.com/rds/aurora/features/) |
30
+ | **Google Cloud** | [Cloud SQL for PostgreSQL](https://cloud.google.com/sql/docs/postgres) |
31
+ | **Microsoft Azure** | [Azure Database for PostgreSQL](https://azure.microsoft.com/en-us/products/postgresql/) |
32
+ | **Neon** | [Neon Database](https://neon.tech/) |
33
+ | **Crunchy Data** | [Crunchy Bridge](https://www.crunchydata.com/products/crunchy-bridge) |
34
+ | **Aiven** | [Aiven for PostgreSQL](https://aiven.io/postgresql) |
35
+ | **DigitalOcean** | [DigitalOcean Managed PostgreSQL](https://www.digitalocean.com/products/managed-databases-postgresql) |
36
+ | **Heroku** | [Heroku Postgres](https://heroku.com/postgres) |
37
+ | **StackGres** | [StackGres](https://stackgres.io/) |
38
+ | **Render.com** | [Render PostgreSQL Database](https://render.com/docs/postgresql-creating-connecting) |
39
+
40
+ !!! tip
41
+ While you could technically create a [Docker volume](https://docs.docker.com/engine/storage/volumes/) to ensure data persistence for your SQLite database, we found it easier to use any managed PostgreSQL service **even if you never used PostgreSQL**.
42
+
43
+ ### Storage
44
+
45
+ ChadStart supports local storage and S3 storage.
46
+
47
+ With **local storage**, files are saved on disk but will be lost when the container restarts if you are using [Docker](https://www.docker.com/).
48
+
49
+ With **S3 storage**, files are stored externally, ensuring they are persistent and accessible.
50
+
51
+ Follow the [S3 Storage documentation](./s3-storage.md) to set it up.
52
+
53
+ ### Environment variables
54
+
55
+ You need to create a `.env` file at app root level with at least the following variables:
56
+
57
+ ```env title=".env"
58
+ TOKEN_SECRET_KEY=%ReplaceByYourKey%
59
+ NODE_ENV=production
60
+ BASE_URL=https://my-backend.com
61
+ ```
62
+
63
+ See more [environment variables](./config.md#general-variables) you may need.
64
+
65
+ ### Start script for production
66
+
67
+ The `npm run start` script should only be used for **development** as it watches file changes.
68
+
69
+ Go back to your codebase and open the `package.json` file and add a new **start:prod** script on the scripts list with the value `node node_modules/chadstart/dist/main.js` as following:
70
+
71
+ ```json title="package.json"
72
+ "scripts": {
73
+ "start:prod": "node node_modules/chadstart/dist/main.js"
74
+ [...]
75
+ }
76
+ ```
77
+
78
+ After that you will be able to run ChadStart for production with `npm run start:prod` without watching file changes.
79
+
80
+ ## Docker
81
+
82
+ [Docker](https://www.docker.com/) is a popular choice among developers. It uses containerization to ensure that the app will work well in any environment.
83
+
84
+ ```dockerfile title="Dockerfile"
85
+ # Use the official Node.js image as a base
86
+ FROM node:22-slim
87
+
88
+ # Copy package.json and package-lock.json (if available)
89
+ COPY package*.json ./
90
+
91
+ # Install dependencies
92
+ RUN npm install && npm cache clean --force && rm -rf /root/.npm && rm -rf /tmp/*
93
+
94
+ # Copy the rest of your application code
95
+ COPY . .
96
+
97
+ # Set the NODE_ENV environment variable
98
+ ENV NODE_ENV=production
99
+
100
+ # Expose the port the app runs on (adjust as needed)
101
+ EXPOSE 3000
102
+
103
+ # Start the application
104
+ CMD ["npm", "run", "start:prod"]
105
+ ```
106
+
107
+ ## Guides for popular app platform services
108
+
109
+ Here are some quick guides to launch your app in a few minutes:
110
+
111
+ - [Deploy ChadStart on DigitalOcean App Platform](https://chadstart.com/integrations/digital-ocean)
112
+ - [Deploy ChadStart on Render.com](https://chadstart.com/integrations/render)
113
+ - [Deploy ChadStart on Heroku](https://chadstart.com/integrations/heroku)
package/docs/docker.md ADDED
@@ -0,0 +1,59 @@
1
+ # Docker
2
+
3
+ ChadStart is available as a Docker image at `ghcr.io/saulmmendoza/chadstart.com`.
4
+
5
+ ## Run with `docker run`
6
+
7
+ ```bash
8
+ docker run -p 3000:3000 \
9
+ -e JWT_SECRET=your-secret \
10
+ -v ./chadstart.yaml:/app/chadstart.yaml:ro \
11
+ -v ./chadstart.db:/app/chadstart.db \
12
+ ghcr.io/saulmmendoza/chadstart.com:latest
13
+ ```
14
+
15
+ ## Run with `docker compose`
16
+
17
+ 1. Create a `.env` file with your secrets:
18
+
19
+ ```bash
20
+ echo "JWT_SECRET=$(openssl rand -hex 32)" > .env
21
+ ```
22
+
23
+ 2. Create a `docker-compose.yml` (or use the provided one):
24
+
25
+ ```yaml
26
+ services:
27
+ chadstart:
28
+ image: ghcr.io/saulmmendoza/chadstart.com:latest
29
+ ports:
30
+ - "3000:3000"
31
+ environment:
32
+ JWT_SECRET: ${JWT_SECRET}
33
+ volumes:
34
+ - ./chadstart.yaml:/app/chadstart.yaml:ro
35
+ - ./chadstart.db:/app/chadstart.db
36
+ ```
37
+
38
+ 3. Start the service:
39
+
40
+ ```bash
41
+ docker compose up
42
+ ```
43
+
44
+ ## Environment Variables
45
+
46
+ | Variable | Default | Description |
47
+ |----------|---------|-------------|
48
+ | `JWT_SECRET` | dev-only default | JWT signing secret — **required in production** |
49
+ | `JWT_EXPIRES` | `7d` | Token expiry duration |
50
+ | `PORT` | `3000` | Server port |
51
+ | `NODE_ENV` | `development` | Set to `production` in production |
52
+
53
+ ## Persistent Storage
54
+
55
+ Mount a volume for the SQLite database to persist data across container restarts:
56
+
57
+ ```bash
58
+ -v ./chadstart.db:/app/chadstart.db
59
+ ```
@@ -0,0 +1,385 @@
1
+ ---
2
+ id: entities
3
+ title: Entities
4
+ descriptions: Entities are the foundation of ChadStart. Define your data structure in few lines and use 15+ real-world types for your properties.
5
+ ---
6
+
7
+ # Entities
8
+
9
+ ## Introduction
10
+
11
+ An entity is a model of objects linked to real-world concepts. Creating an entity in chadstart generates **CRUD endpoints** that can be used by the [REST API](./crud.md#using-the-rest-api) or the [SDK](./crud.md#using-the-javascript-sdk).
12
+
13
+ All entities are located in the `chadstart.yaml` file under the **entities** property.
14
+
15
+ There are 2 types of entities in ChadStart: [Collections](#collections) and [Singles](#singles). **Collections** are multiple instances of similar data, stored as a list. E.g., users, customers, videos, etc. Singles are unique, standalone data that are singular in nature. E.g., home content, about content, settings, logo...
16
+
17
+ ## Collections
18
+
19
+ Let's see a simple example:
20
+
21
+ ```yaml title="chadstart.yaml"
22
+ name: A pet app
23
+
24
+ entities:
25
+ Cat 😺:
26
+ properties:
27
+ - name
28
+ Dog 🐶:
29
+ properties:
30
+ - name
31
+ ```
32
+
33
+ This file will generate the **Cat** and **Dog** entity both with a `name` property. In ChadStart by default all entities have an **id** (UUID format) so you do not need to add it. They also have automatic **createdAt** and **updatedAt** columns that are not selected by default in the API requests.
34
+
35
+ You can now add your own pets through the admin panel!
36
+
37
+ To generate dummy data for all your entities, run the simple command:
38
+
39
+ ```
40
+ npm run seed
41
+ ```
42
+
43
+ !!! warning
44
+ The seed replaces the previous data by the new one and thus should never be used in production.
45
+
46
+ ### Entity params
47
+
48
+ You can pass different arguments to configure your entities. Example:
49
+
50
+ ```yaml
51
+ entities:
52
+ Member 👤:
53
+ seedCount: 200
54
+ mainProp: lastName
55
+ properties:
56
+ - firstName
57
+ - lastName
58
+ - email
59
+ ```
60
+
61
+ | Option | Default | Type | Description |
62
+ | ----------------- | -------------------------- | -------- | -------------------------------------------------------------------------------------------------------- |
63
+ | **authenticable** | false | Boolean | Whether the entity is [authenticable](auth.md#authenticable-entities) or not |
64
+ | **mainProp** | _first string field_ | String | Identifier prop. Used widely on the admin panel |
65
+ | **nameSingular** | _singular lower case name_ | String | The singular lowercase name of your entity. Used widely on the admin panel. |
66
+ | **namePlural** | _plural lowercase name_ | String | The plural lowercase name of your entity. Used widely on the admin panel. |
67
+ | **policies** | - | Policies | The [access control policies](./access-policies.md) of your entity |
68
+ | **properties** | `[]` | Array | The [properties](./entities.md#properties) of your entity |
69
+ | **seedCount** | `50` | Number | The number of entities to seed when running the seed command. |
70
+ | **slug** | _plural kebab-case name_ | String | The kebab-case slug of the entity that will define API endpoints. |
71
+
72
+ ## Singles
73
+
74
+ Single entities differ a bit from [collections](#collections). A single entity is **singular in nature**, and there can be only one record of them. Examples are website dynamic elements, pages, standalone content or settings. They do not have [relations](./entities.md#relations).
75
+
76
+ On single entities **Create** and **Delete** CRUD actions are disabled. Thus, the [REST API endpoints for single entities](./crud.md#singles) are different.
77
+
78
+ ```yaml
79
+ ContactPage:
80
+ single: true
81
+ slug: contact
82
+ properties:
83
+ - { name: title, type: string }
84
+ - { name: content, type: text }
85
+ - { name: image, type: image }
86
+ validation:
87
+ title: { required: true }
88
+ ```
89
+
90
+ You can generate dummy data for all your entities with the simple command:
91
+
92
+ ```
93
+ npm run seed
94
+ ```
95
+
96
+ ### Entity params
97
+
98
+ You can pass different arguments to configure your single entities. Example:
99
+
100
+ ```yaml
101
+ entities:
102
+ Member 👤:
103
+ seedCount: 200
104
+ mainProp: lastName
105
+ properties:
106
+ - firstName
107
+ - lastName
108
+ - email
109
+ ```
110
+
111
+ | Option | Default | Type | Description |
112
+ | ---------------- | -------------------------- | -------- | --------------------------------------------------------------------------- |
113
+ | **nameSingular** | _singular lower case name_ | string | The singular lowercase name of your entity. Used widely on the admin panel. |
114
+ | **policies** | - | Policies | The [access control policies](./access-policies.md) of your entity |
115
+ | **properties** | `[]` | Array | The [properties](./entities.md#properties) of your entity |
116
+ | **slug** | _plural dasherized name_ | string | The kebab-case slug of the entity that will define API endpoints. |
117
+
118
+
119
+ ## Properties
120
+
121
+ Properties are the characteristics of your [entities](./entities.md). For example, a **Product** can have properties like `name`, `description`, `price`...
122
+
123
+ ### Syntax
124
+
125
+ You can add the properties to your entities in the **chadstart.yaml file**
126
+
127
+ ```yaml title="chadstart.yaml"
128
+ name: Blog about cats
129
+ entities:
130
+ Post 📝:
131
+ properties:
132
+ - name # Short syntax for string type.
133
+ - { name: content, type: text } # Long syntax for other types.
134
+ - { name: publishedAt, type: date }
135
+ - { name: authorEmail, type: email, hidden: true } # Extra options.
136
+ - {
137
+ name: status,
138
+ type: choice,
139
+ options: { values: [draft, pending, published] },
140
+ default: draft # Default value if property not specified.
141
+ }
142
+ ```
143
+
144
+ ### Property params
145
+
146
+ You can pass arguments using the long syntax:
147
+
148
+ | Option | Default | Type | Description |
149
+ | -------------- | -------- | ---------- | --------------------------------------------------------------------------------------------------------- |
150
+ | **type** | "string" | _PropType_ | The [Property type](#property-types) (text, number, email, location...) |
151
+ | **hidden** | `false` | boolean | If the property should be hidden in the API response |
152
+ | **options** | - | Object | Specific options depending on [property type](#property-types) |
153
+ | **validation** | - | Object | The [property validators](./validation.md) that each request compares against |
154
+ | **helpText** | - | string | Optional help text to display in admin UI |
155
+ | **default** | - | any | The default value. When creating an item, if the property is not specified it will default to this value. |
156
+
157
+ ### Property types
158
+
159
+ ChadStart vision of **property types** goes beyond software development typing and is already built-in for real world usages. For example, the [Money](#money) PropType is handier than [Number](#number) for managing amounts as it comes with a `currency` option that only allows 2 digits after the comma.
160
+
161
+ Each PropType comes with built-in type [validation](./validation.md).
162
+
163
+ Some of them have specific options. Here is a list of the available types:
164
+
165
+ #### String
166
+
167
+ A simple string.
168
+
169
+ ```yaml
170
+ - { name: firstName, type: string }
171
+
172
+ # Short syntax, same as above.
173
+ - firstName
174
+ ```
175
+
176
+ #### Textarea
177
+
178
+ Textarea field for medium-size texts.
179
+
180
+ ```yaml
181
+ - { name: description, type: text }
182
+ ```
183
+
184
+ #### Rich text
185
+
186
+ Rich text field for HTML content. The admin panel input can generate basic HTML tags like bold, italic, headings, links and bullet lists.
187
+
188
+ ```yaml
189
+ - { name: description, type: richText }
190
+ ```
191
+
192
+ #### Number
193
+
194
+ A numerical value.
195
+
196
+ ```yaml
197
+ - { name: age, type: number }
198
+ ```
199
+
200
+ #### Link
201
+
202
+ An URL that links to an external page.
203
+
204
+ ```yaml
205
+ - { name: website, type: link }
206
+ ```
207
+
208
+ #### Money
209
+
210
+ A money field with a currency. Money properties can have up to 2 digits after the comma.
211
+
212
+ ```yaml
213
+ - { name: price, type: money, options: { currency: 'EUR' } }
214
+ ```
215
+
216
+ ###### Parameters
217
+
218
+ | Option | Default | Type | Description |
219
+ | ------------ | ------- | ------ | ------------------------------------------------------------------------------------------------ |
220
+ | **currency** | _USD_ | string | [ISO 4217 currency code](https://en.wikipedia.org/wiki/ISO_4217#List_of_ISO_4217_currency_codes) |
221
+
222
+ #### Date
223
+
224
+ Basic date field.
225
+
226
+ ```yaml
227
+ - { name: startDate, type: date }
228
+ ```
229
+
230
+ #### Timestamp
231
+
232
+ Timestamp field (ISO 8601 Format)
233
+
234
+ ```yaml
235
+ - { name: acquiredAt, type: timestamp }
236
+ ```
237
+
238
+ #### Email
239
+
240
+ You can create one-to-many relationships or many-to-many relationships. Defining relationships in your entities allows you to load relations when you query them and also filter by relations.
241
+
242
+ ```yaml
243
+ - { name: email, type: email }
244
+ ```
245
+
246
+ #### Boolean
247
+
248
+ For any field with a "true or false" value.
249
+
250
+ ```yaml
251
+ - { name: isActive, type: boolean }
252
+ ```
253
+
254
+ #### File
255
+
256
+ A file upload. Read more in the [file upload doc](./upload.md#upload-a-file).
257
+
258
+ ```yaml
259
+ - { name: document, type: file }
260
+ ```
261
+
262
+ !!! note
263
+ ChadStart stores the **absolute paths** of uploaded files. Use the [`BASE_URL`](./upload.md#add-a-base_url-variable) environment variable to adapt it to your domain.
264
+
265
+ #### Image
266
+
267
+ An image upload. The different sizes should be provided to generate several sizes of it. Read more in the [image upload doc](./upload.md#upload-an-image).
268
+
269
+ ```yaml
270
+ - {
271
+ name: photo,
272
+ type: image,
273
+ options:
274
+ { sizes: { small: { height: 90, width: 90 }, large: { width: 200 } } }
275
+ }
276
+ ```
277
+
278
+ !!! note
279
+ ChadStart stores the **absolute paths** of uploaded images. Use the [`BASE_URL`](./upload.md#add-a-base_url-variable) environment variable to adapt it to your domain.
280
+
281
+ ###### Parameters
282
+
283
+ | Option | Default | Type | Description |
284
+ | --------- | -------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
285
+ | **sizes** | _thumbnail (80x80)_ _medium (160x160)_ | ImageSizesObject | An object with each key being the name of each size and with `width`, `height` and `fit` optional props. The _fit_ options works as in [Sharp](https://sharp.pixelplumbing.com/api-resize) |
286
+
287
+ #### Password
288
+
289
+ Password field. Most of the time you do not need to implement passwords manually as [authenticable entities](./auth.md#authenticable-entities) have built-in `email` and `password` fields to log in.
290
+
291
+ ```yaml
292
+ - { name: password, type: password }
293
+ ```
294
+
295
+ !!! warning
296
+ When setting the type as `password`, ChadStart hashes automatically the value before storing it. Passwords should never be stored as clear text.
297
+
298
+ #### Choice
299
+
300
+ A given choice of options.
301
+
302
+ ```yaml
303
+ - { name: sex, type: choice, options: { values: [male, female] } }
304
+
305
+ # Sequential if the values are ordered in a logical sense..
306
+ - {
307
+ name: status,
308
+ type: choice,
309
+ options: { values: [draft, submitted, published], sequential: true }
310
+ }
311
+ ```
312
+
313
+ ###### Parameters
314
+
315
+ | Option | Default | Type | Description |
316
+ | -------------- | --------- | -------- | ------------------------------------------------------ |
317
+ | **values** | _(empty)_ | String[] | An array of strings representing the available choices |
318
+ | **sequential** | `false` | boolean | Specifies if the values are ordered in a logical sense |
319
+
320
+ #### Location
321
+
322
+ The location type consists in a object with `lat` and `lng` coordinates.
323
+
324
+ ```yaml
325
+ - { name: location, type: location }
326
+ ```
327
+
328
+ ## Relations
329
+
330
+ You can create **one-to-many** relationships or **many-to-many** relationships. Defining relationships in your entities allows you to [load relations](./crud.md#load-relations) when you query them and also [filter your query by relations](./crud.md#filter-by-relation).
331
+
332
+ ### Syntax
333
+
334
+ The following example showcases the possibilities of **ChadStart relations**:
335
+
336
+ ```yaml title="chadstart.yaml"
337
+ name: Basketball League 🏀
338
+
339
+ entities:
340
+ Player 🤾:
341
+ properties:
342
+ - name
343
+ belongsTo:
344
+ - Team
345
+ belongsToMany:
346
+ - Skill
347
+
348
+ Team 👥:
349
+ properties:
350
+ - name
351
+
352
+ Skill 💪:
353
+ properties:
354
+ - name
355
+
356
+ Fixture 🏟️:
357
+ properties:
358
+ - { name: homeScore, type: number }
359
+ - { name: awayScore, type: number }
360
+ belongsTo:
361
+ - { name: homeTeam, entity: Team }
362
+ - { name: awayTeam, entity: Team }
363
+ ```
364
+
365
+ In other words:
366
+
367
+ - The **belongsTo** keyword creates a **many-to-one** relationship (and its opposite _one-to-many_)
368
+ - The **belongsToMany** keyword creates a **many-to-many** bi-directional relationship
369
+ - The **long syntax** (as in _Fixture.belongsTo_) is useful when we want to edit the name of the relationships
370
+
371
+ !!! tip
372
+ All relationships are **bi-directional**, which means that you just have to specify them **in one side only** to work with them in both directions.
373
+
374
+ When you define a **belongsTo** relationship, it implicitly set the opposite _hasMany_ relationship and allow [querying relations](./crud.md#work-with-relations) in both directions.
375
+
376
+ ### Relation params
377
+
378
+ You can pass arguments using the long syntax:
379
+
380
+ | Option | Default | Type | Description |
381
+ | ------------ | ----------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
382
+ | **name** | Entity name | string | The name of the relation |
383
+ | **entity** | - | string | The class name of the entity that the relationship is with |
384
+ | **helpText** | - | string | Optional help text to display in admin UI |
385
+ | **eager** | `false` | boolean | Whether the relationship should be eager loaded. Otherwise, you need to explicitly request the relation in the client SDK or API |