@fluojs/openapi 1.0.0-beta.4 → 1.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +14 -4
- package/README.md +14 -4
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +2 -1
- package/dist/openapi-module.d.ts +8 -0
- package/dist/openapi-module.d.ts.map +1 -1
- package/dist/openapi-module.js +69 -7
- package/package.json +5 -5
package/README.ko.md
CHANGED
|
@@ -29,7 +29,7 @@ pnpm add @fluojs/openapi
|
|
|
29
29
|
|
|
30
30
|
## 빠른 시작
|
|
31
31
|
|
|
32
|
-
`OpenApiModule`을 등록하고 `sources
|
|
32
|
+
`OpenApiModule`을 등록하고 `sources`, 미리 만든 `descriptors`, 또는 둘 다를 전달해 문서에 포함할 HTTP 핸들러를 명시합니다. 두 입력을 모두 제공하면 병합됩니다.
|
|
33
33
|
|
|
34
34
|
```typescript
|
|
35
35
|
import { Controller, Get } from '@fluojs/http';
|
|
@@ -67,7 +67,7 @@ await app.listen(3000);
|
|
|
67
67
|
// Swagger UI: http://localhost:3000/docs
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
컨트롤러 탐색을 직접 건너뛰고 싶다면 `
|
|
70
|
+
컨트롤러 탐색을 직접 건너뛰고 싶다면 `@fluojs/http`의 `createHandlerMapping(...)`으로 handler descriptor를 만들고 `descriptors`로 전달하세요. `OpenApiModule`은 `@Module({ controllers: [...] })`만으로 핸들러를 자동 추론하지 않습니다.
|
|
71
71
|
|
|
72
72
|
## 핵심 기능
|
|
73
73
|
|
|
@@ -89,7 +89,13 @@ HTTP 핸들러가 `@fluojs/http`의 `@Produces(...)`를 선언하면, 생성된
|
|
|
89
89
|
같은 scheme에 대해 여러 `@ApiSecurity()` 데코레이터를 쌓으면, 해당 scheme의 scope가 하나의 누적 OpenAPI security requirement로 병합됩니다. 따라서 라우트가 `['reports:read']`와 `['reports:write', 'reports:read']`처럼 겹치는 scope를 선언해도 OAuth 스타일 요구사항은 결정적으로 유지되며, 서로 다른 scheme은 별도 requirement로 남습니다.
|
|
90
90
|
|
|
91
91
|
### 결정적인 Swagger UI 자산
|
|
92
|
-
`ui: true`를 활성화하면 생성되는 `/docs` 페이지는 정확한 `swagger-ui-dist` 버전의 자산을 참조하여 패키지 릴리스마다 동일한 동작을 유지합니다.
|
|
92
|
+
`ui: true`를 활성화하면 생성되는 `/docs` 페이지는 정확한 `swagger-ui-dist` 버전의 자산을 참조하여 패키지 릴리스마다 동일한 동작을 유지합니다. 오프라인 또는 CSP 제어 환경에서 자체 호스팅 자산이 필요하면 `swaggerUiAssets.cssUrl`과 `swaggerUiAssets.jsBundleUrl`을 설정하세요. 생성된 HTML은 해당 URL을 이스케이프하며 Swagger UI 인스턴스를 `window.ui`에 노출하지 않습니다.
|
|
93
|
+
|
|
94
|
+
### 모듈 옵션 결정성
|
|
95
|
+
`OpenApiModule.forRoot(...)`는 등록 시점에 옵션을 스냅샷하고 freeze합니다. 등록 후 원본 options 객체, `sources`, `descriptors`, `securitySchemes`, `extraModels`, `swaggerUiAssets`를 변경해도 제공되는 OpenAPI 문서나 `/docs` HTML은 바뀌지 않습니다. `OpenApiModule.forRootAsync(...)`도 async factory가 resolve된 뒤 같은 스냅샷을 적용하며, factory 실패는 bootstrap 중 전파됩니다.
|
|
96
|
+
|
|
97
|
+
### Async 등록과 옵션
|
|
98
|
+
title/version/source 설정이 DI나 async setup에서 나오는 경우 `OpenApiModule.forRootAsync(...)`를 사용합니다. Module option에는 `sources`, `descriptors`, `securitySchemes`, `extraModels`, `defaultErrorResponsesPolicy`, `documentTransform`, `ui`, `swaggerUiAssets`가 포함됩니다. `defaultErrorResponsesPolicy`는 기본적으로 표준 error response와 `ErrorResponse` schema를 주입하며, `documentTransform`은 문서 생성 뒤 제공되기 전에 실행됩니다.
|
|
93
99
|
|
|
94
100
|
## 공개 API
|
|
95
101
|
|
|
@@ -99,6 +105,10 @@ HTTP 핸들러가 `@fluojs/http`의 `@Produces(...)`를 선언하면, 생성된
|
|
|
99
105
|
- `ApiBearerAuth`, `ApiSecurity`: 보안 요구사항 데코레이터.
|
|
100
106
|
- `ApiExcludeEndpoint`: 특정 핸들러를 문서화에서 제외.
|
|
101
107
|
- `buildOpenApiDocument`: 프로그래밍 방식의 문서 빌더 (저수준).
|
|
108
|
+
- `OpenApiHandlerRegistry`: 고급 통합에서 문서 생성 전에 handler descriptor를 스냅샷하는 mutable descriptor registry.
|
|
109
|
+
- `getControllerTags`, `getMethodApiMetadata`: 고급 테스트와 통합 tooling을 위한 metadata reader.
|
|
110
|
+
- `OpenApiModuleOptions`, `OpenApiSwaggerUiAssetsOptions`, `BuildOpenApiDocumentOptions`, `DefaultErrorResponsesPolicy`: module과 builder integration을 위한 option type.
|
|
111
|
+
- `OpenApiDocument`, `OpenApiSecuritySchemeObject` 및 관련 OpenAPI shape type: 테스트, tooling, integration을 위한 typed document surface.
|
|
102
112
|
- `OpenApiSchemaObject`: 명시적 `@ApiBody(...)` 및 `@ApiResponse(...)` 스키마를 위한 타입화된 스키마 표면입니다. OpenAPI 3.1 조합(`allOf`, `oneOf`, `anyOf`), 객체/배열 제약, examples/defaults, 읽기/쓰기/Deprecated 주석을 포함합니다.
|
|
103
113
|
|
|
104
114
|
## 관련 패키지
|
|
@@ -110,4 +120,4 @@ HTTP 핸들러가 `@fluojs/http`의 `@Produces(...)`를 선언하면, 생성된
|
|
|
110
120
|
## 예제 소스
|
|
111
121
|
|
|
112
122
|
- `packages/openapi/src/openapi-module.test.ts`: 통합 테스트 및 사용 예제.
|
|
113
|
-
- `
|
|
123
|
+
- `packages/openapi/src/schema-builder.test.ts`: 문서 builder와 schema generation 예제.
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ pnpm add @fluojs/openapi
|
|
|
29
29
|
|
|
30
30
|
## Quick Start
|
|
31
31
|
|
|
32
|
-
Register the `OpenApiModule` and pass `sources
|
|
32
|
+
Register the `OpenApiModule` and pass `sources`, prebuilt `descriptors`, or both so the document builder knows which HTTP handlers to include. When both inputs are provided, they are merged.
|
|
33
33
|
|
|
34
34
|
```typescript
|
|
35
35
|
import { Controller, Get } from '@fluojs/http';
|
|
@@ -67,7 +67,7 @@ await app.listen(3000);
|
|
|
67
67
|
// Swagger UI: http://localhost:3000/docs
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
If you need to bypass controller discovery,
|
|
70
|
+
If you need to bypass controller discovery, create handler descriptors with `createHandlerMapping(...)` from `@fluojs/http` and pass them through `descriptors`. `OpenApiModule` does not infer handlers from `@Module({ controllers: [...] })` on its own.
|
|
71
71
|
|
|
72
72
|
## Core Capabilities
|
|
73
73
|
|
|
@@ -89,7 +89,13 @@ Easily document authentication requirements like Bearer tokens or API keys using
|
|
|
89
89
|
Stacking multiple `@ApiSecurity()` decorators for the same scheme merges scopes into one cumulative OpenAPI security requirement for that scheme. This keeps OAuth-style requirements deterministic when a route declares overlapping scopes such as `['reports:read']` and `['reports:write', 'reports:read']`, while different schemes remain separate requirements.
|
|
90
90
|
|
|
91
91
|
### Deterministic Swagger UI Assets
|
|
92
|
-
When `ui: true` is enabled, the generated `/docs` page references an exact `swagger-ui-dist` asset version so release behavior stays deterministic across package updates.
|
|
92
|
+
When `ui: true` is enabled, the generated `/docs` page references an exact `swagger-ui-dist` asset version so release behavior stays deterministic across package updates. If your deployment requires self-hosted assets for offline or CSP-controlled environments, set `swaggerUiAssets.cssUrl` and `swaggerUiAssets.jsBundleUrl`; the generated HTML escapes those URLs and does not expose the Swagger UI instance on `window.ui`.
|
|
93
|
+
|
|
94
|
+
### Module Option Determinism
|
|
95
|
+
`OpenApiModule.forRoot(...)` snapshots and freezes its options at registration time. Mutating the original options object, `sources`, `descriptors`, `securitySchemes`, `extraModels`, or `swaggerUiAssets` after registration does not alter the served OpenAPI document or `/docs` HTML. `OpenApiModule.forRootAsync(...)` applies the same snapshot once the async factory resolves, and factory failures propagate during bootstrap.
|
|
96
|
+
|
|
97
|
+
### Async Registration and Options
|
|
98
|
+
Use `OpenApiModule.forRootAsync(...)` when title/version/source configuration comes from DI or async setup. Module options include `sources`, `descriptors`, `securitySchemes`, `extraModels`, `defaultErrorResponsesPolicy`, `documentTransform`, `ui`, and `swaggerUiAssets`. `defaultErrorResponsesPolicy` defaults to injecting standard error responses and an `ErrorResponse` schema, while `documentTransform` runs after document generation and before serving.
|
|
93
99
|
|
|
94
100
|
## Public API
|
|
95
101
|
|
|
@@ -99,6 +105,10 @@ When `ui: true` is enabled, the generated `/docs` page references an exact `swag
|
|
|
99
105
|
- `ApiBearerAuth`, `ApiSecurity`: Security requirement decorators.
|
|
100
106
|
- `ApiExcludeEndpoint`: Omit specific handlers from documentation.
|
|
101
107
|
- `buildOpenApiDocument`: Programmatic document builder (low-level).
|
|
108
|
+
- `OpenApiHandlerRegistry`: Mutable descriptor registry used by advanced integrations to snapshot handler descriptors before document generation.
|
|
109
|
+
- `getControllerTags`, `getMethodApiMetadata`: Metadata readers for advanced tests and integration tooling.
|
|
110
|
+
- `OpenApiModuleOptions`, `OpenApiSwaggerUiAssetsOptions`, `BuildOpenApiDocumentOptions`, `DefaultErrorResponsesPolicy`: Option types for module and builder integrations.
|
|
111
|
+
- `OpenApiDocument`, `OpenApiSecuritySchemeObject`, and related OpenAPI shape types: Typed document surface for tests, tooling, and integrations.
|
|
102
112
|
- `OpenApiSchemaObject`: Typed schema surface for explicit `@ApiBody(...)` and `@ApiResponse(...)` schemas, including OpenAPI 3.1 composition (`allOf`, `oneOf`, `anyOf`), object/array constraints, examples/defaults, and read/write/deprecated annotations.
|
|
103
113
|
|
|
104
114
|
## Related Packages
|
|
@@ -110,4 +120,4 @@ When `ui: true` is enabled, the generated `/docs` page references an exact `swag
|
|
|
110
120
|
## Example Sources
|
|
111
121
|
|
|
112
122
|
- `packages/openapi/src/openapi-module.test.ts`: Integration tests and usage examples.
|
|
113
|
-
- `
|
|
123
|
+
- `packages/openapi/src/schema-builder.test.ts`: Document builder and schema generation examples.
|
package/dist/decorators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,mBAAmB,CAAA;KAAE,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,mBAAmB,CAAA;KAAE,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACpC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,8BAA8B,EAAE,CAAC;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"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"}
|
package/dist/decorators.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getStandardMetadataBag } from '@fluojs/core/internal';
|
|
1
|
+
import { ensureMetadataSymbol, getStandardMetadataBag } from '@fluojs/core/internal';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* User-facing operation metadata accepted by `@ApiOperation(...)`.
|
|
@@ -48,6 +48,7 @@ const openApiMethodRequestBodyKey = Symbol.for('fluo.openapi.method-request-body
|
|
|
48
48
|
const openApiMethodSecurityKey = Symbol.for('fluo.openapi.method-security');
|
|
49
49
|
const openApiMethodSecurityRequirementsKey = Symbol.for('fluo.openapi.method-security-requirements');
|
|
50
50
|
const openApiMethodExcludeEndpointKey = Symbol.for('fluo.openapi.method-exclude-endpoint');
|
|
51
|
+
ensureMetadataSymbol();
|
|
51
52
|
function getMetadataBag(target) {
|
|
52
53
|
return getStandardMetadataBag(target);
|
|
53
54
|
}
|
package/dist/openapi-module.d.ts
CHANGED
|
@@ -2,6 +2,13 @@ import { type HandlerDescriptor, type HandlerSource } from '@fluojs/http';
|
|
|
2
2
|
import { type AsyncModuleOptions, type Constructor } from '@fluojs/core';
|
|
3
3
|
import { type ModuleType } from '@fluojs/runtime';
|
|
4
4
|
import { type DefaultErrorResponsesPolicy, type OpenApiDocument, type OpenApiSecuritySchemeObject } from './schema-builder.js';
|
|
5
|
+
/**
|
|
6
|
+
* Asset URLs used by the generated Swagger UI HTML page.
|
|
7
|
+
*/
|
|
8
|
+
export interface OpenApiSwaggerUiAssetsOptions {
|
|
9
|
+
cssUrl?: string;
|
|
10
|
+
jsBundleUrl?: string;
|
|
11
|
+
}
|
|
5
12
|
/**
|
|
6
13
|
* Public options for `OpenApiModule.forRoot(...)` and `OpenApiModule.forRootAsync(...)`.
|
|
7
14
|
*
|
|
@@ -17,6 +24,7 @@ export interface OpenApiModuleOptions {
|
|
|
17
24
|
descriptors?: readonly HandlerDescriptor[];
|
|
18
25
|
sources?: readonly HandlerSource[];
|
|
19
26
|
securitySchemes?: Record<string, OpenApiSecuritySchemeObject>;
|
|
27
|
+
swaggerUiAssets?: OpenApiSwaggerUiAssetsOptions;
|
|
20
28
|
extraModels?: Constructor[];
|
|
21
29
|
documentTransform?: (document: OpenApiDocument) => OpenApiDocument;
|
|
22
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi-module.d.ts","sourceRoot":"","sources":["../src/openapi-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAEnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAU,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAiC,MAAM,cAAc,CAAC;AAChH,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGhE,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAC;AAO7B;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IAC9D,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,eAAe,CAAC;CACpE;
|
|
1
|
+
{"version":3,"file":"openapi-module.d.ts","sourceRoot":"","sources":["../src/openapi-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAEnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAU,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAiC,MAAM,cAAc,CAAC;AAChH,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGhE,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAC;AAO7B;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IAC9D,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAChD,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,eAAe,CAAC;CACpE;AA6ID;;GAEG;AACH,qBAAa,aAAa;IACxB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,UAAU;IAOzD;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,GAAG,UAAU;IAQlF,OAAO,CAAC,MAAM,CAAC,YAAY;CAqE5B"}
|
package/dist/openapi-module.js
CHANGED
|
@@ -13,6 +13,10 @@ const SWAGGER_UI_DIST_BASE_URL = `https://unpkg.com/swagger-ui-dist@${SWAGGER_UI
|
|
|
13
13
|
const SWAGGER_UI_CSS_URL = `${SWAGGER_UI_DIST_BASE_URL}/swagger-ui.css`;
|
|
14
14
|
const SWAGGER_UI_BUNDLE_JS_URL = `${SWAGGER_UI_DIST_BASE_URL}/swagger-ui-bundle.js`;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Asset URLs used by the generated Swagger UI HTML page.
|
|
18
|
+
*/
|
|
19
|
+
|
|
16
20
|
/**
|
|
17
21
|
* Public options for `OpenApiModule.forRoot(...)` and `OpenApiModule.forRootAsync(...)`.
|
|
18
22
|
*
|
|
@@ -24,24 +28,82 @@ const SWAGGER_UI_BUNDLE_JS_URL = `${SWAGGER_UI_DIST_BASE_URL}/swagger-ui-bundle.
|
|
|
24
28
|
function escapeHtml(value) {
|
|
25
29
|
return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
26
30
|
}
|
|
27
|
-
function
|
|
31
|
+
function cloneRecord(record) {
|
|
32
|
+
if (!record) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const clone = {};
|
|
36
|
+
for (const [key, value] of Object.entries(record)) {
|
|
37
|
+
clone[key] = cloneSnapshotValue(value);
|
|
38
|
+
}
|
|
39
|
+
return clone;
|
|
40
|
+
}
|
|
41
|
+
function cloneSnapshotValue(value) {
|
|
42
|
+
if (value === null || value === undefined) {
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
return value.map(entry => cloneSnapshotValue(entry));
|
|
47
|
+
}
|
|
48
|
+
if (typeof value !== 'object') {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
const clone = {};
|
|
52
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
53
|
+
clone[key] = cloneSnapshotValue(value[key]);
|
|
54
|
+
}
|
|
55
|
+
return clone;
|
|
56
|
+
}
|
|
57
|
+
function deepFreeze(value) {
|
|
58
|
+
if (value === null || typeof value !== 'object') {
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
62
|
+
deepFreeze(value[key]);
|
|
63
|
+
}
|
|
64
|
+
return Object.freeze(value);
|
|
65
|
+
}
|
|
66
|
+
function snapshotOpenApiModuleOptions(options) {
|
|
67
|
+
return deepFreeze({
|
|
68
|
+
defaultErrorResponsesPolicy: options.defaultErrorResponsesPolicy,
|
|
69
|
+
descriptors: options.descriptors ? cloneSnapshotValue(options.descriptors) : undefined,
|
|
70
|
+
documentTransform: options.documentTransform,
|
|
71
|
+
extraModels: options.extraModels ? [...options.extraModels] : undefined,
|
|
72
|
+
securitySchemes: cloneRecord(options.securitySchemes),
|
|
73
|
+
sources: options.sources ? cloneSnapshotValue(options.sources) : undefined,
|
|
74
|
+
swaggerUiAssets: options.swaggerUiAssets ? {
|
|
75
|
+
...options.swaggerUiAssets
|
|
76
|
+
} : undefined,
|
|
77
|
+
title: options.title,
|
|
78
|
+
ui: options.ui,
|
|
79
|
+
version: options.version
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function resolveSwaggerUiAssets(options) {
|
|
83
|
+
return {
|
|
84
|
+
cssUrl: options.swaggerUiAssets?.cssUrl ?? SWAGGER_UI_CSS_URL,
|
|
85
|
+
jsBundleUrl: options.swaggerUiAssets?.jsBundleUrl ?? SWAGGER_UI_BUNDLE_JS_URL
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function createSwaggerUiHtml(title, assets) {
|
|
28
89
|
return `<!doctype html>
|
|
29
90
|
<html lang="en">
|
|
30
91
|
<head>
|
|
31
92
|
<meta charset="utf-8" />
|
|
32
93
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
33
94
|
<title>${escapeHtml(title)}</title>
|
|
34
|
-
<link rel="stylesheet" href="${
|
|
95
|
+
<link rel="stylesheet" href="${escapeHtml(assets.cssUrl)}" />
|
|
35
96
|
</head>
|
|
36
97
|
<body>
|
|
37
98
|
<div id="swagger-ui"></div>
|
|
38
|
-
<script src="${
|
|
99
|
+
<script src="${escapeHtml(assets.jsBundleUrl)}" crossorigin></script>
|
|
39
100
|
<script>
|
|
40
101
|
const specUrl = window.location.pathname.replace(/\/docs\/?$/, '/openapi.json');
|
|
41
|
-
|
|
102
|
+
const swaggerUi = SwaggerUIBundle({
|
|
42
103
|
url: specUrl,
|
|
43
104
|
dom_id: '#swagger-ui'
|
|
44
105
|
});
|
|
106
|
+
void swaggerUi;
|
|
45
107
|
</script>
|
|
46
108
|
</body>
|
|
47
109
|
</html>`;
|
|
@@ -87,7 +149,7 @@ export class OpenApiModule {
|
|
|
87
149
|
static forRoot(options) {
|
|
88
150
|
return this.createModule({
|
|
89
151
|
scope: 'singleton',
|
|
90
|
-
useValue: options
|
|
152
|
+
useValue: snapshotOpenApiModuleOptions(options)
|
|
91
153
|
});
|
|
92
154
|
}
|
|
93
155
|
|
|
@@ -112,7 +174,7 @@ export class OpenApiModule {
|
|
|
112
174
|
return this.createModule({
|
|
113
175
|
inject: options.inject,
|
|
114
176
|
scope: 'singleton',
|
|
115
|
-
useFactory: options.useFactory
|
|
177
|
+
useFactory: async (...deps) => snapshotOpenApiModuleOptions(await options.useFactory(...deps))
|
|
116
178
|
});
|
|
117
179
|
}
|
|
118
180
|
static createModule(optionsProvider) {
|
|
@@ -140,7 +202,7 @@ export class OpenApiModule {
|
|
|
140
202
|
throw new NotFoundException('Swagger UI is disabled.');
|
|
141
203
|
}
|
|
142
204
|
context.response.setHeader('content-type', 'text/html; charset=utf-8');
|
|
143
|
-
return createSwaggerUiHtml(this.options.title);
|
|
205
|
+
return createSwaggerUiHtml(this.options.title, resolveSwaggerUiAssets(this.options));
|
|
144
206
|
}
|
|
145
207
|
static {
|
|
146
208
|
_initClass();
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"documentation",
|
|
10
10
|
"rest"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.0-beta.
|
|
12
|
+
"version": "1.0.0-beta.6",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@fluojs/core": "^1.0.0-beta.
|
|
40
|
-
"@fluojs/validation": "^1.0.0-beta.
|
|
41
|
-
"@fluojs/http": "^1.0.0-beta.
|
|
42
|
-
"@fluojs/runtime": "^1.0.0-beta.
|
|
39
|
+
"@fluojs/core": "^1.0.0-beta.4",
|
|
40
|
+
"@fluojs/validation": "^1.0.0-beta.3",
|
|
41
|
+
"@fluojs/http": "^1.0.0-beta.10",
|
|
42
|
+
"@fluojs/runtime": "^1.0.0-beta.11"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"vitest": "^3.2.4"
|