@venizia/ignis-docs 0.0.7 → 0.0.8-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/dist/mcp-server/common/paths.d.ts +4 -2
- package/dist/mcp-server/common/paths.d.ts.map +1 -1
- package/dist/mcp-server/common/paths.js +8 -6
- package/dist/mcp-server/common/paths.js.map +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.js +7 -7
- package/dist/mcp-server/tools/docs/get-document-metadata.tool.js +3 -3
- package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/get-package-overview.tool.js +1 -1
- package/package.json +1 -1
- package/wiki/best-practices/api-usage-examples.md +9 -9
- package/wiki/best-practices/architectural-patterns.md +19 -3
- package/wiki/best-practices/architecture-decisions.md +6 -6
- package/wiki/best-practices/code-style-standards/advanced-patterns.md +1 -1
- package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
- package/wiki/best-practices/code-style-standards/function-patterns.md +2 -2
- package/wiki/best-practices/code-style-standards/index.md +2 -2
- package/wiki/best-practices/code-style-standards/naming-conventions.md +1 -1
- package/wiki/best-practices/code-style-standards/route-definitions.md +4 -4
- package/wiki/best-practices/data-modeling.md +1 -1
- package/wiki/best-practices/deployment-strategies.md +1 -1
- package/wiki/best-practices/error-handling.md +2 -2
- package/wiki/best-practices/performance-optimization.md +3 -3
- package/wiki/best-practices/security-guidelines.md +2 -2
- package/wiki/best-practices/troubleshooting-tips.md +1 -1
- package/wiki/{references → extensions}/components/authentication/api.md +12 -20
- package/wiki/{references → extensions}/components/authentication/errors.md +1 -1
- package/wiki/{references → extensions}/components/authentication/index.md +5 -8
- package/wiki/{references → extensions}/components/authentication/usage.md +20 -36
- package/wiki/{references → extensions}/components/authorization/api.md +62 -13
- package/wiki/{references → extensions}/components/authorization/errors.md +12 -7
- package/wiki/{references → extensions}/components/authorization/index.md +93 -6
- package/wiki/{references → extensions}/components/authorization/usage.md +42 -4
- package/wiki/{references → extensions}/components/health-check.md +5 -4
- package/wiki/{references → extensions}/components/index.md +2 -0
- package/wiki/{references → extensions}/components/mail/index.md +1 -1
- package/wiki/{references → extensions}/components/request-tracker.md +1 -1
- package/wiki/{references → extensions}/components/socket-io/api.md +2 -2
- package/wiki/{references → extensions}/components/socket-io/errors.md +2 -0
- package/wiki/{references → extensions}/components/socket-io/index.md +24 -20
- package/wiki/{references → extensions}/components/socket-io/usage.md +2 -2
- package/wiki/{references → extensions}/components/static-asset/api.md +14 -15
- package/wiki/{references → extensions}/components/static-asset/errors.md +3 -1
- package/wiki/{references → extensions}/components/static-asset/index.md +158 -89
- package/wiki/{references → extensions}/components/static-asset/usage.md +8 -5
- package/wiki/{references → extensions}/components/swagger.md +3 -3
- package/wiki/{references → extensions}/components/template/index.md +4 -4
- package/wiki/{references → extensions}/components/template/setup-page.md +1 -1
- package/wiki/{references → extensions}/components/template/single-page.md +1 -1
- package/wiki/{references → extensions}/components/websocket/api.md +7 -6
- package/wiki/{references → extensions}/components/websocket/errors.md +17 -3
- package/wiki/{references → extensions}/components/websocket/index.md +17 -11
- package/wiki/{references → extensions}/components/websocket/usage.md +2 -2
- package/wiki/{references → extensions}/helpers/crypto/index.md +1 -1
- package/wiki/{references → extensions}/helpers/env/index.md +9 -5
- package/wiki/{references → extensions}/helpers/error/index.md +2 -7
- package/wiki/{references → extensions}/helpers/index.md +18 -6
- package/wiki/{references → extensions}/helpers/kafka/admin.md +13 -1
- package/wiki/{references → extensions}/helpers/kafka/consumer.md +28 -28
- package/wiki/{references → extensions}/helpers/kafka/examples.md +19 -19
- package/wiki/{references → extensions}/helpers/kafka/index.md +51 -48
- package/wiki/{references → extensions}/helpers/kafka/producer.md +18 -18
- package/wiki/{references → extensions}/helpers/kafka/schema-registry.md +25 -25
- package/wiki/{references → extensions}/helpers/logger/index.md +2 -2
- package/wiki/{references → extensions}/helpers/queue/index.md +400 -4
- package/wiki/{references → extensions}/helpers/storage/api.md +170 -10
- package/wiki/{references → extensions}/helpers/storage/index.md +44 -8
- package/wiki/{references → extensions}/helpers/template/index.md +1 -1
- package/wiki/{references → extensions}/helpers/testing/index.md +4 -4
- package/wiki/{references → extensions}/helpers/types/index.md +63 -16
- package/wiki/{references → extensions}/helpers/websocket/index.md +1 -1
- package/wiki/extensions/index.md +48 -0
- package/wiki/guides/core-concepts/application/bootstrapping.md +55 -37
- package/wiki/guides/core-concepts/application/index.md +95 -35
- package/wiki/guides/core-concepts/components-guide.md +23 -19
- package/wiki/guides/core-concepts/components.md +34 -10
- package/wiki/guides/core-concepts/dependency-injection.md +99 -34
- package/wiki/guides/core-concepts/grpc-controllers.md +295 -0
- package/wiki/guides/core-concepts/persistent/datasources.md +27 -8
- package/wiki/guides/core-concepts/persistent/models.md +43 -1
- package/wiki/guides/core-concepts/persistent/repositories.md +75 -8
- package/wiki/guides/core-concepts/persistent/transactions.md +38 -8
- package/wiki/guides/core-concepts/{controllers.md → rest-controllers.md} +30 -33
- package/wiki/guides/core-concepts/services.md +19 -5
- package/wiki/guides/get-started/5-minute-quickstart.md +6 -7
- package/wiki/guides/get-started/philosophy.md +1 -1
- package/wiki/guides/index.md +2 -2
- package/wiki/guides/reference/glossary.md +7 -7
- package/wiki/guides/reference/mcp-docs-server.md +1 -1
- package/wiki/guides/tutorials/building-a-crud-api.md +2 -2
- package/wiki/guides/tutorials/complete-installation.md +17 -14
- package/wiki/guides/tutorials/ecommerce-api.md +18 -18
- package/wiki/guides/tutorials/realtime-chat.md +8 -8
- package/wiki/guides/tutorials/testing.md +2 -2
- package/wiki/index.md +4 -3
- package/wiki/references/base/application.md +341 -21
- package/wiki/references/base/bootstrapping.md +43 -13
- package/wiki/references/base/components.md +259 -8
- package/wiki/references/base/controllers.md +556 -253
- package/wiki/references/base/datasources.md +159 -79
- package/wiki/references/base/dependency-injection.md +299 -48
- package/wiki/references/base/filter-system/application-usage.md +18 -2
- package/wiki/references/base/filter-system/array-operators.md +14 -6
- package/wiki/references/base/filter-system/comparison-operators.md +9 -3
- package/wiki/references/base/filter-system/default-filter.md +28 -3
- package/wiki/references/base/filter-system/fields-order-pagination.md +17 -13
- package/wiki/references/base/filter-system/index.md +169 -11
- package/wiki/references/base/filter-system/json-filtering.md +51 -18
- package/wiki/references/base/filter-system/list-operators.md +4 -3
- package/wiki/references/base/filter-system/logical-operators.md +7 -2
- package/wiki/references/base/filter-system/null-operators.md +50 -0
- package/wiki/references/base/filter-system/quick-reference.md +82 -243
- package/wiki/references/base/filter-system/range-operators.md +7 -1
- package/wiki/references/base/filter-system/tips.md +34 -7
- package/wiki/references/base/filter-system/use-cases.md +6 -5
- package/wiki/references/base/grpc-controllers.md +984 -0
- package/wiki/references/base/index.md +32 -24
- package/wiki/references/base/middleware.md +347 -0
- package/wiki/references/base/models.md +390 -46
- package/wiki/references/base/providers.md +14 -14
- package/wiki/references/base/repositories/advanced.md +84 -69
- package/wiki/references/base/repositories/index.md +447 -12
- package/wiki/references/base/repositories/mixins.md +103 -98
- package/wiki/references/base/repositories/relations.md +129 -45
- package/wiki/references/base/repositories/soft-deletable.md +104 -23
- package/wiki/references/base/services.md +94 -14
- package/wiki/references/index.md +12 -10
- package/wiki/references/quick-reference.md +98 -65
- package/wiki/references/utilities/crypto.md +21 -4
- package/wiki/references/utilities/date.md +25 -7
- package/wiki/references/utilities/index.md +26 -24
- package/wiki/references/utilities/jsx.md +54 -54
- package/wiki/references/utilities/module.md +8 -6
- package/wiki/references/utilities/parse.md +16 -9
- package/wiki/references/utilities/performance.md +22 -7
- package/wiki/references/utilities/promise.md +19 -16
- package/wiki/references/utilities/request.md +48 -26
- package/wiki/references/utilities/schema.md +69 -6
- package/wiki/references/utilities/statuses.md +131 -140
- /package/wiki/{references → extensions}/components/mail/api.md +0 -0
- /package/wiki/{references → extensions}/components/mail/errors.md +0 -0
- /package/wiki/{references → extensions}/components/mail/usage.md +0 -0
- /package/wiki/{references → extensions}/components/template/api-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/errors-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/usage-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/cron/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/inversion/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/redis/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/template/single-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/uid/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/websocket/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/worker-thread/index.md +0 -0
- /package/wiki/{references → extensions}/src-details/mcp-server.md +0 -0
|
@@ -25,14 +25,51 @@ export class TodoRepository extends DefaultCRUDRepository<typeof Todo.schema> {
|
|
|
25
25
|
|
|
26
26
|
| Class | Capabilities | Use Case |
|
|
27
27
|
|-------|--------------|----------|
|
|
28
|
-
| **AbstractRepository** | Base class with properties | Extend for custom repositories |
|
|
29
|
-
| **ReadableRepository** | Read-only operations | Views, external tables |
|
|
30
|
-
| **PersistableRepository** | Read + Write operations |
|
|
31
|
-
| **DefaultCRUDRepository** |
|
|
28
|
+
| **AbstractRepository** | Base class with properties, mixins, lazy resolution | Extend for custom repositories |
|
|
29
|
+
| **ReadableRepository** | Read-only operations (write methods throw errors) | Views, external tables, read-only access |
|
|
30
|
+
| **PersistableRepository** | Read + Write operations | Full CRUD access |
|
|
31
|
+
| **DefaultCRUDRepository** | Extends PersistableRepository (no additions) | Standard data tables (recommended) |
|
|
32
32
|
| **SoftDeletableRepository** | CRUD + soft delete + restore | Tables with `deletedAt` column |
|
|
33
33
|
|
|
34
34
|
**Most common:** Extend `DefaultCRUDRepository` for standard tables, or `SoftDeletableRepository` for soft-delete patterns.
|
|
35
35
|
|
|
36
|
+
### Hierarchy
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
BaseHelper
|
|
40
|
+
+ FieldsVisibilityMixin
|
|
41
|
+
+ DefaultFilterMixin
|
|
42
|
+
= AbstractRepository (abstract base, declares all CRUD signatures)
|
|
43
|
+
|
|
|
44
|
+
+-- ReadableRepository (implements read ops; write ops throw errors)
|
|
45
|
+
|
|
|
46
|
+
+-- PersistableRepository (implements write + delete ops, READ_WRITE scope)
|
|
47
|
+
|
|
|
48
|
+
+-- DefaultCRUDRepository (empty subclass, recommended entry point)
|
|
49
|
+
|
|
|
50
|
+
+-- SoftDeletableRepository (overrides delete with soft-delete)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Type Parameters
|
|
54
|
+
|
|
55
|
+
All repository classes share the same four type parameters:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
class DefaultCRUDRepository<
|
|
59
|
+
EntitySchema extends TTableSchemaWithId = TTableSchemaWithId,
|
|
60
|
+
DataObject extends TTableObject<EntitySchema> = TTableObject<EntitySchema>,
|
|
61
|
+
PersistObject extends TTableInsert<EntitySchema> = TTableInsert<EntitySchema>,
|
|
62
|
+
ExtraOptions extends IExtraOptions = IExtraOptions,
|
|
63
|
+
>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Parameter | Description |
|
|
67
|
+
|-----------|-------------|
|
|
68
|
+
| `EntitySchema` | The Drizzle `pgTable` schema type (e.g., `typeof User.schema`) |
|
|
69
|
+
| `DataObject` | The inferred SELECT type from the schema |
|
|
70
|
+
| `PersistObject` | The inferred INSERT type from the schema |
|
|
71
|
+
| `ExtraOptions` | Extra options for operations (defaults to `IExtraOptions`) |
|
|
72
|
+
|
|
36
73
|
|
|
37
74
|
## Available Methods
|
|
38
75
|
|
|
@@ -52,10 +89,357 @@ export class TodoRepository extends DefaultCRUDRepository<typeof Todo.schema> {
|
|
|
52
89
|
| `create(opts)` | Create single record | `repo.create({ data: { title: 'New' } })` |
|
|
53
90
|
| `createAll(opts)` | Create multiple records | `repo.createAll({ data: [{ title: 'A' }, { title: 'B' }] })` |
|
|
54
91
|
| `updateById(opts)` | Update by primary key | `repo.updateById({ id: '123', data: { title: 'Updated' } })` |
|
|
55
|
-
| `updateAll(opts)` | Update matching records | `repo.updateAll({
|
|
92
|
+
| `updateAll(opts)` | Update matching records | `repo.updateAll({ data: { status: 'published' }, where: { status: 'draft' } })` |
|
|
93
|
+
| `updateBy(opts)` | Alias for `updateAll` | `repo.updateBy({ data: { status: 'published' }, where: { status: 'draft' } })` |
|
|
56
94
|
| `deleteById(opts)` | Delete by primary key | `repo.deleteById({ id: '123' })` |
|
|
57
95
|
| `deleteAll(opts)` | Delete matching records | `repo.deleteAll({ where: { status: 'archived' } })` |
|
|
58
|
-
| `deleteBy(opts)` |
|
|
96
|
+
| `deleteBy(opts)` | Alias for `deleteAll` | `repo.deleteBy({ where: { status: 'archived' } })` |
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
## Method Signatures
|
|
100
|
+
|
|
101
|
+
### Read Operations
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Count matching records
|
|
105
|
+
count(opts: {
|
|
106
|
+
where: TWhere<DataObject>;
|
|
107
|
+
options?: IExtraOptions;
|
|
108
|
+
}): Promise<{ count: number }>;
|
|
109
|
+
|
|
110
|
+
// Check if any record matches
|
|
111
|
+
existsWith(opts: {
|
|
112
|
+
where: TWhere<DataObject>;
|
|
113
|
+
options?: IExtraOptions;
|
|
114
|
+
}): Promise<boolean>;
|
|
115
|
+
|
|
116
|
+
// Find multiple records (returns array)
|
|
117
|
+
find<R = DataObject>(opts: {
|
|
118
|
+
filter: TFilter<DataObject>;
|
|
119
|
+
options?: IExtraOptions & { shouldQueryRange?: false };
|
|
120
|
+
}): Promise<R[]>;
|
|
121
|
+
|
|
122
|
+
// Find multiple records with range info (returns data + range)
|
|
123
|
+
find<R = DataObject>(opts: {
|
|
124
|
+
filter: TFilter<DataObject>;
|
|
125
|
+
options: IExtraOptions & { shouldQueryRange: true };
|
|
126
|
+
}): Promise<{ data: Array<R>; range: TDataRange }>;
|
|
127
|
+
|
|
128
|
+
// Find single record
|
|
129
|
+
findOne<R = DataObject>(opts: {
|
|
130
|
+
filter: TFilter<DataObject>;
|
|
131
|
+
options?: IExtraOptions;
|
|
132
|
+
}): Promise<R | null>;
|
|
133
|
+
|
|
134
|
+
// Find by primary key
|
|
135
|
+
findById<R = DataObject>(opts: {
|
|
136
|
+
id: IdType;
|
|
137
|
+
filter?: Omit<TFilter<DataObject>, 'where'>;
|
|
138
|
+
options?: IExtraOptions;
|
|
139
|
+
}): Promise<R | null>;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Write Operations
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Create single record (returns created data by default)
|
|
146
|
+
create<R = DataObject>(opts: {
|
|
147
|
+
data: PersistObject;
|
|
148
|
+
options?: IExtraOptions & { shouldReturn?: true };
|
|
149
|
+
}): Promise<{ count: number; data: R }>;
|
|
150
|
+
|
|
151
|
+
// Create single record (skip returning data)
|
|
152
|
+
create(opts: {
|
|
153
|
+
data: PersistObject;
|
|
154
|
+
options: IExtraOptions & { shouldReturn: false };
|
|
155
|
+
}): Promise<{ count: number; data: undefined | null }>;
|
|
156
|
+
|
|
157
|
+
// Create multiple records (returns created data by default)
|
|
158
|
+
createAll<R = DataObject>(opts: {
|
|
159
|
+
data: Array<PersistObject>;
|
|
160
|
+
options?: IExtraOptions & { shouldReturn?: true };
|
|
161
|
+
}): Promise<{ count: number; data: Array<R> }>;
|
|
162
|
+
|
|
163
|
+
// Create multiple records (skip returning data)
|
|
164
|
+
createAll(opts: {
|
|
165
|
+
data: Array<PersistObject>;
|
|
166
|
+
options: IExtraOptions & { shouldReturn: false };
|
|
167
|
+
}): Promise<{ count: number; data: undefined | null }>;
|
|
168
|
+
|
|
169
|
+
// Update by primary key (returns updated data by default)
|
|
170
|
+
updateById<R = DataObject>(opts: {
|
|
171
|
+
id: IdType;
|
|
172
|
+
data: Partial<PersistObject>;
|
|
173
|
+
options?: IExtraOptions & { shouldReturn?: true };
|
|
174
|
+
}): Promise<{ count: number; data: R }>;
|
|
175
|
+
|
|
176
|
+
// Update by primary key (skip returning data)
|
|
177
|
+
updateById(opts: {
|
|
178
|
+
id: IdType;
|
|
179
|
+
data: Partial<PersistObject>;
|
|
180
|
+
options: IExtraOptions & { shouldReturn: false };
|
|
181
|
+
}): Promise<{ count: number; data: undefined | null }>;
|
|
182
|
+
|
|
183
|
+
// Update matching records (returns updated data by default)
|
|
184
|
+
updateAll<R = DataObject>(opts: {
|
|
185
|
+
data: Partial<PersistObject>;
|
|
186
|
+
where: TWhere<DataObject>;
|
|
187
|
+
options?: IExtraOptions & { shouldReturn?: true; force?: boolean };
|
|
188
|
+
}): Promise<{ count: number; data: Array<R> }>;
|
|
189
|
+
|
|
190
|
+
// Update matching records (skip returning data)
|
|
191
|
+
updateAll(opts: {
|
|
192
|
+
data: Partial<PersistObject>;
|
|
193
|
+
where: TWhere<DataObject>;
|
|
194
|
+
options: IExtraOptions & { shouldReturn: false; force?: boolean };
|
|
195
|
+
}): Promise<{ count: number; data: undefined | null }>;
|
|
196
|
+
|
|
197
|
+
// updateBy is an alias for updateAll (same signatures)
|
|
198
|
+
|
|
199
|
+
// Delete by primary key (returns deleted data by default)
|
|
200
|
+
deleteById<R = DataObject>(opts: {
|
|
201
|
+
id: IdType;
|
|
202
|
+
options?: IExtraOptions & { shouldReturn?: true };
|
|
203
|
+
}): Promise<{ count: number; data: R }>;
|
|
204
|
+
|
|
205
|
+
// Delete by primary key (skip returning data)
|
|
206
|
+
deleteById(opts: {
|
|
207
|
+
id: IdType;
|
|
208
|
+
options: IExtraOptions & { shouldReturn: false };
|
|
209
|
+
}): Promise<{ count: number; data: undefined | null }>;
|
|
210
|
+
|
|
211
|
+
// Delete matching records (returns deleted data by default)
|
|
212
|
+
deleteAll<R = DataObject>(opts: {
|
|
213
|
+
where: TWhere<DataObject>;
|
|
214
|
+
options?: IExtraOptions & { shouldReturn?: true; force?: boolean };
|
|
215
|
+
}): Promise<{ count: number; data: Array<R> }>;
|
|
216
|
+
|
|
217
|
+
// Delete matching records (skip returning data)
|
|
218
|
+
deleteAll(opts: {
|
|
219
|
+
where: TWhere<DataObject>;
|
|
220
|
+
options: IExtraOptions & { shouldReturn: false; force?: boolean };
|
|
221
|
+
}): Promise<{ count: number; data: undefined | null }>;
|
|
222
|
+
|
|
223
|
+
// deleteBy is an alias for deleteAll (same signatures)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
## IExtraOptions
|
|
228
|
+
|
|
229
|
+
All repository operations accept an `options` parameter with these fields:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
interface IExtraOptions {
|
|
233
|
+
/** Transaction context — switches the underlying Drizzle connector. */
|
|
234
|
+
transaction?: ITransaction;
|
|
235
|
+
|
|
236
|
+
/** Operation logging configuration. */
|
|
237
|
+
log?: { use: boolean; level?: TLogLevel };
|
|
238
|
+
|
|
239
|
+
/** If true, bypass the default filter configured in model settings (e.g., soft delete). */
|
|
240
|
+
shouldSkipDefaultFilter?: boolean;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Additional fields are available as intersections on specific methods:
|
|
245
|
+
|
|
246
|
+
| Field | Type | Methods | Description |
|
|
247
|
+
|-------|------|---------|-------------|
|
|
248
|
+
| `shouldReturn` | `boolean` | `create`, `createAll`, `updateById`, `updateAll`, `deleteById`, `deleteAll` | If `false`, skip returning the data (only return count). Defaults to `true`. |
|
|
249
|
+
| `shouldQueryRange` | `boolean` | `find` | If `true`, returns `{ data, range: { start, end, total } }` instead of a plain array. |
|
|
250
|
+
| `force` | `boolean` | `updateAll`, `deleteAll`, `updateBy`, `deleteBy` | Required to allow empty `where` conditions. |
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
## TDataRange
|
|
254
|
+
|
|
255
|
+
When `shouldQueryRange: true` is used, the range follows the HTTP Content-Range standard:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
type TDataRange = {
|
|
259
|
+
start: number; // Inclusive start index (based on skip/offset)
|
|
260
|
+
end: number; // Inclusive end index
|
|
261
|
+
total: number; // Total matching records (ignoring limit)
|
|
262
|
+
};
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
## AbstractRepository Properties
|
|
267
|
+
|
|
268
|
+
### dataSource
|
|
269
|
+
|
|
270
|
+
Getter/setter for the repository's datasource. Throws if accessed before being set (either via constructor or `@repository` auto-injection).
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
get dataSource(): IDataSource;
|
|
274
|
+
set dataSource(value: IDataSource);
|
|
275
|
+
setDataSource(opts: { dataSource: IDataSource }): void;
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### entity
|
|
279
|
+
|
|
280
|
+
Lazy-resolved from `@repository` metadata on first access. Can also be set explicitly via constructor `entityClass` option.
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
get entity(): BaseEntity<EntitySchema>;
|
|
284
|
+
set entity(value: BaseEntity<EntitySchema>);
|
|
285
|
+
getEntity(): BaseEntity<EntitySchema>;
|
|
286
|
+
getEntitySchema(): EntitySchema;
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### operationScope
|
|
290
|
+
|
|
291
|
+
Returns the repository's operation scope: `'READ_ONLY'`, `'WRITE_ONLY'`, or `'READ_WRITE'`.
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
get operationScope(): TRepositoryOperationScope;
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
- `ReadableRepository` defaults to `READ_ONLY`
|
|
298
|
+
- `PersistableRepository` and `DefaultCRUDRepository` default to `READ_WRITE`
|
|
299
|
+
|
|
300
|
+
### filterBuilder
|
|
301
|
+
|
|
302
|
+
Access to the `FilterBuilder` instance used for converting filter objects to Drizzle SQL.
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
get filterBuilder(): FilterBuilder;
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### connector
|
|
309
|
+
|
|
310
|
+
Shortcut for `this.dataSource.connector`.
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
get connector(): IDataSource['connector'];
|
|
314
|
+
getConnector(): IDataSource['connector'];
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### updateBuilder (PersistableRepository+)
|
|
318
|
+
|
|
319
|
+
Access to the `UpdateBuilder` instance used for transforming update data (including JSON path updates).
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
get updateBuilder(): UpdateBuilder;
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
## Key Methods
|
|
327
|
+
|
|
328
|
+
### beginTransaction
|
|
329
|
+
|
|
330
|
+
Start a new database transaction through the repository's datasource:
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
await repo.beginTransaction(opts?: ITransactionOptions): Promise<ITransaction>;
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Usage:
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
const tx = await repo.beginTransaction();
|
|
340
|
+
try {
|
|
341
|
+
await repo.create({ data: { name: 'John' }, options: { transaction: tx } });
|
|
342
|
+
await repo.updateById({ id: '456', data: { count: 1 }, options: { transaction: tx } });
|
|
343
|
+
await tx.commit();
|
|
344
|
+
} catch (e) {
|
|
345
|
+
await tx.rollback();
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### buildQuery
|
|
350
|
+
|
|
351
|
+
Converts a `TFilter` into Drizzle query options, automatically excluding hidden properties from `@model` settings:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
buildQuery(opts: { filter: TFilter<DataObject> }): TDrizzleQueryOptions;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
The returned `TDrizzleQueryOptions` contains:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
type TDrizzleQueryOptions = Partial<{
|
|
361
|
+
limit: number;
|
|
362
|
+
offset: number;
|
|
363
|
+
orderBy: SQL[];
|
|
364
|
+
where: SQL;
|
|
365
|
+
with: Record<string, true | TDrizzleQueryOptions>;
|
|
366
|
+
columns: Record<string, boolean>;
|
|
367
|
+
}>;
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
## Dual Query API
|
|
372
|
+
|
|
373
|
+
`ReadableRepository` automatically selects the optimal query strategy:
|
|
374
|
+
|
|
375
|
+
- **Core API** (Drizzle `select().from()`): ~15-20% faster for flat queries without relations or field selection
|
|
376
|
+
- **Query API** (Drizzle `connector.query[entity].findMany()`): Supports `include` for relations and `fields` for column selection
|
|
377
|
+
|
|
378
|
+
The selection is automatic based on filter complexity:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// Uses Core API (no include, no fields)
|
|
382
|
+
await repo.find({ filter: { where: { status: 'active' }, limit: 10 } });
|
|
383
|
+
|
|
384
|
+
// Uses Query API (has include)
|
|
385
|
+
await repo.find({
|
|
386
|
+
filter: {
|
|
387
|
+
where: { status: 'active' },
|
|
388
|
+
include: [{ relation: 'posts' }],
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// Uses Query API (has fields)
|
|
393
|
+
await repo.find({
|
|
394
|
+
filter: {
|
|
395
|
+
fields: { id: true, name: true },
|
|
396
|
+
where: { status: 'active' },
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
## Constructor
|
|
403
|
+
|
|
404
|
+
### AbstractRepository
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
constructor(
|
|
408
|
+
ds?: IDataSource,
|
|
409
|
+
opts?: {
|
|
410
|
+
scope?: string;
|
|
411
|
+
entityClass?: TClass<BaseEntity<EntitySchema>>;
|
|
412
|
+
operationScope?: TRepositoryOperationScope;
|
|
413
|
+
},
|
|
414
|
+
)
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
- `ds` -- DataSource instance (optional; auto-injected by `@repository` decorator)
|
|
418
|
+
- `opts.scope` -- Logger scope name (defaults to class name)
|
|
419
|
+
- `opts.entityClass` -- Entity class to instantiate (optional; lazy-resolved from `@repository` metadata)
|
|
420
|
+
- `opts.operationScope` -- Defaults to `READ_ONLY`
|
|
421
|
+
|
|
422
|
+
### ReadableRepository
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
constructor(
|
|
426
|
+
ds?: IDataSource,
|
|
427
|
+
opts?: { entityClass?: TClass<BaseEntity<EntitySchema>> },
|
|
428
|
+
)
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Forces `operationScope` to `READ_ONLY`.
|
|
432
|
+
|
|
433
|
+
### PersistableRepository
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
constructor(
|
|
437
|
+
ds?: IDataSource,
|
|
438
|
+
opts?: { entityClass?: TClass<BaseEntity<EntitySchema>> },
|
|
439
|
+
)
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Forces `operationScope` to `READ_WRITE`. Also creates an `UpdateBuilder` instance.
|
|
59
443
|
|
|
60
444
|
|
|
61
445
|
## Documentation Sections
|
|
@@ -135,15 +519,29 @@ Composable mixins for repository features - `DefaultFilterMixin` and `FieldsVisi
|
|
|
135
519
|
**Both `model` AND `dataSource` are required** for schema auto-discovery:
|
|
136
520
|
|
|
137
521
|
```typescript
|
|
138
|
-
|
|
522
|
+
@repository({ model: Model, dataSource: DataSourceClass })
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
The decorator accepts `IRepositoryMetadata`:
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
interface IRepositoryMetadata<Schema, Model, DataSource> {
|
|
529
|
+
model: TValueOrResolver<TClass<Model>>;
|
|
530
|
+
dataSource: string | TValueOrResolver<TClass<DataSource>>;
|
|
531
|
+
operationScope?: TRepositoryOperationScope; // 'READ_ONLY' | 'WRITE_ONLY' | 'READ_WRITE'
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
// WRONG - Missing dataSource
|
|
139
537
|
@repository({ model: User })
|
|
140
538
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
141
539
|
|
|
142
|
-
//
|
|
540
|
+
// WRONG - Missing model
|
|
143
541
|
@repository({ dataSource: PostgresDataSource })
|
|
144
542
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
145
543
|
|
|
146
|
-
//
|
|
544
|
+
// CORRECT
|
|
147
545
|
@repository({ model: User, dataSource: PostgresDataSource })
|
|
148
546
|
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {}
|
|
149
547
|
```
|
|
@@ -179,19 +577,28 @@ export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
|
|
|
179
577
|
}
|
|
180
578
|
```
|
|
181
579
|
|
|
580
|
+
### Lazy Resolution
|
|
581
|
+
|
|
582
|
+
The `@repository` decorator enables two lazy resolution mechanisms:
|
|
583
|
+
|
|
584
|
+
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.
|
|
585
|
+
2. **DataSource resolution**: The DataSource is auto-injected at constructor param[0] unless an explicit `@inject` is present.
|
|
586
|
+
|
|
182
587
|
|
|
183
588
|
## Safety Features
|
|
184
589
|
|
|
185
590
|
### Empty Where Protection
|
|
186
591
|
|
|
187
|
-
Prevents accidental mass updates/deletes:
|
|
592
|
+
Prevents accidental mass updates/deletes (in `PersistableRepository` and above):
|
|
188
593
|
|
|
189
594
|
```typescript
|
|
190
|
-
//
|
|
595
|
+
// Throws error - empty where without force flag
|
|
191
596
|
await repo.deleteAll({ where: {} });
|
|
597
|
+
await repo.updateAll({ data: { status: 'archived' }, where: {} });
|
|
192
598
|
|
|
193
|
-
//
|
|
599
|
+
// Explicitly allow with force flag (logs warning)
|
|
194
600
|
await repo.deleteAll({ where: {}, options: { force: true } });
|
|
601
|
+
await repo.updateAll({ data: { status: 'archived' }, where: {}, options: { force: true } });
|
|
195
602
|
```
|
|
196
603
|
|
|
197
604
|
| Scenario | `force: false` (default) | `force: true` |
|
|
@@ -199,6 +606,29 @@ await repo.deleteAll({ where: {}, options: { force: true } });
|
|
|
199
606
|
| Empty `where` | Throws error | Logs warning, proceeds |
|
|
200
607
|
| Valid `where` | Executes normally | Executes normally |
|
|
201
608
|
|
|
609
|
+
### ReadableRepository Write Protection
|
|
610
|
+
|
|
611
|
+
All write methods (`create`, `createAll`, `updateById`, `updateAll`, `deleteById`, `deleteAll`) throw errors on `ReadableRepository`, enforcing the read-only scope at runtime.
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
## TFilter Reference
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
type TFilter<T = any> = {
|
|
618
|
+
where?: TWhere<T>;
|
|
619
|
+
fields?: Partial<{ [K in keyof T]: boolean }> | Array<keyof T>;
|
|
620
|
+
include?: Array<{
|
|
621
|
+
relation: string;
|
|
622
|
+
scope?: TFilter;
|
|
623
|
+
shouldSkipDefaultFilter?: boolean;
|
|
624
|
+
}>;
|
|
625
|
+
order?: string[]; // e.g., ['createdAt DESC', 'name ASC']
|
|
626
|
+
limit?: number; // Defaults to 10
|
|
627
|
+
offset?: number;
|
|
628
|
+
skip?: number; // Alias for offset
|
|
629
|
+
};
|
|
630
|
+
```
|
|
631
|
+
|
|
202
632
|
|
|
203
633
|
## Quick Reference
|
|
204
634
|
|
|
@@ -209,7 +639,10 @@ await repo.deleteAll({ where: {}, options: { force: true } });
|
|
|
209
639
|
| Find by ID | `repo.findById({ id: '123' })` |
|
|
210
640
|
| Find with relations | `repo.find({ filter: { include: [{ relation: 'posts' }] } })` |
|
|
211
641
|
| Create one | `repo.create({ data: { name: 'John' } })` |
|
|
642
|
+
| Create without returning data | `repo.create({ data: { name: 'John' }, options: { shouldReturn: false } })` |
|
|
643
|
+
| Create many | `repo.createAll({ data: [{ name: 'A' }, { name: 'B' }] })` |
|
|
212
644
|
| Update by ID | `repo.updateById({ id: '123', data: { name: 'Jane' } })` |
|
|
645
|
+
| Update by condition | `repo.updateAll({ data: { status: 'published' }, where: { status: 'draft' } })` |
|
|
213
646
|
| Delete by ID | `repo.deleteById({ id: '123' })` |
|
|
214
647
|
| Delete by condition | `repo.deleteBy({ where: { status: 'archived' } })` |
|
|
215
648
|
| Soft delete | `repo.deleteById({ id: '123' })` (with `SoftDeletableRepository`) |
|
|
@@ -217,6 +650,8 @@ await repo.deleteAll({ where: {}, options: { force: true } });
|
|
|
217
650
|
| Hard delete (bypass soft) | `repo.deleteById({ id: '123', options: { shouldHardDelete: true } })` |
|
|
218
651
|
| Count matching | `repo.count({ where: { status: 'active' } })` |
|
|
219
652
|
| Check exists | `repo.existsWith({ where: { email: 'test@example.com' } })` |
|
|
653
|
+
| Skip default filter | `repo.find({ filter, options: { shouldSkipDefaultFilter: true } })` |
|
|
654
|
+
| Use transaction | `repo.create({ data, options: { transaction: tx } })` |
|
|
220
655
|
|
|
221
656
|
|
|
222
657
|
## Next Steps
|