@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
@@ -0,0 +1,228 @@
1
+ # Repositories Overview
2
+
3
+ Repositories are the data access layer in Ignis - they provide type-safe CRUD operations for your database entities.
4
+
5
+ **Files:** `packages/core/src/base/repositories/core/*.ts`
6
+
7
+
8
+ ## Quick Start
9
+
10
+ If you're new to repositories, start here:
11
+
12
+ ```typescript
13
+ import { DefaultCRUDRepository, repository } from '@venizia/ignis';
14
+ import { Todo } from '@/models/todo.model';
15
+ import { PostgresDataSource } from '@/datasources/postgres.datasource';
16
+
17
+ @repository({ model: Todo, dataSource: PostgresDataSource })
18
+ export class TodoRepository extends DefaultCRUDRepository<typeof Todo.schema> {
19
+ // That's it! You get: find, findOne, create, updateById, deleteById, etc.
20
+ }
21
+ ```
22
+
23
+
24
+ ## Repository Classes
25
+
26
+ | Class | Capabilities | Use Case |
27
+ |-------|--------------|----------|
28
+ | **AbstractRepository** | Base class with properties | Extend for custom repositories |
29
+ | **ReadableRepository** | Read-only operations | Views, external tables |
30
+ | **PersistableRepository** | Read + Write operations | Rarely used directly |
31
+ | **DefaultCRUDRepository** | Full CRUD operations | Standard data tables |
32
+
33
+ **Most common:** Extend `DefaultCRUDRepository` for standard tables.
34
+
35
+
36
+ ## Available Methods
37
+
38
+ ### Read Operations
39
+ | Method | Description | Example |
40
+ |--------|-------------|---------|
41
+ | `find(opts)` | Find multiple records | `repo.find({ filter: { where: { status: 'active' } } })` |
42
+ | `findOne(opts)` | Find single record | `repo.findOne({ filter: { where: { email } } })` |
43
+ | `findById(opts)` | Find by primary key | `repo.findById({ id: '123' })` |
44
+ | `count(opts)` | Count matching records | `repo.count({ where: { status: 'active' } })` |
45
+ | `existsWith(opts)` | Check if exists | `repo.existsWith({ where: { email } })` |
46
+
47
+ ### Write Operations
48
+ | Method | Description | Example |
49
+ |--------|-------------|---------|
50
+ | `create(opts)` | Create single record | `repo.create({ data: { title: 'New' } })` |
51
+ | `createAll(opts)` | Create multiple records | `repo.createAll({ data: [{ title: 'A' }, { title: 'B' }] })` |
52
+ | `updateById(opts)` | Update by primary key | `repo.updateById({ id: '123', data: { title: 'Updated' } })` |
53
+ | `updateAll(opts)` | Update matching records | `repo.updateAll({ where: { status: 'draft' }, data: { status: 'published' } })` |
54
+ | `deleteById(opts)` | Delete by primary key | `repo.deleteById({ id: '123' })` |
55
+ | `deleteAll(opts)` | Delete matching records | `repo.deleteAll({ where: { status: 'archived' } })` |
56
+
57
+
58
+ ## Documentation Sections
59
+
60
+ This documentation is split into focused guides:
61
+
62
+ ### [Filter System](/references/base/filter-system/)
63
+ Complete reference for querying data - operators, JSON filtering, array operators, default filters, and query patterns.
64
+
65
+ ```typescript
66
+ // Preview
67
+ await repo.find({
68
+ filter: {
69
+ where: {
70
+ status: 'active',
71
+ age: { gte: 18 },
72
+ 'metadata.priority': { gte: 3 },
73
+ tags: { contains: ['featured'] }
74
+ },
75
+ order: ['createdAt DESC'],
76
+ limit: 20
77
+ }
78
+ });
79
+ ```
80
+
81
+ ### [Relations & Includes](./relations.md)
82
+ Fetch related data using `include` for eager loading and nested queries.
83
+
84
+ ```typescript
85
+ // Preview
86
+ await repo.find({
87
+ filter: {
88
+ include: [{
89
+ relation: 'posts',
90
+ scope: { where: { published: true } }
91
+ }]
92
+ }
93
+ });
94
+ ```
95
+
96
+ ### [Advanced Features](./advanced.md)
97
+ Transactions, hidden properties, default filter bypass, performance optimization, and type inference.
98
+
99
+ ```typescript
100
+ // Preview
101
+ const tx = await repo.beginTransaction();
102
+ try {
103
+ await repo.create({ data, options: { transaction: tx } });
104
+ await tx.commit();
105
+ } catch (e) {
106
+ await tx.rollback();
107
+ }
108
+ ```
109
+
110
+ ### [Repository Mixins](./mixins.md)
111
+ Composable mixins for repository features - `DefaultFilterMixin` and `FieldsVisibilityMixin`.
112
+
113
+
114
+ ## @repository Decorator
115
+
116
+ **Both `model` AND `dataSource` are required** for schema auto-discovery:
117
+
118
+ ```typescript
119
+ // ❌ WRONG - Missing dataSource
120
+ @repository({ model: User })
121
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
122
+
123
+ // ❌ WRONG - Missing model
124
+ @repository({ dataSource: PostgresDataSource })
125
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
126
+
127
+ // ✅ CORRECT
128
+ @repository({ model: User, dataSource: PostgresDataSource })
129
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
130
+ ```
131
+
132
+ ### Zero Boilerplate Pattern (Recommended)
133
+
134
+ DataSource is auto-injected - no constructor needed:
135
+
136
+ ```typescript
137
+ @repository({ model: User, dataSource: PostgresDataSource })
138
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
139
+ // Custom methods only - no boilerplate!
140
+
141
+ async findByEmail(opts: { email: string }) {
142
+ return this.findOne({ filter: { where: { email: opts.email } } });
143
+ }
144
+ }
145
+ ```
146
+
147
+ ### Explicit @inject Pattern
148
+
149
+ When you need constructor control:
150
+
151
+ ```typescript
152
+ @repository({ model: User, dataSource: PostgresDataSource })
153
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
154
+ constructor(
155
+ @inject({ key: 'datasources.PostgresDataSource' })
156
+ dataSource: PostgresDataSource,
157
+ ) {
158
+ super(dataSource);
159
+ }
160
+ }
161
+ ```
162
+
163
+
164
+ ## Safety Features
165
+
166
+ ### Empty Where Protection
167
+
168
+ Prevents accidental mass updates/deletes:
169
+
170
+ ```typescript
171
+ // ❌ Throws error - empty where without force flag
172
+ await repo.deleteAll({ where: {} });
173
+
174
+ // ✅ Explicitly allow with force flag (logs warning)
175
+ await repo.deleteAll({ where: {}, options: { force: true } });
176
+ ```
177
+
178
+ | Scenario | `force: false` (default) | `force: true` |
179
+ |----------|-------------------------|---------------|
180
+ | Empty `where` | Throws error | Logs warning, proceeds |
181
+ | Valid `where` | Executes normally | Executes normally |
182
+
183
+
184
+ ## Quick Reference
185
+
186
+ | Want to... | Code |
187
+ |------------|------|
188
+ | Find all active | `repo.find({ filter: { where: { status: 'active' } } })` |
189
+ | Find by ID | `repo.findById({ id: '123' })` |
190
+ | Find with relations | `repo.find({ filter: { include: [{ relation: 'posts' }] } })` |
191
+ | Create one | `repo.create({ data: { name: 'John' } })` |
192
+ | Update by ID | `repo.updateById({ id: '123', data: { name: 'Jane' } })` |
193
+ | Delete by ID | `repo.deleteById({ id: '123' })` |
194
+ | Count matching | `repo.count({ where: { status: 'active' } })` |
195
+ | Check exists | `repo.existsWith({ where: { email: 'test@example.com' } })` |
196
+
197
+
198
+ ## Next Steps
199
+
200
+ - **New to filtering?** Start with [Filter System](/references/base/filter-system/)
201
+ - **Need related data?** See [Relations & Includes](./relations.md)
202
+ - **Need transactions?** Go to [Advanced Features](./advanced.md)
203
+
204
+ ## See Also
205
+
206
+ - **Related Concepts:**
207
+ - [Repositories Guide](/guides/core-concepts/persistent/repositories) - Creating repositories tutorial
208
+ - [Models](/guides/core-concepts/persistent/models) - Entity definitions used by repositories
209
+ - [DataSources](/guides/core-concepts/persistent/datasources) - Database connections
210
+ - [Services](/guides/core-concepts/persistent/services) - Use repositories for data access
211
+ - [Transactions](/guides/core-concepts/persistent/transactions) - Multi-operation consistency
212
+
213
+ - **Repository Topics:**
214
+ - [Relations & Includes](./relations) - Loading related data
215
+ - [Advanced Features](./advanced) - JSON queries, performance tuning, transactions
216
+ - [Repository Mixins](./mixins) - Soft delete and auditing
217
+
218
+ - **Filtering:**
219
+ - [Filter System Overview](/references/base/filter-system/) - Complete filtering guide
220
+ - [Filter Quick Reference](/references/base/filter-system/quick-reference) - All operators cheat sheet
221
+
222
+ - **Best Practices:**
223
+ - [Data Modeling](/best-practices/data-modeling) - Repository design patterns
224
+ - [Performance Optimization](/best-practices/performance-optimization) - Query optimization
225
+
226
+ - **Tutorials:**
227
+ - [Building a CRUD API](/guides/tutorials/building-a-crud-api) - Repository examples
228
+ - [E-commerce API](/guides/tutorials/ecommerce-api) - Advanced queries and relations
@@ -0,0 +1,331 @@
1
+ ---
2
+ title: Repository Mixins
3
+ description: Composable mixins for repository functionality
4
+ difficulty: intermediate
5
+ lastUpdated: 2026-01-02
6
+ ---
7
+
8
+ # Repository Mixins <Badge type="tip" text="v0.0.5+" />
9
+
10
+ Composable mixins that provide reusable functionality for repository classes.
11
+
12
+ ::: info Refactored in v0.0.5
13
+ Repository mixins were extracted and refactored in v0.0.5 to provide better composition and reusability.
14
+ :::
15
+
16
+ **Files:** `packages/core/src/base/repositories/mixins/`
17
+
18
+
19
+ ## Overview
20
+
21
+ Ignis uses the mixin pattern to compose repository features. This enables:
22
+
23
+ - **Separation of concerns** - Each mixin handles one responsibility
24
+ - **Reusability** - Mixins can be applied to different base classes
25
+ - **Testability** - Individual features can be tested in isolation
26
+ - **Flexibility** - Create custom repositories with only needed features
27
+
28
+
29
+ ## Available Mixins
30
+
31
+ | Mixin | Responsibility |
32
+ |-------|----------------|
33
+ | `DefaultFilterMixin` | Automatic filter application from model settings |
34
+ | `FieldsVisibilityMixin` | Hidden properties exclusion |
35
+
36
+
37
+ ## DefaultFilterMixin
38
+
39
+ Provides automatic default filter application for all repository queries.
40
+
41
+ **File:** `packages/core/src/base/repositories/mixins/default-filter.ts`
42
+
43
+ ### Properties
44
+
45
+ | Property | Type | Description |
46
+ |----------|------|-------------|
47
+ | `_defaultFilter` | `TFilter \| null \| undefined` | Cached default filter |
48
+
49
+ ### Methods
50
+
51
+ | Method | Returns | Description |
52
+ |--------|---------|-------------|
53
+ | `getDefaultFilter()` | `TFilter \| undefined` | Get default filter from model metadata |
54
+ | `hasDefaultFilter()` | `boolean` | Check if model has a default filter configured |
55
+ | `applyDefaultFilter(opts)` | `TFilter` | Merge default filter with user filter |
56
+
57
+ ### Usage
58
+
59
+ ```typescript
60
+ import { DefaultFilterMixin } from '@venizia/ignis';
61
+ import { BaseHelper } from '@venizia/ignis-helpers';
62
+
63
+ class MyRepository extends DefaultFilterMixin(BaseHelper) {
64
+ // Required abstract implementations
65
+ abstract getEntity(): BaseEntity;
66
+ abstract get filterBuilder(): FilterBuilder;
67
+
68
+ // Now has access to:
69
+ // - getDefaultFilter()
70
+ // - hasDefaultFilter()
71
+ // - applyDefaultFilter()
72
+ }
73
+ ```
74
+
75
+ ### applyDefaultFilter Options
76
+
77
+ ```typescript
78
+ interface ApplyDefaultFilterOptions {
79
+ userFilter?: TFilter; // User-provided filter
80
+ shouldSkipDefaultFilter?: boolean; // If true, bypass default filter
81
+ }
82
+ ```
83
+
84
+ ### Implementation
85
+
86
+ ```typescript
87
+ applyDefaultFilter<DataObject = any>(opts: {
88
+ userFilter?: TFilter<DataObject>;
89
+ shouldSkipDefaultFilter?: boolean;
90
+ }): TFilter<DataObject> {
91
+ const { userFilter, shouldSkipDefaultFilter } = opts;
92
+
93
+ // Skip default filter if explicitly requested
94
+ if (shouldSkipDefaultFilter) {
95
+ return userFilter ?? {};
96
+ }
97
+
98
+ // Get default filter from model metadata
99
+ const defaultFilter = this.getDefaultFilter();
100
+
101
+ // No default filter configured - return user filter
102
+ if (!defaultFilter) {
103
+ return userFilter ?? {};
104
+ }
105
+
106
+ // Merge default filter with user filter
107
+ return this.filterBuilder.mergeFilter({ defaultFilter, userFilter });
108
+ }
109
+ ```
110
+
111
+
112
+ ## FieldsVisibilityMixin
113
+
114
+ Provides hidden properties management for SQL-level field exclusion.
115
+
116
+ **File:** `packages/core/src/base/repositories/mixins/fields-visibility.ts`
117
+
118
+ ### Properties
119
+
120
+ | Property | Type | Description |
121
+ |----------|------|-------------|
122
+ | `_hiddenProperties` | `Set<string> \| null` | Cached hidden property names |
123
+ | `_visibleProperties` | `Record<string, any> \| null \| undefined` | Cached visible columns |
124
+
125
+ ### Methods
126
+
127
+ | Method | Returns | Description |
128
+ |--------|---------|-------------|
129
+ | `get hiddenProperties` | `Set<string>` | Get hidden property names |
130
+ | `set hiddenProperties` | `void` | Override hidden properties |
131
+ | `getHiddenProperties()` | `Set<string>` | Get hidden properties from model metadata |
132
+ | `hasHiddenProperties()` | `boolean` | Check if model has hidden properties |
133
+ | `get visibleProperties` | `Record<string, any> \| undefined` | Get visible columns for Drizzle |
134
+ | `set visibleProperties` | `void` | Override visible properties |
135
+ | `getVisibleProperties()` | `Record<string, any> \| undefined` | Build visible columns object |
136
+
137
+ ### Usage
138
+
139
+ ```typescript
140
+ import { FieldsVisibilityMixin } from '@venizia/ignis';
141
+ import { BaseHelper } from '@venizia/ignis-helpers';
142
+
143
+ class MyRepository extends FieldsVisibilityMixin(BaseHelper) {
144
+ // Required abstract implementation
145
+ abstract getEntity(): BaseEntity;
146
+
147
+ // Now has access to:
148
+ // - hiddenProperties (getter/setter)
149
+ // - visibleProperties (getter/setter)
150
+ // - getHiddenProperties()
151
+ // - hasHiddenProperties()
152
+ // - getVisibleProperties()
153
+ }
154
+ ```
155
+
156
+ ### Visible Properties for Drizzle
157
+
158
+ The `getVisibleProperties()` method returns a columns object for Drizzle's `select()` or `returning()`:
159
+
160
+ ```typescript
161
+ // Model with hiddenProperties: ['password', 'apiKey']
162
+ // Schema columns: { id, email, password, apiKey, createdAt }
163
+
164
+ const visibleProps = this.getVisibleProperties();
165
+ // Result: { id: column, email: column, createdAt: column }
166
+ // (password and apiKey excluded)
167
+
168
+ // Used in Drizzle queries
169
+ await connector.select(visibleProps).from(schema);
170
+ // SELECT id, email, created_at FROM users
171
+ ```
172
+
173
+
174
+ ## Mixin Composition
175
+
176
+ The `AbstractRepository` composes multiple mixins:
177
+
178
+ ```typescript
179
+ export abstract class AbstractRepository<...>
180
+ extends DefaultFilterMixin(FieldsVisibilityMixin(BaseHelper))
181
+ implements IPersistableRepository<...>
182
+ {
183
+ // Inherits from both mixins:
184
+ // From DefaultFilterMixin:
185
+ // - getDefaultFilter()
186
+ // - hasDefaultFilter()
187
+ // - applyDefaultFilter()
188
+ //
189
+ // From FieldsVisibilityMixin:
190
+ // - hiddenProperties
191
+ // - visibleProperties
192
+ // - getHiddenProperties()
193
+ // - hasHiddenProperties()
194
+ // - getVisibleProperties()
195
+ }
196
+ ```
197
+
198
+ ### Composition Order
199
+
200
+ Mixins are applied right-to-left:
201
+
202
+ ```typescript
203
+ // FieldsVisibilityMixin applied first (to BaseHelper)
204
+ // DefaultFilterMixin applied second (to the result)
205
+ DefaultFilterMixin(FieldsVisibilityMixin(BaseHelper))
206
+ ```
207
+
208
+
209
+ ## Creating Custom Mixins
210
+
211
+ Follow the TypeScript mixin pattern:
212
+
213
+ ```typescript
214
+ import { TMixinTarget } from '@venizia/ignis-helpers';
215
+
216
+ export const AuditLogMixin = <T extends TMixinTarget<object>>(baseClass: T) => {
217
+ abstract class Mixed extends baseClass {
218
+ // Properties
219
+ private _auditEnabled: boolean = true;
220
+
221
+ // Abstract dependencies (if needed)
222
+ abstract getEntity(): BaseEntity;
223
+
224
+ // Public methods
225
+ enableAudit(): void {
226
+ this._auditEnabled = true;
227
+ }
228
+
229
+ disableAudit(): void {
230
+ this._auditEnabled = false;
231
+ }
232
+
233
+ isAuditEnabled(): boolean {
234
+ return this._auditEnabled;
235
+ }
236
+
237
+ logOperation(operation: string, data: any): void {
238
+ if (this._auditEnabled) {
239
+ console.log(`[${this.getEntity().name}] ${operation}:`, data);
240
+ }
241
+ }
242
+ }
243
+
244
+ return Mixed;
245
+ };
246
+ ```
247
+
248
+ ### Using Custom Mixins
249
+
250
+ ```typescript
251
+ // Compose with existing mixins
252
+ class MyRepository extends AuditLogMixin(DefaultFilterMixin(BaseHelper)) {
253
+ getEntity() {
254
+ return this._entity;
255
+ }
256
+
257
+ get filterBuilder() {
258
+ return this._filterBuilder;
259
+ }
260
+ }
261
+
262
+ // Or create a composed base
263
+ const AuditableRepository = AuditLogMixin(DefaultFilterMixin(FieldsVisibilityMixin(BaseHelper)));
264
+
265
+ class ProductRepository extends AuditableRepository {
266
+ // Has all mixin functionality
267
+ }
268
+ ```
269
+
270
+
271
+ ## Caching Behavior
272
+
273
+ Both mixins use caching for performance:
274
+
275
+ ```typescript
276
+ // DefaultFilterMixin caching
277
+ // null = not computed yet
278
+ // undefined = computed, no default filter
279
+ // TFilter = computed, has default filter
280
+ private _defaultFilter: TFilter | null | undefined = null;
281
+
282
+ getDefaultFilter() {
283
+ if (this._defaultFilter !== null) {
284
+ return this._defaultFilter; // Return cached value
285
+ }
286
+ // Compute and cache...
287
+ }
288
+
289
+ // FieldsVisibilityMixin caching
290
+ // null = not computed yet
291
+ // Set<string> = computed
292
+ private _hiddenProperties: Set<string> | null = null;
293
+
294
+ // null = not computed yet
295
+ // undefined = computed, no hidden properties
296
+ // Record<string, any> = computed, has hidden properties
297
+ private _visibleProperties: Record<string, any> | null | undefined = null;
298
+ ```
299
+
300
+
301
+ ## Quick Reference
302
+
303
+ | Mixin | Method | Purpose |
304
+ |-------|--------|---------|
305
+ | `DefaultFilterMixin` | `hasDefaultFilter()` | Check if default filter exists |
306
+ | `DefaultFilterMixin` | `getDefaultFilter()` | Get raw default filter |
307
+ | `DefaultFilterMixin` | `applyDefaultFilter()` | Merge filters |
308
+ | `FieldsVisibilityMixin` | `hasHiddenProperties()` | Check if hidden props exist |
309
+ | `FieldsVisibilityMixin` | `getHiddenProperties()` | Get hidden property names |
310
+ | `FieldsVisibilityMixin` | `getVisibleProperties()` | Get Drizzle columns object |
311
+
312
+
313
+ ## Next Steps
314
+
315
+ - [Default Filter](../filter-system/default-filter.md) - Full default filter documentation
316
+ - [Advanced Features](./advanced.md) - Hidden properties usage
317
+ - [Repository Overview](./index.md) - Repository basics
318
+
319
+ ## See Also
320
+
321
+ - **Related Concepts:**
322
+ - [Repositories Overview](./index) - Core repository operations
323
+ - [Models](/guides/core-concepts/persistent/models) - Entity definitions
324
+
325
+ - **Related Topics:**
326
+ - [Default Filter](../filter-system/default-filter) - Automatic filtering
327
+ - [Advanced Features](./advanced) - Hidden properties and transactions
328
+ - [Relations & Includes](./relations) - Loading related data
329
+
330
+ - **Best Practices:**
331
+ - [Data Modeling](/best-practices/data-modeling) - Soft delete patterns