@venizia/ignis-docs 0.0.2 → 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 (134) 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 +647 -182
  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 +86 -0
  21. package/wiki/changelogs/2025-12-26-transaction-support.md +57 -0
  22. package/wiki/changelogs/2025-12-29-dynamic-binding-registration.md +104 -0
  23. package/wiki/changelogs/2025-12-29-snowflake-uid-helper.md +100 -0
  24. package/wiki/changelogs/2025-12-30-repository-enhancements.md +214 -0
  25. package/wiki/changelogs/2025-12-31-json-path-filtering-array-operators.md +214 -0
  26. package/wiki/changelogs/2025-12-31-string-id-custom-generator.md +137 -0
  27. package/wiki/changelogs/2026-01-02-default-filter-and-repository-mixins.md +418 -0
  28. package/wiki/changelogs/index.md +8 -1
  29. package/wiki/changelogs/planned-schema-migrator.md +2 -10
  30. package/wiki/{get-started/core-concepts → guides/core-concepts/application}/bootstrapping.md +18 -5
  31. package/wiki/{get-started/core-concepts/application.md → guides/core-concepts/application/index.md} +47 -104
  32. package/wiki/guides/core-concepts/components-guide.md +509 -0
  33. package/wiki/guides/core-concepts/components.md +122 -0
  34. package/wiki/{get-started → guides}/core-concepts/controllers.md +30 -13
  35. package/wiki/{get-started → guides}/core-concepts/dependency-injection.md +97 -0
  36. package/wiki/guides/core-concepts/persistent/datasources.md +179 -0
  37. package/wiki/guides/core-concepts/persistent/index.md +119 -0
  38. package/wiki/guides/core-concepts/persistent/models.md +241 -0
  39. package/wiki/guides/core-concepts/persistent/repositories.md +219 -0
  40. package/wiki/guides/core-concepts/persistent/transactions.md +170 -0
  41. package/wiki/{get-started → guides}/core-concepts/services.md +26 -3
  42. package/wiki/{get-started → guides/get-started}/5-minute-quickstart.md +59 -14
  43. package/wiki/guides/get-started/philosophy.md +682 -0
  44. package/wiki/guides/get-started/setup.md +157 -0
  45. package/wiki/guides/index.md +89 -0
  46. package/wiki/guides/reference/glossary.md +243 -0
  47. package/wiki/{get-started → guides/reference}/mcp-docs-server.md +0 -10
  48. package/wiki/{get-started → guides/tutorials}/building-a-crud-api.md +134 -132
  49. package/wiki/{get-started/quickstart.md → guides/tutorials/complete-installation.md} +107 -71
  50. package/wiki/guides/tutorials/ecommerce-api.md +1399 -0
  51. package/wiki/guides/tutorials/realtime-chat.md +1261 -0
  52. package/wiki/guides/tutorials/testing.md +723 -0
  53. package/wiki/index.md +176 -37
  54. package/wiki/references/base/application.md +27 -0
  55. package/wiki/references/base/bootstrapping.md +30 -26
  56. package/wiki/references/base/components.md +532 -31
  57. package/wiki/references/base/controllers.md +136 -38
  58. package/wiki/references/base/datasources.md +108 -5
  59. package/wiki/references/base/dependency-injection.md +39 -3
  60. package/wiki/references/base/filter-system/application-usage.md +224 -0
  61. package/wiki/references/base/filter-system/array-operators.md +132 -0
  62. package/wiki/references/base/filter-system/comparison-operators.md +109 -0
  63. package/wiki/references/base/filter-system/default-filter.md +428 -0
  64. package/wiki/references/base/filter-system/fields-order-pagination.md +155 -0
  65. package/wiki/references/base/filter-system/index.md +127 -0
  66. package/wiki/references/base/filter-system/json-filtering.md +197 -0
  67. package/wiki/references/base/filter-system/list-operators.md +71 -0
  68. package/wiki/references/base/filter-system/logical-operators.md +156 -0
  69. package/wiki/references/base/filter-system/null-operators.md +58 -0
  70. package/wiki/references/base/filter-system/pattern-matching.md +108 -0
  71. package/wiki/references/base/filter-system/quick-reference.md +431 -0
  72. package/wiki/references/base/filter-system/range-operators.md +63 -0
  73. package/wiki/references/base/filter-system/tips.md +190 -0
  74. package/wiki/references/base/filter-system/use-cases.md +452 -0
  75. package/wiki/references/base/index.md +90 -0
  76. package/wiki/references/base/middlewares.md +602 -0
  77. package/wiki/references/base/models.md +215 -23
  78. package/wiki/references/base/providers.md +732 -0
  79. package/wiki/references/base/repositories/advanced.md +555 -0
  80. package/wiki/references/base/repositories/index.md +228 -0
  81. package/wiki/references/base/repositories/mixins.md +331 -0
  82. package/wiki/references/base/repositories/relations.md +486 -0
  83. package/wiki/references/base/repositories.md +40 -549
  84. package/wiki/references/base/services.md +28 -4
  85. package/wiki/references/components/authentication.md +22 -2
  86. package/wiki/references/components/health-check.md +12 -0
  87. package/wiki/references/components/index.md +23 -0
  88. package/wiki/references/components/mail.md +687 -0
  89. package/wiki/references/components/request-tracker.md +16 -0
  90. package/wiki/references/components/socket-io.md +18 -0
  91. package/wiki/references/components/static-asset.md +14 -26
  92. package/wiki/references/components/swagger.md +17 -0
  93. package/wiki/references/configuration/environment-variables.md +427 -0
  94. package/wiki/references/configuration/index.md +73 -0
  95. package/wiki/references/helpers/cron.md +14 -0
  96. package/wiki/references/helpers/crypto.md +15 -0
  97. package/wiki/references/helpers/env.md +16 -0
  98. package/wiki/references/helpers/error.md +17 -0
  99. package/wiki/references/helpers/index.md +15 -0
  100. package/wiki/references/helpers/inversion.md +24 -4
  101. package/wiki/references/helpers/logger.md +19 -0
  102. package/wiki/references/helpers/network.md +11 -0
  103. package/wiki/references/helpers/queue.md +19 -0
  104. package/wiki/references/helpers/redis.md +21 -0
  105. package/wiki/references/helpers/socket-io.md +24 -5
  106. package/wiki/references/helpers/storage.md +18 -10
  107. package/wiki/references/helpers/testing.md +18 -0
  108. package/wiki/references/helpers/types.md +167 -0
  109. package/wiki/references/helpers/uid.md +167 -0
  110. package/wiki/references/helpers/worker-thread.md +16 -0
  111. package/wiki/references/index.md +177 -0
  112. package/wiki/references/quick-reference.md +634 -0
  113. package/wiki/references/src-details/boot.md +3 -3
  114. package/wiki/references/src-details/dev-configs.md +0 -4
  115. package/wiki/references/src-details/docs.md +2 -2
  116. package/wiki/references/src-details/index.md +86 -0
  117. package/wiki/references/src-details/inversion.md +1 -6
  118. package/wiki/references/src-details/mcp-server.md +3 -15
  119. package/wiki/references/utilities/index.md +86 -10
  120. package/wiki/references/utilities/jsx.md +577 -0
  121. package/wiki/references/utilities/request.md +0 -2
  122. package/wiki/references/utilities/statuses.md +740 -0
  123. package/wiki/changelogs/planned-transaction-support.md +0 -216
  124. package/wiki/get-started/best-practices/api-usage-examples.md +0 -266
  125. package/wiki/get-started/best-practices/architectural-patterns.md +0 -170
  126. package/wiki/get-started/best-practices/data-modeling.md +0 -177
  127. package/wiki/get-started/best-practices/deployment-strategies.md +0 -121
  128. package/wiki/get-started/best-practices/performance-optimization.md +0 -88
  129. package/wiki/get-started/best-practices/security-guidelines.md +0 -99
  130. package/wiki/get-started/core-concepts/components.md +0 -98
  131. package/wiki/get-started/core-concepts/persistent.md +0 -543
  132. package/wiki/get-started/index.md +0 -65
  133. package/wiki/get-started/philosophy.md +0 -296
  134. package/wiki/get-started/prerequisites.md +0 -113
