@venizia/ignis-docs 0.2.0 → 0.2.1-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +24 -13
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +27 -3
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +8 -4
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +247 -153
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +109 -323
  26. package/content/extensions/components/authentication/api.md +489 -602
  27. package/content/extensions/components/authentication/errors.md +135 -498
  28. package/content/extensions/components/authentication/index.md +89 -801
  29. package/content/extensions/components/authentication/usage.md +231 -955
  30. package/content/extensions/components/authorization/api.md +991 -644
  31. package/content/extensions/components/authorization/errors.md +204 -208
  32. package/content/extensions/components/authorization/getting-started.md +227 -0
  33. package/content/extensions/components/authorization/index.md +88 -795
  34. package/content/extensions/components/authorization/usage.md +219 -528
  35. package/content/extensions/components/health-check.md +77 -243
  36. package/content/extensions/components/index.md +24 -90
  37. package/content/extensions/components/mail/api.md +553 -285
  38. package/content/extensions/components/mail/errors.md +76 -62
  39. package/content/extensions/components/mail/index.md +111 -463
  40. package/content/extensions/components/mail/usage.md +139 -173
  41. package/content/extensions/components/request-tracker.md +70 -173
  42. package/content/extensions/components/socket-io/api.md +462 -785
  43. package/content/extensions/components/socket-io/errors.md +49 -51
  44. package/content/extensions/components/socket-io/index.md +69 -372
  45. package/content/extensions/components/socket-io/usage.md +212 -105
  46. package/content/extensions/components/static-asset/api.md +461 -141
  47. package/content/extensions/components/static-asset/errors.md +121 -53
  48. package/content/extensions/components/static-asset/index.md +84 -606
  49. package/content/extensions/components/static-asset/usage.md +184 -299
  50. package/content/extensions/components/template/index.md +3 -3
  51. package/content/extensions/components/websocket/api.md +311 -404
  52. package/content/extensions/components/websocket/errors.md +47 -56
  53. package/content/extensions/components/websocket/index.md +75 -407
  54. package/content/extensions/components/websocket/usage.md +120 -338
  55. package/content/extensions/helpers/cron/index.md +52 -160
  56. package/content/extensions/helpers/crypto/index.md +67 -480
  57. package/content/extensions/helpers/crypto/reference.md +528 -0
  58. package/content/extensions/helpers/env/index.md +64 -178
  59. package/content/extensions/helpers/error/index.md +286 -196
  60. package/content/extensions/helpers/index.md +61 -47
  61. package/content/extensions/helpers/inversion/index.md +76 -550
  62. package/content/extensions/helpers/inversion/reference.md +530 -0
  63. package/content/extensions/helpers/kafka/admin.md +23 -3
  64. package/content/extensions/helpers/kafka/compile-binary.md +83 -52
  65. package/content/extensions/helpers/kafka/consumer.md +65 -28
  66. package/content/extensions/helpers/kafka/examples.md +46 -253
  67. package/content/extensions/helpers/kafka/index.md +55 -617
  68. package/content/extensions/helpers/kafka/producer.md +156 -22
  69. package/content/extensions/helpers/kafka/schema-registry.md +59 -79
  70. package/content/extensions/helpers/logger/hf-logger.md +220 -0
  71. package/content/extensions/helpers/logger/index.md +78 -552
  72. package/content/extensions/helpers/logger/pino.md +105 -0
  73. package/content/extensions/helpers/logger/reference.md +937 -0
  74. package/content/extensions/helpers/network/api.md +276 -195
  75. package/content/extensions/helpers/network/index.md +87 -524
  76. package/content/extensions/helpers/queue/index.md +80 -897
  77. package/content/extensions/helpers/queue/reference.md +494 -0
  78. package/content/extensions/helpers/redis/index.md +86 -640
  79. package/content/extensions/helpers/redis/reference.md +784 -0
  80. package/content/extensions/helpers/secrets/index.md +136 -0
  81. package/content/extensions/helpers/socket-io/api.md +325 -204
  82. package/content/extensions/helpers/socket-io/index.md +79 -429
  83. package/content/extensions/helpers/storage/api.md +584 -464
  84. package/content/extensions/helpers/storage/index.md +80 -573
  85. package/content/extensions/helpers/types/index.md +75 -495
  86. package/content/extensions/helpers/types/reference.md +689 -0
  87. package/content/extensions/helpers/uid/index.md +176 -189
  88. package/content/extensions/helpers/websocket/api.md +366 -214
  89. package/content/extensions/helpers/websocket/index.md +68 -503
  90. package/content/extensions/helpers/worker-thread/index.md +62 -396
  91. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  92. package/content/extensions/index.md +38 -39
  93. package/content/extensions/src-details/mcp-server.md +96 -548
  94. package/content/guides/core-concepts/persistent/datasources.md +2 -2
  95. package/content/guides/core-concepts/persistent/index.md +5 -1
  96. package/content/guides/core-concepts/persistent/models.md +1 -1
  97. package/content/guides/core-concepts/persistent/pglite.md +218 -0
  98. package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
  99. package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
  100. package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
  101. package/content/guides/core-concepts/persistent/sqlite.md +296 -0
  102. package/content/guides/core-concepts/persistent/transactions.md +12 -11
  103. package/content/guides/core-concepts/secrets-vault.md +177 -0
  104. package/content/guides/core-concepts/services.md +1 -1
  105. package/content/guides/get-started/5-minute-quickstart.md +59 -206
  106. package/content/guides/get-started/philosophy.md +135 -670
  107. package/content/guides/get-started/setup.md +53 -74
  108. package/content/guides/migrations/redis-helpers-migration.md +5 -4
  109. package/content/guides/migrations/scoped-rbac-migration.md +5 -5
  110. package/content/guides/migrations/unified-connectors-migration.md +8 -7
  111. package/content/guides/tutorials/ecommerce-api.md +3 -8
  112. package/content/guides/tutorials/realtime-chat.md +1 -1
  113. package/content/references/base/application.md +64 -22
  114. package/content/references/base/components.md +3 -3
  115. package/content/references/base/connectors.md +79 -136
  116. package/content/references/base/controllers.md +12 -12
  117. package/content/references/base/datasources-reference.md +600 -0
  118. package/content/references/base/datasources.md +84 -444
  119. package/content/references/base/dependency-injection.md +25 -46
  120. package/content/references/base/filter-system/application-usage.md +95 -123
  121. package/content/references/base/filter-system/array-operators.md +33 -43
  122. package/content/references/base/filter-system/comparison-operators.md +55 -63
  123. package/content/references/base/filter-system/default-filter.md +144 -350
  124. package/content/references/base/filter-system/fields-order-pagination.md +116 -148
  125. package/content/references/base/filter-system/index.md +114 -253
  126. package/content/references/base/filter-system/json-filtering.md +52 -181
  127. package/content/references/base/filter-system/list-operators.md +28 -44
  128. package/content/references/base/filter-system/logical-operators.md +69 -114
  129. package/content/references/base/filter-system/null-operators.md +41 -98
  130. package/content/references/base/filter-system/pattern-matching.md +48 -51
  131. package/content/references/base/filter-system/quick-reference.md +93 -196
  132. package/content/references/base/filter-system/range-operators.md +22 -38
  133. package/content/references/base/filter-system/tips.md +70 -133
  134. package/content/references/base/filter-system/use-cases.md +173 -232
  135. package/content/references/base/grpc-controllers.md +53 -17
  136. package/content/references/base/index.md +5 -3
  137. package/content/references/base/middlewares.md +43 -28
  138. package/content/references/base/models-reference.md +886 -0
  139. package/content/references/base/models.md +81 -1452
  140. package/content/references/base/providers.md +8 -8
  141. package/content/references/base/repositories/advanced.md +281 -419
  142. package/content/references/base/repositories/index.md +84 -644
  143. package/content/references/base/repositories/mixins.md +25 -21
  144. package/content/references/base/repositories/relations.md +194 -375
  145. package/content/references/base/repositories/soft-deletable.md +67 -55
  146. package/content/references/base/secrets.md +267 -0
  147. package/content/references/base/services.md +8 -6
  148. package/content/references/configuration/environment-variables.md +73 -21
  149. package/content/references/configuration/index.md +51 -31
  150. package/content/references/index.md +1 -1
  151. package/content/references/quick-reference.md +3 -16
  152. package/content/references/utilities/crypto.md +35 -76
  153. package/content/references/utilities/date.md +33 -73
  154. package/content/references/utilities/duration.md +85 -0
  155. package/content/references/utilities/index.md +6 -2
  156. package/content/references/utilities/jsx-reference.md +298 -0
  157. package/content/references/utilities/jsx.md +82 -525
  158. package/content/references/utilities/module.md +81 -61
  159. package/content/references/utilities/parse.md +34 -64
  160. package/content/references/utilities/performance.md +33 -58
  161. package/content/references/utilities/promise.md +28 -62
  162. package/content/references/utilities/request.md +58 -218
  163. package/content/references/utilities/retry.md +139 -0
  164. package/content/references/utilities/schema.md +43 -137
  165. package/content/references/utilities/statuses-reference.md +361 -0
  166. package/content/references/utilities/statuses.md +63 -667
  167. package/dist/mcp-server/index.js +0 -0
  168. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  169. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  170. package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
  171. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  172. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  173. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  174. package/package.json +24 -23
