@scalar/mock-server 0.9.8 → 0.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/create-mock-server.js +79 -68
  3. package/dist/index.js +1 -5
  4. package/dist/libs/store.js +66 -65
  5. package/dist/routes/mock-any-response.js +70 -63
  6. package/dist/routes/mock-handler-response.js +140 -100
  7. package/dist/routes/respond-with-authorize-page.js +89 -80
  8. package/dist/routes/respond-with-openapi-document.js +32 -35
  9. package/dist/routes/respond-with-token.js +40 -45
  10. package/dist/types.js +2 -5
  11. package/dist/utils/build-handler-context.js +83 -70
  12. package/dist/utils/build-seed-context.js +59 -52
  13. package/dist/utils/create-openapi-definition.js +7 -10
  14. package/dist/utils/execute-handler.js +16 -18
  15. package/dist/utils/execute-seed.js +22 -21
  16. package/dist/utils/find-preferred-response-key.js +9 -9
  17. package/dist/utils/get-open-auth-token-urls.js +45 -35
  18. package/dist/utils/get-operation.js +12 -12
  19. package/dist/utils/handle-authentication.js +106 -101
  20. package/dist/utils/hono-route-from-path.js +6 -6
  21. package/dist/utils/is-authentication-required.js +17 -15
  22. package/dist/utils/log-authentication-instructions.js +105 -110
  23. package/dist/utils/process-openapi-document.js +71 -58
  24. package/dist/utils/set-up-authentication-routes.js +80 -77
  25. package/dist/utils/store-wrapper.js +40 -39
  26. package/package.json +10 -14
  27. package/dist/create-mock-server.js.map +0 -7
  28. package/dist/index.js.map +0 -7
  29. package/dist/libs/store.js.map +0 -7
  30. package/dist/routes/mock-any-response.js.map +0 -7
  31. package/dist/routes/mock-handler-response.js.map +0 -7
  32. package/dist/routes/respond-with-authorize-page.js.map +0 -7
  33. package/dist/routes/respond-with-openapi-document.js.map +0 -7
  34. package/dist/routes/respond-with-token.js.map +0 -7
  35. package/dist/types.js.map +0 -7
  36. package/dist/utils/build-handler-context.js.map +0 -7
  37. package/dist/utils/build-seed-context.js.map +0 -7
  38. package/dist/utils/create-openapi-definition.js.map +0 -7
  39. package/dist/utils/execute-handler.js.map +0 -7
  40. package/dist/utils/execute-seed.js.map +0 -7
  41. package/dist/utils/find-preferred-response-key.js.map +0 -7
  42. package/dist/utils/get-open-auth-token-urls.js.map +0 -7
  43. package/dist/utils/get-operation.js.map +0 -7
  44. package/dist/utils/handle-authentication.js.map +0 -7
  45. package/dist/utils/hono-route-from-path.js.map +0 -7
  46. package/dist/utils/is-authentication-required.js.map +0 -7
  47. package/dist/utils/log-authentication-instructions.js.map +0 -7
  48. package/dist/utils/process-openapi-document.js.map +0 -7
  49. package/dist/utils/set-up-authentication-routes.js.map +0 -7
  50. package/dist/utils/store-wrapper.js.map +0 -7