@@ -1,543 +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
- ### Transactions (Current)
422
-
423
- Currently, use Drizzle's callback-based `connector.transaction` for atomic operations:
424
-
425
- ```typescript
426
- const ds = this.get<PostgresDataSource>({ key: 'datasources.PostgresDataSource' });
427
-
428
- await ds.connector.transaction(async (tx) => {
429
- await tx.insert(User.schema).values({ /* ... */ });
430
- await tx.insert(Configuration.schema).values({ /* ... */ });
431
- });
432
- ```
433
-
434
- > **Note:** This callback-based approach requires all transaction logic to be in one callback. See [Section 5](#5-transactions-planned) for the planned improvement.
435
-
436
- ### Modular Persistence with Components
437
-
438
- Bundle related persistence resources into Components for better organization:
439
-
440
- ```typescript
441
- export class UserManagementComponent extends BaseComponent {
442
- override binding() {
443
- this.application.dataSource(PostgresDataSource);
444
- this.application.repository(UserRepository);
445
- this.application.repository(ProfileRepository);
446
- }
447
- }
448
- ```
449
-
450
- ---
451
-
452
- ## 5. Transactions (Planned)
453
-
454
- > **Status:** Planned - Not yet implemented. See [full plan](../../changelogs/planned-transaction-support).
455
-
456
- ### The Problem
457
-
458
- Drizzle's callback-based transactions make it hard to pass transactions across services:
459
-
460
- ```typescript
461
- // Current: Everything must be inside the callback
462
- await ds.connector.transaction(async (tx) => {
463
- // Can't easily call other services with this tx
464
- });
465
- ```
466
-
467
- ### Planned Solution
468
-
469
- Loopback 4-style explicit transaction objects that can be passed anywhere:
470
-
471
- ```typescript
472
- // Start transaction from repository
473
- const tx = await userRepo.beginTransaction({
474
- isolationLevel: 'SERIALIZABLE' // Optional, defaults to 'READ COMMITTED'
475
- });
476
-
477
- try {
478
- // Pass tx to multiple services/repositories
479
- const user = await userRepo.create({ data, options: { transaction: tx } });
480
- await profileRepo.create({ data: { userId: user.id }, options: { transaction: tx } });
481
- await orderService.createInitialOrder(user.id, { transaction: tx });
482
-
483
- await tx.commit();
484
- } catch (err) {
485
- await tx.rollback();
486
- throw err;
487
- }
488
- ```
489
-
490
- ### Isolation Levels
491
-
492
- | Level | Description | Use Case |
493
- |-------|-------------|----------|
494
- | `READ COMMITTED` | Default. Sees only committed data | General use |
495
- | `REPEATABLE READ` | Snapshot from transaction start | Reports, consistent reads |
496
- | `SERIALIZABLE` | Full isolation, may throw errors | Financial, critical data |
497
-
498
- ### Benefits
499
-
500
- | Aspect | Current (Callback) | Planned (Pass-through) |
501
- |--------|-------------------|------------------------|
502
- | Service composition | Hard | Easy - pass tx anywhere |
503
- | Separation of concerns | Services coupled | Services independent |
504
- | Testing | Complex mocking | Easy to mock tx |
505
- | Code organization | Nested callbacks | Flat, sequential |
506
-
507
- ---
508
-
509
- ## Quick Reference
510
-
511
- ### Model Template
512
-
513
- ```typescript
514
- import { BaseEntity, generateIdColumnDefs, model, TRelationConfig } from '@venizia/ignis';
515
- import { pgTable, text } from 'drizzle-orm/pg-core';
516
-
517
- @model({ type: 'entity' })
518
- export class MyModel extends BaseEntity<typeof MyModel.schema> {
519
- static override schema = pgTable('MyModel', {
520
- ...generateIdColumnDefs({ id: { dataType: 'string' } }),
521
- name: text('name').notNull(),
522
- });
523
-
524
- static override relations = (): TRelationConfig[] => [];
525
- }
526
- ```
527
-
528
- ### Repository Template
529
-
530
- ```typescript
531
- import { DefaultCRUDRepository, repository } from '@venizia/ignis';
532
- import { MyModel } from '@/models/entities';
533
- import { PostgresDataSource } from '@/datasources/postgres.datasource';
534
-
535
- @repository({ model: MyModel, dataSource: PostgresDataSource })
536
- export class MyModelRepository extends DefaultCRUDRepository<typeof MyModel.schema> {}
537
- ```
538
-
539
- > **Deep Dive:**
540
- > - [BaseEntity Reference](../../references/base/models.md#baseentity-class)
541
- > - [Schema Enrichers](../../references/base/models.md#schema-enrichers)
542
- > - [BaseDataSource Reference](../../references/base/datasources.md)
543
- > - [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