@scalar/mock-server 0.10.15 → 0.10.17
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 +10 -0
- package/dist/create-mock-server.d.ts.map +1 -1
- package/dist/create-mock-server.js +7 -3
- package/dist/routes/mock-any-response.d.ts.map +1 -1
- package/dist/routes/mock-any-response.js +8 -3
- package/dist/routes/mock-handler-response.d.ts.map +1 -1
- package/dist/routes/mock-handler-response.js +4 -2
- package/dist/routes/respond-with-openapi-document.d.ts +1 -11
- package/dist/routes/respond-with-openapi-document.d.ts.map +1 -1
- package/dist/routes/respond-with-openapi-document.js +2 -1
- package/dist/utils/build-handler-context.d.ts.map +1 -1
- package/dist/utils/build-handler-context.js +4 -2
- package/dist/utils/get-open-auth-token-urls.d.ts.map +1 -1
- package/dist/utils/get-open-auth-token-urls.js +5 -2
- package/dist/utils/handle-authentication.d.ts.map +1 -1
- package/dist/utils/handle-authentication.js +2 -5
- package/dist/utils/log-authentication-instructions.d.ts.map +1 -1
- package/dist/utils/log-authentication-instructions.js +7 -1
- package/dist/utils/process-openapi-document.d.ts +7 -2
- package/dist/utils/process-openapi-document.d.ts.map +1 -1
- package/dist/utils/process-openapi-document.js +12 -24
- package/dist/utils/set-up-authentication-routes.d.ts.map +1 -1
- package/dist/utils/set-up-authentication-routes.js +7 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @scalar/mock-server
|
|
2
2
|
|
|
3
|
+
## 0.10.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#9437](https://github.com/scalar/scalar/pull/9437): chore(mock-server): resolve OpenAPI references with `@scalar/workspace-store` instead of `@scalar/openapi-parser`
|
|
8
|
+
|
|
9
|
+
The mock server no longer eagerly dereferences the whole document. It now keeps `$ref` nodes intact via the `@scalar/json-magic` magic proxy and resolves them lazily with `getResolvedRef`/`getResolvedRefDeep` from `@scalar/workspace-store`. The `/openapi.{json,yaml}` endpoints use `@scalar/json-magic` and `yaml` for normalization and serialization. This drops the `@scalar/openapi-parser` dependency. Behavior is unchanged.
|
|
10
|
+
|
|
11
|
+
## 0.10.16
|
|
12
|
+
|
|
3
13
|
## 0.10.15
|
|
4
14
|
|
|
5
15
|
## 0.10.14
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-mock-server.d.ts","sourceRoot":"","sources":["../src/create-mock-server.ts"],"names":[],"mappings":"
|
|
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;AAgB5D;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,aAAa,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFtF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getResolvedRef, mergeSiblingReferences } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
1
2
|
import { Hono } from 'hono';
|
|
2
3
|
import { cors } from 'hono/cors';
|
|
3
4
|
import { buildSeedContext } from './utils/build-seed-context.js';
|
|
@@ -25,7 +26,8 @@ export async function createMockServer(configuration) {
|
|
|
25
26
|
const schemas = schema?.components?.schemas;
|
|
26
27
|
if (schemas) {
|
|
27
28
|
for (const [schemaName, schemaObject] of Object.entries(schemas)) {
|
|
28
|
-
|
|
29
|
+
// Merge `$ref` siblings so an `x-seed` placed next to a `$ref` is preserved (OpenAPI 3.1 semantics)
|
|
30
|
+
const seedCode = getResolvedRef(schemaObject, mergeSiblingReferences)?.['x-seed'];
|
|
29
31
|
if (seedCode && typeof seedCode === 'string') {
|
|
30
32
|
try {
|
|
31
33
|
// Check if collection is empty (idempotent seeding)
|
|
@@ -53,11 +55,13 @@ export async function createMockServer(configuration) {
|
|
|
53
55
|
/** Paths specified in the OpenAPI document */
|
|
54
56
|
const paths = schema?.paths ?? {};
|
|
55
57
|
Object.keys(paths).forEach((path) => {
|
|
56
|
-
|
|
58
|
+
// A path item may itself be a `$ref`, so resolve it before reading its operations.
|
|
59
|
+
const pathItem = getResolvedRef(paths[path]);
|
|
60
|
+
const methods = Object.keys(getOperations(pathItem));
|
|
57
61
|
/** Keys for all operations of a specified path */
|
|
58
62
|
methods.forEach((method) => {
|
|
59
63
|
const route = honoRouteFromPath(path);
|
|
60
|
-
const operation =
|
|
64
|
+
const operation = pathItem?.[method];
|
|
61
65
|
// Check if authentication is required for this operation
|
|
62
66
|
if (isAuthenticationRequired(operation.security)) {
|
|
63
67
|
app[method](route, handleAuthentication(schema, operation));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-any-response.d.ts","sourceRoot":"","sources":["../../src/routes/mock-any-response.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"mock-any-response.d.ts","sourceRoot":"","sources":["../../src/routes/mock-any-response.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAIxD,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,WAAW,CAAC,eAAe,EAAE,OAAO,EAAE,iBAAiB;;yPAwF7G"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { json2xml } from '@scalar/helpers/file/json2xml';
|
|
2
|
+
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
3
|
+
import { getResolvedRefDeep } from '@scalar/workspace-store/helpers/get-resolved-ref-deep';
|
|
2
4
|
import { getExampleFromSchema } from '@scalar/workspace-store/request-example';
|
|
3
5
|
import { accepts } from 'hono/accepts';
|
|
4
6
|
import { findPreferredResponseKey } from '../utils/find-preferred-response-key.js';
|
|
@@ -16,7 +18,7 @@ export function mockAnyResponse(c, operation, options) {
|
|
|
16
18
|
// Response
|
|
17
19
|
// default, 200, 201 …
|
|
18
20
|
const preferredResponseKey = findPreferredResponseKey(Object.keys(operation.responses ?? {}));
|
|
19
|
-
const preferredResponse = preferredResponseKey ? operation.responses?.[preferredResponseKey] : null;
|
|
21
|
+
const preferredResponse = preferredResponseKey ? getResolvedRef(operation.responses?.[preferredResponseKey]) : null;
|
|
20
22
|
if (!preferredResponse) {
|
|
21
23
|
c.status(500);
|
|
22
24
|
return c.json({ error: 'No response defined for this operation.' });
|
|
@@ -26,7 +28,10 @@ export function mockAnyResponse(c, operation, options) {
|
|
|
26
28
|
// Headers
|
|
27
29
|
const headers = preferredResponse?.headers ?? {};
|
|
28
30
|
Object.keys(headers).forEach((header) => {
|
|
29
|
-
const
|
|
31
|
+
const headerObject = getResolvedRef(headers[header]);
|
|
32
|
+
const value = headerObject?.schema
|
|
33
|
+
? getExampleFromSchema(getResolvedRefDeep(headerObject.schema))
|
|
34
|
+
: null;
|
|
30
35
|
if (value !== null) {
|
|
31
36
|
c.header(header, value);
|
|
32
37
|
}
|
|
@@ -56,7 +61,7 @@ export function mockAnyResponse(c, operation, options) {
|
|
|
56
61
|
const body = acceptedResponse?.example
|
|
57
62
|
? acceptedResponse.example
|
|
58
63
|
: acceptedResponse?.schema
|
|
59
|
-
? getExampleFromSchema(acceptedResponse.schema, {
|
|
64
|
+
? getExampleFromSchema(getResolvedRefDeep(acceptedResponse.schema), {
|
|
60
65
|
emptyString: 'string',
|
|
61
66
|
variables: c.req.param(),
|
|
62
67
|
mode: 'read',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-handler-response.d.ts","sourceRoot":"","sources":["../../src/routes/mock-handler-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"mock-handler-response.d.ts","sourceRoot":"","sources":["../../src/routes/mock-handler-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAIxD,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;AAoHhD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,CAAC,EAAE,OAAO,EACV,SAAS,EAAE,WAAW,CAAC,eAAe,EACtC,OAAO,EAAE,iBAAiB,gMAkE3B"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
2
|
+
import { getResolvedRefDeep } from '@scalar/workspace-store/helpers/get-resolved-ref-deep';
|
|
1
3
|
import { getExampleFromSchema } from '@scalar/workspace-store/request-example';
|
|
2
4
|
import { accepts } from 'hono/accepts';
|
|
3
5
|
import { buildHandlerContext } from '../utils/build-handler-context.js';
|
|
@@ -11,7 +13,7 @@ function getExampleFromResponse(c, statusCode, responses) {
|
|
|
11
13
|
return null;
|
|
12
14
|
}
|
|
13
15
|
const statusCodeStr = statusCode.toString();
|
|
14
|
-
const response = responses[statusCodeStr] || responses.default;
|
|
16
|
+
const response = getResolvedRef(responses[statusCodeStr] || responses.default);
|
|
15
17
|
if (!response) {
|
|
16
18
|
return null;
|
|
17
19
|
}
|
|
@@ -36,7 +38,7 @@ function getExampleFromResponse(c, statusCode, responses) {
|
|
|
36
38
|
return acceptedResponse.example !== undefined
|
|
37
39
|
? acceptedResponse.example
|
|
38
40
|
: acceptedResponse.schema
|
|
39
|
-
? getExampleFromSchema(acceptedResponse.schema, {
|
|
41
|
+
? getExampleFromSchema(getResolvedRefDeep(acceptedResponse.schema), {
|
|
40
42
|
emptyString: 'string',
|
|
41
43
|
variables: c.req.param(),
|
|
42
44
|
mode: 'read',
|
|
@@ -2,17 +2,7 @@ import type { Context } from 'hono';
|
|
|
2
2
|
/**
|
|
3
3
|
* OpenAPI endpoints
|
|
4
4
|
*/
|
|
5
|
-
export declare function respondWithOpenApiDocument(c: Context, input?: string | Record<string, any>, format?: 'json' | 'yaml'): (Response & import("hono").TypedResponse<"Not found", 404, "text">) | (Response & import("hono").TypedResponse<{
|
|
6
|
-
[x: string]: import("hono/utils/types").JSONValue;
|
|
7
|
-
} | {
|
|
8
|
-
dir: string;
|
|
9
|
-
isEntrypoint: boolean;
|
|
10
|
-
references: string[];
|
|
11
|
-
filename: string;
|
|
12
|
-
specification: {
|
|
13
|
-
[x: string]: import("hono/utils/types").JSONValue;
|
|
14
|
-
};
|
|
15
|
-
}[], import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<string, 200, "text">) | (Response & import("hono").TypedResponse<{
|
|
5
|
+
export declare function respondWithOpenApiDocument(c: Context, input?: string | Record<string, any>, format?: 'json' | 'yaml'): (Response & import("hono").TypedResponse<"Not found", 404, "text">) | (Response & import("hono").TypedResponse<import("hono/utils/types").JSONValue, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<string, 200, "text">) | (Response & import("hono").TypedResponse<{
|
|
16
6
|
error: string;
|
|
17
7
|
message: string;
|
|
18
8
|
}, 500, "json">) | (Response & import("hono").TypedResponse<{
|
|
@@ -1 +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;
|
|
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;AAGnC;;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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-handler-context.d.ts","sourceRoot":"","sources":["../../src/utils/build-handler-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"build-handler-context.d.ts","sourceRoot":"","sources":["../../src/utils/build-handler-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAIxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAInC,OAAO,EAAE,KAAK,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEjF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,cAAc,CAAC,CAAA;IAC5D,KAAK,EAAE,OAAO,KAAK,CAAA;IACnB,GAAG,EAAE;QACH,IAAI,EAAE,GAAG,CAAA;QACT,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAChC,CAAA;IACD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACzB,CAAA;AAED;;GAEG;AACH,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE,cAAc,CAAA;IACvB,QAAQ,EAAE,sBAAsB,CAAA;CACjC,CAAA;AAuDD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,CAAC,EAAE,OAAO,EACV,SAAS,CAAC,EAAE,WAAW,CAAC,eAAe,GACtC,OAAO,CAAC,oBAAoB,CAAC,CA4C/B"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { faker } from '@faker-js/faker';
|
|
2
|
+
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
3
|
+
import { getResolvedRefDeep } from '@scalar/workspace-store/helpers/get-resolved-ref-deep';
|
|
2
4
|
import { getExampleFromSchema } from '@scalar/workspace-store/request-example';
|
|
3
5
|
import { accepts } from 'hono/accepts';
|
|
4
6
|
import { store } from '../libs/store.js';
|
|
@@ -11,7 +13,7 @@ function getExampleFromResponse(c, statusCode, responses) {
|
|
|
11
13
|
if (!responses) {
|
|
12
14
|
return null;
|
|
13
15
|
}
|
|
14
|
-
const response = responses[statusCode] || responses.default;
|
|
16
|
+
const response = getResolvedRef(responses[statusCode] || responses.default);
|
|
15
17
|
if (!response) {
|
|
16
18
|
return null;
|
|
17
19
|
}
|
|
@@ -36,7 +38,7 @@ function getExampleFromResponse(c, statusCode, responses) {
|
|
|
36
38
|
return acceptedResponse.example !== undefined
|
|
37
39
|
? acceptedResponse.example
|
|
38
40
|
: acceptedResponse.schema
|
|
39
|
-
? getExampleFromSchema(acceptedResponse.schema, {
|
|
41
|
+
? getExampleFromSchema(getResolvedRefDeep(acceptedResponse.schema), {
|
|
40
42
|
emptyString: 'string',
|
|
41
43
|
variables: c.req.param(),
|
|
42
44
|
mode: 'read',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-open-auth-token-urls.d.ts","sourceRoot":"","sources":["../../src/utils/get-open-auth-token-urls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"get-open-auth-token-urls.d.ts","sourceRoot":"","sources":["../../src/utils/get-open-auth-token-urls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,MAAM,uBAAuB,CAAA;AAG5E;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYlD;AAiBD,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,EAAE,CAuCxE"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
1
2
|
/**
|
|
2
3
|
* Extract path from URL
|
|
3
4
|
*/
|
|
@@ -33,8 +34,10 @@ export function getOpenAuthTokenUrls(schema) {
|
|
|
33
34
|
// Use Set from the start for better memory efficiency
|
|
34
35
|
const oauthUrls = new Set();
|
|
35
36
|
// Iterate through all security schemes
|
|
36
|
-
for (const
|
|
37
|
-
|
|
37
|
+
for (const rawScheme of Object.values(securitySchemes)) {
|
|
38
|
+
const scheme = getResolvedRef(rawScheme);
|
|
39
|
+
// Skip schemes that could not be resolved (e.g. a `$ref` to a missing component)
|
|
40
|
+
if (!scheme || !isOAuth2Scheme(scheme)) {
|
|
38
41
|
continue;
|
|
39
42
|
}
|
|
40
43
|
const flows = scheme.flows; // Type assertion no longer needed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle-authentication.d.ts","sourceRoot":"","sources":["../../src/utils/handle-authentication.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"handle-authentication.d.ts","sourceRoot":"","sources":["../../src/utils/handle-authentication.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAGnC;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,WAAW,CAAC,eAAe,IAC3F,GAAG,OAAO,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAwH/E"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
1
2
|
import { getCookie } from 'hono/cookie';
|
|
2
3
|
/**
|
|
3
4
|
* Handles authentication for incoming requests based on the OpenAPI document.
|
|
@@ -11,11 +12,7 @@ export function handleAuthentication(schema, operation) {
|
|
|
11
12
|
for (const securityRequirement of operationSecuritySchemes) {
|
|
12
13
|
let securitySchemeAuthenticated = true;
|
|
13
14
|
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;
|
|
18
|
-
}
|
|
15
|
+
const scheme = getResolvedRef(schema?.components?.securitySchemes?.[schemeName]);
|
|
19
16
|
if (scheme && 'type' in scheme) {
|
|
20
17
|
const securityScheme = scheme;
|
|
21
18
|
switch (securityScheme.type) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-authentication-instructions.d.ts","sourceRoot":"","sources":["../../src/utils/log-authentication-instructions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"log-authentication-instructions.d.ts","sourceRoot":"","sources":["../../src/utils/log-authentication-instructions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAKxD;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,oBAAoB,CAAC,QA0H9G"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
1
2
|
import { getPathFromUrl } from './get-open-auth-token-urls.js';
|
|
2
3
|
/**
|
|
3
4
|
* Log authentication instructions for different security schemes
|
|
@@ -8,7 +9,12 @@ export function logAuthenticationInstructions(securitySchemes) {
|
|
|
8
9
|
}
|
|
9
10
|
console.log('Authentication:');
|
|
10
11
|
console.log();
|
|
11
|
-
Object.entries(securitySchemes).forEach(([_,
|
|
12
|
+
Object.entries(securitySchemes).forEach(([_, rawScheme]) => {
|
|
13
|
+
const scheme = getResolvedRef(rawScheme);
|
|
14
|
+
// Skip schemes that could not be resolved (e.g. a `$ref` to a missing component)
|
|
15
|
+
if (!scheme) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
12
18
|
switch (scheme.type) {
|
|
13
19
|
case 'apiKey':
|
|
14
20
|
if (scheme.in === 'header') {
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import type { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
2
|
/**
|
|
3
3
|
* Processes an OpenAPI document by bundling external references, upgrading to OpenAPI 3.1,
|
|
4
|
-
* and
|
|
4
|
+
* and wrapping it so internal references stay intact but resolve lazily.
|
|
5
|
+
*
|
|
6
|
+
* Unlike a full dereference, the returned document keeps `$ref` nodes in place. Consumers
|
|
7
|
+
* resolve them on demand with `getResolvedRef` from `@scalar/workspace-store`, which reads the
|
|
8
|
+
* `$ref-value` exposed by the magic proxy. This avoids eagerly flattening (and duplicating)
|
|
9
|
+
* the whole document up front.
|
|
5
10
|
*
|
|
6
11
|
* @param document - The OpenAPI document to process. Can be a string (URL/path) or an object.
|
|
7
|
-
* @returns A promise that resolves to the
|
|
12
|
+
* @returns A promise that resolves to the OpenAPI 3.1 document with lazily resolvable references.
|
|
8
13
|
* @throws Error if the document cannot be processed or is invalid.
|
|
9
14
|
*/
|
|
10
15
|
export declare function processOpenApiDocument(document: string | Record<string, any> | undefined): Promise<OpenAPIV3_1.Document>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-openapi-document.d.ts","sourceRoot":"","sources":["../../src/utils/process-openapi-document.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"process-openapi-document.d.ts","sourceRoot":"","sources":["../../src/utils/process-openapi-document.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGxD;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GACjD,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAiD/B"}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { bundle } from '@scalar/json-magic/bundle';
|
|
2
|
-
import { parseJson } from '@scalar/json-magic/bundle/plugins/node';
|
|
3
|
-
import {
|
|
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';
|
|
2
|
+
import { fetchUrls, parseJson, parseYaml, readFiles } from '@scalar/json-magic/bundle/plugins/node';
|
|
3
|
+
import { createMagicProxy } from '@scalar/json-magic/magic-proxy';
|
|
7
4
|
import { upgrade } from '@scalar/openapi-upgrader';
|
|
8
5
|
/**
|
|
9
6
|
* Processes an OpenAPI document by bundling external references, upgrading to OpenAPI 3.1,
|
|
10
|
-
* and
|
|
7
|
+
* and wrapping it so internal references stay intact but resolve lazily.
|
|
8
|
+
*
|
|
9
|
+
* Unlike a full dereference, the returned document keeps `$ref` nodes in place. Consumers
|
|
10
|
+
* resolve them on demand with `getResolvedRef` from `@scalar/workspace-store`, which reads the
|
|
11
|
+
* `$ref-value` exposed by the magic proxy. This avoids eagerly flattening (and duplicating)
|
|
12
|
+
* the whole document up front.
|
|
11
13
|
*
|
|
12
14
|
* @param document - The OpenAPI document to process. Can be a string (URL/path) or an object.
|
|
13
|
-
* @returns A promise that resolves to the
|
|
15
|
+
* @returns A promise that resolves to the OpenAPI 3.1 document with lazily resolvable references.
|
|
14
16
|
* @throws Error if the document cannot be processed or is invalid.
|
|
15
17
|
*/
|
|
16
18
|
export async function processOpenApiDocument(document) {
|
|
@@ -52,21 +54,7 @@ export async function processOpenApiDocument(document) {
|
|
|
52
54
|
if (!upgraded) {
|
|
53
55
|
throw new Error('Upgraded document is invalid: upgrade returned null or undefined');
|
|
54
56
|
}
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
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;
|
|
57
|
+
// Wrap the document in a magic proxy so internal references resolve lazily via `$ref-value`.
|
|
58
|
+
// External references were already pulled inline by `bundle` above, so only local `$ref`s remain.
|
|
59
|
+
return createMagicProxy(upgraded);
|
|
72
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-up-authentication-routes.d.ts","sourceRoot":"","sources":["../../src/utils/set-up-authentication-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"set-up-authentication-routes.d.ts","sourceRoot":"","sources":["../../src/utils/set-up-authentication-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,MAAM,uBAAuB,CAAA;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAOhC;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,QAmG7E"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
1
2
|
import { respondWithAuthorizePage } from '../routes/respond-with-authorize-page.js';
|
|
2
3
|
import { respondWithToken } from '../routes/respond-with-token.js';
|
|
3
4
|
import { getOpenAuthTokenUrls, getPathFromUrl } from './get-open-auth-token-urls.js';
|
|
@@ -28,7 +29,12 @@ export function setUpAuthenticationRoutes(app, schema) {
|
|
|
28
29
|
// Set up routes for different OAuth 2.0 flows
|
|
29
30
|
const authorizeUrls = new Set();
|
|
30
31
|
const tokenUrls = new Set();
|
|
31
|
-
Object.entries(securitySchemes).forEach(([_,
|
|
32
|
+
Object.entries(securitySchemes).forEach(([_, rawScheme]) => {
|
|
33
|
+
const scheme = getResolvedRef(rawScheme);
|
|
34
|
+
// Skip schemes that could not be resolved (e.g. a `$ref` to a missing component)
|
|
35
|
+
if (!scheme) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
32
38
|
if (scheme.type === 'oauth2') {
|
|
33
39
|
if (scheme.flows?.authorizationCode) {
|
|
34
40
|
const authorizeRoute = scheme.flows.authorizationCode.authorizationUrl ?? '/oauth/authorize';
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"swagger",
|
|
17
17
|
"cli"
|
|
18
18
|
],
|
|
19
|
-
"version": "0.10.
|
|
19
|
+
"version": "0.10.17",
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=22"
|
|
22
22
|
},
|
|
@@ -53,12 +53,12 @@
|
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@faker-js/faker": "10.4.0",
|
|
55
55
|
"hono": "^4.12.7",
|
|
56
|
-
"
|
|
57
|
-
"@scalar/
|
|
58
|
-
"@scalar/
|
|
59
|
-
"@scalar/openapi-
|
|
60
|
-
"@scalar/openapi-
|
|
61
|
-
"@scalar/workspace-store": "0.
|
|
56
|
+
"yaml": "^2.8.3",
|
|
57
|
+
"@scalar/helpers": "0.8.1",
|
|
58
|
+
"@scalar/json-magic": "0.12.15",
|
|
59
|
+
"@scalar/openapi-types": "0.9.1",
|
|
60
|
+
"@scalar/openapi-upgrader": "0.2.9",
|
|
61
|
+
"@scalar/workspace-store": "0.54.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/node": "^24.1.0",
|