@venizia/ignis-docs 0.0.7 → 0.0.8-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/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/helpers/docs.helper.d.ts.map +1 -1
- package/dist/mcp-server/helpers/docs.helper.js +1 -1
- package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
- package/dist/mcp-server/tools/base.tool.d.ts +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/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/search-documents.tool.js +1 -1
- package/dist/mcp-server/tools/docs/search-documents.tool.js.map +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js.map +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
- package/package.json +9 -9
- 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 +32 -31
- package/wiki/{references → extensions}/helpers/kafka/examples.md +20 -20
- package/wiki/{references → extensions}/helpers/kafka/index.md +61 -54
- package/wiki/{references → extensions}/helpers/kafka/producer.md +21 -20
- 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 +37 -19
- package/wiki/guides/core-concepts/persistent/index.md +6 -6
- package/wiki/guides/core-concepts/persistent/models.md +50 -6
- package/wiki/guides/core-concepts/persistent/repositories.md +83 -8
- package/wiki/guides/core-concepts/persistent/transactions.md +39 -8
- package/wiki/guides/core-concepts/{controllers.md → rest-controllers.md} +32 -35
- package/wiki/guides/core-concepts/services.md +19 -6
- package/wiki/guides/get-started/5-minute-quickstart.md +17 -17
- 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 +45 -39
- package/wiki/guides/tutorials/complete-installation.md +74 -51
- package/wiki/guides/tutorials/ecommerce-api.md +39 -30
- package/wiki/guides/tutorials/realtime-chat.md +12 -13
- 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 +195 -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
|
@@ -9,19 +9,24 @@ difficulty: advanced
|
|
|
9
9
|
Technical reference for the DI system in Ignis - managing resource lifecycles and dependency resolution.
|
|
10
10
|
|
|
11
11
|
**Files:**
|
|
12
|
-
- `packages/inversion/src/container.ts`
|
|
13
|
-
- `packages/
|
|
14
|
-
- `packages/
|
|
15
|
-
- `packages/
|
|
12
|
+
- `packages/inversion/src/container.ts` — Base `Container` and `Binding` classes
|
|
13
|
+
- `packages/inversion/src/registry.ts` — Base `MetadataRegistry`
|
|
14
|
+
- `packages/inversion/src/metadata/injectors.ts` — Base `@inject` and `@injectable` decorators
|
|
15
|
+
- `packages/inversion/src/common/types.ts` — `BindingScopes`, `BindingValueTypes`, `BindingKeys`, `IProvider`
|
|
16
|
+
- `packages/core/src/helpers/inversion/container.ts` — Extended `Container` with `ApplicationLogger`
|
|
17
|
+
- `packages/core/src/helpers/inversion/registry.ts` — Extended `MetadataRegistry` (singleton, with model/repository/datasource mixins)
|
|
18
|
+
- `packages/core/src/base/metadata/injectors.ts` — Core `@inject` and `@injectable` (wired to extended registry)
|
|
16
19
|
|
|
17
20
|
## Quick Reference
|
|
18
21
|
|
|
19
22
|
| Component | Purpose | Key Methods |
|
|
20
23
|
|-----------|---------|-------------|
|
|
21
|
-
| **Container** | DI registry managing resource lifecycles | `bind()`, `get()`, `instantiate()`, `findByTag()` |
|
|
22
|
-
| **Binding** | Single registered dependency configuration | `toClass()`, `toValue()`, `toProvider()`, `setScope()`, `setTags()` |
|
|
23
|
-
| **@inject** | Decorator marking injection points | Applied to constructor parameters
|
|
24
|
-
| **
|
|
24
|
+
| **Container** | DI registry managing resource lifecycles | `bind()`, `get()`, `gets()`, `instantiate()`, `resolve()`, `findByTag()`, `isBound()`, `unbind()`, `clear()`, `reset()` |
|
|
25
|
+
| **Binding** | Single registered dependency configuration | `toClass()`, `toValue()`, `toProvider()`, `setScope()`, `setTags()`, `getValue()`, `clearCache()` |
|
|
26
|
+
| **@inject** | Decorator marking injection points | Applied to constructor parameters and class properties |
|
|
27
|
+
| **@injectable** | Decorator marking a class as injectable | Stores scope and tag metadata |
|
|
28
|
+
| **MetadataRegistry** | Stores decorator metadata | Singleton — base via `metadataRegistry` export, core via `MetadataRegistry.getInstance()` |
|
|
29
|
+
| **BindingKeys** | Utility for building namespaced keys | `BindingKeys.build({ namespace, key })` |
|
|
25
30
|
| **Boot System** | Automatic artifact discovery and binding | Integrates with Container via tags and bindings |
|
|
26
31
|
|
|
27
32
|
## Prerequisites
|
|
@@ -30,7 +35,7 @@ Before reading this document, you should understand:
|
|
|
30
35
|
|
|
31
36
|
- [TypeScript Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html) - How decorators work in TypeScript
|
|
32
37
|
- [IGNIS Application basics](./application.md) - Application lifecycle and initialization
|
|
33
|
-
- [Services](./services.md) and [Controllers](./controllers.md) - Basic understanding of IGNIS architecture
|
|
38
|
+
- [Services](./services.md) and [Controllers](./controllers.md) - Basic understanding of IGNIS architecture (REST controllers)
|
|
34
39
|
- Inversion of Control (IoC) pattern - [Martin Fowler's article](https://martinfowler.com/articles/injection.html)
|
|
35
40
|
|
|
36
41
|
## `Container` Class
|
|
@@ -39,65 +44,311 @@ Heart of the DI system - registry managing all application resources.
|
|
|
39
44
|
|
|
40
45
|
**File:** `packages/inversion/src/container.ts` (Base) & `packages/core/src/helpers/inversion/container.ts` (Extended)
|
|
41
46
|
|
|
47
|
+
The base `Container` extends `BaseHelper` (which provides `scope` and `identifier` properties). The core `Container` extends the base and adds a `Logger` instance.
|
|
48
|
+
|
|
49
|
+
### Constructor
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const container = new Container({ scope: 'MyApp' }); // scope is optional, defaults to "Container"
|
|
53
|
+
```
|
|
54
|
+
|
|
42
55
|
### Key Methods
|
|
43
56
|
|
|
44
|
-
| Method | Description |
|
|
45
|
-
| :--- | :--- |
|
|
46
|
-
| **`bind<T>({ key })
|
|
47
|
-
| **`get<T>({ key, isOptional })
|
|
48
|
-
| **`
|
|
49
|
-
| **`
|
|
57
|
+
| Method | Signature | Description |
|
|
58
|
+
| :--- | :--- | :--- |
|
|
59
|
+
| **`bind`** | `bind<T>({ key: string \| symbol }): Binding<T>` | Creates and registers a new `Binding` for the given key. Returns the `Binding` for fluent configuration. |
|
|
60
|
+
| **`get`** | `get<T>({ key, isOptional? }): T` | Retrieves a resolved dependency. `key` can be a `string`, `symbol`, or `{ namespace, key }` object. Throws if not found and `isOptional` is `false` (default). Returns `undefined` if `isOptional` is `true` and not found. |
|
|
61
|
+
| **`gets`** | `gets<T>({ bindings }): T[]` | Resolves multiple dependencies at once. Each entry in `bindings` accepts `{ key, isOptional? }`. All lookups are treated as optional (returns `undefined` for missing). |
|
|
62
|
+
| **`getBinding`** | `getBinding<T>({ key }): Binding<T> \| undefined` | Returns the raw `Binding` object without resolving it. `key` accepts `string`, `symbol`, or `{ namespace, key }`. |
|
|
63
|
+
| **`set`** | `set<T>({ binding: Binding<T> }): void` | Directly sets a pre-built `Binding` into the container. |
|
|
64
|
+
| **`isBound`** | `isBound({ key: string \| symbol }): boolean` | Checks if a binding exists for the given key. |
|
|
65
|
+
| **`unbind`** | `unbind({ key: string \| symbol }): boolean` | Removes a binding. Returns `true` if it existed. |
|
|
66
|
+
| **`resolve`** | `resolve<T>(cls: TClass<T>): T` | Alias for `instantiate()`. Creates a new instance of the class with DI. |
|
|
67
|
+
| **`instantiate`** | `instantiate<T>(cls: TClass<T>): T` | Creates a new instance of a class, injecting constructor parameters and property dependencies from the container. |
|
|
68
|
+
| **`findByTag`** | `findByTag<T>({ tag, exclude? }): Binding<T>[]` | Finds all bindings tagged with `tag`. Optionally exclude specific binding keys via `exclude` (accepts `Array<string>` or `Set<string>`). |
|
|
69
|
+
| **`clear`** | `clear(): void` | Clears cached singleton values on all bindings (does not remove bindings). |
|
|
70
|
+
| **`reset`** | `reset(): void` | Removes all bindings entirely. |
|
|
71
|
+
| **`getMetadataRegistry`** | `getMetadataRegistry(): MetadataRegistry` | Returns the metadata registry. The core `Container` overrides this to return `MetadataRegistry.getInstance()`. |
|
|
72
|
+
|
|
73
|
+
### Instantiation Algorithm (Two-Phase)
|
|
74
|
+
|
|
75
|
+
When `container.instantiate(MyClass)` is called:
|
|
76
|
+
|
|
77
|
+
1. **Constructor injection** — Reads `@inject` metadata from the class, sorts by parameter index, resolves each dependency from the container, and passes them as constructor arguments.
|
|
78
|
+
2. **Property injection** — After the instance is created, reads property metadata, resolves each dependency, and assigns them directly to the instance properties.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// Both constructor and property injection in action
|
|
82
|
+
class UserController {
|
|
83
|
+
@inject({ key: 'services.NotificationService' })
|
|
84
|
+
private notificationService!: NotificationService; // Property injection
|
|
85
|
+
|
|
86
|
+
constructor(
|
|
87
|
+
@inject({ key: 'services.UserService' })
|
|
88
|
+
private userService: UserService, // Constructor injection
|
|
89
|
+
) {}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
50
92
|
|
|
51
93
|
## `Binding` Class
|
|
52
94
|
|
|
53
|
-
A `Binding` represents a single registered dependency in the container. It
|
|
95
|
+
A `Binding` represents a single registered dependency in the container. It provides a fluent API to configure *how* a dependency should be created and managed.
|
|
96
|
+
|
|
97
|
+
**File:** `packages/inversion/src/container.ts`
|
|
98
|
+
|
|
99
|
+
The `Binding` class extends `BaseHelper`.
|
|
54
100
|
|
|
55
|
-
|
|
101
|
+
### Constructor
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const binding = new Binding<MyService>({ key: 'services.MyService' });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
When a binding key contains a dot (e.g., `services.MyService`), the namespace portion (`services`) is automatically added as a tag. This enables `findByTag({ tag: 'services' })` to work without manual tagging.
|
|
56
108
|
|
|
57
109
|
### Configuration Methods
|
|
58
110
|
|
|
59
|
-
| Method | Description |
|
|
60
|
-
| :--- | :--- |
|
|
61
|
-
| **`toClass(
|
|
62
|
-
| **`toValue(
|
|
63
|
-
| **`toProvider(
|
|
64
|
-
| **`setScope(scope)
|
|
111
|
+
| Method | Signature | Description |
|
|
112
|
+
| :--- | :--- | :--- |
|
|
113
|
+
| **`toClass`** | `toClass(value: TClass<T>): this` | Binds to a class. The container will instantiate it (resolving constructor and property dependencies) when requested. |
|
|
114
|
+
| **`toValue`** | `toValue(value: T): this` | Binds to a constant value (e.g., a config object, string, number). |
|
|
115
|
+
| **`toProvider`** | `toProvider(value: ((container) => T) \| TClass<IProvider<T>>): this` | Binds to a factory function or a class implementing `IProvider<T>`. |
|
|
116
|
+
| **`setScope`** | `setScope(scope: TBindingScope): this` | Sets the lifecycle scope (`'singleton'` or `'transient'`). |
|
|
117
|
+
| **`setTags`** | `setTags(...tags: string[]): this` | Adds one or more tags to the binding. Tags are additive — calling this multiple times adds more tags. |
|
|
118
|
+
| **`getValue`** | `getValue(container?: Container): T` | Resolves the binding's value. For `CLASS` and `PROVIDER` types, a `container` argument is required. Respects singleton caching. |
|
|
119
|
+
| **`clearCache`** | `clearCache(): void` | Clears the cached singleton instance (if any). Next `getValue()` call will re-create it. |
|
|
120
|
+
| **`hasTag`** | `hasTag(tag: string): boolean` | Checks if the binding has a specific tag. |
|
|
121
|
+
| **`getTags`** | `getTags(): string[]` | Returns all tags as an array. |
|
|
122
|
+
| **`getScope`** | `getScope(): TBindingScope` | Returns the current scope setting. |
|
|
123
|
+
| **`getBindingMeta`** | `getBindingMeta({ type }): TClass<T> \| T \| ...` | Returns the raw resolver value. Throws if the requested type does not match the binding's actual type. |
|
|
124
|
+
|
|
125
|
+
### Fluent API Example
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
container
|
|
129
|
+
.bind<UserService>({ key: 'services.UserService' })
|
|
130
|
+
.toClass(UserService)
|
|
131
|
+
.setScope(BindingScopes.SINGLETON)
|
|
132
|
+
.setTags('core');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Provider Bindings
|
|
136
|
+
|
|
137
|
+
Providers allow complex creation logic. Two forms are supported:
|
|
138
|
+
|
|
139
|
+
**Function provider:**
|
|
140
|
+
```typescript
|
|
141
|
+
container.bind({ key: 'config.db' }).toProvider((container) => {
|
|
142
|
+
const env = container.get<EnvConfig>({ key: 'config.env' });
|
|
143
|
+
return { host: env.DB_HOST, port: env.DB_PORT };
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Class provider** (must implement `IProvider<T>`):
|
|
148
|
+
```typescript
|
|
149
|
+
class DbConfigProvider implements IProvider<DbConfig> {
|
|
150
|
+
value(container: Container): DbConfig {
|
|
151
|
+
const env = container.get<EnvConfig>({ key: 'config.env' });
|
|
152
|
+
return { host: env.DB_HOST, port: env.DB_PORT };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
container.bind({ key: 'config.db' }).toProvider(DbConfigProvider);
|
|
157
|
+
```
|
|
65
158
|
|
|
66
159
|
### Binding Scopes
|
|
67
160
|
|
|
68
|
-
| Scope | Description |
|
|
69
|
-
| :--- | :--- |
|
|
70
|
-
| **`BindingScopes.TRANSIENT`** | (Default) A new instance
|
|
71
|
-
| **`BindingScopes.SINGLETON`** | A single instance is created
|
|
161
|
+
| Scope | Value | Description |
|
|
162
|
+
| :--- | :--- | :--- |
|
|
163
|
+
| **`BindingScopes.TRANSIENT`** | `'transient'` | (Default) A new instance is created every time the dependency is requested. |
|
|
164
|
+
| **`BindingScopes.SINGLETON`** | `'singleton'` | A single instance is created on first request and reused for all subsequent requests. The cache is per-Binding, not per-Container. |
|
|
165
|
+
|
|
166
|
+
### Binding Value Types
|
|
167
|
+
|
|
168
|
+
| Type | Value | Description |
|
|
169
|
+
| :--- | :--- | :--- |
|
|
170
|
+
| **`BindingValueTypes.CLASS`** | `'class'` | Bound via `toClass()`. Container instantiates with DI. |
|
|
171
|
+
| **`BindingValueTypes.VALUE`** | `'value'` | Bound via `toValue()`. Direct value return. |
|
|
172
|
+
| **`BindingValueTypes.PROVIDER`** | `'provider'` | Bound via `toProvider()`. Factory function or `IProvider` class. |
|
|
173
|
+
|
|
174
|
+
## `BindingKeys` Utility
|
|
175
|
+
|
|
176
|
+
Builds namespaced binding keys from structured objects.
|
|
177
|
+
|
|
178
|
+
**File:** `packages/inversion/src/common/types.ts`
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
BindingKeys.build({ namespace: 'services', key: 'UserService' });
|
|
182
|
+
// → 'services.UserService'
|
|
183
|
+
|
|
184
|
+
BindingKeys.build({ namespace: '', key: 'AppConfig' });
|
|
185
|
+
// → 'AppConfig'
|
|
186
|
+
|
|
187
|
+
BindingKeys.build({ namespace: 'services', key: '' });
|
|
188
|
+
// → Throws error: key is required
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This is also used internally by `container.get()` and `container.getBinding()` when you pass a `{ namespace, key }` object as the key.
|
|
72
192
|
|
|
73
193
|
## `@inject` Decorator
|
|
74
194
|
|
|
75
|
-
The `@inject` decorator
|
|
195
|
+
The `@inject` decorator marks where dependencies should be injected — either on constructor parameters or class properties.
|
|
76
196
|
|
|
77
|
-
|
|
197
|
+
**File:** `packages/inversion/src/metadata/injectors.ts` (base) & `packages/core/src/base/metadata/injectors.ts` (core wrapper)
|
|
198
|
+
|
|
199
|
+
### Signature
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
@inject({ key: string | symbol; isOptional?: boolean })
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
| Parameter | Type | Default | Description |
|
|
206
|
+
| :--- | :--- | :--- | :--- |
|
|
207
|
+
| `key` | `string \| symbol` | — | The binding key to resolve from the container. |
|
|
208
|
+
| `isOptional` | `boolean` | `false` | If `true`, returns `undefined` instead of throwing when the binding is not found. |
|
|
209
|
+
|
|
210
|
+
### Constructor Parameter Injection
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
class UserController {
|
|
214
|
+
constructor(
|
|
215
|
+
@inject({ key: 'services.UserService' })
|
|
216
|
+
private userService: UserService,
|
|
217
|
+
|
|
218
|
+
@inject({ key: 'services.CacheService', isOptional: true })
|
|
219
|
+
private cacheService?: CacheService, // Won't throw if not registered
|
|
220
|
+
) {}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Property Injection
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
class UserController {
|
|
228
|
+
@inject({ key: 'services.UserService' })
|
|
229
|
+
private userService!: UserService;
|
|
230
|
+
|
|
231
|
+
@inject({ key: 'services.CacheService', isOptional: true })
|
|
232
|
+
private cacheService?: CacheService;
|
|
233
|
+
}
|
|
234
|
+
```
|
|
78
235
|
|
|
79
236
|
### How It Works
|
|
80
237
|
|
|
81
|
-
1.
|
|
82
|
-
2.
|
|
83
|
-
3.
|
|
84
|
-
|
|
85
|
-
|
|
238
|
+
1. When `@inject` is applied to a **constructor parameter**, it stores `IInjectMetadata` (key, index, isOptional) on the class via the `MetadataRegistry`.
|
|
239
|
+
2. When `@inject` is applied to a **property**, it stores `IPropertyMetadata` (bindingKey, isOptional) on the class prototype via the `MetadataRegistry`.
|
|
240
|
+
3. When `container.instantiate(MyClass)` is called, it reads both metadata sets, resolves each dependency from the container, and injects them.
|
|
241
|
+
|
|
242
|
+
### Base vs Core Decorators
|
|
243
|
+
|
|
244
|
+
The `@venizia/ignis-inversion` package exports base decorators that use the module-level `metadataRegistry` singleton. The `@venizia/ignis` (core) package re-exports wrappers that use the core `MetadataRegistry.getInstance()` singleton instead, which includes model/repository/datasource metadata support.
|
|
245
|
+
|
|
246
|
+
**Always import from `@venizia/ignis` in application code:**
|
|
247
|
+
```typescript
|
|
248
|
+
import { inject, injectable } from '@venizia/ignis';
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## `@injectable` Decorator
|
|
252
|
+
|
|
253
|
+
Marks a class as injectable and attaches optional metadata.
|
|
86
254
|
|
|
87
|
-
|
|
255
|
+
**File:** `packages/inversion/src/metadata/injectors.ts` (base) & `packages/core/src/base/metadata/injectors.ts` (core wrapper)
|
|
256
|
+
|
|
257
|
+
### Signature
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
@injectable({ scope?: TBindingScope; tags?: Record<string, any> })
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
| Parameter | Type | Default | Description |
|
|
264
|
+
| :--- | :--- | :--- | :--- |
|
|
265
|
+
| `scope` | `'singleton' \| 'transient'` | — | Optional scope hint for the binding. |
|
|
266
|
+
| `tags` | `Record<string, any>` | — | Optional metadata tags. |
|
|
267
|
+
|
|
268
|
+
### Example
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
@injectable({ scope: BindingScopes.SINGLETON })
|
|
272
|
+
class UserService extends BaseService {
|
|
273
|
+
constructor(
|
|
274
|
+
@inject({ key: 'repositories.UserRepository' })
|
|
275
|
+
private userRepo: UserRepository,
|
|
276
|
+
) {
|
|
277
|
+
super({ scope: UserService.name });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
88
281
|
|
|
89
282
|
## `MetadataRegistry`
|
|
90
283
|
|
|
91
|
-
The `MetadataRegistry`
|
|
284
|
+
The `MetadataRegistry` stores and retrieves all metadata attached by decorators (`@inject`, `@injectable`, `@controller`, `@model`, etc.).
|
|
285
|
+
|
|
286
|
+
### Base MetadataRegistry
|
|
92
287
|
|
|
93
|
-
|
|
288
|
+
**File:** `packages/inversion/src/registry.ts`
|
|
94
289
|
|
|
95
|
-
|
|
290
|
+
A singleton exported as `metadataRegistry`. Extends `BaseHelper`.
|
|
96
291
|
|
|
97
|
-
|
|
98
|
-
|
|
292
|
+
| Method | Description |
|
|
293
|
+
| :--- | :--- |
|
|
294
|
+
| `define({ target, key, value })` | Stores arbitrary metadata on a target using `Reflect.defineMetadata`. |
|
|
295
|
+
| `get({ target, key })` | Retrieves metadata by key from a target. |
|
|
296
|
+
| `has({ target, key })` | Checks if metadata exists. |
|
|
297
|
+
| `delete({ target, key })` | Removes metadata. Returns `true` if it existed. |
|
|
298
|
+
| `getKeys({ target })` | Returns all metadata keys on a target. |
|
|
299
|
+
| `getMethodNames({ target })` | Returns all method names on a class prototype (excluding `constructor`). |
|
|
300
|
+
| `clearMetadata({ target })` | Removes all metadata from a target. |
|
|
301
|
+
| `setInjectMetadata({ target, index, metadata })` | Stores constructor parameter injection metadata (`IInjectMetadata`). |
|
|
302
|
+
| `getInjectMetadata({ target })` | Returns all constructor injection metadata for a class. |
|
|
303
|
+
| `setPropertyMetadata({ target, propertyName, metadata })` | Stores property injection metadata (`IPropertyMetadata`). |
|
|
304
|
+
| `getPropertiesMetadata({ target })` | Returns a `Map<string \| symbol, IPropertyMetadata>` for all injected properties. |
|
|
305
|
+
| `getPropertyMetadata({ target, propertyName })` | Returns property metadata for a specific property. |
|
|
306
|
+
| `setInjectableMetadata({ target, metadata })` | Stores `@injectable` metadata on a class. |
|
|
307
|
+
| `getInjectableMetadata({ target })` | Returns `@injectable` metadata for a class. |
|
|
308
|
+
|
|
309
|
+
### Core MetadataRegistry
|
|
310
|
+
|
|
311
|
+
**File:** `packages/core/src/helpers/inversion/registry.ts`
|
|
312
|
+
|
|
313
|
+
Extends the base with controller, repository, model, and datasource metadata support via mixins. Accessed as a singleton via `MetadataRegistry.getInstance()`.
|
|
314
|
+
|
|
315
|
+
Additional capabilities include:
|
|
316
|
+
- Controller metadata (route configs, path mappings)
|
|
317
|
+
- REST and gRPC controller metadata
|
|
318
|
+
- Repository binding metadata
|
|
319
|
+
- Model registry (schema, settings)
|
|
320
|
+
- DataSource metadata and schema auto-discovery
|
|
321
|
+
|
|
322
|
+
### Metadata Keys
|
|
323
|
+
|
|
324
|
+
Defined in `packages/inversion/src/common/keys.ts`:
|
|
99
325
|
|
|
100
|
-
|
|
326
|
+
```typescript
|
|
327
|
+
MetadataKeys.PROPERTIES = Symbol.for('ignis:properties')
|
|
328
|
+
MetadataKeys.INJECT = Symbol.for('ignis:inject')
|
|
329
|
+
MetadataKeys.INJECTABLE = Symbol.for('ignis:injectable')
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Key Types
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
interface IInjectMetadata {
|
|
336
|
+
key: string | symbol;
|
|
337
|
+
index: number;
|
|
338
|
+
isOptional?: boolean;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
interface IPropertyMetadata {
|
|
342
|
+
bindingKey: string | symbol;
|
|
343
|
+
isOptional?: boolean;
|
|
344
|
+
[key: string]: any;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
interface IInjectableMetadata {
|
|
348
|
+
scope?: TBindingScope;
|
|
349
|
+
tags?: Record<string, any>;
|
|
350
|
+
}
|
|
351
|
+
```
|
|
101
352
|
|
|
102
353
|
## Boot System Integration
|
|
103
354
|
|
|
@@ -136,19 +387,19 @@ This pattern allows the `Bootstrapper` to automatically discover and execute all
|
|
|
136
387
|
|
|
137
388
|
### Artifact Bindings
|
|
138
389
|
|
|
139
|
-
Once artifacts are discovered and loaded, they're bound using consistent patterns:
|
|
390
|
+
Once artifacts are discovered and loaded, they're bound using consistent namespace patterns:
|
|
140
391
|
|
|
141
392
|
```typescript
|
|
142
|
-
// Controllers
|
|
393
|
+
// Controllers — auto-tagged with 'controllers'
|
|
143
394
|
this.bind({ key: 'controllers.UserController' }).toClass(UserController);
|
|
144
395
|
|
|
145
|
-
// Services
|
|
396
|
+
// Services — auto-tagged with 'services'
|
|
146
397
|
this.bind({ key: 'services.UserService' }).toClass(UserService);
|
|
147
398
|
|
|
148
|
-
// Repositories
|
|
399
|
+
// Repositories — auto-tagged with 'repositories'
|
|
149
400
|
this.bind({ key: 'repositories.UserRepository' }).toClass(UserRepository);
|
|
150
401
|
|
|
151
|
-
// Datasources
|
|
402
|
+
// Datasources — auto-tagged with 'datasources'
|
|
152
403
|
this.bind({ key: 'datasources.PostgresDataSource' }).toClass(PostgresDataSource);
|
|
153
404
|
```
|
|
154
405
|
|
|
@@ -227,12 +478,12 @@ class MyApp extends BaseApplication {
|
|
|
227
478
|
- **Related Concepts:**
|
|
228
479
|
- [Dependency Injection Guide](/guides/core-concepts/dependency-injection) - DI fundamentals tutorial
|
|
229
480
|
- [Application](/guides/core-concepts/application/) - Application extends Container
|
|
230
|
-
- [Controllers](/guides/core-concepts/controllers) - Use DI for injecting services
|
|
481
|
+
- [Controllers](/guides/core-concepts/rest-controllers) - Use DI for injecting services
|
|
231
482
|
- [Services](/guides/core-concepts/services) - Use DI for injecting repositories
|
|
232
483
|
- [Providers](/references/base/providers) - Factory pattern for dynamic injection
|
|
233
484
|
|
|
234
485
|
- **References:**
|
|
235
|
-
- [Inversion Helper](/
|
|
486
|
+
- [Inversion Helper](/extensions/helpers/inversion/) - DI container utilities
|
|
236
487
|
- [Bootstrapping API](/references/base/bootstrapping) - Auto-discovery and DI
|
|
237
488
|
- [Glossary](/guides/reference/glossary#dependency-injection-di) - DI concepts explained
|
|
238
489
|
|
|
@@ -35,7 +35,8 @@ How filters flow through the application layers.
|
|
|
35
35
|
v
|
|
36
36
|
+-----------------------------------------------------------------+
|
|
37
37
|
| Repository Layer |
|
|
38
|
-
| -
|
|
38
|
+
| - DefaultFilterMixin merges default filter |
|
|
39
|
+
| - FilterBuilder transforms Filter -> Drizzle query options |
|
|
39
40
|
| - Executes query via Drizzle ORM |
|
|
40
41
|
| - Returns typed results |
|
|
41
42
|
+-----------------------------------------------------------------+
|
|
@@ -102,7 +103,7 @@ export class ProductController extends _Controller {
|
|
|
102
103
|
|
|
103
104
|
```typescript
|
|
104
105
|
@controller({ path: '/products' })
|
|
105
|
-
export class ProductController extends
|
|
106
|
+
export class ProductController extends BaseRestController {
|
|
106
107
|
constructor(
|
|
107
108
|
@inject({ key: 'repositories.ProductRepository' })
|
|
108
109
|
private _productRepo: ProductRepository,
|
|
@@ -130,6 +131,21 @@ export class ProductController extends BaseController {
|
|
|
130
131
|
```
|
|
131
132
|
|
|
132
133
|
|
|
134
|
+
## Filter Schema Validation
|
|
135
|
+
|
|
136
|
+
The `FilterSchema` (Zod) accepts both object and JSON string formats:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// Object format (from parsed query params)
|
|
140
|
+
{ where: { status: 'active' }, limit: 10 }
|
|
141
|
+
|
|
142
|
+
// JSON string format (from URL query string)
|
|
143
|
+
'{"where":{"status":"active"},"limit":10}'
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The `WhereSchema` also accepts both formats independently, useful for the `count` endpoint which takes `where` directly.
|
|
147
|
+
|
|
148
|
+
|
|
133
149
|
## Service Layer
|
|
134
150
|
|
|
135
151
|
Services can modify filters before passing to repositories:
|
|
@@ -27,8 +27,9 @@ Find rows where the array column contains **all** specified elements.
|
|
|
27
27
|
{ where: { tags: { contains: ['electronics', 'featured'] } } }
|
|
28
28
|
// SQL: "tags"::text[] @> ARRAY['electronics', 'featured']::text[]
|
|
29
29
|
|
|
30
|
-
// Single element
|
|
30
|
+
// Single element (can pass single value or array)
|
|
31
31
|
{ where: { tags: { contains: ['featured'] } } }
|
|
32
|
+
{ where: { tags: { contains: 'featured' } } } // Also works
|
|
32
33
|
// Matches: ['featured'], ['featured', 'sale'], ['a', 'featured', 'b']
|
|
33
34
|
```
|
|
34
35
|
|
|
@@ -85,11 +86,14 @@ Find rows where the arrays share at least one common element.
|
|
|
85
86
|
|
|
86
87
|
## Empty Array Behavior
|
|
87
88
|
|
|
88
|
-
| Operator | Empty Value `[]` | Behavior |
|
|
89
|
-
|
|
90
|
-
| `contains: []` | Returns **ALL** rows |
|
|
91
|
-
| `containedBy: []` | Returns only rows with **empty arrays** |
|
|
92
|
-
| `overlaps: []` | Returns **NO** rows |
|
|
89
|
+
| Operator | Empty Value `[]` | SQL Generated | Behavior |
|
|
90
|
+
|----------|------------------|---------------|----------|
|
|
91
|
+
| `contains: []` | `WHERE true` | Returns **ALL** rows |
|
|
92
|
+
| `containedBy: []` | `WHERE "col" = '{}'` | Returns only rows with **empty arrays** |
|
|
93
|
+
| `overlaps: []` | `WHERE false` | Returns **NO** rows |
|
|
94
|
+
|
|
95
|
+
> [!NOTE]
|
|
96
|
+
> Single values are automatically wrapped in an array: `{ contains: 'value' }` is treated as `{ contains: ['value'] }`.
|
|
93
97
|
|
|
94
98
|
|
|
95
99
|
## Type Handling
|
|
@@ -100,12 +104,16 @@ Find rows where the arrays share at least one common element.
|
|
|
100
104
|
// SQL: "tags"::text[] @> ARRAY['a', 'b']::text[]
|
|
101
105
|
```
|
|
102
106
|
|
|
107
|
+
Both the column and the array literal are cast to `text[]` for compatibility.
|
|
108
|
+
|
|
103
109
|
**Numeric Arrays** (`integer[]`, `numeric[]`):
|
|
104
110
|
```typescript
|
|
105
111
|
{ where: { scores: { contains: [100, 200] } } }
|
|
106
112
|
// SQL: "scores" @> ARRAY[100, 200]
|
|
107
113
|
```
|
|
108
114
|
|
|
115
|
+
No casting needed for numeric arrays.
|
|
116
|
+
|
|
109
117
|
**Boolean Arrays**:
|
|
110
118
|
```typescript
|
|
111
119
|
{ where: { flags: { contains: [true, false] } } }
|
|
@@ -33,12 +33,16 @@ Matches records where field equals the value.
|
|
|
33
33
|
// Array shorthand (becomes IN)
|
|
34
34
|
{ where: { id: [1, 2, 3] } }
|
|
35
35
|
// SQL: WHERE "id" IN (1, 2, 3)
|
|
36
|
+
|
|
37
|
+
// Empty array shorthand
|
|
38
|
+
{ where: { id: [] } }
|
|
39
|
+
// SQL: WHERE false (no results)
|
|
36
40
|
```
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
## ne / neq - Not Equal To
|
|
40
44
|
|
|
41
|
-
Matches records where field does NOT equal the value.
|
|
45
|
+
Matches records where field does NOT equal the value. Both `ne` and `neq` are aliases and behave identically.
|
|
42
46
|
|
|
43
47
|
```typescript
|
|
44
48
|
{ where: { status: { ne: 'deleted' } } }
|
|
@@ -48,6 +52,7 @@ Matches records where field does NOT equal the value.
|
|
|
48
52
|
|
|
49
53
|
// Null handling
|
|
50
54
|
{ where: { deletedAt: { ne: null } } }
|
|
55
|
+
{ where: { deletedAt: { neq: null } } }
|
|
51
56
|
// SQL: WHERE "deleted_at" IS NOT NULL
|
|
52
57
|
```
|
|
53
58
|
|
|
@@ -101,8 +106,9 @@ Matches records where field does NOT equal the value.
|
|
|
101
106
|
|
|
102
107
|
| Operator | SQL | Description |
|
|
103
108
|
|----------|-----|-------------|
|
|
104
|
-
| `eq` | `=` | Equal to |
|
|
105
|
-
| `ne` / `
|
|
109
|
+
| `eq` | `=` / `IS NULL` | Equal to (handles null) |
|
|
110
|
+
| `ne` | `!=` / `IS NOT NULL` | Not equal to (handles null) |
|
|
111
|
+
| `neq` | `!=` / `IS NOT NULL` | Alias for `ne` |
|
|
106
112
|
| `gt` | `>` | Greater than |
|
|
107
113
|
| `gte` | `>=` | Greater than or equal |
|
|
108
114
|
| `lt` | `<` | Less than |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: Default Filter
|
|
3
3
|
description: Automatically apply filter conditions to all repository queries
|
|
4
4
|
difficulty: intermediate
|
|
5
|
-
lastUpdated: 2026-
|
|
5
|
+
lastUpdated: 2026-03-15
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Default Filter <Badge type="tip" text="v0.0.5+" />
|
|
@@ -93,11 +93,11 @@ export class User extends BaseEntity<typeof User.schema> {}
|
|
|
93
93
|
|
|
94
94
|
## Merge Behavior
|
|
95
95
|
|
|
96
|
-
When a user provides a filter, it is merged with the default filter
|
|
96
|
+
When a user provides a filter, it is merged with the default filter using `FilterBuilder.mergeFilter()`:
|
|
97
97
|
|
|
98
98
|
| Property | Merge Strategy |
|
|
99
99
|
|----------|----------------|
|
|
100
|
-
| `where` | **Deep merge**
|
|
100
|
+
| `where` | **Deep merge** (via lodash `merge`) -- user values override matching keys |
|
|
101
101
|
| `limit` | User replaces default (if provided) |
|
|
102
102
|
| `offset`/`skip` | User replaces default (if provided) |
|
|
103
103
|
| `order` | User replaces default (if provided) |
|
|
@@ -316,6 +316,28 @@ await logRepo.find({ filter: { limit: 50 } }); // LIMIT 50
|
|
|
316
316
|
```
|
|
317
317
|
|
|
318
318
|
|
|
319
|
+
## Relation Include Default Filters
|
|
320
|
+
|
|
321
|
+
When using `include` to load relations, the default filter of the related model is also applied. You can bypass it per-relation:
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
await repo.find({
|
|
325
|
+
filter: {
|
|
326
|
+
include: [
|
|
327
|
+
// Default filter of related model applies
|
|
328
|
+
{ relation: 'posts' },
|
|
329
|
+
|
|
330
|
+
// Skip default filter for this specific relation
|
|
331
|
+
{ relation: 'comments', shouldSkipDefaultFilter: true },
|
|
332
|
+
|
|
333
|
+
// Apply a custom scope (merged with relation's default filter)
|
|
334
|
+
{ relation: 'tags', scope: { limit: 10, order: ['name ASC'] } },
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
|
|
319
341
|
## IExtraOptions Interface
|
|
320
342
|
|
|
321
343
|
The `shouldSkipDefaultFilter` option is part of the `IExtraOptions` interface:
|
|
@@ -392,6 +414,8 @@ applyDefaultFilter(opts: {
|
|
|
392
414
|
}): TFilter
|
|
393
415
|
```
|
|
394
416
|
|
|
417
|
+
The default filter is resolved from `MetadataRegistry` on first access and cached for subsequent calls.
|
|
418
|
+
|
|
395
419
|
### FilterBuilder.mergeFilter()
|
|
396
420
|
|
|
397
421
|
The merge logic is implemented in `FilterBuilder`:
|
|
@@ -415,6 +439,7 @@ const merged = filterBuilder.mergeFilter({
|
|
|
415
439
|
|------------|------|
|
|
416
440
|
| Configure default filter | `@model({ settings: { defaultFilter: { ... } } })` |
|
|
417
441
|
| Bypass default filter | `options: { shouldSkipDefaultFilter: true }` |
|
|
442
|
+
| Bypass for relation | `include: [{ relation: 'x', shouldSkipDefaultFilter: true }]` |
|
|
418
443
|
| Combine with transaction | `options: { transaction: tx, shouldSkipDefaultFilter: true }` |
|
|
419
444
|
| Check if model has default | `repo.hasDefaultFilter()` |
|
|
420
445
|
| Get raw default filter | `repo.getDefaultFilter()` |
|