@navios/openapi-bun 0.7.0
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/CHANGELOG.md +33 -0
- package/LICENSE +8 -0
- package/README.md +286 -0
- package/dist/src/controllers/index.d.mts +4 -0
- package/dist/src/controllers/index.d.mts.map +1 -0
- package/dist/src/controllers/openapi-json.controller.d.mts +10 -0
- package/dist/src/controllers/openapi-json.controller.d.mts.map +1 -0
- package/dist/src/controllers/openapi-ui.controller.d.mts +10 -0
- package/dist/src/controllers/openapi-ui.controller.d.mts.map +1 -0
- package/dist/src/controllers/openapi-yaml.controller.d.mts +10 -0
- package/dist/src/controllers/openapi-yaml.controller.d.mts.map +1 -0
- package/dist/src/index.d.mts +8 -0
- package/dist/src/index.d.mts.map +1 -0
- package/dist/src/openapi-bun.plugin.d.mts +68 -0
- package/dist/src/openapi-bun.plugin.d.mts.map +1 -0
- package/dist/src/schemas/index.d.mts +2 -0
- package/dist/src/schemas/index.d.mts.map +1 -0
- package/dist/src/schemas/openapi-bun-options.schema.d.mts +114 -0
- package/dist/src/schemas/openapi-bun-options.schema.d.mts.map +1 -0
- package/dist/src/services/index.d.mts +2 -0
- package/dist/src/services/index.d.mts.map +1 -0
- package/dist/src/services/openapi-document.service.d.mts +38 -0
- package/dist/src/services/openapi-document.service.d.mts.map +1 -0
- package/dist/src/tokens/index.d.mts +2 -0
- package/dist/src/tokens/index.d.mts.map +1 -0
- package/dist/src/tokens/openapi-options.token.d.mts +25 -0
- package/dist/src/tokens/openapi-options.token.d.mts.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/tsdown.config.d.mts +3 -0
- package/dist/tsdown.config.d.mts.map +1 -0
- package/dist/vitest.config.d.mts +3 -0
- package/dist/vitest.config.d.mts.map +1 -0
- package/lib/index.cjs +4326 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +262 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +262 -0
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +4311 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +48 -0
- package/project.json +66 -0
- package/src/controllers/index.mts +3 -0
- package/src/controllers/openapi-json.controller.mts +51 -0
- package/src/controllers/openapi-ui.controller.mts +72 -0
- package/src/controllers/openapi-yaml.controller.mts +46 -0
- package/src/index.mts +30 -0
- package/src/openapi-bun.plugin.mts +167 -0
- package/src/schemas/index.mts +10 -0
- package/src/schemas/openapi-bun-options.schema.mts +135 -0
- package/src/services/index.mts +4 -0
- package/src/services/openapi-document.service.mts +83 -0
- package/src/tokens/index.mts +1 -0
- package/src/tokens/openapi-options.token.mts +31 -0
- package/tsconfig.json +15 -0
- package/tsconfig.lib.json +8 -0
- package/tsconfig.spec.json +8 -0
- package/tsdown.config.mts +41 -0
- package/vitest.config.mts +11 -0
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@navios/openapi-bun",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "Oleksandr Hanzha",
|
|
6
|
+
"email": "alex@granted.name"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"directory": "packages/openapi-bun",
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/Arilas/navios.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"@navios/adapter-bun": "^0.7.1",
|
|
16
|
+
"@navios/builder": "^0.5.1",
|
|
17
|
+
"@navios/core": "^0.7.1",
|
|
18
|
+
"@navios/openapi": "^0.7.0",
|
|
19
|
+
"zod": "^3.25.0 || ^4.0.0"
|
|
20
|
+
},
|
|
21
|
+
"typings": "./lib/index.d.mts",
|
|
22
|
+
"main": "./lib/index.cjs",
|
|
23
|
+
"module": "./lib/index.mjs",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./lib/index.d.mts",
|
|
28
|
+
"default": "./lib/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./lib/index.d.cts",
|
|
32
|
+
"default": "./lib/index.cjs"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@navios/adapter-bun": "^0.7.1",
|
|
38
|
+
"@navios/builder": "^0.5.1",
|
|
39
|
+
"@navios/core": "^0.7.1",
|
|
40
|
+
"@navios/openapi": "^0.7.0",
|
|
41
|
+
"typescript": "^5.9.3",
|
|
42
|
+
"zod": "^4.2.1"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@scalar/core": "^0.3.28",
|
|
46
|
+
"yaml": "^2.8.2"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@navios/openapi-bun",
|
|
3
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "packages/openapi-bun/src",
|
|
5
|
+
"prefix": "openapi-bun",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"projectType": "library",
|
|
8
|
+
"targets": {
|
|
9
|
+
"check": {
|
|
10
|
+
"executor": "nx:run-commands",
|
|
11
|
+
"outputs": ["{projectRoot}/dist"],
|
|
12
|
+
"inputs": [
|
|
13
|
+
"^projectSources",
|
|
14
|
+
"projectSources",
|
|
15
|
+
"{projectRoot}/tsconfig.json",
|
|
16
|
+
"{projectRoot}/tsconfig.lib.json"
|
|
17
|
+
],
|
|
18
|
+
"options": {
|
|
19
|
+
"command": ["tsc -b"],
|
|
20
|
+
"cwd": "packages/openapi-bun"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"lint": {
|
|
24
|
+
"executor": "nx:run-commands",
|
|
25
|
+
"inputs": ["^projectSources", "project"],
|
|
26
|
+
"options": {
|
|
27
|
+
"command": "oxlint --fix",
|
|
28
|
+
"cwd": "packages/openapi-bun"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"test:ci": {
|
|
32
|
+
"executor": "nx:run-commands",
|
|
33
|
+
"inputs": ["^projectSources", "project"],
|
|
34
|
+
"options": {
|
|
35
|
+
"command": "vitest run",
|
|
36
|
+
"cwd": "packages/openapi-bun"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"build": {
|
|
40
|
+
"executor": "nx:run-commands",
|
|
41
|
+
"inputs": ["projectSources", "{projectRoot}/tsdown.config.mts"],
|
|
42
|
+
"outputs": ["{projectRoot}/lib"],
|
|
43
|
+
"dependsOn": ["check", "lint"],
|
|
44
|
+
"options": {
|
|
45
|
+
"command": "tsdown",
|
|
46
|
+
"cwd": "packages/openapi-bun"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"publish": {
|
|
50
|
+
"executor": "nx:run-commands",
|
|
51
|
+
"dependsOn": ["build"],
|
|
52
|
+
"options": {
|
|
53
|
+
"command": "yarn npm publish --access public",
|
|
54
|
+
"cwd": "packages/openapi-bun"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"publish:next": {
|
|
58
|
+
"executor": "nx:run-commands",
|
|
59
|
+
"dependsOn": ["build"],
|
|
60
|
+
"options": {
|
|
61
|
+
"command": "yarn npm publish --access public --tag next",
|
|
62
|
+
"cwd": "packages/openapi-bun"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { EndpointParams, EndpointResult } from '@navios/core'
|
|
2
|
+
import type { ClassType } from '@navios/di'
|
|
3
|
+
|
|
4
|
+
import { builder } from '@navios/builder'
|
|
5
|
+
import { Controller, Endpoint, inject } from '@navios/core'
|
|
6
|
+
import { ApiExclude } from '@navios/openapi'
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod'
|
|
9
|
+
|
|
10
|
+
import { OpenApiDocumentServiceToken } from '../services/openapi-document.service.mjs'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Schema for OpenAPI document response.
|
|
14
|
+
* Uses z.record(z.unknown()) since OpenAPI documents have complex structure.
|
|
15
|
+
*/
|
|
16
|
+
const openApiDocumentSchema = z.record(z.string(), z.unknown())
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates a customized JSON controller with the correct path.
|
|
20
|
+
* Called by the plugin to create a controller with the configured jsonPath.
|
|
21
|
+
*
|
|
22
|
+
* @param jsonPath - The path to serve the OpenAPI JSON (e.g., '/openapi.json')
|
|
23
|
+
* @returns A controller class that serves the OpenAPI document as JSON
|
|
24
|
+
*/
|
|
25
|
+
export function createOpenApiJsonController(jsonPath: string): ClassType {
|
|
26
|
+
const API = builder()
|
|
27
|
+
|
|
28
|
+
const endpoint = API.declareEndpoint({
|
|
29
|
+
method: 'GET',
|
|
30
|
+
url: jsonPath,
|
|
31
|
+
responseSchema: openApiDocumentSchema,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
@ApiExclude()
|
|
35
|
+
@Controller()
|
|
36
|
+
class OpenApiJsonController {
|
|
37
|
+
private documentService = inject(OpenApiDocumentServiceToken)
|
|
38
|
+
|
|
39
|
+
@Endpoint(endpoint)
|
|
40
|
+
async getJson(
|
|
41
|
+
_params: EndpointParams<typeof endpoint>,
|
|
42
|
+
): EndpointResult<typeof endpoint> {
|
|
43
|
+
return this.documentService.getDocument() as unknown as Record<
|
|
44
|
+
string,
|
|
45
|
+
unknown
|
|
46
|
+
>
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return OpenApiJsonController
|
|
51
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { StreamParams } from '@navios/core'
|
|
2
|
+
import type { ClassType } from '@navios/di'
|
|
3
|
+
|
|
4
|
+
import { builder } from '@navios/builder'
|
|
5
|
+
import { Controller, inject, Stream } from '@navios/core'
|
|
6
|
+
import { ApiExclude, ApiStream } from '@navios/openapi'
|
|
7
|
+
|
|
8
|
+
import { getHtmlDocument } from '@scalar/core/libs/html-rendering'
|
|
9
|
+
|
|
10
|
+
import type { ScalarOptions } from '../schemas/index.mjs'
|
|
11
|
+
|
|
12
|
+
import { OpenApiOptionsToken } from '../tokens/openapi-options.token.mjs'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a customized Scalar UI controller with the correct path.
|
|
16
|
+
*
|
|
17
|
+
* @param docsPath - The path to serve the Scalar UI (e.g., '/docs')
|
|
18
|
+
* @param jsonPath - The path to the OpenAPI JSON spec (used by Scalar to load the spec)
|
|
19
|
+
* @returns A controller class that serves the Scalar API Reference UI
|
|
20
|
+
*/
|
|
21
|
+
export function createOpenApiUiController(
|
|
22
|
+
docsPath: string,
|
|
23
|
+
jsonPath: string,
|
|
24
|
+
): ClassType {
|
|
25
|
+
const API = builder()
|
|
26
|
+
|
|
27
|
+
const endpoint = API.declareStream({
|
|
28
|
+
method: 'GET',
|
|
29
|
+
url: docsPath,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
@ApiExclude()
|
|
33
|
+
@Controller()
|
|
34
|
+
class OpenApiUiController {
|
|
35
|
+
private options = inject(OpenApiOptionsToken)
|
|
36
|
+
private html: string | null = null
|
|
37
|
+
|
|
38
|
+
// @ts-expect-error - Stream decorator is not typed correctly
|
|
39
|
+
@Stream(endpoint)
|
|
40
|
+
@ApiStream({ contentType: 'text/html' })
|
|
41
|
+
async getUi(_params: StreamParams<typeof endpoint>) {
|
|
42
|
+
// Generate HTML on first request (lazy initialization)
|
|
43
|
+
if (!this.html) {
|
|
44
|
+
this.html = this.generateHtml()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return new Response(this.html, {
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private generateHtml(): string {
|
|
55
|
+
const scalarOptions: ScalarOptions = this.options.scalar ?? {}
|
|
56
|
+
|
|
57
|
+
return getHtmlDocument({
|
|
58
|
+
url: jsonPath,
|
|
59
|
+
theme: scalarOptions.theme ?? 'default',
|
|
60
|
+
favicon: scalarOptions.favicon,
|
|
61
|
+
customCss: scalarOptions.customCss,
|
|
62
|
+
hideDownloadButton: scalarOptions.hideDownloadButton,
|
|
63
|
+
hideSearch: scalarOptions.hideSearch,
|
|
64
|
+
metaData: scalarOptions.metaData,
|
|
65
|
+
cdn: scalarOptions.cdn,
|
|
66
|
+
pageTitle: scalarOptions.metaData?.title ?? 'API Reference',
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return OpenApiUiController
|
|
72
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { StreamParams } from '@navios/core'
|
|
2
|
+
import type { ClassType } from '@navios/di'
|
|
3
|
+
|
|
4
|
+
import { builder } from '@navios/builder'
|
|
5
|
+
import { Controller, inject, Stream } from '@navios/core'
|
|
6
|
+
import { ApiExclude, ApiStream } from '@navios/openapi'
|
|
7
|
+
|
|
8
|
+
import { OpenApiDocumentServiceToken } from '../services/openapi-document.service.mjs'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a customized YAML controller with the correct path.
|
|
12
|
+
* Uses Stream endpoint to set content-type header properly.
|
|
13
|
+
*
|
|
14
|
+
* @param yamlPath - The path to serve the OpenAPI YAML (e.g., '/openapi.yaml')
|
|
15
|
+
* @returns A controller class that serves the OpenAPI document as YAML
|
|
16
|
+
*/
|
|
17
|
+
export function createOpenApiYamlController(yamlPath: string): ClassType {
|
|
18
|
+
const API = builder()
|
|
19
|
+
|
|
20
|
+
const endpoint = API.declareStream({
|
|
21
|
+
method: 'GET',
|
|
22
|
+
url: yamlPath,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
@ApiExclude()
|
|
26
|
+
@Controller()
|
|
27
|
+
class OpenApiYamlController {
|
|
28
|
+
private documentService = inject(OpenApiDocumentServiceToken)
|
|
29
|
+
|
|
30
|
+
// @ts-expect-error - Stream decorator is not typed correctly
|
|
31
|
+
@Stream(endpoint)
|
|
32
|
+
@ApiStream({ contentType: 'text/yaml' })
|
|
33
|
+
async getYaml(_params: StreamParams<typeof endpoint>) {
|
|
34
|
+
const yaml = this.documentService.getYamlDocument()
|
|
35
|
+
|
|
36
|
+
// Return a Response with proper content-type
|
|
37
|
+
return new Response(yaml, {
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'text/yaml; charset=utf-8',
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return OpenApiYamlController
|
|
46
|
+
}
|
package/src/index.mts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Plugin
|
|
2
|
+
export {
|
|
3
|
+
OpenApiBunPlugin,
|
|
4
|
+
defineOpenApiPlugin,
|
|
5
|
+
type BunOpenApiPluginOptions,
|
|
6
|
+
type ScalarOptions,
|
|
7
|
+
type ScalarTheme,
|
|
8
|
+
} from './openapi-bun.plugin.mjs'
|
|
9
|
+
|
|
10
|
+
// Schemas (for advanced use cases)
|
|
11
|
+
export {
|
|
12
|
+
bunOpenApiPluginOptionsSchema,
|
|
13
|
+
scalarOptionsSchema,
|
|
14
|
+
scalarThemeSchema,
|
|
15
|
+
type BunOpenApiPluginOptionsBase,
|
|
16
|
+
} from './schemas/index.mjs'
|
|
17
|
+
|
|
18
|
+
// Tokens (for advanced use cases)
|
|
19
|
+
export { OpenApiOptionsToken } from './tokens/index.mjs'
|
|
20
|
+
|
|
21
|
+
// Services (for advanced use cases)
|
|
22
|
+
export {
|
|
23
|
+
OpenApiDocumentService,
|
|
24
|
+
OpenApiDocumentServiceToken,
|
|
25
|
+
} from './services/index.mjs'
|
|
26
|
+
|
|
27
|
+
// Controller factories (for custom setups)
|
|
28
|
+
export { createOpenApiJsonController } from './controllers/openapi-json.controller.mjs'
|
|
29
|
+
export { createOpenApiYamlController } from './controllers/openapi-yaml.controller.mjs'
|
|
30
|
+
export { createOpenApiUiController } from './controllers/openapi-ui.controller.mjs'
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NaviosPlugin,
|
|
3
|
+
PluginContext,
|
|
4
|
+
PluginDefinition,
|
|
5
|
+
} from '@navios/core'
|
|
6
|
+
import type { ClassType } from '@navios/di'
|
|
7
|
+
|
|
8
|
+
import { InjectableScope, InjectableType } from '@navios/di'
|
|
9
|
+
|
|
10
|
+
import type { ScalarOptions, ScalarTheme } from './schemas/index.mjs'
|
|
11
|
+
import type { BunOpenApiPluginOptions } from './tokens/openapi-options.token.mjs'
|
|
12
|
+
|
|
13
|
+
import { createOpenApiJsonController } from './controllers/openapi-json.controller.mjs'
|
|
14
|
+
import { createOpenApiUiController } from './controllers/openapi-ui.controller.mjs'
|
|
15
|
+
import { createOpenApiYamlController } from './controllers/openapi-yaml.controller.mjs'
|
|
16
|
+
import { bunOpenApiPluginOptionsSchema } from './schemas/index.mjs'
|
|
17
|
+
import { OpenApiDocumentService } from './services/openapi-document.service.mjs'
|
|
18
|
+
import { OpenApiOptionsToken } from './tokens/openapi-options.token.mjs'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* OpenAPI plugin for Bun adapter.
|
|
22
|
+
*
|
|
23
|
+
* This plugin:
|
|
24
|
+
* - Scans all registered modules for endpoints
|
|
25
|
+
* - Generates an OpenAPI 3.1 document
|
|
26
|
+
* - Injects controllers for JSON, YAML, and Scalar UI endpoints
|
|
27
|
+
*
|
|
28
|
+
* Unlike the Fastify plugin which registers routes directly,
|
|
29
|
+
* this plugin uses the standard Navios controller pattern via
|
|
30
|
+
* ModuleLoaderService.extendModules().
|
|
31
|
+
*/
|
|
32
|
+
export class OpenApiBunPlugin implements NaviosPlugin<BunOpenApiPluginOptions> {
|
|
33
|
+
readonly name = 'openapi-bun'
|
|
34
|
+
|
|
35
|
+
async register(
|
|
36
|
+
context: PluginContext,
|
|
37
|
+
options: BunOpenApiPluginOptions,
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
// Parse and validate options with defaults
|
|
40
|
+
const parsedOptions = bunOpenApiPluginOptionsSchema.parse(options)
|
|
41
|
+
const fullOptions = { ...options, ...parsedOptions }
|
|
42
|
+
|
|
43
|
+
// Step 1: Register options in DI container
|
|
44
|
+
this.registerOptions(context, fullOptions)
|
|
45
|
+
|
|
46
|
+
// Step 2: Register document service and initialize it
|
|
47
|
+
await this.initializeDocumentService(context, fullOptions)
|
|
48
|
+
|
|
49
|
+
// Step 3: Create and register controllers based on options
|
|
50
|
+
const controllers = this.createControllers(parsedOptions)
|
|
51
|
+
|
|
52
|
+
// Step 4: Extend modules with our controllers
|
|
53
|
+
if (controllers.length > 0) {
|
|
54
|
+
await context.moduleLoader.extendModules([
|
|
55
|
+
{
|
|
56
|
+
controllers,
|
|
57
|
+
moduleName: 'OpenApiBunModule',
|
|
58
|
+
},
|
|
59
|
+
])
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Registers the plugin options in the DI container.
|
|
65
|
+
*/
|
|
66
|
+
private registerOptions(
|
|
67
|
+
context: PluginContext,
|
|
68
|
+
options: BunOpenApiPluginOptions,
|
|
69
|
+
): void {
|
|
70
|
+
const locator = context.container.getServiceLocator()
|
|
71
|
+
const instanceName = locator.getInstanceIdentifier(OpenApiOptionsToken)
|
|
72
|
+
|
|
73
|
+
locator
|
|
74
|
+
.getManager()
|
|
75
|
+
.storeCreatedHolder(
|
|
76
|
+
instanceName,
|
|
77
|
+
options,
|
|
78
|
+
InjectableType.Class,
|
|
79
|
+
InjectableScope.Singleton,
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Registers and initializes the document service.
|
|
85
|
+
*/
|
|
86
|
+
private async initializeDocumentService(
|
|
87
|
+
context: PluginContext,
|
|
88
|
+
_options: BunOpenApiPluginOptions,
|
|
89
|
+
): Promise<void> {
|
|
90
|
+
// Get the document service from container (triggers DI registration)
|
|
91
|
+
const documentService = await context.container.get(OpenApiDocumentService)
|
|
92
|
+
|
|
93
|
+
// Initialize with modules and global prefix
|
|
94
|
+
documentService.initialize(context.modules, context.globalPrefix)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Creates controller classes based on options.
|
|
99
|
+
*/
|
|
100
|
+
private createControllers(
|
|
101
|
+
options: ReturnType<typeof bunOpenApiPluginOptionsSchema.parse>,
|
|
102
|
+
): ClassType[] {
|
|
103
|
+
const controllers: ClassType[] = []
|
|
104
|
+
|
|
105
|
+
if (!options.disableJson) {
|
|
106
|
+
controllers.push(createOpenApiJsonController(options.jsonPath))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!options.disableYaml) {
|
|
110
|
+
controllers.push(createOpenApiYamlController(options.yamlPath))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!options.disableScalar) {
|
|
114
|
+
controllers.push(
|
|
115
|
+
createOpenApiUiController(options.docsPath, options.jsonPath),
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return controllers
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Creates a plugin definition for the OpenAPI Bun plugin.
|
|
125
|
+
*
|
|
126
|
+
* @param options - Plugin configuration options
|
|
127
|
+
* @returns Plugin definition to pass to `app.usePlugin()`
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* import { NaviosFactory } from '@navios/core'
|
|
132
|
+
* import { defineBunEnvironment } from '@navios/adapter-bun'
|
|
133
|
+
* import { defineOpenApiPlugin } from '@navios/openapi-bun'
|
|
134
|
+
*
|
|
135
|
+
* const app = await NaviosFactory.create(AppModule, {
|
|
136
|
+
* adapter: defineBunEnvironment(),
|
|
137
|
+
* })
|
|
138
|
+
*
|
|
139
|
+
* app.usePlugin(defineOpenApiPlugin({
|
|
140
|
+
* info: {
|
|
141
|
+
* title: 'My API',
|
|
142
|
+
* version: '1.0.0',
|
|
143
|
+
* description: 'API documentation',
|
|
144
|
+
* },
|
|
145
|
+
* servers: [
|
|
146
|
+
* { url: 'http://localhost:3000', description: 'Development' },
|
|
147
|
+
* ],
|
|
148
|
+
* scalar: {
|
|
149
|
+
* theme: 'purple',
|
|
150
|
+
* },
|
|
151
|
+
* }))
|
|
152
|
+
*
|
|
153
|
+
* await app.listen({ port: 3000 })
|
|
154
|
+
* // API docs available at http://localhost:3000/docs
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
export function defineOpenApiPlugin(
|
|
158
|
+
options: BunOpenApiPluginOptions,
|
|
159
|
+
): PluginDefinition<BunOpenApiPluginOptions> {
|
|
160
|
+
return {
|
|
161
|
+
plugin: new OpenApiBunPlugin(),
|
|
162
|
+
options,
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Re-export types for convenience
|
|
167
|
+
export type { ScalarOptions, ScalarTheme, BunOpenApiPluginOptions }
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for Scalar UI theme options
|
|
5
|
+
*/
|
|
6
|
+
export const scalarThemeSchema = z.enum([
|
|
7
|
+
'default',
|
|
8
|
+
'alternate',
|
|
9
|
+
'moon',
|
|
10
|
+
'purple',
|
|
11
|
+
'solarized',
|
|
12
|
+
'bluePlanet',
|
|
13
|
+
'saturn',
|
|
14
|
+
'kepler',
|
|
15
|
+
'mars',
|
|
16
|
+
'deepSpace',
|
|
17
|
+
'laserwave',
|
|
18
|
+
'elysiajs',
|
|
19
|
+
'fastify',
|
|
20
|
+
'none',
|
|
21
|
+
])
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Zod schema for Scalar UI metadata
|
|
25
|
+
*/
|
|
26
|
+
export const scalarMetaDataSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
title: z.string().optional(),
|
|
29
|
+
description: z.string().optional(),
|
|
30
|
+
ogDescription: z.string().optional(),
|
|
31
|
+
ogTitle: z.string().optional(),
|
|
32
|
+
ogImage: z.string().optional(),
|
|
33
|
+
twitterCard: z.string().optional(),
|
|
34
|
+
})
|
|
35
|
+
.optional()
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Zod schema for Scalar UI configuration options
|
|
39
|
+
*/
|
|
40
|
+
export const scalarOptionsSchema = z.object({
|
|
41
|
+
/**
|
|
42
|
+
* Theme for Scalar UI
|
|
43
|
+
* @default 'default'
|
|
44
|
+
*/
|
|
45
|
+
theme: scalarThemeSchema.optional(),
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Custom favicon URL
|
|
49
|
+
*/
|
|
50
|
+
favicon: z.string().optional(),
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Custom logo URL
|
|
54
|
+
*/
|
|
55
|
+
logo: z.string().optional(),
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Hide the "Download OpenAPI Spec" button
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
hideDownloadButton: z.boolean().optional(),
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Hide the "Search" input
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
hideSearch: z.boolean().optional(),
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Custom CSS to inject
|
|
71
|
+
*/
|
|
72
|
+
customCss: z.string().optional(),
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Meta data for the HTML page
|
|
76
|
+
*/
|
|
77
|
+
metaData: scalarMetaDataSchema,
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* CDN URL for Scalar API Reference
|
|
81
|
+
* @default 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'
|
|
82
|
+
*/
|
|
83
|
+
cdn: z.string().optional(),
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Zod schema for Bun OpenAPI plugin options
|
|
88
|
+
*/
|
|
89
|
+
export const bunOpenApiPluginOptionsSchema = z.object({
|
|
90
|
+
/**
|
|
91
|
+
* Path to serve OpenAPI JSON
|
|
92
|
+
* @default '/openapi.json'
|
|
93
|
+
*/
|
|
94
|
+
jsonPath: z.string().optional().default('/openapi.json'),
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Path to serve OpenAPI YAML
|
|
98
|
+
* @default '/openapi.yaml'
|
|
99
|
+
*/
|
|
100
|
+
yamlPath: z.string().optional().default('/openapi.yaml'),
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Path to serve Scalar UI
|
|
104
|
+
* @default '/docs'
|
|
105
|
+
*/
|
|
106
|
+
docsPath: z.string().optional().default('/docs'),
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Scalar UI configuration
|
|
110
|
+
*/
|
|
111
|
+
scalar: scalarOptionsSchema.optional(),
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Disable JSON endpoint
|
|
115
|
+
* @default false
|
|
116
|
+
*/
|
|
117
|
+
disableJson: z.boolean().optional().default(false),
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Disable Scalar UI (only serve JSON/YAML)
|
|
121
|
+
* @default false
|
|
122
|
+
*/
|
|
123
|
+
disableScalar: z.boolean().optional().default(false),
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Disable YAML endpoint
|
|
127
|
+
* @default true
|
|
128
|
+
*/
|
|
129
|
+
disableYaml: z.boolean().optional().default(true),
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
export type ScalarTheme = z.infer<typeof scalarThemeSchema>
|
|
133
|
+
export type ScalarMetaData = z.infer<typeof scalarMetaDataSchema>
|
|
134
|
+
export type ScalarOptions = z.infer<typeof scalarOptionsSchema>
|
|
135
|
+
export type BunOpenApiPluginOptionsBase = z.infer<typeof bunOpenApiPluginOptionsSchema>
|