@venizia/ignis-docs 0.0.3 → 0.0.4-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 (131) hide show
  1. package/README.md +1 -1
  2. package/package.json +4 -2
  3. package/wiki/best-practices/api-usage-examples.md +591 -0
  4. package/wiki/best-practices/architectural-patterns.md +415 -0
  5. package/wiki/best-practices/architecture-decisions.md +488 -0
  6. package/wiki/{get-started/best-practices → best-practices}/code-style-standards.md +406 -17
  7. package/wiki/{get-started/best-practices → best-practices}/common-pitfalls.md +109 -4
  8. package/wiki/{get-started/best-practices → best-practices}/contribution-workflow.md +34 -7
  9. package/wiki/best-practices/data-modeling.md +376 -0
  10. package/wiki/best-practices/deployment-strategies.md +698 -0
  11. package/wiki/best-practices/index.md +27 -0
  12. package/wiki/best-practices/performance-optimization.md +196 -0
  13. package/wiki/best-practices/security-guidelines.md +218 -0
  14. package/wiki/{get-started/best-practices → best-practices}/troubleshooting-tips.md +97 -1
  15. package/wiki/changelogs/2025-12-16-initial-architecture.md +1 -1
  16. package/wiki/changelogs/2025-12-16-model-repo-datasource-refactor.md +1 -1
  17. package/wiki/changelogs/2025-12-17-refactor.md +1 -1
  18. package/wiki/changelogs/2025-12-18-performance-optimizations.md +5 -5
  19. package/wiki/changelogs/2025-12-18-repository-validation-security.md +13 -7
  20. package/wiki/changelogs/2025-12-26-nested-relations-and-generics.md +2 -2
  21. package/wiki/changelogs/2025-12-29-dynamic-binding-registration.md +104 -0
  22. package/wiki/changelogs/2025-12-29-snowflake-uid-helper.md +100 -0
  23. package/wiki/changelogs/2025-12-30-repository-enhancements.md +214 -0
  24. package/wiki/changelogs/2025-12-31-json-path-filtering-array-operators.md +214 -0
  25. package/wiki/changelogs/2025-12-31-string-id-custom-generator.md +137 -0
  26. package/wiki/changelogs/2026-01-02-default-filter-and-repository-mixins.md +418 -0
  27. package/wiki/changelogs/index.md +6 -0
  28. package/wiki/changelogs/planned-schema-migrator.md +0 -8
  29. package/wiki/{get-started/core-concepts → guides/core-concepts/application}/bootstrapping.md +18 -5
  30. package/wiki/{get-started/core-concepts/application.md → guides/core-concepts/application/index.md} +47 -104
  31. package/wiki/guides/core-concepts/components-guide.md +509 -0
  32. package/wiki/{get-started → guides}/core-concepts/components.md +24 -17
  33. package/wiki/{get-started → guides}/core-concepts/controllers.md +30 -13
  34. package/wiki/{get-started → guides}/core-concepts/dependency-injection.md +97 -0
  35. package/wiki/guides/core-concepts/persistent/datasources.md +179 -0
  36. package/wiki/guides/core-concepts/persistent/index.md +119 -0
  37. package/wiki/guides/core-concepts/persistent/models.md +241 -0
  38. package/wiki/guides/core-concepts/persistent/repositories.md +219 -0
  39. package/wiki/guides/core-concepts/persistent/transactions.md +170 -0
  40. package/wiki/{get-started → guides}/core-concepts/services.md +26 -3
  41. package/wiki/{get-started → guides/get-started}/5-minute-quickstart.md +59 -14
  42. package/wiki/guides/get-started/philosophy.md +682 -0
  43. package/wiki/guides/get-started/setup.md +157 -0
  44. package/wiki/guides/index.md +89 -0
  45. package/wiki/guides/reference/glossary.md +243 -0
  46. package/wiki/{get-started → guides/reference}/mcp-docs-server.md +0 -10
  47. package/wiki/{get-started → guides/tutorials}/building-a-crud-api.md +134 -132
  48. package/wiki/{get-started/quickstart.md → guides/tutorials/complete-installation.md} +107 -71
  49. package/wiki/guides/tutorials/ecommerce-api.md +1399 -0
  50. package/wiki/guides/tutorials/realtime-chat.md +1261 -0
  51. package/wiki/guides/tutorials/testing.md +723 -0
  52. package/wiki/index.md +176 -37
  53. package/wiki/references/base/application.md +27 -0
  54. package/wiki/references/base/bootstrapping.md +30 -26
  55. package/wiki/references/base/components.md +24 -7
  56. package/wiki/references/base/controllers.md +51 -20
  57. package/wiki/references/base/datasources.md +30 -0
  58. package/wiki/references/base/dependency-injection.md +39 -3
  59. package/wiki/references/base/filter-system/application-usage.md +224 -0
  60. package/wiki/references/base/filter-system/array-operators.md +132 -0
  61. package/wiki/references/base/filter-system/comparison-operators.md +109 -0
  62. package/wiki/references/base/filter-system/default-filter.md +428 -0
  63. package/wiki/references/base/filter-system/fields-order-pagination.md +155 -0
  64. package/wiki/references/base/filter-system/index.md +127 -0
  65. package/wiki/references/base/filter-system/json-filtering.md +197 -0
  66. package/wiki/references/base/filter-system/list-operators.md +71 -0
  67. package/wiki/references/base/filter-system/logical-operators.md +156 -0
  68. package/wiki/references/base/filter-system/null-operators.md +58 -0
  69. package/wiki/references/base/filter-system/pattern-matching.md +108 -0
  70. package/wiki/references/base/filter-system/quick-reference.md +431 -0
  71. package/wiki/references/base/filter-system/range-operators.md +63 -0
  72. package/wiki/references/base/filter-system/tips.md +190 -0
  73. package/wiki/references/base/filter-system/use-cases.md +452 -0
  74. package/wiki/references/base/index.md +90 -0
  75. package/wiki/references/base/middlewares.md +602 -0
  76. package/wiki/references/base/models.md +215 -23
  77. package/wiki/references/base/providers.md +732 -0
  78. package/wiki/references/base/repositories/advanced.md +555 -0
  79. package/wiki/references/base/repositories/index.md +228 -0
  80. package/wiki/references/base/repositories/mixins.md +331 -0
  81. package/wiki/references/base/repositories/relations.md +486 -0
  82. package/wiki/references/base/repositories.md +40 -635
  83. package/wiki/references/base/services.md +28 -4
  84. package/wiki/references/components/authentication.md +22 -2
  85. package/wiki/references/components/health-check.md +12 -0
  86. package/wiki/references/components/index.md +23 -0
  87. package/wiki/references/components/mail.md +687 -0
  88. package/wiki/references/components/request-tracker.md +16 -0
  89. package/wiki/references/components/socket-io.md +18 -0
  90. package/wiki/references/components/static-asset.md +14 -26
  91. package/wiki/references/components/swagger.md +17 -0
  92. package/wiki/references/configuration/environment-variables.md +427 -0
  93. package/wiki/references/configuration/index.md +73 -0
  94. package/wiki/references/helpers/cron.md +14 -0
  95. package/wiki/references/helpers/crypto.md +15 -0
  96. package/wiki/references/helpers/env.md +16 -0
  97. package/wiki/references/helpers/error.md +17 -0
  98. package/wiki/references/helpers/index.md +14 -0
  99. package/wiki/references/helpers/inversion.md +24 -4
  100. package/wiki/references/helpers/logger.md +19 -0
  101. package/wiki/references/helpers/network.md +11 -0
  102. package/wiki/references/helpers/queue.md +19 -0
  103. package/wiki/references/helpers/redis.md +21 -0
  104. package/wiki/references/helpers/socket-io.md +24 -5
  105. package/wiki/references/helpers/storage.md +18 -10
  106. package/wiki/references/helpers/testing.md +18 -0
  107. package/wiki/references/helpers/types.md +16 -0
  108. package/wiki/references/helpers/uid.md +167 -0
  109. package/wiki/references/helpers/worker-thread.md +16 -0
  110. package/wiki/references/index.md +177 -0
  111. package/wiki/references/quick-reference.md +634 -0
  112. package/wiki/references/src-details/boot.md +3 -3
  113. package/wiki/references/src-details/dev-configs.md +0 -4
  114. package/wiki/references/src-details/docs.md +2 -2
  115. package/wiki/references/src-details/index.md +86 -0
  116. package/wiki/references/src-details/inversion.md +1 -6
  117. package/wiki/references/src-details/mcp-server.md +3 -15
  118. package/wiki/references/utilities/index.md +86 -10
  119. package/wiki/references/utilities/jsx.md +577 -0
  120. package/wiki/references/utilities/request.md +0 -2
  121. package/wiki/references/utilities/statuses.md +740 -0
  122. package/wiki/get-started/best-practices/api-usage-examples.md +0 -266
  123. package/wiki/get-started/best-practices/architectural-patterns.md +0 -170
  124. package/wiki/get-started/best-practices/data-modeling.md +0 -177
  125. package/wiki/get-started/best-practices/deployment-strategies.md +0 -121
  126. package/wiki/get-started/best-practices/performance-optimization.md +0 -97
  127. package/wiki/get-started/best-practices/security-guidelines.md +0 -99
  128. package/wiki/get-started/core-concepts/persistent.md +0 -539
  129. package/wiki/get-started/index.md +0 -65
  130. package/wiki/get-started/philosophy.md +0 -296
  131. package/wiki/get-started/prerequisites.md +0 -113
