@venizia/ignis-docs 0.0.1-8 → 0.0.1-9

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 (27) hide show
  1. package/package.json +1 -1
  2. package/wiki/changelogs/2025-12-17-refactor.md +22 -0
  3. package/wiki/changelogs/2025-12-18-performance-optimizations.md +192 -0
  4. package/wiki/changelogs/2025-12-18-repository-validation-security.md +445 -0
  5. package/wiki/changelogs/index.md +22 -0
  6. package/wiki/changelogs/v0.0.1-7-initial-architecture.md +137 -0
  7. package/wiki/changelogs/v0.0.1-8-model-repo-datasource-refactor.md +278 -0
  8. package/wiki/get-started/5-minute-quickstart.md +1 -1
  9. package/wiki/get-started/best-practices/api-usage-examples.md +12 -8
  10. package/wiki/get-started/best-practices/common-pitfalls.md +2 -2
  11. package/wiki/get-started/best-practices/data-modeling.md +14 -20
  12. package/wiki/get-started/building-a-crud-api.md +60 -75
  13. package/wiki/get-started/core-concepts/controllers.md +14 -14
  14. package/wiki/get-started/core-concepts/persistent.md +110 -130
  15. package/wiki/get-started/quickstart.md +1 -1
  16. package/wiki/references/base/controllers.md +40 -16
  17. package/wiki/references/base/datasources.md +195 -33
  18. package/wiki/references/base/dependency-injection.md +5 -5
  19. package/wiki/references/base/models.md +398 -28
  20. package/wiki/references/base/repositories.md +475 -22
  21. package/wiki/references/components/authentication.md +224 -7
  22. package/wiki/references/components/health-check.md +1 -1
  23. package/wiki/references/components/swagger.md +1 -1
  24. package/wiki/references/helpers/inversion.md +8 -3
  25. package/wiki/references/src-details/core.md +6 -5
  26. package/wiki/references/src-details/inversion.md +4 -4
  27. package/wiki/references/utilities/request.md +16 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@venizia/ignis-docs",
3
- "version": "0.0.1-8",
3
+ "version": "0.0.1-9",
4
4
  "description": "Documentation and MCP Server for Ignis Framework",
