@venizia/ignis-docs 0.0.8-3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/{wiki → content}/best-practices/api-usage-examples.md +15 -12
- package/{wiki → content}/best-practices/architectural-patterns.md +70 -78
- package/{wiki → content}/best-practices/architecture-decisions.md +91 -60
- package/{wiki → content}/best-practices/code-style-standards/advanced-patterns.md +56 -44
- package/{wiki → content}/best-practices/code-style-standards/constants-configuration.md +11 -11
- package/{wiki → content}/best-practices/code-style-standards/control-flow.md +5 -2
- package/{wiki → content}/best-practices/code-style-standards/documentation.md +13 -13
- package/{wiki → content}/best-practices/code-style-standards/function-patterns.md +9 -10
- package/{wiki → content}/best-practices/code-style-standards/index.md +1 -1
- package/{wiki → content}/best-practices/code-style-standards/naming-conventions.md +10 -8
- package/{wiki → content}/best-practices/code-style-standards/route-definitions.md +30 -12
- package/{wiki → content}/best-practices/code-style-standards/tooling.md +8 -5
- package/{wiki → content}/best-practices/code-style-standards/type-safety.md +13 -12
- package/{wiki → content}/best-practices/common-pitfalls.md +56 -37
- package/{wiki → content}/best-practices/contribution-workflow.md +13 -14
- package/{wiki → content}/best-practices/data-modeling.md +44 -20
- package/{wiki → content}/best-practices/deployment-strategies.md +28 -27
- package/{wiki → content}/best-practices/error-handling.md +48 -24
- package/{wiki → content}/best-practices/index.md +5 -5
- package/{wiki → content}/best-practices/performance-optimization.md +36 -28
- package/{wiki → content}/best-practices/security-guidelines.md +52 -23
- package/{wiki → content}/best-practices/testing-strategies.md +65 -51
- package/{wiki → content}/best-practices/troubleshooting-tips.md +24 -24
- package/{wiki/extensions/components/swagger.md → content/extensions/components/api-reference.md} +40 -31
- package/{wiki → content}/extensions/components/authentication/api.md +19 -19
- package/{wiki → content}/extensions/components/authentication/errors.md +7 -7
- package/{wiki → content}/extensions/components/authentication/index.md +10 -8
- package/{wiki → content}/extensions/components/authentication/usage.md +101 -6
- package/{wiki → content}/extensions/components/authorization/api.md +45 -25
- package/{wiki → content}/extensions/components/authorization/errors.md +6 -6
- package/{wiki → content}/extensions/components/authorization/index.md +11 -10
- package/{wiki → content}/extensions/components/authorization/usage.md +21 -21
- package/{wiki → content}/extensions/components/health-check.md +1 -1
- package/{wiki → content}/extensions/components/index.md +5 -5
- package/{wiki → content}/extensions/components/mail/errors.md +15 -15
- package/{wiki → content}/extensions/components/mail/index.md +1 -2
- package/{wiki → content}/extensions/components/mail/usage.md +1 -1
- package/{wiki → content}/extensions/components/request-tracker.md +1 -1
- package/{wiki → content}/extensions/components/socket-io/api.md +9 -9
- package/{wiki → content}/extensions/components/socket-io/errors.md +5 -5
- package/{wiki → content}/extensions/components/socket-io/index.md +8 -8
- package/{wiki → content}/extensions/components/socket-io/usage.md +1 -1
- package/{wiki → content}/extensions/components/static-asset/api.md +17 -4
- package/{wiki → content}/extensions/components/static-asset/errors.md +4 -4
- package/{wiki → content}/extensions/components/static-asset/index.md +26 -28
- package/{wiki → content}/extensions/components/static-asset/usage.md +13 -12
- package/{wiki → content}/extensions/components/template/index.md +2 -2
- package/{wiki → content}/extensions/components/template/setup-page.md +1 -1
- package/{wiki → content}/extensions/components/websocket/api.md +3 -3
- package/{wiki → content}/extensions/components/websocket/errors.md +5 -5
- package/{wiki → content}/extensions/components/websocket/index.md +5 -5
- package/{wiki → content}/extensions/components/websocket/usage.md +3 -3
- package/{wiki → content}/extensions/helpers/cron/index.md +2 -2
- package/{wiki → content}/extensions/helpers/crypto/index.md +1 -1
- package/{wiki → content}/extensions/helpers/env/index.md +27 -12
- package/content/extensions/helpers/error/index.md +283 -0
- package/{wiki → content}/extensions/helpers/index.md +2 -3
- package/{wiki → content}/extensions/helpers/inversion/index.md +15 -7
- package/{wiki → content}/extensions/helpers/kafka/examples.md +1 -1
- package/{wiki → content}/extensions/helpers/logger/index.md +32 -2
- package/{wiki → content}/extensions/helpers/network/index.md +6 -0
- package/{wiki → content}/extensions/helpers/queue/index.md +14 -17
- package/content/extensions/helpers/redis/index.md +713 -0
- package/{wiki → content}/extensions/helpers/socket-io/index.md +14 -10
- package/{wiki → content}/extensions/helpers/storage/api.md +44 -8
- package/{wiki → content}/extensions/helpers/storage/index.md +43 -7
- package/{wiki → content}/extensions/helpers/template/index.md +6 -3
- package/{wiki → content}/extensions/helpers/types/index.md +11 -8
- package/{wiki → content}/extensions/helpers/websocket/api.md +9 -9
- package/{wiki → content}/extensions/helpers/websocket/index.md +7 -7
- package/{wiki → content}/extensions/helpers/worker-thread/index.md +2 -2
- package/{wiki → content}/extensions/index.md +3 -4
- package/{wiki → content}/extensions/src-details/mcp-server.md +18 -24
- package/{wiki → content}/guides/core-concepts/application/bootstrapping.md +11 -14
- package/{wiki → content}/guides/core-concepts/application/index.md +3 -3
- package/{wiki → content}/guides/core-concepts/components.md +19 -10
- package/{wiki → content}/guides/core-concepts/dependency-injection.md +6 -3
- package/{wiki → content}/guides/core-concepts/grpc-controllers.md +6 -5
- package/{wiki → content}/guides/core-concepts/persistent/datasources.md +33 -27
- package/{wiki → content}/guides/core-concepts/persistent/index.md +16 -5
- package/{wiki → content}/guides/core-concepts/persistent/models.md +24 -20
- package/content/guides/core-concepts/persistent/postgres-drivers.md +167 -0
- package/{wiki → content}/guides/core-concepts/persistent/repositories.md +40 -23
- package/content/guides/core-concepts/persistent/search-meilisearch.md +183 -0
- package/content/guides/core-concepts/persistent/search-typesense.md +429 -0
- package/{wiki → content}/guides/core-concepts/persistent/transactions.md +61 -25
- package/{wiki → content}/guides/core-concepts/rest-controllers.md +12 -9
- package/content/guides/core-concepts/services.md +389 -0
- package/{wiki → content}/guides/get-started/5-minute-quickstart.md +19 -19
- package/{wiki → content}/guides/get-started/philosophy.md +36 -36
- package/{wiki → content}/guides/get-started/setup.md +3 -3
- package/{wiki → content}/guides/index.md +3 -3
- package/content/guides/migrations/redis-helpers-migration.md +177 -0
- package/{wiki → content}/guides/migrations/scoped-rbac-migration.md +17 -17
- package/content/guides/migrations/unified-connectors-migration.md +113 -0
- package/{wiki → content}/guides/reference/glossary.md +19 -12
- package/{wiki → content}/guides/reference/mcp-docs-server.md +22 -18
- package/{wiki → content}/guides/tutorials/building-a-crud-api.md +30 -33
- package/{wiki → content}/guides/tutorials/complete-installation.md +17 -17
- package/{wiki → content}/guides/tutorials/ecommerce-api.md +158 -119
- package/{wiki → content}/guides/tutorials/realtime-chat.md +176 -130
- package/content/guides/tutorials/testing.md +264 -0
- package/content/index.md +5 -0
- package/content/public/apple-touch-icon.png +0 -0
- package/content/public/og-image.png +0 -0
- package/content/public/site.webmanifest +11 -0
- package/{wiki → content}/references/base/application.md +4 -5
- package/{wiki → content}/references/base/bootstrapping.md +18 -5
- package/{wiki → content}/references/base/components.md +149 -120
- package/content/references/base/connectors.md +178 -0
- package/{wiki → content}/references/base/controllers.md +41 -30
- package/content/references/base/datasources.md +527 -0
- package/{wiki → content}/references/base/dependency-injection.md +34 -22
- package/{wiki → content}/references/base/filter-system/application-usage.md +17 -14
- package/{wiki → content}/references/base/filter-system/array-operators.md +7 -2
- package/{wiki → content}/references/base/filter-system/comparison-operators.md +3 -0
- package/{wiki → content}/references/base/filter-system/default-filter.md +89 -71
- package/{wiki → content}/references/base/filter-system/fields-order-pagination.md +22 -22
- package/{wiki → content}/references/base/filter-system/index.md +6 -3
- package/{wiki → content}/references/base/filter-system/json-filtering.md +20 -1
- package/{wiki → content}/references/base/filter-system/list-operators.md +1 -1
- package/{wiki → content}/references/base/filter-system/logical-operators.md +33 -1
- package/{wiki → content}/references/base/filter-system/null-operators.md +30 -1
- package/{wiki → content}/references/base/filter-system/quick-reference.md +23 -4
- package/{wiki → content}/references/base/filter-system/tips.md +5 -5
- package/{wiki → content}/references/base/filter-system/use-cases.md +12 -12
- package/{wiki → content}/references/base/grpc-controllers.md +13 -13
- package/{wiki → content}/references/base/index.md +24 -12
- package/{wiki/references/base/middleware.md → content/references/base/middlewares.md} +205 -24
- package/{wiki → content}/references/base/models.md +63 -49
- package/{wiki → content}/references/base/providers.md +136 -130
- package/{wiki → content}/references/base/repositories/advanced.md +59 -58
- package/{wiki → content}/references/base/repositories/index.md +115 -91
- package/content/references/base/repositories/mixins.md +99 -0
- package/{wiki → content}/references/base/repositories/relations.md +54 -64
- package/{wiki → content}/references/base/repositories/soft-deletable.md +31 -30
- package/content/references/base/services.md +404 -0
- package/{wiki → content}/references/configuration/environment-variables.md +46 -30
- package/{wiki → content}/references/configuration/index.md +6 -6
- package/{wiki → content}/references/index.md +17 -12
- package/{wiki → content}/references/quick-reference.md +65 -106
- package/content/references/utilities/crypto.md +98 -0
- package/{wiki → content}/references/utilities/index.md +3 -3
- package/{wiki → content}/references/utilities/jsx.md +6 -4
- package/content/references/utilities/module.md +90 -0
- package/{wiki → content}/references/utilities/parse.md +4 -14
- package/{wiki → content}/references/utilities/promise.md +9 -7
- package/{wiki → content}/references/utilities/schema.md +5 -3
- package/dist/mcp-server/common/guards.d.ts +8 -0
- package/dist/mcp-server/common/guards.d.ts.map +1 -0
- package/dist/mcp-server/common/guards.js +14 -0
- package/dist/mcp-server/common/guards.js.map +1 -0
- package/dist/mcp-server/common/index.d.ts +1 -0
- package/dist/mcp-server/common/index.d.ts.map +1 -1
- package/dist/mcp-server/common/index.js +1 -0
- package/dist/mcp-server/common/index.js.map +1 -1
- package/dist/mcp-server/common/paths.d.ts.map +1 -1
- package/dist/mcp-server/common/paths.js +2 -2
- 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 +4 -2
- package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
- package/dist/mcp-server/helpers/github.helper.js +1 -1
- package/dist/mcp-server/index.js +7 -2
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/mcp-server/tools/base.tool.d.ts +6 -2
- package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/base.tool.js.map +1 -1
- package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.js +4 -1
- package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +3 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
- package/package.json +12 -12
- package/wiki/extensions/helpers/error/index.md +0 -227
- package/wiki/extensions/helpers/redis/index.md +0 -488
- package/wiki/extensions/helpers/testing/index.md +0 -510
- package/wiki/guides/core-concepts/services.md +0 -119
- package/wiki/guides/tutorials/testing.md +0 -722
- package/wiki/index.md +0 -183
- package/wiki/references/base/datasources.md +0 -454
- package/wiki/references/base/middlewares.md +0 -590
- package/wiki/references/base/repositories/mixins.md +0 -335
- package/wiki/references/base/services.md +0 -201
- package/wiki/references/utilities/crypto.md +0 -56
- package/wiki/references/utilities/module.md +0 -42
- /package/{wiki → content}/extensions/components/mail/api.md +0 -0
- /package/{wiki → content}/extensions/components/template/api-page.md +0 -0
- /package/{wiki → content}/extensions/components/template/errors-page.md +0 -0
- /package/{wiki → content}/extensions/components/template/single-page.md +0 -0
- /package/{wiki → content}/extensions/components/template/usage-page.md +0 -0
- /package/{wiki → content}/extensions/helpers/kafka/admin.md +0 -0
- /package/{wiki → content}/extensions/helpers/kafka/consumer.md +0 -0
- /package/{wiki → content}/extensions/helpers/kafka/index.md +0 -0
- /package/{wiki → content}/extensions/helpers/kafka/producer.md +0 -0
- /package/{wiki → content}/extensions/helpers/kafka/schema-registry.md +0 -0
- /package/{wiki → content}/extensions/helpers/network/api.md +0 -0
- /package/{wiki → content}/extensions/helpers/socket-io/api.md +0 -0
- /package/{wiki → content}/extensions/helpers/template/single-page.md +0 -0
- /package/{wiki → content}/extensions/helpers/uid/index.md +0 -0
- /package/{wiki → content}/guides/core-concepts/components-guide.md +0 -0
- /package/{wiki → content}/public/logo.svg +0 -0
- /package/{wiki → content}/references/base/filter-system/pattern-matching.md +0 -0
- /package/{wiki → content}/references/base/filter-system/range-operators.md +0 -0
- /package/{wiki → content}/references/utilities/date.md +0 -0
- /package/{wiki → content}/references/utilities/performance.md +0 -0
- /package/{wiki → content}/references/utilities/request.md +0 -0
- /package/{wiki → content}/references/utilities/statuses.md +0 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Services Reference
|
|
3
|
+
description: Technical reference for BaseService and the business logic layer in IGNIS
|
|
4
|
+
difficulty: beginner
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Deep Dive: Services
|
|
8
|
+
|
|
9
|
+
Technical reference for `BaseService` - the foundation for the business logic layer in IGNIS.
|
|
10
|
+
|
|
11
|
+
**File:** `packages/core/src/base/services/base.ts`
|
|
12
|
+
|
|
13
|
+
## Quick Reference
|
|
14
|
+
|
|
15
|
+
| Feature | Detail |
|
|
16
|
+
|---------|--------|
|
|
17
|
+
| **Import** | `import { BaseService, inject } from '@venizia/ignis'` |
|
|
18
|
+
| **Extends** | `BaseHelper` from `@venizia/ignis-helpers` |
|
|
19
|
+
| **Logging** | `this.logger` (scoped to constructor `scope`) |
|
|
20
|
+
| **Registration** | `this.service(MyService)` in application lifecycle |
|
|
21
|
+
| **Binding key** | `services.{ClassName}` (e.g., `services.AuthenticationService`) |
|
|
22
|
+
| **DI decorator** | `@injectable` is NOT used on services - registration is imperative only |
|
|
23
|
+
| **CRUD service** | Removed - use `DefaultCRUDRepository` for data access |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## `BaseService` Class
|
|
28
|
+
|
|
29
|
+
Abstract class that all application services must extend.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
// packages/core/src/base/services/base.ts
|
|
33
|
+
import { BaseHelper } from '@venizia/ignis-helpers';
|
|
34
|
+
import { IService } from './types';
|
|
35
|
+
|
|
36
|
+
export abstract class BaseService extends BaseHelper implements IService {
|
|
37
|
+
constructor(opts: { scope: string }) {
|
|
38
|
+
super({ scope: opts.scope });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`BaseHelper` wires a scoped logger at `this.logger`. Pass `scope: ClassName.name` so log lines are tagged with the service name.
|
|
44
|
+
|
|
45
|
+
### `IService` Interface
|
|
46
|
+
|
|
47
|
+
Marker interface with no required methods - it exists purely for type-level contracts:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
export interface IService {}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Registering a Service
|
|
56
|
+
|
|
57
|
+
Services are registered imperatively in an application lifecycle method. There is no `@injectable` or `@service` decorator used on service classes in application code - `this.service()` handles everything.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// In your Application class (e.g., in preConfigure())
|
|
61
|
+
this.service(AuthenticationService); // binds as 'services.AuthenticationService'
|
|
62
|
+
this.service(GreeterService); // binds as 'services.GreeterService'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`this.service(Ctor)` is implemented directly on `BaseApplication`:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// packages/core/src/base/applications/base.ts
|
|
69
|
+
service<Base extends IService, Args extends AnyObject = any>(
|
|
70
|
+
ctor: TClass<Base>,
|
|
71
|
+
opts?: TMixinOpts<Args>,
|
|
72
|
+
): Binding<Base> {
|
|
73
|
+
return this.bind<Base>({
|
|
74
|
+
key: BindingKeys.build(
|
|
75
|
+
opts?.binding ?? {
|
|
76
|
+
namespace: BindingNamespaces.SERVICE, // 'services'
|
|
77
|
+
key: ctor.name, // class name
|
|
78
|
+
},
|
|
79
|
+
),
|
|
80
|
+
}).toClass(ctor);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The resulting binding key defaults to `services.{ClassName}` (overridable via `opts.binding`).
|
|
85
|
+
|
|
86
|
+
### Lifecycle Placement
|
|
87
|
+
|
|
88
|
+
Register services before anything that depends on them. The correct hook is `preConfigure()`, or a private helper called from `preConfigure()`:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
export class Application extends BaseApplication {
|
|
92
|
+
preConfigure(): void {
|
|
93
|
+
// DataSources and repositories that services depend on must come first
|
|
94
|
+
this.dataSource(PostgresDataSource);
|
|
95
|
+
this.repository(UserRepository);
|
|
96
|
+
|
|
97
|
+
// Then register services
|
|
98
|
+
this.service(AuthenticationService);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Dependency Injection into Services
|
|
106
|
+
|
|
107
|
+
Inject repositories, other services, or datasources via `@inject` in the constructor. Two equivalent key forms are available:
|
|
108
|
+
|
|
109
|
+
### String-literal keys
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { BaseService, inject } from '@venizia/ignis';
|
|
113
|
+
import { UserRepository } from '../repositories';
|
|
114
|
+
import { JWKSIssuerTokenService } from '@venizia/ignis';
|
|
115
|
+
|
|
116
|
+
export class AuthenticationService extends BaseService {
|
|
117
|
+
constructor(
|
|
118
|
+
@inject({ key: 'repositories.UserRepository' })
|
|
119
|
+
private userRepository: UserRepository,
|
|
120
|
+
|
|
121
|
+
@inject({ key: 'services.JWKSIssuerTokenService' })
|
|
122
|
+
private jwksTokenService: JWKSIssuerTokenService,
|
|
123
|
+
) {
|
|
124
|
+
super({ scope: AuthenticationService.name });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Programmatic keys with `BindingKeys.build`
|
|
130
|
+
|
|
131
|
+
`BindingKeys.build({ namespace, key })` produces the same `namespace.key` string. Use this form when you want a compile-time reference to a class name rather than a plain string:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { BaseService, BindingKeys, BindingNamespaces, inject } from '@venizia/ignis';
|
|
135
|
+
import { UserRepository } from '../repositories';
|
|
136
|
+
|
|
137
|
+
export class AuthenticationService extends BaseService {
|
|
138
|
+
constructor(
|
|
139
|
+
@inject({
|
|
140
|
+
key: BindingKeys.build({
|
|
141
|
+
namespace: BindingNamespaces.REPOSITORY, // 'repositories'
|
|
142
|
+
key: UserRepository.name, // 'UserRepository'
|
|
143
|
+
}),
|
|
144
|
+
})
|
|
145
|
+
private userRepository: UserRepository,
|
|
146
|
+
) {
|
|
147
|
+
super({ scope: AuthenticationService.name });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Both forms produce identical binding keys at runtime. The `BindingKeys.build` form avoids typo risk when the class name changes.
|
|
153
|
+
|
|
154
|
+
### Available `BindingNamespaces`
|
|
155
|
+
|
|
156
|
+
| Constant | Value |
|
|
157
|
+
|----------|-------|
|
|
158
|
+
| `BindingNamespaces.SERVICE` | `'services'` |
|
|
159
|
+
| `BindingNamespaces.REPOSITORY` | `'repositories'` |
|
|
160
|
+
| `BindingNamespaces.DATASOURCE` | `'datasources'` |
|
|
161
|
+
| `BindingNamespaces.CONTROLLER` | `'controllers'` |
|
|
162
|
+
| `BindingNamespaces.COMPONENT` | `'components'` |
|
|
163
|
+
| `BindingNamespaces.PROVIDER` | `'providers'` |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Logging
|
|
168
|
+
|
|
169
|
+
`BaseService` inherits `this.logger` from `BaseHelper`. Log with method scope for structured output:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
export class AuthenticationService extends BaseService {
|
|
173
|
+
async signIn(opts: { identifier: string }): Promise<string> {
|
|
174
|
+
// Method-scoped log - produces tag "[signIn]" in log output
|
|
175
|
+
this.logger.for('signIn').info('SignIn called | identifier: %s', opts.identifier);
|
|
176
|
+
|
|
177
|
+
// ... business logic ...
|
|
178
|
+
|
|
179
|
+
this.logger.for('signIn').info('SignIn successful');
|
|
180
|
+
return token;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Use `this.logger.for('methodName')` to scope log lines to the current method. This matches the project-wide convention seen in all examples.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Service-to-Service Composition
|
|
190
|
+
|
|
191
|
+
Services can inject other services to compose business logic. Inject them the same way as repositories, using the `services.*` namespace:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { BaseService, BindingKeys, BindingNamespaces, inject } from '@venizia/ignis';
|
|
195
|
+
|
|
196
|
+
export class OrderService extends BaseService {
|
|
197
|
+
constructor(
|
|
198
|
+
@inject({
|
|
199
|
+
key: BindingKeys.build({
|
|
200
|
+
namespace: BindingNamespaces.REPOSITORY,
|
|
201
|
+
key: OrderRepository.name,
|
|
202
|
+
}),
|
|
203
|
+
})
|
|
204
|
+
private orderRepository: OrderRepository,
|
|
205
|
+
|
|
206
|
+
@inject({
|
|
207
|
+
key: BindingKeys.build({
|
|
208
|
+
namespace: BindingNamespaces.REPOSITORY,
|
|
209
|
+
key: InventoryRepository.name,
|
|
210
|
+
}),
|
|
211
|
+
})
|
|
212
|
+
private inventoryRepository: InventoryRepository,
|
|
213
|
+
|
|
214
|
+
@inject({
|
|
215
|
+
key: BindingKeys.build({
|
|
216
|
+
namespace: BindingNamespaces.SERVICE,
|
|
217
|
+
key: NotificationService.name,
|
|
218
|
+
}),
|
|
219
|
+
})
|
|
220
|
+
private notificationService: NotificationService,
|
|
221
|
+
) {
|
|
222
|
+
super({ scope: OrderService.name });
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async createOrder(opts: { userId: string; items: OrderItem[] }): Promise<Order> {
|
|
226
|
+
this.logger.for('createOrder').info('Creating order | userId: %s', opts.userId);
|
|
227
|
+
|
|
228
|
+
const { data: order } = await this.orderRepository.create({ data: opts });
|
|
229
|
+
|
|
230
|
+
// Compose with another service
|
|
231
|
+
await this.notificationService.sendOrderConfirmation({ orderId: order.id });
|
|
232
|
+
|
|
233
|
+
return order;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Register both services in `preConfigure()`:
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
this.service(NotificationService);
|
|
242
|
+
this.service(OrderService);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Abstract Base Services
|
|
246
|
+
|
|
247
|
+
For shared dependencies across multiple related services, define an abstract base. The container only ever `instantiate()`s the **concrete** class (`this.service(UserAuditTestService)` registers `UserAuditTestService`, never `BaseTestService`), and the hard DI rule - every constructor parameter of a container-instantiated class must carry `@inject` - applies to that concrete constructor. A `scope: string` computed from `ClassName.name` is not something the container can supply anyway, so it cannot sit as a bare constructor parameter next to an `@inject`-decorated one. The shared repository is injected as a **property** on the base instead, and the concrete subclass's constructor is left with zero parameters - nothing to decorate, nothing to violate:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// Shared repository access for a group of test services - property injection,
|
|
251
|
+
// so the concrete subclass's constructor stays free of undecorated parameters
|
|
252
|
+
export abstract class BaseTestService extends BaseService {
|
|
253
|
+
@inject({
|
|
254
|
+
key: BindingKeys.build({
|
|
255
|
+
namespace: BindingNamespaces.REPOSITORY,
|
|
256
|
+
key: UserRepository.name,
|
|
257
|
+
}),
|
|
258
|
+
})
|
|
259
|
+
protected userRepository!: UserRepository;
|
|
260
|
+
|
|
261
|
+
constructor(opts: { scope: string }) {
|
|
262
|
+
super(opts);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
abstract run(): Promise<void>;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Concrete subclass takes no constructor parameters - only container-instantiated
|
|
269
|
+
// classes are subject to the "every parameter decorated" rule, and an empty
|
|
270
|
+
// parameter list trivially satisfies it
|
|
271
|
+
export class UserAuditTestService extends BaseTestService {
|
|
272
|
+
constructor() {
|
|
273
|
+
super({ scope: UserAuditTestService.name });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async run(): Promise<void> {
|
|
277
|
+
this.logger.for('run').info('Running user audit tests');
|
|
278
|
+
// ...
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Register the concrete class - never the abstract base:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
this.service(UserAuditTestService);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> [!IMPORTANT]
|
|
290
|
+
> `BaseTestService`'s own constructor (`opts: { scope: string }`) is never processed by the container - `BaseTestService` is abstract and is never passed to `instantiate()`. Only the concrete class the container actually instantiates is subject to the "every parameter decorated" rule. See [Dependency Injection Reference](./dependency-injection.md#instantiation-algorithm-two-phase) for the full rule.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Transaction Orchestration
|
|
295
|
+
|
|
296
|
+
Services are the correct place to manage transactions that span multiple repository calls. Begin a transaction on the DataSource and pass it through repository options:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import { BaseService, BindingKeys, BindingNamespaces, inject } from '@venizia/ignis';
|
|
300
|
+
import { PostgresDataSource } from '../datasources';
|
|
301
|
+
|
|
302
|
+
export class CheckoutService extends BaseService {
|
|
303
|
+
constructor(
|
|
304
|
+
@inject({ key: 'datasources.PostgresDataSource' })
|
|
305
|
+
private dataSource: PostgresDataSource,
|
|
306
|
+
|
|
307
|
+
@inject({ key: 'repositories.OrderRepository' })
|
|
308
|
+
private orderRepository: OrderRepository,
|
|
309
|
+
|
|
310
|
+
@inject({ key: 'repositories.InventoryRepository' })
|
|
311
|
+
private inventoryRepository: InventoryRepository,
|
|
312
|
+
) {
|
|
313
|
+
super({ scope: CheckoutService.name });
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async placeOrder(opts: { userId: string; items: OrderItem[] }): Promise<Order> {
|
|
317
|
+
const log = this.logger.for('placeOrder');
|
|
318
|
+
const transaction = await this.dataSource.beginTransaction();
|
|
319
|
+
|
|
320
|
+
try {
|
|
321
|
+
const { data: order } = await this.orderRepository.create({
|
|
322
|
+
data: { userId: opts.userId },
|
|
323
|
+
options: { transaction },
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
for (const item of opts.items) {
|
|
327
|
+
await this.inventoryRepository.updateById({
|
|
328
|
+
id: item.productId,
|
|
329
|
+
data: { stock: item.quantity },
|
|
330
|
+
options: { transaction },
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
await transaction.commit();
|
|
335
|
+
log.info('Order placed | orderId: %s', order.id);
|
|
336
|
+
return order;
|
|
337
|
+
} catch (error) {
|
|
338
|
+
await transaction.rollback();
|
|
339
|
+
log.error('Order failed, rolled back | error: %s', error);
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Pass `{ transaction }` in the `options` field of any repository call. The repository API is identical with or without a transaction - only the underlying Drizzle connector switches.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Resolving a Service Imperatively
|
|
351
|
+
|
|
352
|
+
When you need to pull a service out of the container at runtime (rather than through constructor injection), use `this.get<T>`:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
// In Application.postConfigure() or a lifecycle hook
|
|
356
|
+
const testService = this.get<RowLockingTestService>({
|
|
357
|
+
key: BindingKeys.build({
|
|
358
|
+
namespace: BindingNamespaces.SERVICE,
|
|
359
|
+
key: RowLockingTestService.name,
|
|
360
|
+
}),
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
await testService.run();
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
This is useful for post-start hooks, one-off tasks that run after the server starts, or when the service is not a constructor dependency.
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## No Built-in CRUD Service
|
|
371
|
+
|
|
372
|
+
IGNIS intentionally does not provide a `BaseCrudService`. CRUD operations belong in the Repository layer (`DefaultCRUDRepository`). Services exist for business logic that cannot be expressed as pure data access: cross-cutting validation, multi-repository coordination, transaction management, and workflow orchestration.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Provider vs Service
|
|
377
|
+
|
|
378
|
+
| Aspect | Service | Provider |
|
|
379
|
+
|--------|---------|----------|
|
|
380
|
+
| **Purpose** | Business logic and orchestration | Factory - produces values or instances |
|
|
381
|
+
| **Base class** | `BaseService` | `BaseProvider<T>` |
|
|
382
|
+
| **Key method** | Business methods | `value(container): T` |
|
|
383
|
+
| **Pattern** | Singleton in DI scope | Factory pattern |
|
|
384
|
+
| **Registration** | `this.service(Ctor)` | `this.bind(...).toProvider(Ctor)` |
|
|
385
|
+
|
|
386
|
+
See [Providers Reference](./providers.md) for the factory pattern details.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## See Also
|
|
391
|
+
|
|
392
|
+
- **Related References:**
|
|
393
|
+
- [Controllers](./controllers.md) - HTTP handlers that call services
|
|
394
|
+
- [Repositories](./repositories/) - Data access layer injected into services
|
|
395
|
+
- [Providers](./providers.md) - Factory pattern, compare with services
|
|
396
|
+
- [Dependency Injection](./dependency-injection.md) - Container and injection system
|
|
397
|
+
|
|
398
|
+
- **Guides:**
|
|
399
|
+
- [Building Services](/guides/core-concepts/services.md)
|
|
400
|
+
- [Dependency Injection Guide](/guides/core-concepts/dependency-injection.md)
|
|
401
|
+
|
|
402
|
+
- **Best Practices:**
|
|
403
|
+
- [Architectural Patterns](/best-practices/architectural-patterns)
|
|
404
|
+
- [Testing Guide](/guides/tutorials/testing)
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Environment Variables Reference
|
|
2
2
|
|
|
3
|
-
Complete reference of all environment variables used by
|
|
3
|
+
Complete reference of all environment variables used by IGNIS framework.
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
IGNIS uses the `APP_ENV_` prefix for all framework-specific environment variables. This prevents conflicts with system variables like `PATH`, `HOME`, etc.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
# ✅
|
|
11
|
+
# ✅ IGNIS variables
|
|
12
12
|
APP_ENV_POSTGRES_HOST=localhost
|
|
13
13
|
|
|
14
14
|
# ❌ Might conflict with system
|
|
@@ -96,9 +96,9 @@ APP_ENV_APPLICATION_ROLES=api,worker
|
|
|
96
96
|
|----------|----------|---------|-------------|
|
|
97
97
|
| `APP_ENV_SERVER_HOST` | No | `localhost` | Server bind address |
|
|
98
98
|
| `APP_ENV_SERVER_PORT` | No | `3000` | Server port |
|
|
99
|
-
| `APP_ENV_SERVER_BASE_PATH` | No |
|
|
100
|
-
| `HOST` | No | - | Alternative to `APP_ENV_SERVER_HOST` |
|
|
101
|
-
| `PORT` | No | - | Alternative to `APP_ENV_SERVER_PORT` |
|
|
99
|
+
| `APP_ENV_SERVER_BASE_PATH` | No | - | Base path convention (`EnvironmentKeys` constant; not read by the framework itself) |
|
|
100
|
+
| `HOST` | No | - | Alternative to `APP_ENV_SERVER_HOST` (takes precedence) |
|
|
101
|
+
| `PORT` | No | - | Alternative to `APP_ENV_SERVER_PORT` (takes precedence) |
|
|
102
102
|
|
|
103
103
|
### Example
|
|
104
104
|
|
|
@@ -116,11 +116,11 @@ APP_ENV_SERVER_BASE_PATH=/v1/api
|
|
|
116
116
|
|
|
117
117
|
### Priority Order
|
|
118
118
|
|
|
119
|
-
The server
|
|
120
|
-
1. Explicit config
|
|
121
|
-
2. `
|
|
122
|
-
3. `
|
|
123
|
-
4. Default values
|
|
119
|
+
The server host/port resolution uses this priority (`packages/core/src/base/applications/abstract.ts`):
|
|
120
|
+
1. Explicit config passed to the application constructor
|
|
121
|
+
2. `HOST`/`PORT` variables (for cloud platforms)
|
|
122
|
+
3. `APP_ENV_SERVER_HOST`/`APP_ENV_SERVER_PORT` variables
|
|
123
|
+
4. Default values (`localhost`/`3000`)
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
## Database Variables (PostgreSQL)
|
|
@@ -179,13 +179,15 @@ export class PostgresDataSource extends BaseDataSource {
|
|
|
179
179
|
|
|
180
180
|
| Variable | Required | Default | Description |
|
|
181
181
|
|----------|----------|---------|-------------|
|
|
182
|
-
| `APP_ENV_APPLICATION_SECRET` |
|
|
183
|
-
| `APP_ENV_JWT_SECRET` |
|
|
184
|
-
| `APP_ENV_JWT_EXPIRES_IN` | No |
|
|
182
|
+
| `APP_ENV_APPLICATION_SECRET` | Yes* | - | Secret for encrypting JWT payload |
|
|
183
|
+
| `APP_ENV_JWT_SECRET` | Yes* | - | Secret for signing JWT tokens |
|
|
184
|
+
| `APP_ENV_JWT_EXPIRES_IN` | No | - | Token expiration in seconds (e.g., `86400` = 24h) |
|
|
185
|
+
|
|
186
|
+
*Required by convention when using the authentication component - see below.
|
|
185
187
|
|
|
186
188
|
### Security Requirements
|
|
187
189
|
|
|
188
|
-
|
|
190
|
+
The `AuthenticateComponent` receives its secrets programmatically via the `jwtOptions` binding (`jwtSecret`, `getTokenExpiresFn`), not by reading these environment variables directly. These `EnvironmentKeys` constants are the conventional way for your application to supply those values. The component throws at startup if `jwtSecret` is missing or left at the placeholder value - so wiring it from an unset environment variable will fail the boot.
|
|
189
191
|
|
|
190
192
|
### Generate Strong Secrets
|
|
191
193
|
|
|
@@ -218,6 +220,12 @@ APP_ENV_JWT_EXPIRES_IN=86400
|
|
|
218
220
|
| Variable | Required | Default | Description |
|
|
219
221
|
|----------|----------|---------|-------------|
|
|
220
222
|
| `APP_ENV_LOGGER_FOLDER_PATH` | No | `./` | Directory for log files |
|
|
223
|
+
| `APP_ENV_LOGGER_FORMAT` | No | `text` | Log output format |
|
|
224
|
+
| `APP_ENV_LOGGER_INSPECT_DEPTH` | No | `5` | How deep a `%s` argument is inspected. Node hard-codes depth `0` for `%s`, which prints `[Object]` one level in; IGNIS widens it. Non-negative integers only - an absent, invalid or negative value falls back to `5` |
|
|
225
|
+
| `APP_ENV_LOGGER_FILE_FREQUENCY` | No | `1h` | Log file rotation frequency |
|
|
226
|
+
| `APP_ENV_LOGGER_FILE_MAX_SIZE` | No | `100m` | Max size per log file |
|
|
227
|
+
| `APP_ENV_LOGGER_FILE_MAX_FILES` | No | `5d` | Log file retention |
|
|
228
|
+
| `APP_ENV_LOGGER_FILE_DATE_PATTERN` | No | `YYYYMMDD_HH` | Rotated file date pattern |
|
|
221
229
|
| `APP_ENV_LOGGER_DGRAM_HOST` | No | - | UDP log transport host |
|
|
222
230
|
| `APP_ENV_LOGGER_DGRAM_PORT` | No | - | UDP log transport port |
|
|
223
231
|
| `APP_ENV_LOGGER_DGRAM_LABEL` | No | - | Label for UDP logs |
|
|
@@ -240,6 +248,9 @@ APP_ENV_LOGGER_DGRAM_LEVELS=error,warn,info
|
|
|
240
248
|
|
|
241
249
|
## Storage Variables (MinIO/S3)
|
|
242
250
|
|
|
251
|
+
> [!NOTE]
|
|
252
|
+
> These are application-level conventions (used by the `vert` reference application), not variables read by the framework. `MinioHelper` and the StaticAsset component receive their configuration programmatically - your application wires these values in.
|
|
253
|
+
|
|
243
254
|
| Variable | Required | Default | Description |
|
|
244
255
|
|----------|----------|---------|-------------|
|
|
245
256
|
| `APP_ENV_MINIO_HOST` | Yes* | - | MinIO/S3 endpoint |
|
|
@@ -248,7 +259,7 @@ APP_ENV_LOGGER_DGRAM_LEVELS=error,warn,info
|
|
|
248
259
|
| `APP_ENV_MINIO_SECRET_KEY` | Yes* | - | Secret key |
|
|
249
260
|
| `APP_ENV_MINIO_USE_SSL` | No | `false` | Enable SSL |
|
|
250
261
|
|
|
251
|
-
*Required when
|
|
262
|
+
*Required (by application convention) when wiring MinIO-backed storage.
|
|
252
263
|
|
|
253
264
|
### Example
|
|
254
265
|
|
|
@@ -271,17 +282,20 @@ APP_ENV_MINIO_USE_SSL=true
|
|
|
271
282
|
|
|
272
283
|
## Mail Variables
|
|
273
284
|
|
|
285
|
+
> [!NOTE]
|
|
286
|
+
> These are application-level conventions, not variables read by the framework. The Mail component's transporter receives its SMTP/OAuth2 configuration programmatically - your application wires these values in.
|
|
287
|
+
|
|
274
288
|
| Variable | Required | Default | Description |
|
|
275
289
|
|----------|----------|---------|-------------|
|
|
276
|
-
| `APP_ENV_MAIL_HOST` | Yes* | `smtp.gmail.com` |
|
|
277
|
-
| `APP_ENV_MAIL_PORT` | No |
|
|
278
|
-
| `APP_ENV_MAIL_SECURE` | No |
|
|
290
|
+
| `APP_ENV_MAIL_HOST` | Yes* | - | SMTP host (e.g., `smtp.gmail.com`) |
|
|
291
|
+
| `APP_ENV_MAIL_PORT` | No | - | SMTP port (e.g., `465`) |
|
|
292
|
+
| `APP_ENV_MAIL_SECURE` | No | - | Use TLS |
|
|
279
293
|
| `APP_ENV_MAIL_USER` | Yes* | - | SMTP username/email |
|
|
280
294
|
| `APP_ENV_MAIL_CLIENT_ID` | Yes* | - | OAuth2 client ID |
|
|
281
295
|
| `APP_ENV_MAIL_CLIENT_SECRET` | Yes* | - | OAuth2 client secret |
|
|
282
296
|
| `APP_ENV_MAIL_REFRESH_TOKEN` | Yes* | - | OAuth2 refresh token |
|
|
283
297
|
|
|
284
|
-
*Required when
|
|
298
|
+
*Required (by application convention) when wiring the Mail component with OAuth2.
|
|
285
299
|
|
|
286
300
|
### Example (Gmail with OAuth2)
|
|
287
301
|
|
|
@@ -310,14 +324,16 @@ APP_ENV_MAIL_REFRESH_TOKEN=your-oauth2-refresh-token
|
|
|
310
324
|
| Variable | Required | Default | Description |
|
|
311
325
|
|----------|----------|---------|-------------|
|
|
312
326
|
| `DEBUG` | No | - | Enable debug mode |
|
|
313
|
-
| `NODE_ENV` | No | `development` | Environment mode |
|
|
327
|
+
| `NODE_ENV` | No | `development` | Environment mode. One of `local`, `debug`, `development`, `dev`, `sit`, `uat`, `alpha`, `beta`, `staging`, `production` |
|
|
314
328
|
| `ALLOW_EMPTY_ENV_VALUE` | No | `false` | Allow empty env values |
|
|
315
329
|
|
|
330
|
+
The gate is fail-closed: an environment IGNIS does not recognise is treated as production, so error responses are sanitized. `local`, `debug`, `development`, `dev` and `sit` are the development environments - only they expose internal error detail. `alpha`, `beta`, `staging` and `production` stay sanitized.
|
|
331
|
+
|
|
316
332
|
### Example
|
|
317
333
|
|
|
318
334
|
```bash
|
|
319
|
-
# Development
|
|
320
|
-
NODE_ENV=
|
|
335
|
+
# Development - `dev` is an alias of `development`, and gets the same error detail
|
|
336
|
+
NODE_ENV=dev
|
|
321
337
|
DEBUG=true
|
|
322
338
|
|
|
323
339
|
# Production
|
|
@@ -347,20 +363,20 @@ project/
|
|
|
347
363
|
|
|
348
364
|
## Custom Environment Prefix
|
|
349
365
|
|
|
350
|
-
You can customize the prefix from `
|
|
366
|
+
You can customize the prefix from `APP_ENV` to something else via the `APPLICATION_ENV_PREFIX` variable. It is read once when `@venizia/ignis-helpers` loads, so set it in the shell (or before any framework import):
|
|
351
367
|
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
|
|
368
|
+
```bash
|
|
369
|
+
# Set custom prefix
|
|
370
|
+
APPLICATION_ENV_PREFIX=MY_APP
|
|
355
371
|
|
|
356
|
-
|
|
357
|
-
|
|
372
|
+
# Now use MY_APP_ prefix
|
|
373
|
+
MY_APP_POSTGRES_HOST=localhost
|
|
358
374
|
```
|
|
359
375
|
|
|
360
376
|
|
|
361
377
|
## Validation
|
|
362
378
|
|
|
363
|
-
|
|
379
|
+
On startup, IGNIS iterates every `APP_ENV_*` (prefixed) variable that is set and throws if any has an empty value (`validateEnvs` in `packages/core/src/base/applications/abstract.ts`). It does not check for variables that are absent entirely - component-level validation (e.g., the authentication component's `jwtSecret` check) covers required values.
|
|
364
380
|
|
|
365
381
|
### Disable Validation
|
|
366
382
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Configuration Reference
|
|
2
2
|
|
|
3
|
-
Configuration options and environment variables for
|
|
3
|
+
Configuration options and environment variables for IGNIS applications.
|
|
4
4
|
|
|
5
5
|
## Quick Reference
|
|
6
6
|
|
|
@@ -11,15 +11,15 @@ Configuration options and environment variables for Ignis applications.
|
|
|
11
11
|
| Database | PostgreSQL connection | `APP_ENV_POSTGRES_HOST`, `APP_ENV_POSTGRES_DATABASE` |
|
|
12
12
|
| Authentication | JWT tokens and secrets | `APP_ENV_JWT_SECRET`, `APP_ENV_APPLICATION_SECRET` |
|
|
13
13
|
| Logging | Log file paths and transports | `APP_ENV_LOGGER_FOLDER_PATH` |
|
|
14
|
-
| Storage | MinIO/S3 file storage | `APP_ENV_MINIO_HOST`, `APP_ENV_MINIO_ACCESS_KEY` |
|
|
15
|
-
| Mail | SMTP email sending | `APP_ENV_MAIL_HOST`, `APP_ENV_MAIL_USER` |
|
|
14
|
+
| Storage | MinIO/S3 file storage (application-level convention) | `APP_ENV_MINIO_HOST`, `APP_ENV_MINIO_ACCESS_KEY` |
|
|
15
|
+
| Mail | SMTP email sending (application-level convention) | `APP_ENV_MAIL_HOST`, `APP_ENV_MAIL_USER` |
|
|
16
16
|
|
|
17
17
|
## Environment Variable Prefix
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
IGNIS uses the `APP_ENV_` prefix to avoid conflicts with system variables:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
# ✅
|
|
22
|
+
# ✅ IGNIS variables
|
|
23
23
|
APP_ENV_POSTGRES_HOST=localhost
|
|
24
24
|
|
|
25
25
|
# ❌ Might conflict with system
|
|
@@ -69,7 +69,7 @@ project/
|
|
|
69
69
|
|
|
70
70
|
### 3. Validation on Startup
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
IGNIS validates every set `APP_ENV_*` variable on startup and fails with a clear error if any is empty (bypass with `ALLOW_EMPTY_ENV_VALUE=true`). Absent variables are not flagged - components validate their own required inputs.
|
|
73
73
|
|
|
74
74
|
> **Related:** [Environment Variables Reference](./environment-variables.md) | [DataSources Guide](../../guides/core-concepts/persistent/datasources)
|
|
75
75
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# API Reference
|
|
2
2
|
|
|
3
|
-
Complete reference documentation for the
|
|
3
|
+
Complete reference documentation for the IGNIS framework. Find detailed API docs, type definitions, and usage examples for every class, component, and utility in the framework.
|
|
4
4
|
|
|
5
5
|
<div class="guide-cards">
|
|
6
6
|
|
|
@@ -63,7 +63,7 @@ Complete reference documentation for the Ignis framework. Find detailed API docs
|
|
|
63
63
|
<span class="stage-num">3</span>
|
|
64
64
|
<h4>Adding Features</h4>
|
|
65
65
|
</div>
|
|
66
|
-
<p><a href="/ignis/extensions/components/authentication/">Auth</a> → <a href="/ignis/extensions/components/socket-io/">Real-time</a> → <a href="/ignis/extensions/components/mail/">Email</a> → <a href="/ignis/extensions/components/
|
|
66
|
+
<p><a href="/ignis/extensions/components/authentication/">Auth</a> → <a href="/ignis/extensions/components/socket-io/">Real-time</a> → <a href="/ignis/extensions/components/mail/">Email</a> → <a href="/ignis/extensions/components/api-reference">API Docs</a></p>
|
|
67
67
|
<span class="stage-desc">Pre-built components for common features</span>
|
|
68
68
|
</div>
|
|
69
69
|
|
|
@@ -99,7 +99,7 @@ Complete reference documentation for the Ignis framework. Find detailed API docs
|
|
|
99
99
|
<span class="stage-num">7</span>
|
|
100
100
|
<h4>Testing & Quality</h4>
|
|
101
101
|
</div>
|
|
102
|
-
<p><a href="
|
|
102
|
+
<p><a href="./base/repositories/advanced">Mocking & Stubs</a> → <a href="./quick-reference">Best Practices</a></p>
|
|
103
103
|
<span class="stage-desc">Testing strategies, quality assurance, and code review</span>
|
|
104
104
|
</div>
|
|
105
105
|
|
|
@@ -123,18 +123,23 @@ class UserController extends BaseRestController {
|
|
|
123
123
|
|
|
124
124
|
**Query with Repository:**
|
|
125
125
|
```typescript
|
|
126
|
-
const users = await
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
const users = await userRepository.find({
|
|
127
|
+
filter: {
|
|
128
|
+
where: { isActive: true },
|
|
129
|
+
order: ['createdAt DESC'],
|
|
130
|
+
limit: 10,
|
|
131
|
+
},
|
|
130
132
|
});
|
|
131
133
|
```
|
|
132
134
|
|
|
133
135
|
**Schedule a Job:**
|
|
134
136
|
```typescript
|
|
135
|
-
CronHelper.
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
CronHelper.newInstance({
|
|
138
|
+
cronTime: '0 * * * *',
|
|
139
|
+
onTick: async () => {
|
|
140
|
+
await cleanupExpiredSessions();
|
|
141
|
+
},
|
|
142
|
+
}).start();
|
|
138
143
|
```
|
|
139
144
|
|
|
140
145
|
## Common Imports
|
|
@@ -156,7 +161,7 @@ import {
|
|
|
156
161
|
// Helpers
|
|
157
162
|
import {
|
|
158
163
|
LoggerFactory,
|
|
159
|
-
|
|
164
|
+
RedisSingleHelper,
|
|
160
165
|
QueueHelper,
|
|
161
166
|
} from '@venizia/ignis-helpers';
|
|
162
167
|
|
|
@@ -166,7 +171,7 @@ import { Container } from '@venizia/ignis-inversion';
|
|
|
166
171
|
|
|
167
172
|
## See Also
|
|
168
173
|
|
|
169
|
-
- [Getting Started](/guides/) - New to
|
|
174
|
+
- [Getting Started](/guides/) - New to IGNIS? Start here
|
|
170
175
|
- [Core Concepts](/guides/core-concepts/application/) - Deep dive into architecture
|
|
171
176
|
- [Best Practices](/best-practices/) - Production patterns
|
|
172
177
|
- [Changelogs](/changelogs/) - Version history
|