@venizia/ignis-docs 0.0.4-1 → 0.0.4-2

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.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/wiki/best-practices/api-usage-examples.md +1 -0
  3. package/wiki/best-practices/code-style-standards/advanced-patterns.md +259 -0
  4. package/wiki/best-practices/code-style-standards/constants-configuration.md +225 -0
  5. package/wiki/best-practices/code-style-standards/control-flow.md +245 -0
  6. package/wiki/best-practices/code-style-standards/documentation.md +221 -0
  7. package/wiki/best-practices/code-style-standards/function-patterns.md +142 -0
  8. package/wiki/best-practices/code-style-standards/index.md +110 -0
  9. package/wiki/best-practices/code-style-standards/naming-conventions.md +174 -0
  10. package/wiki/best-practices/code-style-standards/route-definitions.md +150 -0
  11. package/wiki/best-practices/code-style-standards/tooling.md +155 -0
  12. package/wiki/best-practices/code-style-standards/type-safety.md +165 -0
  13. package/wiki/best-practices/common-pitfalls.md +164 -3
  14. package/wiki/best-practices/contribution-workflow.md +1 -1
  15. package/wiki/best-practices/data-modeling.md +102 -2
  16. package/wiki/best-practices/error-handling.md +468 -0
  17. package/wiki/best-practices/index.md +204 -21
  18. package/wiki/best-practices/performance-optimization.md +180 -0
  19. package/wiki/best-practices/security-guidelines.md +249 -0
  20. package/wiki/best-practices/testing-strategies.md +620 -0
  21. package/wiki/changelogs/2026-01-05-range-queries-content-range.md +184 -0
  22. package/wiki/changelogs/2026-01-06-basic-authentication.md +103 -0
  23. package/wiki/changelogs/2026-01-07-controller-route-customization.md +209 -0
  24. package/wiki/changelogs/index.md +3 -0
  25. package/wiki/guides/core-concepts/components-guide.md +1 -1
  26. package/wiki/guides/core-concepts/persistent/models.md +10 -0
  27. package/wiki/guides/tutorials/complete-installation.md +1 -1
  28. package/wiki/guides/tutorials/testing.md +1 -1
  29. package/wiki/references/base/components.md +47 -29
  30. package/wiki/references/base/controllers.md +215 -18
  31. package/wiki/references/base/filter-system/fields-order-pagination.md +84 -0
  32. package/wiki/references/base/middlewares.md +33 -1
  33. package/wiki/references/base/models.md +40 -2
  34. package/wiki/references/base/repositories/index.md +2 -0
  35. package/wiki/references/components/authentication.md +261 -247
  36. package/wiki/references/helpers/index.md +1 -1
  37. package/wiki/references/src-details/core.md +1 -1
  38. package/wiki/best-practices/code-style-standards.md +0 -1193
