@scalar/mock-server 0.4.2 → 0.5.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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @scalar/mock-server
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - edf694b: refactor!: use openapi-parser utils, remove the deprecated pipeline syntax
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [151ef09]
12
+ - Updated dependencies [442c0a3]
13
+ - Updated dependencies [edf694b]
14
+ - @scalar/oas-utils@0.3.2
15
+ - @scalar/openapi-parser@0.12.0
16
+
3
17
  ## 0.4.2
4
18
 
5
19
  ### Patch Changes
package/README.md CHANGED
@@ -20,11 +20,11 @@ A powerful Node.js mock server that automatically generates realistic API respon
20
20
 
21
21
  ## Quickstart
22
22
 
23
- The easiest way to get started is through [our Scalar CLI](https://github.com/scalar/scalar/tree/main/packages/cli).
23
+ The easiest way to get started is through [our Scalar CLI](https://www.npmjs.com/package/@scalar/cli).
24
24
  You can have a mock server up and running in seconds:
25
25
 
26
26
  ```bash
27
- npx @scalar/cli mock openapi.json --watch
27
+ npx @scalar/cli document mock openapi.json --watch
28
28
  ```
29
29
 
30
30
  ## Installation
@@ -1 +1 @@
1
- {"version":3,"file":"createMockServer.d.ts","sourceRoot":"","sources":["../src/createMockServer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,IAAI,EAAE,MAAM,MAAM,CAAA;AAGzC,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAW5D;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,uFA+ChE"}
1
+ {"version":3,"file":"createMockServer.d.ts","sourceRoot":"","sources":["../src/createMockServer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,IAAI,EAAE,MAAM,MAAM,CAAA;AAGzC,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAW5D;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,uFA4ChE"}
@@ -1,4 +1,4 @@
1
- import { openapi } from "@scalar/openapi-parser";
1
+ import { dereference } from "@scalar/openapi-parser";
2
2
  import { Hono } from "hono";
3
3
  import { cors } from "hono/cors";
4
4
  import { getOperations } from "./utils/getOperations.js";
@@ -11,7 +11,7 @@ import { mockAnyResponse } from "./routes/mockAnyResponse.js";
11
11
  import { respondWithOpenApiDocument } from "./routes/respondWithOpenApiDocument.js";
12
12
  async function createMockServer(options) {
13
13
  const app = new Hono();
14
- const { schema } = await openapi().load(options?.specification ?? {}).dereference().get();
14
+ const { schema } = await dereference(options?.specification ?? {});
15
15
  app.use(cors());
16
16
  setupAuthenticationRoutes(app, schema);
17
17
  logAuthenticationInstructions(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/createMockServer.ts"],
4
- "sourcesContent": ["import { openapi } from '@scalar/openapi-parser'\nimport type { OpenAPI, OpenAPIV3_1 } from '@scalar/openapi-types'\nimport { type Context, Hono } from 'hono'\nimport { cors } from 'hono/cors'\n\nimport type { HttpMethod, MockServerOptions } from '@/types'\nimport { getOperations } from '@/utils/getOperations'\nimport { handleAuthentication } from '@/utils/handleAuthentication'\nimport { honoRouteFromPath } from '@/utils/honoRouteFromPath'\nimport { isAuthenticationRequired } from '@/utils/isAuthenticationRequired'\nimport { logAuthenticationInstructions } from '@/utils/logAuthenticationInstructions'\nimport { setupAuthenticationRoutes } from '@/utils/setupAuthenticationRoutes'\n\nimport { mockAnyResponse } from './routes/mockAnyResponse'\nimport { respondWithOpenApiDocument } from './routes/respondWithOpenApiDocument'\n\n/**\n * Create a mock server instance\n */\nexport async function createMockServer(options: MockServerOptions) {\n const app = new Hono()\n\n /** Dereferenced OpenAPI document */\n const { schema } = await openapi()\n .load(options?.specification ?? {})\n .dereference()\n .get()\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: Context) => mockAnyResponse(c, operation, options))\n })\n })\n\n // OpenAPI JSON file\n app.get('/openapi.json', (c) => respondWithOpenApiDocument(c, options?.specification, 'json'))\n\n // OpenAPI YAML file\n app.get('/openapi.yaml', (c) => respondWithOpenApiDocument(c, options?.specification, 'yaml'))\n\n return app\n}\n"],
5
- "mappings": "AAAA,SAAS,eAAe;AAExB,SAAuB,YAAY;AACnC,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;AAK3C,eAAsB,iBAAiB,SAA4B;AACjE,QAAM,MAAM,IAAI,KAAK;AAGrB,QAAM,EAAE,OAAO,IAAI,MAAM,QAAQ,EAC9B,KAAK,SAAS,iBAAiB,CAAC,CAAC,EACjC,YAAY,EACZ,IAAI;AAGP,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,MAAe,gBAAgB,GAAG,WAAW,OAAO,CAAC;AAAA,IAC3E,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,iBAAiB,CAAC,MAAM,2BAA2B,GAAG,SAAS,eAAe,MAAM,CAAC;AAG7F,MAAI,IAAI,iBAAiB,CAAC,MAAM,2BAA2B,GAAG,SAAS,eAAe,MAAM,CAAC;AAE7F,SAAO;AACT;",
4
+ "sourcesContent": ["import { dereference } from '@scalar/openapi-parser'\nimport type { OpenAPI, OpenAPIV3_1 } from '@scalar/openapi-types'\nimport { type Context, Hono } from 'hono'\nimport { cors } from 'hono/cors'\n\nimport type { HttpMethod, MockServerOptions } from '@/types'\nimport { getOperations } from '@/utils/getOperations'\nimport { handleAuthentication } from '@/utils/handleAuthentication'\nimport { honoRouteFromPath } from '@/utils/honoRouteFromPath'\nimport { isAuthenticationRequired } from '@/utils/isAuthenticationRequired'\nimport { logAuthenticationInstructions } from '@/utils/logAuthenticationInstructions'\nimport { setupAuthenticationRoutes } from '@/utils/setupAuthenticationRoutes'\n\nimport { mockAnyResponse } from './routes/mockAnyResponse'\nimport { respondWithOpenApiDocument } from './routes/respondWithOpenApiDocument'\n\n/**\n * Create a mock server instance\n */\nexport async function createMockServer(options: MockServerOptions) {\n const app = new Hono()\n\n /** Dereferenced OpenAPI document */\n const { schema } = await dereference(options?.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: Context) => mockAnyResponse(c, operation, options))\n })\n })\n\n // OpenAPI JSON file\n app.get('/openapi.json', (c) => respondWithOpenApiDocument(c, options?.specification, 'json'))\n\n // OpenAPI YAML file\n app.get('/openapi.yaml', (c) => respondWithOpenApiDocument(c, options?.specification, 'yaml'))\n\n return app\n}\n"],
5
+ "mappings": "AAAA,SAAS,mBAAmB;AAE5B,SAAuB,YAAY;AACnC,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;AAK3C,eAAsB,iBAAiB,SAA4B;AACjE,QAAM,MAAM,IAAI,KAAK;AAGrB,QAAM,EAAE,OAAO,IAAI,MAAM,YAAY,SAAS,iBAAiB,CAAC,CAAC;AAGjE,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,MAAe,gBAAgB,GAAG,WAAW,OAAO,CAAC;AAAA,IAC3E,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,iBAAiB,CAAC,MAAM,2BAA2B,GAAG,SAAS,eAAe,MAAM,CAAC;AAG7F,MAAI,IAAI,iBAAiB,CAAC,MAAM,2BAA2B,GAAG,SAAS,eAAe,MAAM,CAAC;AAE7F,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -2,9 +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'): Promise<(Response & import("hono").TypedResponse<"Not found", 404, "text">) | (Response & import("hono").TypedResponse<{
6
- [x: string]: any;
7
- }, import("hono/utils/http-status").StatusCode, "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'): Promise<(Response & import("hono").TypedResponse<"Not found", 404, "text">) | (Response & import("hono").TypedResponse<never, import("hono/utils/http-status").StatusCode, "json">) | (Response & import("hono").TypedResponse<string, 200, "text">) | (Response & import("hono").TypedResponse<{
8
6
  error: string;
9
7
  message: string;
10
8
  }, 500, "json">) | (Response & import("hono").TypedResponse<{
@@ -1 +1 @@
1
- {"version":3,"file":"respondWithOpenApiDocument.d.ts","sourceRoot":"","sources":["../../src/routes/respondWithOpenApiDocument.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,CAAC,EAAE,OAAO,EACV,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpC,MAAM,GAAE,MAAM,GAAG,MAAe;;;;;;;;kBAuCjC"}
1
+ {"version":3,"file":"respondWithOpenApiDocument.d.ts","sourceRoot":"","sources":["../../src/routes/respondWithOpenApiDocument.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,CAAC,EAAE,OAAO,EACV,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpC,MAAM,GAAE,MAAM,GAAG,MAAe;;;;;;kBAwCjC"}
@@ -1,23 +1,23 @@
1
- import { openapi } from "@scalar/openapi-parser";
1
+ import { normalize, toYaml } from "@scalar/openapi-parser";
2
2
  async function respondWithOpenApiDocument(c, input, format = "json") {
3
3
  if (!input) {
4
4
  return c.text("Not found", 404);
5
5
  }
6
6
  try {
7
- const { specification } = await openapi().load(input).get();
7
+ const document = normalize(input);
8
8
  if (format === "json") {
9
- return c.json(specification);
9
+ return c.json(document);
10
10
  }
11
11
  try {
12
- const yamlSpecification = await openapi().load(input).toYaml();
12
+ const yamlDocument = toYaml(normalize(document));
13
13
  c.header("Content-Type", "text/yaml");
14
- return c.text(yamlSpecification, 200, {
14
+ return c.text(yamlDocument, 200, {
15
15
  "Content-Type": "application/yaml; charset=UTF-8"
16
16
  });
17
17
  } catch (error) {
18
18
  return c.json(
19
19
  {
20
- error: "Failed to convert specification to YAML",
20
+ error: "Failed to convert document to YAML",
21
21
  message: error instanceof Error ? error.message : "Unknown error occurred"
22
22
  },
23
23
  500
@@ -26,7 +26,7 @@ async function respondWithOpenApiDocument(c, input, format = "json") {
26
26
  } catch (error) {
27
27
  return c.json(
28
28
  {
29
- error: "Failed to parse OpenAPI specification",
29
+ error: "Failed to parse OpenAPI document",
30
30
  message: error instanceof Error ? error.message : "Unknown error occurred"
31
31
  },
32
32
  400
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/routes/respondWithOpenApiDocument.ts"],
4
- "sourcesContent": ["import { openapi } from '@scalar/openapi-parser'\nimport type { Context } from 'hono'\n\n/**\n * OpenAPI endpoints\n */\nexport async 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 { specification } = await openapi().load(input).get()\n\n // JSON\n if (format === 'json') {\n return c.json(specification)\n }\n\n // YAML\n try {\n const yamlSpecification = await openapi().load(input).toYaml()\n c.header('Content-Type', 'text/yaml')\n return c.text(yamlSpecification, 200, {\n 'Content-Type': 'application/yaml; charset=UTF-8',\n })\n } catch (error) {\n return c.json(\n {\n error: 'Failed to convert specification 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 specification',\n message: error instanceof Error ? error.message : 'Unknown error occurred',\n },\n 400,\n )\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,eAAe;AAMxB,eAAsB,2BACpB,GACA,OACA,SAA0B,QAC1B;AACA,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,KAAK,aAAa,GAAG;AAAA,EAChC;AAEA,MAAI;AACF,UAAM,EAAE,cAAc,IAAI,MAAM,QAAQ,EAAE,KAAK,KAAK,EAAE,IAAI;AAG1D,QAAI,WAAW,QAAQ;AACrB,aAAO,EAAE,KAAK,aAAa;AAAA,IAC7B;AAGA,QAAI;AACF,YAAM,oBAAoB,MAAM,QAAQ,EAAE,KAAK,KAAK,EAAE,OAAO;AAC7D,QAAE,OAAO,gBAAgB,WAAW;AACpC,aAAO,EAAE,KAAK,mBAAmB,KAAK;AAAA,QACpC,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;",
4
+ "sourcesContent": ["import { normalize, toYaml } from '@scalar/openapi-parser'\nimport type { Context } from 'hono'\n\n/**\n * OpenAPI endpoints\n */\nexport async 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
+ "mappings": "AAAA,SAAS,WAAW,cAAc;AAMlC,eAAsB,2BACpB,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": []
7
7
  }
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "swagger",
17
17
  "cli"
18
18
  ],
19
- "version": "0.4.2",
19
+ "version": "0.5.0",
20
20
  "engines": {
21
21
  "node": ">=20"
22
22
  },
@@ -38,8 +38,8 @@
38
38
  "dependencies": {
39
39
  "hono": "^4.6.5",
40
40
  "object-to-xml": "^2.0.0",
41
- "@scalar/oas-utils": "0.3.1",
42
- "@scalar/openapi-parser": "0.11.1",
41
+ "@scalar/oas-utils": "0.3.2",
42
+ "@scalar/openapi-parser": "0.12.0",
43
43
  "@scalar/openapi-types": "0.3.1"
44
44
  },
45
45
  "devDependencies": {
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "scripts": {
53
53
  "build": "scalar-build-esbuild",
54
- "dev": "nodemon --exec \"vite-node playground/index.ts\" --ext ts --quiet",
54
+ "dev": "nodemon --exec \"vite-node playground/src/index.ts\" --ext ts --quiet",
55
55
  "lint:check": "scalar-lint-check",
56
56
  "lint:fix": "scalar-lint-fix",
57
57
  "test": "vitest",