@venizia/ignis-docs 0.2.0 → 0.2.1-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/README.md +14 -14
- package/content/best-practices/api-usage-examples.md +39 -19
- package/content/best-practices/architectural-patterns.md +24 -13
- 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 +27 -3
- 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 +8 -4
- 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 +247 -153
- 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 +109 -323
- package/content/extensions/components/authentication/api.md +489 -602
- package/content/extensions/components/authentication/errors.md +135 -498
- package/content/extensions/components/authentication/index.md +89 -801
- package/content/extensions/components/authentication/usage.md +231 -955
- package/content/extensions/components/authorization/api.md +991 -644
- package/content/extensions/components/authorization/errors.md +204 -208
- package/content/extensions/components/authorization/getting-started.md +227 -0
- package/content/extensions/components/authorization/index.md +88 -795
- package/content/extensions/components/authorization/usage.md +219 -528
- package/content/extensions/components/health-check.md +77 -243
- package/content/extensions/components/index.md +24 -90
- package/content/extensions/components/mail/api.md +553 -285
- package/content/extensions/components/mail/errors.md +76 -62
- package/content/extensions/components/mail/index.md +111 -463
- package/content/extensions/components/mail/usage.md +139 -173
- package/content/extensions/components/request-tracker.md +70 -173
- package/content/extensions/components/socket-io/api.md +462 -785
- package/content/extensions/components/socket-io/errors.md +49 -51
- package/content/extensions/components/socket-io/index.md +69 -372
- package/content/extensions/components/socket-io/usage.md +212 -105
- package/content/extensions/components/static-asset/api.md +461 -141
- package/content/extensions/components/static-asset/errors.md +121 -53
- package/content/extensions/components/static-asset/index.md +84 -606
- package/content/extensions/components/static-asset/usage.md +184 -299
- package/content/extensions/components/template/index.md +3 -3
- package/content/extensions/components/websocket/api.md +311 -404
- package/content/extensions/components/websocket/errors.md +47 -56
- package/content/extensions/components/websocket/index.md +75 -407
- package/content/extensions/components/websocket/usage.md +120 -338
- package/content/extensions/helpers/cron/index.md +52 -160
- package/content/extensions/helpers/crypto/index.md +67 -480
- package/content/extensions/helpers/crypto/reference.md +528 -0
- package/content/extensions/helpers/env/index.md +64 -178
- package/content/extensions/helpers/error/index.md +286 -196
- package/content/extensions/helpers/index.md +61 -47
- package/content/extensions/helpers/inversion/index.md +76 -550
- package/content/extensions/helpers/inversion/reference.md +530 -0
- package/content/extensions/helpers/kafka/admin.md +23 -3
- package/content/extensions/helpers/kafka/compile-binary.md +83 -52
- package/content/extensions/helpers/kafka/consumer.md +65 -28
- package/content/extensions/helpers/kafka/examples.md +46 -253
- package/content/extensions/helpers/kafka/index.md +55 -617
- package/content/extensions/helpers/kafka/producer.md +156 -22
- package/content/extensions/helpers/kafka/schema-registry.md +59 -79
- package/content/extensions/helpers/logger/hf-logger.md +220 -0
- package/content/extensions/helpers/logger/index.md +78 -552
- package/content/extensions/helpers/logger/pino.md +105 -0
- package/content/extensions/helpers/logger/reference.md +937 -0
- package/content/extensions/helpers/network/api.md +276 -195
- package/content/extensions/helpers/network/index.md +87 -524
- package/content/extensions/helpers/queue/index.md +80 -897
- package/content/extensions/helpers/queue/reference.md +494 -0
- package/content/extensions/helpers/redis/index.md +86 -640
- package/content/extensions/helpers/redis/reference.md +784 -0
- package/content/extensions/helpers/secrets/index.md +136 -0
- package/content/extensions/helpers/socket-io/api.md +325 -204
- package/content/extensions/helpers/socket-io/index.md +79 -429
- package/content/extensions/helpers/storage/api.md +584 -464
- package/content/extensions/helpers/storage/index.md +80 -573
- package/content/extensions/helpers/types/index.md +75 -495
- package/content/extensions/helpers/types/reference.md +689 -0
- package/content/extensions/helpers/uid/index.md +176 -189
- package/content/extensions/helpers/websocket/api.md +366 -214
- package/content/extensions/helpers/websocket/index.md +68 -503
- package/content/extensions/helpers/worker-thread/index.md +62 -396
- package/content/extensions/helpers/worker-thread/reference.md +428 -0
- package/content/extensions/index.md +38 -39
- package/content/extensions/src-details/mcp-server.md +96 -548
- package/content/guides/core-concepts/persistent/datasources.md +2 -2
- package/content/guides/core-concepts/persistent/index.md +5 -1
- package/content/guides/core-concepts/persistent/models.md +1 -1
- package/content/guides/core-concepts/persistent/pglite.md +218 -0
- package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
- package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
- package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
- package/content/guides/core-concepts/persistent/sqlite.md +296 -0
- package/content/guides/core-concepts/persistent/transactions.md +12 -11
- package/content/guides/core-concepts/secrets-vault.md +177 -0
- package/content/guides/core-concepts/services.md +1 -1
- package/content/guides/get-started/5-minute-quickstart.md +59 -206
- package/content/guides/get-started/philosophy.md +135 -670
- package/content/guides/get-started/setup.md +53 -74
- package/content/guides/migrations/redis-helpers-migration.md +5 -4
- package/content/guides/migrations/scoped-rbac-migration.md +5 -5
- package/content/guides/migrations/unified-connectors-migration.md +8 -7
- package/content/guides/tutorials/ecommerce-api.md +3 -8
- package/content/guides/tutorials/realtime-chat.md +1 -1
- package/content/references/base/application.md +64 -22
- package/content/references/base/components.md +3 -3
- package/content/references/base/connectors.md +79 -136
- package/content/references/base/controllers.md +12 -12
- package/content/references/base/datasources-reference.md +600 -0
- package/content/references/base/datasources.md +84 -444
- package/content/references/base/dependency-injection.md +25 -46
- package/content/references/base/filter-system/application-usage.md +95 -123
- package/content/references/base/filter-system/array-operators.md +33 -43
- package/content/references/base/filter-system/comparison-operators.md +55 -63
- package/content/references/base/filter-system/default-filter.md +144 -350
- package/content/references/base/filter-system/fields-order-pagination.md +116 -148
- package/content/references/base/filter-system/index.md +114 -253
- package/content/references/base/filter-system/json-filtering.md +52 -181
- package/content/references/base/filter-system/list-operators.md +28 -44
- package/content/references/base/filter-system/logical-operators.md +69 -114
- package/content/references/base/filter-system/null-operators.md +41 -98
- package/content/references/base/filter-system/pattern-matching.md +48 -51
- package/content/references/base/filter-system/quick-reference.md +93 -196
- package/content/references/base/filter-system/range-operators.md +22 -38
- package/content/references/base/filter-system/tips.md +70 -133
- package/content/references/base/filter-system/use-cases.md +173 -232
- package/content/references/base/grpc-controllers.md +53 -17
- package/content/references/base/index.md +5 -3
- package/content/references/base/middlewares.md +43 -28
- package/content/references/base/models-reference.md +886 -0
- package/content/references/base/models.md +81 -1452
- package/content/references/base/providers.md +8 -8
- package/content/references/base/repositories/advanced.md +281 -419
- package/content/references/base/repositories/index.md +84 -644
- package/content/references/base/repositories/mixins.md +25 -21
- package/content/references/base/repositories/relations.md +194 -375
- package/content/references/base/repositories/soft-deletable.md +67 -55
- package/content/references/base/secrets.md +267 -0
- package/content/references/base/services.md +8 -6
- package/content/references/configuration/environment-variables.md +73 -21
- package/content/references/configuration/index.md +51 -31
- package/content/references/index.md +1 -1
- 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/duration.md +85 -0
- package/content/references/utilities/index.md +6 -2
- package/content/references/utilities/jsx-reference.md +298 -0
- package/content/references/utilities/jsx.md +82 -525
- package/content/references/utilities/module.md +81 -61
- 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 +58 -218
- package/content/references/utilities/retry.md +139 -0
- 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/dist/mcp-server/index.js +0 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
- package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
- package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
- package/package.json +24 -23
|
@@ -1,712 +1,152 @@
|
|
|
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`.
|
|
327
|
-
|
|
328
|
-
```typescript
|
|
329
|
-
get filterBuilder(): FilterBuilder;
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
### connector (PostgresBaseRepository+)
|
|
333
|
-
|
|
334
|
-
Shortcut for `this.dataSource.connector`. Not present on the engine-neutral `AbstractRepository`.
|
|
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).
|
|
13
|
+
The smallest real repository: bind a model and a datasource, extend `DefaultCRUDRepository`.
|
|
355
14
|
|
|
356
15
|
```typescript
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
Usage:
|
|
16
|
+
import { repository, DefaultCRUDRepository } from '@venizia/ignis';
|
|
17
|
+
import { User } from '../models/user.model';
|
|
18
|
+
import { PostgresDataSource } from '../datasources/postgres.datasource';
|
|
361
19
|
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
|
|
380
|
-
|
|
381
|
-
The returned `TDrizzleQueryOptions` contains:
|
|
382
|
-
|
|
383
|
-
```typescript
|
|
384
|
-
type TDrizzleQueryOptions = Partial<{
|
|
385
|
-
limit: number;
|
|
386
|
-
offset: number;
|
|
387
|
-
orderBy: SQL[];
|
|
388
|
-
where: SQL;
|
|
389
|
-
with: Record<string, true | TDrizzleQueryOptions>;
|
|
390
|
-
columns: Record<string, boolean>;
|
|
391
|
-
}>;
|
|
392
|
-
```
|
|
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`. Every verb also accepts an `options` bag for `transaction`, `shouldReturn`, and `shouldSkipDefaultFilter`.
|
|
393
31
|
|
|
32
|
+
**PostgreSQL class chain**
|
|
394
33
|
|
|
395
|
-
|
|
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 |
|
|
396
41
|
|
|
397
|
-
|
|
42
|
+
## Common tasks
|
|
398
43
|
|
|
399
|
-
|
|
400
|
-
- **Query API** (Drizzle `connector.query[entity].findMany()`): Supports `include` for relations and `fields` for column selection
|
|
44
|
+
### Read with a filter
|
|
401
45
|
|
|
402
|
-
|
|
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({
|
|
410
|
-
filter: {
|
|
411
|
-
where: { status: 'active' },
|
|
412
|
-
include: [{ relation: 'posts' }],
|
|
413
|
-
},
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
// Uses Query API (has fields)
|
|
417
|
-
await repository.find({
|
|
49
|
+
const users = await userRepository.find({
|
|
418
50
|
filter: {
|
|
419
|
-
fields: { id: true, name: true },
|
|
420
51
|
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
|
-
|
|
70
|
+
### Update by id
|
|
468
71
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
This documentation is split into focused guides:
|
|
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
|
-
```
|
|
93
|
+
See [SoftDeletableRepository](./soft-deletable) for hard delete and bulk restore.
|
|
536
94
|
|
|
537
|
-
###
|
|
538
|
-
Tombstone for the removed `DefaultFilterMixin` and `FieldsVisibilityMixin` - where the equivalent behavior lives now.
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
## @repository Decorator
|
|
542
|
-
|
|
543
|
-
**Both `model` AND `dataSource` are required** for schema auto-discovery:
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
@repository({ model: Model, dataSource: DataSourceClass })
|
|
547
|
-
```
|
|
95
|
+
### Include relations
|
|
548
96
|
|
|
549
|
-
|
|
97
|
+
Pass `include` in the filter to eager-load related rows, with an optional nested `scope` filter.
|
|
550
98
|
|
|
551
99
|
```typescript
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
}
|
|
100
|
+
await userRepository.find({
|
|
101
|
+
filter: {
|
|
102
|
+
include: [{ relation: 'posts', scope: { where: { published: true } } }],
|
|
103
|
+
},
|
|
104
|
+
});
|
|
557
105
|
```
|
|
558
106
|
|
|
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
|
-
```
|
|
107
|
+
See [Relations & Includes](./relations) for one-to-many, many-to-many, and nested includes.
|
|
572
108
|
|
|
573
|
-
###
|
|
109
|
+
### Run inside a transaction
|
|
574
110
|
|
|
575
|
-
|
|
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!
|
|
581
|
-
|
|
582
|
-
async findByEmail(opts: { email: string }) {
|
|
583
|
-
return this.findOne({ filter: { where: { email: opts.email } } });
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
```
|
|
114
|
+
const transaction = await userRepository.beginTransaction();
|
|
587
115
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
-
|
|
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.
|
|
605
126
|
|
|
606
|
-
|
|
127
|
+
### Retry a read behind a replicated pool
|
|
607
128
|
|
|
608
|
-
|
|
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):
|
|
129
|
+
A read right after a write can hit a replica that has not caught up. Pass `retry` to re-read until the result is fresh:
|
|
617
130
|
|
|
618
131
|
```typescript
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
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 } });
|
|
132
|
+
const user = await userRepository.findById({
|
|
133
|
+
id,
|
|
134
|
+
options: { retry: { maxAttempts: 4 } },
|
|
135
|
+
});
|
|
626
136
|
```
|
|
627
137
|
|
|
628
|
-
|
|
629
|
-
|----------|-------------------------|---------------|
|
|
630
|
-
| Empty `where` | Throws error | Logs warning, proceeds |
|
|
631
|
-
| Valid `where` | Executes normally | Executes normally |
|
|
138
|
+
Full options and rules: [Advanced Features - Read Retry](./advanced#read-retry-replica-lag).
|
|
632
139
|
|
|
633
|
-
|
|
140
|
+
## See also
|
|
634
141
|
|
|
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
|
-
```
|
|
142
|
+
- [Relations & Includes](./relations) - eager loading, nested `scope` filters, many-to-many
|
|
143
|
+
- [Advanced Features](./advanced) - transactions, hidden properties, `shouldQueryRange`, performance, read retry
|
|
144
|
+
- [SoftDeletableRepository](./soft-deletable) - soft delete, restore, hard delete
|
|
145
|
+
- [Repository Mixins (Removed)](./mixins) - where `FieldsVisibilityMixin`/`DefaultFilterMixin` behavior lives now
|
|
146
|
+
- [Filter System](/references/base/filter-system/) - every `where` operator, ordering, pagination
|
|
147
|
+
- [Repositories Guide](/guides/core-concepts/persistent/repositories) - creating repositories step by step
|
|
655
148
|
|
|
149
|
+
**Files:**
|
|
656
150
|
|
|
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
|
|
151
|
+
- [`packages/core-server/src/base/repositories/core/abstract.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/base/repositories/core/abstract.ts) - neutral `AbstractRepository`
|
|
152
|
+
- [`packages/core-server/src/connectors/postgres/repositories/core/index.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/core/index.ts) - PostgreSQL hierarchy + compatibility aliases
|