@@ -0,0 +1,177 @@
1
+ ---
2
+ title: Secrets & Vault
3
+ description: Load configuration and credentials from a vault, hydrate them at boot, and rotate database credentials without a restart
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Secrets & Vault
8
+
9
+ IGNIS can load configuration and credentials from a vault instead of reading `process.env` directly. This guide shows how to enable it, how to consume secrets in your code, and how to rotate dynamic database credentials into a live pool without restarting the server.
10
+
11
+ > [!TIP] You do not have to do anything to keep working as before
12
+ > Until you override `registerSecrets()`, IGNIS uses the `system-envs` provider, which reads `process.env`. Everything below is opt-in.
13
+
14
+ ## The Mental Model
15
+
16
+ Secrets reach your app through two paths:
17
+
18
+ - **Hydrate** - at boot, IGNIS fetches secrets and merges them into `process.env` / `Envs`. Existing code that reads `process.env.APP_ENV_*` keeps working with no change.
19
+ - **Provider** - the resolved provider is bound in the container at `@app/config`. Inject it wherever you need on-demand reads, dynamic credentials, or rotation.
20
+
21
+ You configure both in one place: a `registerSecrets()` override on your application class.
22
+
23
+ ## Enabling a Provider
24
+
25
+ Override `registerSecrets()` on your `Application extends BaseApplication`.
26
+
27
+ ### HashiCorp Vault
28
+
29
+ Recommended for enterprise: KV v2 static secrets plus dynamic database credentials with automatic rotation.
30
+
31
+ ```typescript
32
+ import { SecretProviders, VaultAuthMethods } from '@venizia/ignis-helpers';
33
+
34
+ export class Application extends BaseApplication {
35
+ override registerSecrets() {
36
+ return {
37
+ provider: SecretProviders.HASHICORP_VAULT,
38
+
39
+ config: {
40
+ endpoint: 'https://vault.internal:8200',
41
+ // Dev: a raw token. Production: AppRole or Kubernetes.
42
+ auth: { method: VaultAuthMethods.APP_ROLE, roleId, secretId },
43
+ // or: { method: VaultAuthMethods.TOKEN, token }
44
+ // or: { method: VaultAuthMethods.KUBERNETES, role: 'my-app' }
45
+ },
46
+
47
+ // Static KV v2 secrets -> merged into Envs once at boot.
48
+ hydrate: [
49
+ { path: 'secret/data/myapp/config' }, // keys land as-is
50
+ { path: 'secret/data/myapp/db', prefix: 'APP_ENV_DS_' }, // optional prefix
51
+ // { path: 'secret/data/myapp/db', keys: { password: 'APP_ENV_DS_PASSWORD' } },
52
+ ],
53
+
54
+ // Dynamic engine secrets -> renewed and rotated automatically.
55
+ lease: [
56
+ { key: 'datasources.PostgresDataSource', path: 'database/creds/app-role' },
57
+ ],
58
+ };
59
+ }
60
+ }
61
+ ```
62
+
63
+ `node-vault` is an optional peer. Install it in the application that uses this provider:
64
+
65
+ ```bash
66
+ bun add node-vault
67
+ ```
68
+
69
+ Applications that do not use this provider never need it - not even when compiling a binary with
70
+ `Bun.build`. If your application uses this provider **and** compiles a binary, ship `node-vault` in
71
+ `node_modules` next to the binary, or inject a ready-made `client` through the helper options.
72
+
73
+ ### Dotenv Vault
74
+
75
+ An encrypted `.env.vault` file decrypted at runtime with a per-environment `DOTENV_KEY`. Static only.
76
+
77
+ ```typescript
78
+ import { SecretProviders } from '@venizia/ignis-helpers';
79
+
80
+ export class Application extends BaseApplication {
81
+ override registerSecrets() {
82
+ return {
83
+ provider: SecretProviders.DOTENV_VAULT,
84
+ config: { path: '.env.vault', dotenvKey: process.env.DOTENV_KEY },
85
+ hydrate: [{ path: 'ignored' }], // decrypts the file and merges it into Envs
86
+ };
87
+ }
88
+ }
89
+ ```
90
+
91
+ ```bash
92
+ bun add @dotenvx/dotenvx
93
+ ```
94
+
95
+ ### System Env (default)
96
+
97
+ The default; shown here only to be explicit. Reads `process.env`, no dependencies.
98
+
99
+ ```typescript
100
+ override registerSecrets() {
101
+ return { provider: SecretProviders.SYSTEM_ENVS };
102
+ }
103
+ ```
104
+
105
+ ## Addressing and Merging
106
+
107
+ Each `hydrate` entry resolves a path to a flat key-value object that is merged into `Envs` and `process.env`:
108
+
109
+ - **Convention** - store the keys in the vault already named `APP_ENV_...` and they merge as-is, no mapping needed.
110
+ - **`prefix`** - prepend a string to every merged key.
111
+ - **`keys`** - an explicit `vaultKey -> envKey` map for precise control (wins over `prefix`).
112
+
113
+ When the provider is live, vault values take precedence over `process.env`.
114
+
115
+ ## Reading Secrets in Your Code
116
+
117
+ Inject the provider bound at `@app/config`.
118
+
119
+ ```typescript
120
+ import type { ISecretsHelper } from '@venizia/ignis-helpers';
121
+
122
+ @service()
123
+ export class BillingService {
124
+ constructor(
125
+ @inject({ key: '@app/config' }) private secrets: ISecretsHelper,
126
+ ) {}
127
+
128
+ async run() {
129
+ // A single keyed value (TTL-cached):
130
+ const apiKey = await this.secrets.get({ path: 'secret/data/myapp/stripe', key: 'apiKey' });
131
+
132
+ // Or the whole bundle at a path:
133
+ const bundle = await this.secrets.getBundle({ path: 'secret/data/myapp/stripe' });
134
+ }
135
+ }
136
+ ```
137
+
138
+ Code that only relies on hydrated values keeps reading `process.env.APP_ENV_*` and needs no injection at all.
139
+
140
+ ## Rotating Database Credentials
141
+
142
+ Dynamic secrets let Vault mint short-lived database credentials that expire and rotate. IGNIS renews them and, on rotation, rebuilds the connection pool gracefully.
143
+
144
+ You do **not** write any rotation code for PostgreSQL. Two steps enable it:
145
+
146
+ 1. Configure a dynamic database engine in Vault so a read against `database/creds/<role>` returns fresh credentials with a TTL.
147
+ 2. Add a `lease` entry whose `key` is the DI binding key of your datasource (`datasources.<ClassName>`), as in the HashiCorp example above.
148
+
149
+ From there IGNIS:
150
+
151
+ - renews the lease before it expires;
152
+ - when Vault issues fresh credentials, calls the datasource's `onSecretRotated()`, which swaps the new credentials in, builds a new pool, and drains the old one so in-flight transactions finish;
153
+ - keeps the app running - no restart.
154
+
155
+ > [!WARNING] Your datasource configure() must read from this.settings
156
+ > Rotation writes the new credentials onto `this.settings` and re-runs `configure()`. If your `configure()` builds the pool from a hard-coded connection string instead, rotation rebuilds with stale credentials. Build the pool from `this.settings`:
157
+ > ```typescript
158
+ > override configure(): void {
159
+ > this.client = new Pool(this.settings);
160
+ > }
161
+ > ```
162
+
163
+ ## Behaviour When the Vault Is Down
164
+
165
+ The failure policy is keyed on `NODE_ENV`:
166
+
167
+ - **Development** (`local`, `debug`, `development`, `dev`, `sit`) - a vault failure logs a warning and falls back to `process.env`, so you can work offline.
168
+ - **Everything else** - a vault failure throws and crashes the boot. The app never starts with missing or empty secrets.
169
+
170
+ ## Testing Against a Real Vault
171
+
172
+ A local end-to-end setup (Vault dev-mode plus a throwaway PostgreSQL) is described in `docs/superpowers/vault-integration-local-testing.md` in the repository.
173
+
174
+ ## See Also
175
+
176
+ - [Secrets & Vault Reference](/references/base/secrets) - full API, machinery, and const-classes
177
+ - [DataSources](/guides/core-concepts/persistent/datasources) - the pool that rotation rebuilds
@@ -57,7 +57,7 @@ export class UserService extends BaseService {
57
57
 
58
58
  ## Registering a Service
59
59
 
60
- Registration is always imperative - call `this.service(ClassName)` inside an application lifecycle method. Do not add `@injectable` to services; `this.service()` handles the binding.
60
+ Registration is always imperative - call `this.service(ClassName)` inside an application lifecycle method, which handles the binding. There is no class-level decorator for this.
61
61
 
62
62
  ```typescript
63
63
  import { BaseApplication } from '@venizia/ignis';
@@ -1,21 +1,27 @@
1
1
  # 5-Minute Quickstart
2
2
 
3
- Build your first IGNIS API endpoint in 5 minutes. No database, no complex setup - just a working "Hello World" API.
3
+ Build a working IGNIS API: one controller, one route, dependency injection, and generated API docs - no database required.
4
4
 
5
- **Time to Complete:** ~5 minutes
5
+ **Time to complete:** ~5 minutes
6
6
 
7
- > **Prerequisites:** [Bun installed](./setup) and basic TypeScript knowledge.
7
+ > **Prerequisite:** [Install Bun](./setup) 1.3 or later before you start.
8
8
 
9
- ## Step 1: Create Project (30 seconds)
9
+ ## 1. Create the project
10
+
11
+ Scaffold a project and install IGNIS:
10
12
 
11
13
  ```bash
12
14
  mkdir my-app && cd my-app
13
15
  bun init -y
14
16
  bun add hono @hono/zod-openapi @scalar/hono-api-reference @venizia/ignis @venizia/ignis-helpers
15
- bun add -d typescript @types/bun @venizia/dev-configs eslint prettier tsc-alias
17
+ bun add -d typescript @types/bun @venizia/dev-configs
16
18
  ```
17
19
 
18
- ## Step 2: Configure Development Tools (30 seconds)
20
+ Both commands finish in a few seconds. You now have a `package.json` with IGNIS in `dependencies`.
21
+
22
+ ## 2. Configure TypeScript for decorators
23
+
24
+ IGNIS controllers use TypeScript's legacy decorators (`@controller`, `@get`). Set the two decorator flags directly in your own `tsconfig.json`. Bun does not reliably resolve them through an `extends` chain, and a missing flag drops your routes silently.
19
25
 
20
26
  Create `tsconfig.json`:
21
27
 
@@ -26,59 +32,23 @@ Create `tsconfig.json`:
26
32
  "compilerOptions": {
27
33
  "outDir": "dist",
28
34
  "rootDir": "src",
29
- "baseUrl": "src",
30
35
  "paths": {
31
- "@/*": ["./*"]
32
- }
36
+ "@/*": ["./src/*"]
37
+ },
38
+ "experimentalDecorators": true,
39
+ "emitDecoratorMetadata": true
33
40
  },
34
41
  "include": ["src"],
35
42
  "exclude": ["node_modules", "dist"]
36
43
  }
37
44
  ```
38
45
 
39
- Create `eslint.config.mjs`:
40
-
41
- ```javascript
42
- import { eslintConfigs } from "@venizia/dev-configs";
43
-
44
- export default eslintConfigs;
45
- ```
46
-
47
- Create `.prettierrc.mjs`:
48
-
49
- ```javascript
50
- import { prettierConfigs } from "@venizia/dev-configs";
51
-
52
- export default prettierConfigs;
53
- ```
54
-
55
- Create `.prettierignore`:
56
-
57
- ```
58
- dist
59
- node_modules
60
- *.log
61
- .*-audit.json
62
- ```
63
-
64
- ## Step 3: Write Your API (2 minutes)
65
-
66
- :::info What is a Decorator?
67
- A decorator is a TypeScript feature that adds behavior to classes, methods, or properties. It's the `@something` syntax you see before definitions (like `@controller`, `@get`, `@inject`). Decorators in IGNIS handle routing, dependency injection, and API documentation automatically.
68
-
69
- [Learn more →](/guides/reference/glossary#decorators)
70
- :::
71
-
72
- :::info What is Binding?
73
- "Binding" means registering a component (like a service or repository) with the application's dependency injection container. Think of it as telling the app: "Hey, this service exists and here's how to create it." Once bound, you can inject it anywhere using `@inject`.
74
-
75
- [Learn more →](/guides/core-concepts/dependency-injection)
76
- :::
46
+ ## 3. Write the API
77
47
 
78
48
  Create `src/index.ts`:
79
49
 
80
50
  ```typescript
81
- import { z } from "@hono/zod-openapi";
51
+ import { z } from '@hono/zod-openapi';
82
52
  import {
83
53
  BaseApplication,
84
54
  BaseRestController,
@@ -87,224 +57,107 @@ import {
87
57
  IApplicationInfo,
88
58
  jsonContent,
89
59
  ApiReferenceComponent,
90
- } from "@venizia/ignis";
91
- import { HTTP } from "@venizia/ignis-helpers";
92
- import { Context } from "hono";
93
- import appInfo from "./../package.json";
60
+ } from '@venizia/ignis';
61
+ import { HTTP } from '@venizia/ignis-helpers';
62
+ import { Context } from 'hono';
63
+ import appInfo from './../package.json';
94
64
 
95
- // 1. Define a controller
96
- @controller({ path: "/hello" })
65
+ @controller({ path: '/hello' })
97
66
  class HelloController extends BaseRestController {
98
67
  constructor() {
99
- super({ scope: "HelloController", path: "/hello" });
68
+ super({ scope: 'HelloController', path: '/hello' });
100
69
  }
101
70
 
102
- // Override binding() to register custom routes via bindRoute() or defineRoute().
103
- // For decorator-based routes (@get, @post), this can be empty.
71
+ // binding() is abstract - leave it empty when every route uses @get/@post decorators.
104
72
  override binding() {}
105
73
 
106
74
  @get({
107
75
  configs: {
108
- path: "/",
76
+ path: '/',
109
77
  responses: {
110
78
  [HTTP.ResultCodes.RS_2.Ok]: jsonContent({
111
- description: "Says hello",
79
+ description: 'Says hello',
112
80
  schema: z.object({ message: z.string() }),
113
81
  }),
114
82
  },
115
83
  },
116
84
  })
117
85
  sayHello(c: Context) {
118
- return c.json({ message: "Hello from IGNIS!" }, HTTP.ResultCodes.RS_2.Ok);
86
+ return c.json({ message: 'Hello from IGNIS!' }, HTTP.ResultCodes.RS_2.Ok);
119
87
  }
120
88
  }
121
89
 
122
- // 2. Create the application
123
90
  class App extends BaseApplication {
124
91
  getAppInfo(): IApplicationInfo {
125
92
  return appInfo;
126
93
  }
127
94
 
128
- staticConfigure() {
129
- // Static configuration before dependency injection
130
- }
95
+ staticConfigure() {}
131
96
 
132
97
  preConfigure() {
133
98
  this.component(ApiReferenceComponent);
134
99
  this.controller(HelloController);
135
100
  }
136
101
 
137
- postConfigure() {
138
- // Configuration after all bindings are complete
139
- }
102
+ postConfigure() {}
140
103
 
141
- setupMiddlewares() {
142
- // Custom middleware setup (optional)
143
- }
104
+ setupMiddlewares() {}
144
105
  }
145
106
 
146
- // 3. Start the server
147
107
  const app = new App({
148
- scope: "App",
108
+ scope: 'App',
149
109
  config: {
150
- host: "0.0.0.0",
110
+ host: '0.0.0.0',
151
111
  port: 3000,
152
- path: { base: "/api", isStrict: false },
153
- debug: { shouldShowRoutes: true }, // Prints all registered routes on startup
112
+ path: { base: '/api', isStrict: false },
154
113
  },
155
114
  });
156
115
 
157
- // start() runs the full lifecycle: preConfigure → register resources → setupMiddlewares → HTTP server
158
- app.start();
116
+ app.init();
117
+ await app.start();
159
118
  ```
160
119
 
161
- Update `package.json` to add build scripts:
120
+ `@controller` groups routes under `/hello`. `@get` registers a GET route together with its OpenAPI schema. `preConfigure()` wires the controller and the API docs component into dependency injection before the server starts. `app.init()` registers the application's core bindings - call it before `app.start()`.
162
121
 
163
- ```json
164
- {
165
- "name": "5-mins-qs",
166
- "version": "1.0.0",
167
- "description": "5-minute quickstart example",
168
- "private": true,
169
- "scripts": {
170
- "start": "bun run src/index.ts",
171
- "lint": "eslint --report-unused-disable-directives . && prettier \"**/*.{js,ts}\" -l",
172
- "lint:fix": "eslint --report-unused-disable-directives . --fix && prettier \"**/*.{js,ts}\" --write",
173
- "build": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
174
- "clean": "sh ./scripts/clean.sh",
175
- "rebuild": "bun run clean && bun run build",
176
- "server:dev": "NODE_ENV=development bun run src/index.ts",
177
- "server:prod": "NODE_ENV=production bun run dist/index.js"
178
- },
179
- "dependencies": {
180
- "hono": "^4.12.25",
181
- "@hono/zod-openapi": "latest",
182
- "@scalar/hono-api-reference": "latest",
183
- "@venizia/ignis": "latest",
184
- "@venizia/ignis-helpers": "latest"
185
- },
186
- "devDependencies": {
187
- "typescript": "^6.0.3",
188
- "@types/bun": "latest",
189
- "@venizia/dev-configs": "latest",
190
- "eslint": "^10.5.0",
191
- "prettier": "^3.8.4",
192
- "tsc-alias": "^1.8.10"
193
- }
194
- }
195
- ```
122
+ New to decorators or dependency injection? See the [glossary](/guides/reference/glossary#decorators) and [Dependency Injection](../core-concepts/dependency-injection.md).
196
123
 
197
- Create `scripts/clean.sh`:
124
+ ## 4. Run it
198
125
 
199
- ```bash
200
- #!/bin/bash
126
+ Start the server:
201
127
 
202
- # Remove build artifacts
203
- rm -rf dist/
204
- rm -rf node_modules/.cache/
128
+ ```bash
129
+ bun run src/index.ts
130
+ ```
205
131
 
206
- # Remove log files
207
- rm -f *.log
208
- rm -f .*.log
209
- rm -f .*-audit.json
132
+ After a moment you'll see:
210
133
 
211
- echo "Cleaned build artifacts and logs"
134
+ ```
135
+ [App-start] Server STARTED | Address: 0.0.0.0:3000
212
136
  ```
213
137
 
214
- ## Step 4: Run It (30 seconds)
138
+ In a new terminal, request the endpoint:
215
139
 
216
140
  ```bash
217
- bun run src/index.ts
141
+ curl http://localhost:3000/api/hello
218
142
  ```
219
143
 
220
- Visit `http://localhost:3000/api/hello` in your browser!
221
-
222
- **Response:**
144
+ You get:
223
145
 
224
146
  ```json
225
- { "message": "Hello from IGNIS!" }
147
+ {"message":"Hello from IGNIS!"}
226
148
  ```
227
149
 
228
- ## View API Docs
229
-
230
- Open `http://localhost:3000/doc/explorer` to see interactive Swagger UI documentation!
231
-
232
- ## What Just Happened?
233
-
234
- ### Framework Patterns
235
-
236
- | Component | What It Does |
237
- |-----------|--------------|
238
- | `@controller` | Registers a class as an API controller at `/api/hello`. Supports `transport` field for REST (default) or gRPC |
239
- | `@get` | Defines a GET endpoint with OpenAPI metadata (auto-sets HTTP method) |
240
- | `Zod schema` | Validates request/response and auto-generates OpenAPI docs |
241
- | `BaseRestController` | Provides lifecycle hooks, route binding, and OpenAPI integration for REST controllers |
242
- | `BaseApplication` | Manages dependency injection, middleware, and server startup |
243
- | `ApiReferenceComponent` | Generates interactive API docs at `/doc/explorer` |
244
- | `app.start()` | Runs the full lifecycle (preConfigure → register resources → middlewares) then starts HTTP server on port 3000 |
245
-
246
- ### Why Development Configs?
247
-
248
- You might wonder why we set up TypeScript, ESLint, and Prettier configs in a "quickstart". Here's why:
249
-
250
- **IGNIS is opinionated about code quality.** We believe clean, consistent code from day one prevents technical debt later. The `@venizia/dev-configs` package provides pre-configured settings that:
251
-
252
- | Config | Purpose |
253
- |--------|---------|
254
- | `tsconfig.json` | Strict TypeScript settings optimized for IGNIS decorators and path aliases |
255
- | `eslint.config.mjs` | Catches common errors, enforces best practices, works with TypeScript |
256
- | `.prettierrc.mjs` | Consistent formatting across your team - no more style debates |
150
+ ## 5. View the API docs
257
151
 
258
- **Benefits of starting with IGNIS code style:**
152
+ Open `http://localhost:3000/api/doc/explorer` in your browser. You'll see an interactive Scalar API reference listing `GET /hello`, generated from the Zod schema you wrote.
259
153
 
260
- - **Consistency** - Same patterns across all IGNIS projects
261
- - **IDE Support** - Better autocomplete, error detection, and refactoring
262
- - **Team Ready** - New developers can onboard faster with familiar structure
263
- - **CI/CD Friendly** - Lint and format checks work out of the box
154
+ ## What you built
264
155
 
265
- > [!TIP]
266
- > All configs extend from `@venizia/dev-configs`, so you get updates automatically. Customize by overriding specific rules in your local config files.
156
+ A running IGNIS REST API: one controller, one route, dependency injection wired through `BaseApplication`, and OpenAPI docs served automatically - all in a single file.
267
157
 
268
- ## Next Steps
158
+ ## Next steps
269
159
 
270
- **You have a working API!**
271
-
272
- **Want more?**
273
-
274
- - **Add a database?** → [Building a CRUD API](../tutorials/building-a-crud-api.md)
275
- - **Production setup?** → [Complete Setup Guide](../tutorials/complete-installation.md) (ESLint, Prettier, etc.)
276
- - **Understand the architecture?** → [Core Concepts](../core-concepts/application/)
277
-
278
- **Quick additions:**
279
-
280
- **Add a POST endpoint:**
281
-
282
- ```typescript
283
- @post({
284
- configs: {
285
- path: '/greet',
286
- request: {
287
- body: jsonContent({
288
- schema: z.object({ name: z.string() }),
289
- }),
290
- },
291
- responses: {
292
- [HTTP.ResultCodes.RS_2.Ok]: jsonContent({
293
- schema: z.object({ greeting: z.string() }),
294
- }),
295
- },
296
- },
297
- })
298
- async greet(c: Context) {
299
- const { name } = c.req.valid('json');
300
- return c.json({ greeting: `Hello, ${name}!` }, HTTP.ResultCodes.RS_2.Ok);
301
- }
302
- ```
303
-
304
- Test it:
305
-
306
- ```bash
307
- curl -X POST http://localhost:3000/api/hello/greet \
308
- -H "Content-Type: application/json" \
309
- -d '{"name":"World"}'
310
- ```
160
+ - Add a database: [Building a CRUD API](../tutorials/building-a-crud-api.md)
161
+ - Add lint, formatting, and build scripts: [Complete Installation](../tutorials/complete-installation.md)
162
+ - Add more routes and methods: [REST Controllers](../core-concepts/rest-controllers.md)
163
+ - Understand the application lifecycle: [Core Concepts: Application](../core-concepts/application/)