@venizia/ignis-docs 0.0.3 → 0.0.4-1
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.
- package/README.md +1 -1
- package/package.json +4 -2
- package/wiki/best-practices/api-usage-examples.md +591 -0
- package/wiki/best-practices/architectural-patterns.md +415 -0
- package/wiki/best-practices/architecture-decisions.md +488 -0
- package/wiki/{get-started/best-practices → best-practices}/code-style-standards.md +406 -17
- package/wiki/{get-started/best-practices → best-practices}/common-pitfalls.md +109 -4
- package/wiki/{get-started/best-practices → best-practices}/contribution-workflow.md +34 -7
- package/wiki/best-practices/data-modeling.md +376 -0
- package/wiki/best-practices/deployment-strategies.md +698 -0
- package/wiki/best-practices/index.md +27 -0
- package/wiki/best-practices/performance-optimization.md +196 -0
- package/wiki/best-practices/security-guidelines.md +218 -0
- package/wiki/{get-started/best-practices → best-practices}/troubleshooting-tips.md +97 -1
- package/wiki/changelogs/2025-12-16-initial-architecture.md +1 -1
- package/wiki/changelogs/2025-12-16-model-repo-datasource-refactor.md +1 -1
- package/wiki/changelogs/2025-12-17-refactor.md +1 -1
- package/wiki/changelogs/2025-12-18-performance-optimizations.md +5 -5
- package/wiki/changelogs/2025-12-18-repository-validation-security.md +13 -7
- package/wiki/changelogs/2025-12-26-nested-relations-and-generics.md +2 -2
- package/wiki/changelogs/2025-12-29-dynamic-binding-registration.md +104 -0
- package/wiki/changelogs/2025-12-29-snowflake-uid-helper.md +100 -0
- package/wiki/changelogs/2025-12-30-repository-enhancements.md +214 -0
- package/wiki/changelogs/2025-12-31-json-path-filtering-array-operators.md +214 -0
- package/wiki/changelogs/2025-12-31-string-id-custom-generator.md +137 -0
- package/wiki/changelogs/2026-01-02-default-filter-and-repository-mixins.md +418 -0
- package/wiki/changelogs/index.md +6 -0
- package/wiki/changelogs/planned-schema-migrator.md +0 -8
- package/wiki/{get-started/core-concepts → guides/core-concepts/application}/bootstrapping.md +18 -5
- package/wiki/{get-started/core-concepts/application.md → guides/core-concepts/application/index.md} +47 -104
- package/wiki/guides/core-concepts/components-guide.md +509 -0
- package/wiki/{get-started → guides}/core-concepts/components.md +24 -17
- package/wiki/{get-started → guides}/core-concepts/controllers.md +30 -13
- package/wiki/{get-started → guides}/core-concepts/dependency-injection.md +97 -0
- package/wiki/guides/core-concepts/persistent/datasources.md +179 -0
- package/wiki/guides/core-concepts/persistent/index.md +119 -0
- package/wiki/guides/core-concepts/persistent/models.md +241 -0
- package/wiki/guides/core-concepts/persistent/repositories.md +219 -0
- package/wiki/guides/core-concepts/persistent/transactions.md +170 -0
- package/wiki/{get-started → guides}/core-concepts/services.md +26 -3
- package/wiki/{get-started → guides/get-started}/5-minute-quickstart.md +59 -14
- package/wiki/guides/get-started/philosophy.md +682 -0
- package/wiki/guides/get-started/setup.md +157 -0
- package/wiki/guides/index.md +89 -0
- package/wiki/guides/reference/glossary.md +243 -0
- package/wiki/{get-started → guides/reference}/mcp-docs-server.md +0 -10
- package/wiki/{get-started → guides/tutorials}/building-a-crud-api.md +134 -132
- package/wiki/{get-started/quickstart.md → guides/tutorials/complete-installation.md} +107 -71
- package/wiki/guides/tutorials/ecommerce-api.md +1399 -0
- package/wiki/guides/tutorials/realtime-chat.md +1261 -0
- package/wiki/guides/tutorials/testing.md +723 -0
- package/wiki/index.md +176 -37
- package/wiki/references/base/application.md +27 -0
- package/wiki/references/base/bootstrapping.md +31 -26
- package/wiki/references/base/components.md +24 -7
- package/wiki/references/base/controllers.md +50 -20
- package/wiki/references/base/datasources.md +30 -0
- package/wiki/references/base/dependency-injection.md +39 -3
- package/wiki/references/base/filter-system/application-usage.md +224 -0
- package/wiki/references/base/filter-system/array-operators.md +132 -0
- package/wiki/references/base/filter-system/comparison-operators.md +109 -0
- package/wiki/references/base/filter-system/default-filter.md +428 -0
- package/wiki/references/base/filter-system/fields-order-pagination.md +155 -0
- package/wiki/references/base/filter-system/index.md +127 -0
- package/wiki/references/base/filter-system/json-filtering.md +197 -0
- package/wiki/references/base/filter-system/list-operators.md +71 -0
- package/wiki/references/base/filter-system/logical-operators.md +156 -0
- package/wiki/references/base/filter-system/null-operators.md +58 -0
- package/wiki/references/base/filter-system/pattern-matching.md +108 -0
- package/wiki/references/base/filter-system/quick-reference.md +431 -0
- package/wiki/references/base/filter-system/range-operators.md +63 -0
- package/wiki/references/base/filter-system/tips.md +190 -0
- package/wiki/references/base/filter-system/use-cases.md +452 -0
- package/wiki/references/base/index.md +90 -0
- package/wiki/references/base/middlewares.md +604 -0
- package/wiki/references/base/models.md +215 -23
- package/wiki/references/base/providers.md +731 -0
- package/wiki/references/base/repositories/advanced.md +555 -0
- package/wiki/references/base/repositories/index.md +228 -0
- package/wiki/references/base/repositories/mixins.md +331 -0
- package/wiki/references/base/repositories/relations.md +486 -0
- package/wiki/references/base/repositories.md +40 -635
- package/wiki/references/base/services.md +28 -4
- package/wiki/references/components/authentication.md +22 -2
- package/wiki/references/components/health-check.md +12 -0
- package/wiki/references/components/index.md +23 -0
- package/wiki/references/components/mail.md +687 -0
- package/wiki/references/components/request-tracker.md +16 -0
- package/wiki/references/components/socket-io.md +18 -0
- package/wiki/references/components/static-asset.md +14 -26
- package/wiki/references/components/swagger.md +17 -0
- package/wiki/references/configuration/environment-variables.md +427 -0
- package/wiki/references/configuration/index.md +73 -0
- package/wiki/references/helpers/cron.md +14 -0
- package/wiki/references/helpers/crypto.md +15 -0
- package/wiki/references/helpers/env.md +16 -0
- package/wiki/references/helpers/error.md +17 -0
- package/wiki/references/helpers/index.md +14 -0
- package/wiki/references/helpers/inversion.md +24 -4
- package/wiki/references/helpers/logger.md +19 -0
- package/wiki/references/helpers/network.md +11 -0
- package/wiki/references/helpers/queue.md +19 -0
- package/wiki/references/helpers/redis.md +21 -0
- package/wiki/references/helpers/socket-io.md +24 -5
- package/wiki/references/helpers/storage.md +18 -10
- package/wiki/references/helpers/testing.md +18 -0
- package/wiki/references/helpers/types.md +16 -0
- package/wiki/references/helpers/uid.md +167 -0
- package/wiki/references/helpers/worker-thread.md +16 -0
- package/wiki/references/index.md +177 -0
- package/wiki/references/quick-reference.md +634 -0
- package/wiki/references/src-details/boot.md +3 -3
- package/wiki/references/src-details/dev-configs.md +0 -4
- package/wiki/references/src-details/docs.md +2 -2
- package/wiki/references/src-details/index.md +86 -0
- package/wiki/references/src-details/inversion.md +1 -6
- package/wiki/references/src-details/mcp-server.md +3 -15
- package/wiki/references/utilities/index.md +86 -10
- package/wiki/references/utilities/jsx.md +577 -0
- package/wiki/references/utilities/request.md +0 -2
- package/wiki/references/utilities/statuses.md +740 -0
- package/wiki/get-started/best-practices/api-usage-examples.md +0 -266
- package/wiki/get-started/best-practices/architectural-patterns.md +0 -170
- package/wiki/get-started/best-practices/data-modeling.md +0 -177
- package/wiki/get-started/best-practices/deployment-strategies.md +0 -121
- package/wiki/get-started/best-practices/performance-optimization.md +0 -97
- package/wiki/get-started/best-practices/security-guidelines.md +0 -99
- package/wiki/get-started/core-concepts/persistent.md +0 -539
- package/wiki/get-started/index.md +0 -65
- package/wiki/get-started/philosophy.md +0 -296
- package/wiki/get-started/prerequisites.md +0 -113
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Build a complete, database-backed REST API for managing todos. This guide covers Models, DataSources, Repositories, and Controllers - the core building blocks of Ignis applications.
|
|
4
4
|
|
|
5
|
+
**⏱️ Time to Complete:** ~45 minutes
|
|
6
|
+
|
|
5
7
|
## Prerequisites
|
|
6
8
|
|
|
7
|
-
- ✅ Completed [
|
|
9
|
+
- ✅ Completed [Complete Installation](./complete-installation.md)
|
|
8
10
|
- ✅ PostgreSQL installed and running
|
|
9
|
-
- ✅ Database created (see [Prerequisites](
|
|
11
|
+
- ✅ Database created (see [Prerequisites](../get-started/setup.md))
|
|
10
12
|
|
|
11
13
|
## What You'll Build
|
|
12
14
|
|
|
@@ -28,63 +30,47 @@ Build a complete, database-backed REST API for managing todos. This guide covers
|
|
|
28
30
|
Here's how a request flows through your application:
|
|
29
31
|
|
|
30
32
|
```
|
|
31
|
-
|
|
32
|
-
│
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
│ │
|
|
56
|
-
│ Drizzle ORM │
|
|
57
|
-
└─────────┬────────┘
|
|
58
|
-
│
|
|
59
|
-
│ executes SQL query
|
|
60
|
-
▼
|
|
61
|
-
┌──────────────────┐
|
|
62
|
-
│ PostgreSQL │ ← Actual database
|
|
63
|
-
│ │
|
|
64
|
-
│ Todo table │
|
|
65
|
-
└─────────┬────────┘
|
|
66
|
-
│
|
|
67
|
-
│ returns data
|
|
68
|
-
▼
|
|
69
|
-
┌──────────────────┐
|
|
70
|
-
│ JSON Response │
|
|
71
|
-
│ │
|
|
72
|
-
│ { id, title,..} │
|
|
73
|
-
└──────────────────┘
|
|
33
|
+
HTTP Request (GET /api/todos/:id)
|
|
34
|
+
│
|
|
35
|
+
▼
|
|
36
|
+
┌─────────────────┐
|
|
37
|
+
│ TodoController │ ← Handles HTTP, validates input
|
|
38
|
+
└────────┬────────┘
|
|
39
|
+
│ calls repository.findById()
|
|
40
|
+
▼
|
|
41
|
+
┌─────────────────┐
|
|
42
|
+
│ TodoRepository │ ← Type-safe data access
|
|
43
|
+
└────────┬────────┘
|
|
44
|
+
│ uses dataSource.connector
|
|
45
|
+
▼
|
|
46
|
+
┌─────────────────┐
|
|
47
|
+
│PostgresDataSource│ ← Database connection (Drizzle ORM)
|
|
48
|
+
└────────┬────────┘
|
|
49
|
+
│ executes SQL query
|
|
50
|
+
▼
|
|
51
|
+
┌─────────────────┐
|
|
52
|
+
│ PostgreSQL │ ← Actual database
|
|
53
|
+
└────────┬────────┘
|
|
54
|
+
│ returns data
|
|
55
|
+
▼
|
|
56
|
+
JSON Response
|
|
74
57
|
```
|
|
75
58
|
|
|
76
59
|
**Key Points:**
|
|
77
|
-
1. **Controller** - Entry point for HTTP requests
|
|
78
|
-
2. **Repository** - Abstracts database operations (you could swap PostgreSQL for MySQL without changing controller)
|
|
79
|
-
3. **DataSource** - Manages connection to database
|
|
80
|
-
4. **Model** - Defines what the data looks like
|
|
81
60
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
61
|
+
| Layer | Responsibility |
|
|
62
|
+
|-------|----------------|
|
|
63
|
+
| **Controller** | Entry point for HTTP requests |
|
|
64
|
+
| **Repository** | Abstracts database operations (swap PostgreSQL for MySQL without changing controller) |
|
|
65
|
+
| **DataSource** | Manages connection to database |
|
|
66
|
+
| **Model** | Defines what the data looks like |
|
|
67
|
+
|
|
68
|
+
**Benefits of this separation:**
|
|
69
|
+
- **Testable** — Mock repository in tests
|
|
70
|
+
- **Maintainable** — Clear responsibility for each layer
|
|
71
|
+
- **Flexible** — Change database without touching business logic
|
|
86
72
|
|
|
87
|
-
## Step
|
|
73
|
+
## Step 1: Install Database Dependencies
|
|
88
74
|
|
|
89
75
|
```bash
|
|
90
76
|
# Add database packages
|
|
@@ -94,7 +80,7 @@ bun add drizzle-orm drizzle-zod pg lodash
|
|
|
94
80
|
bun add -d drizzle-kit @types/pg @types/lodash
|
|
95
81
|
```
|
|
96
82
|
|
|
97
|
-
## Step
|
|
83
|
+
## Step 2: Define the Model
|
|
98
84
|
|
|
99
85
|
Models combine Drizzle ORM schemas with Entity classes to define your data structure.
|
|
100
86
|
|
|
@@ -142,36 +128,28 @@ export class Todo extends BaseEntity<typeof Todo.schema> {
|
|
|
142
128
|
```
|
|
143
129
|
|
|
144
130
|
**Schema Enrichers:**
|
|
145
|
-
- `generateIdColumnDefs()` - Adds `id` column (UUID
|
|
131
|
+
- `generateIdColumnDefs()` - Adds `id` column (text with UUID default, or auto-incrementing number)
|
|
146
132
|
- `generateTzColumnDefs()` - Adds `createdAt` and `modifiedAt` timestamps
|
|
147
133
|
|
|
148
|
-
> **Deep Dive:** See [Models & Enrichers Reference](
|
|
134
|
+
> **Deep Dive:** See [Models & Enrichers Reference](/references/base/models#schema-enrichers) for all available enrichers and options.
|
|
149
135
|
|
|
150
|
-
## Step
|
|
136
|
+
## Step 3: Configure Database Connection
|
|
151
137
|
|
|
152
138
|
### Understanding Environment Variables
|
|
153
139
|
|
|
154
|
-
|
|
140
|
+
Environment variables store configuration outside code (in `.env` files). Benefits: security (no passwords in Git), flexibility (different values per environment).
|
|
155
141
|
|
|
156
|
-
**What are they?**
|
|
157
|
-
Environment variables are configuration values stored outside your code. Think of them as settings that can change without modifying your source code.
|
|
158
|
-
|
|
159
|
-
**Why use them?**
|
|
160
142
|
```typescript
|
|
161
143
|
// ❌ BAD: Hardcoded values
|
|
162
|
-
const password = "secret123"; //
|
|
144
|
+
const password = "secret123"; // In Git history forever!
|
|
163
145
|
|
|
164
|
-
// ✅ GOOD: Environment variable
|
|
165
|
-
const password = process.env.
|
|
146
|
+
// ✅ GOOD: Environment variable with APP_ENV_ prefix
|
|
147
|
+
const password = process.env.APP_ENV_DB_PASSWORD;
|
|
148
|
+
// or
|
|
149
|
+
const password = Bun.env.APP_ENV_DB_PASSWORD;
|
|
166
150
|
```
|
|
167
151
|
|
|
168
|
-
|
|
169
|
-
1. **Security** - Never commit passwords to Git
|
|
170
|
-
2. **Flexibility** - Different values for dev/staging/production
|
|
171
|
-
3. **Team Collaboration** - Each developer has their own `.env` file
|
|
172
|
-
|
|
173
|
-
**The `APP_ENV_` prefix:**
|
|
174
|
-
Ignis uses `APP_ENV_` prefix for all its environment variables. This prevents conflicts with system variables (like `PATH`, `HOME`, etc.).
|
|
152
|
+
Ignis uses `APP_ENV_` prefix to prevent conflicts with system variables.
|
|
175
153
|
|
|
176
154
|
### Create `.env` File
|
|
177
155
|
|
|
@@ -188,7 +166,7 @@ APP_ENV_POSTGRES_DATABASE=todo_db
|
|
|
188
166
|
|
|
189
167
|
**Replace these values:**
|
|
190
168
|
- `your_password_here` - Your PostgreSQL password (or leave blank if no password)
|
|
191
|
-
- `todo_db` - The database you created in [Prerequisites](
|
|
169
|
+
- `todo_db` - The database you created in [Prerequisites](../get-started/setup.md#database-setup)
|
|
192
170
|
|
|
193
171
|
**Important:** Add `.env` to your `.gitignore`:
|
|
194
172
|
```bash
|
|
@@ -267,9 +245,17 @@ export class PostgresDataSource extends BaseDataSource<TNodePostgresConnector, I
|
|
|
267
245
|
- Uses environment variables for connection config
|
|
268
246
|
- Implements connection lifecycle methods (`connect()`, `disconnect()`)
|
|
269
247
|
|
|
270
|
-
> **Deep Dive:** See [DataSources Reference](
|
|
248
|
+
> **Deep Dive:** See [DataSources Reference](/references/base/datasources) for advanced configuration and multiple database support.
|
|
249
|
+
|
|
250
|
+
## Step 4: Create the Repository
|
|
251
|
+
|
|
252
|
+
:::info What are Generic Types?
|
|
253
|
+
Generic types in TypeScript are like placeholders that let you write reusable code that works with different types. The `<T>` syntax means "this class/function works with type T, which you'll specify later."
|
|
271
254
|
|
|
272
|
-
|
|
255
|
+
Example: `DefaultCRUDRepository<typeof Todo.schema>` means "a repository that works specifically with the Todo schema type." This gives you type safety and autocomplete for your model's properties.
|
|
256
|
+
|
|
257
|
+
[Learn more →](/guides/reference/glossary#generic-types)
|
|
258
|
+
:::
|
|
273
259
|
|
|
274
260
|
Repositories provide type-safe CRUD operations using `DefaultCRUDRepository`.
|
|
275
261
|
|
|
@@ -290,11 +276,33 @@ export class TodoRepository extends DefaultCRUDRepository<typeof Todo.schema> {
|
|
|
290
276
|
```
|
|
291
277
|
|
|
292
278
|
**Available Methods:**
|
|
293
|
-
`create()`, `find()`, `findOne()`, `findById()`, `updateById()`, `updateAll()`, `deleteById()`, `deleteAll()`, `count()`
|
|
294
279
|
|
|
295
|
-
|
|
280
|
+
| Method | Description |
|
|
281
|
+
|--------|-------------|
|
|
282
|
+
| `create()` | Insert new record(s) |
|
|
283
|
+
| `find()` | Query multiple records with filters |
|
|
284
|
+
| `findOne()` | Get single record by filter |
|
|
285
|
+
| `findById()` | Get record by ID |
|
|
286
|
+
| `updateById()` | Update record by ID |
|
|
287
|
+
| `updateAll()` | Update multiple records |
|
|
288
|
+
| `deleteById()` | Delete record by ID |
|
|
289
|
+
| `deleteAll()` | Delete multiple records |
|
|
290
|
+
| `count()` | Count matching records |
|
|
291
|
+
|
|
292
|
+
> **Deep Dive:** See [Repositories Reference](/references/base/repositories) for query options and advanced filtering.
|
|
293
|
+
|
|
294
|
+
## Step 5: Create the Controller
|
|
295
|
+
|
|
296
|
+
:::info What is Dependency Injection?
|
|
297
|
+
Dependency Injection (DI) is a design pattern where objects receive their dependencies from outside rather than creating them internally. Instead of `new Repository()` inside a controller, you declare "I need a Repository" using `@inject`, and the framework provides it automatically.
|
|
298
|
+
|
|
299
|
+
**Benefits:**
|
|
300
|
+
- **Testable** — Replace real services with mocks in tests
|
|
301
|
+
- **Flexible** — Swap implementations without changing code
|
|
302
|
+
- **Maintainable** — Dependencies are explicit and centralized
|
|
296
303
|
|
|
297
|
-
|
|
304
|
+
[Learn more →](/guides/core-concepts/dependency-injection)
|
|
305
|
+
:::
|
|
298
306
|
|
|
299
307
|
`ControllerFactory` generates a full CRUD controller with automatic validation and OpenAPI docs.
|
|
300
308
|
|
|
@@ -354,15 +362,15 @@ export class TodoController extends _Controller {
|
|
|
354
362
|
| DELETE | `/todos/:id` | Delete todo by ID (deleteById) |
|
|
355
363
|
| DELETE | `/todos` | Delete multiple todos by filter (deleteBy) |
|
|
356
364
|
|
|
357
|
-
> **Deep Dive:** See [ControllerFactory Reference](
|
|
365
|
+
> **Deep Dive:** See [ControllerFactory Reference](/references/base/controllers#controllerfactory) for customization options.
|
|
358
366
|
|
|
359
|
-
## Step
|
|
367
|
+
## Step 6: Register Components
|
|
360
368
|
|
|
361
369
|
Update `src/application.ts` to register all components:
|
|
362
370
|
|
|
363
371
|
```typescript
|
|
364
372
|
// src/application.ts
|
|
365
|
-
import { BaseApplication, IApplicationConfigs, IApplicationInfo, ValueOrPromise } from '@venizia/ignis';
|
|
373
|
+
import { BaseApplication, IApplicationConfigs, IApplicationInfo, SwaggerComponent, ValueOrPromise } from '@venizia/ignis';
|
|
366
374
|
import { HelloController } from './controllers/hello.controller';
|
|
367
375
|
import packageJson from '../package.json';
|
|
368
376
|
|
|
@@ -387,13 +395,16 @@ export class Application extends BaseApplication {
|
|
|
387
395
|
setupMiddlewares(): ValueOrPromise<void> {}
|
|
388
396
|
|
|
389
397
|
preConfigure(): ValueOrPromise<void> {
|
|
390
|
-
// 1. Register
|
|
398
|
+
// 1. Register SwaggerComponent for API docs
|
|
399
|
+
this.component(SwaggerComponent);
|
|
400
|
+
|
|
401
|
+
// 2. Register datasource
|
|
391
402
|
this.dataSource(PostgresDataSource);
|
|
392
403
|
|
|
393
|
-
//
|
|
404
|
+
// 3. Register repository
|
|
394
405
|
this.repository(TodoRepository);
|
|
395
406
|
|
|
396
|
-
//
|
|
407
|
+
// 4. Register controllers
|
|
397
408
|
this.controller(HelloController);
|
|
398
409
|
this.controller(TodoController);
|
|
399
410
|
}
|
|
@@ -402,28 +413,16 @@ export class Application extends BaseApplication {
|
|
|
402
413
|
}
|
|
403
414
|
```
|
|
404
415
|
|
|
405
|
-
## Step
|
|
416
|
+
## Step 7: Run Database Migration
|
|
406
417
|
|
|
407
418
|
### Understanding Database Migrations
|
|
408
419
|
|
|
409
|
-
|
|
410
|
-
Your database is currently empty. It has no `Todo` table. But your code expects one!
|
|
411
|
-
|
|
412
|
-
```typescript
|
|
413
|
-
// Your code says:
|
|
414
|
-
todoTable = pgTable('Todo', { id: ..., title: ..., ... });
|
|
420
|
+
Your code defines a `Todo` table, but PostgreSQL doesn't have it yet. A migration creates/modifies database tables - like "Git commits for your schema."
|
|
415
421
|
|
|
416
|
-
// But PostgreSQL doesn't have a 'Todo' table yet!
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
**What is a Migration?**
|
|
420
|
-
A migration is a script that creates or modifies database tables. Think of it as "Git commits for your database schema."
|
|
421
|
-
|
|
422
|
-
**Example Migration:**
|
|
423
422
|
```sql
|
|
424
|
-
--
|
|
423
|
+
-- Drizzle generates and runs this for you:
|
|
425
424
|
CREATE TABLE "Todo" (
|
|
426
|
-
"id"
|
|
425
|
+
"id" TEXT PRIMARY KEY,
|
|
427
426
|
"title" TEXT NOT NULL,
|
|
428
427
|
"description" TEXT,
|
|
429
428
|
"is_completed" BOOLEAN DEFAULT false,
|
|
@@ -432,10 +431,7 @@ CREATE TABLE "Todo" (
|
|
|
432
431
|
);
|
|
433
432
|
```
|
|
434
433
|
|
|
435
|
-
|
|
436
|
-
- **Team Collaboration** - Everyone runs the same migrations, databases stay in sync
|
|
437
|
-
- **Version Control** - Schema changes are tracked in Git
|
|
438
|
-
- **Rollback** - Can undo changes if something breaks
|
|
434
|
+
Benefits: team sync, version control, rollback capability.
|
|
439
435
|
|
|
440
436
|
### Create Migration Config
|
|
441
437
|
|
|
@@ -460,9 +456,18 @@ export default defineConfig({
|
|
|
460
456
|
});
|
|
461
457
|
```
|
|
462
458
|
|
|
463
|
-
###
|
|
459
|
+
### Add Migration Scripts
|
|
464
460
|
|
|
465
|
-
|
|
461
|
+
Add these scripts to your `package.json`:
|
|
462
|
+
|
|
463
|
+
```json
|
|
464
|
+
"scripts": {
|
|
465
|
+
"migrate:dev": "NODE_ENV=development drizzle-kit migrate --config=src/migration.ts",
|
|
466
|
+
"generate-migration:dev": "NODE_ENV=development drizzle-kit generate --config=src/migration.ts"
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Run the Migration
|
|
466
471
|
|
|
467
472
|
```bash
|
|
468
473
|
bun run migrate:dev
|
|
@@ -491,7 +496,7 @@ psql -U postgres -d todo_db -c "\d Todo"
|
|
|
491
496
|
|
|
492
497
|
You should see the `Todo` table structure with all your columns!
|
|
493
498
|
|
|
494
|
-
## Step
|
|
499
|
+
## Step 8: Run and Test
|
|
495
500
|
|
|
496
501
|
Start your application:
|
|
497
502
|
|
|
@@ -523,7 +528,7 @@ curl -X DELETE http://localhost:3000/api/todos/{id}
|
|
|
523
528
|
```
|
|
524
529
|
|
|
525
530
|
**View API Documentation:**
|
|
526
|
-
Open `http://localhost:3000/
|
|
531
|
+
Open `http://localhost:3000/doc/explorer` to see interactive Swagger UI.
|
|
527
532
|
|
|
528
533
|
🎉 **Congratulations!** You've built a complete CRUD API with:
|
|
529
534
|
- ✅ Type-safe database operations
|
|
@@ -545,7 +550,6 @@ this.dataSource(PostgresDataSource); // ← Make sure this is here!
|
|
|
545
550
|
|
|
546
551
|
**Order matters:** DataSource must be registered before Repository.
|
|
547
552
|
|
|
548
|
-
---
|
|
549
553
|
|
|
550
554
|
### Error: "connection refused" or "ECONNREFUSED"
|
|
551
555
|
|
|
@@ -563,7 +567,6 @@ sudo service postgresql start # Linux
|
|
|
563
567
|
|
|
564
568
|
**Verify `.env` values match your PostgreSQL setup.**
|
|
565
569
|
|
|
566
|
-
---
|
|
567
570
|
|
|
568
571
|
### Error: "relation 'Todo' does not exist"
|
|
569
572
|
|
|
@@ -581,7 +584,6 @@ psql -U postgres -d todo_db -c "\dt"
|
|
|
581
584
|
|
|
582
585
|
You should see `Todo` in the list.
|
|
583
586
|
|
|
584
|
-
---
|
|
585
587
|
|
|
586
588
|
### Error: 404 Not Found on `/api/todos`
|
|
587
589
|
|
|
@@ -598,7 +600,6 @@ path: { base: '/api', isStrict: true }, // All routes start with /api
|
|
|
598
600
|
|
|
599
601
|
**Debug:** Set `debug.showRoutes: true` in appConfigs to see all registered routes on startup.
|
|
600
602
|
|
|
601
|
-
---
|
|
602
603
|
|
|
603
604
|
### Error: "Invalid JSON" when creating todo
|
|
604
605
|
|
|
@@ -612,7 +613,6 @@ curl -X POST http://localhost:3000/api/todos \
|
|
|
612
613
|
-d '{"title":"Learn Ignis"}'
|
|
613
614
|
```
|
|
614
615
|
|
|
615
|
-
---
|
|
616
616
|
|
|
617
617
|
## Test Your Understanding: Build a Second Feature
|
|
618
618
|
|
|
@@ -624,18 +624,20 @@ Now that you've built the Todo API, try building a **User** feature on your own!
|
|
|
624
624
|
- Use `ControllerFactory` for CRUD operations
|
|
625
625
|
|
|
626
626
|
**Challenge checklist:**
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
627
|
+
|
|
628
|
+
| Step | Task |
|
|
629
|
+
|:----:|------|
|
|
630
|
+
| 1 | Create `src/models/user.model.ts` |
|
|
631
|
+
| 2 | Create `src/repositories/user.repository.ts` (auto-registers User with PostgresDataSource) |
|
|
632
|
+
| 3 | Create `src/controllers/user.controller.ts` |
|
|
633
|
+
| 4 | Register repository and controller in `application.ts` |
|
|
634
|
+
| 5 | Run migration: `bun run migrate:dev` |
|
|
635
|
+
| 6 | Test with curl |
|
|
633
636
|
|
|
634
637
|
**Hint:** Follow the exact same pattern as `Todo`. The only changes are the model name and fields!
|
|
635
638
|
|
|
636
|
-
**Solution:** If you get stuck, check the [API Usage Examples](
|
|
639
|
+
**Solution:** If you get stuck, check the [API Usage Examples](/best-practices/api-usage-examples.md) guide.
|
|
637
640
|
|
|
638
|
-
---
|
|
639
641
|
|
|
640
642
|
## Next Steps
|
|
641
643
|
|
|
@@ -680,23 +682,23 @@ Register in `application.ts`:
|
|
|
680
682
|
this.service(TodoService);
|
|
681
683
|
```
|
|
682
684
|
|
|
683
|
-
> **Deep Dive:** See [Services Reference](
|
|
685
|
+
> **Deep Dive:** See [Services Reference](../core-concepts/services.md) for best practices and advanced patterns.
|
|
684
686
|
|
|
685
687
|
## Continue Your Journey
|
|
686
688
|
|
|
687
689
|
You now have a fully functional CRUD API! Here's what to explore next:
|
|
688
690
|
|
|
689
691
|
**Core Concepts:**
|
|
690
|
-
1. [Application Architecture](
|
|
691
|
-
2. [Dependency Injection](
|
|
692
|
-
3. [Components](
|
|
692
|
+
1. [Application Architecture](../core-concepts/application/) - Understand the framework structure
|
|
693
|
+
2. [Dependency Injection](../core-concepts/dependency-injection.md) - Master DI patterns
|
|
694
|
+
3. [Components](../core-concepts/components.md) - Build reusable modules
|
|
693
695
|
|
|
694
696
|
**Add Features:**
|
|
695
|
-
1. [Authentication](
|
|
696
|
-
2. [Custom Routes](
|
|
697
|
-
3. [Relationships](
|
|
697
|
+
1. [Authentication](/references/components/authentication) - Add JWT authentication
|
|
698
|
+
2. [Custom Routes](/best-practices/api-usage-examples.md) - Beyond CRUD operations
|
|
699
|
+
3. [Relationships](../core-concepts/persistent/) - Link todos to users
|
|
698
700
|
|
|
699
701
|
**Production:**
|
|
700
|
-
1. [Deployment Strategies](
|
|
701
|
-
2. [Performance Optimization](
|
|
702
|
-
3. [Security Guidelines](
|
|
702
|
+
1. [Deployment Strategies](/best-practices/deployment-strategies.md) - Deploy your API
|
|
703
|
+
2. [Performance Optimization](/best-practices/performance-optimization.md) - Make it faster
|
|
704
|
+
3. [Security Guidelines](/best-practices/security-guidelines.md) - Secure your API
|