@@ -0,0 +1,184 @@
1
+ ---
2
+ title: Range Queries & Content-Range Header
3
+ description: Added shouldQueryRange option for paginated API responses with HTTP Content-Range standard support
4
+ ---
5
+
6
+ # Changelog - 2026-01-05
7
+
8
+ ## Range Queries & Content-Range Header
9
+
10
+ This release adds the `shouldQueryRange` option to the `find()` method, enabling paginated API responses with range information following the HTTP Content-Range header standard.
11
+
12
+ ## Overview
13
+
14
+ - **shouldQueryRange Option**: New option for `find()` that returns data with range information
15
+ - **TDataRange Type**: New type for pagination range data (`start`, `end`, `total`)
16
+ - **HTTP Content-Range Standard**: Range format follows RFC 7233 for compatibility with browsers and HTTP clients
17
+ - **Parallel Execution**: Count and data queries run in parallel for optimal performance
18
+
19
+ ## New Features
20
+
21
+ ### shouldQueryRange Option
22
+
23
+ **Files:**
24
+ - `packages/core/src/base/repositories/common/types.ts`
25
+ - `packages/core/src/base/repositories/core/readable.ts`
26
+ - `packages/core/src/base/repositories/core/abstract.ts`
27
+
28
+ **Problem:** When building paginated APIs, you often need to return both the data and total count for pagination UI (showing "Page 1 of 10" or "Showing 1-20 of 200 results"). Previously, this required two separate queries.
29
+
30
+ **Solution:** Pass `shouldQueryRange: true` to get range information alongside the data:
31
+
32
+ ```typescript
33
+ // Without range (default behavior)
34
+ const users = await userRepo.find({
35
+ filter: { limit: 10, skip: 20 }
36
+ });
37
+ // Returns: Array<User>
38
+
39
+ // With range information
40
+ const result = await userRepo.find({
41
+ filter: { limit: 10, skip: 20 },
42
+ options: { shouldQueryRange: true }
43
+ });
44
+ // Returns: { data: Array<User>, range: TDataRange }
45
+ ```
46
+
47
+ **Benefits:**
48
+ - Single method call returns both data and count
49
+ - Count query runs in parallel with data fetch (no performance penalty)
50
+ - Range format follows HTTP Content-Range standard
51
+ - Easy to set HTTP headers for RESTful APIs
52
+
53
+ ### TDataRange Type
54
+
55
+ **File:** `packages/core/src/base/repositories/common/types.ts`
56
+
57
+ New type for range information following HTTP Content-Range standard:
58
+
59
+ ```typescript
60
+ type TDataRange = {
61
+ start: number; // Starting index (0-based, inclusive)
62
+ end: number; // Ending index (0-based, inclusive)
63
+ total: number; // Total count matching the query
64
+ };
65
+ ```
66
+
67
+ **HTTP Content-Range Header Format:**
68
+
69
+ ```typescript
70
+ const { data, range } = await repo.find({
71
+ filter: { limit: 10, skip: 20 },
72
+ options: { shouldQueryRange: true }
73
+ });
74
+
75
+ // Format: "unit start-end/total"
76
+ const contentRange = data.length > 0
77
+ ? `records ${range.start}-${range.end}/${range.total}`
78
+ : `records */${range.total}`;
79
+
80
+ res.setHeader('Content-Range', contentRange);
81
+ // → "records 20-29/100"
82
+ ```
83
+
84
+ | Scenario | Content-Range Header |
85
+ |----------|---------------------|
86
+ | Items 0-9 of 100 | `records 0-9/100` |
87
+ | Items 20-29 of 100 | `records 20-29/100` |
88
+ | No items found | `records */0` |
89
+ | Last page (90-99) | `records 90-99/100` |
90
+
91
+ ### Performance Optimization
92
+
93
+ When `shouldQueryRange: true`, the repository uses `Promise.all` to run the data query and count query in parallel:
94
+
95
+ ```typescript
96
+ // Runs in parallel - no extra latency
97
+ const [data, { count: total }] = await Promise.all([
98
+ dataPromise,
99
+ this.count({ where: mergedFilter.where ?? {}, options: effectiveOptions }),
100
+ ]);
101
+ ```
102
+
103
+ ## Files Changed
104
+
105
+ ### Core Package (`packages/core`)
106
+
107
+ | File | Changes |
108
+ |------|---------|
109
+ | `src/base/repositories/common/types.ts` | Added `TDataRange` type, updated `IReadableRepository.find()` overloads |
110
+ | `src/base/repositories/core/abstract.ts` | Added abstract `find()` overload for `shouldQueryRange: true` |
111
+ | `src/base/repositories/core/readable.ts` | Implemented `shouldQueryRange` logic with parallel execution |
112
+ | `src/base/controllers/factory/controller.ts` | Updated to use `shouldQueryRange` and set `Content-Range` header |
113
+
114
+ ### Helpers Package (`packages/helpers`)
115
+
116
+ | File | Changes |
117
+ |------|---------|
118
+ | `src/common/constants/http.ts` | Added `CONTENT_RANGE` header constant |
119
+
120
+ ## No Breaking Changes
121
+
122
+ All changes are additive. The default behavior of `find()` remains unchanged:
123
+
124
+ ```typescript
125
+ // Still works exactly as before
126
+ const users = await repo.find({ filter: { where: { active: true } } });
127
+ // Returns: Array<User>
128
+ ```
129
+
130
+ The new `shouldQueryRange` option is opt-in only.
131
+
132
+ ## Usage Examples
133
+
134
+ ### Basic Pagination API
135
+
136
+ ```typescript
137
+ // In your controller
138
+ async list(req, res) {
139
+ const page = parseInt(req.query.page) || 1;
140
+ const pageSize = parseInt(req.query.pageSize) || 20;
141
+
142
+ const { data, range } = await this.repo.find({
143
+ filter: {
144
+ where: req.query.filter,
145
+ limit: pageSize,
146
+ skip: (page - 1) * pageSize,
147
+ order: ['createdAt DESC']
148
+ },
149
+ options: { shouldQueryRange: true }
150
+ });
151
+
152
+ res.setHeader('Content-Range', `records ${range.start}-${range.end}/${range.total}`);
153
+ return res.json({
154
+ data,
155
+ pagination: {
156
+ page,
157
+ pageSize,
158
+ totalPages: Math.ceil(range.total / pageSize),
159
+ totalItems: range.total
160
+ }
161
+ });
162
+ }
163
+ ```
164
+
165
+ ### React Admin / Data Grid Integration
166
+
167
+ Many data grid libraries expect the `Content-Range` header for pagination:
168
+
169
+ ```typescript
170
+ // Server response
171
+ res.setHeader('Content-Range', `records 0-24/100`);
172
+ res.setHeader('Access-Control-Expose-Headers', 'Content-Range');
173
+ return res.json(data);
174
+
175
+ // Client can read the header
176
+ const response = await fetch('/api/users?limit=25&skip=0');
177
+ const contentRange = response.headers.get('Content-Range');
178
+ // → "records 0-24/100"
179
+ ```
180
+
181
+ ## Documentation
182
+
183
+ - [Fields, Order & Pagination](/references/base/filter-system/fields-order-pagination) - Range Queries section added
184
+ - [Repositories Overview](/references/base/repositories/) - Updated method tables
@@ -0,0 +1,103 @@
1
+ ---
2
+ title: Basic Authentication Strategy
3
+ description: Added HTTP Basic Authentication strategy for API authentication
4
+ ---
5
+
6
+ # Changelog - 2026-01-06
7
+
8
+ ## Basic Authentication Strategy
9
+
10
+ This release adds HTTP Basic Authentication support to the Ignis authentication system.
11
+
12
+ ## Overview
13
+
14
+ - **BasicAuthenticationStrategy**: New strategy implementing HTTP Basic auth
15
+ - **BasicTokenService**: Service for extracting and verifying credentials from `Authorization: Basic <base64>` header
16
+ - **Integration**: Works with existing AuthenticationStrategyRegistry
17
+
18
+ ## New Features
19
+
20
+ ### BasicAuthenticationStrategy
21
+
22
+ **File:** `packages/core/src/components/auth/authenticate/strategies/basic.strategy.ts`
23
+
24
+ New authentication strategy that:
25
+ - Extracts credentials from `Authorization: Basic <base64>` header
26
+ - Decodes base64-encoded `username:password` format
27
+ - Verifies credentials using custom `verifyCredentials` function
28
+ - Returns user profile on successful authentication
29
+
30
+ ### BasicTokenService
31
+
32
+ **File:** `packages/core/src/components/auth/authenticate/services/basic-token.service.ts`
33
+
34
+ Service handling credential extraction and verification:
35
+ - Parses `Authorization` header with `Basic` scheme
36
+ - Decodes base64 credentials to `username:password`
37
+ - Supports custom credential verification logic
38
+
39
+ ## Usage
40
+
41
+ ### Step 1: Configure Basic Auth in Controller
42
+
43
+ ```typescript
44
+ import { Authentication, ControllerFactory } from '@venizia/ignis';
45
+
46
+ const _Controller = ControllerFactory.defineCrudController({
47
+ repository: { name: UserRepository.name },
48
+ controller: { name: 'UserController', basePath: '/users' },
49
+
50
+ // Enable basic auth for all routes
51
+ authStrategies: [Authentication.STRATEGY_BASIC],
52
+
53
+ // Or per-route configuration
54
+ routes: {
55
+ create: {
56
+ authStrategies: [Authentication.STRATEGY_BASIC],
57
+ },
58
+ },
59
+ });
60
+ ```
61
+
62
+ ### Step 2: Implement Credential Verification
63
+
64
+ ```typescript
65
+ import { BasicTokenService } from '@venizia/ignis';
66
+
67
+ // Custom credential verification
68
+ const verifyCredentials = async (username: string, password: string) => {
69
+ const user = await userRepository.findOne({ where: { username } });
70
+
71
+ if (!user || !await comparePassword(password, user.passwordHash)) {
72
+ throw new HttpErrors.Unauthorized('Invalid credentials');
73
+ }
74
+
75
+ return { id: user.id, username: user.username };
76
+ };
77
+ ```
78
+
79
+ ### Step 3: Client Usage
80
+
81
+ ```bash
82
+ # Base64 encode credentials: username:password
83
+ curl -X GET http://api.example.com/users \
84
+ -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="
85
+ ```
86
+
87
+ ## Files Changed
88
+
89
+ ### Core Package (`packages/core`)
90
+
91
+ | File | Changes |
92
+ |------|---------|
93
+ | `src/components/auth/authenticate/strategies/basic.strategy.ts` | New BasicAuthenticationStrategy |
94
+ | `src/components/auth/authenticate/services/basic-token.service.ts` | New BasicTokenService |
95
+ | `src/components/auth/authenticate/common/keys.ts` | Added STRATEGY_BASIC constant |
96
+ | `src/components/auth/index.ts` | Export basic auth components |
97
+
98
+ ## Security Considerations
99
+
100
+ - Basic Auth transmits credentials in base64 (NOT encrypted)
101
+ - Always use HTTPS in production
102
+ - Consider rate limiting to prevent brute force attacks
103
+ - For sensitive APIs, prefer JWT or OAuth2 strategies
@@ -0,0 +1,209 @@
1
+ ---
2
+ title: Controller Route Customization
3
+ description: Enhanced request/response customization for CRUD controllers with typed method overrides
4
+ ---
5
+
6
+ # Changelog - 2026-01-07
7
+
8
+ ## Controller Factory Route Customization
9
+
10
+ This release enhances the Controller Factory with comprehensive request/response schema customization and introduces helper types for strongly-typed method overrides.
11
+
12
+ ## Overview
13
+
14
+ - **Route Customization**: New `request` and `response` configuration for all CRUD routes
15
+ - **Helper Types**: Added `THandlerContext` and `TInferSchema` for typed method overrides
16
+ - **Generic Definitions**: Controllers now preserve route definition types for better IDE support
17
+ - **Compact Descriptions**: OpenAPI route descriptions made more concise
18
+ - **Response Metadata**: Added meaningful response descriptions for API explorers
19
+
20
+ ## New Features
21
+
22
+ ### Enhanced Route Customization
23
+
24
+ **Files:**
25
+ - `packages/core/src/base/controllers/factory/definition.ts`
26
+ - `packages/core/src/base/controllers/common/types.ts`
27
+
28
+ **Problem:** Users could only customize `requestBody` and `schema` (response). No way to customize query parameters, headers, or path parameters.
29
+
30
+ **Solution:** New unified `request` and `response` configuration objects:
31
+
32
+ ```typescript
33
+ routes: {
34
+ create: {
35
+ authStrategies: ['jwt'],
36
+ request: {
37
+ body: CreateUserSchema, // Custom request body
38
+ headers: CustomHeadersSchema, // Custom headers
39
+ },
40
+ response: {
41
+ schema: PublicUserSchema, // Custom response body
42
+ },
43
+ },
44
+ find: {
45
+ skipAuth: true,
46
+ request: {
47
+ query: CustomQuerySchema, // Custom query parameters
48
+ },
49
+ response: {
50
+ schema: z.array(PublicUserSchema),
51
+ },
52
+ },
53
+ }
54
+ ```
55
+
56
+ **Customizable Components per Route:**
57
+
58
+ | Route | query | headers | params | body | response |
59
+ |-------|-------|---------|--------|------|----------|
60
+ | COUNT | ✅ | ✅ | - | - | ✅ |
61
+ | FIND | ✅ | ✅ | - | - | ✅ |
62
+ | FIND_BY_ID | ✅ | ✅ | ✅ | - | ✅ |
63
+ | FIND_ONE | ✅ | ✅ | - | - | ✅ |
64
+ | CREATE | - | ✅ | - | ✅ | ✅ |
65
+ | UPDATE_BY_ID | - | ✅ | ✅ | ✅ | ✅ |
66
+ | UPDATE_BY | ✅ | ✅ | - | ✅ | ✅ |
67
+ | DELETE_BY_ID | - | ✅ | ✅ | - | ✅ |
68
+ | DELETE_BY | ✅ | ✅ | - | - | ✅ |
69
+
70
+ ### Helper Types for Method Overrides
71
+
72
+ **File:** `packages/core/src/base/controllers/common/types.ts`
73
+
74
+ **Problem:** When overriding CRUD methods, the context type was not strongly typed.
75
+
76
+ **Solution:** New helper types for extracting context types from route definitions:
77
+
78
+ ```typescript
79
+ // Extract definitions type from controller
80
+ type TRouteDefinitions = InstanceType<typeof _Controller>['definitions'];
81
+
82
+ // Use THandlerContext for typed method overrides
83
+ override async create(opts: { context: THandlerContext<TRouteDefinitions, 'CREATE'> }) {
84
+ const { context } = opts;
85
+
86
+ // Use TInferSchema for typed request body
87
+ const data = context.req.valid('json') as TInferSchema<typeof CreateSchema>;
88
+
89
+ // data.code, data.name are now strongly typed!
90
+ return super.create(opts);
91
+ }
92
+ ```
93
+
94
+ **Available Route Keys:**
95
+ - `'COUNT'`, `'FIND'`, `'FIND_BY_ID'`, `'FIND_ONE'`
96
+ - `'CREATE'`, `'UPDATE_BY_ID'`, `'UPDATE_BY'`
97
+ - `'DELETE_BY_ID'`, `'DELETE_BY'`
98
+
99
+ ### Generic Controller Definitions
100
+
101
+ **Files:**
102
+ - `packages/core/src/base/controllers/abstract.ts`
103
+ - `packages/core/src/base/controllers/base.ts`
104
+ - `packages/core/src/base/controllers/factory/controller.ts`
105
+
106
+ **Problem:** Route definition types were lost, preventing proper type inference in overridden methods.
107
+
108
+ **Solution:** Added `Definitions` generic parameter to `AbstractController` and `BaseController`:
109
+
110
+ ```typescript
111
+ export abstract class AbstractController<
112
+ RouteEnv extends Env = Env,
113
+ RouteSchema extends Schema = {},
114
+ BasePath extends string = '/',
115
+ ConfigurableOptions extends object = {},
116
+ Definitions extends Record<string, TAuthRouteConfig<RouteConfig>> = Record<...>,
117
+ >
118
+ ```
119
+
120
+ The `definitions` property now preserves the actual route definition types.
121
+
122
+ ### Compact OpenAPI Descriptions
123
+
124
+ **File:** `packages/core/src/base/controllers/factory/definition.ts`
125
+
126
+ **Before:**
127
+ ```typescript
128
+ description: 'Returns the total count of records matching the optional where condition. Useful for pagination metadata or checking data existence without fetching records.'
129
+ ```
130
+
131
+ **After:**
132
+ ```typescript
133
+ description: 'Count records matching where condition'
134
+ ```
135
+
136
+ All route descriptions are now concise and easy to read in API explorers.
137
+
138
+ ### Response Metadata
139
+
140
+ **File:** `packages/core/src/base/controllers/factory/definition.ts`
141
+
142
+ Added meaningful response descriptions for OpenAPI:
143
+
144
+ | Route | Response Description |
145
+ |-------|---------------------|
146
+ | COUNT | Total count of matching records |
147
+ | FIND | Array of matching records (with optional count) |
148
+ | FIND_BY_ID | Single record matching ID or null |
149
+ | FIND_ONE | First matching record or null |
150
+ | CREATE | Created record with generated fields (id, createdAt, etc.) |
151
+ | UPDATE_BY_ID | Updated record with all current fields |
152
+ | UPDATE_BY | Array of updated records |
153
+ | DELETE_BY_ID | Deleted record data |
154
+ | DELETE_BY | Array of deleted records |
155
+
156
+ ## Files Changed
157
+
158
+ ### Core Package (`packages/core`)
159
+
160
+ | File | Changes |
161
+ |------|---------|
162
+ | `src/base/controllers/abstract.ts` | Added `Definitions` generic parameter |
163
+ | `src/base/controllers/base.ts` | Added `Definitions` generic parameter |
164
+ | `src/base/controllers/common/types.ts` | Added `THandlerContext`, `TInferSchema`, route config types |
165
+ | `src/base/controllers/factory/controller.ts` | Made `ICrudControllerOptions` generic, added type casts |
166
+ | `src/base/controllers/factory/definition.ts` | Updated route configs, compact descriptions, response metadata |
167
+
168
+ ### Examples (`examples/vert`)
169
+
170
+ | File | Changes |
171
+ |------|---------|
172
+ | `src/controllers/configuration.controller.ts` | Updated to use new route customization syntax |
173
+
174
+ ## Migration Guide
175
+
176
+ ### Step 1: Update Route Configuration Syntax
177
+
178
+ **Before:**
179
+ ```typescript
180
+ routes: {
181
+ create: {
182
+ requestBody: CreateSchema,
183
+ schema: ResponseSchema,
184
+ }
185
+ }
186
+ ```
187
+
188
+ **After:**
189
+ ```typescript
190
+ routes: {
191
+ create: {
192
+ request: { body: CreateSchema },
193
+ response: { schema: ResponseSchema },
194
+ }
195
+ }
196
+ ```
197
+
198
+ ### Step 2: Use Helper Types for Method Overrides
199
+
200
+ ```typescript
201
+ // Extract definitions type
202
+ type TRouteDefinitions = InstanceType<typeof _Controller>['definitions'];
203
+
204
+ // Use THandlerContext in method signature
205
+ override async create(opts: { context: THandlerContext<TRouteDefinitions, 'CREATE'> }) {
206
+ const data = context.req.valid('json') as TInferSchema<typeof CreateSchema>;
207
+ // ...
208
+ }
209
+ ```
@@ -17,6 +17,9 @@ This section tracks the history of significant changes, refactors, and updates t
17
17
 
