@venizia/ignis-docs 0.0.1-9 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -0
- package/package.json +2 -2
- package/wiki/changelogs/{v0.0.1-7-initial-architecture.md → 2025-12-16-initial-architecture.md} +20 -12
- package/wiki/changelogs/2025-12-16-model-repo-datasource-refactor.md +300 -0
- package/wiki/changelogs/2025-12-17-refactor.md +80 -12
- package/wiki/changelogs/2025-12-18-performance-optimizations.md +28 -90
- package/wiki/changelogs/2025-12-18-repository-validation-security.md +101 -297
- package/wiki/changelogs/index.md +19 -8
- package/wiki/changelogs/planned-transaction-support.md +216 -0
- package/wiki/changelogs/template.md +123 -0
- package/wiki/get-started/best-practices/api-usage-examples.md +0 -2
- package/wiki/get-started/best-practices/architectural-patterns.md +2 -2
- package/wiki/get-started/best-practices/common-pitfalls.md +5 -3
- package/wiki/get-started/best-practices/contribution-workflow.md +2 -0
- package/wiki/get-started/best-practices/data-modeling.md +91 -34
- package/wiki/get-started/best-practices/security-guidelines.md +3 -1
- package/wiki/get-started/building-a-crud-api.md +3 -3
- package/wiki/get-started/core-concepts/application.md +72 -3
- package/wiki/get-started/core-concepts/bootstrapping.md +566 -0
- package/wiki/get-started/core-concepts/components.md +4 -2
- package/wiki/get-started/core-concepts/persistent.md +350 -378
- package/wiki/get-started/core-concepts/services.md +21 -27
- package/wiki/references/base/bootstrapping.md +789 -0
- package/wiki/references/base/components.md +1 -1
- package/wiki/references/base/dependency-injection.md +95 -2
- package/wiki/references/base/services.md +2 -2
- package/wiki/references/components/authentication.md +4 -3
- package/wiki/references/components/index.md +1 -1
- package/wiki/references/helpers/error.md +2 -2
- package/wiki/references/src-details/boot.md +379 -0
- package/wiki/references/src-details/core.md +2 -2
- package/wiki/changelogs/v0.0.1-8-model-repo-datasource-refactor.md +0 -278
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Repository Validation & Security
|
|
3
|
+
description: Strict validation for @repository decorator and security fixes for filter operators
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Changelog - 2025-12-18
|
|
2
7
|
|
|
3
8
|
## Repository Validation & Security Improvements
|
|
@@ -6,18 +11,19 @@ This update adds strict validation to the `@repository` decorator and fixes seve
|
|
|
6
11
|
|
|
7
12
|
## Overview
|
|
8
13
|
|
|
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
|
|
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()
|
|
14
|
+
- **@repository Decorator**: Now requires both `model` AND `dataSource` for schema auto-discovery.
|
|
15
|
+
- **Constructor Validation**: First parameter must extend `AbstractDataSource` (enforced via reflection).
|
|
16
|
+
- **DataSource Auto-Discovery**: Schema is automatically built from `@repository` bindings.
|
|
17
|
+
- **Filter Security**: Fixed empty IN array bypass, invalid column handling, BETWEEN validation.
|
|
18
|
+
- **PostgreSQL Compatibility**: REGEXP now uses PostgreSQL POSIX operators.
|
|
19
|
+
- **UUID Generation**: Now uses native PostgreSQL `uuid` type with `gen_random_uuid()`.
|
|
15
20
|
|
|
16
21
|
## Breaking Changes
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
> [!WARNING]
|
|
24
|
+
> This section contains changes that require migration or manual updates to existing code.
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
### 1. Repository Constructor Signature
|
|
21
27
|
|
|
22
28
|
**Before:**
|
|
23
29
|
```typescript
|
|
@@ -33,101 +39,49 @@ constructor(opts: {
|
|
|
33
39
|
constructor(ds?: IDataSource, opts?: { entityClass?: TClass<BaseEntity<EntitySchema>> })
|
|
34
40
|
```
|
|
35
41
|
|
|
36
|
-
|
|
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`
|
|
42
|
+
### 2. @repository Decorator Requirements
|
|
75
43
|
|
|
76
|
-
**Before
|
|
44
|
+
**Before:**
|
|
77
45
|
```typescript
|
|
78
|
-
//
|
|
46
|
+
// Would silently fail to register model
|
|
79
47
|
@repository({ model: User })
|
|
80
48
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
81
49
|
```
|
|
82
50
|
|
|
83
|
-
**After
|
|
51
|
+
**After:**
|
|
84
52
|
```typescript
|
|
85
|
-
// Error:
|
|
53
|
+
// Throws Error: Invalid metadata | Missing 'dataSource'
|
|
86
54
|
@repository({ model: User })
|
|
87
55
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
88
56
|
|
|
89
|
-
//
|
|
57
|
+
// Correct
|
|
90
58
|
@repository({ model: User, dataSource: PostgresDataSource })
|
|
91
59
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
92
60
|
```
|
|
93
61
|
|
|
94
|
-
###
|
|
95
|
-
|
|
96
|
-
When using explicit `@inject` in constructor, the first parameter **must** extend `AbstractDataSource`:
|
|
62
|
+
### 3. Constructor Parameter Type
|
|
97
63
|
|
|
98
|
-
**Before
|
|
64
|
+
**Before:**
|
|
99
65
|
```typescript
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
dataSource: any, // ❌ This would compile but is wrong
|
|
105
|
-
) {
|
|
106
|
-
super(dataSource);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
66
|
+
constructor(
|
|
67
|
+
@inject({ key: 'datasources.PostgresDataSource' })
|
|
68
|
+
dataSource: any, // Would compile but is wrong
|
|
69
|
+
)
|
|
109
70
|
```
|
|
110
71
|
|
|
111
|
-
**After
|
|
72
|
+
**After:**
|
|
112
73
|
```typescript
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
dataSource: PostgresDataSource, // ✅ Must be concrete DataSource type
|
|
118
|
-
) {
|
|
119
|
-
super(dataSource);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
74
|
+
constructor(
|
|
75
|
+
@inject({ key: 'datasources.PostgresDataSource' })
|
|
76
|
+
dataSource: PostgresDataSource, // Must be concrete DataSource type
|
|
77
|
+
)
|
|
122
78
|
```
|
|
123
79
|
|
|
124
|
-
###
|
|
125
|
-
|
|
126
|
-
Invalid column names now throw errors instead of being silently ignored:
|
|
80
|
+
### 4. Filter Column Validation
|
|
127
81
|
|
|
128
82
|
**Before:**
|
|
129
83
|
```typescript
|
|
130
|
-
//
|
|
84
|
+
// Silently ignored 'invalidColumn'
|
|
131
85
|
await repo.find({ filter: { where: { invalidColumn: 'value' } } });
|
|
132
86
|
```
|
|
133
87
|
|
|
@@ -137,68 +91,17 @@ await repo.find({ filter: { where: { invalidColumn: 'value' } } });
|
|
|
137
91
|
await repo.find({ filter: { where: { invalidColumn: 'value' } } });
|
|
138
92
|
```
|
|
139
93
|
|
|
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
94
|
## New Features
|
|
180
95
|
|
|
181
96
|
### DataSource Schema Auto-Discovery
|
|
182
97
|
|
|
183
|
-
|
|
98
|
+
**File:** `packages/core/src/base/datasources/base.ts`
|
|
184
99
|
|
|
185
|
-
|
|
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
|
-
}
|
|
100
|
+
**Problem:** Manual schema merging was error-prone and verbose.
|
|
200
101
|
|
|
201
|
-
|
|
102
|
+
**Solution:** DataSources automatically discover their schema from `@repository` bindings.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
202
105
|
@datasource({ driver: 'node-postgres' })
|
|
203
106
|
export class PostgresDataSource extends BaseDataSource<...> {
|
|
204
107
|
constructor() {
|
|
@@ -211,174 +114,114 @@ export class PostgresDataSource extends BaseDataSource<...> {
|
|
|
211
114
|
}
|
|
212
115
|
```
|
|
213
116
|
|
|
214
|
-
|
|
117
|
+
### UUID Type Improvement
|
|
215
118
|
|
|
216
|
-
|
|
119
|
+
**File:** `packages/core/src/base/models/enrichers/id.enricher.ts`
|
|
217
120
|
|
|
218
|
-
|
|
121
|
+
**Problem:** JS-generated UUIDs were stored as text, which is less efficient.
|
|
219
122
|
|
|
220
|
-
|
|
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`:
|
|
123
|
+
**Solution:** Changed to native PostgreSQL `uuid` type with `gen_random_uuid()`.
|
|
227
124
|
|
|
228
125
|
```typescript
|
|
229
|
-
// Before: text('id').primaryKey().$defaultFn(() => crypto.randomUUID())
|
|
230
126
|
// After: uuid('id').defaultRandom().primaryKey()
|
|
231
127
|
```
|
|
232
128
|
|
|
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
129
|
### Case-Insensitive REGEXP (IREGEXP)
|
|
239
130
|
|
|
240
|
-
|
|
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
|
-
```
|
|
131
|
+
**File:** `packages/core/src/base/repositories/operators/query.ts`
|
|
249
132
|
|
|
250
|
-
|
|
133
|
+
**Problem:** PostgreSQL regex matching is case-sensitive by default.
|
|
251
134
|
|
|
252
|
-
|
|
135
|
+
**Solution:** Added `IREGEXP` operator for case-insensitive matching (`~*`).
|
|
253
136
|
|
|
254
137
|
```typescript
|
|
255
|
-
|
|
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
|
-
}
|
|
138
|
+
await repo.find({ filter: { where: { name: { IREGEXP: '^john' } } } });
|
|
270
139
|
```
|
|
271
140
|
|
|
272
|
-
Relations are now auto-resolved from the entity's static `relations` property - no need to pass them in repository constructor.
|
|
273
|
-
|
|
274
141
|
### Repository Log Option
|
|
275
142
|
|
|
276
|
-
|
|
143
|
+
**File:** `packages/core/src/base/repositories/core/persistable.ts`
|
|
144
|
+
|
|
145
|
+
**Problem:** Debugging repository operations was difficult without logging.
|
|
146
|
+
|
|
147
|
+
**Solution:** Added `log` option to all CRUD operations.
|
|
277
148
|
|
|
278
149
|
```typescript
|
|
279
|
-
// Enable logging for a specific operation
|
|
280
150
|
await repo.create({
|
|
281
151
|
data: { name: 'John' },
|
|
282
152
|
options: {
|
|
283
153
|
log: { use: true, level: 'debug' }
|
|
284
154
|
}
|
|
285
155
|
});
|
|
286
|
-
|
|
287
|
-
// Log output: [_create] Executing with opts: { data: [...], options: {...} }
|
|
288
156
|
```
|
|
289
157
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
### Improved TypeScript Return Types
|
|
158
|
+
## Security Fixes
|
|
293
159
|
|
|
294
|
-
|
|
160
|
+
### Empty IN Array Bypass
|
|
295
161
|
|
|
296
|
-
|
|
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 }>
|
|
162
|
+
**Vulnerability:** Empty `IN` arrays would return `true`, bypassing security filters.
|
|
303
163
|
|
|
304
|
-
|
|
305
|
-
const result2 = await repo.create({
|
|
306
|
-
data: { name: 'John' },
|
|
307
|
-
options: { shouldReturn: true }
|
|
308
|
-
});
|
|
309
|
-
// Type: Promise<TCount & { data: User }>
|
|
164
|
+
**Fix:** Empty `IN` arrays now return `sql\`false\``.
|
|
310
165
|
|
|
311
|
-
|
|
166
|
+
```typescript
|
|
167
|
+
// Before: WHERE id IN () => true (bypass)
|
|
168
|
+
// After: WHERE false => no records
|
|
169
|
+
await repo.find({ filter: { where: { id: { IN: [] } } } });
|
|
312
170
|
```
|
|
313
171
|
|
|
314
|
-
###
|
|
172
|
+
### BETWEEN Validation
|
|
173
|
+
|
|
174
|
+
**Vulnerability:** Invalid `BETWEEN` values could cause unexpected behavior.
|
|
315
175
|
|
|
316
|
-
|
|
176
|
+
**Fix:** `BETWEEN` now validates input is an array of exactly 2 elements.
|
|
317
177
|
|
|
318
178
|
```typescript
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
schema: Schema;
|
|
322
|
-
relations?: TValueOrResolver<Array<TRelationConfig>>;
|
|
323
|
-
}
|
|
179
|
+
// Throws: [BETWEEN] Invalid value: expected array of 2 elements
|
|
180
|
+
await repo.find({ filter: { where: { age: { BETWEEN: [10] } } } });
|
|
324
181
|
```
|
|
325
182
|
|
|
326
183
|
## Files Changed
|
|
327
184
|
|
|
328
|
-
### Core Package
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
###
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
|
185
|
+
### Core Package (`packages/core`)
|
|
186
|
+
|
|
187
|
+
| File | Changes |
|
|
188
|
+
|------|---------|
|
|
189
|
+
| `src/base/models/base.ts` | Static schema/relations support, IEntity interface |
|
|
190
|
+
| `src/base/models/common/types.ts` | IEntity interface definition |
|
|
191
|
+
| `src/base/models/enrichers/id.enricher.ts` | Native PostgreSQL UUID type |
|
|
192
|
+
| `src/base/repositories/core/base.ts` | Constructor signature change, relations auto-resolution |
|
|
193
|
+
| `src/base/repositories/core/readable.ts` | Constructor change, getQueryInterface validation |
|
|
194
|
+
| `src/base/repositories/core/persistable.ts` | Constructor change, log option, TypeScript overloads |
|
|
195
|
+
| `src/base/repositories/operators/filter.ts` | Column validation, error throwing |
|
|
196
|
+
| `src/base/repositories/operators/query.ts` | REGEXP/IREGEXP fix, BETWEEN validation, IN empty array fix |
|
|
197
|
+
| `src/base/datasources/base.ts` | Schema auto-discovery feature |
|
|
198
|
+
| `src/base/metadata/persistents.ts` | Repository decorator validation, constructor type validation |
|
|
199
|
+
|
|
200
|
+
### Examples (`examples/vert`)
|
|
201
|
+
|
|
202
|
+
| File | Changes |
|
|
203
|
+
|------|---------|
|
|
204
|
+
| `src/repositories/user.repository.ts` | Updated to proper types |
|
|
205
|
+
| `src/repositories/configuration.repository.ts` | Updated patterns |
|
|
206
|
+
| `src/datasources/postgres.datasource.ts` | Using auto-discovery |
|
|
353
207
|
|
|
354
208
|
## Migration Guide
|
|
355
209
|
|
|
356
|
-
|
|
210
|
+
> [!NOTE]
|
|
211
|
+
> Follow these steps if you're upgrading from a previous version.
|
|
357
212
|
|
|
358
|
-
|
|
213
|
+
### Step 1: Update Repository Constructors
|
|
359
214
|
|
|
360
|
-
|
|
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
|
-
}
|
|
215
|
+
The repository constructor signature has changed. Update all repository classes.
|
|
374
216
|
|
|
375
|
-
|
|
217
|
+
```typescript
|
|
218
|
+
// Option A: Zero boilerplate (recommended)
|
|
376
219
|
@repository({ model: User, dataSource: PostgresDataSource })
|
|
377
220
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
|
|
378
221
|
// No constructor needed!
|
|
379
222
|
}
|
|
380
223
|
|
|
381
|
-
//
|
|
224
|
+
// Option B: With explicit constructor
|
|
382
225
|
@repository({ model: User, dataSource: PostgresDataSource })
|
|
383
226
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
|
|
384
227
|
constructor(
|
|
@@ -389,57 +232,18 @@ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
|
|
|
389
232
|
}
|
|
390
233
|
```
|
|
391
234
|
|
|
392
|
-
### Step 2: Update
|
|
235
|
+
### Step 2: Update @repository Decorators
|
|
393
236
|
|
|
394
|
-
|
|
237
|
+
Ensure all `@repository` decorators have both `model` and `dataSource`.
|
|
395
238
|
|
|
396
239
|
```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
240
|
@repository({ model: YourModel, dataSource: YourDataSource })
|
|
421
241
|
```
|
|
422
242
|
|
|
423
|
-
### Step
|
|
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)
|
|
243
|
+
### Step 3: REGEXP Migration (PostgreSQL Users)
|
|
442
244
|
|
|
443
245
|
Replace MySQL-style REGEXP with PostgreSQL syntax:
|
|
444
|
-
- REGEXP
|
|
445
|
-
-
|
|
246
|
+
- `REGEXP` → uses `~` (case-sensitive)
|
|
247
|
+
- `IREGEXP` → uses `~*` (case-insensitive)
|
|
248
|
+
|
|
249
|
+
```
|
package/wiki/changelogs/index.md
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Changelogs
|
|
3
|
+
description: History of significant changes, refactors, and updates to the Ignis framework
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Changelogs
|
|
2
7
|
|
|
3
8
|
This section tracks the history of significant changes, refactors, and updates to the Ignis framework.
|
|
4
9
|
|
|
5
|
-
##
|
|
10
|
+
## Planned Features
|
|
11
|
+
|
|
12
|
+
| Feature | Description | Priority |
|
|
13
|
+
|---------|-------------|----------|
|
|
14
|
+
| [Transaction Support](./planned-transaction-support) | Loopback 4-style explicit transaction objects with isolation levels | Future |
|
|
15
|
+
|
|
16
|
+
## Recent Changes
|
|
6
17
|
|
|
7
|
-
|
|
|
8
|
-
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
| [
|
|
13
|
-
|
|
|
18
|
+
| Date | Title | Type |
|
|
19
|
+
|------|-------|------|
|
|
20
|
+
| 2025-12-18 | [Performance Optimizations](./2025-12-18-performance-optimizations) | Enhancement |
|
|
21
|
+
| 2025-12-18 | [Repository Validation & Security](./2025-12-18-repository-validation-security) | Breaking Change, Security |
|
|
22
|
+
| 2025-12-17 | [Inversion of Control Refactor](./2025-12-17-refactor) | Refactor |
|
|
23
|
+
| 2025-12-16 | [Model-Repository-DataSource Refactor](./2025-12-16-model-repo-datasource-refactor) | Breaking Change |
|
|
24
|
+
| 2025-12-16 | [Initial Architecture](./2025-12-16-initial-architecture) | Documentation |
|
|
14
25
|
|
|
15
26
|
## How to Read Changelogs
|
|
16
27
|
|