@@ -1,539 +0,0 @@
1
- ---
2
- title: Persistent Layer
3
- description: Models, DataSources, and Repositories in Ignis
4
- ---
5
-
6
- # Persistent Layer: Models, DataSources, and Repositories
7
-
8
- The persistent layer manages data using [Drizzle ORM](https://orm.drizzle.team/) for type-safe database access and the Repository pattern for data abstraction.
9
-
10
- **Three main components:**
11
-
12
- - **Models** - Define data structure (static schema + relations on Entity class)
13
- - **DataSources** - Manage database connections with auto-discovery
14
- - **Repositories** - Provide CRUD operations with zero boilerplate
15
-
16
- ## 1. Models: Defining Your Data Structure
17
-
18
- A model in Ignis is a single class with static properties for schema and relations. No separate variables needed.
19
-
20
- ### Creating a Basic Model
21
-
22
- ```typescript
23
- // src/models/entities/user.model.ts
24
- import { BaseEntity, extraUserColumns, generateIdColumnDefs, model } from '@venizia/ignis';
25
- import { pgTable } from 'drizzle-orm/pg-core';
26
-
27
- @model({ type: 'entity' })
28
- export class User extends BaseEntity<typeof User.schema> {
29
- // Define schema as static property
30
- static override schema = pgTable('User', {
31
- ...generateIdColumnDefs({ id: { dataType: 'string' } }),
32
- ...extraUserColumns({ idType: 'string' }),
33
- });
34
-
35
- // Relations (empty array if none)
36
- static override relations = () => [];
37
- }
38
- ```
39
-
40
- **Key points:**
41
-
42
- - Schema is defined inline as `static override schema`
43
- - Relations are defined as `static override relations`
44
- - No constructor needed - BaseEntity auto-discovers from static properties
45
- - Type parameter uses `typeof User.schema` (self-referencing)
46
-
47
- ### Creating a Model with Relations
48
-
49
- ```typescript
50
- // src/models/entities/configuration.model.ts
51
- import {
52
- BaseEntity,
53
- generateDataTypeColumnDefs,
54
- generateIdColumnDefs,
55
- generateTzColumnDefs,
56
- generateUserAuditColumnDefs,
57
- model,
58
- RelationTypes,
59
- TRelationConfig,
60
- } from '@venizia/ignis';
61
- import { foreignKey, index, pgTable, text, unique } from 'drizzle-orm/pg-core';
62
- import { User } from './user.model';
63
-
64
- @model({ type: 'entity' })
65
- export class Configuration extends BaseEntity<typeof Configuration.schema> {
66
- static override schema = pgTable(
67
- 'Configuration',
68
- {
69
- ...generateIdColumnDefs({ id: { dataType: 'string' } }),
70
- ...generateTzColumnDefs(),
71
- ...generateDataTypeColumnDefs(),
72
- ...generateUserAuditColumnDefs({
73
- created: { dataType: 'string', columnName: 'created_by' },
74
- modified: { dataType: 'string', columnName: 'modified_by' },
75
- }),
76
- code: text('code').notNull(),
77
- description: text('description'),
78
- group: text('group').notNull(),
79
- },
80
- def => [
81
- unique('UQ_Configuration_code').on(def.code),
82
- index('IDX_Configuration_group').on(def.group),
83
- foreignKey({
84
- columns: [def.createdBy],
85
- foreignColumns: [User.schema.id], // Reference User.schema, not a separate variable
86
- name: 'FK_Configuration_createdBy_User_id',
87
- }),
88
- ],
89
- );
90
-
91
- // Define relations using TRelationConfig array
92
- static override relations = (): TRelationConfig[] => [
93
- {
94
- name: 'creator',
95
- type: RelationTypes.ONE,
96
- schema: User.schema,
97
- metadata: {
98
- fields: [Configuration.schema.createdBy],
99
- references: [User.schema.id],
100
- },
101
- },
102
- {
103
- name: 'modifier',
104
- type: RelationTypes.ONE,
105
- schema: User.schema,
106
- metadata: {
107
- fields: [Configuration.schema.modifiedBy],
108
- references: [User.schema.id],
109
- },
110
- },
111
- ];
112
- }
113
- ```
114
-
115
- **Key points:**
116
-
117
- - Relations use `TRelationConfig[]` format directly
118
- - Reference other models via `Model.schema` (e.g., `User.schema.id`)
119
- - Relation names (`creator`, `modifier`) are used in queries with `include`
120
-
121
- ### Understanding Enrichers
122
-
123
- Enrichers are helper functions that generate common database columns automatically.
124
-
125
- **Without enrichers:**
126
-
127
- ```typescript
128
- static override schema = pgTable('User', {
129
- id: uuid('id').defaultRandom().primaryKey(),
130
- status: text('status').notNull().default('ACTIVE'),
131
- createdBy: text('created_by'),
132
- modifiedBy: text('modified_by'),
133
- createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
134
- modifiedAt: timestamp('modified_at', { withTimezone: true }).notNull().defaultNow(),
135
- // ... your fields
136
- });
137
- ```
138
-
139
- **With enrichers:**
140
-
141
- ```typescript
142
- static override schema = pgTable('User', {
143
- ...generateIdColumnDefs({ id: { dataType: 'string' } }), // id (UUID)
144
- ...extraUserColumns({ idType: 'string' }), // status, audit fields, timestamps
145
- // ... your fields
146
- });
147
- ```
148
-
149
- #### Available Enrichers
150
-
151
- | Enricher | Columns Added | Use Case |
152
- |----------|---------------|----------|
153
- | `generateIdColumnDefs()` | `id` (UUID or number) | Every table |
154
- | `generateTzColumnDefs()` | `createdAt`, `modifiedAt` | Track timestamps |
155
- | `generateUserAuditColumnDefs()` | `createdBy`, `modifiedBy` | Track who created/updated |
156
- | `generateDataTypeColumnDefs()` | `dataType`, `tValue`, `nValue`, etc. | Configuration tables |
157
- | `extraUserColumns()` | Combines audit + status + type | Full-featured entities |
158
-
159
- :::tip
160
- For a complete list of enrichers and options, see the [Schema Enrichers Reference](../../references/base/models.md#schema-enrichers).
161
- :::
162
-
163
- ---
164
-
165
- ## 2. DataSources: Connecting to Your Database
166
-
167
- A DataSource manages database connections and supports **schema auto-discovery** from repositories.
168
-
169
- ### Creating a DataSource
170
-
171
- ```typescript
172
- // src/datasources/postgres.datasource.ts
173
- import {
174
- BaseDataSource,
175
- datasource,
176
- TNodePostgresConnector,
177
- ValueOrPromise,
178
- } from '@venizia/ignis';
179
- import { drizzle } from 'drizzle-orm/node-postgres';
180
- import { Pool } from 'pg';
181
-
182
- interface IDSConfigs {
183
- host: string;
184
- port: number;
185
- database: string;
186
- user: string;
187
- password: string;
188
- }
189
-
190
- @datasource({ driver: 'node-postgres' })
191
- export class PostgresDataSource extends BaseDataSource<TNodePostgresConnector, IDSConfigs> {
192
- constructor() {
193
- super({
194
- name: PostgresDataSource.name,
195
- config: {
196
- host: process.env.POSTGRES_HOST ?? 'localhost',
197
- port: +(process.env.POSTGRES_PORT ?? 5432),
198
- database: process.env.POSTGRES_DATABASE ?? 'mydb',
199
- user: process.env.POSTGRES_USER ?? 'postgres',
200
- password: process.env.POSTGRES_PASSWORD ?? '',
201
- },
202
- // No schema needed - auto-discovered from @repository bindings!
203
- });
204
- }
205
-
206
- override configure(): ValueOrPromise<void> {
207
- // getSchema() auto-discovers models from @repository bindings
208
- const schema = this.getSchema();
209
-
210
- this.logger.debug(
211
- '[configure] Auto-discovered schema | Keys: %o',
212
- Object.keys(schema),
213
- );
214
-
215
- const client = new Pool(this.settings);
216
- this.connector = drizzle({ client, schema });
217
- }
218
-
219
- override getConnectionString(): ValueOrPromise<string> {
220
- const { host, port, user, password, database } = this.settings;
221
- return `postgresql://${user}:${password}@${host}:${port}/${database}`;
222
- }
223
- }
224
- ```
225
-
226
- **How auto-discovery works:**
227
-
228
- 1. `@repository` decorators register model-datasource bindings
229
- 2. When `configure()` is called, `getSchema()` collects all bound models
230
- 3. Drizzle is initialized with the complete schema
231
-
232
- ### Manual Schema (Optional)
233
-
234
- If you need explicit control, you can still provide schema manually:
235
-
236
- ```typescript
237
- @datasource({ driver: 'node-postgres' })
238
- export class PostgresDataSource extends BaseDataSource<TNodePostgresConnector, IDSConfigs> {
239
- constructor() {
240
- super({
241
- name: PostgresDataSource.name,
242
- config: { /* ... */ },
243
- schema: {
244
- User: User.schema,
245
- Configuration: Configuration.schema,
246
- // Add relations if using Drizzle's relational queries
247
- },
248
- });
249
- }
250
- }
251
- ```
252
-
253
- ### Registering a DataSource
254
-
255
- ```typescript
256
- // src/application.ts
257
- export class Application extends BaseApplication {
258
- preConfigure(): ValueOrPromise<void> {
259
- this.dataSource(PostgresDataSource);
260
- }
261
- }
262
- ```
263
-
264
- ---
265
-
266
- ## 3. Repositories: The Data Access Layer
267
-
268
- Repositories provide type-safe CRUD operations. Use `@repository` decorator with both `model` and `dataSource` for auto-discovery.
269
-
270
- ### Pattern 1: Zero Boilerplate (Recommended)
271
-
272
- The simplest approach - everything is auto-resolved:
273
-
274
- ```typescript
275
- // src/repositories/configuration.repository.ts
276
- import { Configuration } from '@/models/entities';
277
- import { PostgresDataSource } from '@/datasources/postgres.datasource';
278
- import { DefaultCRUDRepository, repository } from '@venizia/ignis';
279
-
280
- @repository({
281
- model: Configuration,
282
- dataSource: PostgresDataSource,
283
- })
284
- export class ConfigurationRepository extends DefaultCRUDRepository<typeof Configuration.schema> {
285
- // No constructor needed!
286
-
287
- async findByCode(code: string) {
288
- return this.findOne({ filter: { where: { code } } });
289
- }
290
-
291
- async findByGroup(group: string) {
292
- return this.find({ filter: { where: { group } } });
293
- }
294
- }
295
- ```
296
-
297
- ### Pattern 2: Explicit @inject
298
-
299
- When you need constructor control (e.g., read-only repository or additional dependencies):
300
-
301
- ```typescript
302
- // src/repositories/user.repository.ts
303
- import { User } from '@/models/entities';
304
- import { PostgresDataSource } from '@/datasources/postgres.datasource';
305
- import { inject, ReadableRepository, repository } from '@venizia/ignis';
306
- import { CacheService } from '@/services/cache.service';
307
-
308
- @repository({ model: User, dataSource: PostgresDataSource })
309
- export class UserRepository extends ReadableRepository<typeof User.schema> {
310
- constructor(
311
- // First parameter MUST be DataSource injection
312
- @inject({ key: 'datasources.PostgresDataSource' })
313
- dataSource: PostgresDataSource, // Must be concrete type, not 'any'
314
-
315
- // After first arg, you can inject any additional dependencies
316
- @inject({ key: 'some.cache' })
317
- private cache: SomeCache,
318
- ) {
319
- super(dataSource);
320
- }
321
-
322
- async findByRealm(realm: string) {
323
- // Use injected dependencies
324
- const cached = await this.cacheService.get(`user:realm:${realm}`);
325
- if (cached) {
326
- return cached;
327
- }
328
-
329
- return this.findOne({ filter: { where: { realm } } });
330
- }
331
- }
332
- ```
333
-
334
- > **Important:**
335
- > - First constructor parameter **MUST** be the DataSource injection
336
- > - After the first argument, you can inject any additional dependencies you need
337
- > - When `@inject` is at param index 0, auto-injection is skipped
338
-
339
- ### Repository Types
340
-
341
- | Type | Description |
342
- |------|-------------|
343
- | `DefaultCRUDRepository` | Full read/write operations |
344
- | `ReadableRepository` | Read-only operations |
345
- | `PersistableRepository` | Write operations only |
346
-
347
- ### Querying Data
348
-
349
- ```typescript
350
- const repo = this.get<ConfigurationRepository>({ key: 'repositories.ConfigurationRepository' });
351
-
352
- // Find multiple records
353
- const configs = await repo.find({
354
- filter: {
355
- where: { group: 'SYSTEM' },
356
- limit: 10,
357
- order: ['createdAt DESC'],
358
- }
359
- });
360
-
361
- // Find one record
362
- const config = await repo.findOne({
363
- filter: { where: { code: 'APP_NAME' } }
364
- });
365
-
366
- // Create a record
367
- const newConfig = await repo.create({
368
- data: {
369
- code: 'NEW_SETTING',
370
- group: 'SYSTEM',
371
- description: 'A new setting',
372
- }
373
- });
374
-
375
- // Update by ID
376
- await repo.updateById({
377
- id: 'uuid-here',
378
- data: { description: 'Updated description' }
379
- });
380
-
381
- // Delete by ID
382
- await repo.deleteById({ id: 'uuid-here' });
383
- ```
384
-
385
- ### Querying with Relations
386
-
387
- Use `include` to fetch related data. The relation name must match what you defined in `static relations`:
388
-
389
- ```typescript
390
- const configWithCreator = await repo.findOne({
391
- filter: {
392
- where: { code: 'APP_NAME' },
393
- include: [{ relation: 'creator' }],
394
- },
395
- });
396
-
397
- console.log('Created by:', configWithCreator.creator.name);
398
- ```
399
-
400
- ### Registering Repositories
401
-
402
- ```typescript
403
- // src/application.ts
404
- export class Application extends BaseApplication {
405
- preConfigure(): ValueOrPromise<void> {
406
- this.dataSource(PostgresDataSource);
407
- this.repository(UserRepository);
408
- this.repository(ConfigurationRepository);
409
- }
410
- }
411
- ```
412
-
413
- ---
414
-
415
- ## 4. Advanced Topics
416
-
417
- ### Performance: Core API Optimization
418
-
419
- Ignis automatically optimizes "flat" queries (no relations, no field selection) by using Drizzle's Core API. This provides **~15-20% faster** queries for simple reads.
420
-
421
- ### Modular Persistence with Components
422
-
423
- Bundle related persistence resources into Components for better organization:
424
-
425
- ```typescript
426
- export class UserManagementComponent extends BaseComponent {
427
- override binding() {
428
- this.application.dataSource(PostgresDataSource);
429
- this.application.repository(UserRepository);
430
- this.application.repository(ProfileRepository);
431
- }
432
- }
433
- ```
434
-
435
- ---
436
-
437
- ## 5. Transactions
438
-
439
- Ignis supports explicit transaction objects that can be passed across multiple services and repositories, allowing for complex, multi-step business logic to be atomic.
440
-
441
- ### Using Transactions
442
-
443
- To use transactions, start one from a repository or datasource, and then pass it to subsequent operations via the `options` parameter.
444
-
445
- ```typescript
446
- // 1. Start a transaction
447
- const tx = await userRepo.beginTransaction({
448
- isolationLevel: 'SERIALIZABLE' // Optional, defaults to 'READ COMMITTED'
449
- });
450
-
451
- try {
452
- // 2. Pass transaction to operations
453
- // Create user
454
- const user = await userRepo.create({
455
- data: userData,
456
- options: { transaction: tx }
457
- });
458
-
459
- // Create profile (using same transaction)
460
- await profileRepo.create({
461
- data: { userId: user.id, ...profileData },
462
- options: { transaction: tx }
463
- });
464
-
465
- // Call a service method (passing the transaction)
466
- await orderService.createInitialOrder(user.id, { transaction: tx });
467
-
468
- // 3. Commit the transaction
469
- await tx.commit();
470
- } catch (err) {
471
- // 4. Rollback on error
472
- await tx.rollback();
473
- throw err;
474
- }
475
- ```
476
-
477
- ### Isolation Levels
478
-
479
- Ignis supports standard PostgreSQL isolation levels:
480
-
481
- | Level | Description | Use Case |
482
- |-------|-------------|----------|
483
- | `READ COMMITTED` | (Default) Queries see only data committed before the query began. | General use, prevents dirty reads. |
484
- | `REPEATABLE READ` | Queries see a snapshot as of the start of the transaction. | Reports, consistent reads across multiple queries. |
485
- | `SERIALIZABLE` | Strictest level. Emulates serial execution. | Financial transactions, critical data integrity. |
486
-
487
- ### Best Practices
488
-
489
- 1. **Always use `try...catch...finally`**: Ensure `rollback()` is called on error to release the connection.
490
- 2. **Keep it short**: Long-running transactions hold database locks and connections.
491
- 3. **Pass explicit options**: When calling other services inside a transaction, ensure they accept and use the `transaction` option.
492
-
493
- ```typescript
494
- // Service method supporting transactions
495
- async createInitialOrder(userId: string, opts?: { transaction?: ITransaction }) {
496
- return this.orderRepository.create({
497
- data: { userId, status: 'PENDING' },
498
- options: { transaction: opts?.transaction } // Forward the transaction
499
- });
500
- }
501
- ```
502
-
503
- ---
504
-
505
- ## Quick Reference
506
-
507
- ### Model Template
508
-
509
- ```typescript
510
- import { BaseEntity, generateIdColumnDefs, model, TRelationConfig } from '@venizia/ignis';
511
- import { pgTable, text } from 'drizzle-orm/pg-core';
512
-
513
- @model({ type: 'entity' })
514
- export class MyModel extends BaseEntity<typeof MyModel.schema> {
515
- static override schema = pgTable('MyModel', {
516
- ...generateIdColumnDefs({ id: { dataType: 'string' } }),
517
- name: text('name').notNull(),
518
- });
519
-
520
- static override relations = (): TRelationConfig[] => [];
521
- }
522
- ```
523
-
524
- ### Repository Template
525
-
526
- ```typescript
527
- import { DefaultCRUDRepository, repository } from '@venizia/ignis';
528
- import { MyModel } from '@/models/entities';
529
- import { PostgresDataSource } from '@/datasources/postgres.datasource';
530
-
531
- @repository({ model: MyModel, dataSource: PostgresDataSource })
532
- export class MyModelRepository extends DefaultCRUDRepository<typeof MyModel.schema> {}
533
- ```
534
-
535
- > **Deep Dive:**
536
- > - [BaseEntity Reference](../../references/base/models.md#baseentity-class)
537
- > - [Schema Enrichers](../../references/base/models.md#schema-enrichers)
538
- > - [BaseDataSource Reference](../../references/base/datasources.md)
539
- > - [Repository Reference](../../references/base/repositories.md)
@@ -1,65 +0,0 @@
1
- # Getting Started with Ignis
2
-
3
- Welcome to Ignis! This guide takes you from zero to a fully functional, database-connected REST API.
4
-
5
- **Recommended learning path:**
6
-
7
- ## 1. Prerequisites
8
-
9
- Before starting, ensure you have the required tools installed.
10
-
11
- [Check Prerequisites](./prerequisites.md)
12
-
13
- ## 2. Philosophy
14
-
15
- Understand the "why" behind Ignis - how it combines enterprise-grade patterns with high performance.
16
-
17
- [Learn the Philosophy](./philosophy.md)
18
-
19
- ## 3. Choose Your Starting Point
20
-
21
- ### Option A: 5-Minute Quickstart (Recommended for First-Timers)
22
-
23
- Build your first "Hello World" endpoint in 5 minutes. No database, minimal setup.
24
-
25
- [5-Minute Quickstart](./5-minute-quickstart.md) ⚡
26
-
27
- ### Option B: Complete Setup Guide
28
-
29
- Full production setup with ESLint, Prettier, and proper project structure.
30
-
31
- [Complete Setup Guide](./quickstart.md)
32
-
33
- ## 4. Building a CRUD API
34
-
35
- **Most important guide** - build a complete Todo API covering:
36
- - Models with Drizzle ORM
37
- - DataSources & Repositories
38
- - Controllers with auto-generated endpoints
39
- - Dependency Injection
40
-
41
- [Build a CRUD API](./building-a-crud-api.md)
42
-
43
- ## 5. Core Concepts
44
-
45
- Deep dive into framework internals:
46
-
47
- - [The Application Class](./core-concepts/application.md) - Lifecycle and configuration
48
- - [Dependency Injection](./core-concepts/dependency-injection.md) - DI container patterns
49
- - [Controllers](./core-concepts/controllers.md) - Routing and request handling
50
- - [Services](./core-concepts/services.md) - Business logic layer
51
- - [Persistent Layer](./core-concepts/persistent.md) - Models, DataSources, Repositories
52
- - [Components](./core-concepts/components.md) - Reusable modules
53
-
54
- ## 6. Best Practices
55
-
56
- Production-ready patterns and practices:
57
-
58
- - [Architectural Patterns](./best-practices/architectural-patterns.md) - Layered architecture
59
- - [API Usage Examples](./best-practices/api-usage-examples.md) - Real-world patterns
60
- - [Code Style Standards](./best-practices/code-style-standards.md) - ESLint & Prettier
61
- - [Security Guidelines](./best-practices/security-guidelines.md) - Protect your API
62
- - [Performance Optimization](./best-practices/performance-optimization.md) - Speed improvements
63
- - [Deployment Strategies](./best-practices/deployment-strategies.md) - Go to production
64
- - [Troubleshooting Tips](./best-practices/troubleshooting-tips.md) - Common issues
65
- - [Contribution Workflow](./best-practices/contribution-workflow.md) - Contribute to Ignis