18
18
  | Date | Title | Type |
19
19
  |------|-------|------|
20
+ | 2026-01-07 | [Controller Route Customization](./2026-01-07-controller-route-customization) | New Feature |
21
+ | 2026-01-06 | [Basic Authentication Strategy](./2026-01-06-basic-authentication) | New Feature |
22
+ | 2026-01-05 | [Range Queries & Content-Range Header](./2026-01-05-range-queries-content-range) | New Feature |
20
23
  | 2026-01-02 | [Default Filter & Repository Mixins](./2026-01-02-default-filter-and-repository-mixins) | New Feature |
21
24
  | 2025-12-31 | [JSON Path Filtering & Array Operators](./2025-12-31-json-path-filtering-array-operators) | New Feature |
22
25
  | 2025-12-31 | [String ID with Custom Generator](./2025-12-31-string-id-custom-generator) | Enhancement |
@@ -506,4 +506,4 @@ export class MyComponent extends BaseComponent {
506
506
 
507
507
  - **Best Practices:**
508
508
  - [Architectural Patterns](/best-practices/architectural-patterns) - Component architecture patterns
509
- - [Code Style Standards](/best-practices/code-style-standards) - Component coding standards
509
+ - [Code Style Standards](/best-practices/code-style-standards/) - Component coding standards
@@ -141,6 +141,16 @@ static override schema = pgTable('User', {
141
141
  | `generateDataTypeColumnDefs()` | `dataType`, `tValue`, `nValue`, etc. | Configuration tables |
142
142
  | `extraUserColumns()` | Combines audit + status + type | Full-featured entities |
143
143
 
144
+ :::note User Audit Options
145
+ The `generateUserAuditColumnDefs` enricher supports an `allowAnonymous` option (default: `true`). Set to `false` to require authenticated user context and throw errors for anonymous operations:
146
+ ```typescript
147
+ ...generateUserAuditColumnDefs({
148
+ created: { dataType: 'string', columnName: 'created_by', allowAnonymous: false },
149
+ modified: { dataType: 'string', columnName: 'modified_by', allowAnonymous: false },
150
+ })
151
+ ```
152
+ :::
153
+
144
154
  :::tip
145
155
  For a complete list of enrichers and options, see the [Schema Enrichers Reference](../../../references/base/models.md#schema-enrichers).
146
156
  :::
@@ -110,7 +110,7 @@ export default eslintConfigs;
110
110
  > export default [...eslintConfigs, { rules: { 'no-console': 'warn' } }];
111
111
  > ```
112
112
 
113
- > **Deep Dive:** See [Code Style Standards](/best-practices/code-style-standards) for detailed configuration options.
113
+ > **Deep Dive:** See [Code Style Standards](/best-practices/code-style-standards/) for detailed configuration options.
114
114
 
115
115
  :::tip Coming from Express/Hono/Fastify?
116
116
  This setup might seem verbose compared to minimal frameworks. The trade-off: ~50 lines of config upfront gives you scalable architecture for 10-1000+ endpoints without spaghetti code. For quick prototypes (< 5 endpoints), use plain Hono instead.
@@ -704,7 +704,7 @@ class CreateAndUpdateAndDeleteHandler extends TestCaseHandler {
704
704
  ## Next Steps
705
705
 
706
706
  - [Testing Reference](../../references/helpers/testing.md) - Complete API documentation
707
- - [Best Practices](../../best-practices/code-style-standards.md) - Code quality standards
707
+ - [Best Practices](../../best-practices/code-style-standards/) - Code quality standards
708
708
  - [Troubleshooting](../../best-practices/troubleshooting-tips.md) - Common issues
709
709
 
710
710
  ## Summary
@@ -120,8 +120,8 @@ import { AnyObject, ValueOrPromise } from '@venizia/ignis-helpers';
120
120
 
121
121
  // Options interface for the component
122
122
  export interface IAuthenticateOptions {
123
- alwaysAllowPaths: Array<string>;
124
- tokenOptions: IJWTTokenServiceOptions;
123
+ jwtOptions?: IJWTTokenServiceOptions;
124
+ basicOptions?: IBasicTokenServiceOptions;
125
125
  restOptions?: {
126
126
  useAuthController?: boolean;
127
127
  controllerOpts?: TDefineAuthControllerOpts;
@@ -307,16 +307,13 @@ export class HealthCheckComponent extends BaseComponent {
307
307
  ```typescript
308
308
  // src/components/auth/authenticate/component.ts
309
309
  import { BaseApplication, BaseComponent, inject, CoreBindings, Binding, ValueOrPromise, getError } from '@venizia/ignis';
310
- import { AuthenticateBindingKeys, IAuthenticateOptions, IJWTTokenServiceOptions } from './common';
311
- import { JWTTokenService } from './services';
310
+ import { AuthenticateBindingKeys, IAuthenticateOptions, IBasicTokenServiceOptions, IJWTTokenServiceOptions } from './common';
311
+ import { BasicTokenService, JWTTokenService } from './services';
312
312
  import { defineAuthController } from './controllers';
313
313
 
314
314
  const DEFAULT_OPTIONS: IAuthenticateOptions = {
315
- alwaysAllowPaths: [],
316
- tokenOptions: {
317
- applicationSecret: process.env.APP_ENV_APPLICATION_SECRET ?? '',
318
- jwtSecret: process.env.APP_ENV_JWT_SECRET ?? '',
319
- getTokenExpiresFn: () => parseInt(process.env.APP_ENV_JWT_EXPIRES_IN ?? '86400'),
315
+ restOptions: {
316
+ useAuthController: false,
320
317
  },
321
318
  };
322
319
 
@@ -336,37 +333,58 @@ export class AuthenticateComponent extends BaseComponent {
336
333
  });
337
334
  }
338
335
 
339
- // Split complex logic into private methods
340
- private defineAuth(): void {
341
- const options = this.application.get<IAuthenticateOptions>({
342
- key: AuthenticateBindingKeys.AUTHENTICATE_OPTIONS,
343
- });
344
-
345
- // Validate required configuration
346
- if (!options?.tokenOptions.jwtSecret) {
336
+ // Validate at least one auth option is provided
337
+ private validateOptions(opts: IAuthenticateOptions): void {
338
+ if (!opts.jwtOptions && !opts.basicOptions) {
347
339
  throw getError({
348
- message: '[defineAuth] Missing required jwtSecret configuration',
340
+ message: '[AuthenticateComponent] At least one of jwtOptions or basicOptions must be provided',
349
341
  });
350
342
  }
343
+ }
344
+
345
+ // Configure JWT authentication if jwtOptions is provided
346
+ private defineJWTAuth(opts: IAuthenticateOptions): void {
347
+ if (!opts.jwtOptions) return;
351
348
 
352
- // Bind service options
353
349
  this.application
354
350
  .bind<IJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS })
355
- .toValue(options.tokenOptions);
356
-
357
- // Register service
351
+ .toValue(opts.jwtOptions);
358
352
  this.application.service(JWTTokenService);
353
+ }
354
+
355
+ // Configure Basic authentication if basicOptions is provided
356
+ private defineBasicAuth(opts: IAuthenticateOptions): void {
357
+ if (!opts.basicOptions) return;
358
+
359
+ this.application
360
+ .bind<IBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTIONS })
361
+ .toValue(opts.basicOptions);
362
+ this.application.service(BasicTokenService);
363
+ }
364
+
365
+ // Configure auth controllers if enabled
366
+ private defineControllers(opts: IAuthenticateOptions): void {
367
+ if (!opts.restOptions?.useAuthController) return;
359
368
 
360
- // Conditionally register controller
361
- if (options.restOptions?.useAuthController) {
362
- this.application.controller(
363
- defineAuthController(options.restOptions.controllerOpts),
364
- );
369
+ // Auth controller requires JWT for token generation
370
+ if (!opts.jwtOptions) {
371
+ throw getError({
372
+ message: '[defineControllers] Auth controller requires jwtOptions to be configured',
373
+ });
365
374
  }
375
+
376
+ this.application.controller(defineAuthController(opts.restOptions.controllerOpts));
366
377
  }
367
378
 
368
379
  override binding(): ValueOrPromise<void> {
369
- this.defineAuth();
380
+ const options = this.application.get<IAuthenticateOptions>({
381
+ key: AuthenticateBindingKeys.AUTHENTICATE_OPTIONS,
382
+ });
383
+
384
+ this.validateOptions(options);
385
+ this.defineJWTAuth(options);
386
+ this.defineBasicAuth(options);
387
+ this.defineControllers(options);
370
388
  }
371
389
  }
372
390
  ```
@@ -578,4 +596,4 @@ export * from './controller';
578
596
 
579
597
  - **Best Practices:**
580
598
  - [Architectural Patterns](/best-practices/architectural-patterns) - Component design patterns
581
- - [Code Style Standards](/best-practices/code-style-standards) - Component coding standards
599
+ - [Code Style Standards](/best-practices/code-style-standards/) - Component coding standards