@venizia/ignis-docs 0.0.1-4 → 0.0.1-6
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/mcp-server/dist/common/config.d.ts +58 -21
- package/mcp-server/dist/common/config.d.ts.map +1 -1
- package/mcp-server/dist/common/config.js +67 -12
- package/mcp-server/dist/common/config.js.map +1 -1
- package/mcp-server/dist/helpers/docs.helper.d.ts +5 -5
- package/mcp-server/dist/helpers/docs.helper.d.ts.map +1 -1
- package/mcp-server/dist/helpers/docs.helper.js +31 -27
- package/mcp-server/dist/helpers/docs.helper.js.map +1 -1
- package/mcp-server/dist/helpers/github.helper.d.ts +37 -0
- package/mcp-server/dist/helpers/github.helper.d.ts.map +1 -0
- package/mcp-server/dist/helpers/github.helper.js +100 -0
- package/mcp-server/dist/helpers/github.helper.js.map +1 -0
- package/mcp-server/dist/helpers/index.d.ts +1 -0
- package/mcp-server/dist/helpers/index.d.ts.map +1 -1
- package/mcp-server/dist/helpers/index.js +1 -0
- package/mcp-server/dist/helpers/index.js.map +1 -1
- package/mcp-server/dist/index.js +60 -32
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/tools/base.tool.d.ts +6 -10
- package/mcp-server/dist/tools/base.tool.d.ts.map +1 -1
- package/mcp-server/dist/tools/base.tool.js +3 -5
- package/mcp-server/dist/tools/base.tool.js.map +1 -1
- package/mcp-server/dist/tools/{get-doc-content.tool.d.ts → docs/get-document-content.tool.d.ts} +4 -4
- package/mcp-server/dist/tools/docs/get-document-content.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/{get-doc-content.tool.js → docs/get-document-content.tool.js} +12 -11
- package/mcp-server/dist/tools/docs/get-document-content.tool.js.map +1 -0
- package/mcp-server/dist/tools/{get-doc-metadata.tool.d.ts → docs/get-document-metadata.tool.d.ts} +4 -4
- package/mcp-server/dist/tools/docs/get-document-metadata.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/{get-doc-metadata.tool.js → docs/get-document-metadata.tool.js} +11 -10
- package/mcp-server/dist/tools/docs/get-document-metadata.tool.js.map +1 -0
- package/mcp-server/dist/tools/docs/get-package-overview.tool.d.ts +50 -0
- package/mcp-server/dist/tools/docs/get-package-overview.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/docs/get-package-overview.tool.js +221 -0
- package/mcp-server/dist/tools/docs/get-package-overview.tool.js.map +1 -0
- package/mcp-server/dist/tools/docs/index.d.ts +7 -0
- package/mcp-server/dist/tools/docs/index.d.ts.map +1 -0
- package/mcp-server/dist/tools/docs/index.js +23 -0
- package/mcp-server/dist/tools/docs/index.js.map +1 -0
- package/mcp-server/dist/tools/{list-categories.tool.d.ts → docs/list-categories.tool.d.ts} +2 -2
- package/mcp-server/dist/tools/docs/list-categories.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/{list-categories.tool.js → docs/list-categories.tool.js} +7 -6
- package/mcp-server/dist/tools/docs/list-categories.tool.js.map +1 -0
- package/mcp-server/dist/tools/{list-docs.tool.d.ts → docs/list-documents.tool.d.ts} +4 -4
- package/mcp-server/dist/tools/docs/list-documents.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/{list-docs.tool.js → docs/list-documents.tool.js} +10 -9
- package/mcp-server/dist/tools/docs/list-documents.tool.js.map +1 -0
- package/mcp-server/dist/tools/{search-docs.tool.d.ts → docs/search-documents.tool.d.ts} +4 -4
- package/mcp-server/dist/tools/docs/search-documents.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/{search-docs.tool.js → docs/search-documents.tool.js} +19 -18
- package/mcp-server/dist/tools/docs/search-documents.tool.js.map +1 -0
- package/mcp-server/dist/tools/github/index.d.ts +5 -0
- package/mcp-server/dist/tools/github/index.d.ts.map +1 -0
- package/mcp-server/dist/tools/github/index.js +21 -0
- package/mcp-server/dist/tools/github/index.js.map +1 -0
- package/mcp-server/dist/tools/github/list-project-files.tool.d.ts +28 -0
- package/mcp-server/dist/tools/github/list-project-files.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/github/list-project-files.tool.js +98 -0
- package/mcp-server/dist/tools/github/list-project-files.tool.js.map +1 -0
- package/mcp-server/dist/tools/github/search-code.tool.d.ts +42 -0
- package/mcp-server/dist/tools/github/search-code.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/github/search-code.tool.js +194 -0
- package/mcp-server/dist/tools/github/search-code.tool.js.map +1 -0
- package/mcp-server/dist/tools/github/verify-dependencies.tool.d.ts +55 -0
- package/mcp-server/dist/tools/github/verify-dependencies.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/github/verify-dependencies.tool.js +167 -0
- package/mcp-server/dist/tools/github/verify-dependencies.tool.js.map +1 -0
- package/mcp-server/dist/tools/github/view-source-file.tool.d.ts +26 -0
- package/mcp-server/dist/tools/github/view-source-file.tool.d.ts.map +1 -0
- package/mcp-server/dist/tools/github/view-source-file.tool.js +91 -0
- package/mcp-server/dist/tools/github/view-source-file.tool.js.map +1 -0
- package/mcp-server/dist/tools/index.d.ts +3 -7
- package/mcp-server/dist/tools/index.d.ts.map +1 -1
- package/mcp-server/dist/tools/index.js +17 -13
- package/mcp-server/dist/tools/index.js.map +1 -1
- package/package.json +25 -6
- package/wiki/get-started/best-practices/api-usage-examples.md +42 -0
- package/wiki/get-started/best-practices/architectural-patterns.md +42 -1
- package/wiki/get-started/best-practices/code-style-standards.md +41 -0
- package/wiki/get-started/best-practices/contribution-workflow.md +40 -6
- package/wiki/get-started/best-practices/data-modeling.md +126 -0
- package/wiki/get-started/core-concepts/dependency-injection.md +13 -1
- package/wiki/get-started/mcp-docs-server.md +130 -32
- package/wiki/get-started/philosophy.md +198 -25
- package/wiki/public/logo.svg +1 -0
- package/wiki/references/base/application.md +5 -5
- package/wiki/references/base/controllers.md +3 -1
- package/wiki/references/base/dependency-injection.md +6 -5
- package/wiki/references/base/models.md +319 -1
- package/wiki/references/components/index.md +3 -1
- package/wiki/references/components/static-asset.md +1289 -0
- package/wiki/references/helpers/inversion.md +21 -11
- package/wiki/references/helpers/storage.md +538 -11
- package/wiki/references/src-details/core.md +15 -1
- package/wiki/references/src-details/docs.md +19 -9
- package/wiki/references/src-details/mcp-server.md +185 -234
- package/wiki/references/utilities/index.md +1 -1
- package/wiki/references/utilities/request.md +150 -0
- 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/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
|
@@ -2,28 +2,107 @@
|
|
|
2
2
|
|
|
3
3
|
Ignis combines the structured, enterprise-grade development experience of **LoopBack 4** with the speed and simplicity of **Hono**.
|
|
4
4
|
|
|
5
|
-
## The
|
|
5
|
+
## The Landscape
|
|
6
6
|
|
|
7
|
-
When building REST APIs with Node.js/Bun, developers
|
|
7
|
+
When building REST APIs with Node.js/Bun, developers choose from three categories of frameworks, each with genuine strengths:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|--------|-------------------|----------------------|-----------|
|
|
11
|
-
| **Examples** | Express, Hono, Fastify | NestJS, LoopBack | **Ignis** |
|
|
12
|
-
| **Performance** | ⚡ Very fast | 🐌 Slower | ⚡ Very fast (Hono) |
|
|
13
|
-
| **Architecture** | ❌ No structure | ✅ Structured | ✅ Structured |
|
|
14
|
-
| **Learning Curve** | ✅ Easy | ❌ Steep | ✅ Gradual |
|
|
15
|
-
| **Dependency Injection** | ❌ Manual | ✅ Built-in | ✅ Built-in |
|
|
16
|
-
| **Boilerplate** | ✅ Minimal | ❌ Heavy | ✅ Moderate |
|
|
17
|
-
| **Best For** | Prototypes, tiny APIs | Large enterprise apps | Growing APIs, teams |
|
|
9
|
+
### Framework Categories
|
|
18
10
|
|
|
19
|
-
|
|
11
|
+
| Category | Examples | Philosophy |
|
|
12
|
+
|----------|----------|------------|
|
|
13
|
+
| **Minimal** | Express, Hono, Fastify, Koa | Freedom, speed, flexibility |
|
|
14
|
+
| **Enterprise** | NestJS, LoopBack 4, AdonisJS | Structure, patterns, conventions |
|
|
15
|
+
| **Balanced** | Ignis, Ts.ED | Structure with lighter footprint |
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
## Honest Comparison
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
### Performance & Runtime
|
|
20
|
+
|
|
21
|
+
| Framework | Requests/sec | Startup Time | Memory | Multi-Runtime |
|
|
22
|
+
|-----------|-------------|--------------|--------|---------------|
|
|
23
|
+
| **Hono** | ~150k | ~10ms | ~20MB | ✅ Bun, Node, Deno, CF Workers |
|
|
24
|
+
| **Fastify** | ~80k | ~50ms | ~40MB | Node only |
|
|
25
|
+
| **Express** | ~15k | ~100ms | ~50MB | Node only |
|
|
26
|
+
| **NestJS** | ~25k | ~500ms | ~100MB | Node (Bun experimental) |
|
|
27
|
+
| **LoopBack 4** | ~20k | ~800ms | ~120MB | Node only |
|
|
28
|
+
| **Ignis** | ~140k | ~30ms | ~30MB | ✅ Bun, Node |
|
|
29
|
+
|
|
30
|
+
*Benchmarks are approximate and vary by use case.*
|
|
31
|
+
|
|
32
|
+
### Developer Experience
|
|
33
|
+
|
|
34
|
+
| Aspect | Minimal (Hono/Express) | Enterprise (NestJS/LoopBack) | Ignis |
|
|
35
|
+
|--------|------------------------|------------------------------|-------|
|
|
36
|
+
| **Setup Time** | 5 minutes | 30+ minutes | 10 minutes |
|
|
37
|
+
| **Learning Curve** | Low | High | Medium |
|
|
38
|
+
| **Boilerplate** | Minimal | Heavy | Moderate |
|
|
39
|
+
| **Type Safety** | Manual | Excellent | Excellent |
|
|
40
|
+
| **IDE Support** | Basic | Excellent | Good |
|
|
41
|
+
| **Documentation** | Good | Excellent | Growing |
|
|
42
|
+
|
|
43
|
+
### Architecture & Patterns
|
|
44
|
+
|
|
45
|
+
| Pattern | Minimal | Enterprise | Ignis |
|
|
46
|
+
|---------|---------|------------|-------|
|
|
47
|
+
| **Dependency Injection** | ❌ Manual/3rd party | ✅ Built-in (complex) | ✅ Built-in (simple) |
|
|
48
|
+
| **Layered Architecture** | ❌ DIY | ✅ Enforced | ✅ Guided |
|
|
49
|
+
| **Repository Pattern** | ❌ DIY | ✅ Built-in | ✅ Built-in |
|
|
50
|
+
| **Validation** | ❌ 3rd party | ✅ Built-in | ✅ Built-in (Zod) |
|
|
51
|
+
| **OpenAPI/Swagger** | ❌ 3rd party | ✅ Built-in | ✅ Built-in |
|
|
52
|
+
| **Authentication** | ❌ DIY | ✅ Modules available | ✅ Built-in component |
|
|
53
|
+
|
|
54
|
+
### Ecosystem & Maturity
|
|
55
|
+
|
|
56
|
+
| Aspect | Minimal (Hono) | Enterprise (NestJS) | Ignis |
|
|
57
|
+
|--------|----------------|---------------------|-------|
|
|
58
|
+
| **Community Size** | Growing fast | Very large | Small |
|
|
59
|
+
| **npm Downloads** | ~500k/week | ~3M/week | New |
|
|
60
|
+
| **Stack Overflow** | Limited | Extensive | Limited |
|
|
61
|
+
| **Third-party Modules** | Middleware-based | Rich ecosystem | Growing |
|
|
62
|
+
| **Production Battle-tested** | Yes | Yes | Emerging |
|
|
63
|
+
| **Corporate Backing** | Cloudflare | Trilon | Independent |
|
|
64
|
+
|
|
65
|
+
### Flexibility vs Convention
|
|
66
|
+
|
|
67
|
+
| Aspect | Minimal | Enterprise | Ignis |
|
|
68
|
+
|--------|---------|------------|-------|
|
|
69
|
+
| **Project Structure** | Total freedom | Strict conventions | Guided conventions |
|
|
70
|
+
| **ORM Choice** | Any | TypeORM/Prisma preferred | Drizzle (flexible) |
|
|
71
|
+
| **Testing Approach** | Any | Jest recommended | Any |
|
|
72
|
+
| **Middleware System** | Simple | Complex interceptors | Hono middleware |
|
|
73
|
+
| **Customization** | Unlimited | Plugin-based | Component-based |
|
|
74
|
+
|
|
75
|
+
## The Middle Ground: Where Ignis Fits
|
|
76
|
+
|
|
77
|
+
### What Each Approach Excels At
|
|
78
|
+
|
|
79
|
+
**Minimal Frameworks (Hono, Express, Fastify):**
|
|
80
|
+
- ✅ Maximum performance
|
|
81
|
+
- ✅ Complete freedom in architecture
|
|
82
|
+
- ✅ Fastest prototyping
|
|
83
|
+
- ✅ Smallest bundle size
|
|
84
|
+
- ✅ Edge/serverless deployments
|
|
85
|
+
- ⚠️ Architecture decisions left to developer
|
|
86
|
+
- ⚠️ Patterns must be implemented manually
|
|
87
|
+
|
|
88
|
+
**Enterprise Frameworks (NestJS, LoopBack):**
|
|
89
|
+
- ✅ Battle-tested patterns
|
|
90
|
+
- ✅ Comprehensive documentation
|
|
91
|
+
- ✅ Large community & ecosystem
|
|
92
|
+
- ✅ Excellent for large teams
|
|
93
|
+
- ✅ Strong conventions prevent chaos
|
|
94
|
+
- ⚠️ Higher resource consumption
|
|
95
|
+
- ⚠️ Steeper learning curve
|
|
96
|
+
- ⚠️ More boilerplate
|
|
97
|
+
|
|
98
|
+
**Ignis (The Middle Ground):**
|
|
99
|
+
- ✅ Enterprise patterns without the weight
|
|
100
|
+
- ✅ Hono's performance foundation
|
|
101
|
+
- ✅ Gradual complexity adoption
|
|
102
|
+
- ✅ TypeScript-first with Zod validation
|
|
103
|
+
- ⚠️ Smaller community (new framework)
|
|
104
|
+
- ⚠️ Less documentation than mature frameworks
|
|
105
|
+
- ⚠️ Fewer third-party integrations
|
|
27
106
|
|
|
28
107
|
## Inspired By The Best
|
|
29
108
|
|
|
@@ -102,17 +181,111 @@ Ignis = LoopBack patterns + Hono performance:
|
|
|
102
181
|
- Type-safe database operations
|
|
103
182
|
- Automatic validation
|
|
104
183
|
|
|
184
|
+
## Choose the Right Tool
|
|
185
|
+
|
|
186
|
+
### Use Hono/Fastify/Express When:
|
|
187
|
+
|
|
188
|
+
| Scenario | Why It's Better |
|
|
189
|
+
|----------|-----------------|
|
|
190
|
+
| Building a simple webhook handler | No structure overhead needed |
|
|
191
|
+
| Edge/serverless functions | Minimal cold start, tiny bundle |
|
|
192
|
+
| Rapid prototyping | Get something running in minutes |
|
|
193
|
+
| Microservices with 1-5 endpoints | Structure adds unnecessary complexity |
|
|
194
|
+
| You want maximum control | No conventions to follow |
|
|
195
|
+
| Learning web development | Simpler mental model |
|
|
196
|
+
|
|
197
|
+
### Use NestJS/LoopBack When:
|
|
198
|
+
|
|
199
|
+
| Scenario | Why It's Better |
|
|
200
|
+
|----------|-----------------|
|
|
201
|
+
| Large team (10+ developers) | Strong conventions prevent chaos |
|
|
202
|
+
| Enterprise with strict standards | Mature, battle-tested, auditable |
|
|
203
|
+
| Need extensive ecosystem | Many official and community modules |
|
|
204
|
+
| Complex microservices architecture | Built-in support for messaging, CQRS |
|
|
205
|
+
| Hiring developers easily | Large talent pool familiar with it |
|
|
206
|
+
| Long-term support is critical | Corporate backing, LTS versions |
|
|
207
|
+
|
|
208
|
+
### Use Ignis When:
|
|
209
|
+
|
|
210
|
+
| Scenario | Why It's Better |
|
|
211
|
+
|----------|-----------------|
|
|
212
|
+
| Medium-sized API (10-100 endpoints) | Right balance of structure and speed |
|
|
213
|
+
| Small team wanting patterns | DI without enterprise complexity |
|
|
214
|
+
| Performance is critical | Hono's speed with structure |
|
|
215
|
+
| Coming from LoopBack/NestJS | Familiar patterns, lighter weight |
|
|
216
|
+
| Bun-first development | Native Bun support |
|
|
217
|
+
| Growing project | Start simple, add complexity gradually |
|
|
218
|
+
|
|
105
219
|
## The Trade-off
|
|
106
220
|
|
|
107
|
-
|
|
108
|
-
|----------|-------------|
|
|
109
|
-
| Clear architecture | ~100 lines setup boilerplate |
|
|
110
|
-
| Built-in DI, validation, docs | Learning curve for patterns |
|
|
111
|
-
| Faster for medium/large projects | Slightly more abstraction than Hono |
|
|
112
|
-
| Easier testing | Initial time investment |
|
|
113
|
-
| Team scalability | Convention over total freedom |
|
|
221
|
+
Every choice has trade-offs. Here's an honest look:
|
|
114
222
|
|
|
115
|
-
|
|
223
|
+
### What You Gain with Ignis
|
|
224
|
+
|
|
225
|
+
| Benefit | Compared To |
|
|
226
|
+
|---------|-------------|
|
|
227
|
+
| ~5x faster than NestJS | Enterprise frameworks |
|
|
228
|
+
| Built-in DI, validation, OpenAPI | Minimal frameworks |
|
|
229
|
+
| Structured codebase | DIY architecture |
|
|
230
|
+
| Easier testing with DI | Manual mocking |
|
|
231
|
+
| Team-friendly patterns | Individual coding styles |
|
|
232
|
+
|
|
233
|
+
### What You Give Up with Ignis
|
|
234
|
+
|
|
235
|
+
| Trade-off | Compared To |
|
|
236
|
+
|-----------|-------------|
|
|
237
|
+
| ~10% slower than raw Hono | Minimal frameworks |
|
|
238
|
+
| Smaller community | NestJS/Express |
|
|
239
|
+
| Less documentation | Mature frameworks |
|
|
240
|
+
| Learning curve for patterns | No-structure approach |
|
|
241
|
+
| Convention requirements | Total freedom |
|
|
242
|
+
|
|
243
|
+
### Honest Assessment
|
|
244
|
+
|
|
245
|
+
| Aspect | Ignis Reality |
|
|
246
|
+
|--------|---------------|
|
|
247
|
+
| **Maturity** | New framework, evolving API |
|
|
248
|
+
| **Community** | Small but growing |
|
|
249
|
+
| **Documentation** | Good but not comprehensive |
|
|
250
|
+
| **Production Use** | Early adopters only |
|
|
251
|
+
| **Breaking Changes** | Possible before v1.0 |
|
|
252
|
+
| **Support** | Community-driven |
|
|
253
|
+
|
|
254
|
+
**Bottom line:** Ignis is ideal for developers who want enterprise patterns without enterprise overhead. If you need battle-tested stability and extensive community support, consider NestJS. If you need maximum simplicity, stick with Hono.
|
|
255
|
+
|
|
256
|
+
## Migration Paths
|
|
257
|
+
|
|
258
|
+
### From Hono to Ignis
|
|
259
|
+
|
|
260
|
+
If your Hono project grows complex:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
1. Add Ignis as dependency
|
|
264
|
+
2. Wrap existing Hono app with Ignis Application
|
|
265
|
+
3. Gradually introduce DI for new features
|
|
266
|
+
4. Migrate routes to controllers over time
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### From NestJS to Ignis
|
|
270
|
+
|
|
271
|
+
If you want better performance:
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
1. Controllers → Ignis Controllers (similar decorators)
|
|
275
|
+
2. Services → Ignis Services (same pattern)
|
|
276
|
+
3. Repositories → Ignis Repositories (Drizzle instead of TypeORM)
|
|
277
|
+
4. Modules → Ignis Components (simpler structure)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### From Ignis to NestJS
|
|
281
|
+
|
|
282
|
+
If you outgrow Ignis:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
1. Patterns are similar - migration is straightforward
|
|
286
|
+
2. Main changes: ORM, module system, interceptors
|
|
287
|
+
3. DI concepts transfer directly
|
|
288
|
+
```
|
|
116
289
|
|
|
117
290
|
## Next Steps
|
|
118
291
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 92.27 122.88" style="enable-background:new 0 0 92.27 122.88" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#EC6F59;} .st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FAD15C;}</style><g><path class="st0" d="M18.61,54.89C15.7,28.8,30.94,10.45,59.52,0C42.02,22.71,74.44,47.31,76.23,70.89 c4.19-7.15,6.57-16.69,7.04-29.45c21.43,33.62,3.66,88.57-43.5,80.67c-4.33-0.72-8.5-2.09-12.3-4.13C10.27,108.8,0,88.79,0,69.68 C0,57.5,5.21,46.63,11.95,37.99C12.85,46.45,14.77,52.76,18.61,54.89L18.61,54.89z"/><path class="st1" d="M33.87,92.58c-4.86-12.55-4.19-32.82,9.42-39.93c0.1,23.3,23.05,26.27,18.8,51.14 c3.92-4.44,5.9-11.54,6.25-17.15c6.22,14.24,1.34,25.63-7.53,31.43c-26.97,17.64-50.19-18.12-34.75-37.72 C26.53,84.73,31.89,91.49,33.87,92.58L33.87,92.58z"/></g></svg>
|
|
@@ -37,11 +37,11 @@ Extends `AbstractApplication` with concrete lifecycle implementations and resour
|
|
|
37
37
|
|
|
38
38
|
| Method | DI Binding Key Convention |
|
|
39
39
|
| :--- | :--- |
|
|
40
|
-
| `component(MyComponent)` | `components.MyComponent` |
|
|
41
|
-
| `controller(MyController)` | `controllers.MyController` |
|
|
42
|
-
| `service(MyService)` | `services.MyService` |
|
|
43
|
-
| `repository(MyRepository)`| `repositories.MyRepository` |
|
|
44
|
-
| `dataSource(MyDataSource)`| `datasources.MyDataSource` |
|
|
40
|
+
| `component(MyComponent, opts?)` | `components.MyComponent` (default) or custom key via `opts.binding` |
|
|
41
|
+
| `controller(MyController, opts?)` | `controllers.MyController` (default) or custom key via `opts.binding` |
|
|
42
|
+
| `service(MyService, opts?)` | `services.MyService` (default) or custom key via `opts.binding` |
|
|
43
|
+
| `repository(MyRepository, opts?)`| `repositories.MyRepository` (default) or custom key via `opts.binding` |
|
|
44
|
+
| `dataSource(MyDataSource, opts?)`| `datasources.MyDataSource` (default) or custom key via `opts.binding` |
|
|
45
45
|
|
|
46
46
|
### `initialize()` Method Flow
|
|
47
47
|
|
|
@@ -287,7 +287,9 @@ The `ControllerFactory` provides a static method `defineCrudController` to quick
|
|
|
287
287
|
|
|
288
288
|
### `static defineCrudController<EntitySchema>(opts: ICrudControllerOptions<EntitySchema>)`
|
|
289
289
|
|
|
290
|
-
This factory method returns a `BaseController` class that is already set up with the following standard CRUD endpoints
|
|
290
|
+
This factory method returns a `BaseController` class that is already set up with the following standard CRUD endpoints.
|
|
291
|
+
|
|
292
|
+
**Note:** The returned class is dynamically named using `controller.name` from the options. This ensures that when registered with `app.controller()`, the class has a proper name for binding keys and debugging (e.g., `ConfigurationController` instead of an anonymous class).
|
|
291
293
|
|
|
292
294
|
| Name | Method | Path | Description |
|
|
293
295
|
| :--- | :--- | :--- | :--- |
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
Technical reference for the DI system in Ignis - managing resource lifecycles and dependency resolution.
|
|
4
4
|
|
|
5
5
|
**Files:**
|
|
6
|
-
- `packages/
|
|
7
|
-
- `packages/
|
|
8
|
-
- `packages/
|
|
6
|
+
- `packages/inversion/src/container.ts` (base Container and Binding classes)
|
|
7
|
+
- `packages/helpers/src/helpers/inversion/container.ts` (extended Container with ApplicationLogger)
|
|
8
|
+
- `packages/core/src/base/metadata/injectors.ts` (@inject, @injectable decorators)
|
|
9
|
+
- `packages/helpers/src/helpers/inversion/registry.ts` (MetadataRegistry)
|
|
9
10
|
|
|
10
11
|
## Quick Reference
|
|
11
12
|
|
|
@@ -20,7 +21,7 @@ Technical reference for the DI system in Ignis - managing resource lifecycles an
|
|
|
20
21
|
|
|
21
22
|
Heart of the DI system - registry managing all application resources.
|
|
22
23
|
|
|
23
|
-
**File:** `packages/
|
|
24
|
+
**File:** `packages/inversion/src/container.ts`
|
|
24
25
|
|
|
25
26
|
### Key Methods
|
|
26
27
|
|
|
@@ -35,7 +36,7 @@ Heart of the DI system - registry managing all application resources.
|
|
|
35
36
|
|
|
36
37
|
A `Binding` represents a single registered dependency in the container. It's a fluent API that allows you to specify *how* a dependency should be created and managed.
|
|
37
38
|
|
|
38
|
-
- **File:** `packages/
|
|
39
|
+
- **File:** `packages/inversion/src/container.ts`
|
|
39
40
|
|
|
40
41
|
### Configuration Methods
|
|
41
42
|
|
|
@@ -79,7 +79,7 @@ Enrichers are helper functions located in `packages/core/src/base/models/enriche
|
|
|
79
79
|
| Enricher Function | Purpose |
|
|
80
80
|
| :--- | :--- |
|
|
81
81
|
| **`generateIdColumnDefs`** | Adds a primary key `id` column (string UUID or numeric serial). |
|
|
82
|
-
| **`generateTzColumnDefs`** | Adds `createdAt` and `
|
|
82
|
+
| **`generateTzColumnDefs`** | Adds `createdAt`, `modifiedAt`, and `deletedAt` timestamp columns with timezone support. |
|
|
83
83
|
| **`generateUserAuditColumnDefs`** | Adds `createdBy` and `modifiedBy` columns to track user audit information. |
|
|
84
84
|
| **`generateDataTypeColumnDefs`** | Adds generic data type columns (`dataType`, `nValue`, `tValue`, `bValue`, `jValue`, `boValue`) for flexible data storage. |
|
|
85
85
|
| **`generatePrincipalColumnDefs`** | Adds polymorphic fields for associating with different principal types. |
|
|
@@ -102,3 +102,321 @@ export const myTable = pgTable('MyTable', {
|
|
|
102
102
|
name: text('name').notNull(),
|
|
103
103
|
});
|
|
104
104
|
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Detailed Enricher Reference
|
|
109
|
+
|
|
110
|
+
### `generateTzColumnDefs`
|
|
111
|
+
|
|
112
|
+
Adds timestamp columns for tracking entity creation, modification, and soft deletion.
|
|
113
|
+
|
|
114
|
+
**File:** `packages/core/src/base/models/enrichers/tz.enricher.ts`
|
|
115
|
+
|
|
116
|
+
#### Signature
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
generateTzColumnDefs(opts?: TTzEnricherOptions): TTzEnricherResult
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### Options (`TTzEnricherOptions`)
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
type TTzEnricherOptions = {
|
|
126
|
+
created?: { columnName: string; withTimezone: boolean };
|
|
127
|
+
modified?: { enable: boolean; columnName: string; withTimezone: boolean };
|
|
128
|
+
deleted?: { enable: boolean; columnName: string; withTimezone: boolean };
|
|
129
|
+
};
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Default values:**
|
|
133
|
+
- `created`: `{ columnName: 'created_at', withTimezone: true }`
|
|
134
|
+
- `modified`: `{ enable: true, columnName: 'modified_at', withTimezone: true }`
|
|
135
|
+
- `deleted`: `{ enable: false }` (disabled by default)
|
|
136
|
+
|
|
137
|
+
#### Generated Columns
|
|
138
|
+
|
|
139
|
+
| Column | Type | Constraints | Default | Description |
|
|
140
|
+
|--------|------|-------------|---------|-------------|
|
|
141
|
+
| `createdAt` | `timestamp` | `NOT NULL` | `now()` | When the record was created (always included) |
|
|
142
|
+
| `modifiedAt` | `timestamp` | `NOT NULL` | `now()` | When the record was last modified (optional, enabled by default) |
|
|
143
|
+
| `deletedAt` | `timestamp` | nullable | `null` | When the record was soft-deleted (optional, **disabled by default**) |
|
|
144
|
+
|
|
145
|
+
#### Usage Examples
|
|
146
|
+
|
|
147
|
+
**Basic usage (default columns):**
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { pgTable, text } from 'drizzle-orm/pg-core';
|
|
151
|
+
import { generateTzColumnDefs } from '@venizia/ignis';
|
|
152
|
+
|
|
153
|
+
export const myTable = pgTable('MyTable', {
|
|
154
|
+
...generateTzColumnDefs(),
|
|
155
|
+
name: text('name').notNull(),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Generates: createdAt, modifiedAt (deletedAt is disabled by default)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Enable soft delete:**
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
export const myTable = pgTable('MyTable', {
|
|
165
|
+
...generateTzColumnDefs({
|
|
166
|
+
deleted: { enable: true, columnName: 'deleted_at', withTimezone: true },
|
|
167
|
+
}),
|
|
168
|
+
name: text('name').notNull(),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Generates: createdAt, modifiedAt, deletedAt
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Custom column names:**
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
export const myTable = pgTable('MyTable', {
|
|
178
|
+
...generateTzColumnDefs({
|
|
179
|
+
created: { columnName: 'created_date', withTimezone: true },
|
|
180
|
+
modified: { enable: true, columnName: 'updated_date', withTimezone: true },
|
|
181
|
+
deleted: { enable: true, columnName: 'removed_date', withTimezone: true },
|
|
182
|
+
}),
|
|
183
|
+
name: text('name').notNull(),
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Without timezone:**
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
export const myTable = pgTable('MyTable', {
|
|
191
|
+
...generateTzColumnDefs({
|
|
192
|
+
created: { columnName: 'created_at', withTimezone: false },
|
|
193
|
+
modified: { enable: true, columnName: 'modified_at', withTimezone: false },
|
|
194
|
+
deleted: { enable: true, columnName: 'deleted_at', withTimezone: false },
|
|
195
|
+
}),
|
|
196
|
+
name: text('name').notNull(),
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
**Minimal setup (only createdAt):**
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
export const myTable = pgTable('MyTable', {
|
|
206
|
+
...generateTzColumnDefs({
|
|
207
|
+
modified: { enable: false },
|
|
208
|
+
deleted: { enable: false },
|
|
209
|
+
}),
|
|
210
|
+
name: text('name').notNull(),
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Generates: createdAt only
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### Soft Delete Pattern
|
|
217
|
+
|
|
218
|
+
The `deletedAt` column enables the soft delete pattern, where records are marked as deleted rather than physically removed from the database.
|
|
219
|
+
|
|
220
|
+
**Example soft delete query:**
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { eq, isNull } from 'drizzle-orm';
|
|
224
|
+
|
|
225
|
+
// Soft delete: set deletedAt timestamp
|
|
226
|
+
await db.update(myTable)
|
|
227
|
+
.set({ deletedAt: new Date() })
|
|
228
|
+
.where(eq(myTable.id, id));
|
|
229
|
+
|
|
230
|
+
// Query only active (non-deleted) records
|
|
231
|
+
const activeRecords = await db.select()
|
|
232
|
+
.from(myTable)
|
|
233
|
+
.where(isNull(myTable.deletedAt));
|
|
234
|
+
|
|
235
|
+
// Query deleted records
|
|
236
|
+
const deletedRecords = await db.select()
|
|
237
|
+
.from(myTable)
|
|
238
|
+
.where(isNotNull(myTable.deletedAt));
|
|
239
|
+
|
|
240
|
+
// Restore a soft-deleted record
|
|
241
|
+
await db.update(myTable)
|
|
242
|
+
.set({ deletedAt: null })
|
|
243
|
+
.where(eq(myTable.id, id));
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### Type Inference
|
|
247
|
+
|
|
248
|
+
The enricher provides proper TypeScript type inference:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
type TTzEnricherResult<ColumnDefinitions extends TColumnDefinitions = TColumnDefinitions> = {
|
|
252
|
+
createdAt: PgTimestampBuilderInitial<string> & NotNull & HasDefault;
|
|
253
|
+
modifiedAt?: PgTimestampBuilderInitial<string> & NotNull & HasDefault;
|
|
254
|
+
deletedAt?: PgTimestampBuilderInitial<string>;
|
|
255
|
+
};
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Schema Utilities
|
|
261
|
+
|
|
262
|
+
### `snakeToCamel`
|
|
263
|
+
|
|
264
|
+
Converts a Zod schema from snake_case to camelCase, transforming both the schema shape and runtime data.
|
|
265
|
+
|
|
266
|
+
**File:** `packages/core/src/base/models/common/types.ts`
|
|
267
|
+
|
|
268
|
+
#### Signature
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
snakeToCamel<T extends z.ZodRawShape>(shape: T): z.ZodEffects<...>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Purpose
|
|
275
|
+
|
|
276
|
+
This utility is useful when working with databases that use snake_case column names but you want to work with camelCase in your TypeScript code. It creates a Zod schema that:
|
|
277
|
+
|
|
278
|
+
1. Accepts snake_case input (validates against original schema)
|
|
279
|
+
2. Transforms the data to camelCase at runtime
|
|
280
|
+
3. Validates the transformed data against a camelCase schema
|
|
281
|
+
|
|
282
|
+
#### Usage Example
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { z } from 'zod';
|
|
286
|
+
import { snakeToCamel } from '@venizia/ignis';
|
|
287
|
+
|
|
288
|
+
// Define schema with snake_case fields
|
|
289
|
+
const userSnakeSchema = {
|
|
290
|
+
user_id: z.number(),
|
|
291
|
+
first_name: z.string(),
|
|
292
|
+
last_name: z.string(),
|
|
293
|
+
created_at: z.date(),
|
|
294
|
+
is_active: z.boolean(),
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// Convert to camelCase schema
|
|
298
|
+
const userCamelSchema = snakeToCamel(userSnakeSchema);
|
|
299
|
+
|
|
300
|
+
// Input data from database (snake_case)
|
|
301
|
+
const dbData = {
|
|
302
|
+
user_id: 123,
|
|
303
|
+
first_name: 'John',
|
|
304
|
+
last_name: 'Doe',
|
|
305
|
+
created_at: new Date(),
|
|
306
|
+
is_active: true,
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
// Parse and transform to camelCase
|
|
310
|
+
const result = userCamelSchema.parse(dbData);
|
|
311
|
+
|
|
312
|
+
// Result is automatically camelCase:
|
|
313
|
+
console.log(result);
|
|
314
|
+
// {
|
|
315
|
+
// userId: 123,
|
|
316
|
+
// firstName: 'John',
|
|
317
|
+
// lastName: 'Doe',
|
|
318
|
+
// createdAt: Date,
|
|
319
|
+
// isActive: true
|
|
320
|
+
// }
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
#### Real-world Example
|
|
324
|
+
|
|
325
|
+
**Use case:** API endpoint that accepts snake_case but works with camelCase internally
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { BaseController, controller, snakeToCamel } from '@venizia/ignis';
|
|
329
|
+
import { z } from '@hono/zod-openapi';
|
|
330
|
+
|
|
331
|
+
const createUserSchema = snakeToCamel({
|
|
332
|
+
first_name: z.string().min(1),
|
|
333
|
+
last_name: z.string().min(1),
|
|
334
|
+
email_address: z.string().email(),
|
|
335
|
+
phone_number: z.string().optional(),
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
@controller({ path: '/users' })
|
|
339
|
+
export class UserController extends BaseController {
|
|
340
|
+
override binding() {
|
|
341
|
+
this.bindRoute({
|
|
342
|
+
configs: {
|
|
343
|
+
path: '/',
|
|
344
|
+
method: 'post',
|
|
345
|
+
request: {
|
|
346
|
+
body: {
|
|
347
|
+
content: {
|
|
348
|
+
'application/json': { schema: createUserSchema },
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
}).to({
|
|
354
|
+
handler: async (ctx) => {
|
|
355
|
+
// Request body is automatically camelCase
|
|
356
|
+
const data = ctx.req.valid('json');
|
|
357
|
+
|
|
358
|
+
// data = {
|
|
359
|
+
// firstName: string,
|
|
360
|
+
// lastName: string,
|
|
361
|
+
// emailAddress: string,
|
|
362
|
+
// phoneNumber?: string
|
|
363
|
+
// }
|
|
364
|
+
|
|
365
|
+
// Work with camelCase data
|
|
366
|
+
console.log(data.firstName); // ✅ TypeScript knows this exists
|
|
367
|
+
console.log(data.first_name); // ❌ TypeScript error
|
|
368
|
+
|
|
369
|
+
return ctx.json({ success: true });
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### Type Transformation
|
|
377
|
+
|
|
378
|
+
The utility includes sophisticated TypeScript type transformation:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
type TSnakeToCamelCase<S extends string> =
|
|
382
|
+
S extends `${infer T}_${infer U}`
|
|
383
|
+
? `${T}${Capitalize<TSnakeToCamelCase<U>>}`
|
|
384
|
+
: S;
|
|
385
|
+
|
|
386
|
+
type TCamelCaseKeys<T extends z.ZodRawShape> = {
|
|
387
|
+
[K in keyof T as K extends string ? TSnakeToCamelCase<K> : K]:
|
|
388
|
+
T[K] extends z.ZodType<infer U> ? z.ZodType<U> : T[K];
|
|
389
|
+
};
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
This ensures full type safety: TypeScript will know that `first_name` becomes `firstName`, `created_at` becomes `createdAt`, etc.
|
|
393
|
+
|
|
394
|
+
#### Validation
|
|
395
|
+
|
|
396
|
+
The schema validates twice for safety:
|
|
397
|
+
|
|
398
|
+
1. **First validation:** Checks that input matches snake_case schema
|
|
399
|
+
2. **Transformation:** Converts keys from snake_case to camelCase
|
|
400
|
+
3. **Second validation:** Validates transformed data against camelCase schema
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
// If validation fails at any step, you get clear error messages
|
|
404
|
+
const invalidData = {
|
|
405
|
+
user_id: 'not-a-number', // ❌ Fails first validation
|
|
406
|
+
first_name: 'John',
|
|
407
|
+
last_name: 'Doe',
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
userCamelSchema.parse(invalidData);
|
|
412
|
+
} catch (error) {
|
|
413
|
+
// ZodError with clear message about user_id expecting number
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### Notes
|
|
418
|
+
|
|
419
|
+
- Built on top of `keysToCamel()` and `toCamel()` utilities from `@venizia/ignis-helpers`
|
|
420
|
+
- Recursively handles nested objects
|
|
421
|
+
- Preserves array structures
|
|
422
|
+
- Works seamlessly with Zod's other features (refinements, transforms, etc.)
|
|
@@ -8,8 +8,10 @@ Reusable, pluggable modules that encapsulate specific features in Ignis applicat
|
|
|
8
8
|
|-----------|---------|--------------|
|
|
9
9
|
| [Authentication](./authentication.md) | JWT-based auth | Token generation, protected routes, user payload |
|
|
10
10
|
| [Health Check](./health-check.md) | Monitoring endpoint | `/health` endpoint, ping/pong functionality |
|
|
11
|
-
| [
|
|
11
|
+
| [Request Tracker](./request-tracker.md) | Request logging | Request ID generation, timing, structured logging |
|
|
12
12
|
| [Socket.IO](./socket-io.md) | Real-time communication | WebSocket support, Redis adapter, event-based |
|
|
13
|
+
| [Static Asset](./static-asset.md) | File management | Upload/download files, MinIO & local filesystem support |
|
|
14
|
+
| [Swagger](./swagger.md) | API documentation | OpenAPI generation, Swagger UI, Scalar UI |
|
|
13
15
|
|
|
14
16
|
## Creating a Component
|
|
15
17
|
|