@venizia/ignis-docs 0.0.1-1 → 0.0.1-10
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/LICENSE.md +102 -0
- package/README.md +459 -0
- package/dist/mcp-server/common/config.d.ts +64 -0
- package/dist/mcp-server/common/config.d.ts.map +1 -0
- package/dist/mcp-server/common/config.js +82 -0
- package/dist/mcp-server/common/config.js.map +1 -0
- package/dist/mcp-server/common/index.d.ts +3 -0
- package/dist/mcp-server/common/index.d.ts.map +1 -0
- package/dist/mcp-server/common/index.js.map +1 -0
- package/dist/mcp-server/common/paths.d.ts.map +1 -0
- package/{mcp-server/dist → dist/mcp-server}/common/paths.js +13 -11
- package/dist/mcp-server/common/paths.js.map +1 -0
- package/{mcp-server/dist → dist/mcp-server}/helpers/docs.helper.d.ts +5 -5
- package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -0
- package/{mcp-server/dist → dist/mcp-server}/helpers/docs.helper.js +38 -34
- package/dist/mcp-server/helpers/docs.helper.js.map +1 -0
- package/dist/mcp-server/helpers/github.helper.d.ts +37 -0
- package/dist/mcp-server/helpers/github.helper.d.ts.map +1 -0
- package/dist/mcp-server/helpers/github.helper.js +100 -0
- package/dist/mcp-server/helpers/github.helper.js.map +1 -0
- package/dist/mcp-server/helpers/index.d.ts +4 -0
- package/dist/mcp-server/helpers/index.d.ts.map +1 -0
- package/{mcp-server/dist → dist/mcp-server}/helpers/index.js +1 -0
- package/dist/mcp-server/helpers/index.js.map +1 -0
- package/dist/mcp-server/helpers/logger.helper.d.ts.map +1 -0
- package/dist/mcp-server/helpers/logger.helper.js.map +1 -0
- package/{mcp-server/dist → dist/mcp-server}/index.d.ts.map +1 -1
- package/dist/mcp-server/index.js +90 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/{mcp-server/dist → dist/mcp-server}/tools/base.tool.d.ts +8 -12
- package/dist/mcp-server/tools/base.tool.d.ts.map +1 -0
- package/{mcp-server/dist → dist/mcp-server}/tools/base.tool.js +3 -5
- package/dist/mcp-server/tools/base.tool.js.map +1 -0
- package/{mcp-server/dist/tools/get-doc-content.tool.d.ts → dist/mcp-server/tools/docs/get-document-content.tool.d.ts} +13 -17
- package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts.map +1 -0
- package/{mcp-server/dist/tools/get-doc-content.tool.js → dist/mcp-server/tools/docs/get-document-content.tool.js} +20 -22
- package/dist/mcp-server/tools/docs/get-document-content.tool.js.map +1 -0
- package/{mcp-server/dist/tools/get-doc-metadata.tool.d.ts → dist/mcp-server/tools/docs/get-document-metadata.tool.d.ts} +21 -25
- package/dist/mcp-server/tools/docs/get-document-metadata.tool.d.ts.map +1 -0
- package/{mcp-server/dist/tools/get-doc-metadata.tool.js → dist/mcp-server/tools/docs/get-document-metadata.tool.js} +35 -27
- package/dist/mcp-server/tools/docs/get-document-metadata.tool.js.map +1 -0
- package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts +50 -0
- package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/docs/get-package-overview.tool.js +221 -0
- package/dist/mcp-server/tools/docs/get-package-overview.tool.js.map +1 -0
- package/dist/mcp-server/tools/docs/index.d.ts +7 -0
- package/dist/mcp-server/tools/docs/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/docs/index.js +23 -0
- package/dist/mcp-server/tools/docs/index.js.map +1 -0
- package/{mcp-server/dist/tools → dist/mcp-server/tools/docs}/list-categories.tool.d.ts +3 -3
- package/dist/mcp-server/tools/docs/list-categories.tool.d.ts.map +1 -0
- package/{mcp-server/dist/tools → dist/mcp-server/tools/docs}/list-categories.tool.js +10 -9
- package/dist/mcp-server/tools/docs/list-categories.tool.js.map +1 -0
- package/{mcp-server/dist/tools/list-docs.tool.d.ts → dist/mcp-server/tools/docs/list-documents.tool.d.ts} +5 -5
- package/dist/mcp-server/tools/docs/list-documents.tool.d.ts.map +1 -0
- package/{mcp-server/dist/tools/list-docs.tool.js → dist/mcp-server/tools/docs/list-documents.tool.js} +15 -14
- package/dist/mcp-server/tools/docs/list-documents.tool.js.map +1 -0
- package/{mcp-server/dist/tools/search-docs.tool.d.ts → dist/mcp-server/tools/docs/search-documents.tool.d.ts} +23 -19
- package/dist/mcp-server/tools/docs/search-documents.tool.d.ts.map +1 -0
- package/{mcp-server/dist/tools/search-docs.tool.js → dist/mcp-server/tools/docs/search-documents.tool.js} +29 -25
- package/dist/mcp-server/tools/docs/search-documents.tool.js.map +1 -0
- package/dist/mcp-server/tools/github/index.d.ts +5 -0
- package/dist/mcp-server/tools/github/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/github/index.js +21 -0
- package/dist/mcp-server/tools/github/index.js.map +1 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +28 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.js +98 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.js.map +1 -0
- package/dist/mcp-server/tools/github/search-code.tool.d.ts +42 -0
- package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/github/search-code.tool.js +194 -0
- package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -0
- package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts +55 -0
- package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +167 -0
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -0
- package/dist/mcp-server/tools/github/view-source-file.tool.d.ts +26 -0
- package/dist/mcp-server/tools/github/view-source-file.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/github/view-source-file.tool.js +91 -0
- package/dist/mcp-server/tools/github/view-source-file.tool.js.map +1 -0
- package/dist/mcp-server/tools/index.d.ts +4 -0
- package/dist/mcp-server/tools/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/index.js +22 -0
- package/dist/mcp-server/tools/index.js.map +1 -0
- package/package.json +46 -23
- package/wiki/changelogs/2025-12-16-initial-architecture.md +145 -0
- package/wiki/changelogs/2025-12-16-model-repo-datasource-refactor.md +300 -0
- package/wiki/changelogs/2025-12-17-refactor.md +90 -0
- package/wiki/changelogs/2025-12-18-performance-optimizations.md +130 -0
- package/wiki/changelogs/2025-12-18-repository-validation-security.md +249 -0
- package/wiki/changelogs/index.md +33 -0
- package/wiki/changelogs/planned-transaction-support.md +216 -0
- package/wiki/changelogs/template.md +123 -0
- package/wiki/get-started/5-minute-quickstart.md +1 -1
- package/wiki/get-started/best-practices/api-usage-examples.md +54 -8
- package/wiki/get-started/best-practices/architectural-patterns.md +43 -2
- package/wiki/get-started/best-practices/code-style-standards.md +41 -0
- package/wiki/get-started/best-practices/common-pitfalls.md +5 -3
- package/wiki/get-started/best-practices/contribution-workflow.md +40 -6
- package/wiki/get-started/best-practices/data-modeling.md +177 -0
- package/wiki/get-started/best-practices/security-guidelines.md +3 -1
- package/wiki/get-started/building-a-crud-api.md +63 -78
- package/wiki/get-started/core-concepts/components.md +4 -2
- package/wiki/get-started/core-concepts/controllers.md +14 -14
- package/wiki/get-started/core-concepts/dependency-injection.md +13 -1
- package/wiki/get-started/core-concepts/persistent.md +383 -431
- package/wiki/get-started/core-concepts/services.md +21 -27
- package/wiki/get-started/mcp-docs-server.md +130 -32
- package/wiki/get-started/philosophy.md +198 -25
- package/wiki/get-started/quickstart.md +1 -1
- package/wiki/public/logo.svg +1 -0
- package/wiki/references/base/application.md +5 -5
- package/wiki/references/base/components.md +1 -1
- package/wiki/references/base/controllers.md +43 -17
- package/wiki/references/base/datasources.md +195 -33
- package/wiki/references/base/dependency-injection.md +8 -7
- package/wiki/references/base/models.md +713 -25
- package/wiki/references/base/repositories.md +475 -22
- package/wiki/references/base/services.md +2 -2
- package/wiki/references/components/authentication.md +228 -10
- package/wiki/references/components/health-check.md +1 -1
- package/wiki/references/components/index.md +4 -2
- package/wiki/references/components/static-asset.md +1289 -0
- package/wiki/references/components/swagger.md +1 -1
- package/wiki/references/helpers/error.md +2 -2
- package/wiki/references/helpers/inversion.md +29 -14
- package/wiki/references/helpers/storage.md +538 -11
- package/wiki/references/src-details/core.md +21 -6
- package/wiki/references/src-details/docs.md +19 -9
- package/wiki/references/src-details/inversion.md +4 -4
- package/wiki/references/src-details/mcp-server.md +185 -234
- package/wiki/references/utilities/index.md +1 -1
- package/wiki/references/utilities/request.md +162 -3
- package/mcp-server/dist/common/config.d.ts +0 -27
- package/mcp-server/dist/common/config.d.ts.map +0 -1
- package/mcp-server/dist/common/config.js +0 -27
- package/mcp-server/dist/common/config.js.map +0 -1
- package/mcp-server/dist/common/index.d.ts +0 -3
- package/mcp-server/dist/common/index.d.ts.map +0 -1
- package/mcp-server/dist/common/index.js.map +0 -1
- package/mcp-server/dist/common/paths.d.ts.map +0 -1
- package/mcp-server/dist/common/paths.js.map +0 -1
- package/mcp-server/dist/helpers/docs.helper.d.ts.map +0 -1
- package/mcp-server/dist/helpers/docs.helper.js.map +0 -1
- package/mcp-server/dist/helpers/index.d.ts +0 -3
- package/mcp-server/dist/helpers/index.d.ts.map +0 -1
- package/mcp-server/dist/helpers/index.js.map +0 -1
- package/mcp-server/dist/helpers/logger.helper.d.ts.map +0 -1
- package/mcp-server/dist/helpers/logger.helper.js.map +0 -1
- package/mcp-server/dist/index.js +0 -62
- package/mcp-server/dist/index.js.map +0 -1
- package/mcp-server/dist/tools/base.tool.d.ts.map +0 -1
- package/mcp-server/dist/tools/base.tool.js.map +0 -1
- package/mcp-server/dist/tools/get-doc-content.tool.d.ts.map +0 -1
- package/mcp-server/dist/tools/get-doc-content.tool.js.map +0 -1
- package/mcp-server/dist/tools/get-doc-metadata.tool.d.ts.map +0 -1
- package/mcp-server/dist/tools/get-doc-metadata.tool.js.map +0 -1
- package/mcp-server/dist/tools/index.d.ts +0 -8
- package/mcp-server/dist/tools/index.d.ts.map +0 -1
- package/mcp-server/dist/tools/index.js +0 -18
- package/mcp-server/dist/tools/index.js.map +0 -1
- package/mcp-server/dist/tools/list-categories.tool.d.ts.map +0 -1
- package/mcp-server/dist/tools/list-categories.tool.js.map +0 -1
- package/mcp-server/dist/tools/list-docs.tool.d.ts.map +0 -1
- package/mcp-server/dist/tools/list-docs.tool.js.map +0 -1
- package/mcp-server/dist/tools/search-docs.tool.d.ts.map +0 -1
- package/mcp-server/dist/tools/search-docs.tool.js.map +0 -1
- /package/{mcp-server/dist → dist/mcp-server}/common/index.js +0 -0
- /package/{mcp-server/dist → dist/mcp-server}/common/paths.d.ts +0 -0
- /package/{mcp-server/dist → dist/mcp-server}/helpers/logger.helper.d.ts +0 -0
- /package/{mcp-server/dist → dist/mcp-server}/helpers/logger.helper.js +0 -0
- /package/{mcp-server/dist → dist/mcp-server}/index.d.ts +0 -0
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
get,
|
|
53
53
|
post,
|
|
54
54
|
TRouteContext,
|
|
55
|
+
HTTP,
|
|
55
56
|
} from '@venizia/ignis';
|
|
56
57
|
import { ROUTE_CONFIGS } from './definitions';
|
|
57
58
|
|
|
@@ -62,7 +63,7 @@ export class TestController extends BaseController {
|
|
|
62
63
|
@get({ configs: ROUTE_CONFIGS['/4'] })
|
|
63
64
|
getWithDecorator(context: TRouteContext<(typeof ROUTE_CONFIGS)['/4']>) {
|
|
64
65
|
// context is fully typed!
|
|
65
|
-
return context.json({ message: 'Hello from decorator', method: 'GET' });
|
|
66
|
+
return context.json({ message: 'Hello from decorator', method: 'GET' }, HTTP.ResultCodes.RS_2.Ok);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
@post({ configs: ROUTE_CONFIGS['/5'] })
|
|
@@ -71,11 +72,14 @@ export class TestController extends BaseController {
|
|
|
71
72
|
const body = context.req.valid('json');
|
|
72
73
|
|
|
73
74
|
// The response is validated against the schema
|
|
74
|
-
return context.json(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
return context.json(
|
|
76
|
+
{
|
|
77
|
+
id: crypto.randomUUID(),
|
|
78
|
+
name: body.name,
|
|
79
|
+
age: body.age,
|
|
80
|
+
},
|
|
81
|
+
HTTP.ResultCodes.RS_2.Ok,
|
|
82
|
+
);
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
```
|
|
@@ -97,7 +101,7 @@ export class TestController extends BaseController {
|
|
|
97
101
|
this.defineRoute({
|
|
98
102
|
configs: ROUTE_CONFIGS['/1'],
|
|
99
103
|
handler: context => {
|
|
100
|
-
return context.json({ message: 'Hello' });
|
|
104
|
+
return context.json({ message: 'Hello' }, HTTP.ResultCodes.RS_2.Ok);
|
|
101
105
|
},
|
|
102
106
|
});
|
|
103
107
|
|
|
@@ -106,7 +110,7 @@ export class TestController extends BaseController {
|
|
|
106
110
|
configs: ROUTE_CONFIGS['/3'],
|
|
107
111
|
}).to({
|
|
108
112
|
handler: context => {
|
|
109
|
-
return context.json({ message: 'Hello 3' });
|
|
113
|
+
return context.json({ message: 'Hello 3' }, HTTP.ResultCodes.RS_2.Ok);
|
|
110
114
|
},
|
|
111
115
|
});
|
|
112
116
|
}
|
|
@@ -219,4 +223,46 @@ const deleted = await configurationRepository.deleteById({
|
|
|
219
223
|
id: newRecord.data!.id,
|
|
220
224
|
options: { shouldReturn: true }, // Option to return the deleted record
|
|
221
225
|
});
|
|
226
|
+
|
|
227
|
+
## Server-Side Rendering (JSX)
|
|
228
|
+
|
|
229
|
+
Ignis supports server-side rendering using Hono's JSX middleware. This is useful for returning HTML content, such as landing pages or simple admin views.
|
|
230
|
+
|
|
231
|
+
**Usage:**
|
|
232
|
+
|
|
233
|
+
Use `defineJSXRoute` in your controller and `htmlResponse` for documentation.
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { BaseController, controller, htmlResponse } from '@venizia/ignis';
|
|
237
|
+
|
|
238
|
+
@controller({ path: '/pages' })
|
|
239
|
+
export class PageController extends BaseController {
|
|
240
|
+
|
|
241
|
+
override binding(): void {
|
|
242
|
+
this.defineJSXRoute({
|
|
243
|
+
configs: {
|
|
244
|
+
method: 'get',
|
|
245
|
+
path: '/welcome',
|
|
246
|
+
description: 'Welcome Page',
|
|
247
|
+
responses: htmlResponse({ description: 'HTML Welcome Page' }),
|
|
248
|
+
},
|
|
249
|
+
handler: (c) => {
|
|
250
|
+
const title = 'Welcome to Ignis';
|
|
251
|
+
|
|
252
|
+
// Return JSX directly
|
|
253
|
+
return c.html(
|
|
254
|
+
<html>
|
|
255
|
+
<head><title>{title}</title></head>
|
|
256
|
+
<body>
|
|
257
|
+
<h1>{title}</h1>
|
|
258
|
+
<p>Server-side rendered content.</p>
|
|
259
|
+
</body>
|
|
260
|
+
</html>
|
|
261
|
+
);
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
222
268
|
```
|
|
@@ -103,7 +103,7 @@ export class ConfigurationController extends _Controller {
|
|
|
103
103
|
|
|
104
104
|
## 3. Component-Based Modularity
|
|
105
105
|
|
|
106
|
-
Components bundle related features into self-contained,
|
|
106
|
+
Components bundle a group of related, reusable, and pluggable features into self-contained modules. A single component can encapsulate multiple providers, services, controllers, and repositories, essentially functioning as a mini-application that can be easily "plugged in" to any Ignis project.
|
|
107
107
|
|
|
108
108
|
**Built-in Components:**
|
|
109
109
|
- `AuthenticateComponent` - JWT authentication
|
|
@@ -126,4 +126,45 @@ export class Application extends BaseApplication {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
```
|
|
129
|
-
This architecture keeps the main `Application` class clean and focused on high-level assembly, while the details of each feature are neatly encapsulated within their respective components.
|
|
129
|
+
This architecture keeps the main `Application` class clean and focused on high-level assembly, while the details of each feature are neatly encapsulated within their respective components.
|
|
130
|
+
|
|
131
|
+
## 4. Custom Components
|
|
132
|
+
|
|
133
|
+
You can encapsulate your own logic or third-party integrations (like Socket.IO, Redis, specific Cron jobs) into reusable Components.
|
|
134
|
+
|
|
135
|
+
**Structure of a Component:**
|
|
136
|
+
1. Extend `BaseComponent`.
|
|
137
|
+
2. Define default `bindings` (optional configuration/options).
|
|
138
|
+
3. Implement `binding()` to register services, providers, or attach logic to the application.
|
|
139
|
+
|
|
140
|
+
**Example (`SocketIOComponent`):**
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { BaseComponent, inject, CoreBindings, Binding } from '@venizia/ignis';
|
|
144
|
+
|
|
145
|
+
export class MySocketComponent extends BaseComponent {
|
|
146
|
+
constructor(
|
|
147
|
+
@inject({ key: CoreBindings.APPLICATION_INSTANCE }) private application: BaseApplication,
|
|
148
|
+
) {
|
|
149
|
+
super({
|
|
150
|
+
scope: MySocketComponent.name,
|
|
151
|
+
// Automatically register bindings when component is loaded
|
|
152
|
+
initDefault: { enable: true, container: application },
|
|
153
|
+
bindings: {
|
|
154
|
+
// Define default configuration binding
|
|
155
|
+
'my.socket.options': Binding.bind({ key: 'my.socket.options' }).toValue({ port: 8080 }),
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// The binding method is called during application startup (preConfigure)
|
|
161
|
+
override binding(): void {
|
|
162
|
+
const options = this.application.get({ key: 'my.socket.options' });
|
|
163
|
+
|
|
164
|
+
this.logger.info('Initializing Socket.IO with options: %j', options);
|
|
165
|
+
|
|
166
|
+
// Perform setup logic, register other services, etc.
|
|
167
|
+
// this.application.bind(...).toValue(...);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
@@ -120,3 +120,44 @@ Use the centralized TypeScript configs:
|
|
|
120
120
|
- `skipLibCheck: true` - Faster compilation
|
|
121
121
|
|
|
122
122
|
See [`@venizia/dev-configs` documentation](../../references/src-details/dev-configs.md) for full details.
|
|
123
|
+
|
|
124
|
+
## Environment Variables Management
|
|
125
|
+
|
|
126
|
+
Avoid using `process.env` directly in your business logic. Instead, use the `applicationEnvironment` helper and define your keys as constants. This ensures type safety and centralized management.
|
|
127
|
+
|
|
128
|
+
**Define Keys (`src/common/environments.ts`):**
|
|
129
|
+
```typescript
|
|
130
|
+
export class EnvironmentKeys {
|
|
131
|
+
static readonly APP_ENV_STRIPE_KEY = 'APP_ENV_STRIPE_KEY';
|
|
132
|
+
static readonly APP_ENV_MAX_RETRIES = 'APP_ENV_MAX_RETRIES';
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Usage:**
|
|
137
|
+
```typescript
|
|
138
|
+
import { applicationEnvironment } from '@venizia/ignis';
|
|
139
|
+
import { EnvironmentKeys } from '@/common/environments';
|
|
140
|
+
|
|
141
|
+
// Correct usage
|
|
142
|
+
const stripeKey = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_STRIPE_KEY);
|
|
143
|
+
const retries = applicationEnvironment.get<number>(EnvironmentKeys.APP_ENV_MAX_RETRIES);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Standardized Error Handling
|
|
147
|
+
|
|
148
|
+
Use the `getError` helper and `HTTP` constants to throw consistent, formatted exceptions that the framework's error handler can process correctly.
|
|
149
|
+
|
|
150
|
+
**Example:**
|
|
151
|
+
```typescript
|
|
152
|
+
import { getError, HTTP } from '@venizia/ignis';
|
|
153
|
+
|
|
154
|
+
if (!record) {
|
|
155
|
+
throw getError({
|
|
156
|
+
statusCode: HTTP.ResultCodes.RS_4.NotFound,
|
|
157
|
+
message: 'Record not found',
|
|
158
|
+
// Optional details
|
|
159
|
+
details: { id: requestedId }
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
@@ -66,6 +66,8 @@ export class Application extends BaseApplication {
|
|
|
66
66
|
|
|
67
67
|
- **Bad:**
|
|
68
68
|
```typescript
|
|
69
|
+
import { ApplicationError, getError } from '@venizia/ignis';
|
|
70
|
+
|
|
69
71
|
// In a Controller
|
|
70
72
|
async createUser(c: Context) {
|
|
71
73
|
const { name, email, companyName } = c.req.valid('json');
|
|
@@ -73,13 +75,13 @@ export class Application extends BaseApplication {
|
|
|
73
75
|
// Complex logic inside the controller
|
|
74
76
|
const existingUser = await this.userRepository.findByEmail(email);
|
|
75
77
|
if (existingUser) {
|
|
76
|
-
throw
|
|
78
|
+
throw getError({ message: 'Email already exists' });
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
const company = await this.companyRepository.findOrCreate(companyName);
|
|
80
82
|
const user = await this.userRepository.create({ name, email, companyId: company.id });
|
|
81
83
|
|
|
82
|
-
return c.json(user);
|
|
84
|
+
return c.json(user, HTTP.ResultCodes.RS_2.Ok);
|
|
83
85
|
}
|
|
84
86
|
```
|
|
85
87
|
- **Good:**
|
|
@@ -89,7 +91,7 @@ export class Application extends BaseApplication {
|
|
|
89
91
|
const userData = c.req.valid('json');
|
|
90
92
|
// Delegate to the service
|
|
91
93
|
const newUser = await this.userService.createUser(userData);
|
|
92
|
-
return c.json(newUser);
|
|
94
|
+
return c.json(newUser, HTTP.ResultCodes.RS_2.Ok);
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
// In UserService
|
|
@@ -32,13 +32,45 @@ feature/*, fix/*, docs/* (your work)
|
|
|
32
32
|
git clone https://github.com/YOUR_USERNAME/ignis.git
|
|
33
33
|
cd ignis
|
|
34
34
|
|
|
35
|
-
# 3. Install dependencies
|
|
36
|
-
|
|
35
|
+
# 3. Install dependencies (this also runs force-update to fetch latest from NPM)
|
|
36
|
+
make install
|
|
37
|
+
# Or: bun install
|
|
37
38
|
|
|
38
39
|
# 4. Add upstream remote
|
|
39
40
|
git remote add upstream https://github.com/VENIZIA-AI/ignis.git
|
|
40
41
|
```
|
|
41
42
|
|
|
43
|
+
## Makefile Commands
|
|
44
|
+
|
|
45
|
+
The project uses a Makefile for common development tasks:
|
|
46
|
+
|
|
47
|
+
| Command | Description |
|
|
48
|
+
|---------|-------------|
|
|
49
|
+
| `make install` | Install dependencies and force-update from NPM |
|
|
50
|
+
| `make update` | Force update all packages from NPM registry |
|
|
51
|
+
| `make build` | Rebuild all packages in correct order |
|
|
52
|
+
| `make clean` | Clean build artifacts from all packages |
|
|
53
|
+
| `make lint` | Lint all packages |
|
|
54
|
+
| `make help` | Show all available commands |
|
|
55
|
+
|
|
56
|
+
**Individual package builds:**
|
|
57
|
+
```bash
|
|
58
|
+
make core # Build @venizia/ignis (after dependencies)
|
|
59
|
+
make helpers # Build @venizia/ignis-helpers
|
|
60
|
+
make inversion # Build @venizia/ignis-inversion
|
|
61
|
+
make dev-configs # Build @venizia/dev-configs
|
|
62
|
+
make docs # Build documentation
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Force update individual packages:**
|
|
66
|
+
```bash
|
|
67
|
+
make update-core
|
|
68
|
+
make update-helpers
|
|
69
|
+
make update-inversion
|
|
70
|
+
make update-dev-configs
|
|
71
|
+
make update-docs
|
|
72
|
+
```
|
|
73
|
+
|
|
42
74
|
## 2. Development Workflow
|
|
43
75
|
|
|
44
76
|
### Step 1: Create Branch
|
|
@@ -92,11 +124,13 @@ git commit -m "chore: upgrade Hono to v4.0"
|
|
|
92
124
|
### Step 4: Validate
|
|
93
125
|
|
|
94
126
|
```bash
|
|
95
|
-
# Lint and format
|
|
96
|
-
|
|
127
|
+
# Lint and format (from root)
|
|
128
|
+
make lint
|
|
129
|
+
# Or: bun run lint:fix
|
|
97
130
|
|
|
98
|
-
# Build
|
|
99
|
-
|
|
131
|
+
# Build all packages
|
|
132
|
+
make build
|
|
133
|
+
# Or: bun run build
|
|
100
134
|
|
|
101
135
|
# Run tests
|
|
102
136
|
bun run test
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Data Modeling
|
|
2
|
+
|
|
3
|
+
Ignis streamlines data modeling with Drizzle ORM by providing powerful helpers and "enrichers" that reduce boilerplate code for common schema patterns.
|
|
4
|
+
|
|
5
|
+
## 1. Base Entity
|
|
6
|
+
|
|
7
|
+
All entity models should extend `BaseEntity`. This provides integration with the framework's repository layer and automatic schema generation support.
|
|
8
|
+
|
|
9
|
+
The recommended pattern is to define the schema and relations as **static properties** on the class. This keeps the definition self-contained and enables powerful type inference.
|
|
10
|
+
|
|
11
|
+
**Example (`src/models/entities/user.model.ts`):**
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { BaseEntity, extraUserColumns, generateIdColumnDefs, model } from '@venizia/ignis';
|
|
15
|
+
import { pgTable } from 'drizzle-orm/pg-core';
|
|
16
|
+
|
|
17
|
+
@model({ type: 'entity' })
|
|
18
|
+
export class User extends BaseEntity<typeof User.schema> {
|
|
19
|
+
// 1. Define schema as a static property
|
|
20
|
+
static override schema = pgTable('User', {
|
|
21
|
+
...generateIdColumnDefs({ id: { dataType: 'string' } }),
|
|
22
|
+
...extraUserColumns({ idType: 'string' }),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// 2. Define relations as a static method (return empty array if none)
|
|
26
|
+
static override relations = () => [];
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 2. Schema Enrichers
|
|
31
|
+
|
|
32
|
+
Instead of manually defining common columns like primary keys, timestamps, or audit fields in every table, use Ignis "enrichers".
|
|
33
|
+
|
|
34
|
+
**Available Enrichers:**
|
|
35
|
+
|
|
36
|
+
| Enricher | Description | Columns Added |
|
|
37
|
+
|----------|-------------|---------------|
|
|
38
|
+
| `generateIdColumnDefs` | Adds a Primary Key | `id` (string/UUID or number/Serial) |
|
|
39
|
+
| `generateTzColumnDefs` | Adds timestamps | `createdAt`, `modifiedAt` (auto-updating) |
|
|
40
|
+
| `generateUserAuditColumnDefs` | Adds audit fields | `createdBy`, `modifiedBy` |
|
|
41
|
+
| `generateDataTypeColumnDefs` | Adds generic value fields | `nValue` (number), `tValue` (text), `jValue` (json), etc. |
|
|
42
|
+
| `extraUserColumns` | Comprehensive user fields | Combines audit, timestamps, status, and type fields |
|
|
43
|
+
|
|
44
|
+
**Usage Example:**
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import {
|
|
48
|
+
generateIdColumnDefs,
|
|
49
|
+
generateTzColumnDefs,
|
|
50
|
+
generateUserAuditColumnDefs,
|
|
51
|
+
} from '@venizia/ignis';
|
|
52
|
+
import { pgTable, text } from 'drizzle-orm/pg-core';
|
|
53
|
+
|
|
54
|
+
export const configurationTable = pgTable(
|
|
55
|
+
'Configuration',
|
|
56
|
+
{
|
|
57
|
+
// 1. Auto-generate UUID Primary Key
|
|
58
|
+
...generateIdColumnDefs({ id: { dataType: 'string' } }),
|
|
59
|
+
|
|
60
|
+
// 2. Auto-generate createdAt / modifiedAt
|
|
61
|
+
...generateTzColumnDefs(),
|
|
62
|
+
|
|
63
|
+
// 3. Auto-generate createdBy / modifiedBy
|
|
64
|
+
...generateUserAuditColumnDefs({
|
|
65
|
+
created: { dataType: 'string', columnName: 'created_by' },
|
|
66
|
+
modified: { dataType: 'string', columnName: 'modified_by' },
|
|
67
|
+
}),
|
|
68
|
+
|
|
69
|
+
// 4. Your custom columns
|
|
70
|
+
code: text('code').notNull(),
|
|
71
|
+
description: text('description'),
|
|
72
|
+
group: text('group').notNull(),
|
|
73
|
+
},
|
|
74
|
+
(table) => [
|
|
75
|
+
// Define indexes/constraints here
|
|
76
|
+
unique('UQ_code').on(table.code),
|
|
77
|
+
]
|
|
78
|
+
);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 3. Defining Relations
|
|
82
|
+
|
|
83
|
+
Relations are defined using the `TRelationConfig` structure within the static `relations` method of your model.
|
|
84
|
+
|
|
85
|
+
**Example (`src/models/entities/configuration.model.ts`):**
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import {
|
|
89
|
+
BaseEntity,
|
|
90
|
+
model,
|
|
91
|
+
RelationTypes,
|
|
92
|
+
TRelationConfig,
|
|
93
|
+
} from '@venizia/ignis';
|
|
94
|
+
import { User } from './user.model';
|
|
95
|
+
|
|
96
|
+
@model({ type: 'entity' })
|
|
97
|
+
export class Configuration extends BaseEntity<typeof Configuration.schema> {
|
|
98
|
+
// ... schema definition ...
|
|
99
|
+
|
|
100
|
+
// Define relations
|
|
101
|
+
static override relations = (): TRelationConfig[] => [
|
|
102
|
+
{
|
|
103
|
+
name: 'creator',
|
|
104
|
+
type: RelationTypes.ONE,
|
|
105
|
+
schema: User.schema,
|
|
106
|
+
metadata: {
|
|
107
|
+
fields: [Configuration.schema.createdBy],
|
|
108
|
+
references: [User.schema.id],
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 4. Repositories and Auto-Discovery
|
|
116
|
+
|
|
117
|
+
Ignis simplifies the connection between models, repositories, and datasources.
|
|
118
|
+
|
|
119
|
+
### DataSource Auto-Discovery
|
|
120
|
+
|
|
121
|
+
DataSources automatically discover their schema from the repositories that bind to them. You **do not** need to manually register schemas in the DataSource constructor.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// src/datasources/postgres.datasource.ts
|
|
125
|
+
@datasource({ driver: 'node-postgres' })
|
|
126
|
+
export class PostgresDataSource extends BaseDataSource<TNodePostgresConnector, IDSConfigs> {
|
|
127
|
+
constructor() {
|
|
128
|
+
super({
|
|
129
|
+
name: PostgresDataSource.name,
|
|
130
|
+
config: { /* connection config */ },
|
|
131
|
+
// NO schema property needed - auto-discovered!
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
override configure(): ValueOrPromise<void> {
|
|
136
|
+
// This method automatically collects all schemas from bound repositories
|
|
137
|
+
const schema = this.getSchema();
|
|
138
|
+
this.connector = drizzle({ client: new Pool(this.settings), schema });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Repository Binding
|
|
144
|
+
|
|
145
|
+
Repositories use the `@repository` decorator to bind a **Model** to a **DataSource**. This binding is what powers the auto-discovery mechanism.
|
|
146
|
+
|
|
147
|
+
**Pattern 1: Zero Boilerplate (Recommended)**
|
|
148
|
+
|
|
149
|
+
For most repositories, you don't need a constructor. The DataSource is automatically injected.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
@repository({ model: Configuration, dataSource: PostgresDataSource })
|
|
153
|
+
export class ConfigurationRepository extends DefaultCRUDRepository<typeof Configuration.schema> {
|
|
154
|
+
// No constructor needed!
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Pattern 2: Explicit Injection (Advanced)**
|
|
159
|
+
|
|
160
|
+
If you need to perform custom initialization or inject additional dependencies, you can define a constructor. **Important:** The first parameter must be the DataSource.
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
@repository({ model: User, dataSource: PostgresDataSource })
|
|
164
|
+
export class UserRepository extends ReadableRepository<typeof User.schema> {
|
|
165
|
+
constructor(
|
|
166
|
+
@inject({ key: 'datasources.PostgresDataSource' })
|
|
167
|
+
dataSource: PostgresDataSource,
|
|
168
|
+
) {
|
|
169
|
+
super(dataSource);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Custom methods
|
|
173
|
+
async findByRealm(realm: string) {
|
|
174
|
+
return this.findOne({ filter: { where: { realm } } });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
@@ -72,9 +72,11 @@ const SecureRoute = {
|
|
|
72
72
|
|
|
73
73
|
**Access user in protected routes:**
|
|
74
74
|
```typescript
|
|
75
|
+
import { Authentication, IJWTTokenPayload, ApplicationError, getError } from '@venizia/ignis';
|
|
76
|
+
|
|
75
77
|
const user = c.get(Authentication.CURRENT_USER) as IJWTTokenPayload;
|
|
76
78
|
if (!user.roles.includes('admin')) {
|
|
77
|
-
throw
|
|
79
|
+
throw getError({ statusCode: 403, message: 'Forbidden' });
|
|
78
80
|
}
|
|
79
81
|
```
|
|
80
82
|
|