@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.
- package/README.md +14 -14
- package/content/best-practices/api-usage-examples.md +39 -19
- package/content/best-practices/architectural-patterns.md +24 -13
- package/content/best-practices/architecture-decisions.md +29 -16
- package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
- package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
- package/content/best-practices/code-style-standards/control-flow.md +33 -1
- package/content/best-practices/code-style-standards/documentation.md +28 -8
- package/content/best-practices/code-style-standards/function-patterns.md +15 -4
- package/content/best-practices/code-style-standards/index.md +7 -2
- package/content/best-practices/code-style-standards/naming-conventions.md +27 -3
- package/content/best-practices/code-style-standards/route-definitions.md +9 -5
- package/content/best-practices/code-style-standards/tooling.md +14 -1
- package/content/best-practices/code-style-standards/type-safety.md +39 -6
- package/content/best-practices/common-pitfalls.md +59 -35
- package/content/best-practices/contribution-workflow.md +8 -4
- package/content/best-practices/data-modeling.md +78 -62
- package/content/best-practices/deployment-strategies.md +56 -19
- package/content/best-practices/error-handling.md +247 -153
- package/content/best-practices/index.md +6 -0
- package/content/best-practices/performance-optimization.md +26 -13
- package/content/best-practices/security-guidelines.md +35 -9
- package/content/best-practices/testing-strategies.md +7 -2
- package/content/best-practices/troubleshooting-tips.md +27 -17
- package/content/extensions/components/api-reference.md +109 -323
- package/content/extensions/components/authentication/api.md +489 -602
- package/content/extensions/components/authentication/errors.md +135 -498
- package/content/extensions/components/authentication/index.md +89 -801
- package/content/extensions/components/authentication/usage.md +231 -955
- package/content/extensions/components/authorization/api.md +991 -644
- package/content/extensions/components/authorization/errors.md +204 -208
- package/content/extensions/components/authorization/getting-started.md +227 -0
- package/content/extensions/components/authorization/index.md +88 -795
- package/content/extensions/components/authorization/usage.md +219 -528
- package/content/extensions/components/health-check.md +77 -243
- package/content/extensions/components/index.md +24 -90
- package/content/extensions/components/mail/api.md +553 -285
- package/content/extensions/components/mail/errors.md +76 -62
- package/content/extensions/components/mail/index.md +111 -463
- package/content/extensions/components/mail/usage.md +139 -173
- package/content/extensions/components/request-tracker.md +70 -173
- package/content/extensions/components/socket-io/api.md +462 -785
- package/content/extensions/components/socket-io/errors.md +49 -51
- package/content/extensions/components/socket-io/index.md +69 -372
- package/content/extensions/components/socket-io/usage.md +212 -105
- package/content/extensions/components/static-asset/api.md +461 -141
- package/content/extensions/components/static-asset/errors.md +121 -53
- package/content/extensions/components/static-asset/index.md +84 -606
- package/content/extensions/components/static-asset/usage.md +184 -299
- package/content/extensions/components/template/index.md +3 -3
- package/content/extensions/components/websocket/api.md +311 -404
- package/content/extensions/components/websocket/errors.md +47 -56
- package/content/extensions/components/websocket/index.md +75 -407
- package/content/extensions/components/websocket/usage.md +120 -338
- package/content/extensions/helpers/cron/index.md +52 -160
- package/content/extensions/helpers/crypto/index.md +67 -480
- package/content/extensions/helpers/crypto/reference.md +528 -0
- package/content/extensions/helpers/env/index.md +64 -178
- package/content/extensions/helpers/error/index.md +286 -196
- package/content/extensions/helpers/index.md +61 -47
- package/content/extensions/helpers/inversion/index.md +76 -550
- package/content/extensions/helpers/inversion/reference.md +530 -0
- package/content/extensions/helpers/kafka/admin.md +23 -3
- package/content/extensions/helpers/kafka/compile-binary.md +83 -52
- package/content/extensions/helpers/kafka/consumer.md +65 -28
- package/content/extensions/helpers/kafka/examples.md +46 -253
- package/content/extensions/helpers/kafka/index.md +55 -617
- package/content/extensions/helpers/kafka/producer.md +156 -22
- package/content/extensions/helpers/kafka/schema-registry.md +59 -79
- package/content/extensions/helpers/logger/hf-logger.md +220 -0
- package/content/extensions/helpers/logger/index.md +78 -552
- package/content/extensions/helpers/logger/pino.md +105 -0
- package/content/extensions/helpers/logger/reference.md +937 -0
- package/content/extensions/helpers/network/api.md +276 -195
- package/content/extensions/helpers/network/index.md +87 -524
- package/content/extensions/helpers/queue/index.md +80 -897
- package/content/extensions/helpers/queue/reference.md +494 -0
- package/content/extensions/helpers/redis/index.md +86 -640
- package/content/extensions/helpers/redis/reference.md +784 -0
- package/content/extensions/helpers/secrets/index.md +136 -0
- package/content/extensions/helpers/socket-io/api.md +325 -204
- package/content/extensions/helpers/socket-io/index.md +79 -429
- package/content/extensions/helpers/storage/api.md +584 -464
- package/content/extensions/helpers/storage/index.md +80 -573
- package/content/extensions/helpers/types/index.md +75 -495
- package/content/extensions/helpers/types/reference.md +689 -0
- package/content/extensions/helpers/uid/index.md +176 -189
- package/content/extensions/helpers/websocket/api.md +366 -214
- package/content/extensions/helpers/websocket/index.md +68 -503
- package/content/extensions/helpers/worker-thread/index.md +62 -396
- package/content/extensions/helpers/worker-thread/reference.md +428 -0
- package/content/extensions/index.md +38 -39
- package/content/extensions/src-details/mcp-server.md +96 -548
- package/content/guides/core-concepts/persistent/datasources.md +2 -2
- package/content/guides/core-concepts/persistent/index.md +5 -1
- package/content/guides/core-concepts/persistent/models.md +1 -1
- package/content/guides/core-concepts/persistent/pglite.md +218 -0
- package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
- package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
- package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
- package/content/guides/core-concepts/persistent/sqlite.md +296 -0
- package/content/guides/core-concepts/persistent/transactions.md +12 -11
- package/content/guides/core-concepts/secrets-vault.md +177 -0
- package/content/guides/core-concepts/services.md +1 -1
- package/content/guides/get-started/5-minute-quickstart.md +59 -206
- package/content/guides/get-started/philosophy.md +135 -670
- package/content/guides/get-started/setup.md +53 -74
- package/content/guides/migrations/redis-helpers-migration.md +5 -4
- package/content/guides/migrations/scoped-rbac-migration.md +5 -5
- package/content/guides/migrations/unified-connectors-migration.md +8 -7
- package/content/guides/tutorials/ecommerce-api.md +3 -8
- package/content/guides/tutorials/realtime-chat.md +1 -1
- package/content/references/base/application.md +64 -22
- package/content/references/base/components.md +3 -3
- package/content/references/base/connectors.md +79 -136
- package/content/references/base/controllers.md +12 -12
- package/content/references/base/datasources-reference.md +600 -0
- package/content/references/base/datasources.md +84 -444
- package/content/references/base/dependency-injection.md +25 -46
- package/content/references/base/filter-system/application-usage.md +95 -123
- package/content/references/base/filter-system/array-operators.md +33 -43
- package/content/references/base/filter-system/comparison-operators.md +55 -63
- package/content/references/base/filter-system/default-filter.md +144 -350
- package/content/references/base/filter-system/fields-order-pagination.md +116 -148
- package/content/references/base/filter-system/index.md +114 -253
- package/content/references/base/filter-system/json-filtering.md +52 -181
- package/content/references/base/filter-system/list-operators.md +28 -44
- package/content/references/base/filter-system/logical-operators.md +69 -114
- package/content/references/base/filter-system/null-operators.md +41 -98
- package/content/references/base/filter-system/pattern-matching.md +48 -51
- package/content/references/base/filter-system/quick-reference.md +93 -196
- package/content/references/base/filter-system/range-operators.md +22 -38
- package/content/references/base/filter-system/tips.md +70 -133
- package/content/references/base/filter-system/use-cases.md +173 -232
- package/content/references/base/grpc-controllers.md +53 -17
- package/content/references/base/index.md +5 -3
- package/content/references/base/middlewares.md +43 -28
- package/content/references/base/models-reference.md +886 -0
- package/content/references/base/models.md +81 -1452
- package/content/references/base/providers.md +8 -8
- package/content/references/base/repositories/advanced.md +281 -419
- package/content/references/base/repositories/index.md +84 -644
- package/content/references/base/repositories/mixins.md +25 -21
- package/content/references/base/repositories/relations.md +194 -375
- package/content/references/base/repositories/soft-deletable.md +67 -55
- package/content/references/base/secrets.md +267 -0
- package/content/references/base/services.md +8 -6
- package/content/references/configuration/environment-variables.md +73 -21
- package/content/references/configuration/index.md +51 -31
- package/content/references/index.md +1 -1
- package/content/references/quick-reference.md +3 -16
- package/content/references/utilities/crypto.md +35 -76
- package/content/references/utilities/date.md +33 -73
- package/content/references/utilities/duration.md +85 -0
- package/content/references/utilities/index.md +6 -2
- package/content/references/utilities/jsx-reference.md +298 -0
- package/content/references/utilities/jsx.md +82 -525
- package/content/references/utilities/module.md +81 -61
- package/content/references/utilities/parse.md +34 -64
- package/content/references/utilities/performance.md +33 -58
- package/content/references/utilities/promise.md +28 -62
- package/content/references/utilities/request.md +58 -218
- package/content/references/utilities/retry.md +139 -0
- package/content/references/utilities/schema.md +43 -137
- package/content/references/utilities/statuses-reference.md +361 -0
- package/content/references/utilities/statuses.md +63 -667
- package/dist/mcp-server/index.js +0 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
- package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
- package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
- package/package.json +24 -23
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# API Reference
|
|
2
2
|
|
|
3
|
-
Automatic interactive API documentation
|
|
3
|
+
Automatic interactive API documentation generated from your OpenAPI spec. A pluggable UI provider renders it - Scalar by default, or classic Swagger UI.
|
|
4
4
|
|
|
5
5
|
> [!NOTE] Renamed from SwaggerComponent
|
|
6
|
-
> Swagger UI is
|
|
6
|
+
> Swagger UI is one of the pluggable UI providers, not the only one, so the component carries a vendor-neutral name. The deprecated `Swagger*` aliases are **removed**: use `ApiReferenceComponent`, `IApiReferenceOptions` and `ApiReferenceBindingKeys.API_REFERENCE_OPTIONS`.
|
|
7
7
|
|
|
8
8
|
## Quick Reference
|
|
9
9
|
|
|
@@ -14,7 +14,7 @@ Automatic interactive API documentation generation using OpenAPI specifications,
|
|
|
14
14
|
| **UI Factory** | `UIProviderFactory` |
|
|
15
15
|
| **Runtimes** | Both |
|
|
16
16
|
|
|
17
|
-
| Provider | Value | When to
|
|
17
|
+
| Provider | Value | When to use |
|
|
18
18
|
|----------|-------|-------------|
|
|
19
19
|
| **Scalar** | `'scalar'` | Modern, clean UI (default) |
|
|
20
20
|
| **Swagger UI** | `'swagger'` | Classic Swagger interface |
|
|
@@ -25,31 +25,9 @@ import { ApiReferenceComponent, ApiReferenceBindingKeys, UIProviderFactory } fro
|
|
|
25
25
|
import type { IApiReferenceOptions, IUIProvider, IUIConfig, IGetProviderParams } from '@venizia/ignis';
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## In one example
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Skip this step to use the defaults (Scalar UI at `/doc/explorer`). To customize:
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
// In your Application class's preConfigure method (src/application.ts)
|
|
36
|
-
import { ApiReferenceBindingKeys, IApiReferenceOptions } from '@venizia/ignis';
|
|
37
|
-
|
|
38
|
-
this.bind<IApiReferenceOptions>({
|
|
39
|
-
key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
|
|
40
|
-
}).toValue({
|
|
41
|
-
restOptions: {
|
|
42
|
-
base: { path: '/doc' },
|
|
43
|
-
doc: { path: '/openapi.json' },
|
|
44
|
-
ui: { path: '/explorer', type: 'swagger' }, // Use Swagger UI instead of Scalar
|
|
45
|
-
},
|
|
46
|
-
explorer: {
|
|
47
|
-
openapi: '3.0.0',
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Step 2: Register Component
|
|
30
|
+
Register the component - no configuration required. The docs UI comes up at `<app base path>/doc/explorer`, the raw spec at `<app base path>/doc/openapi.json`. With the `/api` base path used throughout the getting-started guide, that's `/api/doc/explorer`.
|
|
53
31
|
|
|
54
32
|
```typescript
|
|
55
33
|
// src/application.ts
|
|
@@ -57,15 +35,12 @@ import { ApiReferenceComponent, BaseApplication, ValueOrPromise } from '@venizia
|
|
|
57
35
|
|
|
58
36
|
export class Application extends BaseApplication {
|
|
59
37
|
preConfigure(): ValueOrPromise<void> {
|
|
60
|
-
// ...
|
|
61
38
|
this.component(ApiReferenceComponent);
|
|
62
39
|
}
|
|
63
40
|
}
|
|
64
41
|
```
|
|
65
42
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
To get the most out of the documentation, define your routes with `zod` schemas:
|
|
43
|
+
Define routes with Zod schemas so they show up in the generated spec:
|
|
69
44
|
|
|
70
45
|
```typescript
|
|
71
46
|
// src/controllers/hello.controller.ts
|
|
@@ -100,45 +75,65 @@ export class HelloController extends BaseRestController {
|
|
|
100
75
|
```
|
|
101
76
|
|
|
102
77
|
> [!TIP]
|
|
103
|
-
>
|
|
78
|
+
> Only routes registered through `defineRoute`, `bindRoute`, or `@api()` with `@hono/zod-openapi` schemas appear in the generated spec.
|
|
104
79
|
|
|
105
|
-
##
|
|
80
|
+
## How it works
|
|
106
81
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
82
|
+
- **Options merge group by group.** `binding()` reads the bound `IApiReferenceOptions`, then shallow-merges `base`, `doc`, and `ui` each against their own defaults. Overriding `ui.type` alone still keeps `ui.path` and every `base`/`doc` field.
|
|
83
|
+
- **`explorer.info` is always overwritten.** The component reads your `package.json` via `application.getAppInfo()`. It replaces `explorer.info` with `{ title, version, description, contact }` - any `explorer.info` you bind is discarded. Edit `package.json` instead.
|
|
84
|
+
- **`explorer.servers` fills in only when empty.** A supplied server entry is kept as-is. Otherwise, the component builds one from `application.getServerAddress()` plus the base path.
|
|
85
|
+
- **UI type resolution uses `??`, not `||`.** The source is `restOptions.ui.type ?? DocumentUITypes.SWAGGER`. Only `null`/`undefined` falls back, and it falls back to `'swagger'` - not the configured default `'scalar'`.
|
|
86
|
+
- An explicit empty string is NOT repaired by this fallback: it fails `DocumentUITypes.isValid()` and the component throws `Invalid document UI Type` immediately.
|
|
87
|
+
- **UI libraries load lazily.** `SwaggerUIProvider`/`ScalarUIProvider` each `await import()` their rendering library inside `render()`. That happens on the first request to the docs UI, not at application startup. Only the configured provider's library is ever loaded.
|
|
88
|
+
- **`ScalarUIProvider` renames `title` to `pageTitle`.** Scalar's own render API takes `pageTitle`, not `title` - worth knowing if you inspect the rendered output or write a custom UI provider.
|
|
89
|
+
- **Security schemes are always registered.** JWT (`bearer`) and Basic security schemes are added to the OpenAPI registry unconditionally. Routes using `authenticate: { strategies: ['jwt'] }` or `['basic']` render the correct auth UI as a result.
|
|
115
90
|
|
|
116
|
-
|
|
117
|
-
> The `explorer.info` field is **always overwritten** during the component's `binding()` phase. The component unconditionally reads your application's `package.json` via `application.getAppInfo()` and sets `explorer.info` to `{ title, version, description, contact }` from that data. Any user-provided `explorer.info` values are discarded. If you need to customize these fields, update your `package.json` instead.
|
|
91
|
+
## Common tasks
|
|
118
92
|
|
|
119
|
-
|
|
120
|
-
|
|
93
|
+
### Switch to Swagger UI
|
|
94
|
+
```typescript
|
|
95
|
+
this.bind<IApiReferenceOptions>({
|
|
96
|
+
key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
|
|
97
|
+
}).toValue({ restOptions: { ui: { type: 'swagger' } } });
|
|
98
|
+
```
|
|
121
99
|
|
|
122
|
-
|
|
100
|
+
### Move the docs under a different base path
|
|
101
|
+
```typescript
|
|
102
|
+
this.bind<IApiReferenceOptions>({
|
|
103
|
+
key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
|
|
104
|
+
}).toValue({ restOptions: { base: { path: '/api-docs' } } });
|
|
105
|
+
```
|
|
106
|
+
Result: UI at `<app base path>/api-docs/explorer`, spec at `<app base path>/api-docs/openapi.json`. The group merge keeps `doc.path`/`ui.path` defaults.
|
|
107
|
+
|
|
108
|
+
### Set the info block shown in the UI
|
|
109
|
+
`explorer.info` always comes from `package.json`. Update `name`, `version`, `description`, and `author` there - binding `explorer.info` directly has no effect.
|
|
110
|
+
|
|
111
|
+
### Register a custom UI provider
|
|
112
|
+
`UIProviderFactory.register()` only understands `'swagger'`/`'scalar'`. Register a custom provider directly on the factory before `ApiReferenceComponent.binding()` runs:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
UIProviderFactory.getInstance().set('my-ui', new MyCustomUIProvider());
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Reference
|
|
119
|
+
|
|
120
|
+
### Options
|
|
123
121
|
```typescript
|
|
124
122
|
export interface IApiReferenceOptions {
|
|
125
|
-
restOptions
|
|
126
|
-
base
|
|
127
|
-
doc
|
|
128
|
-
ui
|
|
123
|
+
restOptions?: {
|
|
124
|
+
base?: { path?: string };
|
|
125
|
+
doc?: { path?: string };
|
|
126
|
+
ui?: { path?: string; type?: TDocumentUIType };
|
|
129
127
|
};
|
|
130
|
-
explorer
|
|
131
|
-
openapi
|
|
128
|
+
explorer?: {
|
|
129
|
+
openapi?: string;
|
|
132
130
|
info?: {
|
|
133
131
|
title: string;
|
|
134
132
|
version: string;
|
|
135
133
|
description: string;
|
|
136
134
|
contact?: { name: string; email: string };
|
|
137
135
|
};
|
|
138
|
-
servers?: Array<{
|
|
139
|
-
url: string;
|
|
140
|
-
description?: string;
|
|
141
|
-
}>;
|
|
136
|
+
servers?: Array<{ url: string; description?: string }>;
|
|
142
137
|
};
|
|
143
138
|
uiConfig?: Record<string, any>;
|
|
144
139
|
}
|
|
@@ -151,194 +146,18 @@ export interface IApiReferenceOptions {
|
|
|
151
146
|
| `restOptions.ui.path` | `string` | `'/explorer'` | Path to the documentation UI (relative to base) |
|
|
152
147
|
| `restOptions.ui.type` | `'swagger' \| 'scalar'` | `'scalar'` | UI provider type |
|
|
153
148
|
| `explorer.openapi` | `string` | `'3.0.0'` | OpenAPI specification version |
|
|
154
|
-
| `explorer.info.title`
|
|
155
|
-
| `explorer.info.version` | `string` | Always from `package.json` `version` | API version (overwritten at runtime) |
|
|
156
|
-
| `explorer.info.description` | `string` | Always from `package.json` `description` | API description (overwritten at runtime) |
|
|
157
|
-
| `explorer.info.contact` | `{ name, email }` | Always from `package.json` `author` | Contact information (overwritten at runtime) |
|
|
149
|
+
| `explorer.info.title` / `.version` / `.description` / `.contact` | - | Always sourced from `package.json` | Overwritten at runtime - binding values are discarded |
|
|
158
150
|
| `explorer.servers` | `Array<{ url, description? }>` | Auto-detected when empty | Server URLs |
|
|
159
|
-
| `uiConfig` | `Record<string, any>` | `undefined` | Custom config passed to the UI provider |
|
|
160
|
-
|
|
161
|
-
#### IGetProviderParams Interface
|
|
162
|
-
|
|
163
|
-
The `IGetProviderParams` interface is used by `UIProviderFactory.getProvider()` and `UIProviderFactory.register()`:
|
|
164
|
-
|
|
165
|
-
```typescript
|
|
166
|
-
export interface IGetProviderParams {
|
|
167
|
-
type: string;
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
This interface is exported for use when building custom tooling around the `UIProviderFactory` -- for example, programmatically querying which providers are available or registering providers in tests.
|
|
172
|
-
|
|
173
|
-
### Tech Stack
|
|
174
|
-
|
|
175
|
-
| Library | Purpose |
|
|
176
|
-
|---------|---------|
|
|
177
|
-
| `@hono/zod-openapi` | OpenAPI generation from Zod schemas |
|
|
178
|
-
| `@hono/swagger-ui` | Swagger UI rendering |
|
|
179
|
-
| `@scalar/hono-api-reference` | Scalar UI rendering |
|
|
180
|
-
| `zod` | Schema validation and type generation |
|
|
181
|
-
|
|
182
|
-
> [!TIP]
|
|
183
|
-
> The component also auto-registers JWT (`bearer`) and Basic security schemes in the OpenAPI spec, so authenticated endpoints display the correct auth UI in the documentation.
|
|
184
|
-
|
|
185
|
-
## Architecture
|
|
186
|
-
|
|
187
|
-
### Component Lifecycle
|
|
188
|
-
|
|
189
|
-
The `ApiReferenceComponent` executes the following during `binding()`:
|
|
190
|
-
|
|
191
|
-
1. **Resolve options** -- reads `ApiReferenceBindingKeys.API_REFERENCE_OPTIONS` from DI using `application.get()` with `isOptional: true`, then deep-merges what it finds over `DEFAULT_API_REFERENCE_OPTIONS` group by group, so an application that overrides one path keeps the defaults for the rest
|
|
192
|
-
2. **Overwrite info** -- unconditionally reads `package.json` via `application.getAppInfo()` and overwrites `explorer.info` with `{ title: appInfo.name, version: appInfo.version, description: appInfo.description, contact: appInfo.author }`
|
|
193
|
-
3. **Auto-detect servers** -- if `explorer.servers` is empty or unset, creates one entry from `http://` + `application.getServerAddress()` + `configs.path.base`
|
|
194
|
-
4. **Normalize paths** -- all path segments (`base.path`, `doc.path`, `ui.path`) are normalized to ensure a leading `/` is present, handling both `/path` and `path` inputs
|
|
195
|
-
5. **Register OpenAPI doc route** -- calls `rootRouter.doc(docPath, explorer)` to register the raw JSON endpoint
|
|
196
|
-
6. **Resolve UI type with fallback** -- evaluates `restOptions.ui.type || DocumentUITypes.SWAGGER`. Note: this means a falsy value (empty string) falls back to `'swagger'`, not `'scalar'`
|
|
197
|
-
7. **Validate UI type** -- checks the resolved type against `DocumentUITypes.SCHEME_SET`, throws if invalid
|
|
198
|
-
8. **Register UI provider** -- calls `UIProviderFactory.register({ type })` to instantiate the UI renderer
|
|
199
|
-
9. **Construct docUrl** -- builds the full documentation URL by joining `configs.path.base`, `configs.basePath`, and the computed `docPath`
|
|
200
|
-
10. **Register UI route** -- creates `GET` handler at `uiPath` that calls `uiProvider.render()` with `{ title: appInfo.name, url: docUrl, ...uiConfig }`
|
|
201
|
-
11. **Register security schemes** -- auto-registers JWT (bearer) and Basic security schemes in the OpenAPI registry
|
|
202
|
-
|
|
203
|
-
### Architecture Components
|
|
204
|
-
|
|
205
|
-
| Component | Class | Role |
|
|
206
|
-
|-----------|-------|------|
|
|
207
|
-
| **ApiReferenceComponent** | `extends BaseComponent` | Orchestrates binding, overwrites OpenAPI metadata from `package.json` |
|
|
208
|
-
| **UIProviderFactory** | `extends MemoryStorageHelper` (singleton) | Registry for UI providers, validates and instantiates |
|
|
209
|
-
| **SwaggerUIProvider** | `implements IUIProvider` | Renders Swagger UI via `@hono/swagger-ui` |
|
|
210
|
-
| **ScalarUIProvider** | `implements IUIProvider` | Renders Scalar UI via `@scalar/hono-api-reference` |
|
|
211
|
-
|
|
212
|
-
#### UIProviderFactory and MemoryStorageHelper
|
|
213
|
-
|
|
214
|
-
`UIProviderFactory` extends `MemoryStorageHelper<{ [key: string | symbol]: IUIProvider }>`, which provides a simple in-memory key-value store with the following methods used internally:
|
|
215
|
-
|
|
216
|
-
- `isBound(key)` -- checks if a provider type is already registered
|
|
217
|
-
- `get(key)` -- retrieves a registered provider instance
|
|
218
|
-
- `set(key, value)` -- stores a provider instance
|
|
219
|
-
- `keys()` -- lists all registered provider type keys
|
|
220
|
-
|
|
221
|
-
This gives the factory a lightweight, type-safe storage backend without requiring the full DI container.
|
|
222
|
-
|
|
223
|
-
#### Lazy Dynamic Imports
|
|
224
|
-
|
|
225
|
-
Both `SwaggerUIProvider` and `ScalarUIProvider` use `await import()` inside their `render()` method to load the underlying UI library:
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
// SwaggerUIProvider
|
|
229
|
-
async render(context, config, next) {
|
|
230
|
-
const { swaggerUI } = await import('@hono/swagger-ui');
|
|
231
|
-
// ...
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// ScalarUIProvider
|
|
235
|
-
async render(context, config, next) {
|
|
236
|
-
const { Scalar } = await import('@scalar/hono-api-reference');
|
|
237
|
-
// ...
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
This means UI libraries are loaded on the **first HTTP request** to the documentation endpoint, not at application startup. This keeps startup time fast and avoids loading unused UI libraries (only the configured provider's library is ever imported).
|
|
242
|
-
|
|
243
|
-
#### ScalarUIProvider Title Mapping
|
|
244
|
-
|
|
245
|
-
The `ScalarUIProvider` maps the `title` field to `pageTitle` when calling the Scalar renderer:
|
|
246
|
-
|
|
247
|
-
```typescript
|
|
248
|
-
const { title, url, ...customConfig } = config;
|
|
249
|
-
return Scalar({ url, pageTitle: title, ...customConfig })(context, next);
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
This is a quirk to be aware of if you are inspecting the rendered output or writing custom UI providers -- Scalar uses `pageTitle` instead of `title`.
|
|
253
|
-
|
|
254
|
-
### UIProviderFactory API
|
|
255
|
-
|
|
256
|
-
| Method | Signature | Description |
|
|
257
|
-
|--------|-----------|-------------|
|
|
258
|
-
| `getInstance()` | `static () => UIProviderFactory` | Returns singleton instance |
|
|
259
|
-
| `register()` | `(opts: { type: string }) => void` | Instantiates and registers a UI provider (idempotent) |
|
|
260
|
-
| `getProvider()` | `(opts: IGetProviderParams) => IUIProvider` | Returns registered provider or throws |
|
|
261
|
-
| `getRegisteredProviders()` | `() => string[]` | Lists all registered provider type keys |
|
|
262
|
-
|
|
263
|
-
#### register() Idempotency
|
|
264
|
-
|
|
265
|
-
The `register()` method is idempotent. If a provider of the given type is already registered, it logs a warning and returns without error:
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
register(opts: { type: string }): void {
|
|
269
|
-
if (this.isBound(opts.type)) {
|
|
270
|
-
this.logger
|
|
271
|
-
.for(this.register.name)
|
|
272
|
-
.warn('Skip registering BOUNDED Document UI | type: %s', opts.type);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
// ... instantiate and store the provider
|
|
276
|
-
}
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
This means calling `register({ type: 'scalar' })` multiple times is safe and will not create duplicate provider instances.
|
|
280
|
-
|
|
281
|
-
### IUIProvider Interface
|
|
282
|
-
|
|
283
|
-
```typescript
|
|
284
|
-
interface IUIProvider {
|
|
285
|
-
render(context: Context, config: IUIConfig, next: Next): Promise<Response | void>;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
interface IUIConfig {
|
|
289
|
-
title: string; // App name from package.json
|
|
290
|
-
url: string; // Full URL to OpenAPI JSON endpoint
|
|
291
|
-
[key: string]: any; // Additional config from uiConfig option
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Security Scheme Registration
|
|
296
|
-
|
|
297
|
-
The component auto-registers two OpenAPI security schemes:
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
// JWT Bearer
|
|
301
|
-
rootRouter.openAPIRegistry.registerComponent('securitySchemes', 'jwt', {
|
|
302
|
-
type: 'http',
|
|
303
|
-
scheme: 'bearer',
|
|
304
|
-
bearerFormat: 'JWT',
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
// Basic Auth
|
|
308
|
-
rootRouter.openAPIRegistry.registerComponent('securitySchemes', 'basic', {
|
|
309
|
-
type: 'http',
|
|
310
|
-
scheme: 'basic',
|
|
311
|
-
});
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
This ensures routes using `authStrategies: ['jwt']` or `authStrategies: ['basic']` display the correct auth UI (lock icon + input fields) in the documentation.
|
|
315
|
-
|
|
316
|
-
## Binding Keys
|
|
151
|
+
| `uiConfig` | `Record<string, any>` | `undefined` | Custom config passed through to the UI provider |
|
|
317
152
|
|
|
153
|
+
### Binding keys
|
|
318
154
|
| Key | Constant | Type | Required | Default |
|
|
319
155
|
|-----|----------|------|----------|---------|
|
|
320
|
-
| `@app/api-reference/options` | `ApiReferenceBindingKeys.API_REFERENCE_OPTIONS` | `IApiReferenceOptions` | No | See
|
|
321
|
-
|
|
322
|
-
The deprecated `SwaggerBindingKeys.SWAGGER_OPTIONS` still resolves - it is an alias whose **value** is that same `'@app/api-reference/options'` string. There is no binding under the literal `'@app/swagger/options'`; binding that raw string does nothing.
|
|
156
|
+
| `@app/api-reference/options` | `ApiReferenceBindingKeys.API_REFERENCE_OPTIONS` | `IApiReferenceOptions` | No | See Options table |
|
|
323
157
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
```typescript
|
|
327
|
-
super({
|
|
328
|
-
scope: ApiReferenceComponent.name,
|
|
329
|
-
initDefault: { enable: true, container: application },
|
|
330
|
-
bindings: {
|
|
331
|
-
[ApiReferenceBindingKeys.API_REFERENCE_OPTIONS]: Binding.bind<IApiReferenceOptions>({
|
|
332
|
-
key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
|
|
333
|
-
}).toValue(DEFAULT_API_REFERENCE_OPTIONS),
|
|
334
|
-
},
|
|
335
|
-
});
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
`binding()` then reads the key back with `isOptional: true` and **deep-merges** whatever the application bound over the defaults, group by group (`base`, `doc`, `ui`, `explorer`) - so overriding one path does not wipe the others. The merge builds a fresh `explorer` object per application; mutating the bound one would leak this application's info into every later application in the same process.
|
|
158
|
+
`SwaggerBindingKeys.SWAGGER_OPTIONS` is removed. It was only ever an alias for the key above - there was never a separate binding under the literal `'@app/swagger/options'`, so nothing needs rebinding.
|
|
339
159
|
|
|
340
160
|
**Default value:**
|
|
341
|
-
|
|
342
161
|
```typescript
|
|
343
162
|
const DEFAULT_API_REFERENCE_OPTIONS: IApiReferenceOptions = {
|
|
344
163
|
restOptions: {
|
|
@@ -358,10 +177,27 @@ const DEFAULT_API_REFERENCE_OPTIONS: IApiReferenceOptions = {
|
|
|
358
177
|
```
|
|
359
178
|
|
|
360
179
|
> [!NOTE]
|
|
361
|
-
> The `explorer.info` values
|
|
180
|
+
> The `explorer.info` values above are never used at runtime - `binding()` unconditionally overwrites `explorer.info` from `package.json`. They exist only as structural defaults.
|
|
362
181
|
|
|
363
|
-
###
|
|
182
|
+
### API endpoints
|
|
183
|
+
| Method | Path (default, relative to app base) | Description |
|
|
184
|
+
|--------|-----------------|-------------|
|
|
185
|
+
| `GET` | `/doc/explorer` | Documentation UI (Scalar by default) |
|
|
186
|
+
| `GET` | `/doc/openapi.json` | Raw OpenAPI specification |
|
|
364
187
|
|
|
188
|
+
These paths are mounted under your application's own base path - `path.base` in `IApplicationConfigs`. With the `/api` base path from the getting-started guide, that's `GET /api/doc/explorer`. They also shift with `restOptions.base.path`, `restOptions.ui.path`, and `restOptions.doc.path`.
|
|
189
|
+
|
|
190
|
+
### UIProviderFactory
|
|
191
|
+
| Method | Signature | Description |
|
|
192
|
+
|--------|-----------|-------------|
|
|
193
|
+
| `getInstance()` | `static () => UIProviderFactory` | Returns the singleton instance |
|
|
194
|
+
| `register()` | `(opts: { type: string }) => void` | Instantiates and registers a built-in provider; idempotent - warns and returns if the type is already bound |
|
|
195
|
+
| `getProvider()` | `(opts: IGetProviderParams) => IUIProvider` | Returns the registered provider or throws `Unknown UI Provider` |
|
|
196
|
+
| `getRegisteredProviders()` | `() => string[]` | Lists all registered provider type keys |
|
|
197
|
+
|
|
198
|
+
Extends `MemoryStorageHelper<{ [key: string | symbol]: IUIProvider }>`, using `isBound()` / `get()` / `set()` / `keys()` for lightweight, type-safe storage without the full DI container.
|
|
199
|
+
|
|
200
|
+
### Type definitions
|
|
365
201
|
```typescript
|
|
366
202
|
type TDocumentUIType = TConstValue<typeof DocumentUITypes>;
|
|
367
203
|
|
|
@@ -373,96 +209,38 @@ class DocumentUITypes {
|
|
|
373
209
|
}
|
|
374
210
|
```
|
|
375
211
|
|
|
376
|
-
`TDocumentUIType` is derived via `TConstValue`, which extracts the union of
|
|
212
|
+
`TDocumentUIType` is derived via `TConstValue`, which extracts the union of every `static readonly` string on `DocumentUITypes`. The type stays in sync with the constants automatically.
|
|
377
213
|
|
|
378
|
-
|
|
214
|
+
### Component lifecycle (`binding()`)
|
|
215
|
+
1. **Resolve options** - reads `ApiReferenceBindingKeys.API_REFERENCE_OPTIONS` with `isOptional: true`, then merges `base`/`doc`/`ui` each against `DEFAULT_API_REFERENCE_OPTIONS`
|
|
216
|
+
2. **Overwrite info** - reads `package.json` via `application.getAppInfo()` and replaces `explorer.info`
|
|
217
|
+
3. **Auto-detect servers** - builds one entry from `application.getServerAddress()` when `explorer.servers` is empty
|
|
218
|
+
4. **Normalize paths** - ensures every path segment (`base.path`, `doc.path`, `ui.path`) has a leading `/`
|
|
219
|
+
5. **Register the OpenAPI doc route** - `rootRouter.doc(docPath, explorer)`
|
|
220
|
+
6. **Resolve `uiType`** - `restOptions.ui.type ?? DocumentUITypes.SWAGGER`
|
|
221
|
+
7. **Validate and register the UI provider** - via `UIProviderFactory`, unless a provider with that type is already bound
|
|
222
|
+
8. **Register the UI route** - `GET` handler at `uiPath` calling `uiProvider.render()`
|
|
223
|
+
9. **Register JWT and Basic security schemes** on the OpenAPI registry
|
|
379
224
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
### Documentation UI Endpoint
|
|
389
|
-
|
|
390
|
-
**Default path:** `/doc/explorer`
|
|
391
|
-
|
|
392
|
-
Renders an interactive API documentation page using the configured UI provider (Scalar or Swagger UI). The UI fetches the OpenAPI spec from the JSON endpoint and renders it with full request/response exploration, authentication controls, and try-it-out functionality.
|
|
393
|
-
|
|
394
|
-
### OpenAPI JSON Endpoint
|
|
395
|
-
|
|
396
|
-
**Default path:** `/doc/openapi.json`
|
|
397
|
-
|
|
398
|
-
Returns the raw OpenAPI JSON specification generated from all registered controller routes and their Zod schemas. This endpoint can be used by:
|
|
399
|
-
- External API testing tools (Postman, Insomnia)
|
|
400
|
-
- CI pipelines for API contract validation
|
|
401
|
-
- Client SDK generators (openapi-generator, orval)
|
|
402
|
-
- API gateway configuration
|
|
225
|
+
### Tech stack
|
|
226
|
+
| Library | Purpose |
|
|
227
|
+
|---------|---------|
|
|
228
|
+
| `@hono/zod-openapi` | OpenAPI generation from Zod schemas |
|
|
229
|
+
| `@hono/swagger-ui` | Swagger UI rendering |
|
|
230
|
+
| `@scalar/hono-api-reference` | Scalar UI rendering |
|
|
231
|
+
| `zod` | Schema validation and type generation |
|
|
403
232
|
|
|
404
233
|
## Troubleshooting
|
|
405
234
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
this.bind<IApiReferenceOptions>({
|
|
414
|
-
key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
|
|
415
|
-
}).toValue({
|
|
416
|
-
restOptions: {
|
|
417
|
-
base: { path: '/doc' },
|
|
418
|
-
doc: { path: '/openapi.json' },
|
|
419
|
-
ui: { path: '/explorer', type: 'scalar' }, // 'scalar' or 'swagger'
|
|
420
|
-
},
|
|
421
|
-
explorer: { openapi: '3.0.0' },
|
|
422
|
-
});
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
### Documentation UI shows no routes
|
|
426
|
-
|
|
427
|
-
**Cause:** Controllers are not defining routes with Zod schemas via `defineRoute` or `bindRoute`. Only routes registered through `@hono/zod-openapi` appear in the OpenAPI spec.
|
|
428
|
-
|
|
429
|
-
**Fix:** Use `defineRoute` with Zod response schemas in your controllers:
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
this.defineRoute({
|
|
433
|
-
configs: {
|
|
434
|
-
path: '/',
|
|
435
|
-
method: 'get',
|
|
436
|
-
responses: {
|
|
437
|
-
200: jsonContent({
|
|
438
|
-
description: 'Success',
|
|
439
|
-
schema: z.object({ message: z.string() }),
|
|
440
|
-
}),
|
|
441
|
-
},
|
|
442
|
-
},
|
|
443
|
-
handler: (c) => c.json({ message: 'ok' }, 200),
|
|
444
|
-
});
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
### "Unknown UI Provider"
|
|
235
|
+
| Symptom | Cause | Fix |
|
|
236
|
+
|---------|-------|-----|
|
|
237
|
+
| `Invalid document UI Type` | `restOptions.ui.type` is not `'swagger'` or `'scalar'` - an explicit empty string is NOT repaired by the `??` fallback | Use `'scalar'` or `'swagger'` explicitly |
|
|
238
|
+
| Documentation UI shows no routes | Controllers aren't defining routes with Zod schemas via `defineRoute`, `bindRoute`, or `@api()` | Add Zod response schemas to your route configs |
|
|
239
|
+
| `Unknown UI Provider` | `UIProviderFactory.getProvider()` was called with a type that was never registered - usually a failed `binding()` | Ensure `ApiReferenceComponent` is registered in `preConfigure()`; check logs for warnings during binding |
|
|
240
|
+
| OpenAPI spec missing authentication schemes | `AuthenticationComponent` isn't registered, so auth strategies aren't available when schemes are added | Register `AuthenticationComponent` before `ApiReferenceComponent` in `preConfigure()` |
|
|
241
|
+
| `explorer.info` doesn't match my binding | `explorer.info` is always overwritten from `package.json` during `binding()` | Update `package.json` fields (`name`, `version`, `description`, `author`) instead |
|
|
448
242
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
**Fix:** Ensure the `ApiReferenceComponent` is registered in `preConfigure()` and that no errors occur during its `binding()` phase. Check the application logs for warnings from `UIProviderFactory`.
|
|
452
|
-
|
|
453
|
-
### OpenAPI spec missing authentication schemes
|
|
454
|
-
|
|
455
|
-
**Cause:** The `ApiReferenceComponent` auto-registers JWT and Basic security schemes. If the `AuthenticationComponent` is not registered, authenticated routes will not show auth UI in the documentation.
|
|
456
|
-
|
|
457
|
-
**Fix:** Register `AuthenticationComponent` before `ApiReferenceComponent` in `preConfigure()` to ensure auth strategies are available when the Swagger component configures security schemes.
|
|
458
|
-
|
|
459
|
-
### explorer.info values not matching custom configuration
|
|
460
|
-
|
|
461
|
-
**Cause:** The `ApiReferenceComponent` unconditionally overwrites `explorer.info` with values from `package.json` during its `binding()` phase. Any values you set in `explorer.info` via the DI binding are discarded.
|
|
462
|
-
|
|
463
|
-
**Fix:** Update your project's `package.json` fields (`name`, `version`, `description`, `author`) to control what appears in the API documentation info section. The component reads these via `application.getAppInfo()`.
|
|
464
|
-
|
|
465
|
-
## See Also
|
|
243
|
+
## See also
|
|
466
244
|
|
|
467
245
|
- **Guides:**
|
|
468
246
|
- [Components Overview](/guides/core-concepts/components) - Component system basics
|
|
@@ -480,3 +258,11 @@ this.defineRoute({
|
|
|
480
258
|
- [OpenAPI Specification](https://swagger.io/specification/) - OpenAPI standard
|
|
481
259
|
- [Scalar Documentation](https://github.com/scalar/scalar) - Scalar API documentation UI
|
|
482
260
|
- [@hono/zod-openapi](https://github.com/honojs/middleware/tree/main/packages/zod-openapi) - Hono OpenAPI integration
|
|
261
|
+
|
|
262
|
+
**Files:**
|
|
263
|
+
|
|
264
|
+
- [`packages/core-server/src/components/api-reference/component.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/api-reference/component.ts) - `ApiReferenceComponent`
|
|
265
|
+
- [`packages/core-server/src/components/api-reference/ui-factory.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/api-reference/ui-factory.ts) - `UIProviderFactory`, `SwaggerUIProvider`, `ScalarUIProvider`
|
|
266
|
+
- [`packages/core-server/src/components/api-reference/common/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/api-reference/common/types.ts) - `IApiReferenceOptions`, `IUIProvider`, `IUIConfig`
|
|
267
|
+
- [`packages/core-server/src/components/api-reference/common/keys.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/api-reference/common/keys.ts) - `ApiReferenceBindingKeys`
|
|
268
|
+
- [`packages/core-server/src/components/api-reference/common/constants.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/api-reference/common/constants.ts) - `DocumentUITypes`
|