5
5
  "keywords": [
6
6
  "ignis",
@@ -0,0 +1,22 @@
1
+ # Changelog - 2025-12-17
2
+
3
+ ## Major Refactor: Inversion of Control
4
+
5
+ The Dependency Injection (DI) system has been extracted from `packages/helpers` into a standalone package `@venizia/ignis-inversion`.
6
+
7
+ ### Changes
8
+
9
+ - **New Package**: `@venizia/ignis-inversion` created.
10
+ - **Removed**: `packages/helpers/src/helpers/inversion` deleted.
11
+ - **Updated**: `packages/core` now imports DI primitives from `@venizia/ignis-inversion`.
12
+ - **Refactored**: `packages/core/src/helpers/inversion` now re-exports from the new package and adds core-specific extensions.
13
+
14
+ ### Impact
15
+
16
+ - **Imports**: Imports from `@venizia/ignis` or `@venizia/ignis-helpers` relating to `Binding`, `Container`, `inject` should generally remain compatible via re-exports, but deep imports to `helpers/inversion` will break.
17
+ - **Structure**: Clearer separation of concerns. `inversion` package has zero dependencies on the rest of the framework (except `lodash`, `reflect-metadata`, `zod`).
18
+
19
+ ## Other Changes
20
+
21
+ - **Mixins**: `server-config.mixin.ts` removed from `packages/core`.
22
+ - **Examples**: `examples/vert` updated to reflect latest core changes.
@@ -0,0 +1,192 @@
1
+ # Changelog - 2025-12-18
2
+
3
+ ## Performance Optimizations
4
+
5
+ This update focuses on performance improvements for the repository layer, reducing GC pressure and improving query execution speed.
6
+
7
+ ## Overview
8
+
9
+ - **WeakMap Cache**: `DrizzleFilterBuilder` now caches `getTableColumns()` results
10
+ - **Core API for Flat Queries**: `ReadableRepository` uses faster Drizzle Core API when possible
11
+ - **Static schemaFactory Singleton**: `BaseEntity` shares a single `schemaFactory` instance across all entities
12
+ - **Async/Await Refactor**: Removed redundant Promise wrappers from repository methods
13
+
14
+ ## Performance Improvements
15
+
16
+ ### 1. WeakMap Cache for Filter Builder
17
+
18
+ **File:** `packages/core/src/base/repositories/operators/filter.ts`
19
+
20
+ **Problem:** `getTableColumns()` was called on every filter operation, causing repeated reflection overhead.
21
+
22
+ **Solution:** Added static WeakMap cache that stores column metadata per schema:
23
+
24
+ ```typescript
25
+ export class DrizzleFilterBuilder extends BaseHelper {
26
+ // Static cache shared across all instances
27
+ private static columnCache = new WeakMap<
28
+ TTableSchemaWithId,
29
+ ReturnType<typeof getTableColumns>
30
+ >();
31
+
32
+ private getColumns<Schema extends TTableSchemaWithId>(schema: Schema) {
33
+ let columns = DrizzleFilterBuilder.columnCache.get(schema);
34
+ if (!columns) {
35
+ columns = getTableColumns(schema);
36
+ DrizzleFilterBuilder.columnCache.set(schema, columns);
37
+ }
38
+ return columns;
39
+ }
40
+ }
41
+ ```
42
+
43
+ **Benefits:**
44
+ - First call: `getTableColumns(schema)` → cached
45
+ - Subsequent calls: Retrieved from WeakMap (O(1) lookup)
46
+ - WeakMap allows garbage collection when schema is no longer referenced
47
+ - Especially beneficial for:
48
+ - High-concurrency environments
49
+ - Queries with nested AND/OR conditions (each recursion reuses cache)
50
+ - Multiple queries to the same table
51
+
52
+ ### 2. Core API for Flat Queries (~15-20% Faster)
53
+
54
+ **File:** `packages/core/src/base/repositories/core/readable.ts`
55
+
56
+ **Problem:** All queries used Drizzle's Query API, which has overhead for relational mapping even when not needed.
57
+
58
+ **Solution:** Automatically use Drizzle Core API for flat queries (no relations, no field selection):
59
+
60
+ ```typescript
61
+ // Automatic optimization - no code changes needed
62
+ const users = await repo.find({
63
+ filter: {
64
+ where: { status: 'active' },
65
+ limit: 10,
66
+ order: ['createdAt DESC'],
67
+ }
68
+ });
69
+ // Uses: db.select().from(table).where(...).orderBy(...).limit(10)
70
+ ```
71
+
72
+ **When Core API is used:**
73
+
74
+ | Filter Options | API Used | Reason |
75
+ |----------------|----------|--------|
76
+ | `where`, `limit`, `order`, `offset` only | Core API | Flat query, no overhead |
77
+ | Has `include` (relations) | Query API | Needs relational mapper |
78
+ | Has `fields` selection | Query API | Core API field syntax differs |
79
+
80
+ **New Protected Methods:**
81
+
82
+ ```typescript
83
+ // Check if Core API can be used
84
+ protected canUseCoreAPI(filter: TFilter<DataObject>): boolean;
85
+
86
+ // Execute flat query using Core API
87
+ protected async findWithCoreAPI(opts: {
88
+ filter: TFilter<DataObject>;
89
+ findOne?: boolean;
90
+ }): Promise<Array<DataObject>>;
91
+ ```
92
+
93
+ ### 3. Static schemaFactory Singleton
94
+
95
+ **File:** `packages/core/src/base/models/base.ts`
96
+
97
+ **Problem:** New `schemaFactory` was created for every `BaseEntity` instance:
98
+
99
+ ```typescript
100
+ // Before - created on every instantiation
101
+ constructor(opts?: { name?: string; schema?: Schema }) {
102
+ this.schemaFactory = createSchemaFactory(); // Memory overhead!
103
+ }
104
+ ```
105
+
106
+ **Solution:** Lazy singleton pattern shared across all instances:
107
+
108
+ ```typescript
109
+ // After - shared singleton
110
+ private static _schemaFactory?: ReturnType<typeof createSchemaFactory>;
111
+ protected static get schemaFactory(): ReturnType<typeof createSchemaFactory> {
112
+ return (BaseEntity._schemaFactory ??= createSchemaFactory());
113
+ }
114
+ ```
115
+
116
+ **Benefits:**
117
+ - Single instance for all entities
118
+ - Lazy initialization (created on first use)
119
+ - Reduced memory footprint
120
+
121
+ ### 4. Async/Await Refactor
122
+
123
+ **Files:**
124
+ - `packages/core/src/base/repositories/core/readable.ts`
125
+ - `packages/core/src/base/repositories/core/persistable.ts`
126
+
127
+ **Problem:** Every CRUD method wrapped existing promises in `new Promise()`:
128
+
129
+ ```typescript
130
+ // Before - Anti-pattern
131
+ return new Promise((resolve, reject) => {
132
+ this.connector.$count(this.entity.schema, where)
133
+ .then((count: number) => resolve({ count }))
134
+ .catch(reject);
135
+ });
136
+ ```
137
+
138
+ **Solution:** Direct async/await:
139
+
140
+ ```typescript
141
+ // After - Clean and efficient
142
+ const count = await this.connector.$count(this.entity.schema, where);
143
+ return { count };
144
+ ```
145
+
146
+ **Benefits:**
147
+ - Eliminates extra microtask queue entries
148
+ - Reduces ~200-400 bytes memory per Promise on V8
149
+ - Cleaner stack traces for debugging
150
+ - For bulk operations, overhead reduction multiplies
151
+
152
+ ## Implementation Details
153
+
154
+ ### Type Safety in Core API
155
+
156
+ The Core API implementation uses a controlled type assertion at the boundary:
157
+
158
+ ```typescript
159
+ // Type assertion to PgTable is safe: EntitySchema extends TTableSchemaWithId which extends PgTable
160
+ const table = schema as unknown as PgTable;
161
+ let query = this.connector.select().from(table).$dynamic();
162
+ ```
163
+
164
+ This approach:
165
+ - Maintains type safety within the method
166
+ - Uses `$dynamic()` for query building with proper types
167
+ - Returns correctly typed `Promise<Array<DataObject>>`
168
+
169
+ ## Files Changed
170
+
171
+ ### Core Package - Repositories
172
+ - `packages/core/src/base/repositories/operators/filter.ts` - WeakMap cache for `getTableColumns()`
173
+ - `packages/core/src/base/repositories/core/readable.ts` - Core API optimization, async/await refactor
174
+ - `packages/core/src/base/repositories/core/persistable.ts` - Async/await refactor
175
+
176
+ ### Core Package - Models
177
+ - `packages/core/src/base/models/base.ts` - Static schemaFactory singleton
178
+
179
+ ## Benchmarks
180
+
181
+ These optimizations target the following scenarios:
182
+
183
+ | Scenario | Improvement |
184
+ |----------|-------------|
185
+ | Simple `find()` queries | ~15-20% faster (Core API) |
186
+ | Repeated filter builds | Eliminates reflection overhead (WeakMap) |
187
+ | Entity instantiation | Reduced memory per instance (schemaFactory) |
188
+ | All CRUD operations | Reduced GC pressure (async/await) |
189
+
190
+ ## No Breaking Changes
191
+
192
+ All changes are internal optimizations. No API changes or migration required.
@@ -0,0 +1,445 @@
1
+ # Changelog - 2025-12-18
2
+
3
+ ## Repository Validation & Security Improvements
4
+
5
+ This update adds strict validation to the `@repository` decorator and fixes several security vulnerabilities in the filter operators.
6
+
7
+ ## Overview
8
+
9
+ - **@repository Decorator**: Now requires both `model` AND `dataSource` for schema auto-discovery
10
+ - **Constructor Validation**: First parameter must extend `AbstractDataSource` (enforced via reflection)
11
+ - **DataSource Auto-Discovery**: Schema is automatically built from `@repository` bindings - no manual merging needed!
12
+ - **Filter Security**: Fixed empty IN array bypass, invalid column handling, BETWEEN validation
13
+ - **PostgreSQL Compatibility**: REGEXP now uses PostgreSQL POSIX operators
14
+ - **UUID Generation**: Now uses native PostgreSQL `uuid` type with `gen_random_uuid()`
15
+
16
+ ## Breaking Changes
17
+
18
+ ### 1. Repository Constructor Signature Changed
19
+
20
+ **This is a major breaking change.** The constructor signature for all repository classes has changed.
21
+
22
+ **Before:**
23
+ ```typescript
24
+ constructor(opts: {
25
+ entityClass: TClass<BaseEntity<EntitySchema>>;
26
+ relations: { [relationName: string]: TRelationConfig };
27
+ dataSource: IDataSource;
28
+ })
29
+ ```
30
+
31
+ **After:**
32
+ ```typescript
33
+ constructor(ds?: IDataSource, opts?: { entityClass?: TClass<BaseEntity<EntitySchema>> })
34
+ ```
35
+
36
+ **Key changes:**
37
+ - DataSource is now the first parameter (auto-injected from `@repository` decorator)
38
+ - `relations` parameter removed - now auto-resolved from entity's static `relations` property
39
+ - Both parameters are optional when using `@repository` decorator with `model` and `dataSource`
40
+
41
+ **Migration:**
42
+ ```typescript
43
+ // Before
44
+ @repository({})
45
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
46
+ constructor(
47
+ @inject({ key: 'datasources.PostgresDataSource' }) ds: PostgresDataSource,
48
+ ) {
49
+ super({
50
+ entityClass: User,
51
+ relations: userRelations.definitions,
52
+ dataSource: ds,
53
+ });
54
+ }
55
+ }
56
+
57
+ // After - Zero boilerplate
58
+ @repository({ model: User, dataSource: PostgresDataSource })
59
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
60
+ // No constructor needed!
61
+ }
62
+
63
+ // After - With explicit constructor
64
+ @repository({ model: User, dataSource: PostgresDataSource })
65
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
66
+ constructor(
67
+ @inject({ key: 'datasources.PostgresDataSource' }) ds: PostgresDataSource,
68
+ ) {
69
+ super(ds); // Just pass dataSource, entity and relations auto-resolved
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### 2. @repository Decorator Requires Both `model` AND `dataSource`
75
+
76
+ **Before (would silently fail to register model):**
77
+ ```typescript
78
+ // ❌ This would not register User for schema auto-discovery
79
+ @repository({ model: User })
80
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
81
+ ```
82
+
83
+ **After (throws error):**
84
+ ```typescript
85
+ // Error: [@repository][UserRepository] Invalid metadata | Missing 'dataSource'
86
+ @repository({ model: User })
87
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
88
+
89
+ // ✅ Correct usage
90
+ @repository({ model: User, dataSource: PostgresDataSource })
91
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
92
+ ```
93
+
94
+ ### 2. Constructor First Parameter Must Be DataSource Type
95
+
96
+ When using explicit `@inject` in constructor, the first parameter **must** extend `AbstractDataSource`:
97
+
98
+ **Before (would work with wrong type):**
99
+ ```typescript
100
+ @repository({ model: User, dataSource: PostgresDataSource })
101
+ export class UserRepository extends ReadableRepository<typeof User.schema> {
102
+ constructor(
103
+ @inject({ key: 'datasources.PostgresDataSource' })
104
+ dataSource: any, // ❌ This would compile but is wrong
105
+ ) {
106
+ super(dataSource);
107
+ }
108
+ }
109
+ ```
110
+
111
+ **After (enforced at decorator time):**
112
+ ```typescript
113
+ @repository({ model: User, dataSource: PostgresDataSource })
114
+ export class UserRepository extends ReadableRepository<typeof User.schema> {
115
+ constructor(
116
+ @inject({ key: 'datasources.PostgresDataSource' })
117
+ dataSource: PostgresDataSource, // ✅ Must be concrete DataSource type
118
+ ) {
119
+ super(dataSource);
120
+ }
121
+ }
122
+ ```
123
+
124
+ ### 3. Filter Column Validation
125
+
126
+ Invalid column names now throw errors instead of being silently ignored:
127
+
128
+ **Before:**
129
+ ```typescript
130
+ // Would silently ignore 'invalidColumn'
131
+ await repo.find({ filter: { where: { invalidColumn: 'value' } } });
132
+ ```
133
+
134
+ **After:**
135
+ ```typescript
136
+ // Error: [toWhere] Table: User | Column NOT FOUND | key: 'invalidColumn'
137
+ await repo.find({ filter: { where: { invalidColumn: 'value' } } });
138
+ ```
139
+
140
+ ## Security Fixes
141
+
142
+ ### Empty IN Array Bypass (CVE-like)
143
+
144
+ **Vulnerability:** Empty `IN` arrays would return `true`, bypassing security filters.
145
+
146
+ **Fix:** Empty `IN` arrays now return `sql\`false\``, correctly matching no records.
147
+
148
+ ```typescript
149
+ // Before: WHERE id IN () => true (security bypass!)
150
+ // After: WHERE false => no records (correct)
151
+ await repo.find({ filter: { where: { id: { IN: [] } } } });
152
+ ```
153
+
154
+ ### BETWEEN Validation
155
+
156
+ **Vulnerability:** Invalid `BETWEEN` values could cause unexpected behavior.
157
+
158
+ **Fix:** BETWEEN now validates input is array of exactly 2 elements.
159
+
160
+ ```typescript
161
+ // Throws: [BETWEEN] Invalid value: expected array of 2 elements
162
+ await repo.find({ filter: { where: { age: { BETWEEN: [10] } } } });
163
+ ```
164
+
165
+ ### PostgreSQL REGEXP Compatibility
166
+
167
+ **Issue:** MySQL-style REGEXP operator doesn't work in PostgreSQL.
168
+
169
+ **Fix:** Now uses PostgreSQL POSIX regex operators:
170
+ - `REGEXP` → `~` (case-sensitive)
171
+ - `IREGEXP` → `~*` (case-insensitive, new!)
172
+
173
+ ```typescript
174
+ // PostgreSQL-compatible regex
175
+ await repo.find({ filter: { where: { name: { REGEXP: '^John' } } } });
176
+ await repo.find({ filter: { where: { name: { IREGEXP: '^john' } } } }); // Case-insensitive
177
+ ```
178
+
179
+ ## New Features
180
+
181
+ ### DataSource Schema Auto-Discovery
182
+
183
+ DataSources can now automatically discover their schema from registered `@repository` decorators:
184
+
185
+ ```typescript
186
+ // Before: Manual schema merging required
187
+ @datasource({ driver: 'node-postgres' })
188
+ export class PostgresDataSource extends BaseDataSource<...> {
189
+ constructor() {
190
+ super({
191
+ name: PostgresDataSource.name,
192
+ config: { /* ... */ },
193
+ schema: Object.assign({}, // Manual merge!
194
+ { [User.TABLE_NAME]: userTable },
195
+ userRelations.relations,
196
+ ),
197
+ });
198
+ }
199
+ }
200
+
201
+ // After: Auto-discovery - no schema needed!
202
+ @datasource({ driver: 'node-postgres' })
203
+ export class PostgresDataSource extends BaseDataSource<...> {
204
+ constructor() {
205
+ super({
206
+ name: PostgresDataSource.name,
207
+ config: { /* ... */ },
208
+ // Schema auto-discovered from @repository decorators!
209
+ });
210
+ }
211
+ }
212
+ ```
213
+
214
+ When repositories are defined with `@repository({ model: User, dataSource: PostgresDataSource })`, the framework automatically builds the schema.
215
+
216
+ ### Schema Key Mismatch Validation
217
+
218
+ Added helpful error when entity name doesn't match schema keys:
219
+
220
+ ```typescript
221
+ // Error: [UserRepository] Schema key mismatch | Entity name 'User' not found in connector.query | Available keys: [Configuration, Post]
222
+ ```
223
+
224
+ ### UUID Type Improvement
225
+
226
+ Changed from `text` type with JS-generated UUID to native PostgreSQL `uuid`:
227
+
228
+ ```typescript
229
+ // Before: text('id').primaryKey().$defaultFn(() => crypto.randomUUID())
230
+ // After: uuid('id').defaultRandom().primaryKey()
231
+ ```
232
+
233
+ Benefits:
234
+ - Native PostgreSQL UUID type (16 bytes vs 36 bytes)
235
+ - Uses `gen_random_uuid()` - no extension required
236
+ - Better indexing performance
237
+
238
+ ### Case-Insensitive REGEXP (IREGEXP)
239
+
240
+ Added new `IREGEXP` operator for case-insensitive regex matching:
241
+
242
+ ```typescript
243
+ // Case-sensitive (existing)
244
+ await repo.find({ filter: { where: { name: { REGEXP: '^John' } } } });
245
+
246
+ // Case-insensitive (new!)
247
+ await repo.find({ filter: { where: { name: { IREGEXP: '^john' } } } });
248
+ ```
249
+
250
+ ### BaseEntity Static Schema & Relations
251
+
252
+ Models can now define schema and relations as static properties, enabling cleaner syntax:
253
+
254
+ ```typescript
255
+ // Before - Constructor-based schema
256
+ @model({ type: 'entity' })
257
+ export class User extends BaseEntity<typeof userTable> {
258
+ constructor() {
259
+ super({ name: 'User', schema: userTable });
260
+ }
261
+ }
262
+
263
+ // After - Static schema (recommended)
264
+ @model({ type: 'entity' })
265
+ export class User extends BaseEntity<typeof User.schema> {
266
+ static override schema = userTable;
267
+ static override relations = () => userRelations.definitions;
268
+ static override TABLE_NAME = 'User';
269
+ }
270
+ ```
271
+
272
+ Relations are now auto-resolved from the entity's static `relations` property - no need to pass them in repository constructor.
273
+
274
+ ### Repository Log Option
275
+
276
+ All CRUD operations now support a `log` option for debugging:
277
+
278
+ ```typescript
279
+ // Enable logging for a specific operation
280
+ await repo.create({
281
+ data: { name: 'John' },
282
+ options: {
283
+ log: { use: true, level: 'debug' }
284
+ }
285
+ });
286
+
287
+ // Log output: [_create] Executing with opts: { data: [...], options: {...} }
288
+ ```
289
+
290
+ **Available on:** `create`, `createAll`, `updateById`, `updateAll`, `deleteById`, `deleteAll`
291
+
292
+ ### Improved TypeScript Return Types
293
+
294
+ Repository methods now have better type inference based on `shouldReturn`:
295
+
296
+ ```typescript
297
+ // When shouldReturn: false - returns null
298
+ const result1 = await repo.create({
299
+ data: { name: 'John' },
300
+ options: { shouldReturn: false }
301
+ });
302
+ // Type: Promise<TCount & { data: null }>
303
+
304
+ // When shouldReturn: true (default) - returns the entity
305
+ const result2 = await repo.create({
306
+ data: { name: 'John' },
307
+ options: { shouldReturn: true }
308
+ });
309
+ // Type: Promise<TCount & { data: User }>
310
+
311
+ // TypeScript now correctly infers the return type!
312
+ ```
313
+
314
+ ### IEntity Interface
315
+
316
+ New interface for model classes with static schema and relations:
317
+
318
+ ```typescript
319
+ interface IEntity<Schema extends TTableSchemaWithId = TTableSchemaWithId> {
320
+ TABLE_NAME?: string;
321
+ schema: Schema;
322
+ relations?: TValueOrResolver<Array<TRelationConfig>>;
323
+ }
324
+ ```
325
+
326
+ ## Files Changed
327
+
328
+ ### Core Package - Models
329
+ - `packages/core/src/base/models/base.ts` - Static schema/relations support, IEntity interface
330
+ - `packages/core/src/base/models/common/types.ts` - IEntity interface definition
331
+ - `packages/core/src/base/models/enrichers/id.enricher.ts` - Native PostgreSQL UUID type
332
+ - `packages/core/src/base/models/enrichers/tz.enricher.ts` - Type naming fix
333
+
334
+ ### Core Package - Repositories
335
+ - `packages/core/src/base/repositories/core/base.ts` - Constructor signature change, relations auto-resolution
336
+ - `packages/core/src/base/repositories/core/readable.ts` - Constructor change, getQueryInterface validation
337
+ - `packages/core/src/base/repositories/core/persistable.ts` - Constructor change, log option, TypeScript overloads
338
+ - `packages/core/src/base/repositories/core/default-crud.ts` - Documentation update
339
+ - `packages/core/src/base/repositories/common/types.ts` - TRepositoryLogOptions, TypeScript overloads
340
+ - `packages/core/src/base/repositories/operators/filter.ts` - Column validation, error throwing
341
+ - `packages/core/src/base/repositories/operators/query.ts` - REGEXP/IREGEXP fix, BETWEEN validation, IN empty array fix
342
+
343
+ ### Core Package - DataSources & Metadata
344
+ - `packages/core/src/base/datasources/base.ts` - Schema auto-discovery feature
345
+ - `packages/core/src/base/metadata/persistents.ts` - Repository decorator validation, constructor type validation
346
+
347
+ ### Examples
348
+ - `examples/vert/src/repositories/user.repository.ts` - Updated to proper types
349
+ - `examples/vert/src/repositories/configuration.repository.ts` - Updated patterns
350
+ - `examples/vert/src/datasources/postgres.datasource.ts` - Using auto-discovery
351
+ - `examples/vert/src/models/entities/user.model.ts` - Static schema pattern
352
+ - `examples/vert/src/models/entities/configuration.model.ts` - Static schema pattern
353
+
354
+ ## Migration Guide
355
+
356
+ ### Step 1: Update Repository Constructors (BREAKING)
357
+
358
+ The repository constructor signature has changed:
359
+
360
+ ```typescript
361
+ // Before
362
+ @repository({})
363
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
364
+ constructor(
365
+ @inject({ key: 'datasources.PostgresDataSource' }) ds: PostgresDataSource,
366
+ ) {
367
+ super({
368
+ entityClass: User,
369
+ relations: userRelations.definitions,
370
+ dataSource: ds,
371
+ });
372
+ }
373
+ }
374
+
375
+ // After - Option A: Zero boilerplate (recommended)
376
+ @repository({ model: User, dataSource: PostgresDataSource })
377
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
378
+ // No constructor needed!
379
+ }
380
+
381
+ // After - Option B: With explicit constructor
382
+ @repository({ model: User, dataSource: PostgresDataSource })
383
+ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
384
+ constructor(
385
+ @inject({ key: 'datasources.PostgresDataSource' }) ds: PostgresDataSource,
386
+ ) {
387
+ super(ds); // Just pass dataSource
388
+ }
389
+ }
390
+ ```
391
+
392
+ ### Step 2: Update Model Definitions (Optional but Recommended)
393
+
394
+ Add static properties to your models for relations auto-resolution:
395
+
396
+ ```typescript
397
+ // Before
398
+ @model({ type: 'entity' })
399
+ export class User extends BaseEntity<typeof userTable> {
400
+ constructor() {
401
+ super({ name: 'User', schema: userTable });
402
+ }
403
+ }
404
+
405
+ // After - Static properties
406
+ @model({ type: 'entity' })
407
+ export class User extends BaseEntity<typeof User.schema> {
408
+ static override schema = userTable;
409
+ static override relations = () => userRelations.definitions;
410
+ static override TABLE_NAME = 'User';
411
+ }
412
+ ```
413
+
414
+ ### Step 3: Update @repository Decorators
415
+
416
+ Ensure all `@repository` decorators have both `model` and `dataSource`:
417
+
418
+ ```typescript
419
+ // Find and update all occurrences
420
+ @repository({ model: YourModel, dataSource: YourDataSource })
421
+ ```
422
+
423
+ ### Step 4: Fix Constructor Types
424
+
425
+ If using explicit `@inject`, ensure first parameter has correct type:
426
+
427
+ ```typescript
428
+ constructor(
429
+ @inject({ key: 'datasources.YourDataSource' })
430
+ dataSource: YourDataSource, // Not 'any' or 'object'
431
+ ) {}
432
+ ```
433
+
434
+ ### Step 5: Review Filter Queries
435
+
436
+ Check for any queries using:
437
+ - Empty `IN` arrays (now return no results instead of all)
438
+ - Invalid column names (now throw errors)
439
+ - `BETWEEN` with non-array or wrong-length values
440
+
441
+ ### Step 6: REGEXP Migration (PostgreSQL Users)
442
+
443
+ Replace MySQL-style REGEXP with PostgreSQL syntax:
444
+ - REGEXP already works (uses `~` operator)
445
+ - For case-insensitive, use new `IREGEXP` (uses `~*` operator)
@@ -0,0 +1,22 @@
1
+ # Changelogs
2
+
3
+ This section tracks the history of significant changes, refactors, and updates to the Ignis framework.
4
+
5
+ ## Version History
6
+
7
+ | Version | Date | Description |
8
+ |---------|------|-------------|
9
+ | [2025-12-18 Performance](./2025-12-18-performance-optimizations.md) | 2025-12-18 | Performance Optimizations (Core API, WeakMap Cache) |
10
+ | [2025-12-18](./2025-12-18-repository-validation-security.md) | 2025-12-18 | Repository Validation & Security Improvements |
11
+ | [2025-12-17](./2025-12-17-refactor.md) | 2025-12-17 | Inversion of Control Refactor |
12
+ | [v0.0.1-8](./v0.0.1-8-model-repo-datasource-refactor.md) | 2025-12-16 | Model-Repository-DataSource Architecture Refactor |
13
+ | [v0.0.1-7](./v0.0.1-7-initial-architecture.md) | 2025-12-16 | Initial Architecture (Pre-Refactor) |
14
+
15
+ ## How to Read Changelogs
16
+
17
+ Each changelog entry includes:
18
+ - **Overview**: Summary of changes
19
+ - **Breaking Changes**: Any changes that require migration
20
+ - **New Features**: New capabilities added
21
+ - **Files Changed**: List of modified files
22
+ - **Migration Guide**: Steps to update existing code (if applicable)