@scalar/oas-utils 0.4.16 → 0.4.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @scalar/oas-utils
2
2
 
3
+ ## 0.4.17
4
+
5
+ ### Patch Changes
6
+
7
+ - 46ebe6e: fix: use schema to example generator for request example request body
8
+ - Updated dependencies [952bde2]
9
+ - Updated dependencies [5301a80]
10
+ - Updated dependencies [ae8d1b9]
11
+ - Updated dependencies [8199955]
12
+ - Updated dependencies [2888e18]
13
+ - @scalar/workspace-store@0.12.0
14
+
3
15
  ## 0.4.16
4
16
 
5
17
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- import type { OperationToHarProps } from '../../helpers/operation-to-har/operation-to-har.js';
1
+ import type { OperationToHarProps } from './operation-to-har.js';
2
2
  import type { PostData } from 'har-format';
3
3
  type ProcessBodyProps = Pick<OperationToHarProps, 'contentType' | 'operation' | 'example'>;
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"process-body.d.ts","sourceRoot":"","sources":["../../../src/helpers/operation-to-har/process-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAA;AAGtF,OAAO,KAAK,EAAS,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEjD,KAAK,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAAE,aAAa,GAAG,WAAW,GAAG,SAAS,CAAC,CAAA;AA0F1F;;GAEG;AACH,eAAO,MAAM,WAAW,wCAAyC,gBAAgB,KAAG,QA8CnF,CAAA"}
1
+ {"version":3,"file":"process-body.d.ts","sourceRoot":"","sources":["../../../src/helpers/operation-to-har/process-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAG7D,OAAO,KAAK,EAAS,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEjD,KAAK,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAAE,aAAa,GAAG,WAAW,GAAG,SAAS,CAAC,CAAA;AAoC1F;;GAEG;AACH,eAAO,MAAM,WAAW,wCAAyC,gBAAgB,KAAG,QA6CnF,CAAA"}
@@ -1,32 +1,5 @@
1
+ import { getExampleFromSchema } from "../../spec-getters/get-example-from-schema.js";
1
2
  import { isReference } from "@scalar/workspace-store/schemas/v3.1/type-guard";
2
- const extractExamplesFromSchema = (schema, depth = 0) => {
3
- if (!schema || depth > 10) {
4
- return void 0;
5
- }
6
- if (schema.examples?.[0] !== void 0) {
7
- return schema.examples[0];
8
- }
9
- if (schema.example !== void 0) {
10
- return schema.example;
11
- }
12
- if (schema.type === "object" && schema.properties) {
13
- const result = {};
14
- let hasExamples = false;
15
- for (const [key, propSchema] of Object.entries(schema.properties)) {
16
- const example = extractExamplesFromSchema(propSchema, depth + 1);
17
- if (example !== void 0) {
18
- result[key] = example;
19
- hasExamples = true;
20
- }
21
- }
22
- return hasExamples ? result : void 0;
23
- }
24
- if (schema.type === "array" && schema.items) {
25
- const itemExample = extractExamplesFromSchema(schema.items, depth + 1);
26
- return itemExample !== void 0 ? [itemExample] : void 0;
27
- }
28
- return void 0;
29
- };
30
3
  const objectToFormParams = (obj) => {
31
4
  const params = [];
32
5
  for (const [key, value] of Object.entries(obj)) {
@@ -50,7 +23,7 @@ const objectToFormParams = (obj) => {
50
23
  };
51
24
  const processBody = ({ operation, contentType, example }) => {
52
25
  const content = !operation.requestBody || isReference(operation.requestBody) ? {} : operation.requestBody.content;
53
- const _contentType = contentType || Object.keys(content)[0];
26
+ const _contentType = (contentType || Object.keys(content)[0]) ?? "";
54
27
  const isFormData = _contentType === "multipart/form-data" || _contentType === "application/x-www-form-urlencoded";
55
28
  if (example) {
56
29
  if (isFormData && typeof example === "object" && example !== null) {
@@ -64,9 +37,9 @@ const processBody = ({ operation, contentType, example }) => {
64
37
  text: JSON.stringify(example)
65
38
  };
66
39
  }
67
- const contentSchema = content[_contentType ?? ""]?.schema;
40
+ const contentSchema = content[_contentType]?.schema;
68
41
  if (contentSchema) {
69
- const extractedExample = extractExamplesFromSchema(contentSchema);
42
+ const extractedExample = getExampleFromSchema(contentSchema);
70
43
  if (extractedExample !== void 0) {
71
44
  if (isFormData && typeof extractedExample === "object" && extractedExample !== null) {
72
45
  return {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/helpers/operation-to-har/process-body.ts"],
4
- "sourcesContent": ["import type { OperationToHarProps } from '@/helpers/operation-to-har/operation-to-har'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.1/strict/schema'\nimport { isReference } from '@scalar/workspace-store/schemas/v3.1/type-guard'\nimport type { Param, PostData } from 'har-format'\n\ntype ProcessBodyProps = Pick<OperationToHarProps, 'contentType' | 'operation' | 'example'>\n\n/**\n * Extended SchemaObject type that includes the examples property from JSON Schema\n */\ntype ExtendedSchemaObject = SchemaObject & {\n examples?: unknown[]\n}\n\n/**\n * Recursively extracts examples from a schema object and its nested properties\n * @param schema - The schema object to extract examples from\n * @param depth - Current recursion depth to prevent infinite loops\n * @returns The extracted example or undefined if none found\n */\nconst extractExamplesFromSchema = (schema: ExtendedSchemaObject | undefined, depth = 0): unknown => {\n // Prevent infinite recursion and handle invalid inputs\n if (!schema || depth > 10) {\n return undefined\n }\n\n // If the schema has examples array, return the first one\n if (schema.examples?.[0] !== undefined) {\n return schema.examples[0]\n }\n\n // If the schema has a single example property, return it\n if (schema.example !== undefined) {\n return schema.example\n }\n\n // For objects, recursively process properties\n if (schema.type === 'object' && schema.properties) {\n const result: Record<string, unknown> = {}\n let hasExamples = false\n\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n const example = extractExamplesFromSchema(propSchema as ExtendedSchemaObject, depth + 1)\n if (example !== undefined) {\n result[key] = example\n hasExamples = true\n }\n }\n\n return hasExamples ? result : undefined\n }\n\n // For arrays, process the items schema\n if (schema.type === 'array' && schema.items) {\n const itemExample = extractExamplesFromSchema(schema.items as ExtendedSchemaObject, depth + 1)\n return itemExample !== undefined ? [itemExample] : undefined\n }\n\n return undefined\n}\n\n/**\n * Converts an object to an array of form parameters\n * @param obj - The object to convert\n * @returns Array of form parameters with name and value properties\n */\nconst objectToFormParams = (obj: Record<string, unknown>): Param[] => {\n const params: Param[] = []\n\n for (const [key, value] of Object.entries(obj)) {\n if (value === undefined || value === null) {\n continue\n }\n\n // Handle arrays by adding each item with the same key\n if (Array.isArray(value)) {\n for (const item of value) {\n params.push({ name: key, value: String(item) })\n }\n }\n // Handle nested objects by flattening them\n else if (typeof value === 'object') {\n const nestedParams = objectToFormParams(value as Record<string, unknown>)\n\n for (const param of nestedParams) {\n params.push({ name: `${key}.${param.name}`, value: param.value })\n }\n } else {\n params.push({ name: key, value: String(value) })\n }\n }\n\n return params\n}\n\n/**\n * Processes the request body and returns the processed data\n */\nexport const processBody = ({ operation, contentType, example }: ProcessBodyProps): PostData => {\n const content = !operation.requestBody || isReference(operation.requestBody) ? {} : operation.requestBody.content\n\n // TODO: This typecast is invalid and must be refactored out.\n const _contentType = contentType || (Object.keys(content)[0] as string)\n\n // Check if this is a form data content type\n const isFormData = _contentType === 'multipart/form-data' || _contentType === 'application/x-www-form-urlencoded'\n\n // Return the provided top level example\n if (example) {\n if (isFormData && typeof example === 'object' && example !== null) {\n return {\n mimeType: _contentType,\n params: objectToFormParams(example as Record<string, unknown>),\n }\n }\n return {\n mimeType: _contentType,\n text: JSON.stringify(example),\n }\n }\n\n // Try to extract examples from the schema\n const contentSchema = content[_contentType ?? '']?.schema\n if (contentSchema) {\n const extractedExample = extractExamplesFromSchema(contentSchema as ExtendedSchemaObject)\n\n if (extractedExample !== undefined) {\n if (isFormData && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: _contentType,\n params: objectToFormParams(extractedExample as Record<string, unknown>),\n }\n }\n return {\n mimeType: _contentType,\n text: JSON.stringify(extractedExample),\n }\n }\n }\n\n return {\n mimeType: _contentType,\n text: 'null',\n }\n}\n"],
5
- "mappings": "AAEA,SAAS,mBAAmB;AAkB5B,MAAM,4BAA4B,CAAC,QAA0C,QAAQ,MAAe;AAElG,MAAI,CAAC,UAAU,QAAQ,IAAI;AACzB,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,WAAW,CAAC,MAAM,QAAW;AACtC,WAAO,OAAO,SAAS,CAAC;AAAA,EAC1B;AAGA,MAAI,OAAO,YAAY,QAAW;AAChC,WAAO,OAAO;AAAA,EAChB;AAGA,MAAI,OAAO,SAAS,YAAY,OAAO,YAAY;AACjD,UAAM,SAAkC,CAAC;AACzC,QAAI,cAAc;AAElB,eAAW,CAAC,KAAK,UAAU,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AACjE,YAAM,UAAU,0BAA0B,YAAoC,QAAQ,CAAC;AACvF,UAAI,YAAY,QAAW;AACzB,eAAO,GAAG,IAAI;AACd,sBAAc;AAAA,MAChB;AAAA,IACF;AAEA,WAAO,cAAc,SAAS;AAAA,EAChC;AAGA,MAAI,OAAO,SAAS,WAAW,OAAO,OAAO;AAC3C,UAAM,cAAc,0BAA0B,OAAO,OAA+B,QAAQ,CAAC;AAC7F,WAAO,gBAAgB,SAAY,CAAC,WAAW,IAAI;AAAA,EACrD;AAEA,SAAO;AACT;AAOA,MAAM,qBAAqB,CAAC,QAA0C;AACpE,QAAM,SAAkB,CAAC;AAEzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,QAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,IACF;AAGA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,QAAQ,OAAO;AACxB,eAAO,KAAK,EAAE,MAAM,KAAK,OAAO,OAAO,IAAI,EAAE,CAAC;AAAA,MAChD;AAAA,IACF,WAES,OAAO,UAAU,UAAU;AAClC,YAAM,eAAe,mBAAmB,KAAgC;AAExE,iBAAW,SAAS,cAAc;AAChC,eAAO,KAAK,EAAE,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,IAAI,OAAO,MAAM,MAAM,CAAC;AAAA,MAClE;AAAA,IACF,OAAO;AACL,aAAO,KAAK,EAAE,MAAM,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AACT;AAKO,MAAM,cAAc,CAAC,EAAE,WAAW,aAAa,QAAQ,MAAkC;AAC9F,QAAM,UAAU,CAAC,UAAU,eAAe,YAAY,UAAU,WAAW,IAAI,CAAC,IAAI,UAAU,YAAY;AAG1G,QAAM,eAAe,eAAgB,OAAO,KAAK,OAAO,EAAE,CAAC;AAG3D,QAAM,aAAa,iBAAiB,yBAAyB,iBAAiB;AAG9E,MAAI,SAAS;AACX,QAAI,cAAc,OAAO,YAAY,YAAY,YAAY,MAAM;AACjE,aAAO;AAAA,QACL,UAAU;AAAA,QACV,QAAQ,mBAAmB,OAAkC;AAAA,MAC/D;AAAA,IACF;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B;AAAA,EACF;AAGA,QAAM,gBAAgB,QAAQ,gBAAgB,EAAE,GAAG;AACnD,MAAI,eAAe;AACjB,UAAM,mBAAmB,0BAA0B,aAAqC;AAExF,QAAI,qBAAqB,QAAW;AAClC,UAAI,cAAc,OAAO,qBAAqB,YAAY,qBAAqB,MAAM;AACnF,eAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ,mBAAmB,gBAA2C;AAAA,QACxE;AAAA,MACF;AACA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM,KAAK,UAAU,gBAAgB;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AACF;",
4
+ "sourcesContent": ["import type { OperationToHarProps } from './operation-to-har'\nimport { getExampleFromSchema } from '@/spec-getters/get-example-from-schema'\nimport { isReference } from '@scalar/workspace-store/schemas/v3.1/type-guard'\nimport type { Param, PostData } from 'har-format'\n\ntype ProcessBodyProps = Pick<OperationToHarProps, 'contentType' | 'operation' | 'example'>\n\n/**\n * Converts an object to an array of form parameters\n * @param obj - The object to convert\n * @returns Array of form parameters with name and value properties\n */\nconst objectToFormParams = (obj: Record<string, unknown>): Param[] => {\n const params: Param[] = []\n\n for (const [key, value] of Object.entries(obj)) {\n if (value === undefined || value === null) {\n continue\n }\n\n // Handle arrays by adding each item with the same key\n if (Array.isArray(value)) {\n for (const item of value) {\n params.push({ name: key, value: String(item) })\n }\n }\n // Handle nested objects by flattening them\n else if (typeof value === 'object') {\n const nestedParams = objectToFormParams(value as Record<string, unknown>)\n\n for (const param of nestedParams) {\n params.push({ name: `${key}.${param.name}`, value: param.value })\n }\n } else {\n params.push({ name: key, value: String(value) })\n }\n }\n\n return params\n}\n\n/**\n * Processes the request body and returns the processed data\n */\nexport const processBody = ({ operation, contentType, example }: ProcessBodyProps): PostData => {\n const content = !operation.requestBody || isReference(operation.requestBody) ? {} : operation.requestBody.content\n\n const _contentType = (contentType || Object.keys(content)[0]) ?? ''\n\n // Check if this is a form data content type\n const isFormData = _contentType === 'multipart/form-data' || _contentType === 'application/x-www-form-urlencoded'\n\n // Return the provided top level example\n if (example) {\n if (isFormData && typeof example === 'object' && example !== null) {\n return {\n mimeType: _contentType,\n params: objectToFormParams(example as Record<string, unknown>),\n }\n }\n return {\n mimeType: _contentType,\n text: JSON.stringify(example),\n }\n }\n\n // Try to extract examples from the schema\n const contentSchema = content[_contentType]?.schema\n if (contentSchema) {\n const extractedExample = getExampleFromSchema(contentSchema)\n\n if (extractedExample !== undefined) {\n if (isFormData && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: _contentType,\n params: objectToFormParams(extractedExample as Record<string, unknown>),\n }\n }\n return {\n mimeType: _contentType,\n text: JSON.stringify(extractedExample),\n }\n }\n }\n\n return {\n mimeType: _contentType,\n text: 'null',\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,4BAA4B;AACrC,SAAS,mBAAmB;AAU5B,MAAM,qBAAqB,CAAC,QAA0C;AACpE,QAAM,SAAkB,CAAC;AAEzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,QAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,IACF;AAGA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,QAAQ,OAAO;AACxB,eAAO,KAAK,EAAE,MAAM,KAAK,OAAO,OAAO,IAAI,EAAE,CAAC;AAAA,MAChD;AAAA,IACF,WAES,OAAO,UAAU,UAAU;AAClC,YAAM,eAAe,mBAAmB,KAAgC;AAExE,iBAAW,SAAS,cAAc;AAChC,eAAO,KAAK,EAAE,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,IAAI,OAAO,MAAM,MAAM,CAAC;AAAA,MAClE;AAAA,IACF,OAAO;AACL,aAAO,KAAK,EAAE,MAAM,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AACT;AAKO,MAAM,cAAc,CAAC,EAAE,WAAW,aAAa,QAAQ,MAAkC;AAC9F,QAAM,UAAU,CAAC,UAAU,eAAe,YAAY,UAAU,WAAW,IAAI,CAAC,IAAI,UAAU,YAAY;AAE1G,QAAM,gBAAgB,eAAe,OAAO,KAAK,OAAO,EAAE,CAAC,MAAM;AAGjE,QAAM,aAAa,iBAAiB,yBAAyB,iBAAiB;AAG9E,MAAI,SAAS;AACX,QAAI,cAAc,OAAO,YAAY,YAAY,YAAY,MAAM;AACjE,aAAO;AAAA,QACL,UAAU;AAAA,QACV,QAAQ,mBAAmB,OAAkC;AAAA,MAC/D;AAAA,IACF;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B;AAAA,EACF;AAGA,QAAM,gBAAgB,QAAQ,YAAY,GAAG;AAC7C,MAAI,eAAe;AACjB,UAAM,mBAAmB,qBAAqB,aAAa;AAE3D,QAAI,qBAAqB,QAAW;AAClC,UAAI,cAAc,OAAO,qBAAqB,YAAY,qBAAqB,MAAM;AACnF,eAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ,mBAAmB,gBAA2C;AAAA,QACxE;AAAA,MACF;AACA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM,KAAK,UAAU,gBAAgB;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AACF;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "specification",
17
17
  "yaml"
18
18
  ],
19
- "version": "0.4.16",
19
+ "version": "0.4.17",
20
20
  "engines": {
21
21
  "node": ">=20"
22
22
  },
@@ -99,11 +99,11 @@
99
99
  "type-fest": "4.41.0",
100
100
  "yaml": "2.8.0",
101
101
  "zod": "3.24.1",
102
+ "@scalar/helpers": "0.0.7",
102
103
  "@scalar/object-utils": "1.2.3",
103
104
  "@scalar/openapi-types": "0.3.7",
104
105
  "@scalar/themes": "0.13.12",
105
- "@scalar/helpers": "0.0.7",
106
- "@scalar/workspace-store": "0.11.0",
106
+ "@scalar/workspace-store": "0.12.0",
107
107
  "@scalar/types": "0.2.11"
108
108
  },
109
109
  "devDependencies": {
@@ -113,7 +113,7 @@
113
113
  "vitest": "^3.2.4",
114
114
  "zod-to-ts": "github:amritk/zod-to-ts#build",
115
115
  "@scalar/build-tooling": "0.2.4",
116
- "@scalar/openapi-parser": "0.18.3",
116
+ "@scalar/openapi-parser": "0.19.0",
117
117
  "@scalar/openapi-types": "0.3.7"
118
118
  },
119
119
  "scripts": {