@venizia/ignis-docs 0.2.0 → 0.2.1-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.
- package/README.md +14 -14
- package/content/best-practices/api-usage-examples.md +39 -19
- package/content/best-practices/architectural-patterns.md +22 -11
- package/content/best-practices/architecture-decisions.md +29 -16
- package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
- package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
- package/content/best-practices/code-style-standards/control-flow.md +33 -1
- package/content/best-practices/code-style-standards/documentation.md +28 -8
- package/content/best-practices/code-style-standards/function-patterns.md +15 -4
- package/content/best-practices/code-style-standards/index.md +7 -2
- package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
- package/content/best-practices/code-style-standards/route-definitions.md +9 -5
- package/content/best-practices/code-style-standards/tooling.md +14 -1
- package/content/best-practices/code-style-standards/type-safety.md +39 -6
- package/content/best-practices/common-pitfalls.md +59 -35
- package/content/best-practices/contribution-workflow.md +6 -2
- package/content/best-practices/data-modeling.md +78 -62
- package/content/best-practices/deployment-strategies.md +56 -19
- package/content/best-practices/error-handling.md +182 -93
- package/content/best-practices/index.md +6 -0
- package/content/best-practices/performance-optimization.md +26 -13
- package/content/best-practices/security-guidelines.md +35 -9
- package/content/best-practices/testing-strategies.md +7 -2
- package/content/best-practices/troubleshooting-tips.md +27 -17
- package/content/extensions/components/api-reference.md +107 -322
- package/content/extensions/components/authentication/api.md +454 -603
- package/content/extensions/components/authentication/errors.md +121 -498
- package/content/extensions/components/authentication/index.md +88 -801
- package/content/extensions/components/authentication/usage.md +207 -956
- package/content/extensions/components/authorization/api.md +736 -656
- package/content/extensions/components/authorization/errors.md +168 -206
- package/content/extensions/components/authorization/index.md +82 -797
- package/content/extensions/components/authorization/usage.md +194 -527
- package/content/extensions/components/health-check.md +71 -243
- package/content/extensions/components/mail/api.md +504 -287
- package/content/extensions/components/mail/errors.md +73 -61
- package/content/extensions/components/mail/index.md +96 -467
- package/content/extensions/components/mail/usage.md +130 -172
- package/content/extensions/components/request-tracker.md +66 -173
- package/content/extensions/components/socket-io/api.md +195 -13
- package/content/extensions/components/socket-io/errors.md +3 -3
- package/content/extensions/components/socket-io/index.md +50 -337
- package/content/extensions/components/socket-io/usage.md +143 -26
- package/content/extensions/components/static-asset/api.md +410 -142
- package/content/extensions/components/static-asset/errors.md +110 -53
- package/content/extensions/components/static-asset/index.md +79 -608
- package/content/extensions/components/static-asset/usage.md +180 -300
- package/content/extensions/components/websocket/api.md +275 -399
- package/content/extensions/components/websocket/errors.md +47 -56
- package/content/extensions/components/websocket/index.md +74 -407
- package/content/extensions/components/websocket/usage.md +110 -341
- package/content/extensions/helpers/cron/index.md +51 -160
- package/content/extensions/helpers/crypto/index.md +62 -483
- package/content/extensions/helpers/crypto/reference.md +456 -0
- package/content/extensions/helpers/env/index.md +60 -178
- package/content/extensions/helpers/error/index.md +221 -207
- package/content/extensions/helpers/inversion/index.md +65 -556
- package/content/extensions/helpers/inversion/reference.md +522 -0
- package/content/extensions/helpers/kafka/admin.md +20 -1
- package/content/extensions/helpers/kafka/compile-binary.md +41 -35
- package/content/extensions/helpers/kafka/consumer.md +54 -20
- package/content/extensions/helpers/kafka/examples.md +21 -16
- package/content/extensions/helpers/kafka/index.md +80 -610
- package/content/extensions/helpers/kafka/producer.md +134 -5
- package/content/extensions/helpers/kafka/schema-registry.md +45 -70
- package/content/extensions/helpers/logger/hf-logger.md +193 -0
- package/content/extensions/helpers/logger/index.md +64 -563
- package/content/extensions/helpers/logger/pino.md +85 -0
- package/content/extensions/helpers/logger/reference.md +746 -0
- package/content/extensions/helpers/network/api.md +241 -195
- package/content/extensions/helpers/network/index.md +72 -530
- package/content/extensions/helpers/queue/index.md +72 -900
- package/content/extensions/helpers/queue/reference.md +467 -0
- package/content/extensions/helpers/redis/index.md +73 -645
- package/content/extensions/helpers/redis/reference.md +727 -0
- package/content/extensions/helpers/secrets/index.md +66 -0
- package/content/extensions/helpers/socket-io/api.md +305 -203
- package/content/extensions/helpers/socket-io/index.md +66 -432
- package/content/extensions/helpers/storage/api.md +564 -462
- package/content/extensions/helpers/storage/index.md +77 -573
- package/content/extensions/helpers/types/index.md +66 -499
- package/content/extensions/helpers/types/reference.md +650 -0
- package/content/extensions/helpers/uid/index.md +58 -227
- package/content/extensions/helpers/websocket/api.md +329 -216
- package/content/extensions/helpers/websocket/index.md +65 -503
- package/content/extensions/helpers/worker-thread/index.md +58 -396
- package/content/extensions/helpers/worker-thread/reference.md +428 -0
- package/content/guides/core-concepts/persistent/models.md +1 -1
- package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
- package/content/guides/core-concepts/persistent/transactions.md +1 -1
- package/content/guides/core-concepts/secrets-vault.md +177 -0
- package/content/guides/core-concepts/services.md +1 -1
- package/content/guides/migrations/redis-helpers-migration.md +1 -1
- package/content/guides/migrations/unified-connectors-migration.md +2 -2
- package/content/guides/tutorials/ecommerce-api.md +3 -8
- package/content/references/base/application.md +1 -1
- package/content/references/base/connectors.md +79 -136
- package/content/references/base/datasources-reference.md +599 -0
- package/content/references/base/datasources.md +84 -444
- package/content/references/base/dependency-injection.md +17 -39
- package/content/references/base/filter-system/application-usage.md +69 -121
- package/content/references/base/filter-system/array-operators.md +12 -0
- package/content/references/base/filter-system/comparison-operators.md +12 -0
- package/content/references/base/filter-system/default-filter.md +136 -348
- package/content/references/base/filter-system/fields-order-pagination.md +38 -16
- package/content/references/base/filter-system/index.md +106 -257
- package/content/references/base/filter-system/json-filtering.md +12 -2
- package/content/references/base/filter-system/list-operators.md +16 -2
- package/content/references/base/filter-system/logical-operators.md +13 -0
- package/content/references/base/filter-system/null-operators.md +13 -0
- package/content/references/base/filter-system/pattern-matching.md +12 -0
- package/content/references/base/filter-system/quick-reference.md +11 -2
- package/content/references/base/filter-system/range-operators.md +12 -0
- package/content/references/base/filter-system/tips.md +70 -133
- package/content/references/base/filter-system/use-cases.md +156 -233
- package/content/references/base/middlewares.md +35 -21
- package/content/references/base/models-reference.md +886 -0
- package/content/references/base/models.md +80 -1452
- package/content/references/base/repositories/advanced.md +156 -192
- package/content/references/base/repositories/index.md +77 -650
- package/content/references/base/repositories/mixins.md +22 -18
- package/content/references/base/repositories/relations.md +123 -171
- package/content/references/base/repositories/soft-deletable.md +58 -56
- package/content/references/base/secrets.md +263 -0
- package/content/references/base/services.md +2 -2
- package/content/references/configuration/environment-variables.md +48 -4
- package/content/references/configuration/index.md +49 -31
- package/content/references/quick-reference.md +3 -16
- package/content/references/utilities/crypto.md +35 -76
- package/content/references/utilities/date.md +33 -73
- package/content/references/utilities/index.md +1 -1
- package/content/references/utilities/jsx-reference.md +298 -0
- package/content/references/utilities/jsx.md +82 -525
- package/content/references/utilities/module.md +29 -62
- package/content/references/utilities/parse.md +34 -64
- package/content/references/utilities/performance.md +33 -58
- package/content/references/utilities/promise.md +28 -62
- package/content/references/utilities/request.md +57 -218
- package/content/references/utilities/schema.md +43 -137
- package/content/references/utilities/statuses-reference.md +361 -0
- package/content/references/utilities/statuses.md +63 -667
- package/package.json +8 -8
|
@@ -1,712 +1,139 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Repositories
|
|
3
|
+
description: The typed data-access object for one model - CRUD, filters, and transactions without hand-written SQL
|
|
4
|
+
difficulty: intermediate
|
|
5
|
+
---
|
|
2
6
|
|
|
3
|
-
Repositories
|
|
7
|
+
# Repositories
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
> `AbstractRepository` (`packages/core/src/base/repositories/core/abstract.ts`) is the engine-neutral root shared by both connectors - it declares the CRUD contract but has no Drizzle, SQL, or mixin composition. The concrete classes documented on this page (`ReadableRepository`, `PersistableRepository`, `DefaultCRUDRepository`, `SoftDeletableRepository`) belong to the **PostgreSQL connector**, built on `PostgresBaseRepository`. Typesense has its own parallel tier - see [Connectors](/references/base/connectors) and [Search & Typesense](/guides/core-concepts/persistent/search-typesense).
|
|
9
|
+
A repository is the typed data-access object for one model - it turns a `@model` schema into `find`, `create`, `updateById`, `deleteById`, and friends, with the query shape validated at compile time.
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
## In one example
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
If you're new to repositories, start here:
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
import { DefaultCRUDRepository, repository } from '@venizia/ignis';
|
|
17
|
-
import { Todo } from '@/models/todo.model';
|
|
18
|
-
import { PostgresDataSource } from '@/datasources/postgres.datasource';
|
|
19
|
-
|
|
20
|
-
@repository({ model: Todo, dataSource: PostgresDataSource })
|
|
21
|
-
export class TodoRepository extends DefaultCRUDRepository<typeof Todo.schema> {
|
|
22
|
-
// That's it! You get: find, findOne, create, updateById, deleteById, etc.
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## Repository Classes
|
|
28
|
-
|
|
29
|
-
| Class | Capabilities | Use Case |
|
|
30
|
-
|-------|--------------|----------|
|
|
31
|
-
| **AbstractRepository** | Engine-neutral base class with lazy dataSource/entity resolution and @model settings getters | Extend for custom repositories |
|
|
32
|
-
| **ReadableRepository** | Read-only operations (write methods throw errors) | Views, external tables, read-only access |
|
|
33
|
-
| **PersistableRepository** | Read + Write operations | Full CRUD access |
|
|
34
|
-
| **DefaultCRUDRepository** | Extends PersistableRepository (no additions) | Standard data tables (recommended) |
|
|
35
|
-
| **SoftDeletableRepository** | CRUD + soft delete + restore | Tables with `deletedAt` column |
|
|
36
|
-
|
|
37
|
-
**Most common:** Extend `DefaultCRUDRepository` for standard tables, or `SoftDeletableRepository` for soft-delete patterns.
|
|
38
|
-
|
|
39
|
-
### Hierarchy
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
BaseHelper
|
|
43
|
-
= AbstractRepository (engine-neutral abstract base, declares all CRUD signatures, src/base)
|
|
44
|
-
|
|
|
45
|
-
+-- PostgresBaseRepository (PostgreSQL connector; hidden-fields + default-filter logic, no mixins)
|
|
46
|
-
|
|
|
47
|
-
+-- ReadableRepository (implements read ops; write ops throw errors)
|
|
48
|
-
|
|
|
49
|
-
+-- PersistableRepository (implements write + delete ops, READ_WRITE scope)
|
|
50
|
-
|
|
|
51
|
-
+-- DefaultCRUDRepository (empty subclass, recommended entry point)
|
|
52
|
-
|
|
|
53
|
-
+-- SoftDeletableRepository (overrides delete with soft-delete)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
> [!NOTE]
|
|
57
|
-
> Prior to the connectors restructure, `AbstractRepository` composed `FieldsVisibilityMixin`/`DefaultFilterMixin` directly onto `BaseHelper`. Those mixins have been **removed** - see [Repository Mixins](./mixins) - and the equivalent behavior lives in `AbstractRepository`'s settings getters and `PostgresBaseRepository` instead.
|
|
58
|
-
|
|
59
|
-
### Type Parameters
|
|
60
|
-
|
|
61
|
-
All repository classes share the same four type parameters:
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
class DefaultCRUDRepository<
|
|
65
|
-
EntitySchema extends TTableSchemaWithId = TTableSchemaWithId,
|
|
66
|
-
DataObject extends TTableObject<EntitySchema> = TTableObject<EntitySchema>,
|
|
67
|
-
PersistObject extends TTableInsert<EntitySchema> = TTableInsert<EntitySchema>,
|
|
68
|
-
ExtraOptions extends IExtraOptions = IDatabaseExtraOptions,
|
|
69
|
-
>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
| Parameter | Description |
|
|
73
|
-
|-----------|-------------|
|
|
74
|
-
| `EntitySchema` | The Drizzle `pgTable` schema type (e.g., `typeof User.schema`) |
|
|
75
|
-
| `DataObject` | The inferred SELECT type from the schema |
|
|
76
|
-
| `PersistObject` | The inferred INSERT type from the schema |
|
|
77
|
-
| `ExtraOptions` | Extra options for operations (defaults to `IDatabaseExtraOptions`, which narrows `IExtraOptions.transaction` to `IDatabaseTransaction`) |
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
## Available Methods
|
|
81
|
-
|
|
82
|
-
### Read Operations
|
|
83
|
-
| Method | Description | Example |
|
|
84
|
-
|--------|-------------|---------|
|
|
85
|
-
| `find(opts)` | Find multiple records | `repository.find({ filter: { where: { status: 'active' } } })` |
|
|
86
|
-
| `find(opts)` with range | Find with pagination range | `repository.find({ filter, options: { shouldQueryRange: true } })` |
|
|
87
|
-
| `findOne(opts)` | Find single record | `repository.findOne({ filter: { where: { email } } })` |
|
|
88
|
-
| `findById(opts)` | Find by primary key | `repository.findById({ id: '123' })` |
|
|
89
|
-
| `count(opts)` | Count matching records | `repository.count({ where: { status: 'active' } })` |
|
|
90
|
-
| `existsWith(opts)` | Check if exists | `repository.existsWith({ where: { email } })` |
|
|
91
|
-
|
|
92
|
-
### Write Operations
|
|
93
|
-
| Method | Description | Example |
|
|
94
|
-
|--------|-------------|---------|
|
|
95
|
-
| `create(opts)` | Create single record | `repository.create({ data: { title: 'New' } })` |
|
|
96
|
-
| `createAll(opts)` | Create multiple records | `repository.createAll({ data: [{ title: 'A' }, { title: 'B' }] })` |
|
|
97
|
-
| `updateById(opts)` | Update by primary key | `repository.updateById({ id: '123', data: { title: 'Updated' } })` |
|
|
98
|
-
| `updateAll(opts)` | Update matching records | `repository.updateAll({ data: { status: 'published' }, where: { status: 'draft' } })` |
|
|
99
|
-
| `updateBy(opts)` | Alias for `updateAll` | `repository.updateBy({ data: { status: 'published' }, where: { status: 'draft' } })` |
|
|
100
|
-
| `deleteById(opts)` | Delete by primary key | `repository.deleteById({ id: '123' })` |
|
|
101
|
-
| `deleteAll(opts)` | Delete matching records | `repository.deleteAll({ where: { status: 'archived' } })` |
|
|
102
|
-
| `deleteBy(opts)` | Alias for `deleteAll` | `repository.deleteBy({ where: { status: 'archived' } })` |
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
## Method Signatures
|
|
106
|
-
|
|
107
|
-
### Read Operations
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
// Count matching records
|
|
111
|
-
count(opts: {
|
|
112
|
-
where: TWhere<DataObject>;
|
|
113
|
-
options?: IExtraOptions;
|
|
114
|
-
}): Promise<{ count: number }>;
|
|
115
|
-
|
|
116
|
-
// Check if any record matches
|
|
117
|
-
existsWith(opts: {
|
|
118
|
-
where: TWhere<DataObject>;
|
|
119
|
-
options?: IExtraOptions;
|
|
120
|
-
}): Promise<boolean>;
|
|
121
|
-
|
|
122
|
-
// Find multiple records (returns array)
|
|
123
|
-
find<R = DataObject>(opts: {
|
|
124
|
-
filter: TFilter<DataObject>;
|
|
125
|
-
options?: IExtraOptions & { shouldQueryRange?: false };
|
|
126
|
-
}): Promise<R[]>;
|
|
127
|
-
|
|
128
|
-
// Find multiple records with range info (returns data + range)
|
|
129
|
-
find<R = DataObject>(opts: {
|
|
130
|
-
filter: TFilter<DataObject>;
|
|
131
|
-
options: IExtraOptions & { shouldQueryRange: true };
|
|
132
|
-
}): Promise<{ data: Array<R>; range: TDataRange }>;
|
|
133
|
-
|
|
134
|
-
// Find single record
|
|
135
|
-
findOne<R = DataObject>(opts: {
|
|
136
|
-
filter: TFilter<DataObject>;
|
|
137
|
-
options?: IExtraOptions;
|
|
138
|
-
}): Promise<R | null>;
|
|
139
|
-
|
|
140
|
-
// Find by primary key
|
|
141
|
-
findById<R = DataObject>(opts: {
|
|
142
|
-
id: IdType;
|
|
143
|
-
filter?: Omit<TFilter<DataObject>, 'where'>;
|
|
144
|
-
options?: IExtraOptions;
|
|
145
|
-
}): Promise<R | null>;
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Write Operations
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
// Create single record (returns created data by default)
|
|
152
|
-
create<R = DataObject>(opts: {
|
|
153
|
-
data: PersistObject;
|
|
154
|
-
options?: IExtraOptions & { shouldReturn?: true };
|
|
155
|
-
}): Promise<{ count: number; data: R }>;
|
|
156
|
-
|
|
157
|
-
// Create single record (skip returning data)
|
|
158
|
-
create(opts: {
|
|
159
|
-
data: PersistObject;
|
|
160
|
-
options: IExtraOptions & { shouldReturn: false };
|
|
161
|
-
}): Promise<{ count: number; data: undefined | null }>;
|
|
162
|
-
|
|
163
|
-
// Create multiple records (returns created data by default)
|
|
164
|
-
createAll<R = DataObject>(opts: {
|
|
165
|
-
data: Array<PersistObject>;
|
|
166
|
-
options?: IExtraOptions & { shouldReturn?: true };
|
|
167
|
-
}): Promise<{ count: number; data: Array<R> }>;
|
|
168
|
-
|
|
169
|
-
// Create multiple records (skip returning data)
|
|
170
|
-
createAll(opts: {
|
|
171
|
-
data: Array<PersistObject>;
|
|
172
|
-
options: IExtraOptions & { shouldReturn: false };
|
|
173
|
-
}): Promise<{ count: number; data: undefined | null }>;
|
|
174
|
-
|
|
175
|
-
// Update by primary key (returns updated data by default)
|
|
176
|
-
updateById<R = DataObject>(opts: {
|
|
177
|
-
id: IdType;
|
|
178
|
-
data: Partial<PersistObject>;
|
|
179
|
-
options?: IExtraOptions & { shouldReturn?: true };
|
|
180
|
-
}): Promise<{ count: number; data: R }>;
|
|
181
|
-
|
|
182
|
-
// Update by primary key (skip returning data)
|
|
183
|
-
updateById(opts: {
|
|
184
|
-
id: IdType;
|
|
185
|
-
data: Partial<PersistObject>;
|
|
186
|
-
options: IExtraOptions & { shouldReturn: false };
|
|
187
|
-
}): Promise<{ count: number; data: undefined | null }>;
|
|
188
|
-
|
|
189
|
-
// Update matching records (returns updated data by default)
|
|
190
|
-
updateAll<R = DataObject>(opts: {
|
|
191
|
-
data: Partial<PersistObject>;
|
|
192
|
-
where: TWhere<DataObject>;
|
|
193
|
-
options?: IExtraOptions & { shouldReturn?: true; force?: boolean };
|
|
194
|
-
}): Promise<{ count: number; data: Array<R> }>;
|
|
195
|
-
|
|
196
|
-
// Update matching records (skip returning data)
|
|
197
|
-
updateAll(opts: {
|
|
198
|
-
data: Partial<PersistObject>;
|
|
199
|
-
where: TWhere<DataObject>;
|
|
200
|
-
options: IExtraOptions & { shouldReturn: false; force?: boolean };
|
|
201
|
-
}): Promise<{ count: number; data: undefined | null }>;
|
|
202
|
-
|
|
203
|
-
// updateBy is an alias for updateAll (same signatures)
|
|
204
|
-
|
|
205
|
-
// Delete by primary key (returns deleted data by default)
|
|
206
|
-
deleteById<R = DataObject>(opts: {
|
|
207
|
-
id: IdType;
|
|
208
|
-
options?: IExtraOptions & { shouldReturn?: true };
|
|
209
|
-
}): Promise<{ count: number; data: R }>;
|
|
210
|
-
|
|
211
|
-
// Delete by primary key (skip returning data)
|
|
212
|
-
deleteById(opts: {
|
|
213
|
-
id: IdType;
|
|
214
|
-
options: IExtraOptions & { shouldReturn: false };
|
|
215
|
-
}): Promise<{ count: number; data: undefined | null }>;
|
|
216
|
-
|
|
217
|
-
// Delete matching records (returns deleted data by default)
|
|
218
|
-
deleteAll<R = DataObject>(opts: {
|
|
219
|
-
where: TWhere<DataObject>;
|
|
220
|
-
options?: IExtraOptions & { shouldReturn?: true; force?: boolean };
|
|
221
|
-
}): Promise<{ count: number; data: Array<R> }>;
|
|
222
|
-
|
|
223
|
-
// Delete matching records (skip returning data)
|
|
224
|
-
deleteAll(opts: {
|
|
225
|
-
where: TWhere<DataObject>;
|
|
226
|
-
options: IExtraOptions & { shouldReturn: false; force?: boolean };
|
|
227
|
-
}): Promise<{ count: number; data: undefined | null }>;
|
|
228
|
-
|
|
229
|
-
// deleteBy is an alias for deleteAll (same signatures)
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
## IExtraOptions
|
|
234
|
-
|
|
235
|
-
All repository operations accept an `options` parameter with these fields:
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
interface IExtraOptions {
|
|
239
|
-
/** Transaction context - switches the underlying Drizzle connector. */
|
|
240
|
-
transaction?: ITransaction;
|
|
241
|
-
|
|
242
|
-
/** Operation logging configuration. */
|
|
243
|
-
log?: { use: boolean; level?: TLogLevel };
|
|
244
|
-
|
|
245
|
-
/** If true, bypass the default filter configured in model settings (e.g., soft delete). */
|
|
246
|
-
shouldSkipDefaultFilter?: boolean;
|
|
247
|
-
|
|
248
|
-
/** Row-level locking (requires transaction, incompatible with Query API). */
|
|
249
|
-
lock?: TLockOptions;
|
|
250
|
-
}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
> [!NOTE]
|
|
254
|
-
> Postgres narrows this via `IDatabaseExtraOptions` (`connectors/postgres/repositories/common`), which overrides `transaction` to `IDatabaseTransaction` so `options.transaction.connector` needs no cast.
|
|
255
|
-
|
|
256
|
-
Additional fields are available as intersections on specific methods:
|
|
257
|
-
|
|
258
|
-
| Field | Type | Methods | Description |
|
|
259
|
-
|-------|------|---------|-------------|
|
|
260
|
-
| `shouldReturn` | `boolean` | `create`, `createAll`, `updateById`, `updateAll`, `deleteById`, `deleteAll` | If `false`, skip returning the data (only return count). Defaults to `true`. |
|
|
261
|
-
| `shouldQueryRange` | `boolean` | `find` | If `true`, returns `{ data, range: { start, end, total } }` instead of a plain array. |
|
|
262
|
-
| `force` | `boolean` | `updateAll`, `deleteAll`, `updateBy`, `deleteBy` | Required to allow empty `where` conditions. |
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
## TDataRange
|
|
266
|
-
|
|
267
|
-
When `shouldQueryRange: true` is used, the range follows the HTTP Content-Range standard:
|
|
268
|
-
|
|
269
|
-
```typescript
|
|
270
|
-
type TDataRange = {
|
|
271
|
-
start: number; // Inclusive start index (based on skip/offset)
|
|
272
|
-
end: number; // Inclusive end index
|
|
273
|
-
total: number; // Total matching records (ignoring limit)
|
|
274
|
-
};
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
## AbstractRepository / PostgresBaseRepository Properties
|
|
279
|
-
|
|
280
|
-
### dataSource
|
|
281
|
-
|
|
282
|
-
Getter/setter for the repository's datasource. Throws if accessed before being set (either via constructor or `@repository` auto-injection).
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
// AbstractRepository (engine-neutral, src/base)
|
|
286
|
-
get dataSource(): AbstractDataSource;
|
|
287
|
-
set dataSource(value: AbstractDataSource);
|
|
288
|
-
setDataSource(opts: { dataSource: AbstractDataSource }): void;
|
|
289
|
-
|
|
290
|
-
// PostgresBaseRepository narrows the return type
|
|
291
|
-
get dataSource(): IPostgresDataSource;
|
|
292
|
-
set dataSource(value: IPostgresDataSource);
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### entity
|
|
296
|
-
|
|
297
|
-
Lazy-resolved from `@repository` metadata on first access. Can also be set explicitly via constructor `entityClass` option.
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
// AbstractRepository
|
|
301
|
-
get entity(): AbstractEntity;
|
|
302
|
-
set entity(value: AbstractEntity);
|
|
303
|
-
getEntity(): AbstractEntity;
|
|
304
|
-
|
|
305
|
-
// PostgresBaseRepository narrows the return type
|
|
306
|
-
get entity(): BasePostgresEntity<EntitySchema>;
|
|
307
|
-
set entity(value: BasePostgresEntity<EntitySchema>);
|
|
308
|
-
getEntitySchema(): EntitySchema;
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
`BaseEntity` is a compatibility alias re-exported for `BasePostgresEntity` - prefer `BasePostgresEntity` in new code.
|
|
312
|
-
|
|
313
|
-
### operationScope
|
|
314
|
-
|
|
315
|
-
Returns the repository's operation scope: `'READ_ONLY'`, `'WRITE_ONLY'`, or `'READ_WRITE'`.
|
|
316
|
-
|
|
317
|
-
```typescript
|
|
318
|
-
get operationScope(): TRepositoryOperationScope;
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
- `ReadableRepository` defaults to `READ_ONLY`
|
|
322
|
-
- `PersistableRepository` and `DefaultCRUDRepository` default to `READ_WRITE`
|
|
323
|
-
|
|
324
|
-
### filterBuilder (PostgresBaseRepository+)
|
|
325
|
-
|
|
326
|
-
Access to the `FilterBuilder` instance used for converting filter objects to Drizzle SQL. Not present on the engine-neutral `AbstractRepository`.
|
|
13
|
+
The smallest real repository: bind a model and a datasource, extend `DefaultCRUDRepository`.
|
|
327
14
|
|
|
328
15
|
```typescript
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
### connector (PostgresBaseRepository+)
|
|
16
|
+
import { repository, DefaultCRUDRepository } from '@venizia/ignis';
|
|
17
|
+
import { User } from '../models/user.model';
|
|
18
|
+
import { PostgresDataSource } from '../datasources/postgres.datasource';
|
|
333
19
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
```typescript
|
|
337
|
-
get connector(): IPostgresDataSource['connector'];
|
|
338
|
-
getConnector(): IPostgresDataSource['connector'];
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### updateBuilder (PersistableRepository+)
|
|
342
|
-
|
|
343
|
-
Access to the `UpdateBuilder` instance used for transforming update data (including JSON path updates).
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
get updateBuilder(): UpdateBuilder;
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
## Key Methods
|
|
351
|
-
|
|
352
|
-
### beginTransaction (PostgresBaseRepository+)
|
|
353
|
-
|
|
354
|
-
Delegates to the repository's datasource. Not present on the engine-neutral `AbstractRepository` - each connector adds it with its own transaction type (or omits it, like typesense).
|
|
355
|
-
|
|
356
|
-
```typescript
|
|
357
|
-
beginTransaction(opts?: IDatabaseTransactionOptions): Promise<IDatabaseTransaction>;
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Usage:
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
const tx = await repository.beginTransaction();
|
|
364
|
-
try {
|
|
365
|
-
await repository.create({ data: { name: 'John' }, options: { transaction: tx } });
|
|
366
|
-
await repository.updateById({ id: '456', data: { count: 1 }, options: { transaction: tx } });
|
|
367
|
-
await tx.commit();
|
|
368
|
-
} catch (e) {
|
|
369
|
-
await tx.rollback();
|
|
370
|
-
}
|
|
20
|
+
@repository({ model: User, dataSource: PostgresDataSource })
|
|
21
|
+
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
371
22
|
```
|
|
372
23
|
|
|
373
|
-
|
|
24
|
+
That's it - `UserRepository` already has `find`, `findOne`, `findById`, `create`, `createAll`, `updateById`, `updateAll`, `deleteById`, `deleteAll`, `count`, and `existsWith`.
|
|
374
25
|
|
|
375
|
-
|
|
26
|
+
## How it works
|
|
376
27
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
28
|
+
- **Engine-neutral contract, PostgreSQL implementation.** `AbstractRepository` (engine-neutral, `src/base`) declares the CRUD contract - no SQL, no Drizzle. The PostgreSQL connector implements it as a chain of classes, each layer adding one capability (see table below).
|
|
29
|
+
- **Datasource is auto-injected.** `@repository({ model, dataSource })` auto-injects the datasource at constructor param[0] and lazily resolves the entity class from its own metadata - a plain `extends DefaultCRUDRepository<...> {}` needs no constructor at all.
|
|
30
|
+
- **One options object per verb.** Reads and updates carry a `filter` (`where`, `fields`, `include`, `order`, `limit`, `offset`); writes carry `data`; all of them accept an `options` bag for `transaction`, `shouldReturn`, and `shouldSkipDefaultFilter`.
|
|
380
31
|
|
|
381
|
-
|
|
32
|
+
**PostgreSQL class chain**
|
|
382
33
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
columns: Record<string, boolean>;
|
|
391
|
-
}>;
|
|
392
|
-
```
|
|
34
|
+
| Class | Alias | Adds |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `RelationalBaseRepository` | `PostgresBaseRepository` | `FilterBuilder`/`UpdateBuilder`, hidden-column exclusion |
|
|
37
|
+
| `ReadableRelationalRepository` | `ReadableRepository` | The read verbs |
|
|
38
|
+
| `PersistableRelationalRepository` | `PersistableRepository` | create/update/delete |
|
|
39
|
+
| `DefaultRelationalRepository` | `DefaultCRUDRepository` | Empty - the recommended entry point |
|
|
40
|
+
| `SoftDeletableRelationalRepository` | `SoftDeletableRepository` | Overrides delete to set `deletedAt` instead of removing the row |
|
|
393
41
|
|
|
42
|
+
## Common tasks
|
|
394
43
|
|
|
395
|
-
|
|
44
|
+
### Read with a filter
|
|
396
45
|
|
|
397
|
-
`
|
|
398
|
-
|
|
399
|
-
- **Core API** (Drizzle `select().from()`): ~15-20% faster for flat queries without relations or field selection
|
|
400
|
-
- **Query API** (Drizzle `connector.query[entity].findMany()`): Supports `include` for relations and `fields` for column selection
|
|
401
|
-
|
|
402
|
-
The selection is automatic based on filter complexity:
|
|
46
|
+
`find` and `findOne` take `filter.where`, plus `order` and `limit` for paging.
|
|
403
47
|
|
|
404
48
|
```typescript
|
|
405
|
-
|
|
406
|
-
await repository.find({ filter: { where: { status: 'active' }, limit: 10 } });
|
|
407
|
-
|
|
408
|
-
// Uses Query API (has include)
|
|
409
|
-
await repository.find({
|
|
49
|
+
const users = await userRepository.find({
|
|
410
50
|
filter: {
|
|
411
51
|
where: { status: 'active' },
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
// Uses Query API (has fields)
|
|
417
|
-
await repository.find({
|
|
418
|
-
filter: {
|
|
419
|
-
fields: { id: true, name: true },
|
|
420
|
-
where: { status: 'active' },
|
|
52
|
+
order: ['createdAt DESC'],
|
|
53
|
+
limit: 20,
|
|
421
54
|
},
|
|
422
55
|
});
|
|
423
56
|
```
|
|
424
57
|
|
|
58
|
+
See [Filter System](/references/base/filter-system/) for every operator (`gte`, `like`, `inq`, JSON paths, `and`/`or`).
|
|
425
59
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
### AbstractRepository
|
|
429
|
-
|
|
430
|
-
```typescript
|
|
431
|
-
constructor(
|
|
432
|
-
dataSource?: AbstractDataSource,
|
|
433
|
-
opts?: {
|
|
434
|
-
scope?: string;
|
|
435
|
-
entityClass?: TClass<AbstractEntity>;
|
|
436
|
-
operationScope?: TRepositoryOperationScope;
|
|
437
|
-
},
|
|
438
|
-
)
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
- `dataSource` -- DataSource instance (optional; auto-injected by `@repository` decorator)
|
|
442
|
-
- `opts.scope` -- Logger scope name (defaults to class name)
|
|
443
|
-
- `opts.entityClass` -- Entity class to instantiate (optional; lazy-resolved from `@repository` metadata)
|
|
444
|
-
- `opts.operationScope` -- Defaults to `READ_ONLY`
|
|
445
|
-
|
|
446
|
-
### ReadableRepository (PostgreSQL)
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
constructor(
|
|
450
|
-
ds?: IPostgresDataSource,
|
|
451
|
-
opts?: { entityClass?: TClass<BasePostgresEntity<EntitySchema>> },
|
|
452
|
-
)
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
Forces `operationScope` to `READ_ONLY`.
|
|
60
|
+
### Create a record
|
|
456
61
|
|
|
457
|
-
|
|
62
|
+
`create` returns `{ count, data }`, not the bare record - `count` is `1` on success, `data` is the inserted row (or `null` if `options.shouldReturn: false`).
|
|
458
63
|
|
|
459
64
|
```typescript
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
)
|
|
65
|
+
const { count, data } = await userRepository.create({
|
|
66
|
+
data: { email: 'jane@example.com' },
|
|
67
|
+
});
|
|
464
68
|
```
|
|
465
69
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
## Documentation Sections
|
|
70
|
+
### Update by id
|
|
470
71
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
### [Filter System](/references/base/filter-system/)
|
|
474
|
-
Complete reference for querying data - operators, JSON filtering, array operators, default filters, and query patterns.
|
|
72
|
+
`updateById` returns the same `{ count, data }` shape, with `data` set to the updated row.
|
|
475
73
|
|
|
476
74
|
```typescript
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
where: {
|
|
481
|
-
status: 'active',
|
|
482
|
-
age: { gte: 18 },
|
|
483
|
-
'metadata.priority': { gte: 3 },
|
|
484
|
-
tags: { contains: ['featured'] }
|
|
485
|
-
},
|
|
486
|
-
order: ['createdAt DESC'],
|
|
487
|
-
limit: 20
|
|
488
|
-
}
|
|
75
|
+
const { data: updated } = await userRepository.updateById({
|
|
76
|
+
id: '123',
|
|
77
|
+
data: { email: 'new@example.com' },
|
|
489
78
|
});
|
|
490
79
|
```
|
|
491
80
|
|
|
492
|
-
###
|
|
493
|
-
Fetch related data using `include` for eager loading and nested queries.
|
|
81
|
+
### Soft delete
|
|
494
82
|
|
|
495
|
-
|
|
496
|
-
// Preview
|
|
497
|
-
await repository.find({
|
|
498
|
-
filter: {
|
|
499
|
-
include: [{
|
|
500
|
-
relation: 'posts',
|
|
501
|
-
scope: { where: { published: true } }
|
|
502
|
-
}]
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
### [SoftDeletableRepository](./soft-deletable.md)
|
|
508
|
-
Soft-delete and restore operations using `deletedAt` timestamps instead of physical deletion.
|
|
83
|
+
Extend `SoftDeletableRepository` instead of `DefaultCRUDRepository` on a model with a `deletedAt` column - `deleteById` sets the timestamp instead of removing the row, and `restoreById` clears it.
|
|
509
84
|
|
|
510
85
|
```typescript
|
|
511
|
-
// Preview
|
|
512
86
|
@repository({ model: Category, dataSource: PostgresDataSource })
|
|
513
87
|
export class CategoryRepository extends SoftDeletableRepository<typeof Category.schema> {}
|
|
514
88
|
|
|
515
|
-
|
|
516
|
-
await
|
|
517
|
-
// Restore
|
|
518
|
-
await repository.restoreById({ id: '123' });
|
|
519
|
-
// Hard delete (physical removal)
|
|
520
|
-
await repository.deleteById({ id: '123', options: { shouldHardDelete: true } });
|
|
89
|
+
await categoryRepository.deleteById({ id: '123' }); // sets deletedAt
|
|
90
|
+
await categoryRepository.restoreById({ id: '123' }); // clears deletedAt
|
|
521
91
|
```
|
|
522
92
|
|
|
523
|
-
|
|
524
|
-
Transactions, hidden properties, default filter bypass, performance optimization, and type inference.
|
|
525
|
-
|
|
526
|
-
```typescript
|
|
527
|
-
// Preview
|
|
528
|
-
const tx = await repository.beginTransaction();
|
|
529
|
-
try {
|
|
530
|
-
await repository.create({ data, options: { transaction: tx } });
|
|
531
|
-
await tx.commit();
|
|
532
|
-
} catch (e) {
|
|
533
|
-
await tx.rollback();
|
|
534
|
-
}
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
### [Repository Mixins (Removed)](./mixins.md)
|
|
538
|
-
Tombstone for the removed `DefaultFilterMixin` and `FieldsVisibilityMixin` - where the equivalent behavior lives now.
|
|
93
|
+
See [SoftDeletableRepository](./soft-deletable) for hard delete and bulk restore.
|
|
539
94
|
|
|
95
|
+
### Include relations
|
|
540
96
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
**Both `model` AND `dataSource` are required** for schema auto-discovery:
|
|
97
|
+
Pass `include` in the filter to eager-load related rows, with an optional nested `scope` filter.
|
|
544
98
|
|
|
545
99
|
```typescript
|
|
546
|
-
|
|
100
|
+
await userRepository.find({
|
|
101
|
+
filter: {
|
|
102
|
+
include: [{ relation: 'posts', scope: { where: { published: true } } }],
|
|
103
|
+
},
|
|
104
|
+
});
|
|
547
105
|
```
|
|
548
106
|
|
|
549
|
-
|
|
107
|
+
See [Relations & Includes](./relations) for one-to-many, many-to-many, and nested includes.
|
|
550
108
|
|
|
551
|
-
|
|
552
|
-
interface IRepositoryMetadata<Schema, Model, DataSource> {
|
|
553
|
-
model: TValueOrResolver<TClass<Model>>;
|
|
554
|
-
dataSource: string | TValueOrResolver<TClass<DataSource>>;
|
|
555
|
-
operationScope?: TRepositoryOperationScope; // 'READ_ONLY' | 'WRITE_ONLY' | 'READ_WRITE'
|
|
556
|
-
}
|
|
557
|
-
```
|
|
109
|
+
### Run inside a transaction
|
|
558
110
|
|
|
559
|
-
|
|
560
|
-
// WRONG - Missing dataSource
|
|
561
|
-
@repository({ model: User })
|
|
562
|
-
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
563
|
-
|
|
564
|
-
// WRONG - Missing model
|
|
565
|
-
@repository({ dataSource: PostgresDataSource })
|
|
566
|
-
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
567
|
-
|
|
568
|
-
// CORRECT
|
|
569
|
-
@repository({ model: User, dataSource: PostgresDataSource })
|
|
570
|
-
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
### Zero Boilerplate Pattern (Recommended)
|
|
574
|
-
|
|
575
|
-
DataSource is auto-injected - no constructor needed:
|
|
111
|
+
`beginTransaction()` delegates to the datasource; pass the handle as `options.transaction` on any repository call to run it inside that transaction.
|
|
576
112
|
|
|
577
113
|
```typescript
|
|
578
|
-
|
|
579
|
-
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
|
|
580
|
-
// Custom methods only - no boilerplate!
|
|
114
|
+
const transaction = await userRepository.beginTransaction();
|
|
581
115
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
### Explicit @inject Pattern
|
|
589
|
-
|
|
590
|
-
When you need constructor control:
|
|
591
|
-
|
|
592
|
-
```typescript
|
|
593
|
-
@repository({ model: User, dataSource: PostgresDataSource })
|
|
594
|
-
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
|
|
595
|
-
constructor(
|
|
596
|
-
@inject({ key: 'datasources.PostgresDataSource' })
|
|
597
|
-
dataSource: PostgresDataSource,
|
|
598
|
-
) {
|
|
599
|
-
super(dataSource);
|
|
600
|
-
}
|
|
116
|
+
try {
|
|
117
|
+
await userRepository.create({ data: { email: 'a@example.com' }, options: { transaction } });
|
|
118
|
+
await transaction.commit();
|
|
119
|
+
} catch (error) {
|
|
120
|
+
await transaction.rollback();
|
|
121
|
+
throw error;
|
|
601
122
|
}
|
|
602
123
|
```
|
|
603
124
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
The `@repository` decorator enables two lazy resolution mechanisms:
|
|
607
|
-
|
|
608
|
-
1. **Entity resolution**: The `entity` getter auto-resolves the model class from `@repository` metadata on first access, so you never need to pass `entityClass` manually.
|
|
609
|
-
2. **DataSource resolution**: The DataSource is auto-injected at constructor param[0] unless an explicit `@inject` is present.
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
## Safety Features
|
|
613
|
-
|
|
614
|
-
### Empty Where Protection
|
|
615
|
-
|
|
616
|
-
Prevents accidental mass updates/deletes (in `PersistableRepository` and above):
|
|
617
|
-
|
|
618
|
-
```typescript
|
|
619
|
-
// Throws error - empty where without force flag
|
|
620
|
-
await repository.deleteAll({ where: {} });
|
|
621
|
-
await repository.updateAll({ data: { status: 'archived' }, where: {} });
|
|
622
|
-
|
|
623
|
-
// Explicitly allow with force flag (logs warning)
|
|
624
|
-
await repository.deleteAll({ where: {}, options: { force: true } });
|
|
625
|
-
await repository.updateAll({ data: { status: 'archived' }, where: {}, options: { force: true } });
|
|
626
|
-
```
|
|
627
|
-
|
|
628
|
-
| Scenario | `force: false` (default) | `force: true` |
|
|
629
|
-
|----------|-------------------------|---------------|
|
|
630
|
-
| Empty `where` | Throws error | Logs warning, proceeds |
|
|
631
|
-
| Valid `where` | Executes normally | Executes normally |
|
|
125
|
+
See [DataSources](/references/base/datasources) for the rollback-safe pattern (`rollback()` itself can throw). See [Advanced Features](./advanced) for isolation levels and other transaction options.
|
|
632
126
|
|
|
633
|
-
|
|
127
|
+
## See also
|
|
634
128
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
type TFilter<T = any> = {
|
|
642
|
-
where?: TWhere<T>;
|
|
643
|
-
fields?: Partial<{ [K in keyof T]: boolean }> | Array<keyof T>;
|
|
644
|
-
include?: Array<{
|
|
645
|
-
relation: string;
|
|
646
|
-
scope?: TFilter;
|
|
647
|
-
shouldSkipDefaultFilter?: boolean;
|
|
648
|
-
}>;
|
|
649
|
-
order?: string[]; // e.g., ['createdAt DESC', 'name ASC']
|
|
650
|
-
limit?: number; // Defaults to 10
|
|
651
|
-
offset?: number;
|
|
652
|
-
skip?: number; // Alias for offset
|
|
653
|
-
};
|
|
654
|
-
```
|
|
129
|
+
- [Relations & Includes](./relations) - eager loading, nested `scope` filters, many-to-many
|
|
130
|
+
- [Advanced Features](./advanced) - transactions, hidden properties, `shouldQueryRange`, performance
|
|
131
|
+
- [SoftDeletableRepository](./soft-deletable) - soft delete, restore, hard delete
|
|
132
|
+
- [Repository Mixins (Removed)](./mixins) - where `FieldsVisibilityMixin`/`DefaultFilterMixin` behavior lives now
|
|
133
|
+
- [Filter System](/references/base/filter-system/) - every `where` operator, ordering, pagination
|
|
134
|
+
- [Repositories Guide](/guides/core-concepts/persistent/repositories) - creating repositories step by step
|
|
655
135
|
|
|
136
|
+
**Files:**
|
|
656
137
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
| Want to... | Code |
|
|
660
|
-
|------------|------|
|
|
661
|
-
| Find all active | `repository.find({ filter: { where: { status: 'active' } } })` |
|
|
662
|
-
| Find with range info | `repository.find({ filter, options: { shouldQueryRange: true } })` |
|
|
663
|
-
| Find by ID | `repository.findById({ id: '123' })` |
|
|
664
|
-
| Find with relations | `repository.find({ filter: { include: [{ relation: 'posts' }] } })` |
|
|
665
|
-
| Create one | `repository.create({ data: { name: 'John' } })` |
|
|
666
|
-
| Create without returning data | `repository.create({ data: { name: 'John' }, options: { shouldReturn: false } })` |
|
|
667
|
-
| Create many | `repository.createAll({ data: [{ name: 'A' }, { name: 'B' }] })` |
|
|
668
|
-
| Update by ID | `repository.updateById({ id: '123', data: { name: 'Jane' } })` |
|
|
669
|
-
| Update by condition | `repository.updateAll({ data: { status: 'published' }, where: { status: 'draft' } })` |
|
|
670
|
-
| Delete by ID | `repository.deleteById({ id: '123' })` |
|
|
671
|
-
| Delete by condition | `repository.deleteBy({ where: { status: 'archived' } })` |
|
|
672
|
-
| Soft delete | `repository.deleteById({ id: '123' })` (with `SoftDeletableRepository`) |
|
|
673
|
-
| Restore soft-deleted | `repository.restoreById({ id: '123' })` (with `SoftDeletableRepository`) |
|
|
674
|
-
| Hard delete (bypass soft) | `repository.deleteById({ id: '123', options: { shouldHardDelete: true } })` |
|
|
675
|
-
| Count matching | `repository.count({ where: { status: 'active' } })` |
|
|
676
|
-
| Check exists | `repository.existsWith({ where: { email: 'test@example.com' } })` |
|
|
677
|
-
| Skip default filter | `repository.find({ filter, options: { shouldSkipDefaultFilter: true } })` |
|
|
678
|
-
| Use transaction | `repository.create({ data, options: { transaction: tx } })` |
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
## Next Steps
|
|
682
|
-
|
|
683
|
-
- **New to filtering?** Start with [Filter System](/references/base/filter-system/)
|
|
684
|
-
- **Need related data?** See [Relations & Includes](./relations.md)
|
|
685
|
-
- **Need soft delete?** See [SoftDeletableRepository](./soft-deletable.md)
|
|
686
|
-
- **Need transactions?** Go to [Advanced Features](./advanced.md)
|
|
687
|
-
|
|
688
|
-
## See Also
|
|
689
|
-
|
|
690
|
-
- **Related Concepts:**
|
|
691
|
-
- [Repositories Guide](/guides/core-concepts/persistent/repositories) - Creating repositories tutorial
|
|
692
|
-
- [Models](/guides/core-concepts/persistent/models) - Entity definitions used by repositories
|
|
693
|
-
- [DataSources](/guides/core-concepts/persistent/datasources) - Database connections
|
|
694
|
-
- [Services](/guides/core-concepts/services) - Use repositories for data access
|
|
695
|
-
- [Transactions](/guides/core-concepts/persistent/transactions) - Multi-operation consistency
|
|
696
|
-
|
|
697
|
-
- **Repository Topics:**
|
|
698
|
-
- [Relations & Includes](./relations) - Loading related data
|
|
699
|
-
- [Advanced Features](./advanced) - JSON updates, transactions, performance tuning
|
|
700
|
-
- [Repository Mixins (Removed)](./mixins) - Where mixin behavior lives now
|
|
701
|
-
|
|
702
|
-
- **Filtering:**
|
|
703
|
-
- [Filter System Overview](/references/base/filter-system/) - Complete filtering guide
|
|
704
|
-
- [Filter Quick Reference](/references/base/filter-system/quick-reference) - All operators cheat sheet
|
|
705
|
-
|
|
706
|
-
- **Best Practices:**
|
|
707
|
-
- [Data Modeling](/best-practices/data-modeling) - Repository design patterns
|
|
708
|
-
- [Performance Optimization](/best-practices/performance-optimization) - Query optimization
|
|
709
|
-
|
|
710
|
-
- **Tutorials:**
|
|
711
|
-
- [Building a CRUD API](/guides/tutorials/building-a-crud-api) - Repository examples
|
|
712
|
-
- [E-commerce API](/guides/tutorials/ecommerce-api) - Advanced queries and relations
|
|
138
|
+
- [`packages/core/src/base/repositories/core/abstract.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/base/repositories/core/abstract.ts) - neutral `AbstractRepository`
|
|
139
|
+
- [`packages/core/src/connectors/postgres/repositories/core/index.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/core/index.ts) - PostgreSQL hierarchy + compatibility aliases
|