@@ -1,110 +1,115 @@
1
- import { getCookie } from "hono/cookie";
2
- function handleAuthentication(schema, operation) {
3
- return async (c, next) => {
4
- const operationSecuritySchemes = operation?.security || schema?.security;
5
- if (operationSecuritySchemes && operationSecuritySchemes.length > 0) {
6
- let isAuthenticated = false;
7
- let authScheme = "";
8
- for (const securityRequirement of operationSecuritySchemes) {
9
- let securitySchemeAuthenticated = true;
10
- for (const [schemeName] of Object.entries(securityRequirement)) {
11
- const scheme = schema?.components?.securitySchemes?.[schemeName];
12
- if (scheme && "$ref" in scheme) {
13
- continue;
14
- }
15
- if (scheme && "type" in scheme) {
16
- const securityScheme = scheme;
17
- switch (securityScheme.type) {
18
- case "http":
19
- if ("scheme" in securityScheme && securityScheme.scheme === "basic") {
20
- authScheme = "Basic";
21
- const authHeader = c.req.header("Authorization");
22
- if (authHeader?.startsWith("Basic ")) {
23
- isAuthenticated = true;
24
- }
25
- } else if ("scheme" in securityScheme && securityScheme.scheme === "bearer") {
26
- authScheme = "Bearer";
27
- const authHeader = c.req.header("Authorization");
28
- if (authHeader?.startsWith("Bearer ")) {
29
- isAuthenticated = true;
30
- }
31
- }
32
- break;
33
- case "apiKey":
34
- if ("name" in securityScheme && "in" in securityScheme && securityScheme.name) {
35
- authScheme = `ApiKey ${securityScheme.name}`;
36
- if (securityScheme.in === "header") {
37
- const apiKey = c.req.header(securityScheme.name);
38
- if (apiKey) {
39
- isAuthenticated = true;
1
+ import { getCookie } from 'hono/cookie';
2
+ /**
3
+ * Handles authentication for incoming requests based on the OpenAPI document.
4
+ */
5
+ export function handleAuthentication(schema, operation) {
6
+ return async (c, next) => {
7
+ const operationSecuritySchemes = operation?.security || schema?.security;
8
+ if (operationSecuritySchemes && operationSecuritySchemes.length > 0) {
9
+ let isAuthenticated = false;
10
+ let authScheme = '';
11
+ for (const securityRequirement of operationSecuritySchemes) {
12
+ let securitySchemeAuthenticated = true;
13
+ for (const [schemeName] of Object.entries(securityRequirement)) {
14
+ const scheme = schema?.components?.securitySchemes?.[schemeName];
15
+ // Skip if scheme is a reference object (should be dereferenced already, but check to be safe)
16
+ if (scheme && '$ref' in scheme) {
17
+ continue;
40
18
  }
41
- } else if (securityScheme.in === "query") {
42
- const apiKey = c.req.query(securityScheme.name);
43
- if (apiKey) {
44
- isAuthenticated = true;
19
+ if (scheme && 'type' in scheme) {
20
+ const securityScheme = scheme;
21
+ switch (securityScheme.type) {
22
+ case 'http':
23
+ if ('scheme' in securityScheme && securityScheme.scheme === 'basic') {
24
+ authScheme = 'Basic';
25
+ const authHeader = c.req.header('Authorization');
26
+ if (authHeader?.startsWith('Basic ')) {
27
+ isAuthenticated = true;
28
+ }
29
+ }
30
+ else if ('scheme' in securityScheme && securityScheme.scheme === 'bearer') {
31
+ authScheme = 'Bearer';
32
+ const authHeader = c.req.header('Authorization');
33
+ if (authHeader?.startsWith('Bearer ')) {
34
+ isAuthenticated = true;
35
+ }
36
+ }
37
+ break;
38
+ case 'apiKey':
39
+ if ('name' in securityScheme && 'in' in securityScheme && securityScheme.name) {
40
+ authScheme = `ApiKey ${securityScheme.name}`;
41
+ if (securityScheme.in === 'header') {
42
+ const apiKey = c.req.header(securityScheme.name);
43
+ if (apiKey) {
44
+ isAuthenticated = true;
45
+ }
46
+ }
47
+ else if (securityScheme.in === 'query') {
48
+ const apiKey = c.req.query(securityScheme.name);
49
+ if (apiKey) {
50
+ isAuthenticated = true;
51
+ }
52
+ }
53
+ else if (securityScheme.in === 'cookie') {
54
+ const apiKey = getCookie(c, securityScheme.name);
55
+ if (apiKey) {
56
+ isAuthenticated = true;
57
+ }
58
+ }
59
+ }
60
+ break;
61
+ case 'oauth2':
62
+ authScheme = 'Bearer';
63
+ // Handle OAuth 2.0 flows, including password grant
64
+ if (c.req.header('Authorization')?.startsWith('Bearer ')) {
65
+ isAuthenticated = true;
66
+ }
67
+ break;
68
+ case 'openIdConnect':
69
+ authScheme = 'Bearer';
70
+ // Handle OpenID Connect similar to OAuth2
71
+ if (c.req.header('Authorization')?.startsWith('Bearer ')) {
72
+ isAuthenticated = true;
73
+ }
74
+ break;
75
+ }
45
76
  }
46
- } else if (securityScheme.in === "cookie") {
47
- const apiKey = getCookie(c, securityScheme.name);
48
- if (apiKey) {
49
- isAuthenticated = true;
77
+ if (!isAuthenticated) {
78
+ securitySchemeAuthenticated = false;
79
+ break;
50
80
  }
51
- }
52
81
  }
53
- break;
54
- case "oauth2":
55
- authScheme = "Bearer";
56
- if (c.req.header("Authorization")?.startsWith("Bearer ")) {
57
- isAuthenticated = true;
82
+ if (securitySchemeAuthenticated) {
83
+ isAuthenticated = true;
84
+ break;
58
85
  }
59
- break;
60
- case "openIdConnect":
61
- authScheme = "Bearer";
62
- if (c.req.header("Authorization")?.startsWith("Bearer ")) {
63
- isAuthenticated = true;
86
+ }
87
+ if (!isAuthenticated) {
88
+ let wwwAuthenticateValue = authScheme;
89
+ if (authScheme.startsWith('ApiKey')) {
90
+ wwwAuthenticateValue += ` realm="Scalar Mock Server", error="invalid_token", error_description="Invalid or missing API key"`;
64
91
  }
65
- break;
92
+ else {
93
+ switch (authScheme) {
94
+ case 'Basic':
95
+ wwwAuthenticateValue += ' realm="Scalar Mock Server", charset="UTF-8"';
96
+ break;
97
+ case 'Bearer':
98
+ wwwAuthenticateValue +=
99
+ ' realm="Scalar Mock Server", error="invalid_token", error_description="The access token is invalid or has expired"';
100
+ break;
101
+ default:
102
+ wwwAuthenticateValue = 'Bearer realm="Scalar Mock Server"';
103
+ }
104
+ }
105
+ c.header('WWW-Authenticate', wwwAuthenticateValue);
106
+ return c.json({
107
+ error: 'Unauthorized',
108
+ message: 'Authentication is required to access this resource.',
109
+ }, 401);
66
110
  }
67
- }
68
- if (!isAuthenticated) {
69
- securitySchemeAuthenticated = false;
70
- break;
71
- }
72
- }
73
- if (securitySchemeAuthenticated) {
74
- isAuthenticated = true;
75
- break;
76
- }
77
- }
78
- if (!isAuthenticated) {
79
- let wwwAuthenticateValue = authScheme;
80
- if (authScheme.startsWith("ApiKey")) {
81
- wwwAuthenticateValue += ` realm="Scalar Mock Server", error="invalid_token", error_description="Invalid or missing API key"`;
82
- } else {
83
- switch (authScheme) {
84
- case "Basic":
85
- wwwAuthenticateValue += ' realm="Scalar Mock Server", charset="UTF-8"';
86
- break;
87
- case "Bearer":
88
- wwwAuthenticateValue += ' realm="Scalar Mock Server", error="invalid_token", error_description="The access token is invalid or has expired"';
89
- break;
90
- default:
91
- wwwAuthenticateValue = 'Bearer realm="Scalar Mock Server"';
92
- }
93
111
  }
94
- c.header("WWW-Authenticate", wwwAuthenticateValue);
95
- return c.json(
96
- {
97
- error: "Unauthorized",
98
- message: "Authentication is required to access this resource."
99
- },
100
- 401
101
- );
102
- }
103
- }
104
- await next();
105
- };
112
+ // If all checks pass, continue to the next middleware
113
+ await next();
114
+ };
106
115
  }
107
- export {
108
- handleAuthentication
109
- };
110
- //# sourceMappingURL=handle-authentication.js.map
@@ -1,7 +1,7 @@
1
- function honoRouteFromPath(path) {
2
- return path.replace(/{/g, ":").replace(/}/g, "");
1
+ /**
2
+ * Convert path to route
3
+ * Example: /posts/{id} -> /posts/:id
4
+ */
5
+ export function honoRouteFromPath(path) {
6
+ return path.replace(/{/g, ':').replace(/}/g, '');
3
7
  }
4
- export {
5
- honoRouteFromPath
6
- };
7
- //# sourceMappingURL=hono-route-from-path.js.map
@@ -1,16 +1,18 @@
1
- function isAuthenticationRequired(security) {
2
- if (!security) {
3
- return false;
4
- }
5
- if (Array.isArray(security) && !security.length) {
6
- return false;
7
- }
8
- if ((security ?? []).some((securityRequirement) => !Object.keys(securityRequirement).length)) {
9
- return false;
10
- }
11
- return true;
1
+ /**
2
+ * Check whether the given security scheme key is in the `security` configuration for this operation.
3
+ */
4
+ export function isAuthenticationRequired(security) {
5
+ // If security is not defined, auth is not required.
6
+ if (!security) {
7
+ return false;
8
+ }
9
+ // Don't require auth if security is just an empty array []
10
+ if (Array.isArray(security) && !security.length) {
11
+ return false;
12
+ }
13
+ // Includes empty object = auth is not required
14
+ if ((security ?? []).some((securityRequirement) => !Object.keys(securityRequirement).length)) {
15
+ return false;
16
+ }
17
+ return true;
12
18
  }
13
- export {
14
- isAuthenticationRequired
15
- };
16
- //# sourceMappingURL=is-authentication-required.js.map
@@ -1,118 +1,113 @@
1
- import { getPathFromUrl } from "./get-open-auth-token-urls.js";
2
- function logAuthenticationInstructions(securitySchemes) {
3
- if (!securitySchemes || Object.keys(securitySchemes).length === 0) {
4
- return;
5
- }
6
- console.log("Authentication:");
7
- console.log();
8
- Object.entries(securitySchemes).forEach(([_, scheme]) => {
9
- switch (scheme.type) {
10
- case "apiKey":
11
- if (scheme.in === "header") {
12
- console.log("\u2705 API Key Authentication");
13
- console.log(` Use any API key in the ${scheme.name} header`);
14
- console.log();
15
- console.log(` ${scheme.name}: YOUR_API_KEY_HERE`);
16
- console.log();
17
- } else if (scheme.in === "query") {
18
- console.log("\u2705 API Key Authentication");
19
- console.log(` Use any API key in the ${scheme.name} query parameter:`);
20
- console.log();
21
- console.log(` ?${scheme.name}=YOUR_API_KEY_HERE`);
22
- console.log();
23
- } else if (scheme.in === "cookie") {
24
- console.log("\u2705 API Key Authentication");
25
- console.log(` Use any API key in the ${scheme.name} cookie:`);
26
- console.log();
27
- console.log(` Cookie: ${scheme.name}=YOUR_API_KEY_HERE`);
28
- console.log();
29
- } else {
30
- console.error(`\u274C Unsupported API Key Location: ${scheme.in}`);
31
- }
32
- break;
33
- case "http":
34
- if (scheme.scheme === "basic") {
35
- console.log("\u2705 HTTP Basic Authentication");
36
- console.log(' Use an Authorization header with any credentials ("username:password" in base64):');
37
- console.log();
38
- console.log(" Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=");
39
- console.log();
40
- } else if (scheme.scheme === "bearer") {
41
- console.log("\u2705 Bearer Token Authentication");
42
- console.log(" Use an Authorization header with any bearer token");
43
- console.log();
44
- console.log(" Authorization: Bearer YOUR_TOKEN_HERE");
45
- console.log();
46
- } else {
47
- console.error("\u274C Unknown Security Scheme:", scheme);
48
- }
49
- break;
50
- case "oauth2":
51
- if (scheme.flows) {
52
- Object.keys(scheme.flows).forEach((flow) => {
53
- switch (flow) {
54
- case "implicit":
55
- console.log("\u2705 OAuth 2.0 Implicit Flow");
56
- console.log(" Use the following URL to initiate the OAuth 2.0 Implicit Flow:");
57
- console.log();
58
- console.log(
59
- ` GET ${scheme?.flows?.implicit?.authorizationUrl || "/oauth/authorize"}?response_type=token&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=YOUR_SCOPES`
60
- );
61
- console.log();
1
+ import { getPathFromUrl } from './get-open-auth-token-urls.js';
2
+ /**
3
+ * Log authentication instructions for different security schemes
4
+ */
5
+ export function logAuthenticationInstructions(securitySchemes) {
6
+ if (!securitySchemes || Object.keys(securitySchemes).length === 0) {
7
+ return;
8
+ }
9
+ console.log('Authentication:');
10
+ console.log();
11
+ Object.entries(securitySchemes).forEach(([_, scheme]) => {
12
+ switch (scheme.type) {
13
+ case 'apiKey':
14
+ if (scheme.in === 'header') {
15
+ console.log('✅ API Key Authentication');
16
+ console.log(` Use any API key in the ${scheme.name} header`);
17
+ console.log();
18
+ console.log(` ${scheme.name}: YOUR_API_KEY_HERE`);
19
+ console.log();
20
+ }
21
+ else if (scheme.in === 'query') {
22
+ console.log('✅ API Key Authentication');
23
+ console.log(` Use any API key in the ${scheme.name} query parameter:`);
24
+ console.log();
25
+ console.log(` ?${scheme.name}=YOUR_API_KEY_HERE`);
26
+ console.log();
27
+ }
28
+ else if (scheme.in === 'cookie') {
29
+ console.log('✅ API Key Authentication');
30
+ console.log(` Use any API key in the ${scheme.name} cookie:`);
31
+ console.log();
32
+ console.log(` Cookie: ${scheme.name}=YOUR_API_KEY_HERE`);
33
+ console.log();
34
+ }
35
+ else {
36
+ console.error(`❌ Unsupported API Key Location: ${scheme.in}`);
37
+ }
62
38
  break;
63
- case "password":
64
- console.log("\u2705 OAuth 2.0 Password Flow");
65
- console.log(" Use the following URL to obtain an access token:");
66
- console.log();
67
- console.log(` POST ${getPathFromUrl(scheme?.flows?.password?.tokenUrl || "/oauth/token")}`);
68
- console.log(" Content-Type: application/x-www-form-urlencoded");
69
- console.log();
70
- console.log(
71
- " grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
72
- );
73
- console.log();
39
+ case 'http':
40
+ if (scheme.scheme === 'basic') {
41
+ console.log('✅ HTTP Basic Authentication');
42
+ console.log(' Use an Authorization header with any credentials ("username:password" in base64):');
43
+ console.log();
44
+ console.log(' Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=');
45
+ console.log();
46
+ }
47
+ else if (scheme.scheme === 'bearer') {
48
+ console.log('✅ Bearer Token Authentication');
49
+ console.log(' Use an Authorization header with any bearer token');
50
+ console.log();
51
+ console.log(' Authorization: Bearer YOUR_TOKEN_HERE');
52
+ console.log();
53
+ }
54
+ else {
55
+ console.error('❌ Unknown Security Scheme:', scheme);
56
+ }
74
57
  break;
75
- case "clientCredentials":
76
- console.log("\u2705 OAuth 2.0 Client Credentials Flow");
77
- console.log(" Use the following URL to obtain an access token:");
78
- console.log();
79
- console.log(` POST ${getPathFromUrl(scheme?.flows?.clientCredentials?.tokenUrl || "/oauth/token")}`);
80
- console.log(" Content-Type: application/x-www-form-urlencoded");
81
- console.log();
82
- console.log(
83
- " grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
84
- );
85
- console.log();
58
+ case 'oauth2':
59
+ if (scheme.flows) {
60
+ Object.keys(scheme.flows).forEach((flow) => {
61
+ switch (flow) {
62
+ case 'implicit':
63
+ console.log('✅ OAuth 2.0 Implicit Flow');
64
+ console.log(' Use the following URL to initiate the OAuth 2.0 Implicit Flow:');
65
+ console.log();
66
+ console.log(` GET ${scheme?.flows?.implicit?.authorizationUrl || '/oauth/authorize'}?response_type=token&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=YOUR_SCOPES`);
67
+ console.log();
68
+ break;
69
+ case 'password':
70
+ console.log('✅ OAuth 2.0 Password Flow');
71
+ console.log(' Use the following URL to obtain an access token:');
72
+ console.log();
73
+ console.log(` POST ${getPathFromUrl(scheme?.flows?.password?.tokenUrl || '/oauth/token')}`);
74
+ console.log(' Content-Type: application/x-www-form-urlencoded');
75
+ console.log();
76
+ console.log(' grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET');
77
+ console.log();
78
+ break;
79
+ case 'clientCredentials':
80
+ console.log('✅ OAuth 2.0 Client Credentials Flow');
81
+ console.log(' Use the following URL to obtain an access token:');
82
+ console.log();
83
+ console.log(` POST ${getPathFromUrl(scheme?.flows?.clientCredentials?.tokenUrl || '/oauth/token')}`);
84
+ console.log(' Content-Type: application/x-www-form-urlencoded');
85
+ console.log();
86
+ console.log(' grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET');
87
+ console.log();
88
+ break;
89
+ case 'authorizationCode':
90
+ console.log('✅ OAuth 2.0 Authorization Code Flow');
91
+ console.log(' Use the following URL to initiate the OAuth 2.0 Authorization Code Flow:');
92
+ console.log();
93
+ console.log(' GET', `${getPathFromUrl(scheme?.flows?.authorizationCode?.authorizationUrl || '/oauth/authorize')}?redirect_uri=https://YOUR_REDIRECT_URI_HERE`);
94
+ console.log();
95
+ break;
96
+ default:
97
+ console.warn(`Unsupported OAuth 2.0 flow: ${flow}`);
98
+ }
99
+ });
100
+ }
86
101
  break;
87
- case "authorizationCode":
88
- console.log("\u2705 OAuth 2.0 Authorization Code Flow");
89
- console.log(" Use the following URL to initiate the OAuth 2.0 Authorization Code Flow:");
102
+ case 'openIdConnect':
103
+ console.log('✅ OpenID Connect Authentication');
104
+ console.log(' Use the following OpenID Connect discovery URL:');
90
105
  console.log();
91
- console.log(
92
- " GET",
93
- `${getPathFromUrl(scheme?.flows?.authorizationCode?.authorizationUrl || "/oauth/authorize")}?redirect_uri=https://YOUR_REDIRECT_URI_HERE`
94
- );
106
+ console.log(` ${getPathFromUrl(scheme.openIdConnectUrl || '/.well-known/openid-configuration')}`);
95
107
  console.log();
96
108
  break;
97
- default:
98
- console.warn(`Unsupported OAuth 2.0 flow: ${flow}`);
99
- }
100
- });
109
+ default:
110
+ console.warn(`Unsupported security scheme type: ${scheme.type}`);
101
111
  }
102
- break;
103
- case "openIdConnect":
104
- console.log("\u2705 OpenID Connect Authentication");
105
- console.log(" Use the following OpenID Connect discovery URL:");
106
- console.log();
107
- console.log(` ${getPathFromUrl(scheme.openIdConnectUrl || "/.well-known/openid-configuration")}`);
108
- console.log();
109
- break;
110
- default:
111
- console.warn(`Unsupported security scheme type: ${scheme.type}`);
112
- }
113
- });
112
+ });
114
113
  }
115
- export {
116
- logAuthenticationInstructions
117
- };
118
- //# sourceMappingURL=log-authentication-instructions.js.map
@@ -1,59 +1,72 @@
1
- import { bundle } from "@scalar/json-magic/bundle";
2
- import { parseJson } from "@scalar/json-magic/bundle/plugins/node";
3
- import { parseYaml } from "@scalar/json-magic/bundle/plugins/node";
4
- import { readFiles } from "@scalar/json-magic/bundle/plugins/node";
5
- import { fetchUrls } from "@scalar/json-magic/bundle/plugins/node";
6
- import { dereference } from "@scalar/openapi-parser";
7
- import { upgrade } from "@scalar/openapi-upgrader";
8
- async function processOpenApiDocument(document) {
9
- if (!document || typeof document === "object" && Object.keys(document).length === 0) {
10
- return {
11
- openapi: "3.1.0",
12
- info: {
13
- title: "Mock API",
14
- version: "1.0.0"
15
- },
16
- paths: {}
17
- };
18
- }
19
- let bundled;
20
- try {
21
- bundled = await bundle(document, {
22
- plugins: [parseJson(), parseYaml(), readFiles(), fetchUrls()],
23
- treeShake: false
24
- });
25
- } catch (error) {
26
- throw new Error(`Failed to bundle OpenAPI document: ${error instanceof Error ? error.message : String(error)}`);
27
- }
28
- if (!bundled || typeof bundled !== "object") {
29
- throw new Error("Bundled document is invalid: expected an object");
30
- }
31
- let upgraded;
32
- try {
33
- upgraded = upgrade(bundled, "3.1");
34
- } catch (error) {
35
- throw new Error(
36
- `Failed to upgrade OpenAPI document to 3.1: ${error instanceof Error ? error.message : String(error)}`
37
- );
38
- }
39
- if (!upgraded) {
40
- throw new Error("Upgraded document is invalid: upgrade returned null or undefined");
41
- }
42
- const dereferenceResult = dereference(upgraded);
43
- if (dereferenceResult.errors && dereferenceResult.errors.length > 0) {
44
- const errorMessages = dereferenceResult.errors.map((err) => err.message).join(", ");
45
- throw new Error(`Failed to dereference OpenAPI document: ${errorMessages}`);
46
- }
47
- const schema = dereferenceResult.schema;
48
- if (!schema) {
49
- throw new Error("Dereference result does not contain a schema");
50
- }
51
- if (typeof schema !== "object") {
52
- throw new Error("Dereferenced schema is invalid: expected an object");
53
- }
54
- return schema;
1
+ import { bundle } from '@scalar/json-magic/bundle';
2
+ import { parseJson } from '@scalar/json-magic/bundle/plugins/node';
3
+ import { parseYaml } from '@scalar/json-magic/bundle/plugins/node';
4
+ import { readFiles } from '@scalar/json-magic/bundle/plugins/node';
5
+ import { fetchUrls } from '@scalar/json-magic/bundle/plugins/node';
6
+ import { dereference } from '@scalar/openapi-parser';
7
+ import { upgrade } from '@scalar/openapi-upgrader';
8
+ /**
9
+ * Processes an OpenAPI document by bundling external references, upgrading to OpenAPI 3.1,
10
+ * and dereferencing the document.
11
+ *
12
+ * @param document - The OpenAPI document to process. Can be a string (URL/path) or an object.
13
+ * @returns A promise that resolves to the dereferenced OpenAPI 3.1 document.
14
+ * @throws Error if the document cannot be processed or is invalid.
15
+ */
16
+ export async function processOpenApiDocument(document) {
17
+ // Handle empty/undefined input gracefully
18
+ if (!document || (typeof document === 'object' && Object.keys(document).length === 0)) {
19
+ // Return a minimal valid OpenAPI 3.1 document
20
+ return {
21
+ openapi: '3.1.0',
22
+ info: {
23
+ title: 'Mock API',
24
+ version: '1.0.0',
25
+ },
26
+ paths: {},
27
+ };
28
+ }
29
+ let bundled;
30
+ try {
31
+ // Bundle external references with Node.js plugins
32
+ // Include parseJson and parseYaml to handle string inputs
33
+ bundled = await bundle(document, {
34
+ plugins: [parseJson(), parseYaml(), readFiles(), fetchUrls()],
35
+ treeShake: false,
36
+ });
37
+ }
38
+ catch (error) {
39
+ throw new Error(`Failed to bundle OpenAPI document: ${error instanceof Error ? error.message : String(error)}`);
40
+ }
41
+ if (!bundled || typeof bundled !== 'object') {
42
+ throw new Error('Bundled document is invalid: expected an object');
43
+ }
44
+ let upgraded;
45
+ try {
46
+ // Upgrade to OpenAPI 3.1
47
+ upgraded = upgrade(bundled, '3.1');
48
+ }
49
+ catch (error) {
50
+ throw new Error(`Failed to upgrade OpenAPI document to 3.1: ${error instanceof Error ? error.message : String(error)}`);
51
+ }
52
+ if (!upgraded) {
53
+ throw new Error('Upgraded document is invalid: upgrade returned null or undefined');
54
+ }
55
+ // Dereference the document
56
+ const dereferenceResult = dereference(upgraded);
57
+ // Check for dereference errors
58
+ if (dereferenceResult.errors && dereferenceResult.errors.length > 0) {
59
+ const errorMessages = dereferenceResult.errors.map((err) => err.message).join(', ');
60
+ throw new Error(`Failed to dereference OpenAPI document: ${errorMessages}`);
61
+ }
62
+ // Extract the schema from the dereference result
63
+ const schema = dereferenceResult.schema;
64
+ if (!schema) {
65
+ throw new Error('Dereference result does not contain a schema');
66
+ }
67
+ // Ensure the schema is a valid OpenAPI 3.1 document
68
+ if (typeof schema !== 'object') {
69
+ throw new Error('Dereferenced schema is invalid: expected an object');
70
+ }
71
+ return schema;
55
72
  }
56
- export {
57
- processOpenApiDocument
58
- };
59
- //# sourceMappingURL=process-openapi-document.js.map