@scalar/mock-server 0.6.1 → 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 +15 -0
- package/README.md +6 -172
- package/dist/create-mock-server.d.ts +7 -0
- package/dist/create-mock-server.d.ts.map +1 -0
- package/dist/create-mock-server.js +45 -0
- package/dist/create-mock-server.js.map +7 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/routes/{mockAnyResponse.d.ts → mock-any-response.d.ts} +3 -2
- package/dist/routes/mock-any-response.d.ts.map +1 -0
- package/dist/routes/{mockAnyResponse.js → mock-any-response.js} +16 -8
- package/dist/routes/mock-any-response.js.map +7 -0
- package/dist/routes/{respondWithAuthorizePage.d.ts → respond-with-authorize-page.d.ts} +1 -1
- package/dist/routes/respond-with-authorize-page.d.ts.map +1 -0
- package/dist/routes/{respondWithAuthorizePage.js → respond-with-authorize-page.js} +1 -1
- package/dist/routes/{respondWithAuthorizePage.js.map → respond-with-authorize-page.js.map} +1 -1
- package/dist/routes/{respondWithOpenApiDocument.d.ts → respond-with-openapi-document.d.ts} +1 -1
- package/dist/routes/respond-with-openapi-document.d.ts.map +1 -0
- package/dist/routes/{respondWithOpenApiDocument.js → respond-with-openapi-document.js} +1 -1
- package/dist/routes/{respondWithOpenApiDocument.js.map → respond-with-openapi-document.js.map} +1 -1
- package/dist/routes/{respondWithToken.d.ts → respond-with-token.d.ts} +1 -1
- package/dist/routes/respond-with-token.d.ts.map +1 -0
- package/dist/routes/{respondWithToken.js → respond-with-token.js} +1 -1
- package/dist/routes/{respondWithToken.js.map → respond-with-token.js.map} +1 -1
- package/dist/types.d.ts +18 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/{createOpenApiDefinition.d.ts → create-openapi-definition.d.ts} +1 -1
- package/dist/utils/create-openapi-definition.d.ts.map +1 -0
- package/dist/utils/{createOpenApiDefinition.js → create-openapi-definition.js} +1 -1
- package/dist/utils/{createOpenApiDefinition.js.map → create-openapi-definition.js.map} +1 -1
- package/dist/utils/{findPreferredResponseKey.d.ts → find-preferred-response-key.d.ts} +1 -1
- package/dist/utils/find-preferred-response-key.d.ts.map +1 -0
- package/dist/utils/{findPreferredResponseKey.js → find-preferred-response-key.js} +1 -1
- package/dist/utils/{findPreferredResponseKey.js.map → find-preferred-response-key.js.map} +1 -1
- package/dist/utils/{getOpenAuthTokenUrls.d.ts → get-open-auth-token-urls.d.ts} +1 -1
- package/dist/utils/get-open-auth-token-urls.d.ts.map +1 -0
- package/dist/utils/{getOpenAuthTokenUrls.js → get-open-auth-token-urls.js} +1 -1
- package/dist/utils/{getOpenAuthTokenUrls.js.map → get-open-auth-token-urls.js.map} +1 -1
- package/dist/utils/{getOperations.d.ts → get-operation.d.ts} +1 -1
- package/dist/utils/{getOperations.d.ts.map → get-operation.d.ts.map} +1 -1
- package/dist/utils/{getOperations.js → get-operation.js} +1 -1
- package/dist/utils/{getOperations.js.map → get-operation.js.map} +1 -1
- package/dist/utils/{handleAuthentication.d.ts → handle-authentication.d.ts} +2 -2
- package/dist/utils/handle-authentication.d.ts.map +1 -0
- package/dist/utils/{handleAuthentication.js → handle-authentication.js} +1 -1
- package/dist/utils/handle-authentication.js.map +7 -0
- package/dist/utils/{honoRouteFromPath.d.ts → hono-route-from-path.d.ts} +1 -1
- package/dist/utils/hono-route-from-path.d.ts.map +1 -0
- package/dist/utils/{honoRouteFromPath.js → hono-route-from-path.js} +1 -1
- package/dist/utils/{honoRouteFromPath.js.map → hono-route-from-path.js.map} +1 -1
- package/dist/utils/{isAuthenticationRequired.d.ts → is-authentication-required.d.ts} +1 -1
- package/dist/utils/is-authentication-required.d.ts.map +1 -0
- package/dist/utils/{isAuthenticationRequired.js → is-authentication-required.js} +1 -1
- package/dist/utils/{isAuthenticationRequired.js.map → is-authentication-required.js.map} +1 -1
- package/dist/utils/{logAuthenticationInstructions.d.ts → log-authentication-instructions.d.ts} +1 -1
- package/dist/utils/log-authentication-instructions.d.ts.map +1 -0
- package/dist/utils/{logAuthenticationInstructions.js → log-authentication-instructions.js} +2 -2
- package/dist/utils/log-authentication-instructions.js.map +7 -0
- package/dist/utils/{setupAuthenticationRoutes.d.ts → set-up-authentication-routes.d.ts} +2 -2
- package/dist/utils/set-up-authentication-routes.d.ts.map +1 -0
- package/dist/utils/{setupAuthenticationRoutes.js → set-up-authentication-routes.js} +6 -6
- package/dist/utils/set-up-authentication-routes.js.map +7 -0
- package/package.json +4 -6
- package/dist/createMockServer.d.ts +0 -7
- package/dist/createMockServer.d.ts.map +0 -1
- package/dist/createMockServer.js +0 -39
- package/dist/createMockServer.js.map +0 -7
- package/dist/createMockServer.test.d.ts +0 -2
- package/dist/createMockServer.test.d.ts.map +0 -1
- package/dist/routes/mockAnyResponse.d.ts.map +0 -1
- package/dist/routes/mockAnyResponse.js.map +0 -7
- package/dist/routes/respondWithAuthorizePage.d.ts.map +0 -1
- package/dist/routes/respondWithOpenApiDocument.d.ts.map +0 -1
- package/dist/routes/respondWithToken.d.ts.map +0 -1
- package/dist/utils/createOpenApiDefinition.d.ts.map +0 -1
- package/dist/utils/findPreferredResponseKey.d.ts.map +0 -1
- package/dist/utils/findPreferredResponseKey.test.d.ts +0 -2
- package/dist/utils/findPreferredResponseKey.test.d.ts.map +0 -1
- package/dist/utils/getOpenAuthTokenUrls.d.ts.map +0 -1
- package/dist/utils/getOpenAuthTokenUrls.test.d.ts +0 -2
- package/dist/utils/getOpenAuthTokenUrls.test.d.ts.map +0 -1
- package/dist/utils/handleAuthentication.d.ts.map +0 -1
- package/dist/utils/handleAuthentication.js.map +0 -7
- package/dist/utils/honoRouteFromPath.d.ts.map +0 -1
- package/dist/utils/honoRouteFromPath.test.d.ts +0 -2
- package/dist/utils/honoRouteFromPath.test.d.ts.map +0 -1
- package/dist/utils/isAuthenticationRequired.d.ts.map +0 -1
- package/dist/utils/isAuthenticationRequired.test.d.ts +0 -2
- package/dist/utils/isAuthenticationRequired.test.d.ts.map +0 -1
- package/dist/utils/logAuthenticationInstructions.d.ts.map +0 -1
- package/dist/utils/logAuthenticationInstructions.js.map +0 -7
- package/dist/utils/setupAuthenticationRoutes.d.ts.map +0 -1
- package/dist/utils/setupAuthenticationRoutes.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @scalar/mock-server
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#7247](https://github.com/scalar/scalar/pull/7247) [`a4f862c`](https://github.com/scalar/scalar/commit/a4f862c73ee509579c96ab86c703e8af74d8efcf) Thanks [@hanspagel](https://github.com/hanspagel)! - feat: use `document`, not `specification` for the configuration
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#7247](https://github.com/scalar/scalar/pull/7247) [`a4f862c`](https://github.com/scalar/scalar/commit/a4f862c73ee509579c96ab86c703e8af74d8efcf) Thanks [@hanspagel](https://github.com/hanspagel)! - fix: fails on 204 No Content responses
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`fddf294`](https://github.com/scalar/scalar/commit/fddf294b00dd8c9eb5c713c338f2ec6e3f62523d), [`c1ecd0c`](https://github.com/scalar/scalar/commit/c1ecd0c6096f3fbe2e3d8ad3794ea718bb6bce66), [`c1ecd0c`](https://github.com/scalar/scalar/commit/c1ecd0c6096f3fbe2e3d8ad3794ea718bb6bce66), [`2377b76`](https://github.com/scalar/scalar/commit/2377b76d050f8de70037b17a32d0dd1181d3311d)]:
|
|
14
|
+
- @scalar/helpers@0.1.0
|
|
15
|
+
- @scalar/openapi-parser@0.23.1
|
|
16
|
+
- @scalar/oas-utils@0.6.2
|
|
17
|
+
|
|
3
18
|
## 0.6.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,187 +1,21 @@
|
|
|
1
1
|
# Scalar Mock Server
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@scalar/mock-server)
|
|
4
|
+
[](https://www.npmjs.com/package/@scalar/mock-server)
|
|
5
|
+
[](https://www.npmjs.com/package/@scalar/mock-server)
|
|
6
6
|
[](https://discord.gg/scalar)
|
|
7
7
|
|
|
8
8
|
A powerful Node.js mock server that automatically generates realistic API responses from your OpenAPI/Swagger documents. It creates fully-functional endpoints with mock data, handles authentication, and respects content types - making it perfect for frontend development, API prototyping, and integration testing.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## Features
|
|
13
|
-
|
|
14
|
-
- Perfect for frontend development and testing
|
|
15
|
-
- Creates endpoints automatically from OpenAPI documents
|
|
16
|
-
- Generates realistic mock data based on your schemas
|
|
17
|
-
- Handles authentication and responds with defined HTTP headers
|
|
18
|
-
- Supports Swagger 2.0 and OpenAPI 3.x documents
|
|
19
|
-
- Customizable response handling
|
|
20
|
-
|
|
21
|
-
## Quickstart
|
|
22
|
-
|
|
23
|
-
The easiest way to get started is through [our Scalar CLI](https://www.npmjs.com/package/@scalar/cli).
|
|
24
|
-
You can have a mock server up and running in seconds:
|
|
10
|
+
## Usage
|
|
25
11
|
|
|
26
12
|
```bash
|
|
27
13
|
npx @scalar/cli document mock openapi.json --watch
|
|
28
14
|
```
|
|
29
15
|
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
For advanced use cases, you can integrate the mock server directly into your Node.js application for full control:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npm install @scalar/mock-server
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Usage
|
|
39
|
-
|
|
40
|
-
```ts
|
|
41
|
-
import { serve } from '@hono/node-server'
|
|
42
|
-
import { createMockServer } from '@scalar/mock-server'
|
|
43
|
-
|
|
44
|
-
// Your OpenAPI document
|
|
45
|
-
const specification = {
|
|
46
|
-
openapi: '3.1.1',
|
|
47
|
-
info: {
|
|
48
|
-
title: 'Hello World',
|
|
49
|
-
version: '1.0.0',
|
|
50
|
-
},
|
|
51
|
-
paths: {
|
|
52
|
-
'/foobar': {
|
|
53
|
-
get: {
|
|
54
|
-
responses: {
|
|
55
|
-
'200': {
|
|
56
|
-
description: 'OK',
|
|
57
|
-
content: {
|
|
58
|
-
'application/json': {
|
|
59
|
-
example: {
|
|
60
|
-
foo: 'bar',
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Create the mocked routes
|
|
72
|
-
const app = await createMockServer({
|
|
73
|
-
specification,
|
|
74
|
-
// Custom logging
|
|
75
|
-
onRequest({ context, operation }) {
|
|
76
|
-
console.log(context.req.method, context.req.path)
|
|
77
|
-
},
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
// Start the server
|
|
81
|
-
serve(
|
|
82
|
-
{
|
|
83
|
-
fetch: app.fetch,
|
|
84
|
-
port: 3000,
|
|
85
|
-
},
|
|
86
|
-
(info) => {
|
|
87
|
-
console.log(`Listening on http://localhost:${info.port}`)
|
|
88
|
-
},
|
|
89
|
-
)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Authentication
|
|
93
|
-
|
|
94
|
-
You can define security schemes in your OpenAPI document and the mock server will validate the authentication:
|
|
95
|
-
|
|
96
|
-
```ts
|
|
97
|
-
import { serve } from '@hono/node-server'
|
|
98
|
-
import { createMockServer } from '@scalar/mock-server'
|
|
99
|
-
|
|
100
|
-
// Your OpenAPI document
|
|
101
|
-
const specification = {
|
|
102
|
-
openapi: '3.1.1',
|
|
103
|
-
info: {
|
|
104
|
-
title: 'Hello World',
|
|
105
|
-
version: '1.0.0',
|
|
106
|
-
},
|
|
107
|
-
paths: {
|
|
108
|
-
'/secret': {
|
|
109
|
-
get: {
|
|
110
|
-
security: [
|
|
111
|
-
{
|
|
112
|
-
bearerAuth: [],
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
apiKey: [],
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
responses: {
|
|
119
|
-
'200': {
|
|
120
|
-
description: 'OK',
|
|
121
|
-
content: {
|
|
122
|
-
'application/json': {
|
|
123
|
-
example: {
|
|
124
|
-
foo: 'bar',
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
'401': {
|
|
130
|
-
description: 'Unauthorized',
|
|
131
|
-
content: {
|
|
132
|
-
'application/json': {
|
|
133
|
-
example: {
|
|
134
|
-
error: 'Unauthorized',
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
components: {
|
|
144
|
-
securitySchemes: {
|
|
145
|
-
bearerAuth: {
|
|
146
|
-
type: 'http',
|
|
147
|
-
scheme: 'bearer',
|
|
148
|
-
bearerFormat: 'JWT',
|
|
149
|
-
},
|
|
150
|
-
apiKey: {
|
|
151
|
-
type: 'apiKey',
|
|
152
|
-
in: 'header',
|
|
153
|
-
name: 'X-API-Key',
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Create the mocked routes
|
|
160
|
-
const app = await createMockServer({
|
|
161
|
-
specification,
|
|
162
|
-
// Custom logging
|
|
163
|
-
onRequest({ context, operation }) {
|
|
164
|
-
console.log(context.req.method, context.req.path)
|
|
165
|
-
},
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
// Start the server
|
|
169
|
-
serve(
|
|
170
|
-
{
|
|
171
|
-
fetch: app.fetch,
|
|
172
|
-
port: 3000,
|
|
173
|
-
},
|
|
174
|
-
(info) => {
|
|
175
|
-
console.log(`Listening on http://localhost:${info.port}`)
|
|
176
|
-
},
|
|
177
|
-
)
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### OpenAPI endpoints
|
|
181
|
-
|
|
182
|
-
The given OpenAPI document is automatically exposed:
|
|
16
|
+
## Documentation
|
|
183
17
|
|
|
184
|
-
|
|
18
|
+
[Read the documentation here](https://guides.scalar.com/scalar/scalar-mock-server/getting-started)
|
|
185
19
|
|
|
186
20
|
## Community
|
|
187
21
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { MockServerOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create a mock server instance
|
|
5
|
+
*/
|
|
6
|
+
export declare function createMockServer(configuration: MockServerOptions): Promise<Hono>;
|
|
7
|
+
//# sourceMappingURL=create-mock-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-mock-server.d.ts","sourceRoot":"","sources":["../src/create-mock-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAW5D;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDhF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { dereference } from "@scalar/openapi-parser";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
import { cors } from "hono/cors";
|
|
4
|
+
import { getOperations } from "./utils/get-operation.js";
|
|
5
|
+
import { handleAuthentication } from "./utils/handle-authentication.js";
|
|
6
|
+
import { honoRouteFromPath } from "./utils/hono-route-from-path.js";
|
|
7
|
+
import { isAuthenticationRequired } from "./utils/is-authentication-required.js";
|
|
8
|
+
import { logAuthenticationInstructions } from "./utils/log-authentication-instructions.js";
|
|
9
|
+
import { setUpAuthenticationRoutes } from "./utils/set-up-authentication-routes.js";
|
|
10
|
+
import { mockAnyResponse } from "./routes/mock-any-response.js";
|
|
11
|
+
import { respondWithOpenApiDocument } from "./routes/respond-with-openapi-document.js";
|
|
12
|
+
function createMockServer(configuration) {
|
|
13
|
+
const app = new Hono();
|
|
14
|
+
const { schema } = dereference(configuration?.document ?? configuration?.specification ?? {});
|
|
15
|
+
app.use(cors());
|
|
16
|
+
setUpAuthenticationRoutes(app, schema);
|
|
17
|
+
logAuthenticationInstructions(
|
|
18
|
+
schema?.components?.securitySchemes || {}
|
|
19
|
+
);
|
|
20
|
+
const paths = schema?.paths ?? {};
|
|
21
|
+
Object.keys(paths).forEach((path) => {
|
|
22
|
+
const methods = Object.keys(getOperations(paths[path]));
|
|
23
|
+
methods.forEach((method) => {
|
|
24
|
+
const route = honoRouteFromPath(path);
|
|
25
|
+
const operation = schema?.paths?.[path]?.[method];
|
|
26
|
+
if (isAuthenticationRequired(operation.security)) {
|
|
27
|
+
app[method](route, handleAuthentication(schema, operation));
|
|
28
|
+
}
|
|
29
|
+
app[method](route, (c) => mockAnyResponse(c, operation, configuration));
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
app.get(
|
|
33
|
+
"/openapi.json",
|
|
34
|
+
(c) => respondWithOpenApiDocument(c, configuration?.document ?? configuration?.specification, "json")
|
|
35
|
+
);
|
|
36
|
+
app.get(
|
|
37
|
+
"/openapi.yaml",
|
|
38
|
+
(c) => respondWithOpenApiDocument(c, configuration?.document ?? configuration?.specification, "yaml")
|
|
39
|
+
);
|
|
40
|
+
return Promise.resolve(app);
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
createMockServer
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=create-mock-server.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/create-mock-server.ts"],
|
|
4
|
+
"sourcesContent": ["import { dereference } from '@scalar/openapi-parser'\nimport type { OpenAPI, OpenAPIV3_1 } from '@scalar/openapi-types'\nimport { Hono } from 'hono'\nimport { cors } from 'hono/cors'\n\nimport type { HttpMethod, MockServerOptions } from '@/types'\nimport { getOperations } from '@/utils/get-operation'\nimport { handleAuthentication } from '@/utils/handle-authentication'\nimport { honoRouteFromPath } from '@/utils/hono-route-from-path'\nimport { isAuthenticationRequired } from '@/utils/is-authentication-required'\nimport { logAuthenticationInstructions } from '@/utils/log-authentication-instructions'\nimport { setUpAuthenticationRoutes } from '@/utils/set-up-authentication-routes'\n\nimport { mockAnyResponse } from './routes/mock-any-response'\nimport { respondWithOpenApiDocument } from './routes/respond-with-openapi-document'\n\n/**\n * Create a mock server instance\n */\nexport function createMockServer(configuration: MockServerOptions): Promise<Hono> {\n const app = new Hono()\n\n /** Dereferenced OpenAPI document */\n const { schema } = dereference(configuration?.document ?? configuration?.specification ?? {})\n\n // CORS headers\n app.use(cors())\n\n /** Authentication methods defined in the OpenAPI document */\n setUpAuthenticationRoutes(app, schema)\n\n logAuthenticationInstructions(\n schema?.components?.securitySchemes || ({} as Record<string, OpenAPIV3_1.SecuritySchemeObject>),\n )\n\n /** Paths specified in the OpenAPI document */\n const paths = schema?.paths ?? {}\n\n Object.keys(paths).forEach((path) => {\n const methods = Object.keys(getOperations(paths[path])) as HttpMethod[]\n\n /** Keys for all operations of a specified path */\n methods.forEach((method) => {\n const route = honoRouteFromPath(path)\n const operation = schema?.paths?.[path]?.[method] as OpenAPI.Operation\n\n // Check if authentication is required for this operation\n if (isAuthenticationRequired(operation.security)) {\n app[method](route, handleAuthentication(schema, operation))\n }\n\n // Actual route\n app[method](route, (c) => mockAnyResponse(c, operation, configuration))\n })\n })\n\n // OpenAPI JSON file\n app.get('/openapi.json', (c) =>\n respondWithOpenApiDocument(c, configuration?.document ?? configuration?.specification, 'json'),\n )\n\n // OpenAPI YAML file\n app.get('/openapi.yaml', (c) =>\n respondWithOpenApiDocument(c, configuration?.document ?? configuration?.specification, 'yaml'),\n )\n\n /**\n * No async code, but returning a Promise to allow future async logic to be implemented\n * @see https://github.com/scalar/scalar/pull/7174#discussion_r2470046281\n */\n return Promise.resolve(app)\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,mBAAmB;AAE5B,SAAS,YAAY;AACrB,SAAS,YAAY;AAGrB,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,yBAAyB;AAClC,SAAS,gCAAgC;AACzC,SAAS,qCAAqC;AAC9C,SAAS,iCAAiC;AAE1C,SAAS,uBAAuB;AAChC,SAAS,kCAAkC;AAKpC,SAAS,iBAAiB,eAAiD;AAChF,QAAM,MAAM,IAAI,KAAK;AAGrB,QAAM,EAAE,OAAO,IAAI,YAAY,eAAe,YAAY,eAAe,iBAAiB,CAAC,CAAC;AAG5F,MAAI,IAAI,KAAK,CAAC;AAGd,4BAA0B,KAAK,MAAM;AAErC;AAAA,IACE,QAAQ,YAAY,mBAAoB,CAAC;AAAA,EAC3C;AAGA,QAAM,QAAQ,QAAQ,SAAS,CAAC;AAEhC,SAAO,KAAK,KAAK,EAAE,QAAQ,CAAC,SAAS;AACnC,UAAM,UAAU,OAAO,KAAK,cAAc,MAAM,IAAI,CAAC,CAAC;AAGtD,YAAQ,QAAQ,CAAC,WAAW;AAC1B,YAAM,QAAQ,kBAAkB,IAAI;AACpC,YAAM,YAAY,QAAQ,QAAQ,IAAI,IAAI,MAAM;AAGhD,UAAI,yBAAyB,UAAU,QAAQ,GAAG;AAChD,YAAI,MAAM,EAAE,OAAO,qBAAqB,QAAQ,SAAS,CAAC;AAAA,MAC5D;AAGA,UAAI,MAAM,EAAE,OAAO,CAAC,MAAM,gBAAgB,GAAG,WAAW,aAAa,CAAC;AAAA,IACxE,CAAC;AAAA,EACH,CAAC;AAGD,MAAI;AAAA,IAAI;AAAA,IAAiB,CAAC,MACxB,2BAA2B,GAAG,eAAe,YAAY,eAAe,eAAe,MAAM;AAAA,EAC/F;AAGA,MAAI;AAAA,IAAI;AAAA,IAAiB,CAAC,MACxB,2BAA2B,GAAG,eAAe,YAAY,eAAe,eAAe,MAAM;AAAA,EAC/F;AAMA,SAAO,QAAQ,QAAQ,GAAG;AAC5B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createMockServer } from './
|
|
1
|
+
export { createMockServer } from './create-mock-server.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { createMockServer } from './
|
|
4
|
+
"sourcesContent": ["export { createMockServer } from './create-mock-server'\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,wBAAwB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { OpenAPI } from '@scalar/openapi-types';
|
|
2
2
|
import type { Context } from 'hono';
|
|
3
|
+
import type { StatusCode } from 'hono/utils/http-status';
|
|
3
4
|
import type { MockServerOptions } from '../types.js';
|
|
4
5
|
/**
|
|
5
6
|
* Mock any response
|
|
6
7
|
*/
|
|
7
8
|
export declare function mockAnyResponse(c: Context, operation: OpenAPI.Operation, options: MockServerOptions): (Response & import("hono").TypedResponse<{
|
|
8
9
|
error: string;
|
|
9
|
-
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<any, import("hono/utils/http-status").ContentfulStatusCode, "body">);
|
|
10
|
-
//# sourceMappingURL=
|
|
10
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<null, StatusCode, "body">) | (Response & import("hono").TypedResponse<any, import("hono/utils/http-status").ContentfulStatusCode, "body">);
|
|
11
|
+
//# sourceMappingURL=mock-any-response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-any-response.d.ts","sourceRoot":"","sources":["../../src/routes/mock-any-response.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAGhD;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,iBAAiB;;yPAqFnG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { json2xml } from "@scalar/helpers/file/json2xml";
|
|
1
2
|
import { getExampleFromSchema } from "@scalar/oas-utils/spec-getters";
|
|
2
3
|
import { accepts } from "hono/accepts";
|
|
3
|
-
import { findPreferredResponseKey } from "../utils/
|
|
4
|
-
import { json2xml } from "@scalar/helpers/file/json2xml";
|
|
4
|
+
import { findPreferredResponseKey } from "../utils/find-preferred-response-key.js";
|
|
5
5
|
function mockAnyResponse(c, operation, options) {
|
|
6
6
|
if (options?.onRequest) {
|
|
7
7
|
options.onRequest({
|
|
@@ -15,7 +15,10 @@ function mockAnyResponse(c, operation, options) {
|
|
|
15
15
|
c.status(500);
|
|
16
16
|
return c.json({ error: "No response defined for this operation." });
|
|
17
17
|
}
|
|
18
|
-
const
|
|
18
|
+
const statusCode = Number.parseInt(
|
|
19
|
+
preferredResponseKey === "default" ? "200" : preferredResponseKey ?? "200",
|
|
20
|
+
10
|
|
21
|
+
);
|
|
19
22
|
const headers = preferredResponse?.headers ?? {};
|
|
20
23
|
Object.keys(headers).forEach((header) => {
|
|
21
24
|
const value = headers[header].schema ? getExampleFromSchema(headers[header].schema) : null;
|
|
@@ -23,6 +26,15 @@ function mockAnyResponse(c, operation, options) {
|
|
|
23
26
|
c.header(header, value);
|
|
24
27
|
}
|
|
25
28
|
});
|
|
29
|
+
if (statusCode === 204) {
|
|
30
|
+
c.status(statusCode);
|
|
31
|
+
return c.body(null);
|
|
32
|
+
}
|
|
33
|
+
const supportedContentTypes = Object.keys(preferredResponse?.content ?? {});
|
|
34
|
+
if (supportedContentTypes.length === 0) {
|
|
35
|
+
c.status(statusCode);
|
|
36
|
+
return c.body(null);
|
|
37
|
+
}
|
|
26
38
|
const acceptedContentType = accepts(c, {
|
|
27
39
|
header: "Accept",
|
|
28
40
|
supports: supportedContentTypes,
|
|
@@ -35,10 +47,6 @@ function mockAnyResponse(c, operation, options) {
|
|
|
35
47
|
variables: c.req.param(),
|
|
36
48
|
mode: "read"
|
|
37
49
|
}) : null;
|
|
38
|
-
const statusCode = Number.parseInt(
|
|
39
|
-
preferredResponseKey === "default" ? "200" : preferredResponseKey ?? "200",
|
|
40
|
-
10
|
|
41
|
-
);
|
|
42
50
|
c.status(statusCode);
|
|
43
51
|
return c.body(
|
|
44
52
|
typeof body === "object" ? (
|
|
@@ -56,4 +64,4 @@ function mockAnyResponse(c, operation, options) {
|
|
|
56
64
|
export {
|
|
57
65
|
mockAnyResponse
|
|
58
66
|
};
|
|
59
|
-
//# sourceMappingURL=
|
|
67
|
+
//# sourceMappingURL=mock-any-response.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/routes/mock-any-response.ts"],
|
|
4
|
+
"sourcesContent": ["import { json2xml } from '@scalar/helpers/file/json2xml'\nimport { getExampleFromSchema } from '@scalar/oas-utils/spec-getters'\nimport type { OpenAPI } from '@scalar/openapi-types'\nimport type { Context } from 'hono'\nimport { accepts } from 'hono/accepts'\nimport type { StatusCode } from 'hono/utils/http-status'\n\nimport type { MockServerOptions } from '@/types'\nimport { findPreferredResponseKey } from '@/utils/find-preferred-response-key'\n\n/**\n * Mock any response\n */\nexport function mockAnyResponse(c: Context, operation: OpenAPI.Operation, options: MockServerOptions) {\n // Call onRequest callback\n if (options?.onRequest) {\n options.onRequest({\n context: c,\n operation,\n })\n }\n\n // Response\n // default, 200, 201 \u2026\n const preferredResponseKey = findPreferredResponseKey(Object.keys(operation.responses ?? {}))\n const preferredResponse = preferredResponseKey ? operation.responses?.[preferredResponseKey] : null\n\n if (!preferredResponse) {\n c.status(500)\n\n return c.json({ error: 'No response defined for this operation.' })\n }\n\n // Status code\n const statusCode = Number.parseInt(\n preferredResponseKey === 'default' ? '200' : (preferredResponseKey ?? '200'),\n 10,\n ) as StatusCode\n\n // Headers\n const headers = preferredResponse?.headers ?? {}\n Object.keys(headers).forEach((header) => {\n const value = headers[header].schema ? getExampleFromSchema(headers[header].schema) : null\n if (value !== null) {\n c.header(header, value)\n }\n })\n\n // For 204 No Content responses, we should not set Content-Type and should return null body\n if (statusCode === 204) {\n c.status(statusCode)\n return c.body(null)\n }\n\n const supportedContentTypes = Object.keys(preferredResponse?.content ?? {})\n\n // If no content types are defined, return the status with no body\n if (supportedContentTypes.length === 0) {\n c.status(statusCode)\n return c.body(null)\n }\n\n // Content-Type\n const acceptedContentType = accepts(c, {\n header: 'Accept',\n supports: supportedContentTypes,\n default: supportedContentTypes.includes('application/json')\n ? 'application/json'\n : (supportedContentTypes[0] ?? 'text/plain;charset=UTF-8'),\n })\n\n c.header('Content-Type', acceptedContentType)\n\n const acceptedResponse = preferredResponse?.content?.[acceptedContentType]\n\n // Body\n const body = acceptedResponse?.example\n ? acceptedResponse.example\n : acceptedResponse?.schema\n ? getExampleFromSchema(acceptedResponse.schema, {\n emptyString: 'string',\n variables: c.req.param(),\n mode: 'read',\n })\n : null\n\n c.status(statusCode)\n\n return c.body(\n typeof body === 'object'\n ? // XML\n acceptedContentType?.includes('xml')\n ? json2xml(body)\n : // JSON\n JSON.stringify(body, null, 2)\n : // String\n body,\n )\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,gBAAgB;AACzB,SAAS,4BAA4B;AAGrC,SAAS,eAAe;AAIxB,SAAS,gCAAgC;AAKlC,SAAS,gBAAgB,GAAY,WAA8B,SAA4B;AAEpG,MAAI,SAAS,WAAW;AACtB,YAAQ,UAAU;AAAA,MAChB,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAIA,QAAM,uBAAuB,yBAAyB,OAAO,KAAK,UAAU,aAAa,CAAC,CAAC,CAAC;AAC5F,QAAM,oBAAoB,uBAAuB,UAAU,YAAY,oBAAoB,IAAI;AAE/F,MAAI,CAAC,mBAAmB;AACtB,MAAE,OAAO,GAAG;AAEZ,WAAO,EAAE,KAAK,EAAE,OAAO,0CAA0C,CAAC;AAAA,EACpE;AAGA,QAAM,aAAa,OAAO;AAAA,IACxB,yBAAyB,YAAY,QAAS,wBAAwB;AAAA,IACtE;AAAA,EACF;AAGA,QAAM,UAAU,mBAAmB,WAAW,CAAC;AAC/C,SAAO,KAAK,OAAO,EAAE,QAAQ,CAAC,WAAW;AACvC,UAAM,QAAQ,QAAQ,MAAM,EAAE,SAAS,qBAAqB,QAAQ,MAAM,EAAE,MAAM,IAAI;AACtF,QAAI,UAAU,MAAM;AAClB,QAAE,OAAO,QAAQ,KAAK;AAAA,IACxB;AAAA,EACF,CAAC;AAGD,MAAI,eAAe,KAAK;AACtB,MAAE,OAAO,UAAU;AACnB,WAAO,EAAE,KAAK,IAAI;AAAA,EACpB;AAEA,QAAM,wBAAwB,OAAO,KAAK,mBAAmB,WAAW,CAAC,CAAC;AAG1E,MAAI,sBAAsB,WAAW,GAAG;AACtC,MAAE,OAAO,UAAU;AACnB,WAAO,EAAE,KAAK,IAAI;AAAA,EACpB;AAGA,QAAM,sBAAsB,QAAQ,GAAG;AAAA,IACrC,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS,sBAAsB,SAAS,kBAAkB,IACtD,qBACC,sBAAsB,CAAC,KAAK;AAAA,EACnC,CAAC;AAED,IAAE,OAAO,gBAAgB,mBAAmB;AAE5C,QAAM,mBAAmB,mBAAmB,UAAU,mBAAmB;AAGzE,QAAM,OAAO,kBAAkB,UAC3B,iBAAiB,UACjB,kBAAkB,SAChB,qBAAqB,iBAAiB,QAAQ;AAAA,IAC5C,aAAa;AAAA,IACb,WAAW,EAAE,IAAI,MAAM;AAAA,IACvB,MAAM;AAAA,EACR,CAAC,IACD;AAEN,IAAE,OAAO,UAAU;AAEnB,SAAO,EAAE;AAAA,IACP,OAAO,SAAS;AAAA;AAAA,MAEZ,qBAAqB,SAAS,KAAK,IACjC,SAAS,IAAI;AAAA;AAAA,QAEb,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA,MAE9B;AAAA;AAAA,EACN;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -3,4 +3,4 @@ import type { Context } from 'hono';
|
|
|
3
3
|
* Responds with an HTML page that simulates an OAuth 2.0 authorization page.
|
|
4
4
|
*/
|
|
5
5
|
export declare function respondWithAuthorizePage(c: Context, title?: string): Response;
|
|
6
|
-
//# sourceMappingURL=
|
|
6
|
+
//# sourceMappingURL=respond-with-authorize-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond-with-authorize-page.d.ts","sourceRoot":"","sources":["../../src/routes/respond-with-authorize-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAKnC;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,SAAK,YA2C9D"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/routes/
|
|
3
|
+
"sources": ["../../src/routes/respond-with-authorize-page.ts"],
|
|
4
4
|
"sourcesContent": ["import type { Context } from 'hono'\n\n/** Always responds with this code */\nconst EXAMPLE_AUTHORIZATION_CODE = 'super-secret-token'\n\n/**\n * Responds with an HTML page that simulates an OAuth 2.0 authorization page.\n */\nexport function respondWithAuthorizePage(c: Context, title = '') {\n const redirectUri = c.req.query('redirect_uri')\n const state = c.req.query('state')\n\n if (!redirectUri) {\n return c.html(\n generateErrorHtml(\n 'Missing redirect_uri parameter',\n 'This parameter is required for the OAuth 2.0 authorization flow to function correctly. Please provide a valid redirect URI in your request.',\n ),\n 400,\n )\n }\n\n try {\n // Validate redirect URI against allowed domains\n const redirectUrl = new URL(redirectUri)\n\n redirectUrl.searchParams.set('code', EXAMPLE_AUTHORIZATION_CODE)\n\n if (state) {\n redirectUrl.searchParams.set('state', state)\n }\n\n const deniedUrl = new URL(redirectUri)\n if (state) {\n deniedUrl.searchParams.set('state', state)\n }\n deniedUrl.searchParams.set('error', 'access_denied')\n deniedUrl.searchParams.set('error_description', 'User has denied the authorization request')\n\n const htmlContent = generateAuthorizationHtml(redirectUrl.toString(), deniedUrl.toString(), title)\n\n return c.html(htmlContent)\n } catch {\n return c.html(\n generateErrorHtml(\n 'Invalid redirect_uri format',\n 'Please provide a valid URL. The redirect_uri parameter must be a properly formatted URL that includes the protocol (e.g., https://) and a valid domain. This is essential for the OAuth 2.0 flow to securely redirect after authorization.',\n ),\n 400,\n )\n }\n}\n\nfunction generateAuthorizationHtml(redirectUrl: string, deniedUrl: string, title = '') {\n return `\n<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>OAuth 2.0 Authorization</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n </head>\n <body class=\"flex justify-center items-center h-screen bg-gray-100\">\n\n <div class=\"flex flex-col\">\n <div class=\"mb-5 flex justify-center items-center gap-2\">\n <img src=\"https://scalar.com/logo-dark.svg\" class=\"w-6 inline-block\" />\n <div class=\"font-medium truncate max-w-[26ch] text-lg\">\n ${title}\n </div>\n </div>\n <div class=\"bg-gray-50 rounded-lg p-1 rounded-lg w-[28rem] shadow\">\n <div class=\"\">\n <h1 class=\"text font-medium text-gray-800 px-6 pt-2 pb-3 flex gap-3 rounded-t-lg\">\n OAuth 2.0 Authorization\n </h1>\n <div class=\"bg-white rounded\">\n <div class=\"text-gray-600 text-base px-6 py-5 flex flex-col gap-3\">\n <p>\n This application is requesting access to your account. By granting authorization, you allow the application to perform certain actions on your behalf.\n </p>\n <p>\n If you're comfortable with the access being requested, click the button below to grant authorization:\n </p>\n </div>\n <div class=\"px-6 py-4 pt-0 flex justify-between\">\n <a href=\"${deniedUrl}\" class=\"inline-block px-6 py-2 text-gray-600 rounded border\" aria-label=\"Cancel authorization\">\n Cancel\n </a>\n <a href=\"${redirectUrl}\" class=\"inline-block px-6 py-2 bg-black text-white rounded transition-colors duration-300 hover:bg-gray-800\" aria-label=\"Authorize application\">\n Authorize\n </a>\n </div>\n </div>\n </div>\n </div>\n\n <p class=\"text-xs text-gray-400 mt-5 text-center\">\n This authorization page is provided by @scalar/mock-server\n </p>\n\n </div>\n </body>\n</html>\n `\n}\n\nfunction generateErrorHtml(title: string, message: string) {\n return `<html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>OAuth 2.0 Authorization</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n </head>\n <body>\n <div class=\"p-4 m-8 flex flex-col gap-4 text-lg\">\n <h1 class=\"font-bold\">\n Error: ${title}\n </h1>\n <p>\n ${message}\n </p>\n <p>\n Example: <code class=\"bg-gray-100 py-1 px-2 rounded text-base\"><a href=\"?redirect_uri=https://example.com/callback\">?redirect_uri=https://example.com/callback</a></code>\n </p>\n </div>\n </body>\n</html>`\n}\n"],
|
|
5
5
|
"mappings": "AAGA,MAAM,6BAA6B;AAK5B,SAAS,yBAAyB,GAAY,QAAQ,IAAI;AAC/D,QAAM,cAAc,EAAE,IAAI,MAAM,cAAc;AAC9C,QAAM,QAAQ,EAAE,IAAI,MAAM,OAAO;AAEjC,MAAI,CAAC,aAAa;AAChB,WAAO,EAAE;AAAA,MACP;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,cAAc,IAAI,IAAI,WAAW;AAEvC,gBAAY,aAAa,IAAI,QAAQ,0BAA0B;AAE/D,QAAI,OAAO;AACT,kBAAY,aAAa,IAAI,SAAS,KAAK;AAAA,IAC7C;AAEA,UAAM,YAAY,IAAI,IAAI,WAAW;AACrC,QAAI,OAAO;AACT,gBAAU,aAAa,IAAI,SAAS,KAAK;AAAA,IAC3C;AACA,cAAU,aAAa,IAAI,SAAS,eAAe;AACnD,cAAU,aAAa,IAAI,qBAAqB,2CAA2C;AAE3F,UAAM,cAAc,0BAA0B,YAAY,SAAS,GAAG,UAAU,SAAS,GAAG,KAAK;AAEjG,WAAO,EAAE,KAAK,WAAW;AAAA,EAC3B,QAAQ;AACN,WAAO,EAAE;AAAA,MACP;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,0BAA0B,aAAqB,WAAmB,QAAQ,IAAI;AACrF,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAeG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAkBQ,SAAS;AAAA;AAAA;AAAA,yBAGT,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBpC;AAEA,SAAS,kBAAkB,OAAe,SAAiB;AACzD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAWQ,KAAK;AAAA;AAAA;AAAA,UAGZ,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQjB;",
|
|
6
6
|
"names": []
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond-with-openapi-document.d.ts","sourceRoot":"","sources":["../../src/routes/respond-with-openapi-document.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,CAAC,EAAE,OAAO,EACV,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpC,MAAM,GAAE,MAAM,GAAG,MAAe;;;;;;;;;;;;;;;;iBAwCjC"}
|
package/dist/routes/{respondWithOpenApiDocument.js.map → respond-with-openapi-document.js.map}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/routes/
|
|
3
|
+
"sources": ["../../src/routes/respond-with-openapi-document.ts"],
|
|
4
4
|
"sourcesContent": ["import { normalize, toYaml } from '@scalar/openapi-parser'\nimport type { Context } from 'hono'\n\n/**\n * OpenAPI endpoints\n */\nexport function respondWithOpenApiDocument(\n c: Context,\n input?: string | Record<string, any>,\n format: 'json' | 'yaml' = 'json',\n) {\n if (!input) {\n return c.text('Not found', 404)\n }\n\n try {\n const document = normalize(input)\n\n // JSON\n if (format === 'json') {\n return c.json(document)\n }\n\n // YAML\n try {\n const yamlDocument = toYaml(normalize(document))\n\n c.header('Content-Type', 'text/yaml')\n return c.text(yamlDocument, 200, {\n 'Content-Type': 'application/yaml; charset=UTF-8',\n })\n } catch (error) {\n return c.json(\n {\n error: 'Failed to convert document to YAML',\n message: error instanceof Error ? error.message : 'Unknown error occurred',\n },\n 500,\n )\n }\n } catch (error) {\n return c.json(\n {\n error: 'Failed to parse OpenAPI document',\n message: error instanceof Error ? error.message : 'Unknown error occurred',\n },\n 400,\n )\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,WAAW,cAAc;AAM3B,SAAS,2BACd,GACA,OACA,SAA0B,QAC1B;AACA,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,KAAK,aAAa,GAAG;AAAA,EAChC;AAEA,MAAI;AACF,UAAM,WAAW,UAAU,KAAK;AAGhC,QAAI,WAAW,QAAQ;AACrB,aAAO,EAAE,KAAK,QAAQ;AAAA,IACxB;AAGA,QAAI;AACF,YAAM,eAAe,OAAO,UAAU,QAAQ,CAAC;AAE/C,QAAE,OAAO,gBAAgB,WAAW;AACpC,aAAO,EAAE,KAAK,cAAc,KAAK;AAAA,QAC/B,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO,EAAE;AAAA,QACP;AAAA,UACE,OAAO;AAAA,UACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACpD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,WAAO,EAAE;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MACpD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
@@ -12,4 +12,4 @@ export declare function respondWithToken(c: Context): (Response & import("hono")
|
|
|
12
12
|
refresh_token: string;
|
|
13
13
|
scope: string;
|
|
14
14
|
}, import("hono/utils/http-status").ContentfulStatusCode, "json">);
|
|
15
|
-
//# sourceMappingURL=
|
|
15
|
+
//# sourceMappingURL=respond-with-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond-with-token.d.ts","sourceRoot":"","sources":["../../src/routes/respond-with-token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAKnC;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO;;;;;;;;;mEAmD1C"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/routes/
|
|
3
|
+
"sources": ["../../src/routes/respond-with-token.ts"],
|
|
4
4
|
"sourcesContent": ["import type { Context } from 'hono'\n\n/** Always responds with this token */\nconst EXAMPLE_ACCESS_TOKEN = 'super-secret-access-token'\n\n/**\n * Responds with a JSON object simulating an OAuth 2.0 token response.\n */\nexport function respondWithToken(c: Context) {\n const grantType = c.req.query('grant_type')\n\n if (!grantType) {\n return c.json(\n {\n error: 'invalid_request',\n error_description: 'Missing grant_type parameter',\n },\n 400,\n )\n }\n\n // Validate supported grant types\n const supportedGrantTypes = ['authorization_code', 'client_credentials', 'refresh_token']\n\n if (!supportedGrantTypes.includes(grantType)) {\n return c.json(\n {\n error: 'unsupported_grant_type',\n error_description: `Grant type must be one of: ${supportedGrantTypes.join(', ')}`,\n },\n 400,\n )\n }\n\n // Validate required parameters for each grant type\n if (grantType === 'authorization_code' && !c.req.query('code')) {\n return c.json(\n {\n error: 'invalid_request',\n error_description: 'Missing code parameter',\n },\n 400,\n )\n }\n\n // Simulate token generation\n const tokenResponse = {\n access_token: EXAMPLE_ACCESS_TOKEN,\n token_type: 'Bearer',\n expires_in: 3600,\n refresh_token: 'example-refresh-token',\n scope: c.req.query('scope') ?? 'read write',\n }\n\n // Security headers\n c.header('Cache-Control', 'no-store')\n c.header('Pragma', 'no-cache')\n\n return c.json(tokenResponse)\n}\n"],
|
|
5
5
|
"mappings": "AAGA,MAAM,uBAAuB;AAKtB,SAAS,iBAAiB,GAAY;AAC3C,QAAM,YAAY,EAAE,IAAI,MAAM,YAAY;AAE1C,MAAI,CAAC,WAAW;AACd,WAAO,EAAE;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,mBAAmB;AAAA,MACrB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,sBAAsB,CAAC,sBAAsB,sBAAsB,eAAe;AAExF,MAAI,CAAC,oBAAoB,SAAS,SAAS,GAAG;AAC5C,WAAO,EAAE;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,mBAAmB,8BAA8B,oBAAoB,KAAK,IAAI,CAAC;AAAA,MACjF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI,cAAc,wBAAwB,CAAC,EAAE,IAAI,MAAM,MAAM,GAAG;AAC9D,WAAO,EAAE;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,mBAAmB;AAAA,MACrB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,gBAAgB;AAAA,IACpB,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,OAAO,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,EACjC;AAGA,IAAE,OAAO,iBAAiB,UAAU;AACpC,IAAE,OAAO,UAAU,UAAU;AAE7B,SAAO,EAAE,KAAK,aAAa;AAC7B;",
|
|
6
6
|
"names": []
|
package/dist/types.d.ts
CHANGED
|
@@ -4,12 +4,25 @@ import type { Context } from 'hono';
|
|
|
4
4
|
export declare const httpMethods: readonly ["get", "put", "post", "delete", "options", "patch"];
|
|
5
5
|
/** Valid HTTP method */
|
|
6
6
|
export type HttpMethod = (typeof httpMethods)[number];
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Represents a partial object where at least one of the given properties is required.
|
|
9
|
+
*/
|
|
10
|
+
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & {
|
|
11
|
+
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
|
|
12
|
+
}[Keys];
|
|
13
|
+
type BaseMockServerOptions = {
|
|
8
14
|
/**
|
|
9
|
-
* The OpenAPI
|
|
15
|
+
* The OpenAPI document to use for mocking.
|
|
10
16
|
* Can be a string (URL or file path) or an object.
|
|
17
|
+
*
|
|
18
|
+
* @deprecated Use `document` instead
|
|
11
19
|
*/
|
|
12
|
-
specification
|
|
20
|
+
specification?: string | Record<string, any>;
|
|
21
|
+
/**
|
|
22
|
+
* The OpenAPI document to use for mocking.
|
|
23
|
+
* Can be a string (URL or file path) or an object.
|
|
24
|
+
*/
|
|
25
|
+
document?: string | Record<string, any>;
|
|
13
26
|
/**
|
|
14
27
|
* Callback function to be called before each request is processed.
|
|
15
28
|
*/
|
|
@@ -18,4 +31,6 @@ export type MockServerOptions = {
|
|
|
18
31
|
operation: OpenAPI.Operation;
|
|
19
32
|
}) => void;
|
|
20
33
|
};
|
|
34
|
+
export type MockServerOptions = RequireAtLeastOne<BaseMockServerOptions, 'specification' | 'document'>;
|
|
35
|
+
export {};
|
|
21
36
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,6CAA6C;AAC7C,eAAO,MAAM,WAAW,+DAAgE,CAAA;AAExF,wBAAwB;AACxB,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAErD,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,6CAA6C;AAC7C,eAAO,MAAM,WAAW,+DAAgE,CAAA;AAExF,wBAAwB;AACxB,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAErD;;GAEG;AACH,KAAK,iBAAiB,CAAC,CAAC,EAAE,IAAI,SAAS,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,GACzF;KACG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;CACzE,CAAC,IAAI,CAAC,CAAA;AAET,KAAK,qBAAqB,GAAG;IAC3B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE5C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAEvC;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAA;KAAE,KAAK,IAAI,CAAA;CAC/E,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,qBAAqB,EAAE,eAAe,GAAG,UAAU,CAAC,CAAA"}
|
package/dist/types.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/types.ts"],
|
|
4
|
-
"sourcesContent": ["import type { OpenAPI } from '@scalar/openapi-types'\nimport type { Context } from 'hono'\n\n/** Available HTTP methods for Hono routes */\nexport const httpMethods = ['get', 'put', 'post', 'delete', 'options', 'patch'] as const\n\n/** Valid HTTP method */\nexport type HttpMethod = (typeof httpMethods)[number]\n\
|
|
4
|
+
"sourcesContent": ["import type { OpenAPI } from '@scalar/openapi-types'\nimport type { Context } from 'hono'\n\n/** Available HTTP methods for Hono routes */\nexport const httpMethods = ['get', 'put', 'post', 'delete', 'options', 'patch'] as const\n\n/** Valid HTTP method */\nexport type HttpMethod = (typeof httpMethods)[number]\n\n/**\n * Represents a partial object where at least one of the given properties is required.\n */\ntype RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &\n {\n [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>\n }[Keys]\n\ntype BaseMockServerOptions = {\n /**\n * The OpenAPI document to use for mocking.\n * Can be a string (URL or file path) or an object.\n *\n * @deprecated Use `document` instead\n */\n specification?: string | Record<string, any>\n\n /**\n * The OpenAPI document to use for mocking.\n * Can be a string (URL or file path) or an object.\n */\n document?: string | Record<string, any>\n\n /**\n * Callback function to be called before each request is processed.\n */\n onRequest?: (data: { context: Context; operation: OpenAPI.Operation }) => void\n}\n\nexport type MockServerOptions = RequireAtLeastOne<BaseMockServerOptions, 'specification' | 'document'>\n"],
|
|
5
5
|
"mappings": "AAIO,MAAM,cAAc,CAAC,OAAO,OAAO,QAAQ,UAAU,WAAW,OAAO;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { OpenAPIV3, OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
2
|
/** Helper function create an OpenAPI document with security schemss */
|
|
3
3
|
export declare function createOpenApiDefinition(securitySchemes: Record<string, OpenAPIV3.SecuritySchemeObject | OpenAPIV3_1.SecuritySchemeObject>): OpenAPIV3_1.Document;
|
|
4
|
-
//# sourceMappingURL=
|
|
4
|
+
//# sourceMappingURL=create-openapi-definition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-openapi-definition.d.ts","sourceRoot":"","sources":["../../src/utils/create-openapi-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnE,uEAAuE;AACvE,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,oBAAoB,GAAG,WAAW,CAAC,oBAAoB,CAAC,GACjG,WAAW,CAAC,QAAQ,CAMtB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/utils/
|
|
3
|
+
"sources": ["../../src/utils/create-openapi-definition.ts"],
|
|
4
4
|
"sourcesContent": ["import type { OpenAPIV3, OpenAPIV3_1 } from '@scalar/openapi-types'\n\n/** Helper function create an OpenAPI document with security schemss */\nexport function createOpenApiDefinition(\n securitySchemes: Record<string, OpenAPIV3.SecuritySchemeObject | OpenAPIV3_1.SecuritySchemeObject>,\n): OpenAPIV3_1.Document {\n return {\n openapi: '3.1.1',\n info: { title: 'Test API', version: '1.0.0' },\n components: { securitySchemes },\n }\n}\n"],
|
|
5
5
|
"mappings": "AAGO,SAAS,wBACd,iBACsB;AACtB,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,EAAE,OAAO,YAAY,SAAS,QAAQ;AAAA,IAC5C,YAAY,EAAE,gBAAgB;AAAA,EAChC;AACF;",
|
|
6
6
|
"names": []
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-preferred-response-key.d.ts","sourceRoot":"","sources":["../../src/utils/find-preferred-response-key.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,sBAQ5D"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/utils/
|
|
3
|
+
"sources": ["../../src/utils/find-preferred-response-key.ts"],
|
|
4
4
|
"sourcesContent": ["/**\n * Find the preferred response key: default, 200, 201 \u2026\n */\nexport function findPreferredResponseKey(responses?: string[]) {\n return (\n // Regular status codes\n ['default', '200', '201', '204', '404', '500'].find((key) => responses?.includes(key) ?? false) ??\n // Lowest status code\n responses?.sort()[0] ??\n undefined\n )\n}\n"],
|
|
5
5
|
"mappings": "AAGO,SAAS,yBAAyB,WAAsB;AAC7D;AAAA;AAAA,IAEE,CAAC,WAAW,OAAO,OAAO,OAAO,OAAO,KAAK,EAAE,KAAK,CAAC,QAAQ,WAAW,SAAS,GAAG,KAAK,KAAK;AAAA,IAE9F,WAAW,KAAK,EAAE,CAAC,KACnB;AAAA;AAEJ;",
|
|
6
6
|
"names": []
|